<commit_before>/*jshint browser: true, jasmine: true */
/*global angular, inject, module, $ */

describe('Autonumeric', function () {
    'use strict';

    var $compile,
        $scope,
        $timeout;

    beforeEach(module('ngMock'));
    beforeEach(module('sky.autonumeric'));

    describe('directive', function () {
        beforeEach(inject(function (_$compile_, _$rootScope_, _$timeout_) {
            $compile = _$compile_;
            $scope = _$rootScope_;
            $timeout = _$timeout_;
        }));

        function compileEl() {
            return $compile('<input type="text" ng-model="numericValue" bb-autonumeric />')($scope);
        }

        it('should not have bb-autonumeric- class', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();
            expect(el.hasClass('bb-autonumeric-')).toBe(false);
        });

        it('should have bb-autonumeric-number class', function () {
            var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric="number" />')($scope);

            $scope.numericValue = 123456.78;
            $scope.$digest();
            expect(el.hasClass('bb-autonumeric-number')).toBe(true);
        });

        // Not passing in IE 10 on BrowserStack.  Maybe revisit this test later.  It's not mission critical.
        //        it('should select existing text on focus', function () {
        //            var el = compileEl();
        //
        //            // Focus and select can't happen unless the element is in the DOM.
        //            el.appendTo(document.body);
        //
        //            $scope.numericValue = 123456.78;
        //            $scope.$digest();
        //
        //            el[0].focus();
        //            $timeout.flush();
        //
        //            expect(el[0].selectionStart).toBe(0);
        //            expect(el[0].selectionEnd).toBe(el.val().length);
        //        });

        it('should clear the element\'s text when the scope\'s property is set to null', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();

            $scope.numericValue = null;
            $scope.$digest();

            expect(el.val()).toBe('');
        });

        it('should set the model value to null when element has no value', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();

            el.val('');
            el.change();

            expect($scope.numericValue).toBe(null);
        });

        it('should allow custom configuration', function () {
            var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric bb-autonumeric-settings="numericOptions" />')($scope);

            $scope.numericValue = 123456.78;
            $scope.numericOptions = {
                aSign: '^'
            };

            $scope.$digest();

            expect(el.val()).toBe('^123,456.78');

            // Ensure we can clear out custom settings.
            $scope.numericOptions = null;
            $scope.$digest();

            expect(el.val()).toBe('123,456.78');
        });

        describe('money option', function () {
            it('should have bb-autonumeric-money class', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;
                $scope.$digest();
                expect(el.hasClass('bb-autonumeric-money')).toBe(true);
            });

            it('should set scope value based on default configuration', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                el.val('$7,654,321.00');
                el.change();

                expect($scope.moneyValue).toBe(7654321);
            });

            it('should set scope value based on default configuration on enter press', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope),
                    event;

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                el.val('$7,654,321.00');
                event = new $.Event('keydown');
                event.which = 13;
                el.trigger(event);

                expect($scope.moneyValue).toBe(7654321);

                el.val('$8,654,321.00');
                event = new $.Event('keydown');
                event.which = 15;
                el.trigger(event);
                expect($scope.moneyValue).toBe(7654321);
            });

            it('should format the input value based on the scope value', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('$123,456.78');
            });

            it('should allow individual settings to be overridden', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" bb-autonumeric-settings="moneyOptions" />')($scope);

                $scope.moneyValue = 123456.78;
                $scope.moneyOptions = {
                    aSign: '^'
                };

                $scope.$digest();

                expect(el.val()).toBe('^123,456.78');
            });
        });

        describe('global configuration', function () {
            var bbAutonumericConfig,
                defaultThousandSeparator;

            beforeEach(inject(function (_bbAutonumericConfig_) {
                bbAutonumericConfig = _bbAutonumericConfig_;
                defaultThousandSeparator = bbAutonumericConfig.number.aSep;

                bbAutonumericConfig.number.aSep = '*';
            }));

            afterEach(function () {
                bbAutonumericConfig.number.aSep = defaultThousandSeparator;
            });

            it('should be respected', function () {
                var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric />')($scope);

                $scope.numericValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('123*456.78');
            });

            it('should cascade from "number" to "money"', function () {
                var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric="money" />')($scope);

                $scope.numericValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('$123*456.78');
            });
        });
    });

    describe('filter', function () {
        var $filter,
            bbAutonumericConfig,
            bbResources;

        function validateMoneyAbbr(input, expected) {
            var formattedValue = $filter('bbAutonumeric')(input, 'money', true);
            expect(formattedValue).toBe(expected);
        }

        beforeEach(inject(function (_$filter_, _bbAutonumericConfig_, _bbResources_) {
            $filter = _$filter_;
            bbAutonumericConfig = _bbAutonumericConfig_;
            bbResources = _bbResources_;
        }));

        it('should format the specified value', function () {
            var formattedValue = $filter('bbAutonumeric')(123456.78, 'money');

            expect(formattedValue).toBe('$123,456.78');
        });

        it('should not reformat the value if it is already a formatted value', function () {
            var formattedValue = $filter('bbAutonumeric')('$123,456.78', 'money');

            expect(formattedValue).toBe('$123,456.78');
        });

        it('should use number as the default config type', function () {
            var formattedValue = $filter('bbAutonumeric')(123456.78);

            expect(formattedValue).toBe('123,456.78');
        });

        it('should not abbreviate values that round to less than 10,000', function () {
            validateMoneyAbbr(1.49, '$1');
            validateMoneyAbbr(1.5, '$2');
            validateMoneyAbbr(999, '$999');
            validateMoneyAbbr(999.49, '$999');
            validateMoneyAbbr(999.50, '$1,000');
            validateMoneyAbbr(1000, '$1,000');
            validateMoneyAbbr(9999, '$9,999');
            validateMoneyAbbr(9999.49, '$9,999');
        });

        it('should abbreviate values that round to more than than or equal to 10,000 but less than 1,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_thousands;

            validateMoneyAbbr(99999, '$99.9' + suffix);
            validateMoneyAbbr(999999, '$999.9' + suffix);
        });

        it('should abbreviate values that round to more than than or equal to 1,000,000 but less than 1,000,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_millions;

            validateMoneyAbbr(999999.50, '$1' + suffix);
            validateMoneyAbbr(1000000, '$1' + suffix);
            validateMoneyAbbr(9999999, '$9.9' + suffix);
            validateMoneyAbbr(99999999, '$99.9' + suffix);
            validateMoneyAbbr(999999999, '$999.9' + suffix);
        });

        it('should abbreviate values that round to more than or equal to 1,000,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_billions;

            validateMoneyAbbr(999999999.50, '$1' + suffix);
            validateMoneyAbbr(1000000000, '$1' + suffix);
            validateMoneyAbbr(9999999999, '$9.9' + suffix);
            validateMoneyAbbr(99999999999, '$99.9' + suffix);
            validateMoneyAbbr(999999999999, '$999.9' + suffix);
            validateMoneyAbbr(9999999999999, '$9,999.9' + suffix);
        });

        it('should floor (not round up) when abbreviating', function () {
            var suffix = bbResources.autonumeric_abbr_millions;

            validateMoneyAbbr(10364671, '$10.3' + suffix);
        });

        it('should display an empty string when the input is null', function () {
            var formattedValue = $filter('bbAutonumeric')(null, 'money');

            expect(formattedValue).toBe('');
        });

        it('should display an empty string when the input is undefined', function () {
            var formattedValue = $filter('bbAutonumeric')(undefined, 'money');

            expect(formattedValue).toBe('');
        });

        describe('when currency symbol placement is configured to be "suffix"', function () {
            var moneyConfig,
                numberConfig;

            beforeEach(function () {
                moneyConfig = bbAutonumericConfig.money;
                numberConfig = bbAutonumericConfig.number;

                bbAutonumericConfig.money = angular.extend(moneyConfig, {
                    aSign: ' €',
                    pSign: 's'
                });

                bbAutonumericConfig.number = angular.extend(numberConfig, {
                    // Tests an edge case in the code where the pSign could have a value but aSign is undefined.
                    aSign: undefined,
                    pSign: 's'
                });
            });

            afterEach(function () {
                bbAutonumericConfig.money = moneyConfig;
                bbAutonumericConfig.number = numberConfig;
            });

            it('should place the currency symbol after a non-abbreviated value', function () {
                var formattedValue = $filter('bbAutonumeric')(123456.78, 'money');

                expect(formattedValue).toBe('123,456.78 €');
            });

            it('should place the currency symbol after the suffix of an abbreviated value', function () {
                var suffix = bbResources.autonumeric_abbr_thousands;

                validateMoneyAbbr(99999, '99.9' + suffix + ' €');
            });

            it('should not add a currency symbol to an abbreviated value when the config type is "number"', function () {
                var formattedValue = $filter('bbAutonumeric')(123456.78, 'number', true),
                    suffix = bbResources.autonumeric_abbr_thousands;

                expect(formattedValue).toBe('123.4' + suffix);
            });
        });
    });
});
<commit_msg>Added test for pasting value into autonumeric<commit_after>/*jshint browser: true, jasmine: true */
/*global angular, inject, module, $ */

describe('Autonumeric', function () {
    'use strict';

    var $compile,
        $scope,
        $timeout;

    beforeEach(module('ngMock'));
    beforeEach(module('sky.autonumeric'));

    describe('directive', function () {
        beforeEach(inject(function (_$compile_, _$rootScope_, _$timeout_) {
            $compile = _$compile_;
            $scope = _$rootScope_;
            $timeout = _$timeout_;
        }));

        function compileEl() {
            return $compile('<input type="text" ng-model="numericValue" bb-autonumeric />')($scope);
        }

        it('should not have bb-autonumeric- class', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();
            expect(el.hasClass('bb-autonumeric-')).toBe(false);
        });

        it('should have bb-autonumeric-number class', function () {
            var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric="number" />')($scope);

            $scope.numericValue = 123456.78;
            $scope.$digest();
            expect(el.hasClass('bb-autonumeric-number')).toBe(true);
        });

        // Not passing in IE 10 on BrowserStack.  Maybe revisit this test later.  It's not mission critical.
        //        it('should select existing text on focus', function () {
        //            var el = compileEl();
        //
        //            // Focus and select can't happen unless the element is in the DOM.
        //            el.appendTo(document.body);
        //
        //            $scope.numericValue = 123456.78;
        //            $scope.$digest();
        //
        //            el[0].focus();
        //            $timeout.flush();
        //
        //            expect(el[0].selectionStart).toBe(0);
        //            expect(el[0].selectionEnd).toBe(el.val().length);
        //        });

        it('should clear the element\'s text when the scope\'s property is set to null', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();

            $scope.numericValue = null;
            $scope.$digest();

            expect(el.val()).toBe('');
        });

        it('should set the model value to null when element has no value', function () {
            var el = compileEl();

            $scope.numericValue = 123456.78;
            $scope.$digest();

            el.val('');
            el.change();

            expect($scope.numericValue).toBe(null);
        });

        it('should allow custom configuration', function () {
            var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric bb-autonumeric-settings="numericOptions" />')($scope);

            $scope.numericValue = 123456.78;
            $scope.numericOptions = {
                aSign: '^'
            };

            $scope.$digest();

            expect(el.val()).toBe('^123,456.78');

            // Ensure we can clear out custom settings.
            $scope.numericOptions = null;
            $scope.$digest();

            expect(el.val()).toBe('123,456.78');
        });

        describe('money option', function () {
            it('should have bb-autonumeric-money class', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;
                $scope.$digest();
                expect(el.hasClass('bb-autonumeric-money')).toBe(true);
            });

            it('should set scope value based on default configuration', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                el.val('$7,654,321.00');
                el.change();

                expect($scope.moneyValue).toBe(7654321);
            });

            it('should set scope value based on default configuration on enter press', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope),
                    event;

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                el.val('$7,654,321.00');
                event = new $.Event('keydown');
                event.which = 13;
                el.trigger(event);

                expect($scope.moneyValue).toBe(7654321);

                el.val('$8,654,321.00');
                event = new $.Event('keydown');
                event.which = 15;
                el.trigger(event);
                expect($scope.moneyValue).toBe(7654321);
            });

            it('should format the input value based on the scope value', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" />')($scope);

                $scope.moneyValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('$123,456.78');
            });

            it('should allow individual settings to be overridden', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" bb-autonumeric-settings="moneyOptions" />')($scope);

                $scope.moneyValue = 123456.78;
                $scope.moneyOptions = {
                    aSign: '^'
                };

                $scope.$digest();

                expect(el.val()).toBe('^123,456.78');
            });

            it('should keep the model in sync with a pasted value that does not meet the requirements', function () {
                var el = $compile('<input type="text" ng-model="moneyValue" bb-autonumeric="money" bb-autonumeric-settings="moneyOptions" />')($scope);

                $scope.moneyOptions = {
                    vMin: 0
                };

                $scope.moneyValue = -1.00;

                $scope.$digest();
                $timeout.flush();

                expect(el.val()).toBe('$0.00');
            });

        });

        describe('global configuration', function () {
            var bbAutonumericConfig,
                defaultThousandSeparator;

            beforeEach(inject(function (_bbAutonumericConfig_) {
                bbAutonumericConfig = _bbAutonumericConfig_;
                defaultThousandSeparator = bbAutonumericConfig.number.aSep;

                bbAutonumericConfig.number.aSep = '*';
            }));

            afterEach(function () {
                bbAutonumericConfig.number.aSep = defaultThousandSeparator;
            });

            it('should be respected', function () {
                var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric />')($scope);

                $scope.numericValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('123*456.78');
            });

            it('should cascade from "number" to "money"', function () {
                var el = $compile('<input type="text" ng-model="numericValue" bb-autonumeric="money" />')($scope);

                $scope.numericValue = 123456.78;

                $scope.$digest();

                expect(el.val()).toBe('$123*456.78');
            });
        });
    });

    describe('filter', function () {
        var $filter,
            bbAutonumericConfig,
            bbResources;

        function validateMoneyAbbr(input, expected) {
            var formattedValue = $filter('bbAutonumeric')(input, 'money', true);
            expect(formattedValue).toBe(expected);
        }

        beforeEach(inject(function (_$filter_, _bbAutonumericConfig_, _bbResources_) {
            $filter = _$filter_;
            bbAutonumericConfig = _bbAutonumericConfig_;
            bbResources = _bbResources_;
        }));

        it('should format the specified value', function () {
            var formattedValue = $filter('bbAutonumeric')(123456.78, 'money');

            expect(formattedValue).toBe('$123,456.78');
        });

        it('should not reformat the value if it is already a formatted value', function () {
            var formattedValue = $filter('bbAutonumeric')('$123,456.78', 'money');

            expect(formattedValue).toBe('$123,456.78');
        });

        it('should use number as the default config type', function () {
            var formattedValue = $filter('bbAutonumeric')(123456.78);

            expect(formattedValue).toBe('123,456.78');
        });

        it('should not abbreviate values that round to less than 10,000', function () {
            validateMoneyAbbr(1.49, '$1');
            validateMoneyAbbr(1.5, '$2');
            validateMoneyAbbr(999, '$999');
            validateMoneyAbbr(999.49, '$999');
            validateMoneyAbbr(999.50, '$1,000');
            validateMoneyAbbr(1000, '$1,000');
            validateMoneyAbbr(9999, '$9,999');
            validateMoneyAbbr(9999.49, '$9,999');
        });

        it('should abbreviate values that round to more than than or equal to 10,000 but less than 1,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_thousands;

            validateMoneyAbbr(99999, '$99.9' + suffix);
            validateMoneyAbbr(999999, '$999.9' + suffix);
        });

        it('should abbreviate values that round to more than than or equal to 1,000,000 but less than 1,000,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_millions;

            validateMoneyAbbr(999999.50, '$1' + suffix);
            validateMoneyAbbr(1000000, '$1' + suffix);
            validateMoneyAbbr(9999999, '$9.9' + suffix);
            validateMoneyAbbr(99999999, '$99.9' + suffix);
            validateMoneyAbbr(999999999, '$999.9' + suffix);
        });

        it('should abbreviate values that round to more than or equal to 1,000,000,000', function () {
            var suffix = bbResources.autonumeric_abbr_billions;

            validateMoneyAbbr(999999999.50, '$1' + suffix);
            validateMoneyAbbr(1000000000, '$1' + suffix);
            validateMoneyAbbr(9999999999, '$9.9' + suffix);
            validateMoneyAbbr(99999999999, '$99.9' + suffix);
            validateMoneyAbbr(999999999999, '$999.9' + suffix);
            validateMoneyAbbr(9999999999999, '$9,999.9' + suffix);
        });

        it('should floor (not round up) when abbreviating', function () {
            var suffix = bbResources.autonumeric_abbr_millions;

            validateMoneyAbbr(10364671, '$10.3' + suffix);
        });

        it('should display an empty string when the input is null', function () {
            var formattedValue = $filter('bbAutonumeric')(null, 'money');

            expect(formattedValue).toBe('');
        });

        it('should display an empty string when the input is undefined', function () {
            var formattedValue = $filter('bbAutonumeric')(undefined, 'money');

            expect(formattedValue).toBe('');
        });

        describe('when currency symbol placement is configured to be "suffix"', function () {
            var moneyConfig,
                numberConfig;

            beforeEach(function () {
                moneyConfig = bbAutonumericConfig.money;
                numberConfig = bbAutonumericConfig.number;

                bbAutonumericConfig.money = angular.extend(moneyConfig, {
                    aSign: ' €',
                    pSign: 's'
                });

                bbAutonumericConfig.number = angular.extend(numberConfig, {
                    // Tests an edge case in the code where the pSign could have a value but aSign is undefined.
                    aSign: undefined,
                    pSign: 's'
                });
            });

            afterEach(function () {
                bbAutonumericConfig.money = moneyConfig;
                bbAutonumericConfig.number = numberConfig;
            });

            it('should place the currency symbol after a non-abbreviated value', function () {
                var formattedValue = $filter('bbAutonumeric')(123456.78, 'money');

                expect(formattedValue).toBe('123,456.78 €');
            });

            it('should place the currency symbol after the suffix of an abbreviated value', function () {
                var suffix = bbResources.autonumeric_abbr_thousands;

                validateMoneyAbbr(99999, '99.9' + suffix + ' €');
            });

            it('should not add a currency symbol to an abbreviated value when the config type is "number"', function () {
                var formattedValue = $filter('bbAutonumeric')(123456.78, 'number', true),
                    suffix = bbResources.autonumeric_abbr_thousands;

                expect(formattedValue).toBe('123.4' + suffix);
            });
        });
    });
});
<|endoftext|>


<commit_before>/** @jsx React.DOM */

define(
  [
    'react',
    'backbone',
    'stores',
    './ImageList.react'
  ],
  function (React, Backbone, stores, ImageList) {

    var ENTER_KEY = 13;

    return React.createClass({

      //
      // Mounting & State
      // ----------------
      //

      propTypes: {
        onPrevious: React.PropTypes.func.isRequired,
        onNext: React.PropTypes.func.isRequired
      },

      getInitialState: function(){
        return this.getState();
      },

      getState: function() {
        var query = this.state ? this.state.query : null;
        var querySubmitted = this.state ? this.state.querySubmitted : false;
        return {
          query: query,
          querySubmitted: querySubmitted,
          images: stores.ApplicationStore.getAll()
        }
      },

      updateState: function () {
        if (this.isMounted()) this.setState(this.getState());
      },

      componentDidMount: function () {
        stores.ApplicationStore.addChangeListener(this.updateState);
      },

      componentWillUnmount: function () {
        stores.ApplicationStore.removeChangeListener(this.updateState);
      },

      //
      // Internal Modal Callbacks
      // ------------------------
      //

      handleChange: function (e) {
        var query = e.target.value;
        this.setState({query: query, querySubmitted: false});
      },

      handleKeyUp: function (e) {
        var query = this.state.query;
        if (e.keyCode == ENTER_KEY && query.length) {
          this.setState({query: query, querySubmitted: true});
        }
      },

      showImageDetails: function(image){
        this.props.onNext(image);
      },

      //
      // Callbacks
      //

      onBack: function(){
        this.props.onPrevious();
      },

      //
      // Render
      // ------
      //

      renderFilterDescription: function(query){
        var message;

        if(query){
          message = 'Showing results for "' + query + '"';
        }else{
          message = "Showing all images"
        }

        return (
          {message}
        )
      },

      renderBody: function(){
        var images = this.state.images,
            query = this.state.query,
            querySubmitted = this.state.querySubmitted;

        // if a search has been requested, use the search results instead of the full image list
        if(query && querySubmitted) {
          images = stores.ApplicationStore.getSearchResultsFor(query);
        }

        if(images){
          return (

              <input type="text" placeholder="Search across image name, tag or description" className="form-control search-input search-bar" onChange={this.handleChange} onKeyUp={this.handleKeyUp}/>
              {this.renderFilterDescription(query)}
              <ImageList images={images} onClick={this.showImageDetails}/>

          );
        }

        return (

            <input className="search-bar" onChange={this.handleChange} onKeyUp={this.handleKeyUp}/>
            {this.renderFilterDescription(query)}

        );
      },

      render: function () {
        return (

              {this.renderBody()}

              <button type="button" className="btn btn-danger cancel-button" onClick={this.onPrevious}>
                Cancel
              </button>

        );
      }

    });

  });
<commit_msg>style search bar<commit_after>/** @jsx React.DOM */

define(
  [
    'react',
    'backbone',
    'stores',
    './ImageList.react'
  ],
  function (React, Backbone, stores, ImageList) {

    var ENTER_KEY = 13;

    return React.createClass({

      //
      // Mounting & State
      // ----------------
      //

      propTypes: {
        onPrevious: React.PropTypes.func.isRequired,
        onNext: React.PropTypes.func.isRequired
      },

      getInitialState: function(){
        return this.getState();
      },

      getState: function() {
        var query = this.state ? this.state.query : null;
        var querySubmitted = this.state ? this.state.querySubmitted : false;
        return {
          query: query,
          querySubmitted: querySubmitted,
          images: stores.ApplicationStore.getAll()
        }
      },

      updateState: function () {
        if (this.isMounted()) this.setState(this.getState());
      },

      componentDidMount: function () {
        stores.ApplicationStore.addChangeListener(this.updateState);
      },

      componentWillUnmount: function () {
        stores.ApplicationStore.removeChangeListener(this.updateState);
      },

      //
      // Internal Modal Callbacks
      // ------------------------
      //

      handleChange: function (e) {
        var query = e.target.value;
        this.setState({query: query, querySubmitted: false});
      },

      handleKeyUp: function (e) {
        var query = this.state.query;
        if (e.keyCode == ENTER_KEY && query.length) {
          this.setState({query: query, querySubmitted: true});
        }
      },

      showImageDetails: function(image){
        this.props.onNext(image);
      },

      //
      // Callbacks
      //

      onBack: function(){
        this.props.onPrevious();
      },

      //
      // Render
      // ------
      //

      renderFilterDescription: function(query){
        var message;

        if(query){
          message = 'Showing results for "' + query + '"';
        }else{
          message = "Showing all images"
        }

        return (
          {message}
        )
      },

      renderBody: function(){
        var images = this.state.images,
            query = this.state.query,
            querySubmitted = this.state.querySubmitted;

        // if a search has been requested, use the search results instead of the full image list
        if(query && querySubmitted) {
          images = stores.ApplicationStore.getSearchResultsFor(query);
        }

        if(images){
          return (

              <input type="text"
                     placeholder="Search across image name, tag or description"
                     className="form-control search-input"
                     onChange={this.handleChange}
                     onKeyUp={this.handleKeyUp}
              />
              {this.renderFilterDescription(query)}
              <ImageList images={images} onClick={this.showImageDetails}/>

          );
        }

        return (

            <input type="text"
                   placeholder="Search across image name, tag or description"
                   className="form-control search-input"
                   onChange={this.handleChange}
                   onKeyUp={this.handleKeyUp}
            />
            {this.renderFilterDescription(query)}

        );
      },

      render: function () {
        return (

              {this.renderBody()}

              <button type="button" className="btn btn-danger cancel-button" onClick={this.onPrevious}>
                Cancel
              </button>

        );
      }

    });

  });
<|endoftext|>


<commit_before>/*********************************************************************************
 * SugarCRM Community Edition is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.

 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 *
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
 ********************************************************************************/

SUGAR.ajaxUI = {
    loadingWindow : false,
    callback : function(o)
    {
        var cont;
        if (typeof window.onbeforeunload == "function")
            window.onbeforeunload = null;
        scroll(0,0);
        try{
            var r = YAHOO.lang.JSON.parse(o.responseText);
            cont = r.content;

            if (r.title)
            {
                document.title = html_entity_decode(r.title);
            }
            if (r.action)
            {
                action_sugar_grp1 = r.action;
            }
            if (r.menu.module)
            {
                module_sugar_grp1 = r.menu.module;
            }
            if (r.favicon)
            {
                SUGAR.ajaxUI.setFavicon(r.favicon);
            }

            var c = document.getElementById("content");
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide content of placeholder before apply new one
            // @see SUGAR.util.evalScript
            c.style.visibility = 'hidden';
            c.innerHTML = cont;
            SUGAR.util.evalScript(cont);
            // all javascripts have been processed - show content of placeholder
            c.style.visibility = 'visible';

            if ( r.moduleList)
            {
                SUGAR.themes.setModuleTabs(r.moduleList);
            }

            // set response time from ajax response
            if(typeof(r.responseTime) != 'undefined'){
                var rt = $("#responseTime");
                if(rt.length > 0){
                    rt.html(rt.html().replace(/[\d]+\.[\d]+/, r.responseTime));
                }
                else if(typeof(logoStats) != "undefined"){
                	$("#logo").attr("title", logoStats.replace(/[\d]+\.[\d]+/, r.responseTime)).tipTip({maxWidth: "auto", edgeOffset: 10});
                }
            }
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide ajax loading message after all scripts are processed
            SUGAR.ajaxUI.hideLoadingPanel();
        } catch (e){
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide ajax loading message after all scripts are processed
            SUGAR.ajaxUI.hideLoadingPanel();
            SUGAR.ajaxUI.showErrorMessage(o.responseText);
        }
        SUGAR_callsInProgress--;
    },
    showErrorMessage : function(errorMessage)
    {
        if (!SUGAR.ajaxUI.errorPanel) {
                SUGAR.ajaxUI.errorPanel = new YAHOO.widget.Panel("ajaxUIErrorPanel", {
                    modal: false,
                    visible: true,
                    //constraintoviewport: true,
                    width	: "800px",
                    height : "600px",
                    close: true
                });
            }
            var panel = SUGAR.ajaxUI.errorPanel;
            panel.setHeader(SUGAR.language.get('app_strings','ERR_AJAX_LOAD')) ;
            panel.setBody('');
            panel.setFooter(SUGAR.language.get('app_strings','ERR_AJAX_LOAD_FOOTER')) ;
            panel.render(document.body);
            SUGAR.util.doWhen(
				function(){
					var f = document.getElementById("ajaxErrorFrame");
					return f != null && f.contentWindow != null && f.contentWindow.document != null;
				}, function(){
					document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML = errorMessage;
					window.setTimeout('throw "AjaxUI error parsing response"', 300);
			});

            //fire off a delayed check to make sure error message was rendered.
            SUGAR.ajaxUI.errorMessage = errorMessage;
            window.setTimeout('if((typeof(document.getElementById("ajaxErrorFrame")) == "undefined" || typeof(document.getElementById("ajaxErrorFrame")) == null  || document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML == "")){document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML=SUGAR.ajaxUI.errorMessage;}',3000);

            panel.show();
            panel.center();

            throw "AjaxUI error parsing response";
    },
    canAjaxLoadModule : function(module)
    {
        var checkLS = /&LicState=check/.exec(window.location.search);

        // Return false if ajax ui is completely disabled, or if license state is set to check
        if( checkLS || (typeof(SUGAR.config.disableAjaxUI) != 'undefined' && SUGAR.config.disableAjaxUI == true)){
            return false;
        }

        var bannedModules = SUGAR.config.stockAjaxBannedModules;
        //If banned modules isn't there, we are probably on a page that isn't ajaxUI compatible
        if (typeof(bannedModules) == 'undefined')
            return false;
        // Mechanism to allow for overriding or adding to this list
        if(typeof(SUGAR.config.addAjaxBannedModules) != 'undefined'){
            bannedModules.concat(SUGAR.config.addAjaxBannedModules);
        }
        if(typeof(SUGAR.config.overrideAjaxBannedModules) != 'undefined'){
            bannedModules = SUGAR.config.overrideAjaxBannedModules;
        }

        return SUGAR.util.arrayIndexOf(bannedModules, module) == -1;
    },

    loadContent : function(url, params)
    {
        if(YAHOO.lang.trim(url) != "")
        {
            //Don't ajax load certain modules
            var mRegex = /module=([^&]*)/.exec(url);
            var module = mRegex ? mRegex[1] : false;
            if (module && SUGAR.ajaxUI.canAjaxLoadModule(module))
            {
                YAHOO.util.History.navigate('ajaxUILoc',  url);
            } else {
                window.location = url;
            }
        }
    },

    go : function(url)
    {

        if(YAHOO.lang.trim(url) != "")
        {
            var con = YAHOO.util.Connect, ui = SUGAR.ajaxUI;
            if (ui.lastURL == url)
                return;
            var inAjaxUI = /action=ajaxui/.exec(window.location);
            if (typeof (window.onbeforeunload) == "function" && window.onbeforeunload())
            {
                //If there is an unload function, we need to check it ourselves
                if (!confirm(window.onbeforeunload()))
                {
                    if (!inAjaxUI)
                    {
                        //User doesn't want to navigate
                        window.location.hash = "";
                    }
                    else
                    {
                        YAHOO.util.History.navigate('ajaxUILoc',  ui.lastURL);
                    }
                    return;
                }
                window.onbeforeunload = null;
            }
            if (ui.lastCall && con.isCallInProgress(ui.lastCall)) {
                con.abort(ui.lastCall);
            }
            var mRegex = /module=([^&]*)/.exec(url);
            var module = mRegex ? mRegex[1] : false;
            //If we can't ajax load the module (blacklisted), set the URL directly.
            if (!ui.canAjaxLoadModule(module)) {
                window.location = url;
                return;
            }
            ui.lastURL = url;
            ui.cleanGlobals();
            var loadLanguageJS = '';
            if(module && typeof(SUGAR.language.languages[module]) == 'undefined'){
                loadLanguageJS = '&loadLanguageJS=1';
            }

            if (!inAjaxUI) {
                //If we aren't in the ajaxUI yet, we need to reload the page to get setup properly
                if (!SUGAR.isIE)
                    window.location.replace("index.php?action=ajaxui#ajaxUILoc=" + encodeURIComponent(url));
                else {
                    //if we use replace under IE, it will cache the page as the replaced version and thus no longer load the previous page.
                    window.location.hash = "#";
                    window.location.assign("index.php?action=ajaxui#ajaxUILoc=" + encodeURIComponent(url));
                }
            }
            else {
                SUGAR_callsInProgress++;
                SUGAR.ajaxUI.showLoadingPanel();
                ui.lastCall = YAHOO.util.Connect.asyncRequest('GET', url + '&ajax_load=1' + loadLanguageJS, {
                    success: SUGAR.ajaxUI.callback,
                    failure: function(){
                        SUGAR_callsInProgress--;
                        SUGAR.ajaxUI.hideLoadingPanel();
                        SUGAR.ajaxUI.showErrorMessage(SUGAR.language.get('app_strings','ERR_AJAX_LOAD_FAILURE'));
                    }
                });
            }
        }
    },

    submitForm : function(formname, params)
    {
        var con = YAHOO.util.Connect, SA = SUGAR.ajaxUI;
        if (SA.lastCall && con.isCallInProgress(SA.lastCall)) {
            con.abort(SA.lastCall);
        }
        //Reset the EmailAddressWidget before loading a new page
        SA.cleanGlobals();
        //Don't ajax load certain modules
        var form = YAHOO.util.Dom.get(formname) || document.forms[formname];
        if (SA.canAjaxLoadModule(form.module.value)
            //Do not try to submit a form that contains a file input via ajax.
            && typeof(YAHOO.util.Selector.query("input[type=file]", form)[0]) == "undefined"
            //Do not try to ajax submit a form if the ajaxUI is not initialized
            && /action=ajaxui/.exec(window.location))
        {
            var string = con.setForm(form);
            var baseUrl = "index.php?action=ajaxui#ajaxUILoc=";
            SA.lastURL = "";
            //Use POST for long forms and GET for short forms (GET allow resubmit via reload)
            if(string.length > 200)
            {
                SUGAR.ajaxUI.showLoadingPanel();
                form.onsubmit = function(){ return true; };
                form.submit();
            } else {
                con.resetFormState();
                window.location = baseUrl + encodeURIComponent("index.php?" + string);
            }
            return true;
        } else {

            if( typeof(YAHOO.util.Selector.query("input[type=submit]", form)[0]) != "undefined"
                    && YAHOO.util.Selector.query("input[type=submit]", form)[0].value == "Save")
            {
                ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
            }

            form.submit();
            return false;
        }
    },

    cleanGlobals : function()
    {
        sqs_objects = {};
        QSProcessedFieldsArray = {};
        collection = {};
        //Reset the EmailAddressWidget before loading a new page
        if (SUGAR.EmailAddressWidget){
            SUGAR.EmailAddressWidget.instances = {};
            SUGAR.EmailAddressWidget.count = {};
        }
        YAHOO.util.Event.removeListener(window, 'resize');
        //Hide any connector dialogs
        if(typeof(dialog) != 'undefined' && typeof(dialog.destroy) == 'function'){
            dialog.destroy();
            delete dialog;
        }

    },
    firstLoad : function()
    {
        //Setup Browser History
        var url = YAHOO.util.History.getBookmarkedState('ajaxUILoc');
        var aRegex = /action=([^&#]*)/.exec(window.location);
        var action = aRegex ? aRegex[1] : false;
        var mRegex = /module=([^&#]*)/.exec(window.location);
        var module = mRegex ? mRegex[1] : false;
        if (module != "ModuleBuilder")
        {
            var go = url != null || action == "ajaxui";
            url = url ? url : 'index.php?module=Home&action=index';
            YAHOO.util.History.register('ajaxUILoc', url, SUGAR.ajaxUI.go);
            YAHOO.util.History.initialize("ajaxUI-history-field", "ajaxUI-history-iframe");
            SUGAR.ajaxUI.hist_loaded = true;
            if (go)
                SUGAR.ajaxUI.go(url);
        }
        SUGAR_callsInProgress--;
    },
    print: function()
    {
        var url = YAHOO.util.History.getBookmarkedState('ajaxUILoc');
        SUGAR.util.openWindow(
            url + '&print=true',
            'printwin',
            'menubar=1,status=0,resizable=1,scrollbars=1,toolbar=0,location=1'
        );
    },
    showLoadingPanel: function()
    {
        if (!SUGAR.ajaxUI.loadingPanel)
        {
            SUGAR.ajaxUI.loadingPanel = new YAHOO.widget.Panel("ajaxloading",
            {
                width:"240px",
                fixedcenter:true,
                close:false,
                draggable:false,
                constraintoviewport:false,
                modal:true,
                visible:false
            });
            SUGAR.ajaxUI.loadingPanel.setBody('
 ' + SUGAR.language.get('app_strings', 'LBL_LOADING_PAGE') +'
');
            SUGAR.ajaxUI.loadingPanel.render(document.body);
        }

        if (document.getElementById('ajaxloading_c'))
            document.getElementById('ajaxloading_c').style.display = '';

        SUGAR.ajaxUI.loadingPanel.show();

    },
    hideLoadingPanel: function()
    {
        SUGAR.ajaxUI.loadingPanel.hide();

        if (document.getElementById('ajaxloading_c'))
            document.getElementById('ajaxloading_c').style.display = 'none';
    },
    setFavicon: function(data)
    {
        var head = document.getElementsByTagName("head")[0];

        // first remove all rel="icon" links as long as updating an existing one
        // could take no effect
        var links = head.getElementsByTagName("link");
        var re = /\bicon\b/i;
        for (var i = 0; i < links.length; i++)        {
            if (re.test(links[i].rel))
            {
                head.removeChild(links[i]);
            }
        }

        var link = document.createElement("link");

        link.href = data.url;
        // type attribute is important for Google Chrome browser
        link.type = data.type;
        link.rel = "icon";
        head.appendChild(link);
    }
};
<commit_msg>Update ajaxUI.js<commit_after>/*********************************************************************************
 * SugarCRM Community Edition is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.

 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 *
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
 ********************************************************************************/

SUGAR.ajaxUI = {
    loadingWindow : false,
    callback : function(o)
    {
        var cont;
        if (typeof window.onbeforeunload == "function")
            window.onbeforeunload = null;
        scroll(0,0);
        try{
            var r = YAHOO.lang.JSON.parse(o.responseText);
            cont = r.content;

            if (r.title)
            {
                document.title = html_entity_decode(r.title);
            }
            if (r.action)
            {
                action_sugar_grp1 = r.action;
            }
            if (r.menu.module)
            {
                module_sugar_grp1 = r.menu.module;
            }
            if (r.favicon)
            {
                SUGAR.ajaxUI.setFavicon(r.favicon);
            }

            var c = document.getElementById("content");
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide content of placeholder before apply new one
            // @see SUGAR.util.evalScript
            c.style.visibility = 'hidden';
            c.innerHTML = cont;
            SUGAR.util.evalScript(cont);
            // all javascripts have been processed - show content of placeholder
            c.style.visibility = 'visible';

            if ( r.moduleList)
            {
                SUGAR.themes.setModuleTabs(r.moduleList);
            }

            // set response time from ajax response
            if(typeof(r.responseTime) != 'undefined'){
                var rt = $("#responseTime");
                if(rt.length > 0){
                    rt.html(rt.html().replace(/[\d]+\.[\d]+/, r.responseTime));
                }
                else if(typeof(logoStats) != "undefined"){
                	$("#logo").attr("title", logoStats.replace(/[\d]+\.[\d]+/, r.responseTime)).tipTip({maxWidth: "auto", edgeOffset: 10});
                }
            }
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide ajax loading message after all scripts are processed
            SUGAR.ajaxUI.hideLoadingPanel();
        } catch (e){
            // Bug #49205 : Subpanels fail to load when selecting subpanel tab
            // hide ajax loading message after all scripts are processed
            SUGAR.ajaxUI.hideLoadingPanel();
            SUGAR.ajaxUI.showErrorMessage(o.responseText);
        }
        SUGAR_callsInProgress--;
    },
    showErrorMessage : function(errorMessage)
    {
        if (!SUGAR.ajaxUI.errorPanel) {
                SUGAR.ajaxUI.errorPanel = new YAHOO.widget.Panel("ajaxUIErrorPanel", {
                    modal: false,
                    visible: true,
                    width	: "800px",
                    height : "600px",
                    close: true
                });
            }
            var panel = SUGAR.ajaxUI.errorPanel;
            panel.setHeader(SUGAR.language.get('app_strings','ERR_AJAX_LOAD')) ;
            panel.setBody('');
            panel.setFooter(SUGAR.language.get('app_strings','ERR_AJAX_LOAD_FOOTER')) ;
            panel.render(document.body);
            SUGAR.util.doWhen(
				function(){
					var f = document.getElementById("ajaxErrorFrame");
					return f != null && f.contentWindow != null && f.contentWindow.document != null;
				}, function(){
					document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML = errorMessage;
					window.setTimeout('throw "AjaxUI error parsing response"', 300);
			});

            //fire off a delayed check to make sure error message was rendered.
            SUGAR.ajaxUI.errorMessage = errorMessage;
            window.setTimeout('if((typeof(document.getElementById("ajaxErrorFrame")) == "undefined" || typeof(document.getElementById("ajaxErrorFrame")) == null  || document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML == "")){document.getElementById("ajaxErrorFrame").contentWindow.document.body.innerHTML=SUGAR.ajaxUI.errorMessage;}',3000);

            panel.show();
            panel.center();

            throw "AjaxUI error parsing response";
    },
    canAjaxLoadModule : function(module)
    {
        var checkLS = /&LicState=check/.exec(window.location.search);

        // Return false if ajax ui is completely disabled, or if license state is set to check
        if( checkLS || (typeof(SUGAR.config.disableAjaxUI) != 'undefined' && SUGAR.config.disableAjaxUI == true)){
            return false;
        }

        var bannedModules = SUGAR.config.stockAjaxBannedModules;
        //If banned modules isn't there, we are probably on a page that isn't ajaxUI compatible
        if (typeof(bannedModules) == 'undefined')
            return false;
        // Mechanism to allow for overriding or adding to this list
        if(typeof(SUGAR.config.addAjaxBannedModules) != 'undefined'){
            bannedModules.concat(SUGAR.config.addAjaxBannedModules);
        }
        if(typeof(SUGAR.config.overrideAjaxBannedModules) != 'undefined'){
            bannedModules = SUGAR.config.overrideAjaxBannedModules;
        }

        return SUGAR.util.arrayIndexOf(bannedModules, module) == -1;
    },

    loadContent : function(url, params)
    {
        if(YAHOO.lang.trim(url) != "")
        {
            //Don't ajax load certain modules
            var mRegex = /module=([^&]*)/.exec(url);
            var module = mRegex ? mRegex[1] : false;
            if (module && SUGAR.ajaxUI.canAjaxLoadModule(module))
            {
                YAHOO.util.History.navigate('ajaxUILoc',  url);
            } else {
                window.location = url;
            }
        }
    },

    go : function(url)
    {

        if(YAHOO.lang.trim(url) != "")
        {
            var con = YAHOO.util.Connect, ui = SUGAR.ajaxUI;
            if (ui.lastURL == url)
                return;
            var inAjaxUI = /action=ajaxui/.exec(window.location);
            if (typeof (window.onbeforeunload) == "function" && window.onbeforeunload())
            {
                //If there is an unload function, we need to check it ourselves
                if (!confirm(window.onbeforeunload()))
                {
                    if (!inAjaxUI)
                    {
                        //User doesn't want to navigate
                        window.location.hash = "";
                    }
                    else
                    {
                        YAHOO.util.History.navigate('ajaxUILoc',  ui.lastURL);
                    }
                    return;
                }
                window.onbeforeunload = null;
            }
            if (ui.lastCall && con.isCallInProgress(ui.lastCall)) {
                con.abort(ui.lastCall);
            }
            var mRegex = /module=([^&]*)/.exec(url);
            var module = mRegex ? mRegex[1] : false;
            //If we can't ajax load the module (blacklisted), set the URL directly.
            if (!ui.canAjaxLoadModule(module)) {
                window.location = url;
                return;
            }
            ui.lastURL = url;
            ui.cleanGlobals();
            var loadLanguageJS = '';
            if(module && typeof(SUGAR.language.languages[module]) == 'undefined'){
                loadLanguageJS = '&loadLanguageJS=1';
            }

            if (!inAjaxUI) {
                //If we aren't in the ajaxUI yet, we need to reload the page to get setup properly
                if (!SUGAR.isIE)
                    window.location.replace("index.php?action=ajaxui#ajaxUILoc=" + encodeURIComponent(url));
                else {
                    //if we use replace under IE, it will cache the page as the replaced version and thus no longer load the previous page.
                    window.location.hash = "#";
                    window.location.assign("index.php?action=ajaxui#ajaxUILoc=" + encodeURIComponent(url));
                }
            }
            else {
                SUGAR_callsInProgress++;
                SUGAR.ajaxUI.showLoadingPanel();
                ui.lastCall = YAHOO.util.Connect.asyncRequest('GET', url + '&ajax_load=1' + loadLanguageJS, {
                    success: SUGAR.ajaxUI.callback,
                    failure: function(){
                        SUGAR_callsInProgress--;
                        SUGAR.ajaxUI.hideLoadingPanel();
                        SUGAR.ajaxUI.showErrorMessage(SUGAR.language.get('app_strings','ERR_AJAX_LOAD_FAILURE'));
                    }
                });
            }
        }
    },

    submitForm : function(formname, params)
    {
        var con = YAHOO.util.Connect, SA = SUGAR.ajaxUI;
        if (SA.lastCall && con.isCallInProgress(SA.lastCall)) {
            con.abort(SA.lastCall);
        }
        //Reset the EmailAddressWidget before loading a new page
        SA.cleanGlobals();
        //Don't ajax load certain modules
        var form = YAHOO.util.Dom.get(formname) || document.forms[formname];
        if (SA.canAjaxLoadModule(form.module.value)
            //Do not try to submit a form that contains a file input via ajax.
            && typeof(YAHOO.util.Selector.query("input[type=file]", form)[0]) == "undefined"
            //Do not try to ajax submit a form if the ajaxUI is not initialized
            && /action=ajaxui/.exec(window.location))
        {
            var string = con.setForm(form);
            var baseUrl = "index.php?action=ajaxui#ajaxUILoc=";
            SA.lastURL = "";
            //Use POST for long forms and GET for short forms (GET allow resubmit via reload)
            if(string.length > 200)
            {
                SUGAR.ajaxUI.showLoadingPanel();
                form.onsubmit = function(){ return true; };
                form.submit();
            } else {
                con.resetFormState();
                window.location = baseUrl + encodeURIComponent("index.php?" + string);
            }
            return true;
        } else {

            if( typeof(YAHOO.util.Selector.query("input[type=submit]", form)[0]) != "undefined"
                    && YAHOO.util.Selector.query("input[type=submit]", form)[0].value == "Save")
            {
                ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
            }

            form.submit();
            return false;
        }
    },

    cleanGlobals : function()
    {
        sqs_objects = {};
        QSProcessedFieldsArray = {};
        collection = {};
        //Reset the EmailAddressWidget before loading a new page
        if (SUGAR.EmailAddressWidget){
            SUGAR.EmailAddressWidget.instances = {};
            SUGAR.EmailAddressWidget.count = {};
        }
        YAHOO.util.Event.removeListener(window, 'resize');
        //Hide any connector dialogs
        if(typeof(dialog) != 'undefined' && typeof(dialog.destroy) == 'function'){
            dialog.destroy();
            delete dialog;
        }

    },
    firstLoad : function()
    {
        //Setup Browser History
        var url = YAHOO.util.History.getBookmarkedState('ajaxUILoc');
        var aRegex = /action=([^&#]*)/.exec(window.location);
        var action = aRegex ? aRegex[1] : false;
        var mRegex = /module=([^&#]*)/.exec(window.location);
        var module = mRegex ? mRegex[1] : false;
        if (module != "ModuleBuilder")
        {
            var go = url != null || action == "ajaxui";
            url = url ? url : 'index.php?module=Home&action=index';
            YAHOO.util.History.register('ajaxUILoc', url, SUGAR.ajaxUI.go);
            YAHOO.util.History.initialize("ajaxUI-history-field", "ajaxUI-history-iframe");
            SUGAR.ajaxUI.hist_loaded = true;
            if (go)
                SUGAR.ajaxUI.go(url);
        }
        SUGAR_callsInProgress--;
    },
    print: function()
    {
        var url = YAHOO.util.History.getBookmarkedState('ajaxUILoc');
        SUGAR.util.openWindow(
            url + '&print=true',
            'printwin',
            'menubar=1,status=0,resizable=1,scrollbars=1,toolbar=0,location=1'
        );
    },
    showLoadingPanel: function()
    {
        if (!SUGAR.ajaxUI.loadingPanel)
        {
            SUGAR.ajaxUI.loadingPanel = new YAHOO.widget.Panel("ajaxloading",
            {
                width:"240px",
                fixedcenter:true,
                close:false,
                draggable:false,
                constraintoviewport:false,
                modal:true,
                visible:false
            });
            SUGAR.ajaxUI.loadingPanel.setBody('
 ' + SUGAR.language.get('app_strings', 'LBL_LOADING_PAGE') +'
');
            SUGAR.ajaxUI.loadingPanel.render(document.body);
        }

        if (document.getElementById('ajaxloading_c'))
            document.getElementById('ajaxloading_c').style.display = '';

        SUGAR.ajaxUI.loadingPanel.show();

    },
    hideLoadingPanel: function()
    {
        SUGAR.ajaxUI.loadingPanel.hide();

        if (document.getElementById('ajaxloading_c'))
            document.getElementById('ajaxloading_c').style.display = 'none';
    },
    setFavicon: function(data)
    {
        var head = document.getElementsByTagName("head")[0];

        // first remove all rel="icon" links as long as updating an existing one
        // could take no effect
        var links = head.getElementsByTagName("link");
        var re = /\bicon\b/i;
        for (var i = 0; i < links.length; i++)        {
            if (re.test(links[i].rel))
            {
                head.removeChild(links[i]);
            }
        }

        var link = document.createElement("link");

        link.href = data.url;
        // type attribute is important for Google Chrome browser
        link.type = data.type;
        link.rel = "icon";
        head.appendChild(link);
    }
};
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var http = require('http');
var ecstatic = require('ecstatic');
var open = require('open');
var browserify = require('browserify');
var watchify = require('watchify');

var constants = require('../../tasks/util/constants');
var compress = require('../../tasks/util/compress_attributes');

var PORT = process.argv[2] || 3000;

// Create server
var server = http.createServer(ecstatic({
    root: constants.pathToRoot,
    cache: 0,
    gzip: true
}));

// Bundle development source code
var b = browserify(constants.pathToPlotlyIndex, {
    debug: true,
    standalone: 'Plotly',
    transform: [compress],
    cache: {},
    packageCache: {},
    plugin: [watchify]
});
b.on('update', bundlePlotly);

// Bundle devtools code
var devtoolsPath = path.join(constants.pathToRoot, 'devtools/test_dashboard');
var devtools = browserify(path.join(devtoolsPath, 'devtools.js'), {});

var firstBundle = true;

// Start the server up!
server.listen(PORT);

// Build and bundle all the things!
console.log('Building the first bundle. This might take a little while...\n');
getMockFiles()
    .then(readFiles)
    .then(createMocksList)
    .then(saveToFile)
    .then(bundleDevtools)
    .then(bundlePlotly);

function getMockFiles() {
    return new Promise(function(resolve, reject) {
        fs.readdir(constants.pathToTestImageMocks, function(err, files) {
            if(err) {
                reject(err);
            } else {
                resolve(files);
            }
        });
    });
}

function readFiles(files) {
    var promises = files.map(function(file) {
        var filePath = path.join(constants.pathToTestImageMocks, file);
        return readFilePromise(filePath);
    });

    return Promise.all(promises);
}

function createMocksList(files) {
    var mocksList = files.map(function(file) {
        var contents = JSON.parse(file.contents);

        // get plot type keywords from mocks
        var types = contents.data.map(function(trace) {
            return trace.type || 'scatter';
        }).reduce(function(acc, type, i, arr) {
            if(arr.lastIndexOf(type) === i) {
                acc.push(type);
            }
            return acc;
        }, []);

        var filename = file.name.split('/').pop();

        return {
            name: filename.slice(0, -5),
            file: filename,
            keywords: types.join(', ')
        };
    });

    return mocksList;
}

function saveToFile(mocksList) {
    var filePath = path.join(constants.pathToBuild, 'test_dashboard_mocks.json');
    var content = JSON.stringify(mocksList, null, 4);

    return writeFilePromise(filePath, content);
}

function readFilePromise(file) {
    return new Promise(function(resolve, reject) {
        fs.readFile(file, { encoding: 'utf-8' }, function(err, contents) {
            if(err) {
                reject(err);
            } else {
                resolve({
                    name: file,
                    contents: contents
                });
            }
        });
    });
}

function writeFilePromise(path, contents) {
    return new Promise(function(resolve, reject) {
        fs.writeFile(path, contents, function(err) {
            if(err) {
                reject(err);
            } else {
                resolve(path);
            }
        });
    });
}

function bundlePlotly() {
    b.bundle(function(err) {
        if(err) {
            console.error('Error while bundling!', err);
        }

        if(firstBundle) {
            open('http://localhost:' + PORT + '/devtools/test_dashboard');
            firstBundle = false;
        }
        console.log('Bundle updated at ' + new Date().toLocaleTimeString());
    }).pipe(fs.createWriteStream(constants.pathToPlotlyBuild));
}

function bundleDevtools() {
    return new Promise(function(resolve, reject) {
        devtools.bundle(function(err) {
            if(err) {
                console.error('Error while bundling!', err);
                return reject(err);
            } else {
                return resolve();
            }
        }).pipe(fs.createWriteStream(constants.pathToTestDashboardBundle));
    });
}
<commit_msg>improve server logs:<commit_after>var fs = require('fs');
var path = require('path');
var http = require('http');
var ecstatic = require('ecstatic');
var open = require('open');
var browserify = require('browserify');
var watchify = require('watchify');

var constants = require('../../tasks/util/constants');
var compress = require('../../tasks/util/compress_attributes');

var PORT = process.argv[2] || 3000;

// Create server
var server = http.createServer(ecstatic({
    root: constants.pathToRoot,
    cache: 0,
    gzip: true
}));

// Bundle development source code
var b = browserify(constants.pathToPlotlyIndex, {
    debug: true,
    standalone: 'Plotly',
    transform: [compress],
    cache: {},
    packageCache: {},
    plugin: [watchify]
});
b.on('update', bundlePlotly);

// Bundle devtools code
var devtoolsPath = path.join(constants.pathToRoot, 'devtools/test_dashboard');
var devtools = browserify(path.join(devtoolsPath, 'devtools.js'), {});

var firstBundle = true;

// Start the server up!
server.listen(PORT);

// Build and bundle all the things!
console.log('Building the first bundle. This might take a little while...\n');
getMockFiles()
    .then(readFiles)
    .then(createMocksList)
    .then(saveToFile)
    .then(bundleDevtools)
    .then(bundlePlotly);

function getMockFiles() {
    return new Promise(function(resolve, reject) {
        fs.readdir(constants.pathToTestImageMocks, function(err, files) {
            if(err) {
                reject(err);
            } else {
                resolve(files);
            }
        });
    });
}

function readFiles(files) {
    var promises = files.map(function(file) {
        var filePath = path.join(constants.pathToTestImageMocks, file);
        return readFilePromise(filePath);
    });

    return Promise.all(promises);
}

function createMocksList(files) {
    var mocksList = files.map(function(file) {
        var contents = JSON.parse(file.contents);

        // get plot type keywords from mocks
        var types = contents.data.map(function(trace) {
            return trace.type || 'scatter';
        }).reduce(function(acc, type, i, arr) {
            if(arr.lastIndexOf(type) === i) {
                acc.push(type);
            }
            return acc;
        }, []);

        var filename = file.name.split('/').pop();

        return {
            name: filename.slice(0, -5),
            file: filename,
            keywords: types.join(', ')
        };
    });

    return mocksList;
}

function saveToFile(mocksList) {
    var filePath = path.join(constants.pathToBuild, 'test_dashboard_mocks.json');
    var content = JSON.stringify(mocksList, null, 4);

    return writeFilePromise(filePath, content);
}

function readFilePromise(file) {
    return new Promise(function(resolve, reject) {
        fs.readFile(file, { encoding: 'utf-8' }, function(err, contents) {
            if(err) {
                reject(err);
            } else {
                resolve({
                    name: file,
                    contents: contents
                });
            }
        });
    });
}

function writeFilePromise(path, contents) {
    return new Promise(function(resolve, reject) {
        fs.writeFile(path, contents, function(err) {
            if(err) {
                reject(err);
            } else {
                resolve(path);
            }
        });
    });
}

function bundlePlotly() {
    b.bundle(function(err) {
        if(err) {
            console.error('Error while bundling!', JSON.stringify(String(err)));
        } else {
            console.log('Bundle updated at ' + new Date().toLocaleTimeString());
        }

        if(firstBundle) {
            open('http://localhost:' + PORT + '/devtools/test_dashboard');
            firstBundle = false;
        }
    }).pipe(fs.createWriteStream(constants.pathToPlotlyBuild));
}

function bundleDevtools() {
    return new Promise(function(resolve, reject) {
        devtools.bundle(function(err) {
            if(err) {
                console.error('Error while bundling!', JSON.stringify(String(err)));
                return reject(err);
            } else {
                return resolve();
            }
        }).pipe(fs.createWriteStream(constants.pathToTestDashboardBundle));
    });
}
<|endoftext|>


<commit_before>describe("256", function() {
  var game;

  beforeEach(function() {
    game = new Game('0000000000000022')
  });

  it("has a board", function() {
    expect(game.board).toEqual([0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2])
  });

  it("has an old board", function() {
    game.moveUp(game.board)
    expect(game.oldBoard).toEqual([0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2])
  })

  it("recognizes which tile is new by tracking it's index", function() {
    expect(game.newBlockIndex).toEqual(undefined);
    game.spawnBlock()
    expect(game.newBlockIndex).not.toEqual(undefined)
  })

  describe("it moves each row to the direction specified", function() {
    describe("click down arrow", function () {
      it("moves all numbers to the right, getting rid of zeros to the right", function() {
        game.moveRight(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[15]).not.toEqual(0)
      });

      it("combines tiles once, prioritizing tiles towards the right", function() {
        game.moveRight(game.board)
        expect(game.board[15]).toEqual(4)
      });
    });

    describe("click left arrow", function() {
      it("moves all numbers to the left, getting rid of zeros to the left", function() {
        game.moveLeft(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[12]).not.toEqual(0)
      });
    });

      it("combines tiles once, prioritizing tiles towards the left", function() {
        game.moveLeft(game.board)
        expect(game.board[12]).toEqual(4)
      });
    });

    describe("click up arrow", function() {
      it("moves all numbers up, getting rid of zeros towards the top", function() {
        game.moveUp(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[15]).toEqual(0)
      });

      it("combines tiles once, prioritizing tiles towards the top wall of the board", function() {
        game.moveUp(game.board)
        expect(game.board[3]).toEqual(2)
      });
    });

    describe("down arrow", function() {
      it("moves all numbers down, getting rid of zeros towards the bottom", function() {
        game.moveDown(game.board)
        expect(game.oldBoard).toEqual(game.board)
      });

      it("combines tiles once, prioritizing tiles towards the floor of the board", function() {
        game.moveDown(game.board)
        expect(game.board[14]).toEqual(game.board[15])
      });
  });
})

<commit_msg>Finish writing jasmine tests<commit_after>describe("256", function() {
  var game;

  beforeEach(function() {
    game = new Game('0000000000000022')
  });

  it("has a board", function() {
    expect(game.board).toEqual([0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2])
  });

  it("has an old board", function() {
    game.moveUp(game.board)
    expect(game.oldBoard).toEqual([0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2])
  })

  it("recognizes which tile is new by tracking it's index", function() {
    expect(game.newBlockIndex).toEqual(undefined);
    game.spawnBlock()
    expect(game.newBlockIndex).not.toEqual(undefined)
  })

  describe("it moves each row to the direction specified", function() {
    describe("move right", function () {
      it("moves all numbers to the right, getting rid of zeros to the right", function() {
        game.moveRight(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[15]).not.toEqual(0)
      });

      it("combines tiles once, prioritizing tiles towards the right", function() {
        game.moveRight(game.board)
        expect(game.board[15]).toEqual(4)
      });
    });

    describe("move left", function() {
      it("moves all numbers to the left, getting rid of zeros to the left", function() {
        game.moveLeft(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[12]).not.toEqual(0)
      });

      it("combines tiles once, prioritizing tiles towards the left", function() {
        game.moveLeft(game.board)
        expect(game.board[12]).toEqual(4)
      });
    });

    describe("move up", function() {
      it("moves all numbers up, getting rid of zeros towards the top", function() {
        game.moveUp(game.board)
        expect(game.oldBoard).not.toEqual(game.board)
        expect(game.board[15]).toEqual(0)
      });

      it("combines tiles once, prioritizing tiles towards the top wall of the board", function() {
        game.moveUp(game.board)
        expect(game.board[3]).toEqual(2)
      });
    });

    describe("move down", function() {
      it("moves all numbers down, getting rid of zeros towards the bottom", function() {
        game.moveDown(game.board)
        expect(game.oldBoard).toEqual(game.board)
      });

      it("combines tiles once, prioritizing tiles towards the floor of the board", function() {
        game.moveDown(game.board)
        expect(game.board[14]).toEqual(game.board[15])
      });
    });
  });

  describe("spawnBlock", function() {
    it("spawns a new tile", function() {
      game.moveRight(game.board)
      expect(game.oldBoard).not.toEqual(game.board)
      var zeroCountOld = 0;
      var zeroCountCurrent = 0;
      for (var i = 0; i < game.oldBoard.length; i++) {
        if (game.oldBoard[i] === 0) {
          zeroCountOld += 1
        }
      }

      for (var i = 0; i < game.board.length; i++) {
        if (game.board[i] === 0) {
          zeroCountCurrent += 1
        }
      }
      expect(zeroCountOld).toBeLessThan(zeroCountCurrent)
    });
  });
});
<|endoftext|>