<commit_before>/*!
 * LocalModel
 * Developer: Rick Craig
 * https://github.com/RickCraig/localmodel
 */

'use strict';

/**
 * Generates a random UUID
 * @private
 * @returns {String} random id
 */
var generateUUID = function(){
  var d = Date.now();
  var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    .replace(/[xy]/g, function(c) {
      var r = (d + Math.random()*16)%16 | 0;
      d = Math.floor(d/16);
      return (c==='x' ? r : (r&0x3|0x8)).toString(16);
    });
  return uuid;
};

/**
 * Builds the key for the data
 * @private
 * @param {String} name - of the model
 * @param {String} id - of the entry
 * @returns {String} the merged key name
 */
var getKey = function(name, id) {
  return name + '::' + id;
};

/**
 * Adds the index for the new entry
 * @private
 * @param {String} name - the name of the model
 * @param {String} newIndex - the key for the new entry
 */
var addIndex = function(name, newIndex) {
  var indexName = name + '-index';
  var indexString = localStorage.getItem(indexName);
  var indices = indexString ? JSON.parse(indexString) : [];
  indices.push(newIndex);
  localStorage.setItem(indexName, JSON.stringify(indices));
};

/**
 * Returns the indices for a model
 * @private
 * @param {String} name - the model name
 * @returns {Array} the indices
 */
var getIndices = function(name) {
  var indices = localStorage.getItem(name + '-index');
  return JSON.parse(indices);
};

/**
 * Get a specific index from the indices
 * @private
 * @param {Array} indices
 * @param {String} term
 * @returns {String} matching index
 */
var getIndex = function(indices, term) {
  var regex = new RegExp('::' + term, 'g');
  for (var i = 0; i < indices.length; i++) {
    var index = indices[i];
    if (regex.test(index)) {
      return index;
    }
  }
  return;
};

/**
 * Checks if an object is empty
 * @private
 * @param {Object} obj
 * @returns {Boolean} true if empty
 */
var isEmpty = function(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      return false;
    }
  }
  return true;
};

/**
 * Takes in a data string and returns
 * true if query matches
 * @private
 * @param {String} data - the string to match
 * @param {Mixed} query
 * @returns {Boolean} true if the data matches the query
 */
var matchQuery = function(data, query) {
  // Query using regular expression
  if (query instanceof RegExp) {
    return queryItem.test(data);
  }

  // Query using string
  if (typeof query === 'string') {
    return data === query;
  }

  if (typeof query === 'object') {
    // Do the business in here for $gte, $gt, $lte, $lt
    // Remember to tag this 0.0.2
  }
};

/**
 * Checks an array of booleans for a false
 * @private
 * @param {Array} arr - an array of booleans
 * @returns {Boolean} true if contains a false
 */
var containsFalse = function(arr) {
  for (var i = 0; i < arr.length; i++) {
    if (!arr[i]) {
      return true;
    }
  }
  return false;
};

/**
 * Local Schema constructor
 * @public
 * @param {Object} schema
 */
var LocalSchema = function(name, schema) {
  this.schema = schema;
  this.name = name;
};

/**
 * Create a new data object for this schema
 * @public
 * @param {Object} data
 * @returns {}
 */
LocalSchema.prototype.create = function(data) {
  var newEntry = {};
  newEntry._id = generateUUID();
  for (var key in this.schema) {
    newEntry[key] = data[key];
  }

  // Save to localstorage
  // At some point if there is an index, it can be added the the key for speed
  var index = getKey(this.name, newEntry._id);
  localStorage.setItem(index, JSON.stringify(newEntry));
  addIndex(this.name, index);

  // Clear indices
  this.indices = null;

  return newEntry;
};

/**
 * Returns all entries in storage
 */
LocalSchema.prototype.all = function() {
  this.indices = this.indices || getIndices(this.name);
  var results = [];
  for (var i = 0; i < this.indices.length; i++) {
    var index = this.indices[i];
    var result = JSON.parse(localStorage.getItem(index));
    results.push(result);
  }
  return results;
};

/**
 * Find an entry by ID
 * @public
 * @param {String} id
 * @returns {Object} the object or null
 */
LocalSchema.prototype.findById = function(id) {
  this.indices = this.indices || getIndices(this.name);
  var match = getIndex(this.indices, id);
  if (!match) {
    return null;
  }
  return JSON.parse(localStorage.getItem(match));
};

/**
 * Find entries matching a query
 * @public
 * @param {Object} query
 * @returns {Array} an array of matches
 */
LocalSchema.prototype.find = function(query) {
  if (!query || isEmpty(query)) {
    return this.all();
  }

  this.indices = this.indices || getIndices(this.name);
  var results = [];
  for (var i = 0; i < this.indices.length; i++) {
    var entry = localStorage.getItem(this.indices[i]);
    entry = JSON.parse(entry);
    var matches = [];

    for (var key in query) {
      var queryItem = query[key];
      if (!queryItem) { continue; }
      matches.push(matchQuery(entry[key], queryItem));
    }

    if (!containsFalse(matches)) {
      results.push(entry);
    }
  }
  return results;
};

/**
 * LocalSchema Schema Types
 * For use in validation and return
 * @public
 */
LocalSchema.SchemaTypes = {
  String: 'string',
  Number: 'number',
  Boolean: 'boolean',
  Mixed: 'mixed'
};

/**
 * LocalModel constructor
 * @public
 * @param {Object} options
 */

var LocalModel = function(options) {
  this.options = options || {};
  this.models = {};
};

/**
 * Adds a model schema to the list of models
 * @public
 * @param {String} name - the name of the model
 * @param {Object} schema - the schema for the model
 * @returns {Object} the schema;
 */
LocalModel.prototype.addModel = function(name, schema) {
  var model = new LocalSchema(name, schema);
  this.models[name] = model;
  return model;
};

/**
 * Returns the schema for the model by name
 * @public
 * @param {String} name - the name of the model
 * @returns {Object} the model schema
 */
LocalModel.prototype.model = function(name) {
  if (!this.models[name]) {
    console.error('The model with name "' + name + '" does not exist.');
    return null;
  }
  return this.models[name];
};
<commit_msg>Added the $gte, $gt, $lte, $lt to query<commit_after>/*!
 * LocalModel
 * Developer: Rick Craig
 * https://github.com/RickCraig/localmodel
 */

'use strict';

/**
 * Generates a random UUID
 * @private
 * @returns {String} random id
 */
var generateUUID = function(){
  var d = Date.now();
  var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    .replace(/[xy]/g, function(c) {
      var r = (d + Math.random()*16)%16 | 0;
      d = Math.floor(d/16);
      return (c==='x' ? r : (r&0x3|0x8)).toString(16);
    });
  return uuid;
};

/**
 * Builds the key for the data
 * @private
 * @param {String} name - of the model
 * @param {String} id - of the entry
 * @returns {String} the merged key name
 */
var getKey = function(name, id) {
  return name + '::' + id;
};

/**
 * Adds the index for the new entry
 * @private
 * @param {String} name - the name of the model
 * @param {String} newIndex - the key for the new entry
 */
var addIndex = function(name, newIndex) {
  var indexName = name + '-index';
  var indexString = localStorage.getItem(indexName);
  var indices = indexString ? JSON.parse(indexString) : [];
  indices.push(newIndex);
  localStorage.setItem(indexName, JSON.stringify(indices));
};

/**
 * Returns the indices for a model
 * @private
 * @param {String} name - the model name
 * @returns {Array} the indices
 */
var getIndices = function(name) {
  var indices = localStorage.getItem(name + '-index');
  return JSON.parse(indices);
};

/**
 * Get a specific index from the indices
 * @private
 * @param {Array} indices
 * @param {String} term
 * @returns {String} matching index
 */
var getIndex = function(indices, term) {
  var regex = new RegExp('::' + term, 'g');
  for (var i = 0; i < indices.length; i++) {
    var index = indices[i];
    if (regex.test(index)) {
      return index;
    }
  }
  return;
};

/**
 * Checks if an object is empty
 * @private
 * @param {Object} obj
 * @returns {Boolean} true if empty
 */
var isEmpty = function(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      return false;
    }
  }
  return true;
};

/**
 * Takes in a data string and returns
 * true if query matches
 * @private
 * @param {String} data - the string to match
 * @param {Mixed} query
 * @returns {Boolean} true if the data matches the query
 */
var matchQuery = function(data, query) {
  // Query using regular expression
  if (query instanceof RegExp) {
    return query.test(data);
  }

  // Query using string
  if (typeof query === 'string') {
    return data === query;
  }

  if (typeof query === 'object') {
    // Do the business in here for $gte, $gt, $lte, $lt
    // Remember to tag this 0.0.2

    if (typeof data === 'number') {
      var matches = [];
      if (query.$gte) {
        matches.push(query.$gte <= data);
      }

      if (query.$gt) {
        matches.push(query.$gt < data);
      }

      if (query.$lte) {
        matches.push(query.$lte >= data);
      }

      if (query.$lt) {
        matches.push(query.$lt > data);
      }

      return !containsFalse(matches);
    }

  }
};

/**
 * Checks an array of booleans for a false
 * @private
 * @param {Array} arr - an array of booleans
 * @returns {Boolean} true if contains a false
 */
var containsFalse = function(arr) {
  for (var i = 0; i < arr.length; i++) {
    if (!arr[i]) {
      return true;
    }
  }
  return false;
};

/**
 * Local Schema constructor
 * @public
 * @param {Object} schema
 */
var LocalSchema = function(name, schema) {
  this.schema = schema;
  this.name = name;
};

/**
 * Create a new data object for this schema
 * @public
 * @param {Object} data
 * @returns {}
 */
LocalSchema.prototype.create = function(data) {
  var newEntry = {};
  newEntry._id = generateUUID();
  for (var key in this.schema) {
    newEntry[key] = data[key];
  }

  // Save to localstorage
  // At some point if there is an index, it can be added the the key for speed
  var index = getKey(this.name, newEntry._id);
  localStorage.setItem(index, JSON.stringify(newEntry));
  addIndex(this.name, index);

  // Clear indices
  this.indices = null;

  return newEntry;
};

/**
 * Returns all entries in storage
 */
LocalSchema.prototype.all = function() {
  this.indices = this.indices || getIndices(this.name);
  var results = [];
  for (var i = 0; i < this.indices.length; i++) {
    var index = this.indices[i];
    var result = JSON.parse(localStorage.getItem(index));
    results.push(result);
  }
  return results;
};

/**
 * Find an entry by ID
 * @public
 * @param {String} id
 * @returns {Object} the object or null
 */
LocalSchema.prototype.findById = function(id) {
  this.indices = this.indices || getIndices(this.name);
  var match = getIndex(this.indices, id);
  if (!match) {
    return null;
  }
  return JSON.parse(localStorage.getItem(match));
};

/**
 * Find entries matching a query
 * @public
 * @param {Object} query
 * @returns {Array} an array of matches
 */
LocalSchema.prototype.find = function(query) {
  if (!query || isEmpty(query)) {
    return this.all();
  }

  this.indices = this.indices || getIndices(this.name);
  var results = [];
  for (var i = 0; i < this.indices.length; i++) {
    var entry = localStorage.getItem(this.indices[i]);
    entry = JSON.parse(entry);
    var matches = [];

    for (var key in query) {
      var queryItem = query[key];
      if (!queryItem) { continue; }
      matches.push(matchQuery(entry[key], queryItem));
    }

    if (!containsFalse(matches)) {
      results.push(entry);
    }
  }
  return results;
};

/**
 * LocalSchema Schema Types
 * For use in validation and return
 * @public
 */
LocalSchema.SchemaTypes = {
  String: 'string',
  Number: 'number',
  Boolean: 'boolean',
  Mixed: 'mixed'
};

/**
 * LocalModel constructor
 * @public
 * @param {Object} options
 */

var LocalModel = function(options) {
  this.options = options || {};
  this.models = {};
};

/**
 * Adds a model schema to the list of models
 * @public
 * @param {String} name - the name of the model
 * @param {Object} schema - the schema for the model
 * @returns {Object} the schema;
 */
LocalModel.prototype.addModel = function(name, schema) {
  var model = new LocalSchema(name, schema);
  this.models[name] = model;
  return model;
};

/**
 * Returns the schema for the model by name
 * @public
 * @param {String} name - the name of the model
 * @returns {Object} the model schema
 */
LocalModel.prototype.model = function(name) {
  if (!this.models[name]) {
    console.error('The model with name "' + name + '" does not exist.');
    return null;
  }
  return this.models[name];
};
<|endoftext|>


<commit_before>module.exports = Em.Component.extend({
    classNames: ['modal-mask'],

    attributeBindings: ['style'],

    zIndex: 1000,

    style: function() {
        return 'z-index:'+this.get('zIndex')+';';
    }.property('zIndex'),

    show: function() {
        this.appendTo(this.container.lookup('application:main').get('rootElement'));
    },

    didInsertElement: function() {
        var self = this,
            el = this.$();
        setTimeout(function() {
            el.addClass('visible');
            self.blurBelowLayer(true);
        }, 0);
    },

    animateDestroy: function() {
        var el = this.$();
        el.removeClass('visible');
        this.blurBelowLayer(false);
        Em.run.later(this, function() {
            this.destroy();
        }, 300);
    },

    blurBelowLayer: function(blurred) {
        var zIndex = this.get('zIndex');
        var belowLayers = this.$().siblings('.application, .layer')
            .filter(function(index, s) {
                var sz = $(s).css('z-index');
                return (sz === 'auto' || sz < zIndex);
            });
        belowLayers[blurred ? 'addClass' : 'removeClass']('modal-mask-blur');
    }
});<commit_msg>Don't try to add visible class if modal-mask was destroyed right after didInsertElement<commit_after>module.exports = Em.Component.extend({
    classNames: ['modal-mask'],

    attributeBindings: ['style'],

    zIndex: 1000,

    style: function() {
        return 'z-index:'+this.get('zIndex')+';';
    }.property('zIndex'),

    show: function() {
        this.appendTo(this.container.lookup('application:main').get('rootElement'));
    },

    didInsertElement: function() {
        var self = this,
            el = this.$();
        Em.run.next(function() {
            if (self.get('isDestroying')) {
                return;
            }
            el.addClass('visible');
            self.blurBelowLayer(true);
        });
    },

    animateDestroy: function() {
        var el = this.$();
        el.removeClass('visible');
        this.blurBelowLayer(false);
        Em.run.later(this, function() {
            this.destroy();
        }, 300);
    },

    blurBelowLayer: function(blurred) {
        var zIndex = this.get('zIndex');
        var belowLayers = this.$().siblings('.application, .layer')
            .filter(function(index, s) {
                var sz = $(s).css('z-index');
                return (sz === 'auto' || sz < zIndex);
            });
        belowLayers[blurred ? 'addClass' : 'removeClass']('modal-mask-blur');
    }
});<|endoftext|>


<commit_before>/**
 * Transition plugin.
 *
 * @package Fundament
 */
;(function($) {
    'use strict';

    var plugin = 'transition';

    var transitionEndEvent = Fm.transitionEnd();

    // Constructor
    function Transition(element, animation, settings, onEnd) {
        var self = this;

        self.config = $.extend({}, $.fn[plugin].defaults, settings);
        self.elem   = element;
        self.$elem  = $(element);

        if (typeof onEnd === 'function')
            self.config.onEnd = onEnd; // onEnd shorthand
        if (settings == parseInt(settings))
            self.config.duration = settings; // duration shorthand
        else if (typeof settings === 'function')
            self.config.onEnd = settings; // onEnd shorthand

        (self.config.queue) ?
            self.$elem.queue(function() {
                self.init(animation);
            }): self.init(animation);
    }

    // Instance
    $.extend(Transition.prototype, {

        init: function(animation) {
            var self   = this,
                config = self.config;

            self.animation = self.parse(animation);

            if (self.animation == 'display') {
                return self.end();
            } else if ( ! config.animations.hasOwnProperty(self.animation)) {
                return console.warn('Trying to call an undefined animation');
            }

            if (transitionEndEvent) {
                self.$elem
                    .off(transitionEndEvent) // prevent any interruptions
                    .one(transitionEndEvent, function(e) {
                        e.stopPropagation(); // prevent event bubbling
                        self.end();
                    });
            } else {
                // Set a timer which functions as a fallback for the
                // unsupported transitionEnd event.
                setTimeout(self.end.bind(self), config.duration + config.delay);
            }

            // Create a separate queue entry to make sure previous
            // re-draw events are finished. This also notifies the
            // browser that the element is soon going to be animated.
            var fire = function() {
                requestAnimationFrame(self.start.bind(self));
            };

            config.delay == 0 ? fire() : setTimeout(fire, config.delay);
        },

        /**
         * Parses the animation and determines the transition direction.
         * Returns the base name of the animation.
         *
         * @param {string} animation
         * @return {string}
         */
        parse: function(animation) {
            if (animation.slice(-2) === 'In') {
                this.direction = 'inward';
                animation = animation.slice(0, -2);
            } else if (animation.slice(-3) === 'Out') {
                this.direction = 'outward';
                animation = animation.slice(0, -3);
            } else {
                this.direction = this.$elem.is(':visible') ? // toggle
                    'outward':
                    'inward' ;
            }

            return animation;
        },

        /**
         * Start the transition.
         */
        start: function() {
            var self = this;

            self.config.onStart.call(self.elem);

            self.$elem
                .css(self.style('start')) // apply start CSS
                .show(); // ensure visibility

            requestAnimationFrame(function() {
                self.$elem.css(self.style('end')); // apply end CSS
            });
        },

        /**
         * End the transition.
         */
        end: function() {
            var self  = this;

            self.toggleDisplay();

            self.config.onEnd.call(self.elem);

            self.$elem.css({
                'opacity'          : '',
                'transform'        : '',
                'transform-origin' : '',
                'transition'       : ''
            });

            if (self.config.queue)
                requestAnimationFrame(function() {
                    self.$elem.dequeue();
                });
        },

        /**
         * Toggle the display.
         */
        toggleDisplay: function() {
            this.direction === 'inward' ?
                this.$elem.show():
                this.$elem.hide();

            if (this.elem.hasAttribute('aria-hidden')) {
                this.$elem.attr('aria-hidden', this.direction !== 'inward');
            }
        },

        /**
         * Get the inline style for the transition.
         *
         * @param {string} state
         */
        style: function(state) {
            var self = this,
                animation = self.config.animations[self.animation],
                direction = self.direction,
                css;

            if (state === 'start') {
                css = (direction == 'inward') ?
                    animation.start:
                    animation.end; // reversed

                css.transition = null;
            } else {
                css = (direction == 'inward') ?
                    animation.end:
                    animation.start; // reversed

                css.transition = 'all ' +
                    self.config.duration + 'ms ' +
                    self.config.curve;
            }

            for (var attr in css) {
                var prefixed = Fm.prefixAttr(attr); // prefix attributes
                if (prefixed !== attr)
                    css[prefixed] = css[attr];
            }

            return css;
        }
    });

    // Plugin definition
    $.fn[plugin] = function(animation, settings, onEnd) {
        return this.each(function() {
            new Transition(this, animation, settings, onEnd);
        });
    };

    // Default settings
    $.fn[plugin].defaults = {
        duration : 280,
        delay    : 0,
        curve    : 'ease',
        queue    : true,
        onStart  : function() {},
        onEnd    : function() {}
    };

    $.fn[plugin].defaults.animations = {
        // fade
        fade: {
            start : { 'opacity': 0 },
            end   : { 'opacity': 1 }
        },
        fadeUp: {
            start : { 'opacity': 0, 'transform': 'translateY(10%)' },
            end   : { 'opacity': 1, 'transform': 'translateY(0)' }
        },
        fadeDown: {
            start : { 'opacity': 0, 'transform': 'translateY(-10%)' },
            end   : { 'opacity': 1, 'transform': 'translateY(0)' }
        },

        // scale
        scale: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)' }
        },
        scaleUp: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)', 'transform-origin': 'bottom' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)', 'transform-origin': 'bottom' }
        },
        scaleDown: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)', 'transform-origin': 'top' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)', 'transform-origin': 'top' }
        },

        // slide
        slideUp: {
            start : { 'opacity': 0.2, 'transform': 'scaleY(0.01)', 'transform-origin': 'bottom'},
            end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'bottom'}
        },
        slideDown: {
            start : { 'opacity': 0.2, 'transform': 'scaleY(0.01)', 'transform-origin': 'top'},
            end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'top'}
        },

        // flip
        flipX: {
            start : { 'opacity': 0, 'transform': 'perspective(2000px) rotateY(-90deg)' },
            end   : { 'opacity': 1, 'transform': 'perspective(2000px) rotateY(0deg)' }
        },
        flipY: {
            start : { 'opacity': 0, 'transform': 'perspective(2000px) rotateX(-90deg)' },
            end   : { 'opacity': 1, 'transform': 'perspective(2000px) rotateX(0deg)' }
        }
    };

})(jQuery);
<commit_msg>Correct type checking<commit_after>/**
 * Transition plugin.
 *
 * @package Fundament
 */
;(function($) {
    'use strict';

    var plugin = 'transition';

    var transitionEndEvent = Fm.transitionEnd();

    // Constructor
    function Transition(element, animation, settings, onEnd) {
        var self = this;

        self.config = $.extend({}, $.fn[plugin].defaults, settings);
        self.elem   = element;
        self.$elem  = $(element);

        if (typeof onEnd === 'function')
            self.config.onEnd = onEnd; // onEnd shorthand
        if (settings == parseInt(settings))
            self.config.duration = settings; // duration shorthand
        else if (typeof settings === 'function')
            self.config.onEnd = settings; // onEnd shorthand

        (self.config.queue) ?
            self.$elem.queue(function() {
                self.init(animation);
            }): self.init(animation);
    }

    // Instance
    $.extend(Transition.prototype, {

        init: function(animation) {
            var self   = this,
                config = self.config;

            self.animation = self.parse(animation);

            if (self.animation === 'display') {
                return self.end();
            } else if ( ! config.animations.hasOwnProperty(self.animation)) {
                return console.warn('Trying to call an undefined animation');
            }

            if (transitionEndEvent) {
                self.$elem
                    .off(transitionEndEvent) // prevent any interruptions
                    .one(transitionEndEvent, function(e) {
                        e.stopPropagation(); // prevent event bubbling
                        self.end();
                    });
            } else {
                // Set a timer which functions as a fallback for the
                // unsupported transitionEnd event.
                setTimeout(self.end.bind(self), config.duration + config.delay);
            }

            // Create a separate queue entry to make sure previous
            // re-draw events are finished. This also notifies the
            // browser that the element is soon going to be animated.
            var fire = function() {
                requestAnimationFrame(self.start.bind(self));
            };

            config.delay ? fire() : setTimeout(fire, config.delay);
        },

        /**
         * Parses the animation and determines the transition direction.
         * Returns the base name of the animation.
         *
         * @param {string} animation
         * @return {string}
         */
        parse: function(animation) {
            if (animation.slice(-2) === 'In') {
                this.direction = 'inward';
                animation = animation.slice(0, -2);
            } else if (animation.slice(-3) === 'Out') {
                this.direction = 'outward';
                animation = animation.slice(0, -3);
            } else {
                this.direction = this.$elem.is(':visible') ? // toggle
                    'outward':
                    'inward' ;
            }

            return animation;
        },

        /**
         * Start the transition.
         */
        start: function() {
            var self = this;

            self.config.onStart.call(self.elem);

            self.$elem
                .css(self.style('start')) // apply start CSS
                .show(); // ensure visibility

            requestAnimationFrame(function() {
                self.$elem.css(self.style('end')); // apply end CSS
            });
        },

        /**
         * End the transition.
         */
        end: function() {
            var self  = this;

            self.toggleDisplay();

            self.config.onEnd.call(self.elem);

            self.$elem.css({
                'opacity'          : '',
                'transform'        : '',
                'transform-origin' : '',
                'transition'       : ''
            });

            if (self.config.queue)
                requestAnimationFrame(function() {
                    self.$elem.dequeue();
                });
        },

        /**
         * Toggle the display.
         */
        toggleDisplay: function() {
            this.direction === 'inward' ?
                this.$elem.show():
                this.$elem.hide();

            if (this.elem.hasAttribute('aria-hidden')) {
                this.$elem.attr('aria-hidden', this.direction !== 'inward');
            }
        },

        /**
         * Get the inline style for the transition.
         *
         * @param {string} state
         */
        style: function(state) {
            var self = this,
                animation = self.config.animations[self.animation],
                direction = self.direction,
                css;

            if (state === 'start') {
                css = (direction === 'inward') ?
                    animation.start:
                    animation.end; // reversed

                css.transition = null;
            } else {
                css = (direction === 'inward') ?
                    animation.end:
                    animation.start; // reversed

                css.transition = 'all ' +
                    self.config.duration + 'ms ' +
                    self.config.curve;
            }

            for (var attr in css) {
                var prefixed = Fm.prefixAttr(attr); // prefix attributes
                if (prefixed !== attr)
                    css[prefixed] = css[attr];
            }

            return css;
        }
    });

    // Plugin definition
    $.fn[plugin] = function(animation, settings, onEnd) {
        return this.each(function() {
            new Transition(this, animation, settings, onEnd);
        });
    };

    // Default settings
    $.fn[plugin].defaults = {
        duration : 280,
        delay    : 0,
        curve    : 'ease',
        queue    : true,
        onStart  : function() {},
        onEnd    : function() {}
    };

    $.fn[plugin].defaults.animations = {
        // fade
        fade: {
            start : { 'opacity': 0 },
            end   : { 'opacity': 1 }
        },
        fadeUp: {
            start : { 'opacity': 0, 'transform': 'translateY(10%)' },
            end   : { 'opacity': 1, 'transform': 'translateY(0)' }
        },
        fadeDown: {
            start : { 'opacity': 0, 'transform': 'translateY(-10%)' },
            end   : { 'opacity': 1, 'transform': 'translateY(0)' }
        },

        // scale
        scale: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)' }
        },
        scaleUp: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)', 'transform-origin': 'bottom' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)', 'transform-origin': 'bottom' }
        },
        scaleDown: {
            start : { 'opacity': 0, 'transform': 'scale(0.6)', 'transform-origin': 'top' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)', 'transform-origin': 'top' }
        },

        // slide
        slideUp: {
            start : { 'opacity': 0.2, 'transform': 'scaleY(0.01)', 'transform-origin': 'bottom'},
            end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'bottom'}
        },
        slideDown: {
            start : { 'opacity': 0.2, 'transform': 'scaleY(0.01)', 'transform-origin': 'top'},
            end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'top'}
        },

        // flip
        flipX: {
            start : { 'opacity': 0, 'transform': 'perspective(2000px) rotateY(-90deg)' },
            end   : { 'opacity': 1, 'transform': 'perspective(2000px) rotateY(0deg)' }
        },
        flipY: {
            start : { 'opacity': 0, 'transform': 'perspective(2000px) rotateX(-90deg)' },
            end   : { 'opacity': 1, 'transform': 'perspective(2000px) rotateX(0deg)' }
        }
    };

})(jQuery);
<|endoftext|>


<commit_before>include("math/vector.js", true);

var Vec = EN.Vector;

EN.Controller = (function(){
    var m_eCanvas = null;

    var m_cBoundEvents = {
        "down": {},
        "move": {},
        "up": {}
    };

    var m_cKeyEvents = {};

    var m_nEventId = 0;

    function InputStart(e)
    {
        e.preventDefault();

        try
        {
            var nX = 0;
            var nY = 0;

            if (isset(e.changedTouches))
            {
                nX = e.changedTouches[0].clientX;
                nY = e.changedTouches[0].clientY;
            }
            else
            {
                nX = e.clientX;
                nY = e.clientY;
            }

            for (var sKey in m_cBoundEvents.down)
            {
                m_cBoundEvents.down[sKey](new Vec(nX, nY));
            }
        }
        catch (e)
        {
            console.error(e.stack);
            throw e;
        }

        return false;
    }

    function InputMove(e)
    {
        e.preventDefault();

        setTimeout(function(){
            try
            {
                var nX = 0;
                var nY = 0;

                if (isset(e.changedTouches))
                {
                    nX = e.changedTouches[0].clientX;
                    nY = e.changedTouches[0].clientY;
                }
                else
                {
                    nX = e.clientX;
                    nY = e.clientY;
                }

                for (var sKey in m_cBoundEvents.move)
                {
                    m_cBoundEvents.move[sKey](new Vec(nX, nY));
                }
            }
            catch (e)
            {
                console.error(e.stack);
                throw e;
            }
        }, 0);

        return false;
    }

    function InputEnd(e)
    {
        e.preventDefault();

        try
        {
            var nX = 0;
            var nY = 0;

            if (isset(e.changedTouches))
            {
                nX = e.changedTouches[0].clientX;
                nY = e.changedTouches[0].clientY;
            }
            else
            {
                nX = e.clientX;
                nY = e.clientY;
            }

            for (var sKey in m_cBoundEvents.up)
            {
                m_cBoundEvents.up[sKey](new Vec(nX, nY));
            }
        }
        catch (e)
        {
            console.error(e.stack);
            throw e;
        }

        return false;
    }

    function KeyDown(e)
    {
        m_cKeyEvents[e.keyCode] = true;
    }

    function KeyUp(e)
    {
        m_cKeyEvents[e.keyCode] = false;
    }

    return {
        Init: function(eCanvas){
            m_eCanvas = eCanvas;

            eCanvas.addEventListener("mousedown", InputStart);
            eCanvas.addEventListener("mousemove", InputMove);
            eCanvas.addEventListener("mouseup", InputEnd);

            //Detect platform and bind relevant events
            if (EN.Device.OS == EN.Device.SUPPORTED_OS.Windows || EN.Device.OS == EN.Device.SUPPORTED_OS.MacOSX)
            {
                window.onkeydown = KeyDown;
                window.onkeyup = KeyUp;
            }
            else
            {
                eCanvas.addEventListener("touchstart", InputStart);
                eCanvas.addEventListener("touchend", InputEnd);
            }
        },
        Bind: function(sEventType, fOnInput){
            var nId = m_nEventId++;

            m_cBoundEvents[sEventType][nId] = fOnInput;

            return nId;
        },
        Unbind: function(sEventType, nEventId){
            delete m_cBoundEvents[sEventType][nEventId];
        },
        GetKeyDown: function(nKey){
            return isset(m_cKeyEvents[nKey]) ? m_cKeyEvents[nKey] : false;
        }
    };
})();

EN.Controller.Keys = {
    UP: 38,
    DOWN: 40,
    LEFT: 37,
    RIGHT: 39,
    A: 65,
    Z: 90
};

//# sourceURL=engine/control/controller.js
<commit_msg>breaking change to the way controls are handled! Won't currently work on mobile<commit_after>include("math/vector.js", true);

var Vec = EN.Vector;

EN.Controller = (function(){
    var m_eCanvas = null;

    var m_cKeyEvents = {};
    var m_cButtonEvents = {};
    var m_cInputPos = new EN.Vector();
    var m_nScrollDelta = 0;

    function InputStart(e)
    {
        e.preventDefault();

        m_cButtonEvents[e.button] = true;

        /*try
        {
            var nX = 0;
            var nY = 0;

            if (isset(e.changedTouches))
            {
                nX = e.changedTouches[0].clientX;
                nY = e.changedTouches[0].clientY;
            }
            else
            {
                nX = e.clientX;
                nY = e.clientY;
            }

            for (var sKey in m_cBoundEvents.down)
            {
                m_cBoundEvents.down[sKey](new Vec(nX, nY));
            }
        }
        catch (e)
        {
            console.error(e.stack);
            throw e;
        }*/

        return false;
    }

    function InputMove(e)
    {
        m_cInputPos.x = e.clientX;
        m_cInputPos.y = e.clientY;

        /*setTimeout(function(){
            try
            {
                var nX = 0;
                var nY = 0;

                if (isset(e.changedTouches))
                {
                    nX = e.changedTouches[0].clientX;
                    nY = e.changedTouches[0].clientY;
                }
                else
                {
                    nX = e.clientX;
                    nY = e.clientY;
                }

                for (var sKey in m_cBoundEvents.move)
                {
                    m_cBoundEvents.move[sKey](new Vec(nX, nY));
                }
            }
            catch (e)
            {
                console.error(e.stack);
                throw e;
            }
        }, 0);*/
    }

    function InputEnd(e)
    {
        e.preventDefault();

        m_cButtonEvents[e.button] = false;

        /*try
        {
            var nX = 0;
            var nY = 0;

            if (isset(e.changedTouches))
            {
                nX = e.changedTouches[0].clientX;
                nY = e.changedTouches[0].clientY;
            }
            else
            {
                nX = e.clientX;
                nY = e.clientY;
            }

            for (var sKey in m_cBoundEvents.up)
            {
                m_cBoundEvents.up[sKey](new Vec(nX, nY));
            }
        }
        catch (e)
        {
            console.error(e.stack);
            throw e;
        }*/

        return false;
    }

    function KeyDown(e)
    {
        m_cKeyEvents[e.keyCode] = true;
    }

    function KeyUp(e)
    {
        m_cKeyEvents[e.keyCode] = false;
    }

    function Scroll(e)
    {
        console.log(e);
        m_nScrollDelta = (e.wheelDeltaY / 120);
    }

    return {
        Init: function(eCanvas){
            m_eCanvas = eCanvas;

            eCanvas.addEventListener("mousedown", InputStart);
            eCanvas.addEventListener("mousemove", InputMove);
            eCanvas.addEventListener("mouseup", InputEnd);

            //Detect platform and bind relevant events
            if (EN.Device.OS == EN.Device.SUPPORTED_OS.Windows || EN.Device.OS == EN.Device.SUPPORTED_OS.MacOSX)
            {
                window.onkeydown = KeyDown;
                window.onkeyup = KeyUp;

                window.onmousewheel = Scroll;

                eCanvas.oncontextmenu = function(e){
                    e.preventDefault();
                    return false;
                };
            }
            else
            {
                eCanvas.addEventListener("touchstart", InputStart);
                eCanvas.addEventListener("touchend", InputEnd);
            }
        },
        GetInputPos: function(){
            return m_cInputPos;
        },
        GetKeyDown: function(nKey){
            return m_cKeyEvents[nKey];
        },
        GetButtonDown: function(nButton){
            return m_cButtonEvents[nButton];
        },
        GetScrollDelta: function(){
            var nScrollDelta = m_nScrollDelta;
            m_nScrollDelta = 0;
            return nScrollDelta;
        }
    };
})();

EN.Controller.Buttons = {
    LEFT: 1,
    RIGHT: 2
}

EN.Controller.Keys = {
    UP: 38,
    DOWN: 40,
    LEFT: 37,
    RIGHT: 39,
    A: 65,
    Z: 90
};

//# sourceURL=engine/control/controller.js
<|endoftext|>


<commit_before>/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 2013-01-23
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs
  || (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  || (function(view) {
	"use strict";
	var
		  doc = view.document
		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
		, get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, URL = view.URL || view.webkitURL || view
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link =  !view.externalHost && "download" in save_link
		, click = function(node) {
			var event = doc.createEvent("MouseEvents");
			event.initMouseEvent(
				"click", true, false, view, 0, 0, 0, 0, 0
				, false, false, false, false, 0, null
			);
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function (ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		, deletion_queue = []
		, process_deletion_queue = function() {
			var i = deletion_queue.length;
			while (i--) {
				var file = deletion_queue[i];
				if (typeof file === "string") { // file is an object URL
					URL.revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			}
			deletion_queue.length = 0; // clear queue
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, FileSaver = function(blob, name) {
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, get_object_url = function() {
					var object_url = get_URL().createObjectURL(blob);
					deletion_queue.push(object_url);
					return object_url;
				}
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_object_url(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
                        window.open(object_url, "_blank");
                    }
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_object_url(blob);
				// FF for Android has a nasty garbage collection mechanism
				// that turns all objects that are not pure javascript into 'deadObject'
				// this means `doc` and `save_link` are unusable and need to be recreated
				// `view` is usable though:
				doc = view.document;
				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
				save_link.href = object_url;
				save_link.download = name;
				var event = doc.createEvent("MouseEvents");
				event.initMouseEvent(
					"click", true, false, view, 0, 0, 0, 0, 0
					, false, false, false, false, 0, null
				);
				save_link.dispatchEvent(event);
				filesaver.readyState = filesaver.DONE;
				dispatch_all();
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									deletion_queue.push(file);
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name) {
			return new FileSaver(blob, name);
		}
	;
	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	view.addEventListener("unload", process_deletion_queue, false);
	return saveAs;
}(typeof self !== 'undefined' ? self : typeof this !== 'undefined' && this.content ? this.content : null));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== 'undefined') module.exports = saveAs;
<commit_msg>Simplifying minj's changes<commit_after>/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 2013-10-21
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs
  || (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  || (function(view) {
	"use strict";
	var
		  doc = view.document
		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
		, get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, URL = view.URL || view.webkitURL || view
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link =  !view.externalHost && "download" in save_link
		, click = function(node) {
			var event = doc.createEvent("MouseEvents");
			event.initMouseEvent(
				"click", true, false, view, 0, 0, 0, 0, 0
				, false, false, false, false, 0, null
			);
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function (ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		, deletion_queue = []
		, process_deletion_queue = function() {
			var i = deletion_queue.length;
			while (i--) {
				var file = deletion_queue[i];
				if (typeof file === "string") { // file is an object URL
					URL.revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			}
			deletion_queue.length = 0; // clear queue
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, FileSaver = function(blob, name) {
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, get_object_url = function() {
					var object_url = get_URL().createObjectURL(blob);
					deletion_queue.push(object_url);
					return object_url;
				}
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_object_url(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
                        window.open(object_url, "_blank");
                    }
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_object_url(blob);
				// FF for Android has a nasty garbage collection mechanism
				// that turns all objects that are not pure javascript into 'deadObject'
				// this means `doc` and `save_link` are unusable and need to be recreated
				// `view` is usable though:
				doc = view.document;
				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
				save_link.href = object_url;
				save_link.download = name;
				var event = doc.createEvent("MouseEvents");
				event.initMouseEvent(
					"click", true, false, view, 0, 0, 0, 0, 0
					, false, false, false, false, 0, null
				);
				save_link.dispatchEvent(event);
				filesaver.readyState = filesaver.DONE;
				dispatch_all();
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									deletion_queue.push(file);
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name) {
			return new FileSaver(blob, name);
		}
	;
	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	view.addEventListener("unload", process_deletion_queue, false);
	return saveAs;
}(this.self || this.window || this.content));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== 'undefined') module.exports = saveAs;
<|endoftext|>


<commit_before>'use strict';

var Http = require('http');

var Connect = /** @type Connect */ require('./track/Connect');
var Router = /** @type Router */ require('finger/Router');
var Tracker = /** @type Tracker */ require('./Tracker');

var _ = require('lodash-node');
var inherit = require('inherit');
var vow = require('vow');

/**
 * @class Framework
 * @extends Tracker
 * */
var Framework = inherit(Tracker, /** @lends Framework.prototype */ {

    /**
     * @private
     * @memberOf {Framework}
     * @method
     *
     * @param {Object} [params]
     *
     * @constructs
     * */
    __constructor: function (params) {
        this.__base(params);

        /**
         * Тут откладываются запросы поступившие во время инициализации
         *
         * @protected
         * @memberOf {Framework}
         * @property
         * @type {Array<Track>}
         * */
        this._pends = [];

        /**
         * Плагины, задачи на инициализацию
         *
         * @protected
         * @memberOf {Framework}
         * @property
         * @type {Array<Function>}
         * */
        this._plugs = [];

        /**
         * Шаблоны для track.render()
         *
         * @public
         * @memberOf {Framework}
         * @property
         * @type {Object<Function>}
         * */
        this.renderers = {};

        /**
         * @public
         * @memberOf {Framework}
         * @property
         * @type {Router}
         * */
        this.router = this._createRouter(this.params.router);
    },

    /**
     * Возвращает коллбэк для запросов на сервер
     *
     * @public
     * @memberOf {Framework}
     * @method
     *
     * @returns {Function}
     * */
    getHandler: function () {

        var self = this;

        return function (req, res) {

            var date = new Date();
            var track = self._createTrack(req, res);

            res.once('finish', function () {
                track.time = new Date() - date;
                self.emit('sys:response', track);
            });

            self.emit('sys:request', track);

            self._handle(track);
        };
    },

    /**
     * Запускает сервер и инициализацию приложения
     *
     * @public
     * @memberOf {Framework}
     * @method
     * */
    listen: function () {

        var server = Http.createServer(this.getHandler());

        server.listen.apply(server, arguments);

        //  автоматически запускаю инициализацию
        this.ready(true);

        return server;
    },

    /**
     * Добавляет плагин[ы]
     *
     * @public
     * @memberOf {Framework}
     * @method
     * */
    plug: function () {

        var plugs = _.map(arguments, this.__wrapPlugin, this);

        Array.prototype.push.apply(this._plugs, plugs);
    },

    /**
     * Запускает операцию разрешения узла.
     * Если один из узлов, участвующих в операции
     * разрешения выполнил ответ приложения самостоятельно,
     * то коллбэк вызван не будет
     *
     * @public
     * @memberOf {Tracker}
     * @method
     *
     * @param {Connect} track
     * @param {String} path
     * @param {*} [params]
     *
     * @returns {vow.Promise}
     * */
    resolve: function (track, path, params) {

        var defer = vow.defer();

        this.__base(track, path, params).
            always(function (res) {

                if ( track.sent() ) {

                    return;
                }

                defer.resolve(res);
            });

        return defer.promise();
    },

    /**
     * Определяет маршрут встроенного роутера
     *
     * @public
     * @memberOf {Framework}
     * @method
     *
     * @param {String} pattern
     * @param {{unit?:String, name?:String}|String} [data]
     *
     * @returns {Framework}
     * */
    route: function (pattern, data) {

        var route;

        if ( !_.isObject(data) ) {
            data = {name: data};
        }

        route = this.router.addRoute(pattern, data);

        if ( _.isUndefined(route.data.unit) || _.isNull(route.data.unit) ) {
            route.data.unit = route.data.name;
        }

        return this;
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @param {*} [params]
     *
     * @returns {Router}
     * */
    _createRouter: function (params) {

        return new Router(params);
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @returns {Connect}
     * */
    _createTrack: function (req, res) {

        return new Connect(this, req, res);
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @returns {vow.Promise}
     * */
    _getReady: function () {

        var promise = this.__base().then(function () {

            return vow.all(_.map(this._plugs, function (plug) {
                return plug();
            }));
        }, this);

        promise.always(function () {

            while ( _.size(this._pends) ) {
                this._handle(this._pends.shift());
            }

        }, this).done();

        return promise;
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @param {Connect} track
     * */
    _handle: function (track) {
        /*eslint complexity: [2, 11]*/
        var self = this;

        //  был сделан send() где-то в обработчке события sys:request
        if ( track.sent() ) {

            return;
        }

        //  При инициализации произошла ошибка
        if ( this.ready().isRejected() ) {
            track.send(502);

            return;
        }

        //  еще не проинициализирован
        if ( !this.ready().isResolved() ) {
            //  отложить запрос
            this._pends.push(track);

            return;
        }

        function next () {
            //  выбирается маршрут
            var route = self.router.
                find(track.method, track.url.pathname, track.route);

            //  однозначно нет такого маршрута
            if ( null === route ) {

                self.emit('sys:ematch', track);
                track.send(404);

                return;
            }

            //  возвращен массив
            if ( _.isArray(route) ) {
                //  это тоже значит что нет такого роута
                self.emit('sys:ematch', track);

                //  если массив пустой, то на сервере совсем нет ни одного
                //  маршрута отвечающего по такому методу запроса
                if ( 0 === route.length ) {
                    //  Not Implemented
                    track.send(501);

                    return;
                }

                //  Иначе есть такие маршруты, но для них не
                // поддерживается такой метод
                track.header('Allow', route.join(', '));

                //  Method Not Allowed
                track.send(405);

                return;
            }

            track.match = route.match;
            route = route.route;
            track.route = route.data.name;

            self.emit('sys:match', track);

            self.resolve(track, route.data.unit).
                done(function () {
                    next();
                }, function (err) {
                    track.send(500, err);
                });
        }

        next();
    },

    /**
     * @private
     * @memberOf {Framework}
     * @method
     *
     * @param {Function} plug
     *
     * @returns {Function}
     * */
    __wrapPlugin: function (plug) {

        var self = this;

        return function () {

            var defer = vow.defer();

            plug.call(self, function (err) {

                if ( 0 === arguments.length ) {
                    defer.resolve();

                    return;
                }

                defer.reject(err);
            });

            return defer.promise();
        };
    }

});

module.exports = Framework;
<commit_msg>Рефакторинг и оптимизация Framework<commit_after>'use strict';

var Http = require('http');

var Connect = /** @type Connect */ require('./track/Connect');
var Router = /** @type Router */ require('finger/Router');
var Tracker = /** @type Tracker */ require('./Tracker');

var _ = require('lodash-node');
var inherit = require('inherit');
var vow = require('vow');

/**
 * @class Framework
 * @extends Tracker
 * */
var Framework = inherit(Tracker, /** @lends Framework.prototype */ {

    /**
     * @private
     * @memberOf {Framework}
     * @method
     *
     * @param {Object} [params]
     *
     * @constructs
     * */
    __constructor: function (params) {
        this.__base(params);

        /**
         * Тут откладываются запросы поступившие во время инициализации
         *
         * @protected
         * @memberOf {Framework}
         * @property
         * @type {Array<Track>}
         * */
        this._pends = [];

        /**
         * Плагины, задачи на инициализацию
         *
         * @protected
         * @memberOf {Framework}
         * @property
         * @type {Array<Function>}
         * */
        this._plugs = [];

        /**
         * Шаблоны для track.render()
         *
         * @public
         * @memberOf {Framework}
         * @property
         * @type {Object<Function>}
         * */
        this.renderers = {};

        /**
         * @public
         * @memberOf {Framework}
         * @property
         * @type {Router}
         * */
        this.router = this._createRouter(this.params.router);
    },

    /**
     * Возвращает коллбэк для запросов на сервер
     *
     * @public
     * @memberOf {Framework}
     * @method
     *
     * @returns {Function}
     * */
    getHandler: function () {

        var self = this;

        return function (req, res) {

            var date = new Date();
            var track = self._createTrack(req, res);

            res.once('finish', function () {
                track.time = new Date() - date;
                self.emit('sys:response', track);
            });

            self.emit('sys:request', track);

            self._handle(track);
        };
    },

    /**
     * Запускает сервер и инициализацию приложения
     *
     * @public
     * @memberOf {Framework}
     * @method
     * */
    listen: function () {

        var server = Http.createServer(this.getHandler());

        server.listen.apply(server, arguments);

        //  автоматически запускаю инициализацию
        this.ready(true);

        return server;
    },

    /**
     * Добавляет плагин[ы]
     *
     * @public
     * @memberOf {Framework}
     * @method
     * */
    plug: function () {
        Array.prototype.push.apply(this._plugs, arguments);
    },

    /**
     * Запускает операцию разрешения узла.
     * Если один из узлов, участвующих в операции
     * разрешения выполнил ответ приложения самостоятельно,
     * то коллбэк вызван не будет
     *
     * @public
     * @memberOf {Tracker}
     * @method
     *
     * @param {Connect} track
     * @param {String} path
     * @param {*} [params]
     *
     * @returns {vow.Promise}
     * */
    resolve: function (track, path, params) {

        var defer = vow.defer();

        this.__base(track, path, params).
            always(function (res) {

                if ( track.sent() ) {

                    return;
                }

                defer.resolve(res);
            });

        return defer.promise();
    },

    /**
     * Определяет маршрут встроенного роутера
     *
     * @public
     * @memberOf {Framework}
     * @method
     *
     * @param {String} pattern
     * @param {{unit?:String, name?:String}|String} [data]
     *
     * @returns {Framework}
     * */
    route: function (pattern, data) {

        var route;

        if ( !_.isObject(data) ) {
            data = {name: data};
        }

        route = this.router.addRoute(pattern, data);

        if ( _.isUndefined(route.data.unit) || _.isNull(route.data.unit) ) {
            route.data.unit = route.data.name;
        }

        return this;
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @param {*} [params]
     *
     * @returns {Router}
     * */
    _createRouter: function (params) {

        return new Router(params);
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @returns {Connect}
     * */
    _createTrack: function (req, res) {

        return new Connect(this, req, res);
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @returns {vow.Promise}
     * */
    _getReady: function () {

        var promise = this.__base().then(function () {

            return vow.all(_.map(this._plugs, callPlugin, this));
        }, this);

        promise.always(function () {

            while ( _.size(this._pends) ) {
                this._handle(this._pends.shift());
            }

        }, this).done();

        return promise;
    },

    /**
     * @protected
     * @memberOf {Framework}
     * @method
     *
     * @param {Connect} track
     * */
    _handle: function (track) {

        //  был сделан send() где-то в обработчке события sys:request
        if ( track.sent() ) {

            return;
        }

        //  При инициализации произошла ошибка
        if ( this.ready().isRejected() ) {
            track.send(502);

            return;
        }

        //  еще не проинициализирован
        if ( !this.ready().isResolved() ) {
            //  отложить запрос
            this._pends.push(track);

            return;
        }

        (function next () {
            //  выбирается маршрут
            var route = this.router.
                find(track.method, track.url.pathname, track.route);

            //  однозначно нет такого маршрута
            if ( null === route ) {
                this.emit('sys:ematch', track);
                track.send(404);

                return;
            }

            //  возвращен массив
            if ( _.isArray(route) ) {
                //  это тоже значит что нет такого роута
                this.emit('sys:ematch', track);

                //  если массив пустой, то на сервере совсем нет ни одного
                //  маршрута отвечающего по такому методу запроса
                if ( 0 === route.length ) {
                    //  Not Implemented
                    track.send(501);

                    return;
                }

                //  Иначе есть такие маршруты, но для них не
                // поддерживается такой метод
                track.header('Allow', route.join(', '));

                //  Method Not Allowed
                track.send(405);

                return;
            }

            track.match = route.match;
            route = route.route;
            track.route = route.data.name;

            this.emit('sys:match', track);

            this.resolve(track, route.data.unit).done(next, function (err) {
                track.send(500, err);
            }, this);

        }.call(this));
    }

});

function callPlugin (plug) {

    var defer = vow.defer();

    plug.call(this, function (err) {

        if ( 0 === arguments.length ) {
            defer.resolve();

            return;
        }

        defer.reject(err);
    });

    return defer.promise();
}

module.exports = Framework;
<|endoftext|>


<commit_before>var menu_balloon;

// Menu State
demo.menu = function(){};

demo.menu.prototype = {
    preload: function(){
        // Always include this line
        loadImages();

        // Make this equal to the size of the tilemap
        var tilemap_height = 800;
        game.world.setBounds(0, 0, 1000, tilemap_height);

    },
    create: function(){
        add_game_bg('bg1');
        restart_state = "menu";
        // This only needs to happen one time.  Add it to the intial state and forget about it after
        game.physics.startSystem(Phaser.Physics.ARCADE);
        // Allows keyboard inputs
        cursors = game.input.keyboard.createCursorKeys();
        game.input.keyboard.addCallbacks(this, null, null, keyPress);

        // Stop sounds when starting a state
        game.sound.stopAll();

        cute = game.add.audio('cute');
        cute.play('','',0.3,true,true);

        // start game at bottom of screen
        game.camera.y = game.world.height;

        // Add game background
        // change 'bg1' to whatever is required
//        add_game_bg('bg1')
        game.stage.backgroundColor = '#DDDDDD';

        // Add chameleon at x,y
        createChameleon(500,500);

        var style = {font: "30px Arial", fill: "Black"}
        var tutorial_menu_option = game.add.sprite(200, 200, "tutorial_state_txt");
        tutorial_menu_option.inputEnabled = true;
        tutorial_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'tutorial'
                game.state.start('tutorial');
            }
        );

        var ice_menu_option = game.add.sprite(200, 250, "ice_state_txt");
        ice_menu_option.inputEnabled = true;
        ice_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'icestate'
                game.state.start('icestate');
            }
        );

        var lava_menu_option = game.add.sprite(200, 300, "lava_state_txt");
        lava_menu_option.inputEnabled = true;
        lava_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'lavastate'
                game.state.start('lavastate');
            }
        );

//        var trial_menu_option = game.add.text(200, 350, "Trial", style);
//        trial_menu_option.inputEnabled = true;
//        trial_menu_option.events.onInputUp.add(
//            function(){
//                restart_state = 'trialstate'
//                game.state.start('trialstate');
//            }
//        );
//
//        var bp_menu_option = game.add.text(200, 400, "Boilerplate", style);
//        bp_menu_option.inputEnabled = true;
//        bp_menu_option.events.onInputUp.add(
//            function(){
//                restart_state = 'boilerplate'
//                game.state.start('boilerplate');
//            }
//        );

        var balloon_menu_option = game.add.sprite(200, 350, "unicorn_state_txt");
        balloon_menu_option.inputEnabled = true;
        balloon_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'balloonstate'
                game.state.start('balloonstate');
            }
        );

        // make groups
        make_fruit_groups();
        make_enemy_groups();
        make_balloon_group();
        addMovingPlatforms();
        make_healthpack_groups();
        menu_balloon = placeBalloon(925, 500);
        menu_balloon.reset_time = game.time.time + 2000;
        placeBalloon(925, 100);

        placeFruit(300, 100, "redfruit");
        placeFruit(700, 100, "bluefruit");
        placeMP(400, 100, 5, 1, 0, 8, 0, 100);

        // Add MP as ground so we don't need a tilemap for menu
        placeMP(0, 600, 18, 3, 0, 0, 0, 0);

        // These should be the last thing added so that it is on top of all other sprites (never hidden)
        createInventory(0, 525);
//        place_hearts(450, 0);
        add_pause_darkener();
    },
    update: function(){
        game.camera.y = 0;

        if (player.ballooning) {
            chameleon_float();
        } else {
            chameleonmove();
        }

        if (!menu_balloon.alive && game.time.time > menu_balloon.reset_time) {
            menu_balloon.revive()
        } else if (menu_balloon.alive) {
            // Revive menu balloon only if it has been dead for 2 seconds
            menu_balloon.reset_time = game.time.time + 2000;
        }

        birds_group.forEach(moveBird, this);
        snakes_group.forEach(moveSnake, this);
        moving_platform_group.forEach(movingPlatformsUpdate, this);
//        update_health(player.health);
    },
}<commit_msg>added title.  Just need to move text around so there is no overlap<commit_after>var menu_balloon;

// Menu State
demo.menu = function(){};

demo.menu.prototype = {
    preload: function(){
        // Always include this line
        loadImages();

        // Make this equal to the size of the tilemap
        var tilemap_height = 800;
        game.world.setBounds(0, 0, 1000, tilemap_height);

    },
    create: function(){
        add_game_bg('bg1');
        restart_state = "menu";
        // This only needs to happen one time.  Add it to the intial state and forget about it after
        game.physics.startSystem(Phaser.Physics.ARCADE);
        // Allows keyboard inputs
        cursors = game.input.keyboard.createCursorKeys();
        game.input.keyboard.addCallbacks(this, null, null, keyPress);

        // Stop sounds when starting a state
        game.sound.stopAll();

        cute = game.add.audio('cute');
        cute.play('','',0.3,true,true);

        // start game at bottom of screen
        game.camera.y = game.world.height;

        // Add game background
        // change 'bg1' to whatever is required
//        add_game_bg('bg1')
        game.stage.backgroundColor = '#DDDDDD';

        // Add chameleon at x,y
        createChameleon(500,500);

        var title = game.add.sprite(500, 200, "title_txt");
        title.anchor.setTo(0.5, 0.5);

        var style = {font: "30px Arial", fill: "Black"}
        var tutorial_menu_option = game.add.sprite(200, 200, "tutorial_state_txt");
        tutorial_menu_option.inputEnabled = true;
        tutorial_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'tutorial'
                game.state.start('tutorial');
            }
        );

        var ice_menu_option = game.add.sprite(200, 250, "ice_state_txt");
        ice_menu_option.inputEnabled = true;
        ice_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'icestate'
                game.state.start('icestate');
            }
        );

        var lava_menu_option = game.add.sprite(200, 300, "lava_state_txt");
        lava_menu_option.inputEnabled = true;
        lava_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'lavastate'
                game.state.start('lavastate');
            }
        );

//        var trial_menu_option = game.add.text(200, 350, "Trial", style);
//        trial_menu_option.inputEnabled = true;
//        trial_menu_option.events.onInputUp.add(
//            function(){
//                restart_state = 'trialstate'
//                game.state.start('trialstate');
//            }
//        );
//
//        var bp_menu_option = game.add.text(200, 400, "Boilerplate", style);
//        bp_menu_option.inputEnabled = true;
//        bp_menu_option.events.onInputUp.add(
//            function(){
//                restart_state = 'boilerplate'
//                game.state.start('boilerplate');
//            }
//        );

        var balloon_menu_option = game.add.sprite(200, 350, "unicorn_state_txt");
        balloon_menu_option.inputEnabled = true;
        balloon_menu_option.events.onInputUp.add(
            function(){
                restart_state = 'balloonstate'
                game.state.start('balloonstate');
            }
        );

        // make groups
        make_fruit_groups();
        make_enemy_groups();
        make_balloon_group();
        addMovingPlatforms();
        make_healthpack_groups();
        menu_balloon = placeBalloon(925, 500);
        menu_balloon.reset_time = game.time.time + 2000;
//        placeBalloon(925, 100);

//        placeFruit(300, 100, "redfruit");
//        placeFruit(700, 100, "bluefruit");
//        placeMP(400, 100, 5, 1, 0, 8, 0, 100);

        // Add MP as ground so we don't need a tilemap for menu
        placeMP(0, 600, 18, 3, 0, 0, 0, 0);

        // These should be the last thing added so that it is on top of all other sprites (never hidden)
//        createInventory(0, 525);
//        place_hearts(450, 0);
        add_pause_darkener();
    },
    update: function(){
        game.camera.y = 0;

        if (player.ballooning) {
            chameleon_float();
        } else {
            chameleonmove();
        }

        if (!menu_balloon.alive && game.time.time > menu_balloon.reset_time) {
            menu_balloon.revive()
        } else if (menu_balloon.alive) {
            // Revive menu balloon only if it has been dead for 2 seconds
            menu_balloon.reset_time = game.time.time + 2000;
        }

        birds_group.forEach(moveBird, this);
        snakes_group.forEach(moveSnake, this);
        moving_platform_group.forEach(movingPlatformsUpdate, this);
//        update_health(player.health);
    },
}<|endoftext|>


<commit_before>import vtkCellArray from './CellArray';
import vtkDataArray from './DataArray';
import vtkEndian from './Endian';
import vtkImageHelper from './ImageHelper';
import vtkLookupTable from './LookupTable';
import * as vtkMath from './Math';
import vtkMatrixBuilder from './MatrixBuilder';
import vtkPoints from './Points';
import vtkProgressHandler from './ProgressHandler';
import vtkScalarsToColors from './ScalarsToColors';
import vtkStringArray from './StringArray';
import vtkURLExtract from './URLExtract';
import vtkVariantArray from './VariantArray';

export default {
  vtkCellArray,
  vtkDataArray,
  vtkEndian,
  vtkImageHelper,
  vtkLookupTable,
  vtkMath,
  vtkMatrixBuilder,
  vtkPoints,
  vtkProgressHandler,
  vtkScalarsToColors,
  vtkStringArray,
  vtkURLExtract,
  vtkVariantArray,
};
<commit_msg>fix(Base64): Expose helper methods to convert base64 to byteArray<commit_after>import vtkBase64 from './Base64';
import vtkCellArray from './CellArray';
import vtkDataArray from './DataArray';
import vtkEndian from './Endian';
import vtkImageHelper from './ImageHelper';
import vtkLookupTable from './LookupTable';
import * as vtkMath from './Math';
import vtkMatrixBuilder from './MatrixBuilder';
import vtkPoints from './Points';
import vtkProgressHandler from './ProgressHandler';
import vtkScalarsToColors from './ScalarsToColors';
import vtkStringArray from './StringArray';
import vtkURLExtract from './URLExtract';
import vtkVariantArray from './VariantArray';

export default {
  vtkBase64,
  vtkCellArray,
  vtkDataArray,
  vtkEndian,
  vtkImageHelper,
  vtkLookupTable,
  vtkMath,
  vtkMatrixBuilder,
  vtkPoints,
  vtkProgressHandler,
  vtkScalarsToColors,
  vtkStringArray,
  vtkURLExtract,
  vtkVariantArray,
};
<|endoftext|>


<commit_before>lvector.CartoDB = lvector.GeoJSONLayer.extend({
    initialize: function(options) {

        // Check for required parameters
        for (var i = 0, len = this._requiredParams.length; i < len; i++) {
            if (!options[this._requiredParams[i]]) {
                throw new Error("No \"" + this._requiredParams[i] + "\" parameter found.");
            }
        }

        // Extend Layer to create CartoDB
        lvector.Layer.prototype.initialize.call(this, options);

        // _globalPointer is a string that points to a global function variable
        // Features returned from a JSONP request are passed to this function
        this._globalPointer = "CartoDB_" + Math.floor(Math.random() * 100000);
        window[this._globalPointer] = this;

        // Create an array to hold the features
        this._vectors = [];

        if (this.options.map) {
            if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) {
                var z = this.options.map.getZoom();
                var sr = this.options.scaleRange;
                this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]);
            }
            this._show();
        }
    },

    options: {
        version: 1,
        user: null,
        table: null,
        fields: "*",
        where: null,
        limit: null,
        uniqueField: "cartodb_id"
    },

    _requiredParams: ["user", "table"],

    _getFeatures: function() {
        // Build Query
        var where = this.options.where || "";
        if (!this.options.showAll) {
            var bounds = this.options.map.getBounds();
            var sw = bounds.getSouthWest();
            var ne = bounds.getNorthEast();
            var tableCount = this.options.table.split(",").length;
            for (var i = 0; i < tableCount; i++) {
                where += (where.length ? " AND " : "") + (tableCount > 1 ? this.options.table.split(",")[i].split(".")[0] + ".the_geom" : "the_geom") + " && st_setsrid(st_makebox2d(st_point(" + sw.lng + "," + sw.lat + "),st_point(" + ne.lng + "," + ne.lat + ")),4326)";
            }
        }
        if (this.options.limit) {
            where += (where.length ? " " : "") + "limit " + this.options.limit;
        }
        where = (where.length ? " " + where : "");
        var query = "SELECT " + this.options.fields + " FROM " + this.options.table + (where.length ? " WHERE " + where : "");

        // Build URL
        var url = "http://" + this.options.user + ".cartodb.com/api/v" + this.options.version + "/sql" + // The API entry point
            "?q=" + encodeURIComponent(query) + // The SQL statement
            "&format=geojson" + // GeoJSON please
            "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP

        // JSONP request
        this._makeJsonpRequest(url);
    }

});
<commit_msg>Add key option to CartoDB.js<commit_after>lvector.CartoDB = lvector.GeoJSONLayer.extend({
    initialize: function(options) {

        // Check for required parameters
        for (var i = 0, len = this._requiredParams.length; i < len; i++) {
            if (!options[this._requiredParams[i]]) {
                throw new Error("No \"" + this._requiredParams[i] + "\" parameter found.");
            }
        }

        // Extend Layer to create CartoDB
        lvector.Layer.prototype.initialize.call(this, options);

        // _globalPointer is a string that points to a global function variable
        // Features returned from a JSONP request are passed to this function
        this._globalPointer = "CartoDB_" + Math.floor(Math.random() * 100000);
        window[this._globalPointer] = this;

        // Create an array to hold the features
        this._vectors = [];

        if (this.options.map) {
            if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) {
                var z = this.options.map.getZoom();
                var sr = this.options.scaleRange;
                this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]);
            }
            this._show();
        }
    },

    options: {
        version: 1,
        user: null,
        table: null,
        fields: "*",
        where: null,
        limit: null,
        key: null,
        uniqueField: "cartodb_id"
    },

    _requiredParams: ["user", "table"],

    _getFeatures: function() {
        // Build Query
        var where = this.options.where || "";
        if (!this.options.showAll) {
            var bounds = this.options.map.getBounds();
            var sw = bounds.getSouthWest();
            var ne = bounds.getNorthEast();
            var tableCount = this.options.table.split(",").length;
            for (var i = 0; i < tableCount; i++) {
                where += (where.length ? " AND " : "") + (tableCount > 1 ? this.options.table.split(",")[i].split(".")[0] + ".the_geom" : "the_geom") + " && st_setsrid(st_makebox2d(st_point(" + sw.lng + "," + sw.lat + "),st_point(" + ne.lng + "," + ne.lat + ")),4326)";
            }
        }
        if (this.options.limit) {
            where += (where.length ? " " : "") + "limit " + this.options.limit;
        }
        where = (where.length ? " " + where : "");
        var query = "SELECT " + this.options.fields + " FROM " + this.options.table + (where.length ? " WHERE " + where : "") + "&api_key="+ this.options.key;

        // Build URL
        var url = "http://" + this.options.user + ".cartodb.com/api/v" + this.options.version + "/sql" + // The API entry point
            "?q=" + encodeURIComponent(query) + // The SQL statement
            "&format=geojson" + // GeoJSON please
            "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP

        // JSONP request
        this._makeJsonpRequest(url);
    }

});
<|endoftext|>