<commit_before>'use strict';

/**
 * @ngdoc interface
 * @name angular.Module
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  return ensure(ensure(window, 'angular', Object), 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @description
     *
     * The `angular.module` is a global place for creating and registering Angular modules. All
     * modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     *
     * # Module
     *
     * A module is a collocation of services, directives, filters, and configuration information. Module
     * is used to configure the {@link AUTO.$injector $injector}.
     *
     *

     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * });
     *

     *
     * Then you can create an injector and load your modules like this:
     *
     *

     * var injector = angular.injector(['ng', 'MyModule'])
     *

     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
     *        the module is being retrieved for further configuration.
     * @param {Function} configFn Optional configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw Error('No module: ' + name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @propertyOf angular.Module
           * @returns {Array.<string>} List of module names which must be loaded before this module.
           * @description
           * Holds the list of modules which the injector will load before the current module is loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @propertyOf angular.Module
           * @returns {string} Name of the module.
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link AUTO.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link AUTO.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @methodOf angular.Module
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link AUTO.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @methodOf angular.Module
           * @param {string} name animation name
           * @param {Function} animationFactory Factory function for creating new instance of an animation.
           * @description
           *
           * Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate}
           * alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives.
           *

           * module.animation('animation-name', function($inject1, $inject2) {
           *   return {
           *     //this gets called in preparation to setup an animation
           *     setup : function(element) { ... },
           *
           *     //this gets called once the animation is run
           *     start : function(element, done, memo) { ... }
           *   }
           * })
           *

           *
           * See {@link ng.$animationProvider#register $animationProvider.register()} and
           * {@link ng.directive:ngAnimate ngAnimate} for more information.
           */
          animation: invokeLater('$animationProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @methodOf angular.Module
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @methodOf angular.Module
           * @param {string} name Controller name.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @methodOf angular.Module
           * @param {string} name directive name
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @methodOf angular.Module
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @methodOf angular.Module
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          }
        }
      });
    };
  });

}
<commit_msg>translate(api:loader.js):Добавил перевод<commit_after>'use strict';

/**
 * @ngdoc interface
 * @name angular.Module
 * @description
 *
 * Интерфейс для настройки {@link angular.module модулей} Angular.
 */

function setupModuleLoader(window) {

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  return ensure(ensure(window, 'angular', Object), 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @description
     *
     * `Angular.module` является глобальным местом для создания и регистрации angular-модулей. Все модули
     * (из ядра Angular или сторонние), которые должны быть доступны для приложений должны быть зарегистрированы
     * с использованием этого механизма.
     *
     * # Модуль
     *
     * Модуль представляет собой сочетание услуг, директив, фильтров и информацию о конфигурации. Модуль
     * используется для настройки {@link AUTO.$injector $injector}.
     *
     *

     * // Создание нового модуля
     * var myModule = angular.module('myModule', []);
     *
     * // регистрация нового сервиса
     * myModule.value('appName', 'MyCoolApp');
     *
     * // настройка существующих сервисов внутри блоков инициализации.
     * myModule.config(function($locationProvider) {
     *   // настройка существующих провайдеров
     *   $locationProvider.hashPrefix('!');
     * });
     *

     *
     * Затем можно создать инжектором и загрузить модули следующим образом:
     *
     *

     * var injector = angular.injector(['ng', 'MyModule'])
     *

     *
     * Однако более вероятно, что вы будете просто использовать
     * {@link ng.directive:ngApp ngApp} или
     * {@link angular.bootstrap} для облегчения процесса.
     *
     * @param {!string} name Имя модуля для создания или восстановления.
     * @param {Array.<string>=} requires Если задано, то новый модуль создается. Если не задано, то модуль
     *        будет восстановлен в дальнейшей конфигурации.
     * @param {Function} configFn Не обязательная функция настройки для модуля. Такая как
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} новый модуль с {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw Error('No module: ' + name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @propertyOf angular.Module
           * @returns {Array.<string>} Список всех модулей, которые инжектор будет загружать перед загрузкой текущего модуля.
           * @description
           * Список имен модулей, которые должны быть загружены перед текущим модулем.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @propertyOf angular.Module
           * @returns {string} Имя модуля
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @methodOf angular.Module
           * @param {string} name Имя сервиса
           * @param {Function} providerType Конструктор для создания нового экземпляра сервиса.
           * @description
           * См. {@link AUTO.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @methodOf angular.Module
           * @param {string} name Имя сервиса
           * @param {Function} providerFunction Конструктор для создания нового экземпляра сервиса.
           * @description
           * See {@link AUTO.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @methodOf angular.Module
           * @param {string} name Имя сервиса
           * @param {Function} constructor Конструктор, экземпляр которого будет создан
           * @description
           * См. {@link AUTO.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @methodOf angular.Module
           * @param {string} name Имя сервиса
           * @param {*} object Экземпляр объекта сервиса
           * @description
           * См. {@link AUTO.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @methodOf angular.Module
           * @param {string} name Имя константы
           * @param {*} object Значение константы.
           * @description
           * Так как константы являются фиксированными значениями, они устанавливаются перед выполнением
           * других методов. См. {@link AUTO.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @methodOf angular.Module
           * @param {string} name Имя анимации
           * @param {Function} animationFactory Фабричная функция для создания нового экземпляра анимации.
           * @description
           *
           * Определяет привязку анимации, которая в дальнейшем может использоваться с
           * {@link ng.directive:ngAnimate ngAnimate} наряду с обычными
           * {@link ng.directive:ngAnimate#Description ng директивами}, а также пользовательскими директивами.
           *
           *

           * module.animation('animation-name', function($inject1, $inject2) {
           *   return {
           *     //вызывается во время подготовки к запуску анимации
           *     setup : function(element) { ... },
           *
           *     //вызывается один раз во время выполнения анимации
           *     start : function(element, done, memo) { ... }
           *   }
           * })
           *

           *
           * См. {@link ng.$animationProvider#register $animationProvider.register()} и
           * {@link ng.directive:ngAnimate ngAnimate} для большей информации.
           */
          animation: invokeLater('$animationProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @methodOf angular.Module
           * @param {string} name Имя фильтра.
           * @param {Function} filterFactory Фабричная функция для создания нового экземпляра фильтра.
           * @description
           * См. {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @methodOf angular.Module
           * @param {string} name Имя контроллера.
           * @param {Function} constructor Конструктор контроллера.
           * @description
           * См.{@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @methodOf angular.Module
           * @param {string} name Имя директивы.
           * @param {Function} directiveFactory Фабричная функция для создания нового экземпляра директивы.
           * @description
           * См. {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @methodOf angular.Module
           * @param {Function} configFn Эта функция выполняется во время загрузки модуля. Обычно используется
           *    для конфигурации сервиса.
           * @description
           * Используйте этот метод для регистрации работы, которую нужно сделать во время загрузки модулю.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @methodOf angular.Module
           * @param {Function} initializationFn Эта функция выполнится после создания инжектора. Используется
           *    для инициализации приложения.
           * @description
           * Используйте этот метод для регистрации работы, которую нужно сделать когда инжектор загрузит все модули.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          }
        }
      });
    };
  });

}
<|endoftext|>


<commit_before>define([
    'js-utils/js/base-page',
    'find/app/model/entity-collection',
    'find/app/model/documents-collection',
    'find/app/router',
    'find/app/vent',
    'text!find/templates/app/page/find-search.html',
    'text!find/templates/app/page/results-container.html',
    'text!find/templates/app/page/suggestions-container.html',
    'text!find/templates/app/page/loading-spinner.html',
    'text!find/templates/app/page/colorbox-controls.html',
    'colorbox'
], function(BasePage, EntityCollection, DocumentsCollection, router, vent, template, resultsTemplate,
            suggestionsTemplate, loadingSpinnerTemplate, colorboxControlsTemplate) {

    return BasePage.extend({

        template: _.template(template),
        resultsTemplate: _.template(resultsTemplate),
        suggestionsTemplate: _.template(suggestionsTemplate),

        events: {
            'keyup .find-input': 'keyupAnimation'
        },

        initialize: function() {
            this.entityCollection = new EntityCollection();
            this.documentsCollection = new DocumentsCollection();

            this.searchRequest = _.debounce(_.bind(this.searchRequest, this), 500);

            router.on('route:search', function(text) {
                this.entityCollection.reset();
                this.documentsCollection.set([]);

                if (text) {
                    this.$('.find-input').val(text); //when clicking one of the suggested search links
                    this.keyupAnimation();
                } else {
                    this.reverseAnimation(); //when clicking the small 'find' logo
                }
            }, this);
        },

        render: function() {
            this.$el.html(this.template());

            this.$('.find-form').submit(function(e){ //preventing input form submit and page reload
                e.preventDefault();
            });

            this.listenTo(this.documentsCollection, 'request', function() {
                if(!this.$('.main-results-container').length) {
                    this.$('.main-results-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'request', function() {
                if(!this.$('.suggestions-content ul').length) {
                   this.$('.suggestions-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'reset', function() {
                this.$('.suggestions-content').empty();

                var clusters = this.entityCollection.groupBy('cluster');

                _.each(clusters, function(entities) {
                    this.$('.suggestions-content').append(this.suggestionsTemplate({
                        entities: entities
                    }));
                }, this);
            });

            this.listenTo(this.documentsCollection, 'add', function(model) {
                var reference = model.get('reference');
                var sourceLink = '...';
                var summary = model.get('summary').split('').slice(0, model.get('summary').lastIndexOf(" ",300)).join('');

                this.$('.main-results-content .loading-spinner').remove();

                var $newResult = $(_.template(resultsTemplate ,{
                    title: model.get('title'),
                    reference: reference,
                    index: model.get('index'),
                    summary: summary
                }));

                this.$('.main-results-content').append($newResult);

                $newResult.find('.result-header').colorbox({
                    iframe: true,
                    width:'70%',
                    height:'70%',
                    href: reference,
                    rel: 'results',
                    current: '{current} of {total}',
                    onLoad: function() {
                       $('#cboxPrevious, #cboxNext').remove(); //removing default colorbox nav buttons
                    }
                });
            });

            this.listenTo(this.documentsCollection, 'remove', function(model) {
                var reference = model.get('reference');

                this.$('[data-reference="' + reference + '"]').remove();
            });
            $('#colorbox').append(_.template(colorboxControlsTemplate));
            $('.nextBtn').on('click', this.handleNextResult);
            $('.prevBtn').on('click', this.handlePrevResult);
        },

        keyupAnimation: function() {
            /*fancy animation*/
            if($.trim(this.$('.find-input').val()).length) { //checking if input doesn't have any spaces or empty
                this.$('.find-logo').slideUp('slow');
                this.$('.find').addClass('animated-container ').removeClass('reverse-animated-container');
                this.$('.form-search').addClass('animated-form ').removeClass('reverse-animated-form');

                this.$('.suggested-links-container.span2, .find-logo-small').show();

                this.searchRequest(this.$('.find-input').val());
            } else {
                this.reverseAnimation();
                vent.navigate('find/find-search', {trigger: false});
                this.$('.main-results-content').empty();
            }
        },

        handlePrevResult: function() {
            $.colorbox.prev();
        },

        handleNextResult: function() {
            $.colorbox.next();
        },

        reverseAnimation: function() {
            /*fancy reverse animation*/
            this.$('.find-logo').slideDown('slow');
            this.$('.find').removeClass('animated-container ').addClass('reverse-animated-container');
            this.$('.form-search').removeClass('animated-form').addClass('reverse-animated-form');

            this.$('.suggested-links-container.span2, .find-logo-small').hide();
            this.$('.find-input').val('');
        },

        searchRequest: function(input) {
            this.documentsCollection.fetch({
                data: {
                    text: input,
                    max_results: 30,
                    summary: 'quick'
                }
            }, this);

            this.entityCollection.fetch({
                data: {
                    text: input
                }
            });

            vent.navigate('find/find-search/' + encodeURIComponent(input), {trigger: false});
        }
    });
});<commit_msg>dotdotdot in the results summary now open colorbox on click<commit_after>define([
    'js-utils/js/base-page',
    'find/app/model/entity-collection',
    'find/app/model/documents-collection',
    'find/app/router',
    'find/app/vent',
    'text!find/templates/app/page/find-search.html',
    'text!find/templates/app/page/results-container.html',
    'text!find/templates/app/page/suggestions-container.html',
    'text!find/templates/app/page/loading-spinner.html',
    'text!find/templates/app/page/colorbox-controls.html',
    'colorbox'
], function(BasePage, EntityCollection, DocumentsCollection, router, vent, template, resultsTemplate,
            suggestionsTemplate, loadingSpinnerTemplate, colorboxControlsTemplate) {

    return BasePage.extend({

        template: _.template(template),
        resultsTemplate: _.template(resultsTemplate),
        suggestionsTemplate: _.template(suggestionsTemplate),

        events: {
            'keyup .find-input': 'keyupAnimation'
        },

        initialize: function() {
            this.entityCollection = new EntityCollection();
            this.documentsCollection = new DocumentsCollection();

            this.searchRequest = _.debounce(_.bind(this.searchRequest, this), 500);

            router.on('route:search', function(text) {
                this.entityCollection.reset();
                this.documentsCollection.set([]);

                if (text) {
                    this.$('.find-input').val(text); //when clicking one of the suggested search links
                    this.keyupAnimation();
                } else {
                    this.reverseAnimation(); //when clicking the small 'find' logo
                }
            }, this);
        },

        render: function() {
            this.$el.html(this.template());

            this.$('.find-form').submit(function(e){ //preventing input form submit and page reload
                e.preventDefault();
            });

            this.listenTo(this.documentsCollection, 'request', function() {
                if(!this.$('.main-results-container').length) {
                    this.$('.main-results-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'request', function() {
                if(!this.$('.suggestions-content ul').length) {
                   this.$('.suggestions-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'reset', function() {
                this.$('.suggestions-content').empty();

                var clusters = this.entityCollection.groupBy('cluster');

                _.each(clusters, function(entities) {
                    this.$('.suggestions-content').append(this.suggestionsTemplate({
                        entities: entities
                    }));
                }, this);
            });

            this.listenTo(this.documentsCollection, 'add', function(model) {
                var reference = model.get('reference');
                var summary = model.get('summary').split('').slice(0, model.get('summary').lastIndexOf(" ",300)).join('');

                this.$('.main-results-content .loading-spinner').remove();

                var $newResult = $(_.template(resultsTemplate ,{
                    title: model.get('title'),
                    reference: reference,
                    index: model.get('index'),
                    summary: summary
                }));

                this.$('.main-results-content').append($newResult);

                $newResult.find('.result-header, .result-summary a').colorbox({
                    iframe: true,
                    width:'70%',
                    height:'70%',
                    href: reference,
                    rel: 'results',
                    current: '{current} of {total}',
                    onLoad: function() {
                       $('#cboxPrevious, #cboxNext').remove(); //removing default colorbox nav buttons
                    }
                });
            });

            this.listenTo(this.documentsCollection, 'remove', function(model) {
                var reference = model.get('reference');

                this.$('[data-reference="' + reference + '"]').remove();
            });
            $('#colorbox').append(_.template(colorboxControlsTemplate));
            $('.nextBtn').on('click', this.handleNextResult);
            $('.prevBtn').on('click', this.handlePrevResult);
        },

        keyupAnimation: function() {
            /*fancy animation*/
            if($.trim(this.$('.find-input').val()).length) { //checking if input doesn't have any spaces or empty
                this.$('.find-logo').slideUp('slow');
                this.$('.find').addClass('animated-container ').removeClass('reverse-animated-container');
                this.$('.form-search').addClass('animated-form ').removeClass('reverse-animated-form');

                this.$('.suggested-links-container.span2, .find-logo-small').show();

                this.searchRequest(this.$('.find-input').val());
            } else {
                this.reverseAnimation();
                vent.navigate('find/find-search', {trigger: false});
                this.$('.main-results-content').empty();
            }
        },

        handlePrevResult: function() {
            $.colorbox.prev();
        },

        handleNextResult: function() {
            $.colorbox.next();
        },

        reverseAnimation: function() {
            /*fancy reverse animation*/
            this.$('.find-logo').slideDown('slow');
            this.$('.find').removeClass('animated-container ').addClass('reverse-animated-container');
            this.$('.form-search').removeClass('animated-form').addClass('reverse-animated-form');

            this.$('.suggested-links-container.span2, .find-logo-small').hide();
            this.$('.find-input').val('');
        },

        searchRequest: function(input) {
            this.documentsCollection.fetch({
                data: {
                    text: input,
                    max_results: 30,
                    summary: 'quick'
                }
            }, this);

            this.entityCollection.fetch({
                data: {
                    text: input
                }
            });

            vent.navigate('find/find-search/' + encodeURIComponent(input), {trigger: false});
        }
    });
});<|endoftext|>


<commit_before>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-04-10
 * @author Liang <liang@maichong.it>
 */

'use strict';

const EventEmitter = require('events');
const Segment = require('./segment');
const Packet = require('./packet');
const CMD = require('./cmd');

class Stream extends EventEmitter {
  constructor(id, connection) {
    super();
    this.id = id;
    this.connection = connection;
    this.sentMaxSegmentId = 0; //发送方,发送的最大Segment ID
    this.successMaxSegmentId = 0; //发送方,确认发送成功的最大Segment ID
    this.receivedMaxSegmentId = 0; //接收方,已经收到的最大Segment ID
    this.confirmedMaxSegmentId = 0; //接收方,已经确认的最大Segment ID
    this.received = {}; // 接收的 Segment 缓冲
    this.receivedLength = 0;
    this.confirmTimer = 0;//确认Timer
    this.lastAlive = Date.now();
    this.sent = {};//发送端,已经发送,待确认的Segment
    this.sentLength = 0;
    this.bytesRead = 0;
    this.bytesWritten = 0;
    this.remoteAddress = connection.remoteAddress;
    this.remotePort = connection.remotePort;
    this._writeQueue = [];
    this.writeTimer = 0;
    this.resentPacketCount = 0;

    this.aliveTimer = setInterval(() => {
      let now = Date.now();
      if (now - this.lastAlive > 300000) {
        //5分钟不活跃
        this.close();
        return;
      }
      if (this.receivedLength && now - this.lastAlive > 5000) {
        //5秒内不活跃,并且有需要重发的包
        //请求重发
        this._confirm();
        return;
      }
    }, 5000);

    this.resendTimer = setInterval(() => {
      let now = Date.now();
      for (let i in this.sent) {
        let segment = this.sent[i];
        //TODO RTT
        if (now - segment.lastSent > 1000) {
          segment.lastSent = now;
          if (segment.a && !segment.a.onBus) {
            this.connection._send(segment.a);
            segment.ra = 0;
            this.resentPacketCount++;
          }
          if (segment.b && !segment.b.onBus) {
            this.connection._send(segment.b);
            segment.rb = 0;
            this.resentPacketCount++;
          }
          if (segment.c && !segment.c.onBus) {
            this.connection._send(segment.c);
            segment.rc = 0;
            this.resentPacketCount++;
          }
          if (segment.p && !segment.p.onBus) {
            this.connection._send(segment.p);
            this.resentPacketCount++;
            delete segment.p;
          }
        }
      }
      if (!this.confirmTimer && this.receivedLength) {
        this.confirmTimer = setTimeout(() => {
          this.confirmTimer = 0;
          this._confirm();
        }, 1);
      }
    }, 20);
  }

  close() {
    //console.log('stream', this.id, 'close');
    if (this.connection) {
      this.emit('close');
      let buffer = new Buffer(4);
      buffer.writeUInt8(CMD.CLOSE_STREAM);
      this.idBuffer.copy(buffer, 1);
      let packet = new Packet(buffer);
      this.connection.send(packet);
    }
    delete this._idBuffer;
    delete this.received;
    delete this.sent;
    delete this.connection;
    delete this._writeQueue;
    if (this.confirmTimer) {
      clearTimeout(this.confirmTimer);
    }
    clearInterval(this.aliveTimer);
    clearInterval(this.resendTimer);
  }

  get idBuffer() {
    if (!this._idBuffer) {
      this._idBuffer = Stream.idToBuffer(this.id);
    }
    return this._idBuffer;
  }

  static idToBuffer(id) {
    let tmp = new Buffer(4);
    let buffer = new Buffer(3);
    tmp.writeInt32LE(id, 0);
    tmp.copy(buffer, 0, 0, 3);
    return buffer;
  }

  static bufferToId(buffer) {
    let tmp = new Buffer(4);
    tmp.fill(0, 3);
    buffer.copy(tmp);
    return tmp.readInt32LE(0);
  }

  /**
   * @param data
   * @param [encoding]
   * @param [callback]
   */
  write(data, encoding, callback) {
    if (!data || !data.length) {
      return;
    }
    if (typeof data === 'string') {
      data = new Buffer(data, encoding);
    }

    //如果一次写入的数据大于单个包最大数据
    //拆开写入多次
    if (data.length > 4350) {
      for (let start = 0; start < data.length; start += 4350) {
        let end = start + 4350;
        if (end > data.length) {
          end = data.length;
        }
        this._writeQueue.push(data.slice(start, end));
      }
    } else {
      this.bytesWritten += data.length;
    }
    if (!this.writeTimer) {
      this._write();
    }
  }

  _write() {
    this.writeTimer = 0;
    if (!this._writeQueue.length) {
      return;
    }
    if (this.sentLength > 1000) {
      this.writeTimer = setTimeout(() => this._write(), 20);
      return;
    }
    let data = this._writeQueue.shift();
    if (!data) {
      return;
    }
    this.sentMaxSegmentId++;
    let segment = new Segment(this.sentMaxSegmentId, this, data);
    segment.pack();
    segment.lastSent = Date.now();
    this.connection.send(segment.a);
    this.connection.send(segment.b);
    this.connection.send(segment.c);
    this.connection.send(segment.p);
    this.sent[segment.id] = segment;
    this.sentLength++;
    if (this.sentLength < 500) {
      this._write();
    } else {
      this.writeTimer = setTimeout(() => this._write(), 1);
    }
  }

  /**
   * 当收到Packet
   * @param packet
   */
  receive(packet) {
    let now = this.lastAlive = Date.now();
    if (packet.cmd === CMD.CONFIRM) {
      let segmentId = packet.segmentId;
      for (let i = this.successMaxSegmentId + 1; i <= packet.segmentId; i++) {
        if (this.sent[i]) {
          this.sentLength--;
          delete this.sent[i];
          //console.log('receive.remove', i);
        }
      }
      //console.log('confirm', segmentId - this.successMaxSegmentId);
      this.successMaxSegmentId = segmentId;

      //SACK
      let buffer = packet.buffer;
      let index = 8;
      let lastSegmentId = segmentId;
      while (buffer.length > index) {
        let offset = buffer.readUInt8(index);
        if (!offset) {
          throw new Error('offset ' + offset);
        }
        let code = buffer.readUInt8(index + 1);
        index += 2;
        let id = segmentId + offset;
        let segment = this.sent[id];
        if (!segment) {
          console.error('error , can not resend ', id);
          continue;
        }
        while (id - lastSegmentId > 1) {
          lastSegmentId++;
          //中间有一些已经接收到了
          if (this.sent[lastSegmentId]) {
            delete this.sent[lastSegmentId];
            this.sentLength--;
            //console.log('remove', lastSegmentId);
          }
          //console.log(lastSegmentId, id);
        }
        lastSegmentId = id;

        //console.log('resend', id, 'by offset ', offset, 'to', segmentId);

        if (segment.a && code % CMD.DATA_A === 0) {
          //重发A
          segment.ra++;
          if (segment.ra > 3) {
            this.connection._send(segment.a);
            segment.ra = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.ra:%s', id, segment.ra);
        } else {
          //已收到
          delete segment.a;
        }
        if (segment.b && code % CMD.DATA_B === 0) {
          //重发B
          segment.rb++;
          if (segment.rb > 3) {
            this.connection._send(segment.b);
            segment.rb = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.rb:%s', id, segment.rb);
        } else {
          //已收到
          delete segment.b;
        }
        if (segment.c && code % CMD.DATA_C === 0) {
          //重发A
          segment.rc++;
          if (segment.rc > 3) {
            this.connection._send(segment.c);
            segment.rc = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.rc:%s', id, segment.rc);
        } else {
          //已收到
          delete segment.c;
        }
        if (segment.p && code % CMD.DATA_RESEND_P === 0) {
          //重发P
          segment.rp++;
          if (segment.rp > 3) {
            this.connection._send(segment.p);
            segment.rp = 0;
            segment.lastSent = now;
            delete segment.p;
            this.resentPacketCount++;
          }
          //console.log('%s.rp:%s', id, segment.rp);
        } else {
          //已收到
          delete segment.p;
        }
      }
    }
  }

  /**
   * 当收到数据Packet
   * @param packet
   */
  receiveData(packet) {
    this.lastAlive = Date.now();
    let segmentId = packet.segmentId;
    if (segmentId < this.confirmedMaxSegmentId) {
      //已经确认,重复接收
      return;
    }

    if (segmentId - this.confirmedMaxSegmentId > 5000) {
      //segmentId太大,不接受
      return;
    }

    let segment = this.received[segmentId];
    if (!segment) {
      segment = this.received[segmentId] = new Segment(segmentId, this, null);
    }

    let cmd = packet.cmd;
    if (!segment.a && cmd % CMD.DATA_A === 0) {
      //a
      segment.a = packet;
      segment.count++;
    } else if (!segment.b && cmd % CMD.DATA_B === 0) {
      //b
      segment.b = packet;
      segment.count++;
    } else if (!segment.c && cmd % CMD.DATA_C === 0) {
      //c
      segment.c = packet;
      segment.count++;
    } else if (!segment.p && cmd % CMD.DATA_P === 0) {
      //p
      segment.p = packet;
      segment.count++;
    } else {
      //没有能够识别包,或重复接收
      if (!segment.count) {
        delete this.received[segmentId];
      }
      return;
    }

    if (segmentId > this.receivedMaxSegmentId) {
      this.receivedMaxSegmentId = segmentId;
    }
    this.receivedLength = this.receivedMaxSegmentId - this.confirmedMaxSegmentId;

    if (segment.count >= 3) {
      this._readData();
    }
  }

  _readData() {
    let i = this.confirmedMaxSegmentId;
    let buffers = [];
    while (true) {
      let segment = this.received[i + 1];
      if (!segment || segment.count < 3) {
        break;
      }
      try {
        let buffer = segment.unpack();
        buffers.push(buffer);
        i++;
        delete this.received[i];
      } catch (e) {
        break;
      }
    }
    if (!buffers.length) {
      return;
    }
    this.confirmedMaxSegmentId = i;
    this.receivedLength = this.receivedMaxSegmentId - this.confirmedMaxSegmentId;
    let data;
    if (buffers.length === 1) {
      data = buffers[0];
    } else {
      data = Buffer.concat(buffers);
    }
    this.bytesRead += data.length;
    setImmediate(() => {
      this.emit('data', data);
    });
    if (!this.confirmTimer) {
      this.confirmTimer = setTimeout(() => {
        //发送确认包
        this.confirmTimer = 0;
        this._confirm();
      }, 20);
    }
  }

  _confirm() {
    //发送确认包
    let buffer = new Buffer(8);
    buffer.writeUInt8(CMD.CONFIRM, 0);
    this.idBuffer.copy(buffer, 1);
    buffer.writeUInt32LE(this.confirmedMaxSegmentId, 4);

    let buffers = [buffer];
    if (this.receivedMaxSegmentId > this.confirmedMaxSegmentId) {
      //有空白
      for (let offset = 1; offset < 250 && this.confirmedMaxSegmentId + offset <= this.receivedMaxSegmentId; offset++) {
        let i = this.confirmedMaxSegmentId + offset;
        let segment = this.received[i];
        if (segment && segment.count >= 3) {
          continue;
        }
        let sack = new Buffer(2);
        sack.writeUInt8(offset);
        let code = 1;
        if (!segment) {
          code = CMD.DATA_RESEND_ALL;
        } else {
          if (!segment.a) {
            code *= CMD.DATA_A;
          }
          if (!segment.b) {
            code *= CMD.DATA_B;
          }
          if (!segment.c) {
            code *= CMD.DATA_C;
          }
          if (!segment.p) {
            code *= CMD.DATA_RESEND_P;
          }
        }
        sack.writeUInt8(code, 1);
        buffers.push(sack);
      }
    }

    if (buffers.length > 1) {
      buffer = Buffer.concat(buffers);
    }
    let packet = new Packet(buffer);
    this.connection._send(packet);
  }
}

Stream.maxId = 16777216;

module.exports = Stream;
<commit_msg>bytesWritten<commit_after>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-04-10
 * @author Liang <liang@maichong.it>
 */

'use strict';

const EventEmitter = require('events');
const Segment = require('./segment');
const Packet = require('./packet');
const CMD = require('./cmd');

class Stream extends EventEmitter {
  constructor(id, connection) {
    super();
    this.id = id;
    this.connection = connection;
    this.sentMaxSegmentId = 0; //发送方,发送的最大Segment ID
    this.successMaxSegmentId = 0; //发送方,确认发送成功的最大Segment ID
    this.receivedMaxSegmentId = 0; //接收方,已经收到的最大Segment ID
    this.confirmedMaxSegmentId = 0; //接收方,已经确认的最大Segment ID
    this.received = {}; // 接收的 Segment 缓冲
    this.receivedLength = 0;
    this.confirmTimer = 0;//确认Timer
    this.lastAlive = Date.now();
    this.sent = {};//发送端,已经发送,待确认的Segment
    this.sentLength = 0;
    this.bytesRead = 0;
    this.bytesWritten = 0;
    this.remoteAddress = connection.remoteAddress;
    this.remotePort = connection.remotePort;
    this._writeQueue = [];
    this.writeTimer = 0;
    this.resentPacketCount = 0;

    this.aliveTimer = setInterval(() => {
      let now = Date.now();
      if (now - this.lastAlive > 300000) {
        //5分钟不活跃
        this.close();
        return;
      }
      if (this.receivedLength && now - this.lastAlive > 5000) {
        //5秒内不活跃,并且有需要重发的包
        //请求重发
        this._confirm();
        return;
      }
    }, 5000);

    this.resendTimer = setInterval(() => {
      let now = Date.now();
      for (let i in this.sent) {
        let segment = this.sent[i];
        //TODO RTT
        if (now - segment.lastSent > 1000) {
          segment.lastSent = now;
          if (segment.a && !segment.a.onBus) {
            this.connection._send(segment.a);
            segment.ra = 0;
            this.resentPacketCount++;
          }
          if (segment.b && !segment.b.onBus) {
            this.connection._send(segment.b);
            segment.rb = 0;
            this.resentPacketCount++;
          }
          if (segment.c && !segment.c.onBus) {
            this.connection._send(segment.c);
            segment.rc = 0;
            this.resentPacketCount++;
          }
          if (segment.p && !segment.p.onBus) {
            this.connection._send(segment.p);
            this.resentPacketCount++;
            delete segment.p;
          }
        }
      }
      if (!this.confirmTimer && this.receivedLength) {
        this.confirmTimer = setTimeout(() => {
          this.confirmTimer = 0;
          this._confirm();
        }, 1);
      }
    }, 20);
  }

  close() {
    //console.log('stream', this.id, 'close');
    if (this.connection) {
      this.emit('close');
      let buffer = new Buffer(4);
      buffer.writeUInt8(CMD.CLOSE_STREAM);
      this.idBuffer.copy(buffer, 1);
      let packet = new Packet(buffer);
      this.connection.send(packet);
    }
    delete this._idBuffer;
    delete this.received;
    delete this.sent;
    delete this.connection;
    delete this._writeQueue;
    if (this.confirmTimer) {
      clearTimeout(this.confirmTimer);
    }
    clearInterval(this.aliveTimer);
    clearInterval(this.resendTimer);
  }

  get idBuffer() {
    if (!this._idBuffer) {
      this._idBuffer = Stream.idToBuffer(this.id);
    }
    return this._idBuffer;
  }

  static idToBuffer(id) {
    let tmp = new Buffer(4);
    let buffer = new Buffer(3);
    tmp.writeInt32LE(id, 0);
    tmp.copy(buffer, 0, 0, 3);
    return buffer;
  }

  static bufferToId(buffer) {
    let tmp = new Buffer(4);
    tmp.fill(0, 3);
    buffer.copy(tmp);
    return tmp.readInt32LE(0);
  }

  /**
   * @param data
   * @param [encoding]
   * @param [callback]
   */
  write(data, encoding, callback) {
    if (!data || !data.length) {
      return;
    }
    if (typeof data === 'string') {
      data = new Buffer(data, encoding);
    }

    //如果一次写入的数据大于单个包最大数据
    //拆开写入多次
    if (data.length > 4350) {
      for (let start = 0; start < data.length; start += 4350) {
        let end = start + 4350;
        if (end > data.length) {
          end = data.length;
        }
        this._writeQueue.push(data.slice(start, end));
      }
    }
    this.bytesWritten += data.length;
    if (!this.writeTimer) {
      this._write();
    }
  }

  _write() {
    this.writeTimer = 0;
    if (!this._writeQueue.length) {
      return;
    }
    if (this.sentLength > 1000) {
      this.writeTimer = setTimeout(() => this._write(), 20);
      return;
    }
    let data = this._writeQueue.shift();
    if (!data) {
      return;
    }
    this.sentMaxSegmentId++;
    let segment = new Segment(this.sentMaxSegmentId, this, data);
    segment.pack();
    segment.lastSent = Date.now();
    this.connection.send(segment.a);
    this.connection.send(segment.b);
    this.connection.send(segment.c);
    this.connection.send(segment.p);
    this.sent[segment.id] = segment;
    this.sentLength++;
    if (this.sentLength < 500) {
      this._write();
    } else {
      this.writeTimer = setTimeout(() => this._write(), 1);
    }
  }

  /**
   * 当收到Packet
   * @param packet
   */
  receive(packet) {
    let now = this.lastAlive = Date.now();
    if (packet.cmd === CMD.CONFIRM) {
      let segmentId = packet.segmentId;
      for (let i = this.successMaxSegmentId + 1; i <= packet.segmentId; i++) {
        if (this.sent[i]) {
          this.sentLength--;
          delete this.sent[i];
          //console.log('receive.remove', i);
        }
      }
      //console.log('confirm', segmentId - this.successMaxSegmentId);
      this.successMaxSegmentId = segmentId;

      //SACK
      let buffer = packet.buffer;
      let index = 8;
      let lastSegmentId = segmentId;
      while (buffer.length > index) {
        let offset = buffer.readUInt8(index);
        if (!offset) {
          throw new Error('offset ' + offset);
        }
        let code = buffer.readUInt8(index + 1);
        index += 2;
        let id = segmentId + offset;
        let segment = this.sent[id];
        if (!segment) {
          console.error('error , can not resend ', id);
          continue;
        }
        while (id - lastSegmentId > 1) {
          lastSegmentId++;
          //中间有一些已经接收到了
          if (this.sent[lastSegmentId]) {
            delete this.sent[lastSegmentId];
            this.sentLength--;
            //console.log('remove', lastSegmentId);
          }
          //console.log(lastSegmentId, id);
        }
        lastSegmentId = id;

        //console.log('resend', id, 'by offset ', offset, 'to', segmentId);

        if (segment.a && code % CMD.DATA_A === 0) {
          //重发A
          segment.ra++;
          if (segment.ra > 3) {
            this.connection._send(segment.a);
            segment.ra = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.ra:%s', id, segment.ra);
        } else {
          //已收到
          delete segment.a;
        }
        if (segment.b && code % CMD.DATA_B === 0) {
          //重发B
          segment.rb++;
          if (segment.rb > 3) {
            this.connection._send(segment.b);
            segment.rb = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.rb:%s', id, segment.rb);
        } else {
          //已收到
          delete segment.b;
        }
        if (segment.c && code % CMD.DATA_C === 0) {
          //重发A
          segment.rc++;
          if (segment.rc > 3) {
            this.connection._send(segment.c);
            segment.rc = 0;
            segment.lastSent = now;
            this.resentPacketCount++;
          }
          //console.log('%s.rc:%s', id, segment.rc);
        } else {
          //已收到
          delete segment.c;
        }
        if (segment.p && code % CMD.DATA_RESEND_P === 0) {
          //重发P
          segment.rp++;
          if (segment.rp > 3) {
            this.connection._send(segment.p);
            segment.rp = 0;
            segment.lastSent = now;
            delete segment.p;
            this.resentPacketCount++;
          }
          //console.log('%s.rp:%s', id, segment.rp);
        } else {
          //已收到
          delete segment.p;
        }
      }
    }
  }

  /**
   * 当收到数据Packet
   * @param packet
   */
  receiveData(packet) {
    this.lastAlive = Date.now();
    let segmentId = packet.segmentId;
    if (segmentId < this.confirmedMaxSegmentId) {
      //已经确认,重复接收
      return;
    }

    if (segmentId - this.confirmedMaxSegmentId > 5000) {
      //segmentId太大,不接受
      return;
    }

    let segment = this.received[segmentId];
    if (!segment) {
      segment = this.received[segmentId] = new Segment(segmentId, this, null);
    }

    let cmd = packet.cmd;
    if (!segment.a && cmd % CMD.DATA_A === 0) {
      //a
      segment.a = packet;
      segment.count++;
    } else if (!segment.b && cmd % CMD.DATA_B === 0) {
      //b
      segment.b = packet;
      segment.count++;
    } else if (!segment.c && cmd % CMD.DATA_C === 0) {
      //c
      segment.c = packet;
      segment.count++;
    } else if (!segment.p && cmd % CMD.DATA_P === 0) {
      //p
      segment.p = packet;
      segment.count++;
    } else {
      //没有能够识别包,或重复接收
      if (!segment.count) {
        delete this.received[segmentId];
      }
      return;
    }

    if (segmentId > this.receivedMaxSegmentId) {
      this.receivedMaxSegmentId = segmentId;
    }
    this.receivedLength = this.receivedMaxSegmentId - this.confirmedMaxSegmentId;

    if (segment.count >= 3) {
      this._readData();
    }
  }

  _readData() {
    let i = this.confirmedMaxSegmentId;
    let buffers = [];
    while (true) {
      let segment = this.received[i + 1];
      if (!segment || segment.count < 3) {
        break;
      }
      try {
        let buffer = segment.unpack();
        buffers.push(buffer);
        i++;
        delete this.received[i];
      } catch (e) {
        break;
      }
    }
    if (!buffers.length) {
      return;
    }
    this.confirmedMaxSegmentId = i;
    this.receivedLength = this.receivedMaxSegmentId - this.confirmedMaxSegmentId;
    let data;
    if (buffers.length === 1) {
      data = buffers[0];
    } else {
      data = Buffer.concat(buffers);
    }
    this.bytesRead += data.length;
    setImmediate(() => {
      this.emit('data', data);
    });
    if (!this.confirmTimer) {
      this.confirmTimer = setTimeout(() => {
        //发送确认包
        this.confirmTimer = 0;
        this._confirm();
      }, 20);
    }
  }

  _confirm() {
    //发送确认包
    let buffer = new Buffer(8);
    buffer.writeUInt8(CMD.CONFIRM, 0);
    this.idBuffer.copy(buffer, 1);
    buffer.writeUInt32LE(this.confirmedMaxSegmentId, 4);

    let buffers = [buffer];
    if (this.receivedMaxSegmentId > this.confirmedMaxSegmentId) {
      //有空白
      for (let offset = 1; offset < 250 && this.confirmedMaxSegmentId + offset <= this.receivedMaxSegmentId; offset++) {
        let i = this.confirmedMaxSegmentId + offset;
        let segment = this.received[i];
        if (segment && segment.count >= 3) {
          continue;
        }
        let sack = new Buffer(2);
        sack.writeUInt8(offset);
        let code = 1;
        if (!segment) {
          code = CMD.DATA_RESEND_ALL;
        } else {
          if (!segment.a) {
            code *= CMD.DATA_A;
          }
          if (!segment.b) {
            code *= CMD.DATA_B;
          }
          if (!segment.c) {
            code *= CMD.DATA_C;
          }
          if (!segment.p) {
            code *= CMD.DATA_RESEND_P;
          }
        }
        sack.writeUInt8(code, 1);
        buffers.push(sack);
      }
    }

    if (buffers.length > 1) {
      buffer = Buffer.concat(buffers);
    }
    let packet = new Packet(buffer);
    this.connection._send(packet);
  }
}

Stream.maxId = 16777216;

module.exports = Stream;
<|endoftext|>


<commit_before>(function (angular, sprintf, vsprintf, moment) {
    'use strict';
    angular.module('logger', []).
    provider('logEnhancer', function () {
        this.loggingPattern = '%s - %s: ';

        this.$get = function () {
            var loggingPattern = this.loggingPattern;
            return {
                enhanceAngularLog: function ($log) {
                    $log.enabledContexts = [];

                    function enhanceLogging(loggingFunc, context, loggingPattern) {
                        return function () {
                            var contextEnabled = $log.enabledContexts[context];
                            if (contextEnabled === undefined || contextEnabled) {
                                var modifiedArguments = [].slice.call(arguments);
                                var output = [];
                                if (sprintf) {
                                    output.push(sprintf(loggingPattern, moment().format("dddd h:mm:ss a"), context));
                                    if (modifiedArguments.length > 1) { //format, arguments
                                        output.push(vsprintf(modifiedArguments[0], modifiedArguments.slice(1)));
                                    } else {
                                        output.push(modifiedArguments[0]);
                                    }
                                }
                                loggingFunc.apply(null, output);
                            }
                        };
                    }

                    $log.getInstance = function (context) {
                        return {
                            log: enhanceLogging($log.log, context, loggingPattern),
                            info: enhanceLogging($log.info, context, loggingPattern),
                            warn: enhanceLogging($log.warn, context, loggingPattern),
                            debug: enhanceLogging($log.debug, context, loggingPattern),
                            error: enhanceLogging($log.error, context, loggingPattern),
                            enableLogging: function (enable) {
                                $log.enabledContexts[context] = enable;
                            }
                        };
                    };
                }
            };
        };
    }).
    config(['logEnhancerProvider',
        function (logEnhancerProvider) {
            logEnhancerProvider.loggingPattern = '%s::[%s]> ';
        }
    ]).
    run(['$log', 'logEnhancer',
        function ($log, logEnhancer) {
            if (!sprintf) {
                $log.warn("sprintf.js not found. https://github.com/alexei/sprintf.js");
            } else {
                $log.debug("sprintf.js located. ;o)");
            }
            logEnhancer.enhanceAngularLog($log);
        }
    ]);
}());
<commit_msg>jslint errors fixed<commit_after>/*global window*/
(function (angular, sprintf, vsprintf, moment) {
    'use strict';
    angular.module('logger', []).
    provider('logEnhancer', function () {
        this.loggingPattern = '%s - %s: ';

        this.$get = function () {
            var loggingPattern = this.loggingPattern;
            return {
                enhanceAngularLog: function ($log) {
                    $log.enabledContexts = [];

                    function enhanceLogging(loggingFunc, context, loggingPattern) {
                        return function () {
                            var contextEnabled = $log.enabledContexts[context];
                            if (contextEnabled === undefined || contextEnabled) {
                                var modifiedArguments = [].slice.call(arguments);
                                var output = [];
                                if (sprintf) {
                                    output.push(sprintf(loggingPattern, moment().format("dddd h:mm:ss a"), context));
                                    if (modifiedArguments.length > 1) { //format, arguments
                                        output.push(vsprintf(modifiedArguments[0], modifiedArguments.slice(1)));
                                    } else {
                                        output.push(modifiedArguments[0]);
                                    }
                                }
                                loggingFunc.apply(null, output);
                            }
                        };
                    }

                    $log.getInstance = function (context) {
                        return {
                            log: enhanceLogging($log.log, context, loggingPattern),
                            info: enhanceLogging($log.info, context, loggingPattern),
                            warn: enhanceLogging($log.warn, context, loggingPattern),
                            debug: enhanceLogging($log.debug, context, loggingPattern),
                            error: enhanceLogging($log.error, context, loggingPattern),
                            enableLogging: function (enable) {
                                $log.enabledContexts[context] = enable;
                            }
                        };
                    };
                }
            };
        };
    }).
    config(['logEnhancerProvider',
        function (logEnhancerProvider) {
            logEnhancerProvider.loggingPattern = '%s::[%s]> ';
        }
    ]).
    run(['$log', 'logEnhancer',
        function ($log, logEnhancer) {
            if (!sprintf) {
                $log.warn("sprintf.js not found. https://github.com/alexei/sprintf.js");
            } else {
                $log.debug("sprintf.js located. ;o)");
            }
            logEnhancer.enhanceAngularLog($log);
        }
    ]);
}(window.angular, window.sprintf, window.vsprintf, window.moment));
<|endoftext|>


<commit_before>/**
 * 队列
 * @type {Array}
 */
var queue = []

/**
 * 队列备份
 * @type {Array}
 */
var _queue = []

/**
 * 队列类
 */
function Queue(loop) {
    this.loop = (typeof loop == 'undefined') ? false : true
}

/**
 * 入队
 * @param {Function} 排队函数
 */
Queue.prototype.enqueue = function(task) {
    //入队
    queue.push(task);
    // Backup
    this.loop && _queue.push(task);
}

/**
 * 执行队列函数
 * @param {Object} 可为空，在排队函数中流通的data
 * @param {Array} 可为空，替换队列中的排队函数
 */
Queue.prototype.execute = function(data, tasks) {

    /**
     * 如果tasks存在则忽略排队函数
     */
    tasks = tasks || queue;
    var task;

    /**
     * 队列不为空
     */
    if (tasks.length) {
        /**
         * 出队
         */
        task = tasks.shift();
        task(data, this.execute.bind(this, data, tasks));
    } else {

        /**
         * 队列为空，执行完成
         */
        task = null;
        this.tasksAchieved(data);

        // Get backup
        this.loop && (queue = _queue.concat())
    }
}

/**
 * 队列中排队函数执行完成后的回调函数
 * @param  {Function} fn
 * @return {object}   返回队列实例，mock Promise
 */
Queue.prototype.after = function(fn) {
    this.tasksAchieved = fn;
    return this;
}

module.exports = Queue
<commit_msg>queue loop defaultValue to true<commit_after>/**
 * 队列
 * @type {Array}
 */
var queue = []

/**
 * 队列备份
 * @type {Array}
 */
var _queue = []

/**
 * 队列类
 */
function Queue(loop) {
    this.loop = (typeof loop == 'undefined') ? true : loop
}

/**
 * 入队
 * @param {Function} 排队函数
 */
Queue.prototype.enqueue = function(task) {
    //入队
    queue.push(task);
    // Backup
    this.loop && _queue.push(task);
}

/**
 * 执行队列函数
 * @param {Object} 可为空，在排队函数中流通的data
 * @param {Array} 可为空，替换队列中的排队函数
 */
Queue.prototype.execute = function(data, tasks) {

    /**
     * 如果tasks存在则忽略排队函数
     */
    tasks = tasks || queue;
    var task;

    /**
     * 队列不为空
     */
    if (tasks.length) {
        /**
         * 出队
         */
        task = tasks.shift();
        task(data, this.execute.bind(this, data, tasks));
    } else {

        /**
         * 队列为空，执行完成
         */
        task = null;
        this.tasksAchieved(data);

        // Get backup
        this.loop && (queue = _queue.concat())
    }
}

/**
 * 队列中排队函数执行完成后的回调函数
 * @param  {Function} fn
 * @return {object}   返回队列实例，mock Promise
 */
Queue.prototype.after = function(fn) {
    this.tasksAchieved = fn;
    return this;
}

module.exports = Queue
<|endoftext|>


<commit_before>let printit = options => new Logger(options)
if (printit.console == null) { printit.console = global.console }

let colors = {
  blue: ['\x1B[34m', '\x1B[39m'],
  cyan: ['\x1B[36m', '\x1B[39m'],
  green: ['\x1B[32m', '\x1B[39m'],
  magenta: ['\x1B[36m', '\x1B[39m'],
  red: ['\x1B[31m', '\x1B[39m'],
  yellow: ['\x1B[33m', '\x1B[39m']
}

let levelColors = {
  error: colors.red,
  debug: colors.green,
  warn: colors.yellow,
  info: colors.blue
}

class Logger {

  constructor (options) {
    this.options = options
    if (this.options == null) { this.options = {} }
    if (this.options.date && (this.options.dateFormat == null)) {
      this.options.dateFormat = 'YYYY-MM-DD hh:mm:ss:S'
    }
  }

  colorify (text, color) {
    return `${color[0]}${text}${color[1]}`
  }

  stringify (text) {
    if (text instanceof Error && text.stack) {
      text = text.stack
    } else if (text instanceof Object) {
      text = JSON.stringify(text)
    }
    return text
  }

  getFileAndLine () {
    let stacklist = (new Error()).stack.split('\n').slice(4)
    let nodeReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
    let browserReg = /at\s+()(.*):(\d*):(\d*)/gi

    let firstLineStack = stacklist[0]
    let fileAndLineInfos =
            nodeReg.exec(firstLineStack) || browserReg.exec(firstLineStack)

    let filePath = fileAndLineInfos[2].substr(process.cwd().length)
    let line = fileAndLineInfos[3]
    return `.${filePath}:${line} |`
  }

  format (level, texts) {
    if (process.env.DEBUG) { texts.unshift(this.getFileAndLine()) }

    var text = ((() => {
      let result = []
      for (text of Array.from(texts)) {
        result.push(this.stringify(text))
      }
      return result
    })()).join(' ')

    if (this.options.prefix != null) { text = `${this.options.prefix} | ${text}` }

    if (process.env.NODE_ENV !== 'production') {
      level = this.colorify(level, levelColors[level])
    }

    if (level) { text = `${level} - ${text}` }
    if (this.options.date) {
      let date = new Date().format(this.options.dateFormat)
      text = `[${date}] ${text}`
    }
    return text
  }

  info (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      return printit.console.info(this.format('info', texts))
    }
  }

  warn (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      if (this.options.duplicateToStdout) {
        printit.console.info(this.format('warn', texts))
      }
      return printit.console.warn(this.format('warn', texts))
    }
  }

  error (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      if (this.options.duplicateToStdout) {
        printit.console.info(this.format('error', texts))
      }
      return printit.console.error(this.format('error', texts))
    }
  }

  debug (...texts) {
    if (process.env.DEBUG) {
      return printit.console.info(this.format('debug', texts))
    }
  }

  raw (...texts) {
    return printit.console.log(...texts)
  }

  lineBreak (text) {
    return this.raw(Array(80).join('*'))
  }
}

export default printit
<commit_msg>logger: Add options type annotation + typechecking<commit_after>/* @flow weak */

let printit = options => new Logger(options)
if (printit.console == null) { printit.console = global.console }

let colors = {
  blue: ['\x1B[34m', '\x1B[39m'],
  cyan: ['\x1B[36m', '\x1B[39m'],
  green: ['\x1B[32m', '\x1B[39m'],
  magenta: ['\x1B[36m', '\x1B[39m'],
  red: ['\x1B[31m', '\x1B[39m'],
  yellow: ['\x1B[33m', '\x1B[39m']
}

let levelColors = {
  error: colors.red,
  debug: colors.green,
  warn: colors.yellow,
  info: colors.blue
}

class Logger {
  options: Object

  constructor (options) {
    this.options = options
    if (this.options == null) { this.options = {} }
    if (this.options.date && (this.options.dateFormat == null)) {
      this.options.dateFormat = 'YYYY-MM-DD hh:mm:ss:S'
    }
  }

  colorify (text, color) {
    return `${color[0]}${text}${color[1]}`
  }

  stringify (text) {
    if (text instanceof Error && text.stack) {
      text = text.stack
    } else if (text instanceof Object) {
      text = JSON.stringify(text)
    }
    return text
  }

  getFileAndLine () {
    let stacklist = (new Error()).stack.split('\n').slice(4)
    let nodeReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
    let browserReg = /at\s+()(.*):(\d*):(\d*)/gi

    let firstLineStack = stacklist[0]
    let fileAndLineInfos =
            nodeReg.exec(firstLineStack) || browserReg.exec(firstLineStack)

    let filePath = fileAndLineInfos[2].substr(process.cwd().length)
    let line = fileAndLineInfos[3]
    return `.${filePath}:${line} |`
  }

  format (level, texts) {
    if (process.env.DEBUG) { texts.unshift(this.getFileAndLine()) }

    var text = ((() => {
      let result = []
      for (text of Array.from(texts)) {
        result.push(this.stringify(text))
      }
      return result
    })()).join(' ')

    if (this.options.prefix != null) { text = `${this.options.prefix} | ${text}` }

    if (process.env.NODE_ENV !== 'production') {
      level = this.colorify(level, levelColors[level])
    }

    if (level) { text = `${level} - ${text}` }
    if (this.options.date) {
      let date = new Date().format(this.options.dateFormat)
      text = `[${date}] ${text}`
    }
    return text
  }

  info (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      return printit.console.info(this.format('info', texts))
    }
  }

  warn (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      if (this.options.duplicateToStdout) {
        printit.console.info(this.format('warn', texts))
      }
      return printit.console.warn(this.format('warn', texts))
    }
  }

  error (...texts) {
    if (process.env.DEBUG || (process.env.NODE_ENV !== 'test')) {
      if (this.options.duplicateToStdout) {
        printit.console.info(this.format('error', texts))
      }
      return printit.console.error(this.format('error', texts))
    }
  }

  debug (...texts) {
    if (process.env.DEBUG) {
      return printit.console.info(this.format('debug', texts))
    }
  }

  raw (...texts) {
    return printit.console.log(...texts)
  }

  lineBreak (text) {
    return this.raw(Array(80).join('*'))
  }
}

export default printit
<|endoftext|>


<commit_before>var util = require('util'),
    Writable = require('stream').Writable,
    Readable = require('stream').Readable,
    //Buffer = require('buffer'),
    bindexOf = require('buffer-indexof'),
//    {Writable, Readable} = require('stream'),
    //dataType = require('./data'),
    c3ctr        = process.env.c3ctr || 'c3io!',
    c3len        = parseInt(process.env.c3len || 3)

//TODO: do it better.. with c3docker stdin input will be passed to stdout. guess: usage of duplexStream.
var _stdin_ignore = null

function stream(emitter) {
  if ( !emitter )
    throw new TypeError('argument needs to be an EventEmitter')

  this.emitter = emitter
  this._stdout = this._stderr = this._stdin =  null
}

Object.defineProperty(stream.prototype, 'stdin', {
  get: function() {
    if ( this._stdin ) return this._stdin

    this._stdin = Readable()
    this._stdin.setEncoding('utf8')

    var _this = this
    this._stdin._read = function(n) { }
    this._stdin.send = function(buf) {
      this.push(_stdin_ignore = Buffer.concat([
        Buffer.isBuffer(buf) ? buf : new Buffer(buf),
        new Buffer('\r')]))
    }
    return this._stdin
  },
  writeable: false
})
Object.defineProperty(stream.prototype, 'stdout', {
  get: function() {
    if ( this._stdout ) return this._stdout
    this._stdout = Writable()
    this._stdout._write = _write.call(this._stdout, this.emitter)

    this._stdout.on('error', function() {
      console.warn(arguments)
    })
    this._stdout.on('close', function() {
      console.warn(arguments)
    })
    return this._stdout
  }, writeable: false
})
Object.defineProperty(stream.prototype, 'stderr', {
  get: function() {
    if ( this._stderr ) return this._stderr
    this._stderr = Writable()
    this._stderr._isErr = true
    this._stderr._write = _write.call(this._stderr, this.emitter)

    return this._stderr
  }, writeable: false
})

function _write(emitter) {
  this.buffer = new Buffer(0)

  return function(chunk, enc, next) {
    var chunk = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, enc),
        newLineIndex = null

    this.buffer = Buffer.concat([this.buffer, chunk])
    while ( (newLineIndex = bindexOf(this.buffer, new Buffer('\n'))) !== -1 ) {//console.log('foo',chunk.toString('utf8'),'bar', newLineIndex) // \033[0G
      var line = this.buffer.slice(0, newLineIndex),
          data = null
      this.buffer = this.buffer.slice(newLineIndex + 1)

      //see latter todo
      if ( _stdin_ignore && line.equals(_stdin_ignore) ) { _stdin_ignore = null; continue }

      line = line.toString('utf8').trim()
      // skip empty lines
      if ( line.length === 0 ) continue

      try {
        if ( line.slice(0, c3ctr.length) == c3ctr )
          data = emitter.c3io.r2d2[line.slice(c3ctr.length, c3ctr.length + c3len)](line.slice(c3ctr.length + c3len))
      }
      catch(e) { console.warn("[missing c3io.r2d2 type]", line.slice(0, c3ctr.length + c3len), e) }

      if ( data === null )
        data = emitter.c3io.r2d2.default(line)

      data.stderr = this._isErr ? true : false
      emitter.emit('message', data)
    }
    next()
  }
}

module.exports = exports = stream
<commit_msg>clean<commit_after>var util = require('util'),
    Writable = require('stream').Writable,
    Readable = require('stream').Readable,
    //Buffer = require('buffer'),
    bindexOf = require('buffer-indexof'),
//    {Writable, Readable} = require('stream'),
    //dataType = require('./data'),
    c3ctr        = process.env.c3ctr || 'c3io!',
    c3len        = parseInt(process.env.c3len || 3)

//TODO: do it better.. with c3docker stdin input will be passed to stdout. guess: usage of duplexStream.
var _stdin_ignore = null

function stream(emitter) {
  if ( !emitter )
    throw new TypeError('argument needs to be an EventEmitter')

  this.emitter = emitter
  this._stdout = this._stderr = this._stdin =  null
}

Object.defineProperty(stream.prototype, 'stdin', {
  get: function() {
    if ( this._stdin ) return this._stdin

    this._stdin = Readable()
    this._stdin.setEncoding('utf8')

    var _this = this
    this._stdin._read = function(n) { }
    this._stdin.send = function(buf) {
      this.push(_stdin_ignore = Buffer.concat([
        Buffer.isBuffer(buf) ? buf : new Buffer(buf),
        new Buffer('\r')]))
    }
    return this._stdin
  },
  writeable: false
})
Object.defineProperty(stream.prototype, 'stdout', {
  get: function() {
    if ( this._stdout ) return this._stdout
    this._stdout = Writable()
    this._stdout._write = _write.call(this._stdout, this.emitter)

    this._stdout.on('error', function() {
      console.warn(arguments)
    })
    this._stdout.on('close', function() {
      console.warn(arguments)
    })
    return this._stdout
  }, writeable: false
})
Object.defineProperty(stream.prototype, 'stderr', {
  get: function() {
    if ( this._stderr ) return this._stderr
    this._stderr = Writable()
    this._stderr._isErr = true
    this._stderr._write = _write.call(this._stderr, this.emitter)

    return this._stderr
  }, writeable: false
})

function _write(emitter) {
  this.buffer = new Buffer(0)

  return function(chunk, enc, next) {
    var chunk = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, enc),
        newLineIndex = null

    this.buffer = Buffer.concat([this.buffer, chunk])
    while ( (newLineIndex = bindexOf(this.buffer, new Buffer('\n'))) !== -1 ) {//console.log('foo',chunk.toString('utf8'),'bar', newLineIndex) // \033[0G
      var line = this.buffer.slice(0, newLineIndex),
          data = null
      this.buffer = this.buffer.slice(newLineIndex + 1)

      //see latter todo
      if ( _stdin_ignore && line.equals(_stdin_ignore) ) { _stdin_ignore = null; continue }

      line = line.toString('utf8').trim()
      // skip empty lines
      if ( line.length === 0 ) continue

      try {
        if ( line.slice(0, c3ctr.length) == c3ctr )
          data = emitter.c3io.r2d2[line.slice(c3ctr.length, c3ctr.length + c3len)].call(emitter, line.slice(c3ctr.length + c3len))
      }
      catch(e) { console.warn("[missing c3io.r2d2 type]", line.slice(0, c3ctr.length + c3len), e) }

      if ( data === null )
        data = emitter.c3io.r2d2.default.call(emitter, line)

      // nothing to pass on
      if ( ! data ) return next();

      data.stderr = this._isErr ? true : false
      emitter.emit('message', data)
    }
    next()
  }
}

module.exports = exports = stream
<|endoftext|>


<commit_before>!function (context, doc) {

  var c, i, j, k, l, m, o, p, r, v,
      el, node, found, classes, item, items, token,
      html = doc.documentElement,
      id = /#([\w\-]+)/,
      clas = /\.[\w\-]+/g,
      idOnly = /^#([\w\-]+$)/,
      classOnly = /^\.([\w\-]+)$/,
      tagOnly = /^([\w\-]+)$/,
      tagAndOrClass = /^([\w]+)?\.([\w\-]+)$/,
      normalizr = /\s*([\s\+\~>])\s*/g,
      splitters = /[\s\>\+\~]/,
      splittersMore = /(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,
      dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g'),
      tokenizr = new RegExp(splitters.source + splittersMore.source),
      specialChars = /([.*+?\^=!:${}()|\[\]\/\\])/g,
      simple = /^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,
      attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
      pseudo = /:([\w\-]+)(\(['"]?([\s\w\+\-]+)['"]?\))?/,
      chunker = new RegExp(simple.source + '(' + attr.source + ')?' + '(' + pseudo.source + ')?'),
      walker = {
    ' ': function (node) {
      return node && node !== html && node.parentNode
    },
    '>': function (node, contestant) {
      return node && node.parentNode == contestant.parentNode && node.parentNode;
    },
    '~': function (node) {
      return node && node.previousSibling;
    },
    '+': function (node, contestant, p1, p2) {
      if (!node) {
        return false;
      }
      p1 = previous(node);
      p2 = previous(contestant);
      return p1 && p2 && p1 == p2 && p1;
    }
  };
  function cache() {
    this.c = {};
  }
  cache.prototype = {
    g: function (k) {
      return this.c[k] || undefined;
    },
    s: function (k, v) {
      this.c[k] = v;
      return v;
    }
  };

  var classCache = new cache(),
      cleanCache = new cache(),
      attrCache = new cache(),
      tokenCache = new cache();

  function flatten(ar) {
    r = [];
    for (i = 0, l = ar.length; i < l; i++) {
      if (arrayLike(ar[i])) {
        r = r.concat(ar[i]);
      } else {
        r.push(ar[i]);
      }
    }
    return r;
  }

  function previous(n) {
    while (n = n.previousSibling) {
      if (n.nodeType == 1) {
        break;
      }
    }
    return n
  }

  function q(query) {
    return query.match(chunker);
  }

  // this next method expect at most these args
  // given => div.hello[title="world"]:foo('bar')

  // div.hello[title="world"]:foo('bar'), div, .hello, [title="world"], title, =, world, :foo('bar'), foo, ('bar'), bar]

  function interpret(whole, tag, idsAndClasses, wholeAttribute, attribute, qualifier, value, wholePseudo, pseudo, wholePseudoVal, pseudoVal) {
    var m, c, k;
    if (tag && this.tagName.toLowerCase() !== tag) {
      return false;
    }
    if (idsAndClasses && (m = idsAndClasses.match(id)) && m[1] !== this.id) {
      return false;
    }
    if (idsAndClasses && (classes = idsAndClasses.match(clas))) {
      for (i = classes.length; i--;) {
        c = classes[i].slice(1);
        if (!(classCache.g(c) || classCache.s(c, new RegExp('(^|\\s+)' + c + '(\\s+|$)'))).test(this.className)) {
          return false;
        }
      }
    }
    if (pseudo && qwery.pseudos && qwery.pseudos[pseudo] && !qwery.pseudos[pseudo](this, pseudoVal)) {
      return false;
    }
    if (wholeAttribute && !value) {
      o = this.attributes;
      for (k in o) {
        if (Object.prototype.hasOwnProperty.call(o, k) && (o[k].name || k) == attribute) {
          return this;
        }
      }
    }
    if (wholeAttribute && !checkAttr(qualifier, this.getAttribute(attribute) || '', value)) {
      return false;
    }
    return this;
  }

  function clean(s) {
    return cleanCache.g(s) || cleanCache.s(s, s.replace(specialChars, '\\$1'));
  }

  function checkAttr(qualify, actual, val) {
    switch (qualify) {
    case '=':
      return actual == val;
    case '^=':
      return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, new RegExp('^' + clean(val))));
    case '$=':
      return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp(clean(val) + '$')));
    case '*=':
      return actual.match(attrCache.g(val) || attrCache.s(val, new RegExp(clean(val))));
    case '~=':
      return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, new RegExp('(?:^|\\s+)' + clean(val) + '(?:\\s+|$)')));
    case '|=':
      return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, new RegExp('^' + clean(val) + '(-|$)')));
    }
    return 0;
  }

  function _qwery(selector) {
    var r = [], ret = [], i, j = 0, k, l, m, p, token, tag, els, root, intr, item, children,
        tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr)),
        dividedTokens = selector.match(dividers), dividedToken;
    tokens = tokens.slice(0); // this makes a copy of the array so the cached original is not effected
    if (!tokens.length) {
      return r;
    }

    token = tokens.pop();
    root = tokens.length && (m = tokens[tokens.length - 1].match(idOnly)) ? doc.getElementById(m[1]) : doc;
    if (!root) {
      return r;
    }
    intr = q(token);
    els = dividedTokens && /^[+~]$/.test(dividedTokens[dividedTokens.length - 1]) ? function (r) {
        while (root = root.nextSibling) {
          root.nodeType == 1 && (intr[1] ? intr[1] == root.tagName.toLowerCase() : 1) && r.push(root)
        }
        return r
      }([]) :
      root.getElementsByTagName(intr[1] || '*');
    for (i = 0, l = els.length; i < l; i++) {
      if (item = interpret.apply(els[i], intr)) {
        r[j++] = item;
      }
    }
    if (!tokens.length) {
      return r;
    }

    // loop through all descendent tokens
    for (j = 0, l = r.length, k = 0; j < l; j++) {
      p = r[j];
      // loop through each token backwards crawling up tree
      for (i = tokens.length; i--;) {
        // loop through parent nodes
        while (p = walker[dividedTokens[i]](p, r[j])) {
          if (found = interpret.apply(p, q(tokens[i]))) {
            break;
          }
        }
      }
      found && (ret[k++] = r[j]);
    }
    return ret;
  }

  function isNode(el) {
    return (el && el.nodeType && (el.nodeType == 1 || el.nodeType == 9));
  }

  function uniq(ar) {
    var a = [], i, j;
    label:
    for (i = 0; i < ar.length; i++) {
      for (j = 0; j < a.length; j++) {
        if (a[j] == ar[i]) {
          continue label;
        }
      }
      a[a.length] = ar[i];
    }
    return a;
  }

  function arrayLike(o) {
    return (typeof o === 'object' && isFinite(o.length));
  }

  function normalizeRoot(root) {
    if (!root) {
      return doc;
    }
    if (typeof root == 'string') {
      return qwery(root)[0];
    }
    if (arrayLike(root)) {
      return root[0];
    }
    return root;
  }

  function qwery(selector, _root) {
    var root = normalizeRoot(_root);

    if (!root || !selector) {
      return [];
    }
    if (selector === window || isNode(selector)) {
      return !_root || (selector !== window && isNode(root) && isAncestor(selector, root)) ? [selector] : [];
    }
    if (selector && arrayLike(selector)) {
      return flatten(selector);
    }
    if (m = selector.match(idOnly)) {
      return (el = doc.getElementById(m[1])) ? [el] : [];
    }
    if (m = selector.match(tagOnly)) {
      return flatten(root.getElementsByTagName(m[1]));
    }
    return select(selector, root);
  }

  var isAncestor = 'compareDocumentPosition' in html ?
    function (element, container) {
      return (container.compareDocumentPosition(element) & 16) == 16;
    } : 'contains' in html ?
    function (element, container) {
      container = container == doc || container == window ? html : container;
      return container !== element && container.contains(element);
    } :
    function (element, container) {
      while (element = element.parentNode) {
        if (element === container) {
          return 1;
        }
      }
      return 0;
    },

  select = (doc.querySelector && doc.querySelectorAll) ?
    function (selector, root) {
      if (doc.getElementsByClassName && (m = selector.match(classOnly))) {
        return flatten((root).getElementsByClassName(m[1]));
      }
      return flatten((root).querySelectorAll(selector));
    } :
    function (selector, root) {
      selector = selector.replace(normalizr, '$1');
      var result = [], element, collection, collections = [], i;
      if (m = selector.match(tagAndOrClass)) {
        items = root.getElementsByTagName(m[1] || '*');
        r = classCache.g(m[2]) || classCache.s(m[2], new RegExp('(^|\\s+)' + m[2] + '(\\s+|$)'));
        for (i = 0, l = items.length, j = 0; i < l; i++) {
          r.test(items[i].className) && (result[j++] = items[i]);
        }
        return result;
      }
      for (i = 0, items = selector.split(','), l = items.length; i < l; i++) {
        collections[i] = _qwery(items[i]);
      }
      for (i = 0, l = collections.length; i < l && (collection = collections[i]); i++) {
        var ret = collection;
        if (root !== doc) {
          ret = [];
          for (j = 0, m = collection.length; j < m && (element = collection[j]); j++) {
            // make sure element is a descendent of root
            isAncestor(element, root) && ret.push(element);
          }
        }
        result = result.concat(ret);
      }
      return uniq(result);
    };

  qwery.uniq = uniq;

  var oldQwery = context.qwery;
  qwery.noConflict = function () {
    context.qwery = oldQwery;
    return this;
  };

  if (typeof module !== 'undefined') module.exports = qwery; else context['qwery'] = qwery

}(this, document);<commit_msg>better feature detection for querySelectorAll<commit_after>!function (context, doc) {

  var c, i, j, k, l, m, o, p, r, v,
      el, node, found, classes, item, items, token,
      html = doc.documentElement,
      id = /#([\w\-]+)/,
      clas = /\.[\w\-]+/g,
      idOnly = /^#([\w\-]+$)/,
      classOnly = /^\.([\w\-]+)$/,
      tagOnly = /^([\w\-]+)$/,
      tagAndOrClass = /^([\w]+)?\.([\w\-]+)$/,
      normalizr = /\s*([\s\+\~>])\s*/g,
      splitters = /[\s\>\+\~]/,
      splittersMore = /(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,
      dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g'),
      tokenizr = new RegExp(splitters.source + splittersMore.source),
      specialChars = /([.*+?\^=!:${}()|\[\]\/\\])/g,
      simple = /^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,
      attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
      pseudo = /:([\w\-]+)(\(['"]?([\s\w\+\-]+)['"]?\))?/,
      chunker = new RegExp(simple.source + '(' + attr.source + ')?' + '(' + pseudo.source + ')?'),
      walker = {
    ' ': function (node) {
      return node && node !== html && node.parentNode
    },
    '>': function (node, contestant) {
      return node && node.parentNode == contestant.parentNode && node.parentNode;
    },
    '~': function (node) {
      return node && node.previousSibling;
    },
    '+': function (node, contestant, p1, p2) {
      if (!node) {
        return false;
      }
      p1 = previous(node);
      p2 = previous(contestant);
      return p1 && p2 && p1 == p2 && p1;
    }
  };
  function cache() {
    this.c = {};
  }
  cache.prototype = {
    g: function (k) {
      return this.c[k] || undefined;
    },
    s: function (k, v) {
      this.c[k] = v;
      return v;
    }
  };

  var classCache = new cache(),
      cleanCache = new cache(),
      attrCache = new cache(),
      tokenCache = new cache();

  function flatten(ar) {
    r = [];
    for (i = 0, l = ar.length; i < l; i++) {
      if (arrayLike(ar[i])) {
        r = r.concat(ar[i]);
      } else {
        r.push(ar[i]);
      }
    }
    return r;
  }

  function previous(n) {
    while (n = n.previousSibling) {
      if (n.nodeType == 1) {
        break;
      }
    }
    return n
  }

  function q(query) {
    return query.match(chunker);
  }

  // this next method expect at most these args
  // given => div.hello[title="world"]:foo('bar')

  // div.hello[title="world"]:foo('bar'), div, .hello, [title="world"], title, =, world, :foo('bar'), foo, ('bar'), bar]

  function interpret(whole, tag, idsAndClasses, wholeAttribute, attribute, qualifier, value, wholePseudo, pseudo, wholePseudoVal, pseudoVal) {
    var m, c, k;
    if (tag && this.tagName.toLowerCase() !== tag) {
      return false;
    }
    if (idsAndClasses && (m = idsAndClasses.match(id)) && m[1] !== this.id) {
      return false;
    }
    if (idsAndClasses && (classes = idsAndClasses.match(clas))) {
      for (i = classes.length; i--;) {
        c = classes[i].slice(1);
        if (!(classCache.g(c) || classCache.s(c, new RegExp('(^|\\s+)' + c + '(\\s+|$)'))).test(this.className)) {
          return false;
        }
      }
    }
    if (pseudo && qwery.pseudos && qwery.pseudos[pseudo] && !qwery.pseudos[pseudo](this, pseudoVal)) {
      return false;
    }
    if (wholeAttribute && !value) {
      o = this.attributes;
      for (k in o) {
        if (Object.prototype.hasOwnProperty.call(o, k) && (o[k].name || k) == attribute) {
          return this;
        }
      }
    }
    if (wholeAttribute && !checkAttr(qualifier, this.getAttribute(attribute) || '', value)) {
      return false;
    }
    return this;
  }

  function clean(s) {
    return cleanCache.g(s) || cleanCache.s(s, s.replace(specialChars, '\\$1'));
  }

  function checkAttr(qualify, actual, val) {
    switch (qualify) {
    case '=':
      return actual == val;
    case '^=':
      return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, new RegExp('^' + clean(val))));
    case '$=':
      return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp(clean(val) + '$')));
    case '*=':
      return actual.match(attrCache.g(val) || attrCache.s(val, new RegExp(clean(val))));
    case '~=':
      return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, new RegExp('(?:^|\\s+)' + clean(val) + '(?:\\s+|$)')));
    case '|=':
      return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, new RegExp('^' + clean(val) + '(-|$)')));
    }
    return 0;
  }

  function _qwery(selector) {
    var r = [], ret = [], i, j = 0, k, l, m, p, token, tag, els, root, intr, item, children,
        tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr)),
        dividedTokens = selector.match(dividers), dividedToken;
    tokens = tokens.slice(0); // this makes a copy of the array so the cached original is not effected
    if (!tokens.length) {
      return r;
    }

    token = tokens.pop();
    root = tokens.length && (m = tokens[tokens.length - 1].match(idOnly)) ? doc.getElementById(m[1]) : doc;
    if (!root) {
      return r;
    }
    intr = q(token);
    els = dividedTokens && /^[+~]$/.test(dividedTokens[dividedTokens.length - 1]) ? function (r) {
        while (root = root.nextSibling) {
          root.nodeType == 1 && (intr[1] ? intr[1] == root.tagName.toLowerCase() : 1) && r.push(root)
        }
        return r
      }([]) :
      root.getElementsByTagName(intr[1] || '*');
    for (i = 0, l = els.length; i < l; i++) {
      if (item = interpret.apply(els[i], intr)) {
        r[j++] = item;
      }
    }
    if (!tokens.length) {
      return r;
    }

    // loop through all descendent tokens
    for (j = 0, l = r.length, k = 0; j < l; j++) {
      p = r[j];
      // loop through each token backwards crawling up tree
      for (i = tokens.length; i--;) {
        // loop through parent nodes
        while (p = walker[dividedTokens[i]](p, r[j])) {
          if (found = interpret.apply(p, q(tokens[i]))) {
            break;
          }
        }
      }
      found && (ret[k++] = r[j]);
    }
    return ret;
  }

  function isNode(el) {
    return (el && el.nodeType && (el.nodeType == 1 || el.nodeType == 9));
  }

  function uniq(ar) {
    var a = [], i, j;
    label:
    for (i = 0; i < ar.length; i++) {
      for (j = 0; j < a.length; j++) {
        if (a[j] == ar[i]) {
          continue label;
        }
      }
      a[a.length] = ar[i];
    }
    return a;
  }

  function arrayLike(o) {
    return (typeof o === 'object' && isFinite(o.length));
  }

  function normalizeRoot(root) {
    if (!root) {
      return doc;
    }
    if (typeof root == 'string') {
      return qwery(root)[0];
    }
    if (arrayLike(root)) {
      return root[0];
    }
    return root;
  }

  function qwery(selector, _root) {
    var root = normalizeRoot(_root);

    if (!root || !selector) {
      return [];
    }
    if (selector === window || isNode(selector)) {
      return !_root || (selector !== window && isNode(root) && isAncestor(selector, root)) ? [selector] : [];
    }
    if (selector && arrayLike(selector)) {
      return flatten(selector);
    }
    if (m = selector.match(idOnly)) {
      return (el = doc.getElementById(m[1])) ? [el] : [];
    }
    if (m = selector.match(tagOnly)) {
      return flatten(root.getElementsByTagName(m[1]));
    }
    return select(selector, root);
  }

  var isAncestor = 'compareDocumentPosition' in html ?
    function (element, container) {
      return (container.compareDocumentPosition(element) & 16) == 16;
    } : 'contains' in html ?
    function (element, container) {
      container = container == doc || container == window ? html : container;
      return container !== element && container.contains(element);
    } :
    function (element, container) {
      while (element = element.parentNode) {
        if (element === container) {
          return 1;
        }
      }
      return 0;
    },

  supportsCSS3 = (function () {
    if (!doc.querySelector || !doc.querySelectorAll) return false;

    try {
      return (doc.querySelectorAll(':nth-of-type(1)').length > 0);
    } catch (e) {
      return false;
    }
  })(),

  select = supportsCSS3 ?
    function (selector, root) {
      if (doc.getElementsByClassName && (m = selector.match(classOnly))) {
        return flatten((root).getElementsByClassName(m[1]));
      }
      return flatten((root).querySelectorAll(selector));
    } :
    function (selector, root) {
      selector = selector.replace(normalizr, '$1');
      var result = [], element, collection, collections = [], i;
      if (m = selector.match(tagAndOrClass)) {
        items = root.getElementsByTagName(m[1] || '*');
        r = classCache.g(m[2]) || classCache.s(m[2], new RegExp('(^|\\s+)' + m[2] + '(\\s+|$)'));
        for (i = 0, l = items.length, j = 0; i < l; i++) {
          r.test(items[i].className) && (result[j++] = items[i]);
        }
        return result;
      }
      for (i = 0, items = selector.split(','), l = items.length; i < l; i++) {
        collections[i] = _qwery(items[i]);
      }
      for (i = 0, l = collections.length; i < l && (collection = collections[i]); i++) {
        var ret = collection;
        if (root !== doc) {
          ret = [];
          for (j = 0, m = collection.length; j < m && (element = collection[j]); j++) {
            // make sure element is a descendent of root
            isAncestor(element, root) && ret.push(element);
          }
        }
        result = result.concat(ret);
      }
      return uniq(result);
    };

  qwery.uniq = uniq;

  var oldQwery = context.qwery;
  qwery.noConflict = function () {
    context.qwery = oldQwery;
    return this;
  };

  if (typeof module !== 'undefined') module.exports = qwery; else context['qwery'] = qwery

}(this, document);<|endoftext|>