<commit_before>var esClient  = new(require('elastical').Client)
  , generator = new(require('./mapping-generator'))
  , events    = require('events');

module.exports = function elasticSearchPlugin(schema, options){
  var indexedFields = getIndexedFields(schema)
    , indexName = options && options.index
    , typeName  = options && options.type
    , alwaysHydrate = options && options.hydrate
    , _mapping = null;

  schema.post('remove', function(){
    var model = this;
    setIndexNameIfUnset(model.constructor.modelName);
    deleteByMongoId(esClient, model, indexName, typeName, 3);
  });

  function setIndexNameIfUnset(model){
    var modelName = model.toLowerCase();
    if(!indexName){
      indexName = modelName + "s";
    }
    if(!typeName){
      typeName = modelName;
    }
  }

  /**
   * Create the mapping. Takes a callback that will be called once
   * the mapping is created
   */
  schema.statics.createMapping = function(cb){
    setIndexNameIfUnset(this.modelName);
    createMappingIfNotPresent(indexName, typeName, schema, cb);
  }
  /**
   * Save in elastic search on save.
   */
  schema.post('save', function(){
    var model = this;
    setIndexNameIfUnset(model.constructor.modelName);
    esClient.index(indexName, typeName, serialize(model, indexedFields), {id:model._id.toString()}, function(err, res){
      model.emit('es-indexed', err, res);
    });
  });

  /**
   * Synchronize an existing collection
   *
   * @param callback - callback when synchronization is complete
   */
  schema.statics.synchronize = function(){
    var model = this
      , em = new events.EventEmitter();

    setIndexNameIfUnset(model.modelName);
    var stream = model.find().stream();

    stream.on('data', function(doc){
      var self = this;
      self.pause();
      doc.save(function(){
        doc.on('es-indexed', function(err, doc){
          if(err){
            em.emit('error', err);
          }else{
            em.emit('data', null, doc);
          }
          self.resume();
        });
      });
    });
    stream.on('close', function(a, b){
      em.emit('close', a, b);
    });
    stream.on('error', function(err){
      em.emit('error', err);
    });
    return em;
  };
  /**
   * ElasticSearch search function
   *
   * @param query - query object to perform search with
   * @param options - (optional) special search options, such as hydrate
   * @param callback - callback called with search results
   */
  schema.statics.search = function(query, options, cb){
    var model = this;
    setIndexNameIfUnset(model.modelName);

    if(typeof options != 'object'){
      cb = options;
      options = {};
    }
    query.index = indexName;
    esClient.search(query, function(err, results, res){
      if(err){
        cb(err);
      }else{
        actions[alwaysHydrate || options.hydrate?'hydrate':'mapResults'](results, model,cb);
      }
    });
  };
};

function createMappingIfNotPresent(indexName, typeName, schema, cb){
  generator.generateMapping(schema, function(err, mapping){
    var completeMapping = {};
    completeMapping[typeName] = mapping;
    esClient.createIndex(indexName, {mappings:completeMapping},cb);
  });
}
var actions = {
  mapResults: function(results, model, cb){
    cb(null, results);
  },
  hydrate: function(results, model, cb){
    var ids = results.hits.map(function(a){
      return a._id;
    });
    model.find({_id:{$in:ids}}, function(err, docs){
      if(err){
        return cb(err)
      }else{
        results.hits = docs;
        cb(null, results);
      }
    });
  }
}
function serialize(model, indexedFields){
  var serializedForm = {};

  if(indexedFields.length > 0){
    indexedFields.forEach(function(field){
      serializedForm[field] = model.get(field);
    });
  }else{
    serializedForm = model.toJSON();
  }
  delete serializedForm._id
  delete serializedForm.id
  return serializedForm;
}
function getIndexedFields(schema){
  var indexedFields = [];
  for(var k in schema.tree){
    if(schema.tree[k].es_indexed){
      indexedFields.push(k);
    }
  }
  return indexedFields;
}
function deleteByMongoId(client, model,indexName, typeName, tries){
    client.delete(indexName, typeName, model._id.toString(), function(err, res){
      if(err && err.message.indexOf('404') > -1){
        setTimeout(function(){
          if(tries <= 0){
            // future issue.. what do we do!?
          }else{
            deleteByMongoId(client, model, indexName, typeName, tries--);
          }
        }, 500);
      }else{
       model.emit('es-removed', err, res);
      }
    });
}
<commit_msg>fixed merge conflicts<commit_after>var elastical = require('elastical')
  , generator = new(require('./mapping-generator'))
  , events    = require('events');

module.exports = function elasticSearchPlugin(schema, options){
  var indexedFields = getIndexedFields(schema)
    , indexName = options && options.index
    , typeName  = options && options.type
    , alwaysHydrate = options && options.hydrate
    , _mapping = null
    , host = options && options.host ? options.host : 'localhost'
    , port = options && options.port ? options.port : 9200
    , esClient  = new elastical.Client(host,{port:port});

  schema.post('remove', function(){
    var model = this;
    setIndexNameIfUnset(model.constructor.modelName);
    deleteByMongoId(esClient, model, indexName, typeName, 3);
  });

  function setIndexNameIfUnset(model){
    var modelName = model.toLowerCase();
    if(!indexName){
      indexName = modelName + "s";
    }
    if(!typeName){
      typeName = modelName;
    }
  }

  /**
   * Create the mapping. Takes a callback that will be called once
   * the mapping is created
   */
  schema.statics.createMapping = function(cb){
    setIndexNameIfUnset(this.modelName);
    createMappingIfNotPresent(esClient, indexName, typeName, schema, cb);
  }
  /**
   * Save in elastic search on save.
   */
  schema.post('save', function(){
    var model = this;
    setIndexNameIfUnset(model.constructor.modelName);
    esClient.index(indexName, typeName, serialize(model, indexedFields), {id:model._id.toString()}, function(err, res){
      model.emit('es-indexed', err, res);
    });
  });

  /**
   * Synchronize an existing collection
   *
   * @param callback - callback when synchronization is complete
   */
  schema.statics.synchronize = function(){
    var model = this
      , em = new events.EventEmitter();

    setIndexNameIfUnset(model.modelName);
    var stream = model.find().stream();

    stream.on('data', function(doc){
      var self = this;
      self.pause();
      doc.save(function(){
        doc.on('es-indexed', function(err, doc){
          if(err){
            em.emit('error', err);
          }else{
            em.emit('data', null, doc);
          }
          self.resume();
        });
      });
    });
    stream.on('close', function(a, b){
      em.emit('close', a, b);
    });
    stream.on('error', function(err){
      em.emit('error', err);
    });
    return em;
  };
  /**
   * ElasticSearch search function
   *
   * @param query - query object to perform search with
   * @param options - (optional) special search options, such as hydrate
   * @param callback - callback called with search results
   */
  schema.statics.search = function(query, options, cb){
    var model = this;
    setIndexNameIfUnset(model.modelName);

    if(typeof options != 'object'){
      cb = options;
      options = {};
    }
    query.index = indexName;
    esClient.search(query, function(err, results, res){
      if(err){
        cb(err);
      }else{
        actions[alwaysHydrate || options.hydrate?'hydrate':'mapResults'](results, model,cb);
      }
    });
  };
};

function createMappingIfNotPresent(client, indexName, typeName, schema, cb){
  generator.generateMapping(schema, function(err, mapping){
    var completeMapping = {};
    completeMapping[typeName] = mapping;
    client.createIndex(indexName, {mappings:completeMapping},cb);
  });
}
var actions = {
  mapResults: function(results, model, cb){
    cb(null, results);
  },
  hydrate: function(results, model, cb){
    var ids = results.hits.map(function(a){
      return a._id;
    });
    model.find({_id:{$in:ids}}, function(err, docs){
      if(err){
        return cb(err)
      }else{
        results.hits = docs;
        cb(null, results);
      }
    });
  }
}
function serialize(model, indexedFields){
  var serializedForm = {};

  if(indexedFields.length > 0){
    indexedFields.forEach(function(field){
      serializedForm[field] = model.get(field);
    });
  }else{
    serializedForm = model.toJSON();
  }
  delete serializedForm._id
  delete serializedForm.id
  return serializedForm;
}
function getIndexedFields(schema){
  var indexedFields = [];
  for(var k in schema.tree){
    if(schema.tree[k].es_indexed){
      indexedFields.push(k);
    }
  }
  return indexedFields;
}
function deleteByMongoId(client, model,indexName, typeName, tries){
    client.delete(indexName, typeName, model._id.toString(), function(err, res){
      if(err && err.message.indexOf('404') > -1){
        setTimeout(function(){
          if(tries <= 0){
            // future issue.. what do we do!?
          }else{
            deleteByMongoId(client, model, indexName, typeName, tries--);
          }
        }, 500);
      }else{
       model.emit('es-removed', err, res);
      }
    });
}
<|endoftext|>


<commit_before>import VueRouter from 'vue-router'

import DiagramsOverview from '@/components/zetalayout/overview/WebpageDiagramsOverview'
import MetamodelCodeEditor from '@/components/zetalayout/metamodel/CodeEditor'
import MetamodelGraphicalEditor from '@/components/zetalayout/metamodel/GraphicalEditor'
import ZetaLayout from '@/components/zetalayout/ZetaLayout'
import AccountLayout from '@/components/accountlayout/AccountLayout'
import SignIn from '@/components/accountlayout/signin/SignIn'
import SignUp from '@/components/accountlayout/signup/signUp'
import PasswordForgot from "@/components/accountlayout/password/forgot/PasswordForgot";
import PasswordChange from "@/components/accountlayout/password/change/PasswordChange";

const isAuthenticated = function() {
    return !!(localStorage.getItem("user-token") || "")
}

const ifNotAuthenticated = (to, from, next) => {
    if (!isAuthenticated()) {
        next();
        return;
    }
    next("/");
};

const ifAuthenticated = (to, from, next) => {
    if (isAuthenticated()) {
        next();
        return;
    }
    next("/account/signIn");
};

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/',
            redirect: '/zeta/overview'
        },
        {
            path: '/zeta',
            component: ZetaLayout,
            beforeEnter: ifAuthenticated,
            children: [
                {
                    path: 'overview/:id?',
                    component: DiagramsOverview
                },
                {
                    path: 'codeEditor/editor/:id/:dslType',
                    component: MetamodelCodeEditor
                },
                {
                    path: 'metamodel/editor/:id',
                    component: MetamodelGraphicalEditor
                }
            ]
        },
        {
            path: '/account',
            component: AccountLayout,
            children: [
                {
                    path: 'signIn',
                    component: SignIn,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'signUp',
                    component: SignUp,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'password/forgot',
                    component: PasswordForgot,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'password/change',
                    component: PasswordChange,
                    beforeEnter: ifAuthenticated
                }
            ]
        }
    ]
})

export default router
<commit_msg>Dependency was not found fixed<commit_after>import VueRouter from 'vue-router'

import DiagramsOverview from '@/components/zetalayout/overview/WebpageDiagramsOverview'
import MetamodelCodeEditor from '@/components/zetalayout/metamodel/CodeEditor'
import MetamodelGraphicalEditor from '@/components/zetalayout/overview/GraphicalEditor'
import ZetaLayout from '@/components/zetalayout/ZetaLayout'
import AccountLayout from '@/components/accountlayout/AccountLayout'
import SignIn from '@/components/accountlayout/signin/SignIn'
import SignUp from '@/components/accountlayout/signup/signUp'
import PasswordForgot from "@/components/accountlayout/password/forgot/PasswordForgot";
import PasswordChange from "@/components/accountlayout/password/change/PasswordChange";

const isAuthenticated = function() {
    return !!(localStorage.getItem("user-token") || "")
}

const ifNotAuthenticated = (to, from, next) => {
    if (!isAuthenticated()) {
        next();
        return;
    }
    next("/");
};

const ifAuthenticated = (to, from, next) => {
    if (isAuthenticated()) {
        next();
        return;
    }
    next("/account/signIn");
};

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/',
            redirect: '/zeta/overview'
        },
        {
            path: '/zeta',
            component: ZetaLayout,
            beforeEnter: ifAuthenticated,
            children: [
                {
                    path: 'overview/:id?',
                    component: DiagramsOverview
                },
                {
                    path: 'codeEditor/editor/:id/:dslType',
                    component: MetamodelCodeEditor
                },
                {
                    path: 'metamodel/editor/:id',
                    component: MetamodelGraphicalEditor
                }
            ]
        },
        {
            path: '/account',
            component: AccountLayout,
            children: [
                {
                    path: 'signIn',
                    component: SignIn,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'signUp',
                    component: SignUp,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'password/forgot',
                    component: PasswordForgot,
                    beforeEnter: ifNotAuthenticated
                },
                {
                    path: 'password/change',
                    component: PasswordChange,
                    beforeEnter: ifAuthenticated
                }
            ]
        }
    ]
})

export default router
<|endoftext|>


<commit_before>define(function(require) {

    'use strict';

    var $        = require('jquery');
    var _        = require('underscore');
    var Backbone = require('backbone'); Backbone.$ = $;

    var defineInputUpdateLocks = require('common/locks/define-locks');
    var Vector2 = require('common/math/vector2');

    var Constants = require('constants');

    require('nouislider');

    var template1DHtml = require('text!templates/ball-settings-1d-item.html');
    var template2DHtml = require('text!templates/ball-settings-2d-item.html');

    /**
     *
     */
    var BallSettingsView = Backbone.View.extend({

        tagName: 'tr',
        //className: '',
        template1D: _.template(template1DHtml),
        template2D: _.template(template2DHtml),

        events: {
            'keyup .mass' : 'changeMassFromText',
            'slide .mass-slider': 'changeMassFromSlider',

            'change .pos-x' : 'changeX',
            'change .pos-y' : 'changeY',
            'change .vel-x' : 'changeVX',
            'change .vel-y' : 'changeVY'
        },

        initialize: function(options) {
            options = _.extend({
                oneDimensional: false,
                showMoreData: false
            }, options);

            this.oneDimensional = options.oneDimensional;
            this.moreDataMode = options.showMoreData;
            this.simulation = options.simulation;

            this._position = new Vector2();

            this.listenTo(this.model, 'change:mass',     this.massChanged);
            this.listenTo(this.model, 'change:position', this.positionChanged);
            this.listenTo(this.model, 'change:velocity', this.velocityChanged);
            this.listenTo(this.model, 'change:momentumX', this.momentumXChanged);
            this.listenTo(this.model, 'change:momentumY', this.momentumYChanged);
        },

        /**
         * Renders content and canvas for heatmap
         */
        render: function() {
            var data = this.model.toJSON();
            _.extend(data, Constants.Ball);

            if (this.oneDimensional)
                this.$el.html(this.template1D(data));
            else
                this.$el.html(this.template2D(data));

            this.$more = this.$('.more');
            this.$less = this.$('.less');

            this.$('.mass-slider').noUiSlider({
                start: this.model.get('mass'),
                connect: 'lower',
                range: {
                    'min': Constants.Ball.MIN_MASS,
                    'max': Constants.Ball.MAX_MASS
                }
            });

            if (this.moreDataMode)
                this.showMoreData();
            else
                this.showLessData();

            return this;
        },

        massChanged: function(ball, mass) {
            this.updateLock(function() {
                if (this.moreDataMode)
                    this.$('.mass').val(mass.toFixed(2));
                else
                    this.$('.mass').val(mass.toFixed(1));
                this.$('.mass-slider').val(mass);
            });
        },

        changeMassFromText: function(event) {
            var mass = parseFloat($(event.target).val());
            if (!isNaN(mass)) {
                this.inputLock(function() {
                    this.model.set('mass', mass);
                });
                this.$('.mass-slider').val(mass);
            }
        },

        changeMassFromSlider: function(event) {
            var mass = parseFloat($(event.target).val());
            if (!isNaN(mass)) {
                this.inputLock(function() {
                    this.model.set('mass', mass);
                });
                this.$('.mass').val(mass.toFixed(1));
            }
        },

        positionChanged: function(ball, position) {
            this.updateLock(function() {
                this.$('.pos-x').val(position.x.toFixed(2));
                if (!this.oneDimensional)
                    this.$('.pos-y').val(position.y.toFixed(2));
            });
        },

        changeX: function(event) {
            var x = parseFloat($(event.target).val());
            if (!isNaN(x)) {
                var position = this._position;
                position.x = x;
                position.y = this.model.get('position').y;

                this.simulation.keepWithinBounds(this.model, position);

                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitX(position.x);
                    this.model.setX(position.x);
                    this.simulation.separateAllBalls();

                    // Update the text box with the correct position if it is different
                    this.$('.pos-x').val(this.model.get('position').x.toFixed(2));
                    if (!this.oneDimensional)
                        this.$('.pos-y').val(this.model.get('position').y.toFixed(2));
                });
            }
        },

        changeY: function(event) {
            var y = parseFloat($(event.target).val());
            if (!isNaN(y)) {
                var position = this._position;
                position.x = this.model.get('position').x;
                position.y = y;

                this.simulation.keepWithinBounds(this.model, position);

                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitY(position.y);
                    this.model.setY(position.y);
                    this.simulation.separateAllBalls();

                    // Update the text box with the correct position if it is different
                    this.$('.pos-x').val(this.model.get('position').x.toFixed(2));
                    if (!this.oneDimensional)
                        this.$('.pos-y').val(this.model.get('position').y.toFixed(2));
                });
            }
        },

        velocityChanged: function(ball, velocity) {
            this.updateLock(function() {
                this.$('.vel-x').val(velocity.x.toFixed(2));
                if (!this.oneDimensional)
                    this.$('.vel-y').val(velocity.y.toFixed(2));
            });
        },

        changeVX: function(event) {
            var vx = parseFloat($(event.target).val());
            if (!isNaN(vx)) {
                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitVX(vx);
                    this.model.setVelocityX(vx);
                });
            }
        },

        changeVY: function(event) {
            var vy = parseFloat($(event.target).val());
            if (!isNaN(vy)) {
                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitVY(vy);
                    this.model.setVelocityY(vy);
                });
            }
        },

        momentumXChanged: function(ball, momentumX) {
            this.updateLock(function() {
                this.$('.mom-x').text(momentumX.toFixed(2));
            });
        },

        momentumYChanged: function(ball, momentumY) {
            this.updateLock(function() {
                this.$('.mom-y').text(momentumY.toFixed(2));
            });
        },

        showMoreData: function() {
            this.$less.hide();
            this.$more.show();
            this.moreDataMode = true;
            this.massChanged(this.model, this.model.get('mass'));
        },

        showLessData: function() {
            this.$more.hide();
            this.$less.show();
            this.moreDataMode = false;
            this.massChanged(this.model, this.model.get('mass'));
        }

    });

    // Add input/update locking functionality to the prototype
    defineInputUpdateLocks(BallSettingsView);

    return BallSettingsView;
});
<commit_msg>When mass (radius) gets changed by user, calls separateAllBalls function to keep them from overlapping if they're close<commit_after>define(function(require) {

    'use strict';

    var $        = require('jquery');
    var _        = require('underscore');
    var Backbone = require('backbone'); Backbone.$ = $;

    var defineInputUpdateLocks = require('common/locks/define-locks');
    var Vector2 = require('common/math/vector2');

    var Constants = require('constants');

    require('nouislider');

    var template1DHtml = require('text!templates/ball-settings-1d-item.html');
    var template2DHtml = require('text!templates/ball-settings-2d-item.html');

    /**
     *
     */
    var BallSettingsView = Backbone.View.extend({

        tagName: 'tr',
        //className: '',
        template1D: _.template(template1DHtml),
        template2D: _.template(template2DHtml),

        events: {
            'keyup .mass' : 'changeMassFromText',
            'slide .mass-slider': 'changeMassFromSlider',

            'change .pos-x' : 'changeX',
            'change .pos-y' : 'changeY',
            'change .vel-x' : 'changeVX',
            'change .vel-y' : 'changeVY'
        },

        initialize: function(options) {
            options = _.extend({
                oneDimensional: false,
                showMoreData: false
            }, options);

            this.oneDimensional = options.oneDimensional;
            this.moreDataMode = options.showMoreData;
            this.simulation = options.simulation;

            this._position = new Vector2();

            this.listenTo(this.model, 'change:mass',     this.massChanged);
            this.listenTo(this.model, 'change:position', this.positionChanged);
            this.listenTo(this.model, 'change:velocity', this.velocityChanged);
            this.listenTo(this.model, 'change:momentumX', this.momentumXChanged);
            this.listenTo(this.model, 'change:momentumY', this.momentumYChanged);
        },

        /**
         * Renders content and canvas for heatmap
         */
        render: function() {
            var data = this.model.toJSON();
            _.extend(data, Constants.Ball);

            if (this.oneDimensional)
                this.$el.html(this.template1D(data));
            else
                this.$el.html(this.template2D(data));

            this.$more = this.$('.more');
            this.$less = this.$('.less');

            this.$('.mass-slider').noUiSlider({
                start: this.model.get('mass'),
                connect: 'lower',
                range: {
                    'min': Constants.Ball.MIN_MASS,
                    'max': Constants.Ball.MAX_MASS
                }
            });

            if (this.moreDataMode)
                this.showMoreData();
            else
                this.showLessData();

            return this;
        },

        massChanged: function(ball, mass) {
            this.updateLock(function() {
                if (this.moreDataMode)
                    this.$('.mass').val(mass.toFixed(2));
                else
                    this.$('.mass').val(mass.toFixed(1));
                this.$('.mass-slider').val(mass);
            });
        },

        changeMassFromText: function(event) {
            var mass = parseFloat($(event.target).val());
            if (!isNaN(mass)) {
                this.inputLock(function() {
                    this.model.set('mass', mass);
                    this.simulation.separateAllBalls();
                });
                this.$('.mass-slider').val(mass);
            }
        },

        changeMassFromSlider: function(event) {
            var mass = parseFloat($(event.target).val());
            if (!isNaN(mass)) {
                this.inputLock(function() {
                    this.model.set('mass', mass);
                    this.simulation.separateAllBalls();
                });
                this.$('.mass').val(mass.toFixed(1));
            }
        },

        positionChanged: function(ball, position) {
            this.updateLock(function() {
                this.$('.pos-x').val(position.x.toFixed(2));
                if (!this.oneDimensional)
                    this.$('.pos-y').val(position.y.toFixed(2));
            });
        },

        changeX: function(event) {
            var x = parseFloat($(event.target).val());
            if (!isNaN(x)) {
                var position = this._position;
                position.x = x;
                position.y = this.model.get('position').y;

                this.simulation.keepWithinBounds(this.model, position);

                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitX(position.x);
                    this.model.setX(position.x);
                    this.simulation.separateAllBalls();

                    // Update the text box with the correct position if it is different
                    this.$('.pos-x').val(this.model.get('position').x.toFixed(2));
                    if (!this.oneDimensional)
                        this.$('.pos-y').val(this.model.get('position').y.toFixed(2));
                });
            }
        },

        changeY: function(event) {
            var y = parseFloat($(event.target).val());
            if (!isNaN(y)) {
                var position = this._position;
                position.x = this.model.get('position').x;
                position.y = y;

                this.simulation.keepWithinBounds(this.model, position);

                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitY(position.y);
                    this.model.setY(position.y);
                    this.simulation.separateAllBalls();

                    // Update the text box with the correct position if it is different
                    this.$('.pos-x').val(this.model.get('position').x.toFixed(2));
                    if (!this.oneDimensional)
                        this.$('.pos-y').val(this.model.get('position').y.toFixed(2));
                });
            }
        },

        velocityChanged: function(ball, velocity) {
            this.updateLock(function() {
                this.$('.vel-x').val(velocity.x.toFixed(2));
                if (!this.oneDimensional)
                    this.$('.vel-y').val(velocity.y.toFixed(2));
            });
        },

        changeVX: function(event) {
            var vx = parseFloat($(event.target).val());
            if (!isNaN(vx)) {
                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitVX(vx);
                    this.model.setVelocityX(vx);
                });
            }
        },

        changeVY: function(event) {
            var vy = parseFloat($(event.target).val());
            if (!isNaN(vy)) {
                this.inputLock(function() {
                    if (!this.simulation.hasStarted())
                        this.model.setInitVY(vy);
                    this.model.setVelocityY(vy);
                });
            }
        },

        momentumXChanged: function(ball, momentumX) {
            this.updateLock(function() {
                this.$('.mom-x').text(momentumX.toFixed(2));
            });
        },

        momentumYChanged: function(ball, momentumY) {
            this.updateLock(function() {
                this.$('.mom-y').text(momentumY.toFixed(2));
            });
        },

        showMoreData: function() {
            this.$less.hide();
            this.$more.show();
            this.moreDataMode = true;
            this.massChanged(this.model, this.model.get('mass'));
        },

        showLessData: function() {
            this.$more.hide();
            this.$less.show();
            this.moreDataMode = false;
            this.massChanged(this.model, this.model.get('mass'));
        }

    });

    // Add input/update locking functionality to the prototype
    defineInputUpdateLocks(BallSettingsView);

    return BallSettingsView;
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name            Scroll 1px on Wheel over AutoScroll
// @author          xiaoxiaoflood
// @include         main
// @startup         UC.WheelAutoScroll_1px.exec(win);
// @shutdown        UC.WheelAutoScroll_1px.destroy();
// @onlyonce
// ==/UserScript==

UC.WheelAutoScroll_1px = {
  exec: function (win) {
    let customElements = win.customElements;
    win.eval('customElements.get(\'browser\').prototype.startScroll = function ' +
             customElements.get('browser').prototype.startScroll.toString().
               replace(/window\.addEventListener\("DOMMouseScroll", this, true\);/,
                       `
      UC.WheelAutoScroll_1px.startar = true;
      this.handleEventWrapper = (e) => {
        this.handleEvent(e, arguments[0]);
      };
      window.addEventListener("DOMMouseScroll", this.handleEventWrapper, { passive: false, capture: true });\n`).
               replace(/!this.autoscrollEnabled/,
                       '!this.autoscrollEnabled || (this._autoScrollPopup?.state == "open" && UC.WheelAutoScroll_1px.startar)').
               replace(/^function /,
                       ''));
    eval('customElements.get(\'browser\').prototype.stopScroll = function ' +
         customElements.get('browser').prototype.stopScroll.toString().
           replace(/window\.removeEventListener\("DOMMouseScroll", this, true\);/,
                   `window.removeEventListener("DOMMouseScroll", this.handleEventWrapper, true);`).
           replace(/^function /,
                   ''));
    eval('customElements.get(\'browser\').prototype.handleEvent = function ' +
         customElements.get('browser').prototype.handleEvent.toString().
           replace(/case "DOMMouseScroll": {\s+[\s\S]+?\n[\s\S]+?\n/,
           `case "DOMMouseScroll": {
            if (!content) {
              let data = arguments[1];
              if (!this._autoScrollPopup._hidePopup) {
                this._autoScrollPopup._hidePopup = this._autoScrollPopup.hidePopup;
              }
              this._autoScrollPopup.hidePopup = () => {};
              setTimeout(() => {
                this._autoScrollPopup.hidePopup = this._autoScrollPopup._hidePopup;
                this.stopScroll();
                UC.WheelAutoScroll_1px.startar = false;
                this.startScroll(data);
              });
            }
            this.messageManager.sendAsyncMessage('autoscroll', { d: aEvent.detail, x: aEvent.clientX, y: aEvent.clientY });
            aEvent.preventDefault();\n`).
           replace(/^function /,
                   ''));
  },

  startar: true,

  startScroll_orig: customElements.get('browser').prototype.startScroll.toString().replace(/^function /, ''),
  stopScroll_orig: customElements.get('browser').prototype.stopScroll.toString().replace(/^function /, ''),
  handleEvent_orig: customElements.get('browser').prototype.handleEvent.toString().replace(/^function /, ''),

  frameScript: 'data:application/javascript;charset=UTF-8,' + encodeURIComponent('(' + (function () {
    getScrollParent = el =>
      el.scrollTop != el.scrollTopMax
        ? el
        : el.parentElement
          ? getScrollParent(el.parentElement)
          : content.document.scrollingElement
    this.contentListener = (msg) => {
      if (msg.data.destroy) {
        removeMessageListener('autoscroll', this.contentListener);
      } else {
        let el = getScrollParent(content.document.elementFromPoint(msg.data.x, msg.data.y));
        if (msg.data.d < 0) {
          el.scrollBy(0, -1);
        } else if (msg.data.d > 0) {
          el.scrollBy(0, 1);
        }
      }
    }
    addMessageListener('autoscroll', this.contentListener);
  }).toString() + ')();'),

  init: function () {
    Services.mm.loadFrameScript(this.frameScript, true);
  },

  destroy: function () {
    Services.mm.removeDelayedFrameScript(this.frameScript);
    Services.mm.broadcastAsyncMessage('autoscroll', { destroy: true });
    _uc.windows((doc, win) => {
      let customElements = win.customElements;
      let eval = win.eval;
      eval('customElements.get(\'browser\').prototype.startScroll = function ' +
               this.startScroll_orig);
      eval('customElements.get(\'browser\').prototype.stopScroll = function ' +
               this.stopScroll_orig);
      eval('customElements.get(\'browser\').prototype.handleEvent = function ' +
               this.handleEvent_orig);
      win.gBrowser.browsers.forEach(browser => {
        if ('handleEventWrapper' in browser) {
          delete browser.handleEventWrapper;
        }
      });
    });
    delete UC.WheelAutoScroll_1px;
  }
}

UC.WheelAutoScroll_1px.init();<commit_msg>fix scroll1pxwheel<commit_after>// ==UserScript==
// @name            Scroll 1px on Wheel over AutoScroll
// @author          xiaoxiaoflood
// @include         main
// @startup         UC.WheelAutoScroll_1px.exec(win);
// @shutdown        UC.WheelAutoScroll_1px.destroy();
// @onlyonce
// ==/UserScript==

UC.WheelAutoScroll_1px = {
  exec: function (win) {
    let customElements = win.customElements;
    win.eval('customElements.get(\'browser\').prototype.startScroll = function ' +
             customElements.get('browser').prototype.startScroll.toString().
               replace(/window\.addEventListener\("DOMMouseScroll", this, true\);/,
                       `
      UC.WheelAutoScroll_1px.startar = true;
      this.handleEventWrapper = (e) => {
        this.handleEvent(e, arguments[0]);
      };
      window.addEventListener("DOMMouseScroll", this.handleEventWrapper, { passive: false, capture: true });\n`).
               replace(/!this.autoscrollEnabled/,
                       '!this.autoscrollEnabled || (this._autoScrollPopup?.state == "open" && UC.WheelAutoScroll_1px.startar)').
               replace(/^function /,
                       '').
               replace(/Services\.obs\.addObserver\(this\.observer, "apz:cancel-autoscroll", true\);/,
                       ''));
    eval('customElements.get(\'browser\').prototype.stopScroll = function ' +
         customElements.get('browser').prototype.stopScroll.toString().
           replace(/window\.removeEventListener\("DOMMouseScroll", this, true\);/,
                   `window.removeEventListener("DOMMouseScroll", this.handleEventWrapper, true);`).
           replace(/^function /,
                   ''));
    eval('customElements.get(\'browser\').prototype.handleEvent = function ' +
         customElements.get('browser').prototype.handleEvent.toString().
           replace(/case "DOMMouseScroll": {\s+[\s\S]+?\n[\s\S]+?\n/,
           `case "DOMMouseScroll": {
            if (!content) {
              let data = arguments[1];
              if (!this._autoScrollPopup._hidePopup) {
                this._autoScrollPopup._hidePopup = this._autoScrollPopup.hidePopup;
              }
              this._autoScrollPopup.hidePopup = () => {};
              setTimeout(() => {
                this._autoScrollPopup.hidePopup = this._autoScrollPopup._hidePopup;
                this.stopScroll();
                UC.WheelAutoScroll_1px.startar = false;
                this.startScroll(data);
              });
            }
            this.messageManager.sendAsyncMessage('autoscroll', { d: aEvent.detail, x: aEvent.clientX, y: aEvent.clientY });
            aEvent.preventDefault();\n`).
           replace(/^function /,
                   ''));
  },

  startar: true,

  startScroll_orig: customElements.get('browser').prototype.startScroll.toString().replace(/^function /, ''),
  stopScroll_orig: customElements.get('browser').prototype.stopScroll.toString().replace(/^function /, ''),
  handleEvent_orig: customElements.get('browser').prototype.handleEvent.toString().replace(/^function /, ''),

  frameScript: 'data:application/javascript;charset=UTF-8,' + encodeURIComponent('(' + (function () {
    getScrollParent = el =>
      el.scrollTop != el.scrollTopMax
        ? el
        : el.parentElement
          ? getScrollParent(el.parentElement)
          : content.document.scrollingElement
    this.contentListener = (msg) => {
      if (msg.data.destroy) {
        removeMessageListener('autoscroll', this.contentListener);
      } else {
        let el = getScrollParent(content.document.elementFromPoint(msg.data.x, msg.data.y));
        if (msg.data.d < 0) {
          el.scrollBy(0, -1);
        } else if (msg.data.d > 0) {
          el.scrollBy(0, 1);
        }
      }
    }
    addMessageListener('autoscroll', this.contentListener);
  }).toString() + ')();'),

  init: function () {
    Services.mm.loadFrameScript(this.frameScript, true);
  },

  destroy: function () {
    Services.mm.removeDelayedFrameScript(this.frameScript);
    Services.mm.broadcastAsyncMessage('autoscroll', { destroy: true });
    _uc.windows((doc, win) => {
      let customElements = win.customElements;
      let eval = win.eval;
      eval('customElements.get(\'browser\').prototype.startScroll = function ' +
               this.startScroll_orig);
      eval('customElements.get(\'browser\').prototype.stopScroll = function ' +
               this.stopScroll_orig);
      eval('customElements.get(\'browser\').prototype.handleEvent = function ' +
               this.handleEvent_orig);
      win.gBrowser.browsers.forEach(browser => {
        if ('handleEventWrapper' in browser) {
          delete browser.handleEventWrapper;
        }
      });
    });
    delete UC.WheelAutoScroll_1px;
  }
}

UC.WheelAutoScroll_1px.init();<|endoftext|>


<commit_before>import { showNotification } from './gh-interface';

let isNewVersion = false;
const pkgVersion = require('../package.json').version.split('.').slice(0, -1).join('.');

const installedVersion = window.localStorage.getItem('OctoLinkerVersion');
window.localStorage.setItem('OctoLinkerVersion', pkgVersion);

if (installedVersion && installedVersion !== pkgVersion) {
  isNewVersion = true;
}

export default function () {
  if (isNewVersion) {
    showNotification();
  }
}
<commit_msg>Store extension version in browser storage (#220)<commit_after>import { showNotification } from './gh-interface';
import * as storage from './options/storage.js';

const pkgVersion = require('../package.json').version.split('.').slice(0, -1).join('.');

export default function () {
  let isNewVersion = false;

  const installedVersion = storage.get('version') || window.localStorage.getItem('OctoLinkerVersion');

  // Remove this in after three releases (v4.8)
  if (window.localStorage.getItem('OctoLinkerVersion')) {
    window.localStorage.removeItem('OctoLinkerVersion');
  }

  storage.set('version', pkgVersion);

  if (installedVersion && installedVersion !== pkgVersion) {
    isNewVersion = true;
  }

  if (isNewVersion) {
    showNotification();
  }
}
<|endoftext|>


<commit_before>var EventEmitter    = require("../core/eventEmitter"),
protoclass          = require("protoclass"),
watchProperty       = require("./watchProperty");

/**
 * @module mojo
 * @submodule mojo-core
 */

/**

BindableObjects make it easy to link properties of two separate objects - when one changes,
the other will automatically update with that change. It enables much easier interactions between data models and UIs,
among other uses outside of MVC.

BindableObjects provide a way to maintain the state between server <-> client for a realtime front-end
application (similar to Firebase), or perhaps a way to communicate between server <-> server for a realtime distributed Node.js
application.

### Example

```javascript
  var bindable = require("bindable");

  var person = new bindable.Object({
    name: "craig",
    last: "condon",
    location: {
      city: "San Francisco"
    }
  });

  person.bind("location.zip", function(value) {
    // 94102
  }).now();

  //triggers the binding
  person.set("location.zip", "94102");

  //bind location.zip to another property in the model, and do it only once
  person.bind("location.zip", { to: "zip", max: 1 }).now();

  //bind location.zip to another object, and make it bi-directional.
  person.bind("location.zip", { target: anotherModel, to: "location.zip", bothWays: true }).now();

  //chain to multiple items, and limit it!
  person.bind("location.zip", { to: ["property", "anotherProperty"], max: 1 }).now();

  //you can also transform data as it's being bound
  person.bind("name", {
    to: "name2",
    map: function (name) {
      return name.toUpperCase();
    }
  }).now();
```

@class BindableObject
@extends EventEmitter
*/

/**
 * Emitted when the bindable object is disposed. This happens
 * when the object is no-longer needed.
 * @event dispose
 */

/**
 * Emitted everytime a property changes
 * @event change
 * @param {String} property
 * @param {Object} value
 * @param {Object} oldValue
 */

/**
 * Emitted when a specific property changes
 * @event change:*
 * @param {Object} value
 * @param {Object} oldValue
 */

/**
 * @constructor
 * @param {Object} context context of the bindable object
 */

/**
 * emitted when a property is being watched
 * @event watching
 */

function Bindable (context) {

  if (context) {
    this.context(context);
  } else {
    this.__context = {};
  }

  Bindable.parent.call(this);
}

watchProperty.BindableObject = Bindable;

protoclass(EventEmitter, Bindable, {

  /**
   */

  __isBindable: true,

  /**
   * The context of the bindable object. Note that the context can be `this`.
   * @method context
   * @param {Object} data (optional) sets the context
   * @returns {Object} context
   */

  context: function (data) {
    if (!arguments.length) return this.__context;

    // only exception is
    if (data.__isBindable && data !== this) {
      throw new Error("context cannot be a bindable object");
    }

    this.__context = data;
  },

  /**
   * Returns the keys in the context
   * @method keys
   * @returns {Array}
   */

  keys: function () {
    return Object.keys(this.toJSON());
  },

  /**
   * Returns TRUE if a property exists in the context
   * @method has
   * @param {String} path
   * @returns {Boolean}
   */

  has: function (key) {
    return this.get(key) != null;
  },

  /**
   * Returns a property stored in the bindable object context
   * @method get
   * @param {String} path path to the value. Can be something like `person.city.name`.
   */

  get: function (property) {

    var isString;

    // optimal
    if ((isString = (typeof property === "string")) && !~property.indexOf(".")) {
      return this.__context[property];
    }

    // avoid split if possible
    var chain    = isString ? property.split(".") : property,
    ctx          = this.__context,
    currentValue = ctx,
    currentProperty;

    // go through all the properties
    for (var i = 0, n = chain.length - 1; i < n; i++) {

      currentValue    = currentValue[chain[i]];

      if (!currentValue) return;

      // current value is a bindable item? grab the context
      if (currentValue.__isBindable && currentValue !== ctx) {
        currentValue = currentValue.__context;
      }
    }
    // might be a bindable object
    if(currentValue) return currentValue[chain[i]];
  },

  /**
   * Properties to set on the bindable object
   * @method setProperties
   * @param {Object} properties properties to set
   * @returns {BindableObject} this
   */

  setProperties: function (properties) {
    for (var property in properties) {
      this.set(property, properties[property]);
    }
    return this;
  },

  /**
   * Sets a property on the bindable object's context
   * @method set
   * @param {String} path path to the value. Can be something like `person.city.name`.
   */

  set: function (property, value) {

    var isString, hasChanged, oldValue;

    // optimal
    if ((isString = (typeof property === "string")) && !~property.indexOf(".")) {
      hasChanged = (oldValue = this.__context[property]) !== value;
      if (hasChanged) this.__context[property] = value;
    } else {

      // avoid split if possible
      var chain     = isString ? property.split(".") : property,
      ctx           = this.__context,
      currentValue  = ctx,
      previousValue,
      currentProperty,
      newChain;

      for (var i = 0, n = chain.length - 1; i < n; i++) {

        currentProperty = chain[i];
        previousValue   = currentValue;
        currentValue    = currentValue[currentProperty];

        // need to take into account functions - easier not to check
        // if value exists
        if (!currentValue /* || (typeof currentValue !== "object")*/) {
          currentValue = previousValue[currentProperty] = {};
        }

        // is the previous value bindable? pass it on
        if (currentValue.__isBindable) {

          newChain = chain.slice(i + 1);
          // check if the value has changed
          hasChanged = (oldValue = currentValue.get(newChain)) !== value;
          currentValue.set(newChain, value);
          currentValue = oldValue;
          break;
        }
      }

      if (!newChain && (hasChanged = (currentValue !== value))) {
        currentProperty = chain[i];
        oldValue = currentValue[currentProperty];
        currentValue[currentProperty] = value;
      }
    }

    if (!hasChanged) return value;

    var prop = chain ? chain.join(".") : property;

    this.emit("change:" + prop, value, oldValue);
    this.emit("change", prop, value, oldValue);
    return value;
  },

  /**
   * Binds a property to a function
   * @method bind
   * @param {String} property path to bind to.
   * @param {Object} listener `function` or `transformer` to bind to
   * @param {Boolean} now (optional) call binding now. Otherwise wait till property changes.
   * @returns {Binding}
   */

  bind: function (property, fn, now) {
    return watchProperty(this, property, fn, now);
  },

  /**
   * Disposes the bindable object. Emits `dispose`.
   * @method dispose
   */

  dispose: function () {
    this.emit("dispose");
  },

  /**
   * Converts the context to a JSON object
   * @method toJSON
   */

  toJSON: function () {
    var obj = {}, value;

    for (var key in this.__context) {
      value = this.__context[key];

      if(value && value.__isBindable) {
        value = value.toJSON()
      }

      obj[key] = value;
    }
    return obj;
  }
});

module.exports = Bindable;
<commit_msg>remove tab<commit_after>var EventEmitter    = require("../core/eventEmitter"),
protoclass          = require("protoclass"),
watchProperty       = require("./watchProperty");

/**
 * @module mojo
 * @submodule mojo-core
 */

/**

BindableObjects make it easy to link properties of two separate objects - when one changes,
the other will automatically update with that change. It enables much easier interactions between data models and UIs,
among other uses outside of MVC.

BindableObjects provide a way to maintain the state between server <-> client for a realtime front-end
application (similar to Firebase), or perhaps a way to communicate between server <-> server for a realtime distributed Node.js
application.

### Example

```javascript
var bindable = require("bindable");

var person = new bindable.Object({
  name: "craig",
  last: "condon",
  location: {
    city: "San Francisco"
  }
});

person.bind("location.zip", function(value) {
  // 94102
}).now();

//triggers the binding
person.set("location.zip", "94102");

//bind location.zip to another property in the model, and do it only once
person.bind("location.zip", { to: "zip", max: 1 }).now();

//bind location.zip to another object, and make it bi-directional.
person.bind("location.zip", { target: anotherModel, to: "location.zip", bothWays: true }).now();

//chain to multiple items, and limit it!
person.bind("location.zip", { to: ["property", "anotherProperty"], max: 1 }).now();

//you can also transform data as it's being bound
person.bind("name", {
  to: "name2",
  map: function (name) {
    return name.toUpperCase();
  }
}).now();
```

@class BindableObject
@extends EventEmitter
*/

/**
 * Emitted when the bindable object is disposed. This happens
 * when the object is no-longer needed.
 * @event dispose
 */

/**
 * Emitted everytime a property changes
 * @event change
 * @param {String} property
 * @param {Object} value
 * @param {Object} oldValue
 */

/**
 * Emitted when a specific property changes
 * @event change:*
 * @param {Object} value
 * @param {Object} oldValue
 */

/**
 * @constructor
 * @param {Object} context context of the bindable object
 */

/**
 * emitted when a property is being watched
 * @event watching
 */

function Bindable (context) {

  if (context) {
    this.context(context);
  } else {
    this.__context = {};
  }

  Bindable.parent.call(this);
}

watchProperty.BindableObject = Bindable;

protoclass(EventEmitter, Bindable, {

  /**
   */

  __isBindable: true,

  /**
   * The context of the bindable object. Note that the context can be `this`.
   * @method context
   * @param {Object} data (optional) sets the context
   * @returns {Object} context
   */

  context: function (data) {
    if (!arguments.length) return this.__context;

    // only exception is
    if (data.__isBindable && data !== this) {
      throw new Error("context cannot be a bindable object");
    }

    this.__context = data;
  },

  /**
   * Returns the keys in the context
   * @method keys
   * @returns {Array}
   */

  keys: function () {
    return Object.keys(this.toJSON());
  },

  /**
   * Returns TRUE if a property exists in the context
   * @method has
   * @param {String} path
   * @returns {Boolean}
   */

  has: function (key) {
    return this.get(key) != null;
  },

  /**
   * Returns a property stored in the bindable object context
   * @method get
   * @param {String} path path to the value. Can be something like `person.city.name`.
   */

  get: function (property) {

    var isString;

    // optimal
    if ((isString = (typeof property === "string")) && !~property.indexOf(".")) {
      return this.__context[property];
    }

    // avoid split if possible
    var chain    = isString ? property.split(".") : property,
    ctx          = this.__context,
    currentValue = ctx,
    currentProperty;

    // go through all the properties
    for (var i = 0, n = chain.length - 1; i < n; i++) {

      currentValue    = currentValue[chain[i]];

      if (!currentValue) return;

      // current value is a bindable item? grab the context
      if (currentValue.__isBindable && currentValue !== ctx) {
        currentValue = currentValue.__context;
      }
    }
    // might be a bindable object
    if(currentValue) return currentValue[chain[i]];
  },

  /**
   * Properties to set on the bindable object
   * @method setProperties
   * @param {Object} properties properties to set
   * @returns {BindableObject} this
   */

  setProperties: function (properties) {
    for (var property in properties) {
      this.set(property, properties[property]);
    }
    return this;
  },

  /**
   * Sets a property on the bindable object's context
   * @method set
   * @param {String} path path to the value. Can be something like `person.city.name`.
   */

  set: function (property, value) {

    var isString, hasChanged, oldValue;

    // optimal
    if ((isString = (typeof property === "string")) && !~property.indexOf(".")) {
      hasChanged = (oldValue = this.__context[property]) !== value;
      if (hasChanged) this.__context[property] = value;
    } else {

      // avoid split if possible
      var chain     = isString ? property.split(".") : property,
      ctx           = this.__context,
      currentValue  = ctx,
      previousValue,
      currentProperty,
      newChain;

      for (var i = 0, n = chain.length - 1; i < n; i++) {

        currentProperty = chain[i];
        previousValue   = currentValue;
        currentValue    = currentValue[currentProperty];

        // need to take into account functions - easier not to check
        // if value exists
        if (!currentValue /* || (typeof currentValue !== "object")*/) {
          currentValue = previousValue[currentProperty] = {};
        }

        // is the previous value bindable? pass it on
        if (currentValue.__isBindable) {

          newChain = chain.slice(i + 1);
          // check if the value has changed
          hasChanged = (oldValue = currentValue.get(newChain)) !== value;
          currentValue.set(newChain, value);
          currentValue = oldValue;
          break;
        }
      }

      if (!newChain && (hasChanged = (currentValue !== value))) {
        currentProperty = chain[i];
        oldValue = currentValue[currentProperty];
        currentValue[currentProperty] = value;
      }
    }

    if (!hasChanged) return value;

    var prop = chain ? chain.join(".") : property;

    this.emit("change:" + prop, value, oldValue);
    this.emit("change", prop, value, oldValue);
    return value;
  },

  /**
   * Binds a property to a function
   * @method bind
   * @param {String} property path to bind to.
   * @param {Object} listener `function` or `transformer` to bind to
   * @param {Boolean} now (optional) call binding now. Otherwise wait till property changes.
   * @returns {Binding}
   */

  bind: function (property, fn, now) {
    return watchProperty(this, property, fn, now);
  },

  /**
   * Disposes the bindable object. Emits `dispose`.
   * @method dispose
   */

  dispose: function () {
    this.emit("dispose");
  },

  /**
   * Converts the context to a JSON object
   * @method toJSON
   */

  toJSON: function () {
    var obj = {}, value;

    for (var key in this.__context) {
      value = this.__context[key];

      if(value && value.__isBindable) {
        value = value.toJSON()
      }

      obj[key] = value;
    }
    return obj;
  }
});

module.exports = Bindable;
<|endoftext|>


<commit_before>module.exports = function (message, callback) {
  var interrupted = false;
  var signal = process.platform.indexOf('win') >= 0 ? "exit" : "SIGINT";
  process.on(signal, function () {
    if (interrupted) {
      process.exit();
    }
    console.log(message + " Interrupt a second time to quit");
    interrupted = true;
    setTimeout(function () {
      interrupted = false;
      callback();
    }, 1500);
  });
};
<commit_msg>Fix interrupt on OS X<commit_after>module.exports = function (message, callback) {
  var interrupted = false;
  var signal = process.platform === "win32" ? "exit" : "SIGINT";
  process.on(signal, function () {
    if (interrupted) {
      process.exit();
    }
    console.log(message + " Interrupt a second time to quit");
    interrupted = true;
    setTimeout(function () {
      interrupted = false;
      callback();
    }, 1500);
  });
};
<|endoftext|>


<commit_before>'use strict'

/**
 * Javascript class to interact with a Parse application's logs.
 */

var assert = require('assert');
var _ = require('underscore');
var Parse = require('parse').Parse;
var request = require('request');

var ParseLogger = function(applicationId,
                           masterKey) {

    var parseLogAPI = 'https://api.parse.com/1/scriptlog';
    var tailDelay = 4000;

    function generateStarTimeJSON(date) {
        assert(date, '"date" is a required parameter');

        if (_.isString(date)) {
            date = new Date(date).toISOString();
        } else {
            date = date.toISOString();
        }

        return JSON.stringify(
            {
                'iso':    date,
                '__type': 'Date'
            }
        );
    }

    /**
     * Log messages from Parse look like:
     * {
     *     timestamp: {
     *         __type: 'Date',
     *         iso: '2014-06-10T21:03:24.877Z'
     *     },
     *     message: 'I2014-06-10T21:03:24.877Z] blah blah blah'
     * }
     */
    function parseDateFromMessage(message) {
        var dateString = message.timestamp.iso;
        var date = new Date(dateString);
        return date;
    }

    function printMessages(messages) {
        if (!_.isArray(messages)) {
            messages = [ messages ];
        }

        for (var i in messages) {
            console.log(messages[i].message);
        }
    }

    this.fetchLog = function(startTime, lines, level) {
        var requestParameters = {};

        if (lines === undefined) {
            lines = 10;
        }
        if (level === undefined) {
            level = 'INFO';
        }

        assert(_.isNumber(lines) && lines > 0,
               '"lines" must be a number greater than 0');
        assert(level === 'INFO' || level === 'ERROR',
               '"level" must be INFO or ERROR');

        if (startTime) {
            requestParameters.startTime = generateStarTimeJSON(startTime);
        }
        requestParameters.n = lines;
        requestParameters.level = level;

        var promise = new Parse.Promise();

        request.get(
            {
                url: parseLogAPI,
                method: 'GET',
                headers: {
                    'X-Parse-Application-Id': applicationId,
                    'X-Parse-Master-Key':     masterKey
                },
                qs: requestParameters
            },
            function(error, response, body) {
                if (response.statusCode === 200) {
                    var messages = {};
                    try {
                        messages = JSON.parse(body);
                    } catch (e) {
                        console.error('Invalid response:\n' + body);
                    }
                    // reverse messages to place them in chronological order
                    messages.reverse();
                    promise.resolve(messages);
                } else {
                    promise.reject('HTTP error: ' + response.statusCode + '\n\n' + body);
                }
            }
        );

        return promise;
    }

    this.tailLog = function(startTime, lines) {
        // Set up a higher scope variable since setInterval doesn't play nice
        // with parameters
        var lastTailStartTime = startTime;
        var self = this;

        function loopableTail() {
            self.fetchLog(lastTailStartTime, lines).then(
                function(messages) {
                    if (messages.length > 0) {
                        // grab the last time in the messages to use as the new
                        // startTime
                        var nextDate = parseDateFromMessage(
                                        messages[messages.length - 1]);
                        lastTailStartTime = nextDate.toISOString();
                        printMessages(messages);
                    }
                }
            );
        }

        var tailInternval = setInterval(loopableTail, tailDelay);
    }
}

module.exports = ParseLogger;
<commit_msg>trying a message buffering technique<commit_after>'use strict'

/**
 * Javascript class to interact with a Parse application's logs.
 */

var assert = require('assert');
var _ = require('underscore');
var Parse = require('parse').Parse;
var request = require('request');

var ParseLogger = function(applicationId,
                           masterKey) {

    var parseLogAPI = 'https://api.parse.com/1/scriptlog';
    var tailDelay = 4000;

    function generateStarTimeJSON(date) {
        assert(date, '"date" is a required parameter');

        if (_.isString(date)) {
            date = new Date(date).toISOString();
        } else {
            date = date.toISOString();
        }

        return JSON.stringify(
            {
                'iso':    date,
                '__type': 'Date'
            }
        );
    }

    /**
     * Log messages from Parse look like:
     * {
     *     timestamp: {
     *         __type: 'Date',
     *         iso: '2014-06-10T21:03:24.877Z'
     *     },
     *     message: 'I2014-06-10T21:03:24.877Z] blah blah blah'
     * }
     */
    function parseDateFromMessage(message) {
        var dateString = message.timestamp.iso;
        var date = new Date(dateString);
        return date;
    }

    function printMessages(messages) {
        if (!_.isArray(messages)) {
            messages = [ messages ];
        }

        var message = null;
        var firstCharacter;
        for (var i in messages) {
            firstCharacter = messages[i].message[0];
            if (firstCharacter === 'I' ||
                firstCharacter === 'E')
            {
                // This means we're starting a new line. Print the accumulated
                // message and start buffering a new one.
                if (message !== null) {
                    console.log(message);
                }
                message = messages[i].message;
            } else {
                message = message + '\n' + messages[i].message;
            }
        }
    }

    this.fetchLog = function(startTime, lines, level) {
        var requestParameters = {};

        if (lines === undefined) {
            lines = 10;
        }
        if (level === undefined) {
            level = 'INFO';
        }

        assert(_.isNumber(lines) && lines > 0,
               '"lines" must be a number greater than 0');
        assert(level === 'INFO' || level === 'ERROR',
               '"level" must be INFO or ERROR');

        if (startTime) {
            requestParameters.startTime = generateStarTimeJSON(startTime);
        }
        requestParameters.n = lines;
        requestParameters.level = level;

        var promise = new Parse.Promise();

        request.get(
            {
                url: parseLogAPI,
                method: 'GET',
                headers: {
                    'X-Parse-Application-Id': applicationId,
                    'X-Parse-Master-Key':     masterKey
                },
                qs: requestParameters
            },
            function(error, response, body) {
                if (response.statusCode === 200) {
                    var messages = {};
                    try {
                        messages = JSON.parse(body);
                    } catch (e) {
                        console.error('Invalid response:\n' + body);
                    }
                    // reverse messages to place them in chronological order
                    messages.reverse();
                    promise.resolve(messages);
                } else {
                    promise.reject('HTTP error: ' + response.statusCode + '\n\n' + body);
                }
            }
        );

        return promise;
    }

    this.tailLog = function(startTime, lines) {
        // Set up a higher scope variable since setInterval doesn't play nice
        // with parameters
        var lastTailStartTime = startTime;
        var self = this;

        function loopableTail() {
            self.fetchLog(lastTailStartTime, lines).then(
                function(messages) {
                    if (messages.length > 0) {
                        // grab the last time in the messages to use as the new
                        // startTime
                        var nextDate = parseDateFromMessage(
                                        messages[messages.length - 1]);
                        lastTailStartTime = nextDate.toISOString();
                        printMessages(messages);
                    }
                }
            );
        }

        var tailInternval = setInterval(loopableTail, tailDelay);
    }
}

module.exports = ParseLogger;
<|endoftext|>


<commit_before>// JavaScript Document

$(document).ready(function(){

	//Go up

	$('.go-up-footer').click(function() {
		$('body,html').animate({
			scrollTop:0
		}, 800, 'easeOutExpo');
		return false;
	});

	//Checkboxes

	$('.checkbox-one').click(function(){
		$(this).toggleClass('checkbox-one-checked');
		return false;
	});
	$('.checkbox-two').click(function(){
		$(this).toggleClass('checkbox-two-checked');
		return false;
	});
	$('.checkbox-three').click(function(){
		$(this).toggleClass('checkbox-three-checked');
		return false;
	});
	$('.radio-one').click(function(){
		$(this).toggleClass('radio-one-checked');
		return false;
	});
	$('.radio-two').click(function(){
		$(this).toggleClass('radio-two-checked');
		return false;
	});

	//Notifications

	$('.tap-dismiss-notification').click(function(){
		$(this).fadeOut();
		return false;
	});

	$('.close-big-notification').click(function(){
		$(this).parent().fadeOut();
		return false;
	});

	//Tabs

	$('.tab-but-1').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-1').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-1').show(100);
		return false;
	});

	$('.tab-but-2').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-2').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-2').show(100);
		return false;
	});

	$('.tab-but-3').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-3').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-3').show(100);
		return false;
	});

	$('.tab-but-4').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-4').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-4').show(100);
		return false;
	});

	$('.tab-but-5').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-5').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-5').show(100);
		return false;
	});

	//Toggles

	$('.deploy-toggle-1').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).toggleClass('toggle-1-active');
		return false;
	});

	$('.deploy-toggle-2').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).toggleClass('toggle-2-active');
		return false;
	});

	$('.deploy-toggle-3').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).find('em strong').toggleClass('toggle-3-active-ball');
		$(this).find('em').toggleClass('toggle-3-active-background');
		return false;
	});

	//Submenu Nav

	$('.submenu-nav-deploy').click(function(){
		$(this).toggleClass('submenu-nav-deploy-active');
		$(this).parent().find('.submenu-nav-items').toggle(100);
		return false;
	});

	//Sliding Door

	$('.sliding-door-top').click(function(){
		$(this).animate({
			left:'101%'
		}, 500, 'easeInOutExpo');
		return false;
	});

	$('.sliding-door-bottom a em').click(function(){
		$(this).parent().parent().parent().find('.sliding-door-top').animate({
			left:'0px'
		}, 500, 'easeOutBounce');
		return false

	});

	//Detect user agent for known mobile devices and show hide elements for each specific element
	var isiPhone = 	  navigator.userAgent.toLowerCase().indexOf("iphone");
	var isiPad = 		navigator.userAgent.toLowerCase().indexOf("ipad");
	var isiPod = 		navigator.userAgent.toLowerCase().indexOf("ipod");
	var isiAndroid = 	navigator.userAgent.toLowerCase().indexOf("android");

	if(isiPhone > -1) 	 {		   $('.ipod-detected').hide();		 $('.ipad-detected').hide();		 $('.iphone-detected').show();		 $('.android-detected').hide();	 }
	if(isiPad > -1)	 {		 	 $('.ipod-detected').hide();		 $('.ipad-detected').show();		 $('.iphone-detected').hide();		 $('.android-detected').hide();	 }
	if(isiPod > -1)	 {		 	 $('.ipod-detected').show();		 $('.ipad-detected').hide();		 $('.iphone-detected').hide();		 $('.android-detected').hide();	 }
	if(isiAndroid > -1) {			 $('.ipod-detected').hide();		 $('.ipad-detected').hide();		 $('.iphone-detected').hide();		 $('.android-detected').show();	 }

});

<commit_msg>快速捷操作列表<commit_after>// JavaScript Document

$(document).ready(function(){

	//Go up

	$('.go-up-footer').click(function() {
		$('body,html').animate({
			scrollTop:0
		}, 800, 'easeOutExpo');
		return false;
	});

	//Checkboxes

	$('.checkbox-one').click(function(){
		$(this).toggleClass('checkbox-one-checked');
		return false;
	});
	$('.checkbox-two').click(function(){
		$(this).toggleClass('checkbox-two-checked');
		return false;
	});
	$('.checkbox-three').click(function(){
		$(this).toggleClass('checkbox-three-checked');
		return false;
	});
	$('.radio-one').click(function(){
		$(this).toggleClass('radio-one-checked');
		return false;
	});
	$('.radio-two').click(function(){
		$(this).toggleClass('radio-two-checked');
		return false;
	});

	//Notifications

	$('.tap-dismiss-notification').click(function(){
		$(this).fadeOut();
		return false;
	});

	$('.close-big-notification').click(function(){
		$(this).parent().fadeOut();
		return false;
	});

	//Tabs

	$('.tab-but-1').click(function(){
	//	$('.tab-but').removeClass('tab-active');
	//	$('.tab-but-1').addClass('tab-active');
	//	$('.tab-content').hide(100);
	//	$('.tab-content-1').show(100);
	//	return false;
	});

	$('.tab-but-2').click(function(){
	//	$('.tab-but').removeClass('tab-active');
	//	$('.tab-but-2').addClass('tab-active');
	//	$('.tab-content').hide(100);
	//	$('.tab-content-2').show(100);
	//	return false;
	});

	$('.tab-but-3').click(function(){
	//	$('.tab-but').removeClass('tab-active');
	//	$('.tab-but-3').addClass('tab-active');
	//	$('.tab-content').hide(100);
	//	$('.tab-content-3').show(100);
	//	return false;
	});

	$('.tab-but-4').click(function(){
	//	$('.tab-but').removeClass('tab-active');
	//	$('.tab-but-4').addClass('tab-active');
	//	$('.tab-content').hide(100);
	//	$('.tab-content-4').show(100);
	//	return false;
	});

	$('.tab-but-5').click(function(){
		$('.tab-but').removeClass('tab-active');
		$('.tab-but-5').addClass('tab-active');
		$('.tab-content').hide(100);
		$('.tab-content-5').show(100);
		return false;
	});

	//Toggles

	$('.deploy-toggle-1').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).toggleClass('toggle-1-active');
		return false;
	});

	$('.deploy-toggle-2').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).toggleClass('toggle-2-active');
		return false;
	});

	$('.deploy-toggle-3').click(function(){
		$(this).parent().find('.toggle-content').toggle(100);
		$(this).find('em strong').toggleClass('toggle-3-active-ball');
		$(this).find('em').toggleClass('toggle-3-active-background');
		return false;
	});

	//Submenu Nav

	$('.submenu-nav-deploy').click(function(){
		$(this).toggleClass('submenu-nav-deploy-active');
		$(this).parent().find('.submenu-nav-items').toggle(100);
		return false;
	});

	//Sliding Door

	$('.sliding-door-top').click(function(){
		$(this).animate({
			left:'101%'
		}, 500, 'easeInOutExpo');
		return false;
	});

	$('.sliding-door-bottom a em').click(function(){
		$(this).parent().parent().parent().find('.sliding-door-top').animate({
			left:'0px'
		}, 500, 'easeOutBounce');
		return false

	});

	//Detect user agent for known mobile devices and show hide elements for each specific element
	var isiPhone = 	  navigator.userAgent.toLowerCase().indexOf("iphone");
	var isiPad = 		navigator.userAgent.toLowerCase().indexOf("ipad");
	var isiPod = 		navigator.userAgent.toLowerCase().indexOf("ipod");
	var isiAndroid = 	navigator.userAgent.toLowerCase().indexOf("android");

	if(isiPhone > -1) 	 {		   $('.ipod-detected').hide();		 $('.ipad-detected').hide();		 $('.iphone-detected').show();		 $('.android-detected').hide();	 }
	if(isiPad > -1)	 {		 	 $('.ipod-detected').hide();		 $('.ipad-detected').show();		 $('.iphone-detected').hide();		 $('.android-detected').hide();	 }
	if(isiPod > -1)	 {		 	 $('.ipod-detected').show();		 $('.ipad-detected').hide();		 $('.iphone-detected').hide();		 $('.android-detected').hide();	 }
	if(isiAndroid > -1) {			 $('.ipod-detected').hide();		 $('.ipad-detected').hide();		 $('.iphone-detected').hide();		 $('.android-detected').show();	 }

});

<|endoftext|>


<commit_before>function isHex(code) {
    return (code >= 48 && code <= 57) || // 0 .. 9
           (code >= 65 && code <= 70) || // A .. F
           (code >= 97 && code <= 102);  // a .. f
}

function cmpStr(testStr, start, end, referenceStr) {
    if (start < 0 || end > testStr.length) {
        return false;
    }

    if (end - start !== referenceStr.length) {
        return false;
    }

    for (var i = start; i < end; i++) {
        var sourceCode = testStr.charCodeAt(i);
        var strCode = referenceStr.charCodeAt(i - start);

        // referenceStr[i].toLowerCase()
        if (sourceCode >= 65 && sourceCode <= 90) {
            sourceCode = sourceCode | 32;
        }

        if (sourceCode !== strCode) {
            return false;
        }
    }

    return true;
}

function endsWith(testStr, referenceStr) {
    return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
}

module.exports = {
    isHex: isHex,
    cmpStr: cmpStr,
    endsWith: endsWith
};
<commit_msg>condition that cuts more goes first<commit_after>function isHex(code) {
    return (code >= 48 && code <= 57) || // 0 .. 9
           (code >= 65 && code <= 70) || // A .. F
           (code >= 97 && code <= 102);  // a .. f
}

function cmpStr(testStr, start, end, referenceStr) {
    if (end - start !== referenceStr.length) {
        return false;
    }

    if (start < 0 || end > testStr.length) {
        return false;
    }

    for (var i = start; i < end; i++) {
        var sourceCode = testStr.charCodeAt(i);
        var strCode = referenceStr.charCodeAt(i - start);

        // referenceStr[i].toLowerCase()
        if (sourceCode >= 65 && sourceCode <= 90) {
            sourceCode = sourceCode | 32;
        }

        if (sourceCode !== strCode) {
            return false;
        }
    }

    return true;
}

function endsWith(testStr, referenceStr) {
    return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
}

module.exports = {
    isHex: isHex,
    cmpStr: cmpStr,
    endsWith: endsWith
};
<|endoftext|>


<commit_before>'use strict'
var Event = require('vigour-js/lib/event')
var Property = require('../property')
var Element = require('../element')
var test = /\$vp/
var cnt = 0

function render (node, event, player) {
  let exec = this.exec
  if (exec) {
    console.log('kanker:', this.key, this.val, 'ready:', player.ready.val === true)
    if (player.ready.val === true) {
      exec.apply(this, arguments)
    }
  }
}

var VideoProperty = new Property({
  inject: [
    require('vigour-js/lib/operator/type')
  ],
  define: {
    render,
    set (val, event) {
      let type = typeof val
      if (!val || type === 'boolean' || type === 'number' || type === 'string') {
        if (val !== this._input) {
          this._input = val
          if (event === void 0) {
            this._on.data.execInternal(this, event = new Event('data'))
            event.trigger()
          } else {
            this._on.data.execInternal(this, event)
          }
        }
      } else {
        Property.prototype.set.apply(this, arguments)
      }
    }
  },
  properties: {
    exec (val) {
      this.define({
        exec: val
      })
    }
  },
  ChildConstructor: 'Constructor'
}).Constructor

var Player = new Element({
  properties: {
    options: true,
    _interval: true,
    _timeouts: {
      val: {}
    }
  },
  // inject: require('vigour-track'),
  ChildConstructor: VideoProperty,
  define: {
    isProgress (event) {
      return test.test(event.stamp)
    },
    toggle () {
      this.play.origin.set(!this.play.val)
    },
    getNodeDelete (block, blocknode, hashed) {
      for (var id in this._timeouts) {
        clearTimeout(this._timeouts[id])
        this._timeouts[id] = null
      }
      if (this._interval) {
        clearInterval(this._interval)
        this._interval = null
      }
      this.dispose()
      this.each(function () {
      }, function (prop) {
        if (prop instanceof VideoProperty) {
          let type = typeof prop._input
          if (type === 'boolean' || type === 'number' || type === 'string') {
            delete prop._input
          }
        }
      })

      Element.prototype.getNodeDelete.apply(this, arguments)
    },
    timeout (id, fn, time) {
      if (typeof id === 'function') {
        time = fn
        fn = id
      }
      if (this._timeouts[id]) {
        clearTimeout(this._timeouts[id])
        this._timeouts[id] = null
      }
      let player = this
      let store = player.storeContext()
      this._timeouts[id] = setTimeout(function () {
        player.applyContext(store)
        fn(player)
      }, time)
    }
  },
  time: {},
  ready: {
    render (node, event, player) {
      var val = this.val
      if (val === true) {
        player.each(function (prop, key) {
        }, function (prop, key) {
          if (prop && prop.exec && key !== 'ready') {
            prop.exec(node, event, player)
          }
        })
      }
    }
  },
  play: {
    val: false,
    exec (node, e, player) {
      console.log('play:', this.val)
      if (this.val) {
        console.log('interval:', player._interval)
        if (!player._interval) {
          let store = player.storeContext()
          player._interval = setInterval(function () {
            player.applyContext(store)
            let time = player.getTime()
            if (time) {
              let stamp = '$vp' + (cnt++)
              let event = new Event(
                'data',
                stamp
              )
              console.log('time:', time)
              player.time.origin.set(time, event)//, event)
              event.trigger()
            }
            // let buffer = player.getBuffer()
            // player.buffer.origin.set(buffer, event)
          }, 500)
        }
      } else {
        if (player._interval) {
          clearInterval(player._interval)
          player._interval = null
        }
      }
    },
    track: {
      data: true
    }
  },
  duration: 0,
  volume: {
    $type: { range: [ 0, 1 ] }
  },
  mute: {
    $type: 'boolean'
  },
  fullscreen: {
    $type: 'boolean'
  },
  buffer: {
    $type: { range: [ 0, 1 ] }
  },
  ad: {
    src: {
      $type: 'string'
    },
    play: {
      $type: 'boolean'
    },
    volume: {
      $type: { range: [ 0, 1 ] }
    },
    duration: {
      $type: 'number'
    },
    buffer: {
      $type: { range: [ 0, 1 ] }
    },
    canSkip: {
      $type: 'boolean'
    },
    skip: {
      $type: 'boolean'
    }
  }
})

module.exports = exports = Player.Constructor
exports.Property = VideoProperty
<commit_msg>removed player logs<commit_after>'use strict'
var Event = require('vigour-js/lib/event')
var Property = require('../property')
var Element = require('../element')
var test = /\$vp/
var cnt = 0

function render (node, event, player) {
  let exec = this.exec
  if (exec) {
    if (player.ready.val === true) {
      exec.apply(this, arguments)
    }
  }
}

var VideoProperty = new Property({
  inject: [
    require('vigour-js/lib/operator/type')
  ],
  define: {
    render,
    set (val, event) {
      let type = typeof val
      if (!val || type === 'boolean' || type === 'number' || type === 'string') {
        if (val !== this._input) {
          this._input = val
          if (event === void 0) {
            this._on.data.execInternal(this, event = new Event('data'))
            event.trigger()
          } else {
            this._on.data.execInternal(this, event)
          }
        }
      } else {
        Property.prototype.set.apply(this, arguments)
      }
    }
  },
  properties: {
    exec (val) {
      this.define({
        exec: val
      })
    }
  },
  ChildConstructor: 'Constructor'
}).Constructor

var Player = new Element({
  properties: {
    options: true,
    _interval: true,
    _timeouts: {
      val: {}
    }
  },
  // inject: require('vigour-track'),
  ChildConstructor: VideoProperty,
  define: {
    isProgress (event) {
      return test.test(event.stamp)
    },
    toggle () {
      this.play.origin.set(!this.play.val)
    },
    getNodeDelete (block, blocknode, hashed) {
      for (var id in this._timeouts) {
        clearTimeout(this._timeouts[id])
        this._timeouts[id] = null
      }
      if (this._interval) {
        clearInterval(this._interval)
        this._interval = null
      }
      this.dispose()
      this.each(function () {
      }, function (prop) {
        if (prop instanceof VideoProperty) {
          let type = typeof prop._input
          if (type === 'boolean' || type === 'number' || type === 'string') {
            delete prop._input
          }
        }
      })

      Element.prototype.getNodeDelete.apply(this, arguments)
    },
    timeout (id, fn, time) {
      if (typeof id === 'function') {
        time = fn
        fn = id
      }
      if (this._timeouts[id]) {
        clearTimeout(this._timeouts[id])
        this._timeouts[id] = null
      }
      let player = this
      let store = player.storeContext()
      this._timeouts[id] = setTimeout(function () {
        player.applyContext(store)
        fn(player)
      }, time)
    }
  },
  time: {},
  ready: {
    render (node, event, player) {
      var val = this.val
      if (val === true) {
        player.each(function (prop, key) {
        }, function (prop, key) {
          if (prop && prop.exec && key !== 'ready') {
            prop.exec(node, event, player)
          }
        })
      }
    }
  },
  play: {
    val: false,
    exec (node, e, player) {
      if (this.val) {
        if (!player._interval) {
          let store = player.storeContext()
          player._interval = setInterval(function () {
            player.applyContext(store)
            let time = player.getTime()
            if (time) {
              let stamp = '$vp' + (cnt++)
              let event = new Event(
                'data',
                stamp
              )
              player.time.origin.set(time, event)//, event)
              event.trigger()
            }
            // let buffer = player.getBuffer()
            // player.buffer.origin.set(buffer, event)
          }, 500)
        }
      } else {
        if (player._interval) {
          clearInterval(player._interval)
          player._interval = null
        }
      }
    },
    track: {
      data: true
    }
  },
  duration: 0,
  volume: {
    $type: { range: [ 0, 1 ] }
  },
  mute: {
    $type: 'boolean'
  },
  fullscreen: {
    $type: 'boolean'
  },
  buffer: {
    $type: { range: [ 0, 1 ] }
  },
  ad: {
    src: {
      $type: 'string'
    },
    play: {
      $type: 'boolean'
    },
    volume: {
      $type: { range: [ 0, 1 ] }
    },
    duration: {
      $type: 'number'
    },
    buffer: {
      $type: { range: [ 0, 1 ] }
    },
    canSkip: {
      $type: 'boolean'
    },
    skip: {
      $type: 'boolean'
    }
  }
})

module.exports = exports = Player.Constructor
exports.Property = VideoProperty
<|endoftext|>