<commit_before>console.log(__dirname);
require.paths.push(__dirname + "/../");
require.paths.push(__dirname + "/../../");
var fs = require('fs');
var Script = process.binding('evals').Script;
var collect = load('docs/collect.js');

describe('collect', function(){
  describe('markdown', function(){
    it('should replace angular in markdown', function(){
      expect(collect.markdown('<angular/>')).
        toEqual('
<tt><angular/></tt>
');
    });

    it('should not replace anything in
', function(){
      expect(collect.markdown('bah x\n
\nangular.k\n
\n asdf x')).
        toEqual(
            '
bah x
' +
            '
\nangular.k\n
' +
            '
asdf x
');
    });
  });

  describe('processNgDoc', function() {
    var processNgDoc = collect.processNgDoc,
        documentation;

    beforeEach(function() {
      documentation = {
        pages: [],
        byName: {}
      };
    });

    it('should store references to docs by name', function() {
      var doc = {ngdoc: 'section', name: 'fake', raw: {text:''}};
      processNgDoc(documentation, doc);
      expect(documentation.byName.fake).toBe(doc);
    });

    it('should connect doc to owner (specified by @methodOf)', function() {
      var parentDoc = {ngdoc: 'section', name: 'parent', raw: {text:''}};
      var doc = {ngdoc: 'section', name: 'child', methodOf: 'parent', raw: {text:''}};
      processNgDoc(documentation, parentDoc);
      processNgDoc(documentation, doc);
      expect(documentation.byName.parent.method).toBeDefined();
      expect(documentation.byName.parent.method[0]).toBe(doc);
    });

    it('should not add doc to sections if @memberOf specified', function() {
      var parentDoc = {ngdoc: 'parent', name: 'parent', raw: {text:''}};
      var doc = {ngdoc: 'child', name: 'child', methodOf: 'parent', raw: {text:''}};
      processNgDoc(documentation, parentDoc);
      processNgDoc(documentation, doc);
      expect(documentation.pages.child).not.toBeDefined();
    });

    it('should throw exception if owner does not exist', function() {
      expect(function() {
        processNgDoc(documentation, {ngdoc: 'section', methodOf: 'not.exist', raw: {text:''}});
      }).toThrow('Owner "not.exist" is not defined.');
    });

    it('should ignore non-ng docs', function() {
      var doc = {name: 'anything'};
      expect(function() {
        processNgDoc(documentation, doc);
      }).not.toThrow();
      expect(documentation.pages).not.toContain(doc);
    });
  });

  describe('TAG', function(){
    var TAG = collect.TAG;
    var doc;
    beforeEach(function(){
      doc = {};
    });

    describe('@param', function(){
      it('should parse with no default', function(){
        TAG.param(doc, 'param',
            '{(number|string)} number Number \n to format.');
        expect(doc.param).toEqual([{
          type : '(number|string)',
          name : 'number',
          optional: false,
          'default' : undefined,
          description : 'Number \n to format.' }]);
      });
      it('should parse with default and optional', function(){
        TAG.param(doc, 'param',
            '{(number|string)=} [fractionSize=2] desc');
        expect(doc.param).toEqual([{
          type : '(number|string)',
          name : 'fractionSize',
          optional: true,
          'default' : '2',
          description : 'desc' }]);
      });
    });

    describe('@requires', function() {
      it('should parse more @requires tag into array', function() {
        TAG.requires(doc, 'requires', '$service');
        TAG.requires(doc, 'requires', '$another');

        expect(doc.requires).toEqual([
          {name: '$service'},
          {name: '$another'}
        ]);
      });
    });

    describe('@property', function() {
      it('should parse @property tags into array', function() {
        TAG.property(doc, 'property', '{type} name1 desc');
        TAG.property(doc, 'property', '{type} name2 desc');
        expect(doc.property.length).toEqual(2);
      });

      it('should parse @property with only name', function() {
        TAG.property(doc, 'property', 'fake');
        expect(doc.property[0].name).toEqual('fake');
      });

      it('should parse @property with optional type', function() {
        TAG.property(doc, 'property', '{string} name');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].type).toEqual('string');
      });

      it('should parse @property with optional description', function() {
        TAG.property(doc, 'property', 'name desc rip tion');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].description).toEqual('desc rip tion');
      });

      it('should parse @property with type and description both', function() {
        TAG.property(doc, 'property', '{bool} name desc rip tion');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].type).toEqual('bool');
        expect(doc.property[0].description).toEqual('desc rip tion');
      });

      /**
       * If property description is undefined, this variable is not set in the template,
       * so the whole @description tag is used instead
       */
      it('should set undefined description to "false"', function() {
        TAG.property(doc, 'property', 'name');
        expect(doc.property[0].description).toBe(false);
      });
    });

    describe('@methodOf', function() {
      it('should parse @methodOf tag', function() {
        expect(function() {
          TAG.methodOf(doc, 'methodOf', 'parentName');
        }).not.toThrow();
        expect(doc.methodOf).toEqual('parentName');
      });
    });

    describe('@returns', function() {
      it('should not parse @returns without type', function() {
      expect(function() {TAG.returns(doc, 'returns', 'lala');})
        .toThrow();
      });

      it('should parse @returns with type and description', function() {
        TAG.returns(doc, 'returns', '{string} descrip tion');
        expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
      });

      it('should transform description of @returns with markdown', function() {
        TAG.returns(doc, 'returns', '{string} descrip *tion*');
        expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
      });
    });

    describe('@description', function(){
      it('should support pre blocks', function(){
        TAG.description(doc, 'description', '
abc
');
        expect(doc.description).
          toBe('

abc

');
      });

      it('should support multiple pre blocks', function() {
        TAG.description(doc, 'description', 'foo \n
abc
\n#bah\nfoo \n
cba
');
        expect(doc.description).
          toBe('
foo
' +
               '

abc

' +
               '
bah
\n\n' +
               '
foo
' +
               '

cba

');

      });

      it('should support nested @link annotations with or without description', function() {
        TAG.description(doc, 'description',
            'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' +
            'dad{@link angular.foo}\n\n' +
            '{@link angular.directive.ng:foo ng:foo}');
        expect(doc.description).
          toBe('
foo angular.foo
\n\n' +
               '
da bar foo bar
\n\n' +
               '
dadangular.foo
\n\n' +
               '
ng:foo
');
      });
    });

    describe('@example', function(){
      it('should not remove {{}}', function(){
        TAG.example(doc, 'example', 'text {{ abc }}');
        expect(doc.example).toEqual('text {{ abc }}');
      });
    });

    describe('@deprecated', function() {
      it('should parse @deprecated', function() {
        TAG.deprecated(doc, 'deprecated', 'Replaced with foo.');
        expect(doc.deprecated).toBe('Replaced with foo.');
      })
    });

  });

  describe('trim', function(){
    var trim = collect.trim;
    it('should remove leading/trailing space', function(){
      expect(trim('  \nabc\n  ')).toEqual('abc');
    });

    it('should remove leading space on every line', function(){
      expect(trim('\n 1\n  2\n   3\n')).toEqual('1\n 2\n  3');
    });
  });

  describe('keywords', function(){
    var keywords = collect.keywords;
    it('should collect keywords', function(){
      expect(keywords('\nHello: World! @ignore.')).toEqual('hello world');
      expect(keywords('The `ng:class-odd` and ')).toEqual('and ng:class-odd the');
    });
  });

});

function load(path){
  var sandbox = {
      require: require,
      console: console,
      __dirname: __dirname,
      testmode: true
  };
  Script.runInNewContext(fs.readFileSync(path), sandbox, path);
  return sandbox;
}
<commit_msg>add spec for incrementing headings<commit_after>console.log(__dirname);
require.paths.push(__dirname + "/../");
require.paths.push(__dirname + "/../../");
var fs = require('fs');
var Script = process.binding('evals').Script;
var collect = load('docs/collect.js');

describe('collect', function(){
  describe('markdown', function(){
    it('should replace angular in markdown', function(){
      expect(collect.markdown('<angular/>')).
        toEqual('
<tt><angular/></tt>
');
    });

    it('should not replace anything in
', function(){
      expect(collect.markdown('bah x\n
\nangular.k\n
\n asdf x')).
        toEqual(
            '
bah x
' +
            '
\nangular.k\n
' +
            '
asdf x
');
    });
  });

  describe('processNgDoc', function() {
    var processNgDoc = collect.processNgDoc,
        documentation;

    beforeEach(function() {
      documentation = {
        pages: [],
        byName: {}
      };
    });

    it('should store references to docs by name', function() {
      var doc = {ngdoc: 'section', name: 'fake', raw: {text:''}};
      processNgDoc(documentation, doc);
      expect(documentation.byName.fake).toBe(doc);
    });

    it('should connect doc to owner (specified by @methodOf)', function() {
      var parentDoc = {ngdoc: 'section', name: 'parent', raw: {text:''}};
      var doc = {ngdoc: 'section', name: 'child', methodOf: 'parent', raw: {text:''}};
      processNgDoc(documentation, parentDoc);
      processNgDoc(documentation, doc);
      expect(documentation.byName.parent.method).toBeDefined();
      expect(documentation.byName.parent.method[0]).toBe(doc);
    });

    it('should not add doc to sections if @memberOf specified', function() {
      var parentDoc = {ngdoc: 'parent', name: 'parent', raw: {text:''}};
      var doc = {ngdoc: 'child', name: 'child', methodOf: 'parent', raw: {text:''}};
      processNgDoc(documentation, parentDoc);
      processNgDoc(documentation, doc);
      expect(documentation.pages.child).not.toBeDefined();
    });

    it('should throw exception if owner does not exist', function() {
      expect(function() {
        processNgDoc(documentation, {ngdoc: 'section', methodOf: 'not.exist', raw: {text:''}});
      }).toThrow('Owner "not.exist" is not defined.');
    });

    it('should ignore non-ng docs', function() {
      var doc = {name: 'anything'};
      expect(function() {
        processNgDoc(documentation, doc);
      }).not.toThrow();
      expect(documentation.pages).not.toContain(doc);
    });
  });

  describe('TAG', function(){
    var TAG = collect.TAG;
    var doc;
    beforeEach(function(){
      doc = {};
    });

    describe('@param', function(){
      it('should parse with no default', function(){
        TAG.param(doc, 'param',
            '{(number|string)} number Number \n to format.');
        expect(doc.param).toEqual([{
          type : '(number|string)',
          name : 'number',
          optional: false,
          'default' : undefined,
          description : 'Number \n to format.' }]);
      });
      it('should parse with default and optional', function(){
        TAG.param(doc, 'param',
            '{(number|string)=} [fractionSize=2] desc');
        expect(doc.param).toEqual([{
          type : '(number|string)',
          name : 'fractionSize',
          optional: true,
          'default' : '2',
          description : 'desc' }]);
      });
    });

    describe('@requires', function() {
      it('should parse more @requires tag into array', function() {
        TAG.requires(doc, 'requires', '$service');
        TAG.requires(doc, 'requires', '$another');

        expect(doc.requires).toEqual([
          {name: '$service'},
          {name: '$another'}
        ]);
      });
    });

    describe('@property', function() {
      it('should parse @property tags into array', function() {
        TAG.property(doc, 'property', '{type} name1 desc');
        TAG.property(doc, 'property', '{type} name2 desc');
        expect(doc.property.length).toEqual(2);
      });

      it('should parse @property with only name', function() {
        TAG.property(doc, 'property', 'fake');
        expect(doc.property[0].name).toEqual('fake');
      });

      it('should parse @property with optional type', function() {
        TAG.property(doc, 'property', '{string} name');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].type).toEqual('string');
      });

      it('should parse @property with optional description', function() {
        TAG.property(doc, 'property', 'name desc rip tion');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].description).toEqual('desc rip tion');
      });

      it('should parse @property with type and description both', function() {
        TAG.property(doc, 'property', '{bool} name desc rip tion');
        expect(doc.property[0].name).toEqual('name');
        expect(doc.property[0].type).toEqual('bool');
        expect(doc.property[0].description).toEqual('desc rip tion');
      });

      /**
       * If property description is undefined, this variable is not set in the template,
       * so the whole @description tag is used instead
       */
      it('should set undefined description to "false"', function() {
        TAG.property(doc, 'property', 'name');
        expect(doc.property[0].description).toBe(false);
      });
    });

    describe('@methodOf', function() {
      it('should parse @methodOf tag', function() {
        expect(function() {
          TAG.methodOf(doc, 'methodOf', 'parentName');
        }).not.toThrow();
        expect(doc.methodOf).toEqual('parentName');
      });
    });

    describe('@returns', function() {
      it('should not parse @returns without type', function() {
      expect(function() {TAG.returns(doc, 'returns', 'lala');})
        .toThrow();
      });

      it('should parse @returns with type and description', function() {
        TAG.returns(doc, 'returns', '{string} descrip tion');
        expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
      });

      it('should transform description of @returns with markdown', function() {
        TAG.returns(doc, 'returns', '{string} descrip *tion*');
        expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
      });
    });

    describe('@description', function(){
      it('should support pre blocks', function(){
        TAG.description(doc, 'description', '
abc
');
        expect(doc.description).
          toBe('

abc

');
      });

      it('should support multiple pre blocks', function() {
        TAG.description(doc, 'description', 'foo \n
abc
\n#bah\nfoo \n
cba
');
        expect(doc.description).
          toBe('
foo
' +
               '

abc

' +
               '
bah
\n\n' +
               '
foo
' +
               '

cba

');

      });

      it('should support nested @link annotations with or without description', function() {
        TAG.description(doc, 'description',
            'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' +
            'dad{@link angular.foo}\n\n' +
            '{@link angular.directive.ng:foo ng:foo}');
        expect(doc.description).
          toBe('
foo angular.foo
\n\n' +
               '
da bar foo bar
\n\n' +
               '
dadangular.foo
\n\n' +
               '
ng:foo
');
      });

      it('should increment all headings by one', function() {
        TAG.description(doc, 'description', '# foo\nabc');
        expect(doc.description).
          toBe('
foo
\n\n
abc
');
      });
    });

    describe('@example', function(){
      it('should not remove {{}}', function(){
        TAG.example(doc, 'example', 'text {{ abc }}');
        expect(doc.example).toEqual('text {{ abc }}');
      });
    });

    describe('@deprecated', function() {
      it('should parse @deprecated', function() {
        TAG.deprecated(doc, 'deprecated', 'Replaced with foo.');
        expect(doc.deprecated).toBe('Replaced with foo.');
      })
    });

  });

  describe('trim', function(){
    var trim = collect.trim;
    it('should remove leading/trailing space', function(){
      expect(trim('  \nabc\n  ')).toEqual('abc');
    });

    it('should remove leading space on every line', function(){
      expect(trim('\n 1\n  2\n   3\n')).toEqual('1\n 2\n  3');
    });
  });

  describe('keywords', function(){
    var keywords = collect.keywords;
    it('should collect keywords', function(){
      expect(keywords('\nHello: World! @ignore.')).toEqual('hello world');
      expect(keywords('The `ng:class-odd` and ')).toEqual('and ng:class-odd the');
    });
  });

});

function load(path){
  var sandbox = {
      require: require,
      console: console,
      __dirname: __dirname,
      testmode: true
  };
  Script.runInNewContext(fs.readFileSync(path), sandbox, path);
  return sandbox;
}
<|endoftext|>


<commit_before>function hkidCharVal(ch) {
  console.log('charVal');
  console.log('ch:', ch);
  var intVal = ch.charCodeAt(0);
  console.log('intVal:', intVal);
  if (intVal >= 48 && intVal <= 57) {
    console.log(intVal-48);
    return (intVal - 48);
  }
  if (intVal >= 65 && intVal <= 90) {
    console.log('intVal, intVal - 55', intVal, intVal - 55);
    return (intVal - 55);
  }
  return false;
}

function verifyHKID(hkid) {
  console.log("Verifying~");
  var len;
  hkid = hkid.replace(/\(|\)/g, '');
  console.log('hkid:', hkid);
	if (hkid.match(/^[A-Z][0-9]{6}[0-9]$/) !== null) {
    len = 8
  } else if (hkid.match(/^[A-Z][A-Z][0-9]{6}[0-9]$/) !== null) {
    len = 9
  } else {
    return false;
  }
  var val = 324;
  var currVal;
  for (var i = len; i >= 2; i--) {
    if ((currVal = hkidCharVal(hkid.charAt(8 - i))) === false) return false;
    console.log('currVal,i:', currVal, i);
    val += currVal * i
  }
  val %= 11
  if (val == 0) val = '0';
  else if (val == 1) val = 'A';
  else val = (11 - val).toString();
  console.log('chkSum:', val);
  return (hkid.charAt(hkid.length - 1) === val ? true : false );
}
<commit_msg>Changed JS name<commit_after><|endoftext|>


<commit_before>(function (requirejs, require, define) {

// VideoSpeedControl module.
define(
'video/08_video_speed_control.js',
[],
function () {

    // VideoSpeedControl() function - what this module "exports".
    return function (state) {
        state.videoSpeedControl = {};

        _makeFunctionsPublic(state);
        _renderElements(state);
        _bindHandlers(state);
    };

    // ***************************************************************
    // Private functions start here.
    // ***************************************************************

    // function _makeFunctionsPublic(state)
    //
    //     Functions which will be accessible via 'state' object. When called,
    //     these functions will get the 'state' object as a context.
    function _makeFunctionsPublic(state) {
        state.videoSpeedControl.changeVideoSpeed = _.bind(
            changeVideoSpeed, state
        );
        state.videoSpeedControl.setSpeed = _.bind(setSpeed, state);
        state.videoSpeedControl.reRender = _.bind(reRender, state);
    }

    // function _renderElements(state)
    //
    //     Create any necessary DOM elements, attach them, and set their
    //     initial configuration. Also make the created DOM elements available
    //     via the 'state' object. Much easier to work this way - you don't
    //     have to do repeated jQuery element selects.
    function _renderElements(state) {
        state.videoSpeedControl.speeds = state.speeds;

        state.videoSpeedControl.el = state.el.find('div.speeds');

        state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el
            .find('.video_speeds');

        state.videoControl.secondaryControlsEl.prepend(
            state.videoSpeedControl.el
        );

        $.each(state.videoSpeedControl.speeds, function(index, speed) {
            var link = '' + speed + 'x';

            state.videoSpeedControl.videoSpeedsEl
                .prepend(
                    $('
' + link + '
')
                );
        });

        state.videoSpeedControl.setSpeed(state.speed);
    }

    // function _bindHandlers(state)
    //
    //     Bind any necessary function callbacks to DOM events (click,
    //     mousemove, etc.).
    function _bindHandlers(state) {
        state.videoSpeedControl.videoSpeedsEl.find('a')
            .on('click', state.videoSpeedControl.changeVideoSpeed);

        if (onTouchBasedDevice()) {
            state.videoSpeedControl.el.on('click', function(event) {
                event.preventDefault();
                $(this).toggleClass('open');
            });
        } else {
            state.videoSpeedControl.el
                .on('mouseenter', function () {
                    $(this).addClass('open');
                })
                .on('mouseleave', function () {
                    $(this).removeClass('open');
                })
                .on('click', function (event) {
                    event.preventDefault();
                    $(this).removeClass('open');
                });

            state.videoSpeedControl.el.children('a')
                .on('focus', function () {
                    $(this).parent().addClass('open');
                })
                .on('blur', function () {
                    state.videoSpeedControl.videoSpeedsEl
                        .find('a.speed_link:first')
                        .focus();
                });

            state.videoSpeedControl.videoSpeedsEl.find('a.speed_link:last')
                .on('blur', function () {
                    state.videoSpeedControl.el.removeClass('open');
                });
        }
    }

    // ***************************************************************
    // Public functions start here.
    // These are available via the 'state' object. Their context ('this'
    // keyword) is the 'state' object. The magic private function that makes
    // them available and sets up their context is makeFunctionsPublic().
    // ***************************************************************

    function setSpeed(speed) {
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.videoSpeedsEl
            .find("li[data-speed='" + speed + "']")
            .addClass('active');
        this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
    }

    function changeVideoSpeed(event) {
        var parentEl = $(event.target).parent();

        event.preventDefault();

        if (!parentEl.hasClass('active')) {
            this.videoSpeedControl.currentSpeed = parentEl.data('speed');

            this.videoSpeedControl.setSpeed(
                // To meet the API expected format.
                parseFloat(this.videoSpeedControl.currentSpeed)
                    .toFixed(2)
                    .replace(/\.00$/, '.0')
            );

            this.trigger(
                'videoPlayer.onSpeedChange',
                this.videoSpeedControl.currentSpeed
            );
        }
    }

    function reRender(params) {
        var _this = this;

        this.videoSpeedControl.videoSpeedsEl.empty();
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.speeds = params.newSpeeds;

        $.each(this.videoSpeedControl.speeds, function(index, speed) {
            var link, listItem;

            link = '' + speed + 'x';

            listItem = $('
' + link + '
');

            if (speed === params.currentSpeed) {
                listItem.addClass('active');
            }

            _this.videoSpeedControl.videoSpeedsEl.prepend(listItem);
        });

        this.videoSpeedControl.videoSpeedsEl.find('a')
            .on('click', this.videoSpeedControl.changeVideoSpeed);

        // TODO: After the control was re-rendered, we should attach 'focus'
        // and 'blur' events once more.
    }

});

}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
<commit_msg>For YouTube videos tabbing from Speeds to Volume closes Speeds dialog.<commit_after>(function (requirejs, require, define) {

// VideoSpeedControl module.
define(
'video/08_video_speed_control.js',
[],
function () {

    // VideoSpeedControl() function - what this module "exports".
    return function (state) {
        state.videoSpeedControl = {};

        _makeFunctionsPublic(state);
        _renderElements(state);
        _bindHandlers(state);
    };

    // ***************************************************************
    // Private functions start here.
    // ***************************************************************

    // function _makeFunctionsPublic(state)
    //
    //     Functions which will be accessible via 'state' object. When called,
    //     these functions will get the 'state' object as a context.
    function _makeFunctionsPublic(state) {
        state.videoSpeedControl.changeVideoSpeed = _.bind(
            changeVideoSpeed, state
        );
        state.videoSpeedControl.setSpeed = _.bind(setSpeed, state);
        state.videoSpeedControl.reRender = _.bind(reRender, state);
    }

    // function _renderElements(state)
    //
    //     Create any necessary DOM elements, attach them, and set their
    //     initial configuration. Also make the created DOM elements available
    //     via the 'state' object. Much easier to work this way - you don't
    //     have to do repeated jQuery element selects.
    function _renderElements(state) {
        state.videoSpeedControl.speeds = state.speeds;

        state.videoSpeedControl.el = state.el.find('div.speeds');

        state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el
            .find('.video_speeds');

        state.videoControl.secondaryControlsEl.prepend(
            state.videoSpeedControl.el
        );

        $.each(state.videoSpeedControl.speeds, function(index, speed) {
            var link = '' + speed + 'x';

            state.videoSpeedControl.videoSpeedsEl
                .prepend(
                    $('
' + link + '
')
                );
        });

        state.videoSpeedControl.setSpeed(state.speed);
    }

    // function _bindHandlers(state)
    //
    //     Bind any necessary function callbacks to DOM events (click,
    //     mousemove, etc.).
    function _bindHandlers(state) {
        state.videoSpeedControl.videoSpeedsEl.find('a')
            .on('click', state.videoSpeedControl.changeVideoSpeed);

        if (onTouchBasedDevice()) {
            state.videoSpeedControl.el.on('click', function(event) {
                event.preventDefault();
                $(this).toggleClass('open');
            });
        } else {
            state.videoSpeedControl.el
                .on('mouseenter', function () {
                    $(this).addClass('open');
                })
                .on('mouseleave', function () {
                    $(this).removeClass('open');
                })
                .on('click', function (event) {
                    event.preventDefault();
                    $(this).removeClass('open');
                });

            state.videoSpeedControl.el.children('a')
                .on('focus', function () {
                    $(this).parent().addClass('open');
                })
                .on('blur', function () {
                    state.videoSpeedControl.videoSpeedsEl
                        .find('a.speed_link:first')
                        .focus();
                });

            state.videoSpeedControl.videoSpeedsEl.find('a.speed_link:last')
                .on('blur', function () {
                    state.videoSpeedControl.el.removeClass('open');
                });
        }
    }

    // ***************************************************************
    // Public functions start here.
    // These are available via the 'state' object. Their context ('this'
    // keyword) is the 'state' object. The magic private function that makes
    // them available and sets up their context is makeFunctionsPublic().
    // ***************************************************************

    function setSpeed(speed) {
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.videoSpeedsEl
            .find("li[data-speed='" + speed + "']")
            .addClass('active');
        this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
    }

    function changeVideoSpeed(event) {
        var parentEl = $(event.target).parent();

        event.preventDefault();

        if (!parentEl.hasClass('active')) {
            this.videoSpeedControl.currentSpeed = parentEl.data('speed');

            this.videoSpeedControl.setSpeed(
                // To meet the API expected format.
                parseFloat(this.videoSpeedControl.currentSpeed)
                    .toFixed(2)
                    .replace(/\.00$/, '.0')
            );

            this.trigger(
                'videoPlayer.onSpeedChange',
                this.videoSpeedControl.currentSpeed
            );
        }
    }

    function reRender(params) {
        var _this = this;

        this.videoSpeedControl.videoSpeedsEl.empty();
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.speeds = params.newSpeeds;

        $.each(this.videoSpeedControl.speeds, function(index, speed) {
            var link, listItem;

            link = '' + speed + 'x';

            listItem = $('
' + link + '
');

            if (speed === params.currentSpeed) {
                listItem.addClass('active');
            }

            _this.videoSpeedControl.videoSpeedsEl.prepend(listItem);
        });

        _bindHandlers(this);
    }

});

}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
<|endoftext|>


<commit_before>var twtQueries = {};

//Auto-streaming
Meteor.startup(function () {
  tp_tweetQueries.find().observe({
    added: function(doc) {
      if (!twtQueries[doc.track]) {
        Meteor.call('streamStatuses', {
          _id: doc._id,
          track: doc.track,
        });
      }
    },
    removed: function(doc) {
      if (twtQueries[doc.track]) {
        twtQueries[doc.track].destroy();
      }
    }
  });
});

//Create Twitter object with tokens
function twitterCredentials (meteorUser) {
  var config = Accounts.loginServiceConfiguration.findOne({service: 'twitter'});
  return new TwitterApi({
    consumer_key: config.consumerKey,
    consumer_secret: config.secret,
				access_token_key: config.access_token_key, // <-- fill me
				access_token_secret: config.access_token_secret // <-- fill me
      });
}

//Insert used to cache tweets from stream.
var wrappedTweetInsert = Meteor.bindEnvironment(function(tweet, queryId) {
  tp_tweetCache.insert({
    id_str: tweet.id_str,
    queryId: queryId,
    created_at: tweet.created_at,
    text: tweet.text,
    in_reply_to_screen_name: tweet.in_reply_to_screen_name,
    user: {
      name: tweet.user.name,
      screen_name: tweet.user.screen_name,
      profile_image_url: tweet.user.profile_image_url
    },
    entities: tweet.entities,
    timestamp_ms: tweet.timestamp_ms
  }, function(err, res) {
    if (err) {
      console.log(err);
    }
  });
}, "Failed to insert tweet into tp_tweetCache collection.");

Meteor.methods({
	streamStatuses: function(data) {
		var client = twitterCredentials(Meteor.user());
		if(!data) {
			throw Meteor.Error( 500, "'null' is not a valid stream query");
		}

		client.stream('statuses/filter', data, function(stream) {
      twtQueries[data.track] = stream;
      stream.on('data', function(tweet) {
        wrappedTweetInsert(tweet, data._id);
      });

      stream.on('error', function(error) {
        throw Meteor.Error( 500, "An error has occured while trying to stream", error);
      });
    });
	},
	destroyOneStream: function(streamToDestroy){
		streamToDestroy.destroy();
	},
	destroyStreams: function() {
		for (var i in twtQueries) {
			twtQueries[i].destroy();
			twtQueries.splice(i, 1);
		}
	},
	addStreamingQuery: function (query) {
		data = {
			track: query,
		}
		tp_tweetQueries.insert(data);
	}
});
<commit_msg>Follow support and hashtag filtering<commit_after>var twtQueries = {};

//Auto-streaming
Meteor.startup(function () {
  tp_tweetQueries.find().observe({
    added: function(doc) {
      if (!twtQueries[doc._id]) {
        Meteor.call('streamStatuses', {
          _id: doc._id,
          track: doc.track,
          follow: doc.follow,
        });
      }
    },
    removed: function(doc) {
      if (twtQueries[doc._id]) {
        twtQueries[doc._id].destroy();
      }
    }
  });
});

//Create Twitter object with tokens
function twitterCredentials (meteorUser) {
  var config = Accounts.loginServiceConfiguration.findOne({service: 'twitter'});
  return new TwitterApi({
    consumer_key: config.consumerKey,
    consumer_secret: config.secret,
    access_token_key: config.access_token_key, // <-- fill me
    access_token_secret: config.access_token_secret // <-- fill me
  });
}

//Insert used to cache tweets from stream.
var wrappedTweetInsert = Meteor.bindEnvironment(function(tweet, queryId) {
  tp_tweetCache.insert({
    id_str: tweet.id_str,
    queryId: queryId,
    created_at: tweet.created_at,
    text: tweet.text,
    in_reply_to_screen_name: tweet.in_reply_to_screen_name,
    user: {
      name: tweet.user.name,
      screen_name: tweet.user.screen_name,
      profile_image_url: tweet.user.profile_image_url
    },
    entities: tweet.entities,
    timestamp_ms: tweet.timestamp_ms
  }, function(err, res) {
    if (err) {
      console.log(err);
    }
  });
}, "Failed to insert tweet into tp_tweetCache collection.");

Meteor.methods({
	streamStatuses: function(data) {
		var client = twitterCredentials(Meteor.user());
		if(!data) {
			throw Meteor.Error( 500, "'null' is not a valid stream query");
		}
		client.stream('statuses/filter', data, function(stream) {
      twtQueries[data._id] = stream;
      stream.on('data', function(tweet) {
        var hasHashtag = false;
        var hashtags = tweet.entities.hashtags;
        for (var i = hashtags.length - 1; i >= 0; i--) {
          if(hashtags[i].text.toLowerCase() == data.track.toLowerCase()) {
            hasHashtag = true;
            break;
          }
        }
        if(hasHashtag || tweet.user.id == data.follow) {
          wrappedTweetInsert(tweet, data._id);
        }
      });

      stream.on('error', function(error) {
        throw Meteor.Error( 500, "An error has occured while trying to stream", error);
      });
    });
	},
	destroyOneStream: function(streamToDestroy){
		streamToDestroy.destroy();
	},
	destroyStreams: function() {
		for (var i in twtQueries) {
			twtQueries[i].destroy();
			twtQueries.splice(i, 1);
		}
	},
	addStreamingQuery: function (hashtags, users) {
		data = {
			track: hashtags,
      follow: users,
		}
		tp_tweetQueries.insert(data);
	}
});
<|endoftext|>


<commit_before>/**
 * @fileoverview Enforce props alphabetical sorting
 * @author Yannick Croissant
 */

'use strict';

// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------

const rule = require('../../../lib/rules/jsx-sort-props');
const RuleTester = require('eslint').RuleTester;

const parserOptions = {
  ecmaVersion: 8,
  sourceType: 'module',
  ecmaFeatures: {
    experimentalObjectRestSpread: true,
    jsx: true
  }
};

// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

const ruleTester = new RuleTester({parserOptions});

const expectedError = {
  message: 'Props should be sorted alphabetically',
  type: 'JSXAttribute'
};
const expectedCallbackError = {
  message: 'Callbacks must be listed after all other props',
  type: 'JSXAttribute'
};
const expectedShorthandFirstError = {
  message: 'Shorthand props must be listed before all other props',
  type: 'JSXAttribute'
};
const expectedShorthandLastError = {
  message: 'Shorthand props must be listed after all other props',
  type: 'JSXAttribute'
};
const expectedReservedFirstError = {
  message: 'Reserved props must be listed before all other props',
  type: 'JSXAttribute'
};
const expectedEmptyReservedFirstError = {
  message: 'A customized reserved first list must not be empty'
};
const expectedInvalidReservedFirstError = {
  message: 'A customized reserved first list must only contain a subset of React reserved props. Remove: notReserved'
};
const callbacksLastArgs = [{
  callbacksLast: true
}];
const ignoreCaseAndCallbackLastArgs = [{
  callbacksLast: true,
  ignoreCase: true
}];
const shorthandFirstArgs = [{
  shorthandFirst: true
}];
const shorthandLastArgs = [{
  shorthandLast: true
}];
const shorthandAndCallbackLastArgs = [{
  callbacksLast: true,
  shorthandLast: true
}];
const ignoreCaseArgs = [{
  ignoreCase: true
}];
const noSortAlphabeticallyArgs = [{
  noSortAlphabetically: true
}];
const sortAlphabeticallyArgs = [{
  noSortAlphabetically: false
}];
const reservedFirstAsBooleanArgs = [{
  reservedFirst: true
}];
const reservedFirstAsArrayArgs = [{
  reservedFirst: ['children', 'dangerouslySetInnerHTML', 'key']
}];
const reservedFirstWithNoSortAlphabeticallyArgs = [{
  noSortAlphabetically: true,
  reservedFirst: true
}];
const reservedFirstAsEmptyArrayArgs = [{
  reservedFirst: []
}];
const reservedFirstAsInvalidArrayArgs = [{
  reservedFirst: ['notReserved']
}];

ruleTester.run('jsx-sort-props', rule, {
  valid: [
    {code: '<App />;'},
    {code: '<App {...this.props} />;'},
    {code: '<App a b c />;'},
    {code: '<App {...this.props} a b c />;'},
    {code: '<App c {...this.props} a b />;'},
    {code: '<App a="c" b="b" c="a" />;'},
    {code: '<App {...this.props} a="c" b="b" c="a" />;'},
    {code: '<App c="a" {...this.props} a="c" b="b" />;'},
    {code: '<App A a />;'},
    // Ignoring case
    {code: '<App a A />;', options: ignoreCaseArgs},
    {code: '<App a B c />;', options: ignoreCaseArgs},
    {code: '<App A b C />;', options: ignoreCaseArgs},
    // Sorting callbacks below all other props
    {code: '<App a z onBar onFoo />;', options: callbacksLastArgs},
    {code: '<App z onBar onFoo />;', options: ignoreCaseAndCallbackLastArgs},
    // Sorting shorthand props before others
    {code: '<App a b="b" />;', options: shorthandFirstArgs},
    {code: '<App z a="a" />;', options: shorthandFirstArgs},
    {code: '<App x y z a="a" b="b" />;', options: shorthandFirstArgs},
    {code: '<App a="a" b="b" x y z />;', options: shorthandLastArgs},
    {
      code: '<App a="a" b="b" x y z onBar onFoo />;',
      options: shorthandAndCallbackLastArgs
    },
    // noSortAlphabetically
    {code: '<App a b />;', options: noSortAlphabeticallyArgs},
    {code: '<App b a />;', options: noSortAlphabeticallyArgs},
    // reservedFirst
    {
      code: '<App children={<App />} key={0} ref="r" a b c />',
      options: reservedFirstAsBooleanArgs
    },
    {
      code: '<App children={<App />} key={0} ref="r" a b c dangerouslySetInnerHTML={{__html: "EPR"}} />',
      options: reservedFirstAsBooleanArgs
    },
    {
      code: '<App children={<App />} key={0} a ref="r" />',
      options: reservedFirstAsArrayArgs
    },
    {
      code: '<App children={<App />} key={0} a dangerouslySetInnerHTML={{__html: "EPR"}} ref="r" />',
      options: reservedFirstAsArrayArgs
    },
    {
      code: '<App ref="r" key={0} children={<App />} b a c />',
      options: reservedFirstWithNoSortAlphabeticallyArgs
    },
    {
      code: '<div ref="r" dangerouslySetInnerHTML={{__html: "EPR"}} key={0} children={<App />} b a c />',
      options: reservedFirstWithNoSortAlphabeticallyArgs
    }
  ],
  invalid: [
    {
      code: '<App b a />;',
      errors: [expectedError],
      output: '<App a b />;'
    },
    {
      code: '<App {...this.props} b a />;',
      errors: [expectedError],
      output: '<App {...this.props} a b />;'
    },
    {
      code: '<App c {...this.props} b a />;',
      errors: [expectedError],
      output: '<App c {...this.props} a b />;'
    },
    {
      code: '<App a A />;',
      errors: [expectedError],
      output: '<App a A />;'
    },
    {
      code: '<App B a />;',
      options: ignoreCaseArgs,
      errors: [expectedError],
      output: '<App a B />;'
    },
    {
      code: '<App B A c />;',
      options: ignoreCaseArgs,
      errors: [expectedError],
      output: '<App A B c />;'
    },
    {
      code: '<App c="a" a="c" b="b" />;',
      output: '<App a="c" b="b" c="a" />;',
      errors: 2
    },
    {
      code: '<App {...this.props} c="a" a="c" b="b" />;',
      output: '<App {...this.props} a="c" b="b" c="a" />;',
      errors: 2
    },
    {
      code: '<App d="d" b="b" {...this.props} c="a" a="c" />;',
      output: '<App b="b" d="d" {...this.props} a="c" c="a" />;',
      errors: 2
    },
    {
      code: `
      <App
        a={true}
        z
        r
        _onClick={function(){}}
        onHandle={function(){}}
        {...this.props}
        b={false}
        {...otherProps}
      >
        {test}
      </App>
    `,
      output: `
      <App
        _onClick={function(){}}
        a={true}
        onHandle={function(){}}
        r
        z
        {...this.props}
        b={false}
        {...otherProps}
      >
        {test}
      </App>
    `,
      errors: 3
    },
    {
      code: '<App a z onFoo onBar />;',
      errors: [expectedError],
      options: callbacksLastArgs
    }, {
      code: '<App a onBar onFoo z />;',
      errors: [expectedCallbackError],
      options: callbacksLastArgs
    }, {
      code: '<App a="a" b />;',
      errors: [expectedShorthandFirstError],
      options: shorthandFirstArgs
    },
    {code: '<App z x a="a" />;', errors: [expectedError], options: shorthandFirstArgs}, {
      code: '<App b a="a" />;',
      errors: [expectedShorthandLastError],
      options: shorthandLastArgs
    }, {
      code: '<App a="a" onBar onFoo z x />;',
      errors: [shorthandAndCallbackLastArgs],
      options: shorthandLastArgs
    },
    {code: '<App b a />;', errors: [expectedError], options: sortAlphabeticallyArgs},
    // reservedFirst
    {
      code: '<App a key={1} />',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '
',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App ref="r" key={2} b />',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedError]
    },
    {
      code: '<App key={2} b a />',
      options: reservedFirstAsBooleanArgs,
      output: '<App key={2} a b />',
      errors: [expectedError]
    },
    {
      code: '<App b a />',
      options: reservedFirstAsBooleanArgs,
      output: '<App a b />',
      errors: [expectedError]
    },
    {
      code: '<App dangerouslySetInnerHTML={{__html: "EPR"}} e key={2} b />',
      options: reservedFirstAsBooleanArgs,
      output: '<App key={2} b dangerouslySetInnerHTML={{__html: "EPR"}} e />',
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App key={3} children={<App />} />',
      options: reservedFirstAsArrayArgs,
      errors: [expectedError]
    },
    {
      code: '<App z ref="r" />',
      options: reservedFirstWithNoSortAlphabeticallyArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App key={4} />',
      options: reservedFirstAsEmptyArrayArgs,
      errors: [expectedEmptyReservedFirstError]
    },
    {
      code: '<App key={5} />',
      options: reservedFirstAsInvalidArrayArgs,
      errors: [expectedInvalidReservedFirstError]
    }
  ]
});
<commit_msg>[Tests] clean up some formatting<commit_after>/**
 * @fileoverview Enforce props alphabetical sorting
 * @author Yannick Croissant
 */

'use strict';

// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------

const rule = require('../../../lib/rules/jsx-sort-props');
const RuleTester = require('eslint').RuleTester;

const parserOptions = {
  ecmaVersion: 8,
  sourceType: 'module',
  ecmaFeatures: {
    experimentalObjectRestSpread: true,
    jsx: true
  }
};

// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

const ruleTester = new RuleTester({parserOptions});

const expectedError = {
  message: 'Props should be sorted alphabetically',
  type: 'JSXAttribute'
};
const expectedCallbackError = {
  message: 'Callbacks must be listed after all other props',
  type: 'JSXAttribute'
};
const expectedShorthandFirstError = {
  message: 'Shorthand props must be listed before all other props',
  type: 'JSXAttribute'
};
const expectedShorthandLastError = {
  message: 'Shorthand props must be listed after all other props',
  type: 'JSXAttribute'
};
const expectedReservedFirstError = {
  message: 'Reserved props must be listed before all other props',
  type: 'JSXAttribute'
};
const expectedEmptyReservedFirstError = {
  message: 'A customized reserved first list must not be empty'
};
const expectedInvalidReservedFirstError = {
  message: 'A customized reserved first list must only contain a subset of React reserved props. Remove: notReserved'
};
const callbacksLastArgs = [{
  callbacksLast: true
}];
const ignoreCaseAndCallbackLastArgs = [{
  callbacksLast: true,
  ignoreCase: true
}];
const shorthandFirstArgs = [{
  shorthandFirst: true
}];
const shorthandLastArgs = [{
  shorthandLast: true
}];
const shorthandAndCallbackLastArgs = [{
  callbacksLast: true,
  shorthandLast: true
}];
const ignoreCaseArgs = [{
  ignoreCase: true
}];
const noSortAlphabeticallyArgs = [{
  noSortAlphabetically: true
}];
const sortAlphabeticallyArgs = [{
  noSortAlphabetically: false
}];
const reservedFirstAsBooleanArgs = [{
  reservedFirst: true
}];
const reservedFirstAsArrayArgs = [{
  reservedFirst: ['children', 'dangerouslySetInnerHTML', 'key']
}];
const reservedFirstWithNoSortAlphabeticallyArgs = [{
  noSortAlphabetically: true,
  reservedFirst: true
}];
const reservedFirstAsEmptyArrayArgs = [{
  reservedFirst: []
}];
const reservedFirstAsInvalidArrayArgs = [{
  reservedFirst: ['notReserved']
}];

ruleTester.run('jsx-sort-props', rule, {
  valid: [
    {code: '<App />;'},
    {code: '<App {...this.props} />;'},
    {code: '<App a b c />;'},
    {code: '<App {...this.props} a b c />;'},
    {code: '<App c {...this.props} a b />;'},
    {code: '<App a="c" b="b" c="a" />;'},
    {code: '<App {...this.props} a="c" b="b" c="a" />;'},
    {code: '<App c="a" {...this.props} a="c" b="b" />;'},
    {code: '<App A a />;'},
    // Ignoring case
    {code: '<App a A />;', options: ignoreCaseArgs},
    {code: '<App a B c />;', options: ignoreCaseArgs},
    {code: '<App A b C />;', options: ignoreCaseArgs},
    // Sorting callbacks below all other props
    {code: '<App a z onBar onFoo />;', options: callbacksLastArgs},
    {code: '<App z onBar onFoo />;', options: ignoreCaseAndCallbackLastArgs},
    // Sorting shorthand props before others
    {code: '<App a b="b" />;', options: shorthandFirstArgs},
    {code: '<App z a="a" />;', options: shorthandFirstArgs},
    {code: '<App x y z a="a" b="b" />;', options: shorthandFirstArgs},
    {code: '<App a="a" b="b" x y z />;', options: shorthandLastArgs},
    {
      code: '<App a="a" b="b" x y z onBar onFoo />;',
      options: shorthandAndCallbackLastArgs
    },
    // noSortAlphabetically
    {code: '<App a b />;', options: noSortAlphabeticallyArgs},
    {code: '<App b a />;', options: noSortAlphabeticallyArgs},
    // reservedFirst
    {
      code: '<App children={<App />} key={0} ref="r" a b c />',
      options: reservedFirstAsBooleanArgs
    },
    {
      code: '<App children={<App />} key={0} ref="r" a b c dangerouslySetInnerHTML={{__html: "EPR"}} />',
      options: reservedFirstAsBooleanArgs
    },
    {
      code: '<App children={<App />} key={0} a ref="r" />',
      options: reservedFirstAsArrayArgs
    },
    {
      code: '<App children={<App />} key={0} a dangerouslySetInnerHTML={{__html: "EPR"}} ref="r" />',
      options: reservedFirstAsArrayArgs
    },
    {
      code: '<App ref="r" key={0} children={<App />} b a c />',
      options: reservedFirstWithNoSortAlphabeticallyArgs
    },
    {
      code: '<div ref="r" dangerouslySetInnerHTML={{__html: "EPR"}} key={0} children={<App />} b a c />',
      options: reservedFirstWithNoSortAlphabeticallyArgs
    }
  ],
  invalid: [
    {
      code: '<App b a />;',
      errors: [expectedError],
      output: '<App a b />;'
    },
    {
      code: '<App {...this.props} b a />;',
      errors: [expectedError],
      output: '<App {...this.props} a b />;'
    },
    {
      code: '<App c {...this.props} b a />;',
      errors: [expectedError],
      output: '<App c {...this.props} a b />;'
    },
    {
      code: '<App a A />;',
      errors: [expectedError],
      output: '<App a A />;'
    },
    {
      code: '<App B a />;',
      options: ignoreCaseArgs,
      errors: [expectedError],
      output: '<App a B />;'
    },
    {
      code: '<App B A c />;',
      options: ignoreCaseArgs,
      errors: [expectedError],
      output: '<App A B c />;'
    },
    {
      code: '<App c="a" a="c" b="b" />;',
      output: '<App a="c" b="b" c="a" />;',
      errors: 2
    },
    {
      code: '<App {...this.props} c="a" a="c" b="b" />;',
      output: '<App {...this.props} a="c" b="b" c="a" />;',
      errors: 2
    },
    {
      code: '<App d="d" b="b" {...this.props} c="a" a="c" />;',
      output: '<App b="b" d="d" {...this.props} a="c" c="a" />;',
      errors: 2
    },
    {
      code: `
      <App
        a={true}
        z
        r
        _onClick={function(){}}
        onHandle={function(){}}
        {...this.props}
        b={false}
        {...otherProps}
      >
        {test}
      </App>
    `,
      output: `
      <App
        _onClick={function(){}}
        a={true}
        onHandle={function(){}}
        r
        z
        {...this.props}
        b={false}
        {...otherProps}
      >
        {test}
      </App>
    `,
      errors: 3
    },
    {
      code: '<App a z onFoo onBar />;',
      errors: [expectedError],
      options: callbacksLastArgs
    },
    {
      code: '<App a onBar onFoo z />;',
      errors: [expectedCallbackError],
      options: callbacksLastArgs
    },
    {
      code: '<App a="a" b />;',
      errors: [expectedShorthandFirstError],
      options: shorthandFirstArgs
    },
    {
      code: '<App z x a="a" />;',
      errors: [expectedError],
      options: shorthandFirstArgs
    },
    {
      code: '<App b a="a" />;',
      errors: [expectedShorthandLastError],
      options: shorthandLastArgs
    },
    {
      code: '<App a="a" onBar onFoo z x />;',
      errors: [shorthandAndCallbackLastArgs],
      options: shorthandLastArgs
    },
    {code: '<App b a />;', errors: [expectedError], options: sortAlphabeticallyArgs},
    // reservedFirst
    {
      code: '<App a key={1} />',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '
',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App ref="r" key={2} b />',
      options: reservedFirstAsBooleanArgs,
      errors: [expectedError]
    },
    {
      code: '<App key={2} b a />',
      options: reservedFirstAsBooleanArgs,
      output: '<App key={2} a b />',
      errors: [expectedError]
    },
    {
      code: '<App b a />',
      options: reservedFirstAsBooleanArgs,
      output: '<App a b />',
      errors: [expectedError]
    },
    {
      code: '<App dangerouslySetInnerHTML={{__html: "EPR"}} e key={2} b />',
      options: reservedFirstAsBooleanArgs,
      output: '<App key={2} b dangerouslySetInnerHTML={{__html: "EPR"}} e />',
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App key={3} children={<App />} />',
      options: reservedFirstAsArrayArgs,
      errors: [expectedError]
    },
    {
      code: '<App z ref="r" />',
      options: reservedFirstWithNoSortAlphabeticallyArgs,
      errors: [expectedReservedFirstError]
    },
    {
      code: '<App key={4} />',
      options: reservedFirstAsEmptyArrayArgs,
      errors: [expectedEmptyReservedFirstError]
    },
    {
      code: '<App key={5} />',
      options: reservedFirstAsInvalidArrayArgs,
      errors: [expectedInvalidReservedFirstError]
    }
  ]
});
<|endoftext|>


<commit_before>/**
* @module helpers
*/
var fs = require('fs');
var yaml = require('../../node_modules/js-yaml');
var configFile = '../../.lifter/lifter.yml'

/**
* Function that reads the lifter.yml file
* @function
* @memberof module:helpers
*
*/

var readYAML = function() {
  var out;
  try {
    var content = fs.readFileSync(configFile);
    out = yaml.safeLoad(content);
  } catch (e) {
    console.log(e.code, e.path);
    if (e.code === 'ENOENT') {
      console.log('... config file does not exist, please run lifter config');
    }
    process.exit();
  }
  return out;
}

module.exports = {
  readYAML: readYAML,
  configFile: configFile
}<commit_msg>add spawnSeries function to helpers<commit_after>/**
* @module helpers
*/
var fs = require('fs');
var yaml = require('../../node_modules/js-yaml');
var configFile = '../../.lifter/lifter.yml';

/**
* Function that reads the lifter.yml file
* @function
* @memberof module:helpers
*/

var readYAML = function() {
  var out;
  try {
    var content = fs.readFileSync(configFile);
    out = yaml.safeLoad(content);
  } catch (e) {
    console.log(e.code, e.path);
    if (e.code === 'ENOENT') {
      console.log('... config file does not exist, please run lifter config');
    }
    process.exit();
  }
  return out;
}

module.exports = {
  readYAML: readYAML,
  configFile: configFile
}<|endoftext|>


<commit_before>
var SeparableConv2d = {};

/**
 * Parser for decoding string array to SeparableConv2d entities.
 */
SeparableConv2d.Parser = class {

  /**
   * @param {string}              encodedString The encoded string.
   * @param {HTMLProgressElement} htmlProgress  If not null, reporting progress to this UI.
   */
  static * ToIntegerWeights(encodedString, htmlProgress) {
  }

  /**
   *
   * @param  {string[]} encodedStringArray     Every string is an encoded entity.
   * @param  {number}   encodedWeightCharCount Every weight is encoded as string with this length. (e.g. 5 )
   * @param  {number}   encodedWeightBase      Every weight is encoded by this base number. (e.g. 2 or 10 or 16 or 36)
   * @param  {number}   weightValueOffset      The value will be subtracted from the integer weight value.
   * @param  {number}   weightValueDivisor     Divide the integer weight value by this value for converting to floating-point number.
   * @param  {string}   htmlProgressTitle      The title of HTMLProgressElement for reporting progress. If null, no reporting.
   *
   * @return {Promise} A promise resolved as an Object[] which is the decoded entity for separableConv2d().
   *   The entity is an array of SeparableConv2d.Layer.
   */
  static StringArrayToSeparableConv2dEntities(
    encodedStringArray, encodedWeightCharCount, encodedWeightBase, weightValueOffset, weightValueDivisor,
    htmlProgressTitle) {

    function integerToFloat(integerWeight) {
      return ( integerWeight - weightValueOffset ) / weightValueDivisor;
    }

    let htmlProgress;

    function* (encodedStringArray) {
    }

    if (htmlProgressTitle) {
      htmlProgress = document.querySelector(`progress[title="${htmlProgressTitle}"`);
    }

    let p = new Promise( (resolve, reject) => {
      setTimeout(() => {
        // RegExp for extracting an encoded weight from the encoded string. (e.g. /(.{5})/g )
        let encodedWeightMatchRegExp = new RegExp("(.{" + encodedWeightCharCount + "})", "g");
        let integerWeightsArray = Array.from(encodedStringArray, str => {
          let encodedWeights = str.match(encodedWeightMatchRegExp);       // Split string.
          let integerWeights = new Float32Array( encodedWeights.length );
          encodedWeights.forEach( ( element, i ) => { integerWeights[ i ] =  parseInt(element, encodedWeightBase); } ); // Decode as integer.
          return integerWeights;
        } );

        let theEntities = integerWeightsArray.map( integerWeights => {
          let theEntity = [], weightIndex = 0, inChannels = 4; /* Suppose the first layer's input channel count is always RGBA 4 channels. */
          while ( weightIndex < integerWeights.length ) {
            let layer = new SeparableConv2d.Layer(integerWeights, weightIndex, inChannels, integerToFloat);
            theEntity.push(layer);
            inChannels =  layer.params.outChannels;  /* The next layer's input channel count is the previous layer's output channel count. */
            weightIndex = layer.weightIndexEnd;
          }
          return theEntity;
        });

        return theEntities;
      });
    });
    return p;
  }

}

/**
 * A CNN layer contains three filters: depthwise, pointwise and bias.
 */
SeparableConv2d.Layer = class {

  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   * @param {number}       inChannels         The input channel count.
   * @param {Function}     integerToFloat     An function which input an integer and return a floating-point number.
   */
  constructor(integerWeights, weightIndexBegin, inChannels, integerToFloat) {
    this.integerWeights =   integerWeights;
    this.weightIndexBegin = weightIndexBegin;

    this.params = new SeparableConv2d.Layer.Params(integerWeights, weightIndexBegin);
    this.depthwise = new SeparableConv2d.Layer.Filter(
      integerWeights, this.params.weightIndexEnd,
      [this.params.filterHeight, this.params.filterWidth, inChannels, this.params.channelMultiplier], integerToFloat );

    this.pointwise = new SeparableConv2d.Layer.Filter(
      integerWeights, this.depthwise.weightIndexEnd,
      [1, 1, inChannels * this.params.channelMultiplier, this.params.outChannels], integerToFloat );

    this.bias = new SeparableConv2d.Layer.Filter(
      integerWeights, this.pointwise.weightIndexEnd,
      [1, 1, this.params.outChannels], integerToFloat );

    this.weightIndexEnd = this.bias.weightIndexEnd;
  }

}

/**
 * A class for the CNN layer parameters.
 */
SeparableConv2d.Layer.Params = class {
  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   */
  constructor(integerWeights, weightIndexBegin) {
    this.weightIndexBegin = weightIndexBegin;
    this.weightIndexEnd =   weightIndexBegin + SeparableConv2d.Layer.ParamNames.length;

    if ( this.weightIndexEnd > integerWeights.length )
      return;

    SeparableConv2d.Layer.ParamNames.forEach( ( paramName, i ) => this[ paramName ] = integerWeights[ weightIndexBegin + i ] );
  }
}

SeparableConv2d.Layer.ParamNames = [
  "filterHeight", "filterWidth", "channelMultiplier", "dilationHeight", "dilationWidth", "outChannels"];

/**
 * A class for the CNN (depthwise, pointwise and bias) filter.
 */
SeparableConv2d.Layer.Filter = class {

  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   * @param {number[]}     shape              The filter shape (element count for every dimension). The shape.length is dimension.
   * @param {Function}     integerToFloat     An function which input an integer and return a floating-point number.
   */
  constructor(integerWeights, weightIndexBegin, shape, integerToFloat) {
    this.shape =            shape;
    this.weightCount =      shape.reduce( ( accumulator, currentValue ) => accumulator * currentValue );
    this.weightIndexBegin = weightIndexBegin;
    this.weightIndexEnd =   weightIndexBegin + this.weightCount;  // Exclusive. As the next filter's begin.

    if ( this.weightIndexEnd > integerWeights.length ) {
      return; // No filter when shape is too large.
    }

    let byteOffset = Float32Array.BYTES_PER_ELEMENT * this.weightIndexBegin;
    this.filter =    new Float32Array( integerWeights.buffer, byteOffset, this.weightCount ); // Share the underlying array buffer.
    this.filter.forEach( ( element, i, array ) => array[ i ] = integerToFloat( element ) ); // Convert weight to floating-point number.
  }
}
<commit_msg>(Temp generator)<commit_after>
var SeparableConv2d = {};

/**
 * Parser for decoding string array to SeparableConv2d entities.
 */
SeparableConv2d.Parser = class {

  /**
   *
   * @param  {number}   encodedWeightCharCount Every weight is encoded as string with this length. (e.g. 5 )
   * @param  {number}   encodedWeightBase      Every weight is encoded by this base number. (e.g. 2 or 10 or 16 or 36)
   * @param  {number}   weightValueOffset      The value will be subtracted from the integer weight value.
   * @param  {number}   weightValueDivisor     Divide the integer weight value by this value for converting to floating-point number.
   * @param  {string}   htmlProgressTitle      The title of HTMLProgressElement for reporting progress. If null, no reporting.
   */
  constructor(encodedWeightCharCount, encodedWeightBase, weightValueOffset, weightValueDivisor, htmlProgressTitle) {
    this.encodedWeightCharCount = encodedWeightCharCount;
    this.encodedWeightBase =      encodedWeightBase;
    this.weightValueOffset =      weightValueOffset;
    this.weightValueDivisor =     weightValueDivisor;
    this.htmlProgressTitle =      htmlProgressTitle;

    this.htmlProgress = null;
    if (htmlProgressTitle) {
      htmlProgress = document.querySelector(`progress[title="${htmlProgressTitle}"]`);
    }
  }

  /**
   * @param {integer} integerWeight The integer which will be converted to floating-point number by subtract and divide.
   * @return The floating-point number.
   */
  integerToFloat(integerWeight) {
    return ( integerWeight - this.weightValueOffset ) / this.weightValueDivisor;
  }

  /**
   * When progress is advanced, call this method to display in UI.
   * @param {integer} advancedVolume The volume which will be added to the HTMLProgressElement.value.
   */
  reportProgressAdvance(advancedVolume) {
    if (this.htmlProgress) {
      this.htmlProgress.value += advancedVolume;
    }
  }

  /**
   * @param {function} promiseTimeoutCallback
   *   The function to be scheduled (by setTimeout()) to execute with two parameters (resolve, reject). Inside the callback,
   *   call resolve() or reject() will resolve or reject the promise.
   *
   * @return A promise for scheduling to run the promiseTimeoutCallback.
   */
  promiseTimeout(promiseTimeoutCallback) {
    return new Promise( (resolve, reject) => {
      setTimeout(promiseTimeoutCallback, 0, resolve, reject);
    });
  }

  /**
   * @param {string[]}            encodedStringArray     Every string is an encoded entity.
   *
   */
  * memoryGenerator(encodedStringArray) {
    this.entityCount =         encodedStringArray.length;
    this.integerWeightsArray = new Array(encodedStringArray.length);
    for (let i = 0; i < encodedStringArray.length; ++i) {
      yield ( this.integerWeightsArray[ i ] = new Float32Array( encodedStringArray[ i ].length ) );
    }
  }

  /**
   * @param {string}              encodedString The encoded string.
   */
  * ToIntegerWeights(encodedString) {
  }

  /**
   * @param {string[]}            encodedStringArray     Every string is an encoded entity.
   */
  * entityGenerator(encodedStringArray) {
    let theMemoryGenerator = memoryGenerator(encodedStringArray);

    promiseTimeout( (resolve, reject) => {
      for (let integerWeights of theMemoryGenerator) {
//!!! ...unfinished...
        for (??? let entity of theEntityGenerator) {
        }
      }
    });

  }

  /**
   *
   * @param  {string[]} encodedStringArray     Every string is an encoded entity.
   *
   * @return {Promise} A promise resolved as an Object[] which is the decoded entity for separableConv2d().
   *   The entity is an array of SeparableConv2d.Layer.
   */
  StringArrayToSeparableConv2dEntities(encodedStringArray) {
    let theEntityGenerator = entityGenerator(encodedStringArray);

//!!! ...unfinished...
    promiseTimeout( (resolve, reject) => {
      for (let entity of theEntityGenerator) {
      }
    });

//!!! ...unfinished...

    this.entityCount =            encodedStringArray.length;
    this.integerWeightsArray =    new Array(encodedStringArray.length);

    let integerToFloat = this.integerToFloat.bind(this);

    let p = new Promise( (resolve, reject) => {
      setTimeout(() => {
        // RegExp for extracting an encoded weight from the encoded string. (e.g. /(.{5})/g )
        let encodedWeightMatchRegExp = new RegExp("(.{" + encodedWeightCharCount + "})", "g");
        let integerWeightsArray = Array.from(encodedStringArray, str => {
          let encodedWeights = str.match(encodedWeightMatchRegExp);       // Split string.
          let integerWeights = new Float32Array( encodedWeights.length );
          encodedWeights.forEach( ( element, i ) => { integerWeights[ i ] =  parseInt(element, encodedWeightBase); } ); // Decode as integer.
          return integerWeights;
        } );

        let theEntities = integerWeightsArray.map( integerWeights => {
          let theEntity = [], weightIndex = 0, inChannels = 4; /* Suppose the first layer's input channel count is always RGBA 4 channels. */
          while ( weightIndex < integerWeights.length ) {
            let layer = new SeparableConv2d.Layer(integerWeights, weightIndex, inChannels, integerToFloat);
            theEntity.push(layer);
            inChannels =  layer.params.outChannels;  /* The next layer's input channel count is the previous layer's output channel count. */
            weightIndex = layer.weightIndexEnd;
          }
          return theEntity;
        });

        return theEntities;
      });
    });
    return p;
  }

}

/**
 * A CNN layer contains three filters: depthwise, pointwise and bias.
 */
SeparableConv2d.Layer = class {

  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   * @param {number}       inChannels         The input channel count.
   * @param {Function}     integerToFloat     An function which input an integer and return a floating-point number.
   */
  constructor(integerWeights, weightIndexBegin, inChannels, integerToFloat) {
    this.integerWeights =   integerWeights;
    this.weightIndexBegin = weightIndexBegin;

    this.params = new SeparableConv2d.Layer.Params(integerWeights, weightIndexBegin);
    this.depthwise = new SeparableConv2d.Layer.Filter(
      integerWeights, this.params.weightIndexEnd,
      [this.params.filterHeight, this.params.filterWidth, inChannels, this.params.channelMultiplier], integerToFloat );

    this.pointwise = new SeparableConv2d.Layer.Filter(
      integerWeights, this.depthwise.weightIndexEnd,
      [1, 1, inChannels * this.params.channelMultiplier, this.params.outChannels], integerToFloat );

    this.bias = new SeparableConv2d.Layer.Filter(
      integerWeights, this.pointwise.weightIndexEnd,
      [1, 1, this.params.outChannels], integerToFloat );

    this.weightIndexEnd = this.bias.weightIndexEnd;
  }

}

/**
 * A class for the CNN layer parameters.
 */
SeparableConv2d.Layer.Params = class {
  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   */
  constructor(integerWeights, weightIndexBegin) {
    this.weightIndexBegin = weightIndexBegin;
    this.weightIndexEnd =   weightIndexBegin + SeparableConv2d.Layer.ParamNames.length;

    if ( this.weightIndexEnd > integerWeights.length )
      return;

    SeparableConv2d.Layer.ParamNames.forEach( ( paramName, i ) => this[ paramName ] = integerWeights[ weightIndexBegin + i ] );
  }
}

SeparableConv2d.Layer.ParamNames = [
  "filterHeight", "filterWidth", "channelMultiplier", "dilationHeight", "dilationWidth", "outChannels"];

/**
 * A class for the CNN (depthwise, pointwise and bias) filter.
 */
SeparableConv2d.Layer.Filter = class {

  /**
   * @param {Float32Array} integerWeights     An Float32Array whose values are all integers.
   * @param {number}       weightIndexBegin   The position to start to decode from the integerWeights.
   * @param {number[]}     shape              The filter shape (element count for every dimension). The shape.length is dimension.
   * @param {Function}     integerToFloat     An function which input an integer and return a floating-point number.
   */
  constructor(integerWeights, weightIndexBegin, shape, integerToFloat) {
    this.shape =            shape;
    this.weightCount =      shape.reduce( ( accumulator, currentValue ) => accumulator * currentValue );
    this.weightIndexBegin = weightIndexBegin;
    this.weightIndexEnd =   weightIndexBegin + this.weightCount;  // Exclusive. As the next filter's begin.

    if ( this.weightIndexEnd > integerWeights.length ) {
      return; // No filter when shape is too large.
    }

    let byteOffset = Float32Array.BYTES_PER_ELEMENT * this.weightIndexBegin;
    this.filter =    new Float32Array( integerWeights.buffer, byteOffset, this.weightCount ); // Share the underlying array buffer.
    this.filter.forEach( ( element, i, array ) => array[ i ] = integerToFloat( element ) ); // Convert weight to floating-point number.
  }
}
<|endoftext|>


<commit_before>(function($) {
	function bytesToSize(bytes) {
		var k = 1000;
		var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
		if (bytes === 0) return '0 Bytes';
		var i = parseInt(Math.floor(Math.log(bytes) / Math.log(k)),10);
		return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
	}
	var loadFiles = function(path){
		Stevenson.ui.Loader.display('Loading files...', 100);
		$('#grid-container').html('');
		$('#grid-container').mustache('grid', {});
		Stevenson.repo.getFiles({
			path: path,
			success: function(files){
				window.location.hash = path;
				$('#files').attr('data-path', path);
				$('.breadcrumb .path').html(path);
				$('#files tbody').html('');
				$.each(files, function(index, file){
					if(file.path.indexOf('_config') != 0 && file.path.indexOf('_layouts') != 0 && file.path.indexOf('_editors') != 0 && file.path.indexOf('_schemas') != 0){
					//if(file.path.indexOf('.jctx') > 0) {
						file.size = file.size ? bytesToSize(file.size) : '';
						$('#files tbody').mustache('file', file);
						}
				});
				$('#files input[type=checkbox]').each(function(index, item){
						$(item).removeAttr('checked');
						if (index == $('#files input[type=checkbox]').length - 1) {
							$(item).attr("checked", true);
						}
					});

				$('.folder-close').click(function(){
					window.location.hash = $(this).attr('data-path');
				});
				$('#files .file').click(function(){
					$('#files input[type=checkbox]').each(function(index, item){
						$(item).removeAttr('checked');
					});
					$(this).find('input[type=checkbox]').each(function(idx, elem){
						$(elem).attr('checked','checked');
					})
				});
				$('#files input[type=checkbox]').click(function(){
					var checked = this;
					$('#files input[type=checkbox]').each(function(index, item){
						if(item != checked){
							$(item).removeAttr('checked');
						}
					});
				});
				$('#files').dataTable();
				Stevenson.ui.Loader.hide();

//				$('.file-edit').click();
//				Stevenson.ui.Loader.display('Loading editor...', 100);
//				var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
//				window.location = Stevenson.Account.siteBaseURL + '/cms/edit.html#' + path;
			},
			error: function(message){
				Stevenson.ui.Loader.hide();
				Stevenson.ui.Messages.displayError('Unable to load branches: ' + message);
			}
		});
	};
	Stevenson.ext.afterInit(function() {
		Stevenson.log.info('Initializing files');

		$('.breadcrumb .repo').html(Stevenson.Account.repo);

		var path = window.location.hash;
		if(path != ''){
			path = path.substr(1);
		}
		$('.breadcrumb .path').html(path);
		loadFiles(path);

	});
	$(document).ready(function(){

		/*
		 * Listen for the hash to change
		 */
		window.addEventListener("hashchange", function(){
			var path = window.location.hash;
			if(path != ''){
				path = path.substr(1);
			}
			loadFiles(path);
		}, false);

		/**
		 * Support creating new files
		 */
		$('.main-menu .new').click(function(){
			$('body').mustache('new-file', {});
			$('#new-file-modal').modal({
				show: true
			});
			$('#new-file-modal .no').click(function() {
				$('#new-file-modal').modal('hide').remove();
			});
			$('form#new-file').submit(function() {
				$('#new-file-modal .modal-body .alert-error').remove();
				var name = $('#file-name').val();
				if(name != ''){
					var path = $('#files').attr('data-path');
					var filePath = path + "/" + name;
					if(path == ""){
						filePath = name;
					}
					$('#new-file-modal .btn, #new-file-modal input').attr('disabled','disabled');
					Stevenson.repo.savePage({
						path: filePath,
						page: {
							content:''
						},
						message: 'Creating new page ' + name,
						success: function(){
							window.location = Stevenson.Account.siteBaseURL + '/cms/edit.html?new=true#'+filePath;
						},
						error: function(msg){
							$('#new-file-modal .btn, #new-file-modal input').removeAttr('disabled');
							$('#new-file-name').addClass('error');
							$('#new-file-modal .modal-body').prepend('
Error creating page: '+msg+'.
');
						}
					});
				} else {
					$('#new-file-name').addClass('error');
					$('#file-name-modal .modal-body').prepend('
Please enter a file name.
');
				}
				return false;
			});
		});

		/**
		 * Support editing files
		 */
		$('.file-edit').click(function(){
			Stevenson.ui.Loader.display('Loading editor...', 100);
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			if (path.indexOf(Stevenson.Account.schemaExtension) >= 0) {
				window.location = Stevenson.Account.siteBaseURL + '/cms/cohortex_edit.html#' + path;
			} else {
				window.location = Stevenson.Account.siteBaseURL + '/cms/edit.html#' + path;
			}
			return false;
		});

		/**
		 * Support deleting files
		 */
		$('.file-delete').click(function(){
			$('#delete-file-modal').modal({
				show: true
			});
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#delete-file-modal .yes').click(function(){
				$('#delete-file-modal').modal('hide');
				Stevenson.ui.Loader.display('Deleting...', 100);
				Stevenson.repo.deleteFile({
					path: path,
					success: function(path){
						Stevenson.ui.Messages.displayMessage("Deleted file: "+path);
						Stevenson.ui.Loader.hide();
						var path = window.location.hash;
						if(path != ''){
							path = path.substr(1);
						}
						loadFiles(path);
					},
					error: function(message){
						Stevenson.ui.Messages.displayError("Failed to delete file: "+path+" due to error "+message);
						Stevenson.ui.Loader.hide();
					}
				});
				return false;
			});
			$('#delete-file-modal .no').click(function(){
				$('#loading-modal').modal('hide');
				return false;
			});
		});

		/**
		 * Support moving files
		 */
		$('.file-move').click(function(){
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#move-modal input').val(path);
			$('#move-modal').modal({
				show: true
			});
		});
		$('#move-modal .no').click(function(){
			$('#move-modal').modal('hide');
			return false;
		});
		$('#move-modal .yes').click(function(){
			$('#move-modal').modal('hide');
			Stevenson.ui.Loader.display('Moving file...', 100);
			var oldPath = $('#move-modal #old-path').val();
			var newPath = $('#move-modal #new-path').val();
			Stevenson.repo.moveFile({
				oldPath: oldPath,
				newPath: newPath,
				success: function(path){
					Stevenson.ui.Messages.displayMessage("Moved file: "+oldPath +' to '+newPath);
					Stevenson.ui.Loader.hide();
					var path = window.location.hash;
					if(path != ''){
						path = path.substr(1);
					}
					loadFiles(path);
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to move file from '"+oldPath+"' to '"+newPath+"' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
			return false;
		});

		/**
		 * Support copying files
		 */
		$('.file-copy').click(function(){
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#copy-modal input').val(path);
			$('#copy-modal').modal({
				show: true
			});
		});
		$('#copy-modal .no').click(function(){
			$('#copy-modal').modal('hide');
			return false;
		});
		$('#copy-modal .yes').click(function(){
			$('#copy-modal').modal('hide');
			Stevenson.ui.Loader.display('Copying file...', 100);
			var oldPath = $('#copy-modal #old-path').val();
			var newPath = $('#copy-modal #new-path').val();
			Stevenson.repo.copyFile({
				oldPath: oldPath,
				newPath: newPath,
				success: function(path){
					Stevenson.ui.Messages.displayMessage("Copied file: "+oldPath +' to '+newPath);
					Stevenson.ui.Loader.hide();
					var path = window.location.hash;
					if(path != ''){
						path = path.substr(1);
					}
					loadFiles(path);
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to copy file from '"+oldPath+"' to '"+newPath+"' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
			return false;
		});

		/**
		 * Support File Uploads
		 */
		$('.main-menu .file-upload').click(function(){
			$('#upload-modal').remove();
			var path = $('#files').attr('data-path');

			$('body').mustache('upload', {
				path: path
			});

			$('#upload-modal .no').click(function() {
				$('#upload-modal').modal('hide').remove();
			});
			$('#upload-modal form').submit(function(){
				$('#upload-modal').modal('hide');
				Stevenson.ui.Loader.display('Uploading file...', 100);

				var reader = new FileReader();
				reader.onload = function(e) {
					var name = $('#upload-modal input[name=file]').val().split(/(\\|\/)/g).pop();
					var page = new Page($('#upload-modal input[name=path]').val()+'/'+name, reader.result);
					Stevenson.repo.savePage({
						page: page,
						path: page.path,
						message: "Adding file: "+name,
						success: function(){
							Stevenson.ui.Messages.displayMessage("Successfully uploaded file "+name);
							Stevenson.ui.Loader.hide();
							loadFiles($('#files').attr('data-path'));
						},
						error: function(message){
							Stevenson.ui.Messages.displayError("Failed to upload file "+name+" due to exception: "+message);
							Stevenson.ui.Loader.hide();
						}

					});
				}
				reader.readAsArrayBuffer(document.getElementById('upload-file-input').files[0]);
				return false;
			});
			$('#upload-modal').modal({
				show: true
			});
			return false;
		});

		/**
		 * Support viewing a file's history
		 */
		$('.main-menu .view-history').click(function(){
			Stevenson.ui.Loader.display('Loading file history...', 100);
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			if(!path){
				path = "";
			}
			Stevenson.repo.getHistory({
				path: path,
				success: function(commits){
					Stevenson.ui.Messages.displayMessage("Loaded history of file: /" + path);
					Stevenson.ui.Loader.hide();
					$('body').mustache('history', {
						file: "/" + path
					});
					$.each(commits, function(idx, commit) {
						$('#history-modal .history-container').mustache('history-item', commit);
					});
					$('#history-modal').modal({
						show: true
					});
					$('#history-modal .no').click(function() {
						$('#history-modal').modal('hide').remove();
					});
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to get history of file '" + path + "' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
		});
	});
})(jQuery);
<commit_msg>- Remove cohortex old code (don’t  check the last file)<commit_after>(function($) {
	function bytesToSize(bytes) {
		var k = 1000;
		var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
		if (bytes === 0) return '0 Bytes';
		var i = parseInt(Math.floor(Math.log(bytes) / Math.log(k)),10);
		return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
	}
	var loadFiles = function(path){
		Stevenson.ui.Loader.display('Loading files...', 100);
		$('#grid-container').html('');
		$('#grid-container').mustache('grid', {});
		Stevenson.repo.getFiles({
			path: path,
			success: function(files){
				window.location.hash = path;
				$('#files').attr('data-path', path);
				$('.breadcrumb .path').html(path);
				$('#files tbody').html('');
				$.each(files, function(index, file){
					if (file.path.indexOf('_config') != 0 && file.path.indexOf('_layouts') != 0 && file.path.indexOf('_editors') != 0){
						file.size = file.size ? bytesToSize(file.size) : '';
						$('#files tbody').mustache('file', file);
						}
				});
				$('#files input[type=checkbox]').each(function(index, item){
						$(item).removeAttr('checked');
					});

				$('.folder-close').click(function(){
					window.location.hash = $(this).attr('data-path');
				});
				$('#files .file').click(function(){
					$('#files input[type=checkbox]').each(function(index, item){
						$(item).removeAttr('checked');
					});
					$(this).find('input[type=checkbox]').each(function(idx, elem){
						$(elem).attr('checked','checked');
					})
				});
				$('#files input[type=checkbox]').click(function(){
					var checked = this;
					$('#files input[type=checkbox]').each(function(index, item){
						if(item != checked){
							$(item).removeAttr('checked');
						}
					});
				});
				$('#files').dataTable();
				Stevenson.ui.Loader.hide();

			},
			error: function(message){
				Stevenson.ui.Loader.hide();
				Stevenson.ui.Messages.displayError('Unable to load branches: ' + message);
			}
		});
	};
	Stevenson.ext.afterInit(function() {
		Stevenson.log.info('Initializing files');

		$('.breadcrumb .repo').html(Stevenson.Account.repo);

		var path = window.location.hash;
		if(path != ''){
			path = path.substr(1);
		}
		$('.breadcrumb .path').html(path);
		loadFiles(path);

	});
	$(document).ready(function(){

		/*
		 * Listen for the hash to change
		 */
		window.addEventListener("hashchange", function(){
			var path = window.location.hash;
			if(path != ''){
				path = path.substr(1);
			}
			loadFiles(path);
		}, false);

		/**
		 * Support creating new files
		 */
		$('.main-menu .new').click(function(){
			$('body').mustache('new-file', {});
			$('#new-file-modal').modal({
				show: true
			});
			$('#new-file-modal .no').click(function() {
				$('#new-file-modal').modal('hide').remove();
			});
			$('form#new-file').submit(function() {
				$('#new-file-modal .modal-body .alert-error').remove();
				var name = $('#file-name').val();
				if(name != ''){
					var path = $('#files').attr('data-path');
					var filePath = path + "/" + name;
					if(path == ""){
						filePath = name;
					}
					$('#new-file-modal .btn, #new-file-modal input').attr('disabled','disabled');
					Stevenson.repo.savePage({
						path: filePath,
						page: {
							content:''
						},
						message: 'Creating new page ' + name,
						success: function(){
							window.location = Stevenson.Account.siteBaseURL + '/cms/edit.html?new=true#'+filePath;
						},
						error: function(msg){
							$('#new-file-modal .btn, #new-file-modal input').removeAttr('disabled');
							$('#new-file-name').addClass('error');
							$('#new-file-modal .modal-body').prepend('
Error creating page: '+msg+'.
');
						}
					});
				} else {
					$('#new-file-name').addClass('error');
					$('#file-name-modal .modal-body').prepend('
Please enter a file name.
');
				}
				return false;
			});
		});

		/**
		 * Support editing files
		 */
		$('.file-edit').click(function(){
			Stevenson.ui.Loader.display('Loading editor...', 100);
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			if (path.indexOf(Stevenson.Account.schemaExtension) >= 0) {
				window.location = Stevenson.Account.siteBaseURL + '/cms/cohortex_edit.html#' + path;
			} else {
				window.location = Stevenson.Account.siteBaseURL + '/cms/edit.html#' + path;
			}
			return false;
		});

		/**
		 * Support deleting files
		 */
		$('.file-delete').click(function(){
			$('#delete-file-modal').modal({
				show: true
			});
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#delete-file-modal .yes').click(function(){
				$('#delete-file-modal').modal('hide');
				Stevenson.ui.Loader.display('Deleting...', 100);
				Stevenson.repo.deleteFile({
					path: path,
					success: function(path){
						Stevenson.ui.Messages.displayMessage("Deleted file: "+path);
						Stevenson.ui.Loader.hide();
						var path = window.location.hash;
						if(path != ''){
							path = path.substr(1);
						}
						loadFiles(path);
					},
					error: function(message){
						Stevenson.ui.Messages.displayError("Failed to delete file: "+path+" due to error "+message);
						Stevenson.ui.Loader.hide();
					}
				});
				return false;
			});
			$('#delete-file-modal .no').click(function(){
				$('#loading-modal').modal('hide');
				return false;
			});
		});

		/**
		 * Support moving files
		 */
		$('.file-move').click(function(){
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#move-modal input').val(path);
			$('#move-modal').modal({
				show: true
			});
		});
		$('#move-modal .no').click(function(){
			$('#move-modal').modal('hide');
			return false;
		});
		$('#move-modal .yes').click(function(){
			$('#move-modal').modal('hide');
			Stevenson.ui.Loader.display('Moving file...', 100);
			var oldPath = $('#move-modal #old-path').val();
			var newPath = $('#move-modal #new-path').val();
			Stevenson.repo.moveFile({
				oldPath: oldPath,
				newPath: newPath,
				success: function(path){
					Stevenson.ui.Messages.displayMessage("Moved file: "+oldPath +' to '+newPath);
					Stevenson.ui.Loader.hide();
					var path = window.location.hash;
					if(path != ''){
						path = path.substr(1);
					}
					loadFiles(path);
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to move file from '"+oldPath+"' to '"+newPath+"' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
			return false;
		});

		/**
		 * Support copying files
		 */
		$('.file-copy').click(function(){
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			$('#copy-modal input').val(path);
			$('#copy-modal').modal({
				show: true
			});
		});
		$('#copy-modal .no').click(function(){
			$('#copy-modal').modal('hide');
			return false;
		});
		$('#copy-modal .yes').click(function(){
			$('#copy-modal').modal('hide');
			Stevenson.ui.Loader.display('Copying file...', 100);
			var oldPath = $('#copy-modal #old-path').val();
			var newPath = $('#copy-modal #new-path').val();
			Stevenson.repo.copyFile({
				oldPath: oldPath,
				newPath: newPath,
				success: function(path){
					Stevenson.ui.Messages.displayMessage("Copied file: "+oldPath +' to '+newPath);
					Stevenson.ui.Loader.hide();
					var path = window.location.hash;
					if(path != ''){
						path = path.substr(1);
					}
					loadFiles(path);
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to copy file from '"+oldPath+"' to '"+newPath+"' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
			return false;
		});

		/**
		 * Support File Uploads
		 */
		$('.main-menu .file-upload').click(function(){
			$('#upload-modal').remove();
			var path = $('#files').attr('data-path');

			$('body').mustache('upload', {
				path: path
			});

			$('#upload-modal .no').click(function() {
				$('#upload-modal').modal('hide').remove();
			});
			$('#upload-modal form').submit(function(){
				$('#upload-modal').modal('hide');
				Stevenson.ui.Loader.display('Uploading file...', 100);

				var reader = new FileReader();
				reader.onload = function(e) {
					var name = $('#upload-modal input[name=file]').val().split(/(\\|\/)/g).pop();
					var page = new Page($('#upload-modal input[name=path]').val()+'/'+name, reader.result);
					Stevenson.repo.savePage({
						page: page,
						path: page.path,
						message: "Adding file: "+name,
						success: function(){
							Stevenson.ui.Messages.displayMessage("Successfully uploaded file "+name);
							Stevenson.ui.Loader.hide();
							loadFiles($('#files').attr('data-path'));
						},
						error: function(message){
							Stevenson.ui.Messages.displayError("Failed to upload file "+name+" due to exception: "+message);
							Stevenson.ui.Loader.hide();
						}

					});
				}
				reader.readAsArrayBuffer(document.getElementById('upload-file-input').files[0]);
				return false;
			});
			$('#upload-modal').modal({
				show: true
			});
			return false;
		});

		/**
		 * Support viewing a file's history
		 */
		$('.main-menu .view-history').click(function(){
			Stevenson.ui.Loader.display('Loading file history...', 100);
			var path = $('#files input[type=checkbox]:checked').parents('tr').attr('data-path');
			if(!path){
				path = "";
			}
			Stevenson.repo.getHistory({
				path: path,
				success: function(commits){
					Stevenson.ui.Messages.displayMessage("Loaded history of file: /" + path);
					Stevenson.ui.Loader.hide();
					$('body').mustache('history', {
						file: "/" + path
					});
					$.each(commits, function(idx, commit) {
						$('#history-modal .history-container').mustache('history-item', commit);
					});
					$('#history-modal').modal({
						show: true
					});
					$('#history-modal .no').click(function() {
						$('#history-modal').modal('hide').remove();
					});
				},
				error: function(message){
					Stevenson.ui.Messages.displayError("Failed to get history of file '" + path + "' due to error "+message);
					Stevenson.ui.Loader.hide();
				}
			});
		});
	});
})(jQuery);
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var calcStats = function(data) {

  var listIsOfLength0 = data.length === 0;

  var min = listIsOfLength0 ? undefined : data.reduce(function(x,y) { return Math.min(x,y); });
  var max = listIsOfLength0 ? undefined : data.reduce(function(x,y) { return Math.max(x,y); });
  var cnt = listIsOfLength0 ? 0 : data.reduce(function(x,y) { return  x + 1; }, 0);
  var sum = listIsOfLength0 ? 0 : data.reduce(function(x,y) { return x + y; });

  return {
    average: listIsOfLength0 ? undefined : (sum / cnt),
    count: cnt,
    minValue: min,
    maxValue: max
  };
};

var testMaximum = function() {
  var emptyList = calcStats([]);
  assert.equal(undefined, emptyList.maxValue);

  var singletonList = calcStats([1]);
  assert.equal(1, singletonList.maxValue);
};

var testMinimum = function() {
  var emptyList = calcStats([]);
  assert.equal(undefined, emptyList.minValue);

  var singletonList = calcStats([1]);
  assert.equal(1, singletonList.minValue);

  var zeroMin = calcStats([0]);
  assert.equal(0, zeroMin.minValue);

  var multiple = calcStats([0,1,2,3,4,5]);
  assert.equal(0, multiple.minValue);
};

var testNumberOfElements = function() {
  assert.equal(0, calcStats([]).count);
  assert.equal(1, calcStats([1]).count);
  assert.equal(5, calcStats([5,6,7,8,9]).count);
};

var testAverage = function() {
  var stats = calcStats([]);
  assert.equal(undefined, stats.average);

  var zero = calcStats([0]);
  assert.equal(0, zero.average);

  var three = calcStats([0,1,2]);
  assert.equal(1, three.average);
};

var test = function() {
  testMinimum();
  testMaximum();
  testNumberOfElements();
  testAverage();

  console.log(calcStats([6,9,15,-2,92,11]));
};

test();

// Retrospectives
// - using fold is nice
// - you can use .reduce
// - but reduce is weird, takes 4 arguments (not 2)
<commit_msg>final retro note<commit_after>"use strict";

var assert = require('assert');

var calcStats = function(data) {

  var listIsOfLength0 = data.length === 0;

  var min = listIsOfLength0 ? undefined : data.reduce(function(x,y) { return Math.min(x,y); });
  var max = listIsOfLength0 ? undefined : data.reduce(function(x,y) { return Math.max(x,y); });
  var cnt = listIsOfLength0 ? 0 : data.reduce(function(x,y) { return  x + 1; }, 0);
  var sum = listIsOfLength0 ? 0 : data.reduce(function(x,y) { return x + y; });

  return {
    average: listIsOfLength0 ? undefined : (sum / cnt),
    count: cnt,
    minValue: min,
    maxValue: max
  };
};

var testMaximum = function() {
  var emptyList = calcStats([]);
  assert.equal(undefined, emptyList.maxValue);

  var singletonList = calcStats([1]);
  assert.equal(1, singletonList.maxValue);
};

var testMinimum = function() {
  var emptyList = calcStats([]);
  assert.equal(undefined, emptyList.minValue);

  var singletonList = calcStats([1]);
  assert.equal(1, singletonList.minValue);

  var zeroMin = calcStats([0]);
  assert.equal(0, zeroMin.minValue);

  var multiple = calcStats([0,1,2,3,4,5]);
  assert.equal(0, multiple.minValue);
};

var testNumberOfElements = function() {
  assert.equal(0, calcStats([]).count);
  assert.equal(1, calcStats([1]).count);
  assert.equal(5, calcStats([5,6,7,8,9]).count);
};

var testAverage = function() {
  var stats = calcStats([]);
  assert.equal(undefined, stats.average);

  var zero = calcStats([0]);
  assert.equal(0, zero.average);

  var three = calcStats([0,1,2]);
  assert.equal(1, three.average);
};

var test = function() {
  testMinimum();
  testMaximum();
  testNumberOfElements();
  testAverage();

  console.log(calcStats([6,9,15,-2,92,11]));
};

test();

// Retrospectives
// - using fold is nice
// - you can use .reduce
// - but reduce is weird, takes 4 arguments (not 2)
// - this does make multiple passes through the list, but that's
// easily fixed
<|endoftext|>