<commit_before>// (function(exports) {
    var exports = window.game;

    exports.sides = 5; // The number of sides that the player can turn
    var ticks = 0;
    var maxWait = 100;

    var enemies = [];
    var enemyPositions = [];
    var ENEMY_HEIGHT = 50;
    var ENEMY_WIDTH = 20;

    var prevColor = ''; // Temp variable to store player's color

    exports.turnStep = 2 * Math.PI / exports.sides;

    // Possible states: complete, movingIn, waiting, attacking
    // Complete: an attack was just completed and new enemies need to slide in
    // Moving In: enemies are moving to position from outside the screen
    // Waiting: enemies are in position, and we're waiting to give the player time
    // Attacking: 5, animate enemies moving in
    var currentState = 'complete';

    exports.enemyDraw = function() {
        var enemy;
        var ctx = exports.ctx;
        ctx.fillStyle = 'white';
        for (var i = 0; i < enemies.length; i++) {
            enemy = enemies[i];
            ctx.save();
            ctx.translate(exports.cx, exports.cy);
            ctx.rotate(enemy.angle);
            ctx.fillRect(enemy.centerDist, -ENEMY_HEIGHT / 2, ENEMY_WIDTH, ENEMY_HEIGHT);
            ctx.restore();
        }
    };

    var addEnemy = function(angle) {
        var obj = {};
        obj.angle = angle || 0;
        obj.centerDist = 500;

        enemies.push(obj);
    };

    var range = function(min, max) {
        var ret = [];
        for (var i = min; i < max; i++) {
            ret.push(i);
        }
        return ret;
    };

    var makeEnemyWave = function() {
        var possible = range(0, exports.sides);
        var numToRemove = 1 + Math.floor(Math.random() * (exports.sides - 2));

        for (var i = 0; i < numToRemove; i++) {
            possible.splice(Math.floor(Math.random() * possible.length), 1);
        }

        for (i = 0; i < possible.length; i++) {
            addEnemy(exports.turnStep * possible[i]);
        }

        currentState = 'movingIn';
        return possible;
    };

    var animateEnemies = function(min, speed, cb) {
        for (var i = 0; i < enemies.length; i++) {
            enemy = enemies[i];
            enemy.centerDist -= speed || 5;
            if (enemy.centerDist < min) {
                enemy.centerDist = min;
                cb();
                break;
            }
        }
    };

    exports.enemyLogic = function() {
        switch(currentState) {
            case 'complete':
                enemyPositions = makeEnemyWave();
                break;
            case 'movingIn':
                animateEnemies(200, 5, function() {
                    currentState = 'waiting';
                });
                break;
            case 'waiting':
                ticks++;
                if (ticks > maxWait) {
                    ticks = 0;
                    currentState = 'attacking';
                }
                break;
            case 'attacking':
                animateEnemies(50, 5, function() {
                    if (enemyPositions.indexOf(exports.player.pos) != -1) {
                        currentState = 'crushing';
                        prevColor = exports.player.color;
                        exports.player.color = '255, 184, 253';
                        setTimeout(function() {
                            exports.player.color = prevColor;
                        }, 100);
                        exports.createParticles(
                            Math.random() * 3 + 1,
                            exports.cx,
                            exports.cy,
                            ['red'],
                            1,
                            exports.player.angle + Math.PI / 2,
                            0.2
                        );
                        exports.createParticles(
                            Math.random() * 3 + 1,
                            exports.cx,
                            exports.cy,
                            ['red'],
                            1,
                            exports.player.angle - Math.PI / 2,
                            0.2
                        );

                        exports.shakeScreen(4);
                    }
                    else {
                        currentState = 'complete';
                        enemies = [];
                    }
                });
                break;
            case 'crushing':
                animateEnemies(29, 1, function() {
                    exports.player.alpha = 0;
                    setTimeout(function() {
                        exports.player.color = prevColor;
                        exports.player.alpha = 1;
                        currentState = 'complete';
                        enemies = [];
                    }, 1000);
                });
                break;
        }
    };

// })(window.game);<commit_msg>Added comments<commit_after>// Here's how level progression will work
// 1) Plain old dodging. You move left/right and dodge.
// 2) Faster enemies
// 3) Player spins X degrees just before the enemies attack. Player has to start accounting for this
// 4) Player still spins, but now so do the enemy blocks.
// 5) Number of sides increases (i.e. a square becomes a pentagon)
// 6) You cut the player's arm off to make the game harder still
// 7) You kidnap their children to test their committment
// 8) PROFIT
// 9) goto 1

// (function(exports) {
    var exports = window.game;

    exports.sides = 5; // The number of sides that the player can turn
    var ticks = 0;
    var maxWait = 20;

    var enemies = [];
    var enemyPositions = [];
    var ENEMY_HEIGHT = 50;
    var ENEMY_WIDTH = 20;

    var prevColor = ''; // Temp variable to store player's color

    exports.turnStep = 2 * Math.PI / exports.sides;

    // Possible states: complete, movingIn, waiting, attacking
    // Complete: an attack was just completed and new enemies need to slide in
    // Moving In: enemies are moving to position from outside the screen
    // Waiting: enemies are in position, and we're waiting to give the player time
    // Attacking: 5, animate enemies moving in
    var currentState = 'complete';

    exports.enemyDraw = function() {
        var enemy;
        var ctx = exports.ctx;
        ctx.fillStyle = 'white';
        for (var i = 0; i < enemies.length; i++) {
            enemy = enemies[i];
            ctx.save();
            ctx.translate(exports.cx, exports.cy);
            ctx.rotate(enemy.angle);
            ctx.fillRect(enemy.centerDist, -ENEMY_HEIGHT / 2, ENEMY_WIDTH, ENEMY_HEIGHT);
            ctx.restore();
        }
    };

    var addEnemy = function(angle) {
        var obj = {};
        obj.angle = angle || 0;
        obj.centerDist = 500;

        enemies.push(obj);
    };

    var range = function(min, max) {
        var ret = [];
        for (var i = min; i < max; i++) {
            ret.push(i);
        }
        return ret;
    };

    var makeEnemyWave = function() {
        var possible = range(0, exports.sides);
        var numToRemove = 1 + Math.floor(Math.random() * (exports.sides - 2));

        for (var i = 0; i < numToRemove; i++) {
            possible.splice(Math.floor(Math.random() * possible.length), 1);
        }

        for (i = 0; i < possible.length; i++) {
            addEnemy(exports.turnStep * possible[i]);
        }

        currentState = 'movingIn';
        return possible;
    };

    var animateEnemies = function(min, speed, cb) {
        for (var i = 0; i < enemies.length; i++) {
            enemy = enemies[i];
            enemy.centerDist -= speed || 5;
            if (enemy.centerDist < min) {
                enemy.centerDist = min;
                cb();
                break;
            }
        }
    };

    exports.enemyLogic = function() {
        switch(currentState) {
            case 'complete':
                enemyPositions = makeEnemyWave();
                break;
            case 'movingIn':
                animateEnemies(200, 5, function() {
                    currentState = 'waiting';
                });
                break;
            case 'waiting':
                ticks++;
                if (ticks > maxWait) {
                    ticks = 0;
                    currentState = 'attacking';
                }
                break;
            case 'attacking':
                animateEnemies(50, 5, function() {
                    if (enemyPositions.indexOf(exports.player.pos) != -1) {
                        currentState = 'crushing';
                        prevColor = exports.player.color;
                        exports.player.color = '255, 184, 253';
                        setTimeout(function() {
                            exports.player.color = prevColor;
                        }, 100);
                        exports.createParticles(
                            Math.random() * 3 + 1,
                            exports.cx,
                            exports.cy,
                            ['red'],
                            1,
                            exports.player.angle + Math.PI / 2,
                            0.2
                        );
                        exports.createParticles(
                            Math.random() * 3 + 1,
                            exports.cx,
                            exports.cy,
                            ['red'],
                            1,
                            exports.player.angle - Math.PI / 2,
                            0.2
                        );

                        exports.shakeScreen(4);
                    }
                    else {
                        currentState = 'complete';
                        enemies = [];
                    }
                });
                break;
            case 'crushing':
                animateEnemies(29, 1, function() {
                    exports.player.alpha = 0;
                    setTimeout(function() {
                        exports.player.color = prevColor;
                        exports.player.alpha = 1;
                        currentState = 'complete';
                        enemies = [];
                    }, 1000);
                });
                break;
        }
    };

// })(window.game);<|endoftext|>


<commit_before>/**
 * Created by tc on 4/Mar/2014.
 */

var currentId = 1;

export class Slide {
    constructor (title = 'Slide ' + currentId,
                 text = 'Default text ' + currentId,
                 thumbnail = '[thumbnail ' + currentId + ']') {
        this.title = title;
        this._text = text;
        this.thumbnail = thumbnail;
        this.id = currentId++;
        this.dirtyTick = 0;
    }

    dirty () {
        this.dirtyTick++;
    }

    get text () {
        return this._text;
    }

    set text (newText) {
        this._text = newText;
        this.dirty();
    }
}

export default Slide;<commit_msg>Fix dirtyTick for slides<commit_after>/**
 * Created by tc on 4/Mar/2014.
 */

var currentId = 1;

export class Slide {
    constructor (title = 'Slide ' + currentId,
                 text = 'Default text ' + currentId,
                 thumbnail = '[thumbnail ' + currentId + ']') {
        this.title = title;
        this._text = text;
        this.thumbnail = thumbnail;
        this.id = currentId++;
        this.dirtyTick = Math.random();
    }

    dirty () {
        this.dirtyTick++;
    }

    get text () {
        return this._text;
    }

    set text (newText) {
        this._text = newText;
        this.dirty();
    }
}

export default Slide;<|endoftext|>


<commit_before>var i18nContext = require('./i18n-context'),
    t = i18nContext.t,
    BasicType = require('./types/basic');

module.exports = require('ember-text-field').extend({
    classNames: ['super-field'],

    classNameBindings: ['hasStringValue', 'hasStringValue:has-value'],

    autocomplete: 'off',

    allowKeyInput: true,
    showSelectorOnDownArrow: true,

    autoSelectOnBlur: false,

    init: function() {
        this.initType();
        this._super();
        var self = this;
        this.addObserver('value.'+this.get('type.inputValuePath'), this, function() {
            self.reformatInputValue();
        });
        if (this.get('autoSelectIfOne')) {
            var type = this.get('type'),
                content;
            type.setQ('', true, true);
            content = type.get('content');
            type.get('content').promise.then(function() {
                if (content.get('length') == 1) {
                    self.set('value', content.get('firstObject'));
                }
            });
        }
    },

    superFieldRecordWillChange: function() {
        if (this._recordStringValueBinding) {
            this._recordStringValueBinding.disconnect(this);
            this._recordStringValueBinding = null;
        }
    }.observesBefore('record'),

    superFieldRecordDidChange: function() {
        var r = this.get('record'),
            stringName = this.get('stringName');
        if (r && stringName) {
            this._recordStringValueBinding = this.bind('stringValue', 'record.'+ stringName);
        }
    }.observes('record').on('init'),

    allowStringValue: false,
    stringName: null,
    stringValue: '',
    hasStringValue: function() {
        return (this.get('stringValue') && !this.get('hasFocus'));
    }.property('hasFocus', 'stringValue'),

    autoSelectIfOne: false,

    initType: function() {
        var type = this.get('type');
        if (typeof type === 'string') {
            var typeName = type;
            type = this.container.lookup('super-field-type:'+typeName);
            Ember.assert('Invalid super field type name: '+typeName, type);
        } else {
            Ember.assert('Invalid super field type: '+type, type instanceof BasicType);
        }
        type.set('field', this);
        this.set('type', type);
    },

    query: null,

    icon: function() {
        return this.get('value.' + this.get('type.iconPath'));
    }.property('value'),

    selectOnFocus: true,
    picker1Icon: 'icons/caret-down',

    didClickPicker1: function() {
        if (this.get('selector')) {
            this.hideSelector();
        } else {
            if (!Em.isEmpty(this.get('type.q'))) {
                this.get('type').resetContent();
            }
            this.showSelector();
            this.get('type').setQ('', true);
        }
        this.focus();
    },

    allowUnformatInputValue: false,
    formatInputValue: function(value) {
        var inputValuePath = this.get('type.inputValuePath');
        return Em.isEmpty(value) ? this.get('inputValue') : (inputValuePath ? value.get(inputValuePath) : '');
    },

    //Value handling
    superFieldValueDidChange: function() {
        if (this.get('value')) {
            this.set('stringValue', null);
        } else {
            this.set('inputValue', '');
        }
    }.observes('value'),
    superFieldInputValueDidChange: function() {
        if (this.get('allowStringValue') && !this.get('value')) {
            this.set('stringValue', this.get('inputValue'));
        }
        this.get('type').setQ(this.get('inputValue'));
    }.observes('inputValue'),
    didBlur: function() {
        this._super();
        //If the value is empty and allowStringValue == false, then we need to handle the inputValue somehow if it is set
        if (Em.isEmpty(this.get('value')) && !this.get('allowStringValue') && !Em.isEmpty(this.get('inputValue'))) {
            var type = this.get('type');
            if (this.get('autoSelectOnBlur')) {
                //If autoSelectOnBlur == true we either select the one and only option, or add an error to the field
                if (type.get('isLoading')) {
                    type.one('didLoad', this, this.autoSelect);
                } else {
                    this.autoSelect();
                }
            } else {
                //Otherwise we clear the inputValue
                this.set('inputValue', '');
            }
        }
    },

    autoSelect: function() {
        var content = this.get('type.content');
        if (content.get('length') === 1) {
            this.set('value', content.get('firstObject'));
        } else {
            this.set('error', t('no_single_value_found'));
        }
    },

    //DOM events
    didInsertElement: function() {
        this._super();
        var input = this.$('input');
        input.keydown(Billy.proxy(this.didKeyDown, this));
    },
    willDestroyElement: function() {
        this._super();
        this.get('type').destroy();
        this.hideSelector();
    },

    didKeyDown: function(e) {
        var self = this,
            key = e.keyCode || e.which,
            hasModifier = e.ctrlKey || e.metaKey;
        switch (key) {
            case $.keyCode.ESCAPE:
            case $.keyCode.UP:
            case $.keyCode.DOWN:
            case $.keyCode.ENTER:
                e.preventDefault();
                break;
        }
        Em.run(function() {
            self.doDidKeyDown(key, hasModifier);
        });
    },
    doDidKeyDown: function(key, hasModifier) {
        switch (key) {
            case $.keyCode.ESCAPE:
                this.hideSelector();
                break;
                break;
            case $.keyCode.UP:
                this.didPressUp();
                break;
            case $.keyCode.DOWN:
                this.didPressDown();
                break;
            case $.keyCode.TAB:
            case $.keyCode.ENTER:
                this.didPressEnter();
                break;
            case $.keyCode.LEFT:
            case $.keyCode.RIGHT:
            case 91: //Left command
            case 93: //Right command
            case 18: //Alt
            case 17: //Control
            case 16: //Shift
                //Ignore
                break;
            default:
                if (this.get('allowKeyInput')) {
                    //Ignore everything with Ctrl or Cmd
                    if (hasModifier) {
                        break;
                    }
                    this.selectOption(null);
                    if (!this.get('selector')) {
                        this.get('type').resetContent();
                        this.showSelector();
                    }
                }
                break;
        }
    },

    //Key handling
    didPressUp: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressUp();
        }
    },
    didPressDown: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressDown();
        } else if (this.get('showSelectorOnDownArrow')) {
            this.showSelector();
            this.get('type').setQ(this.get('inputValue'), true);
            this.get('selector').highlightOptionByIndex(0);
        }
    },
    didPressEnter: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressEnter();
        }
    },

    //Selector
    showSelector: function() {
        var self = this,
            selector = this.get('selector');
        if (!selector) {
            selector = require('./selector').create({
                container: this.container
            });
            this.set('selector', selector);
            selector.set('field', this);
            selector.one('willDestroyElement', function() {
                self.set('selector', null);
            });
            selector.show(this);
        }
    },
    hideSelector: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.destroy();
        }
    },
    selectOption: function(option) {
        this.set('value', option);
        Em.run.schedule('sync', this, function() {
            this.sendAction('didSelect', option);
        });
    },

    //Create
    create: function() {
        var self = this,
            type = this.get('type'),
            create = type.get('create');
        Ember.assert('No create method set on superfield type.', create);
        this.hideSelector();
        create.call(type, this.get('inputValue'), function(value) {
            self.selectOption(value);
        });
    }
});

module.exports.types = {
    Basic: require('./types/basic'),
    Model: require('./types/model'),
    Empty: require('./types/empty')
};

module.exports.OptionView = require('./option-view');

module.exports.locale = i18nContext.locale;

module.exports.lang = function() {
    console.warn('.lang() is deprecated. Use .locale() instead');
    return i18nContext.locale.apply(null, arguments);
};<commit_msg>`didSelect` action should only be sent if the value changed<commit_after>var i18nContext = require('./i18n-context'),
    t = i18nContext.t,
    BasicType = require('./types/basic');

module.exports = require('ember-text-field').extend({
    classNames: ['super-field'],

    classNameBindings: ['hasStringValue', 'hasStringValue:has-value'],

    autocomplete: 'off',

    allowKeyInput: true,
    showSelectorOnDownArrow: true,

    autoSelectOnBlur: false,

    init: function() {
        this.initType();
        this._super();
        var self = this;
        this.addObserver('value.'+this.get('type.inputValuePath'), this, function() {
            self.reformatInputValue();
        });
        if (this.get('autoSelectIfOne')) {
            var type = this.get('type'),
                content;
            type.setQ('', true, true);
            content = type.get('content');
            type.get('content').promise.then(function() {
                if (content.get('length') == 1) {
                    self.set('value', content.get('firstObject'));
                }
            });
        }
    },

    superFieldRecordWillChange: function() {
        if (this._recordStringValueBinding) {
            this._recordStringValueBinding.disconnect(this);
            this._recordStringValueBinding = null;
        }
    }.observesBefore('record'),

    superFieldRecordDidChange: function() {
        var r = this.get('record'),
            stringName = this.get('stringName');
        if (r && stringName) {
            this._recordStringValueBinding = this.bind('stringValue', 'record.'+ stringName);
        }
    }.observes('record').on('init'),

    allowStringValue: false,
    stringName: null,
    stringValue: '',
    hasStringValue: function() {
        return (this.get('stringValue') && !this.get('hasFocus'));
    }.property('hasFocus', 'stringValue'),

    autoSelectIfOne: false,

    initType: function() {
        var type = this.get('type');
        if (typeof type === 'string') {
            var typeName = type;
            type = this.container.lookup('super-field-type:'+typeName);
            Ember.assert('Invalid super field type name: '+typeName, type);
        } else {
            Ember.assert('Invalid super field type: '+type, type instanceof BasicType);
        }
        type.set('field', this);
        this.set('type', type);
    },

    query: null,

    icon: function() {
        return this.get('value.' + this.get('type.iconPath'));
    }.property('value'),

    selectOnFocus: true,
    picker1Icon: 'icons/caret-down',

    didClickPicker1: function() {
        if (this.get('selector')) {
            this.hideSelector();
        } else {
            if (!Em.isEmpty(this.get('type.q'))) {
                this.get('type').resetContent();
            }
            this.showSelector();
            this.get('type').setQ('', true);
        }
        this.focus();
    },

    allowUnformatInputValue: false,
    formatInputValue: function(value) {
        var inputValuePath = this.get('type.inputValuePath');
        return Em.isEmpty(value) ? this.get('inputValue') : (inputValuePath ? value.get(inputValuePath) : '');
    },

    //Value handling
    superFieldValueDidChange: function() {
        if (this.get('value')) {
            this.set('stringValue', null);
        } else {
            this.set('inputValue', '');
        }
    }.observes('value'),
    superFieldInputValueDidChange: function() {
        if (this.get('allowStringValue') && !this.get('value')) {
            this.set('stringValue', this.get('inputValue'));
        }
        this.get('type').setQ(this.get('inputValue'));
    }.observes('inputValue'),
    didBlur: function() {
        this._super();
        //If the value is empty and allowStringValue == false, then we need to handle the inputValue somehow if it is set
        if (Em.isEmpty(this.get('value')) && !this.get('allowStringValue') && !Em.isEmpty(this.get('inputValue'))) {
            var type = this.get('type');
            if (this.get('autoSelectOnBlur')) {
                //If autoSelectOnBlur == true we either select the one and only option, or add an error to the field
                if (type.get('isLoading')) {
                    type.one('didLoad', this, this.autoSelect);
                } else {
                    this.autoSelect();
                }
            } else {
                //Otherwise we clear the inputValue
                this.set('inputValue', '');
            }
        }
    },

    autoSelect: function() {
        var content = this.get('type.content');
        if (content.get('length') === 1) {
            this.set('value', content.get('firstObject'));
        } else {
            this.set('error', t('no_single_value_found'));
        }
    },

    //DOM events
    didInsertElement: function() {
        this._super();
        var input = this.$('input');
        input.keydown(Billy.proxy(this.didKeyDown, this));
    },
    willDestroyElement: function() {
        this._super();
        this.get('type').destroy();
        this.hideSelector();
    },

    didKeyDown: function(e) {
        var self = this,
            key = e.keyCode || e.which,
            hasModifier = e.ctrlKey || e.metaKey;
        switch (key) {
            case $.keyCode.ESCAPE:
            case $.keyCode.UP:
            case $.keyCode.DOWN:
            case $.keyCode.ENTER:
                e.preventDefault();
                break;
        }
        Em.run(function() {
            self.doDidKeyDown(key, hasModifier);
        });
    },
    doDidKeyDown: function(key, hasModifier) {
        switch (key) {
            case $.keyCode.ESCAPE:
                this.hideSelector();
                break;
                break;
            case $.keyCode.UP:
                this.didPressUp();
                break;
            case $.keyCode.DOWN:
                this.didPressDown();
                break;
            case $.keyCode.TAB:
            case $.keyCode.ENTER:
                this.didPressEnter();
                break;
            case $.keyCode.LEFT:
            case $.keyCode.RIGHT:
            case 91: //Left command
            case 93: //Right command
            case 18: //Alt
            case 17: //Control
            case 16: //Shift
                //Ignore
                break;
            default:
                if (this.get('allowKeyInput')) {
                    //Ignore everything with Ctrl or Cmd
                    if (hasModifier) {
                        break;
                    }
                    this.selectOption(null);
                    if (!this.get('selector')) {
                        this.get('type').resetContent();
                        this.showSelector();
                    }
                }
                break;
        }
    },

    //Key handling
    didPressUp: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressUp();
        }
    },
    didPressDown: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressDown();
        } else if (this.get('showSelectorOnDownArrow')) {
            this.showSelector();
            this.get('type').setQ(this.get('inputValue'), true);
            this.get('selector').highlightOptionByIndex(0);
        }
    },
    didPressEnter: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.didPressEnter();
        }
    },

    //Selector
    showSelector: function() {
        var self = this,
            selector = this.get('selector');
        if (!selector) {
            selector = require('./selector').create({
                container: this.container
            });
            this.set('selector', selector);
            selector.set('field', this);
            selector.one('willDestroyElement', function() {
                self.set('selector', null);
            });
            selector.show(this);
        }
    },
    hideSelector: function() {
        var selector = this.get('selector');
        if (selector) {
            selector.destroy();
        }
    },
    selectOption: function(option) {
        var didChange = (option || null) !== (this.get('value') || null);
        this.set('value', option);
        if (didChange) {
            Em.run.schedule('sync', this, function() {
                this.sendAction('didSelect', option);
            });
        }
    },

    //Create
    create: function() {
        var self = this,
            type = this.get('type'),
            create = type.get('create');
        Ember.assert('No create method set on superfield type.', create);
        this.hideSelector();
        create.call(type, this.get('inputValue'), function(value) {
            self.selectOption(value);
        });
    }
});

module.exports.types = {
    Basic: require('./types/basic'),
    Model: require('./types/model'),
    Empty: require('./types/empty')
};

module.exports.OptionView = require('./option-view');

module.exports.locale = i18nContext.locale;

module.exports.lang = function() {
    console.warn('.lang() is deprecated. Use .locale() instead');
    return i18nContext.locale.apply(null, arguments);
};<|endoftext|>


<commit_before>function CookieStore (name, minCustomers, maxCustomers, avgCookiesPerCust) {
    this.name = name;
    this.minCustomers = minCustomers;
    this.maxCustomers = maxCustomers;
    this.avgCookiesPerCust = avgCookiesPerCust;
    this.elementId = this.name; //TO DO: replace constructor instances of this.elementId with this.name
    this.staticCookies = [];
    this.cookieSum = 0;
    this.addToDom();
};

CookieStore.prototype.randomCust = function () {
    return (Math.floor(Math.random() * (this.maxCustomers - this.minCustomers + 1)) + this.minCustomers);
};

CookieStore.prototype.avgCookiesPerHour = function () {
    return this.randomCust() * this.avgCookiesPerCust;
};

CookieStore.prototype.cookieDataArray = function () {
    for (var i = 0; i < 15; i++){
        this.staticCookies.push(Math.floor(this.avgCookiesPerHour()));
    }
};

//Cookie tosser requirement formula
CookieStore.prototype.cookieTossers = function (input) {
    if (input < 40){
        return 2;
    }
    else if (input % 20 == 0){
        return input / 20;
    }
    else {
        return Math.floor(input / 20) + 1;
    }
};

//Method to make new table element with optional id
CookieStore.prototype.makeTableElement = function (elementName, elementType, newElementId) {
    var container = document.getElementById(elementName);
    var createNewElement = document.createElement(elementType);
    createNewElement.id = newElementId;
    container.appendChild( createNewElement );
};

//Method to make new TD element with inner HTML content **DOESNT WORK YET**
CookieStore.prototype.makeHTMLelement = function (container,elementType, innerHTML, tosser) {
    if (tosser) {
        var createTosserElement = document.createElement( elementType );
        createTosserElement.innerHTML = innerHTML;
        container.appendChild( createTosserElement );
    }
    else {
        var createNewElement = document.createElement(elementType);
        createNewElement.innerHTML = innerHTML;
        container.appendChild( createNewElement );
    }
};

CookieStore.prototype.addToDom = function () {
    this.cookieDataArray();
    //Create TR element with id as this.elementId
    this.makeTableElement('masterTable','tr',this.elementId);
    //cookietosser code - create same code as above in cookieTosser table
    this.makeTableElement('cookieTossers','tr',this.elementId + 'tosser','');

    //Create TD Element with location name
    var container = document.getElementById(this.elementId);
    this.makeHTMLelement(container, 'td','' + this.name + '');

    //cookietosser code - apply the same code to the "elementID+tosser" element
    var tosserContainer = document.getElementById(this.elementId + 'tosser');
    this.makeHTMLelement(tosserContainer,'td','' + this.name + '', true);

    for (var i = 0; i < this.staticCookies.length; i++) { //populate table row with td elements containing each element from staticCookies array
        this.makeHTMLelement(container,'td',this.staticCookies[i]);
        //cookietosser code- does the same as above, but numbers are run through the cookieTossers method
        this.makeHTMLelement(tosserContainer,'td',this.cookieTossers(this.staticCookies[i]),true);
    }
    //calculate total
    for (var i = 0; i < this.staticCookies.length; i++){
        this.cookieSum = this.cookieSum + this.staticCookies[i];
    }
    this.makeHTMLelement(container,'td','' + this.cookieSum + '');
};

//create table headers populated with openHours elements
CookieStore.prototype.tableHeaders = function(){
    var openHours = ['6:00am','7:00am','8:00am','9:00am','10:00am','11:00am','12:00am','1:00pm','2:00pm','3:00pm','4:00pm','5:00pm','6:00pm','7:00pm','8:00pm', 'Total'];

    //create new row for main table, inserting before all other child elements
    var headers = document.getElementById('masterTable');
    var headerTableRow = document.createElement( 'tr' );
    headerTableRow.id = 'headerRow';
    headers.insertBefore(headerTableRow, headers.childNodes[0]);

    //create empty TH element
    var tableHeader = document.getElementById('headerRow');
    var createTableHead = document.createElement( 'th' );
    tableHeader.appendChild( createTableHead );

    //cookietosser code - create cookietosser headers
    var tosserHeaders = document.getElementById('cookieTossers');
    var headerTableRow = document.createElement( 'tr' );
    headerTableRow.id = 'tosserRow';
    tosserHeaders.insertBefore(headerTableRow, tosserHeaders.childNodes[0]);
    //create empty TH element
    var tosserHeader = document.getElementById('tosserRow');
    var createTosserHead = document.createElement( 'th' );
    tosserHeader.appendChild( createTosserHead );

    for (var i = 0; i < openHours.length; i++) {
        var createTableHead = document.createElement( 'th' );
        createTableHead.innerHTML = openHours[i];
        tableHeader.appendChild( createTableHead );
        //cookietosser code - nested if conditional to prevent cookietosser table from loading "Total" column
        if ( i < openHours.length - 1 ){
            var createTosserHead = document.createElement( 'th' );
            createTosserHead.innerHTML = openHours[i];
            tosserHeader.appendChild( createTosserHead );
        }
    }
}; // End of tableHeaders method

//Calculate total cookies in all stores
CookieStore.prototype.totalCookies = function () {

    //create new table row to display column totals
    var container = document.getElementById('masterTable');
    var newTableRow = document.createElement( 'tr' );
    newTableRow.id = 'totals' ;
    container.appendChild( newTableRow );

    //create blank table header
    container = document.getElementById( 'totals' );
    var totalTableHeader = document.createElement( 'th' );
    totalTableHeader.innerHTML = 'Totals';
    container.appendChild( totalTableHeader );

    for (var rowNumber = 0; rowNumber < cookieStoreArray[0].staticCookies.length; rowNumber++){
        var totalCookieTD = document.createElement( 'td' );
        var trackyMcVariable = 0;
        for (var colNumber = 0; colNumber < cookieStoreArray.length; colNumber++){
            trackyMcVariable += cookieStoreArray[colNumber].staticCookies[rowNumber];
        }
        totalCookieTD.innerHTML = '' + trackyMcVariable + '';
        container.appendChild( totalCookieTD );
    }
    //calculate cookie total per td
    var totalCounter = 0;
    for (var i = 0; i < cookieStoreArray.length; i++){ //TO DO: change length to be based on number of children of 'masterTable' element
        totalCounter = totalCounter + cookieStoreArray[i].cookieSum;
    }
    // var container = document.getElementById('total');
    var totalHeader = document.createElement('td');
    totalHeader.innerHTML = '' + totalCounter + '';
    container.appendChild( totalHeader );
};

var cookieStoreArray = [
    new CookieStore('PDX Airport', 23, 65, 6.3),
    new CookieStore('Pioneer Square', 3, 24, 1.2),
    new CookieStore('Powell\'s', 11, 38, 3.7),
    new CookieStore('St Johns', 20, 38, 2.3),
    new CookieStore('Waterfront', 2, 16, 4.6)
];
// cookieStoreArray[0].tableHeaders();
cookieStoreArray[0].totalCookies();

//Form & Event Sorcery

var form = document.getElementById( 'store-entry' ); //.this referrs to form (html element that is listening )
form.addEventListener( 'submit', function(){
    event.preventDefault();

    //ALTERNATIVE WAY TO WRITE THIS
    // var name = event.target.storeName.value;
    // var minCustomers = parseInt(event.target.minCustomers.value);
    // var maxCustomers = parseInt(event.target.maxCustomers.value);
    // var avgCookiesPerCust = parseInt(event.target.avgCookies.value);
    // var newQuestion = new CookieStore (name, minCustomers, maxCustomers, avgCookiesPerCust);
    var removeTotal = document.getElementById( 'totals' );
    removeTotal.outerHTML = '';
    var newQuestion = new CookieStore ( this.storeName.value, parseInt(this.minCustomers.value), parseInt(this.maxCustomers.value), this.avgCookies.value);
    cookieStoreArray[0].totalCookies();
    // document.form.reset();   TO DO: MAKE THE TEXT FIELDS CLEAR ON SUBMIT

    //DEBUGGING HELPER GARBAGE
    // console.log('submitted store name is ' + this.storeName );
    // console.log('submitted mincustomers is ' + this.minCustomers );
    // console.log('submitted max customers is ' + this.maxCustomers.value );
    // console.log('submitted avg is ' + this.avgCookies.value );
});<commit_msg>fix total error<commit_after>function CookieStore (name, minCustomers, maxCustomers, avgCookiesPerCust) {
    this.name = name;
    this.minCustomers = minCustomers;
    this.maxCustomers = maxCustomers;
    this.avgCookiesPerCust = avgCookiesPerCust;
    this.elementId = this.name; //TO DO: replace constructor instances of this.elementId with this.name
    this.staticCookies = [];
    this.cookieSum = 0;
    this.addToDom();
};

CookieStore.prototype.randomCust = function () {
    return (Math.floor(Math.random() * (this.maxCustomers - this.minCustomers + 1)) + this.minCustomers);
};

CookieStore.prototype.avgCookiesPerHour = function () {
    return this.randomCust() * this.avgCookiesPerCust;
};

CookieStore.prototype.cookieDataArray = function () {
    for (var i = 0; i < 15; i++){
        this.staticCookies.push(Math.floor(this.avgCookiesPerHour()));
    }
};

//Cookie tosser requirement formula
CookieStore.prototype.cookieTossers = function (input) {
    if (input < 40){
        return 2;
    }
    else if (input % 20 == 0){
        return input / 20;
    }
    else {
        return Math.floor(input / 20) + 1;
    }
};

//Method to make new table element with optional id
CookieStore.prototype.makeTableElement = function (elementName, elementType, newElementId) {
    var container = document.getElementById(elementName);
    var createNewElement = document.createElement(elementType);
    createNewElement.id = newElementId;
    container.appendChild( createNewElement );
};

//Method to make new TD element with inner HTML content **DOESNT WORK YET**
CookieStore.prototype.makeHTMLelement = function (container,elementType, innerHTML, tosser) {
    if (tosser) {
        var createTosserElement = document.createElement( elementType );
        createTosserElement.innerHTML = innerHTML;
        container.appendChild( createTosserElement );
    }
    else {
        var createNewElement = document.createElement(elementType);
        createNewElement.innerHTML = innerHTML;
        container.appendChild( createNewElement );
    }
};

CookieStore.prototype.addToDom = function () {
    this.cookieDataArray();
    //Create TR element with id as this.elementId
    this.makeTableElement('masterTable','tr',this.elementId);
    //cookietosser code - create same code as above in cookieTosser table
    this.makeTableElement('cookieTossers','tr',this.elementId + 'tosser','');

    //Create TD Element with location name
    var container = document.getElementById(this.elementId);
    this.makeHTMLelement(container, 'td','' + this.name + '');

    //cookietosser code - apply the same code to the "elementID+tosser" element
    var tosserContainer = document.getElementById(this.elementId + 'tosser');
    this.makeHTMLelement(tosserContainer,'td','' + this.name + '', true);

    for (var i = 0; i < this.staticCookies.length; i++) { //populate table row with td elements containing each element from staticCookies array
        this.makeHTMLelement(container,'td',this.staticCookies[i]);
        //cookietosser code- does the same as above, but numbers are run through the cookieTossers method
        this.makeHTMLelement(tosserContainer,'td',this.cookieTossers(this.staticCookies[i]),true);
    }
    //calculate total
    for (var i = 0; i < this.staticCookies.length; i++){
        this.cookieSum = this.cookieSum + this.staticCookies[i];
    }
    this.makeHTMLelement(container,'td','' + this.cookieSum + '');
};

//create table headers populated with openHours elements
CookieStore.prototype.tableHeaders = function(){
    var openHours = ['6:00am','7:00am','8:00am','9:00am','10:00am','11:00am','12:00am','1:00pm','2:00pm','3:00pm','4:00pm','5:00pm','6:00pm','7:00pm','8:00pm', 'Total'];

    //create new row for main table, inserting before all other child elements
    var headers = document.getElementById('masterTable');
    var headerTableRow = document.createElement( 'tr' );
    headerTableRow.id = 'headerRow';
    headers.insertBefore(headerTableRow, headers.childNodes[0]);

    //create empty TH element
    var tableHeader = document.getElementById('headerRow');
    var createTableHead = document.createElement( 'th' );
    tableHeader.appendChild( createTableHead );

    //cookietosser code - create cookietosser headers
    var tosserHeaders = document.getElementById('cookieTossers');
    var headerTableRow = document.createElement( 'tr' );
    headerTableRow.id = 'tosserRow';
    tosserHeaders.insertBefore(headerTableRow, tosserHeaders.childNodes[0]);
    //create empty TH element
    var tosserHeader = document.getElementById('tosserRow');
    var createTosserHead = document.createElement( 'th' );
    tosserHeader.appendChild( createTosserHead );

    for (var i = 0; i < openHours.length; i++) {
        var createTableHead = document.createElement( 'th' );
        createTableHead.innerHTML = openHours[i];
        tableHeader.appendChild( createTableHead );
        //cookietosser code - nested if conditional to prevent cookietosser table from loading "Total" column
        if ( i < openHours.length - 1 ){
            var createTosserHead = document.createElement( 'th' );
            createTosserHead.innerHTML = openHours[i];
            tosserHeader.appendChild( createTosserHead );
        }
    }
}; // End of tableHeaders method

//Calculate total cookies in all stores
CookieStore.prototype.totalCookies = function () {

    //create new table row to display column totals
    var container = document.getElementById('masterTable');
    var newTableRow = document.createElement( 'tr' );
    newTableRow.id = 'totals' ;
    container.appendChild( newTableRow );

    //create blank table header
    container = document.getElementById( 'totals' );
    var totalTableHeader = document.createElement( 'th' );
    totalTableHeader.innerHTML = 'Totals';
    container.appendChild( totalTableHeader );

    for (var rowNumber = 0; rowNumber < cookieStoreArray[0].staticCookies.length; rowNumber++){
        var totalCookieTD = document.createElement( 'td' );
        var trackyMcVariable = 0;
        for (var colNumber = 0; colNumber < cookieStoreArray.length; colNumber++){
            trackyMcVariable += cookieStoreArray[colNumber].staticCookies[rowNumber];
        }
        totalCookieTD.innerHTML = '' + trackyMcVariable + '';
        container.appendChild( totalCookieTD );
    }
    //calculate cookie total per td
    var totalCounter = 0;
    for (var i = 0; i < cookieStoreArray.length; i++){ //TO DO: change length to be based on number of children of 'masterTable' element
        totalCounter = totalCounter + cookieStoreArray[i].cookieSum;
    }
    // var container = document.getElementById('total');
    var totalHeader = document.createElement('td');
    totalHeader.innerHTML = '' + totalCounter + '';
    container.appendChild( totalHeader );
};

var cookieStoreArray = [
    new CookieStore('PDX Airport', 23, 65, 6.3),
    new CookieStore('Pioneer Square', 3, 24, 1.2),
    new CookieStore('Powell\'s', 11, 38, 3.7),
    new CookieStore('St Johns', 20, 38, 2.3),
    new CookieStore('Waterfront', 2, 16, 4.6)
];
// cookieStoreArray[0].tableHeaders();
cookieStoreArray[0].totalCookies();

//Form & Event Sorcery

var form = document.getElementById( 'store-entry' ); //.this referrs to form (html element that is listening )
form.addEventListener( 'submit', function(){
    event.preventDefault();

    //ALTERNATIVE WAY TO WRITE THIS PART
    // var name = event.target.storeName.value;
    // var minCustomers = parseInt(event.target.minCustomers.value);
    // var maxCustomers = parseInt(event.target.maxCustomers.value);
    // var avgCookiesPerCust = parseInt(event.target.avgCookies.value);
    // var newQuestion = new CookieStore (name, minCustomers, maxCustomers, avgCookiesPerCust);

    var removeTotal = document.getElementById( 'totals' );
    removeTotal.outerHTML = '';
    cookieStoreArray.push(new CookieStore ( this.storeName.value, parseInt(this.minCustomers.value), parseInt(this.maxCustomers.value), this.avgCookies.value));
    cookieStoreArray[0].totalCookies();
    // document.form.reset();   TO DO: MAKE THE TEXT FIELDS CLEAR ON SUBMIT

    //DEBUGGING HELPER GARBAGE
    // console.log('submitted store name is ' + this.storeName );
    // console.log('submitted mincustomers is ' + this.minCustomers );
    // console.log('submitted max customers is ' + this.maxCustomers.value );
    // console.log('submitted avg is ' + this.avgCookies.value );
});<|endoftext|>


<commit_before>/**
 * Basic View Engine. (Using Mustache.js as templating engine)
 *
 * Plugins (to app)
 * ----------------
 * app.ve
 * app.ve.view
 * app.ve.component
 * app.ve.components
 * app.ve.inject
 * $(el).data('view')
 *
 *
 * Use of View
 * -----------
 * 1. new View({
 * 		template: [name],
 * 		[init]: function(){...}
 * 		[$el]:
 * 		[data]:
 * 		[events]:
 * })
 * 2. view.render(data, [$el])
 * 3. view.on/trigger/once/off()
 * 4. view.teardown()
 * 5. View.extend({...})
 * 6. view.bind() TBI (two-way with binders in tpl)
 * 7. view.vm (available after view.bind())
 *
 *
 * Life cycle
 * ----------
 * init() --> render(e) --> render(e) ... --> teardown(e)
 *
 * *Note*: that due to implemenation constrains (using $el for events) init() will not emit any `initialize` event.
 *
 *
 * Ghost View
 * ----------
 * 1. only views with `$el` can be rendered on screen, otherwise html is returned by `.render()`;
 * 2. only `template` name is required when defining a View, `data` and `$el` can be inserted later using `.render()`;
 * 3. only views with `$el` can register events;
 * 4. rendering same view again and again will not re-register the listeners;
 * 5. rendering a new view on a `$el` will `.teardown()` the previous view if template names are different;
 * 6. `.teardown()` will not `$.remove()` a view's `$el`, but `$.empty()` it and remove all the event listeners;
 *
 * Ghost View will NOT happen in this implementation since jQuery removes data and event handlers from child
 * elements during `$.empty()`. If you render parent `$el` with a new view, child views will be removed properly
 * given that we bind everything on the `$el` through jQuery.
 *
 *
 * Gotcha
 * ------
 * 1. If you use `app.coordinator.on` for co-op with other things in the application, make sure to clean the listener
 * up in the view's `teardown` event.
 * 2. there are no `on<event>` shortcut functions for listeners in a view. use `.on`/`.once` and `options.events` to
 * register them instead.
 *
 *
 * Hardcode
 * --------
 * 1. templates must be named `*.mst.html`
 *
 *
 * @author Tim Lauv <bluekvirus@gmail.com>
 * @created 2015.04.27
 */
(function(_, $, app, Mustache){
	app.ve = {name: 'Basic', _tplSuffix: '.mst.html'};

	//--------------------------------View class definition---------------------------------
	//.template, .$el, .data, init() .render(e), .teardown(e), .events, .once/on/off/trigger()
	//constructor (logic-free)
	var View = function(options){
		this._options = options || {};

		//optional
		this.$el = this._options.el && $(this._options.el);
		this.$el = this._options.$el || this.$el;
		this.data = this._options.data || this.data;
		this.init = this._options.init || this._options.initialize || this.init;
		this.events = this._options.events || this.events;
		this.template = this._options.template || this.template;

		//extension point
		this.init(this._options);
		if(this.$el) this.render();
	};
	//member methods
	_.extend(View.prototype, {
		init: _.noop,

		render: function($el, data){

			//check the template first!
			if(!this.template) app.throw('View definition requires a template!');
			var tpl = app.templates[this.template] || app.templates[this.template + app.ve._tplSuffix] || this.template;

			this.$el = $el || this.$el;
			this.data = data || this.data;

			var content = Mustache.render(tpl, this.data);

			if(this.$el) {
				//teardown previous view if template is different.
				var meta = this.$el.data();
				if(meta.view && (meta.view.template !== this.template))
					meta.view.teardown();

				//re-render but not registering the listeners again.
				this.$el.html(content);
				if(!this.$el.data('_events_')) {
					this.$el.on(this.events);
					this.$el.data('_events_', true);
				}
				this.$el.data('view', this);
			}
			else return content;

			this.trigger('render');
			return this;
		},

		teardown: function(){
			if(this.$el){
				this.$el.removeData('_events_', 'view');
				this.$el.empty();
				this.trigger('teardown');
				this.off();
			}
		},

		//dynamic instance events support .once, .trigger
		//use options.events for easy .on listener registration.
		once: function(){
			if(this.$el) {
				this.$el.one.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		on: function(){
			if(this.$el) {
				this.$el.on.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		off: function(){
			if(this.$el) {
				this.$el.off.apply(this.$el, arguments);
			}
		},

		trigger: function(){
			if(this.$el) {
				//note that we use triggerHandler instead of trigger to avoid custom event bubbling
				this.$el.triggerHandler.apply(this.$el, arguments);
			}
		},

		$trigger: function(){
			if(this.$el) {
				//allow event bubbling
				this.$el.trigger.apply(this.$el, arguments);
			}
		}
	});
	//static methods
	_.extend(View, {
		//class inheritance
		extend: function(configure, statics){
			var A = this.prototype.constructor;

			var B = function(){
				A.apply(this, arguments); //instead of A.call(this, arg1, arg2, ...)
			};

			B.prototype = new A(); //logic-free constructor
			_.extend(B.prototype, configure);
			_.extend(B, A, statics);
			//note that `prototype` and `constructor` are non-enumerable, thus won't be copied by _.extend()

			B.prototype.constructor = B;

			return B;
		}
	});

	//-----------------hooks into app infrastructure-------------------
	//convert templates into components
	app.coordinator.on('app.load', function(){

		_.each(app.templates, function(tpl, filename){
			var name = app.tplNameToCompName(filename, app.ve._tplSuffix);
			app.ve.component(name, {
				template: filename
			});

			app.debug('component registered:', name);
		});

		app.coordinator.trigger('app.loaded');
	});

	//----------------apis enhancement to app-------------------------
	app.ve.view = function(options){
		return new View(options);
	};

	app.ve.components = {};
	app.ve.component = function(name, configure){
		if(app.ve.components[name]) {
			//override
			app.ve.components[name] = app.ve.components[name].extend(configure);
		} else
			//register
			app.ve.components[name] = View.extend(configure);
		return app.ve.components[name];
	};

	app.ve.inject = function(options, cb){
		if(!app.isAMDEnabled()) app.throw('AMD is not enabled, use task:dance before ve.inject()');
		if(_.isString(options))
			options = {path: options};
		if(_.isFunction(options)){
			cb = options;
			options = {};
		}
		options = _.extend({
			baseURL: 'vanilla/',
			tplOnly: false,
			forceName: ''
		}, options);
		var compName = options.forceName?options.forceName:app.tplNameToCompName(options.path);
		var tplTarget = _.endsWith(options.path, '/')?[options.baseURL, options.path, 'index', app.ve._tplSuffix].join(''):[options.baseURL, options.path, app.ve._tplSuffix].join(''),
		jsTarget = tplTarget.replace(app.ve._tplSuffix, '');
		var targets = ['text!' + tplTarget];
		if(!options.tplOnly) targets.push(jsTarget);
		//don't use define here... the cb will never gets invoked. (until what's define()-ed gets required)
		require(targets, function(tpl, js){
			js = js || {};
			//success cb
			cb(null, app.ve.component(compName, _.extend(js, {template: tpl})));
		}, cb);//as error cb
	};

})(_, jQuery, Application, Mustache);<commit_msg>ve.inject now supports multiple targets. updated view.render params.<commit_after>/**
 * Basic View Engine. (Using Mustache.js as templating engine)
 *
 * Plugins (to app)
 * ----------------
 * app.ve
 * app.ve.view
 * app.ve.component
 * app.ve.components
 * app.ve.inject
 * $(el).data('view')
 *
 *
 * Use of View
 * -----------
 * 1. new View({
 * 		template: [name],
 * 		[init]: function(){...}
 * 		[$el]:
 * 		[data]:
 * 		[events]:
 * })
 * 2. view.render(data, [$el])
 * 3. view.on/($)trigger/once/off()
 * 4. view.teardown()
 * 5. View.extend({...})
 * 6. view.bind() TBI (two-way with binders in tpl)
 * 7. view.vm (available after view.bind())
 *
 *
 * Life cycle
 * ----------
 * init() --> render(e) --> render(e) ... --> teardown(e)
 *
 * *Note*: that due to implemenation constrains (using $el for events) init() will not emit any `initialize` event.
 *
 *
 * Ghost View
 * ----------
 * 1. only views with `$el` can be rendered on screen, otherwise html is returned by `.render()`;
 * 2. only `template` name is required when defining a View, `data` and `$el` can be inserted later using `.render()`;
 * 3. only views with `$el` can register events;
 * 4. rendering same view again and again will not re-register the listeners;
 * 5. rendering a new view on a `$el` will `.teardown()` the previous view if template names are different;
 * 6. `.teardown()` will not `$.remove()` a view's `$el`, but `$.empty()` it and remove all the event listeners;
 *
 * Ghost View will NOT happen in this implementation since jQuery removes data and event handlers from child
 * elements during `$.empty()`. If you render parent `$el` with a new view, child views will be removed properly
 * given that we bind everything on the `$el` through jQuery.
 *
 *
 * Gotcha
 * ------
 * 1. If you use `app.coordinator.on` for co-op with other things in the application, make sure to clean the listener
 * up in the view's `teardown` event.
 * 2. there are no `on<event>` shortcut functions for listeners in a view. use `.on`/`.once` and `options.events` to
 * register them instead.
 *
 *
 * Hardcode
 * --------
 * 1. templates must be named `*.mst.html`
 *
 *
 * @author Tim Lauv <bluekvirus@gmail.com>
 * @created 2015.04.27
 */
(function(_, $, app, Mustache){
	app.ve = {name: 'Basic', _tplSuffix: '.mst.html'};

	//--------------------------------View class definition---------------------------------
	//.template, .$el, .data, init() .render(e), .teardown(e), .events, .once/on/off/trigger()
	//constructor (logic-free)
	var View = function(options){
		this._options = options || {};

		//optional
		this.$el = this._options.el && $(this._options.el);
		this.$el = this._options.$el || this.$el;
		this.data = this._options.data || this.data;
		this.init = this._options.init || this._options.initialize || this.init;
		this.events = this._options.events || this.events;
		this.template = this._options.template || this.template;

		//extension point
		this.init(this._options);
		if(this.$el) this.render();
	};
	//member methods
	_.extend(View.prototype, {
		init: _.noop,

		render: function(data, $el){

			//check the template first!
			if(!this.template) app.throw('View definition requires a template!');
			var tpl = app.templates[this.template] || app.templates[this.template + app.ve._tplSuffix] || this.template;

			//sanitize params
			if(data instanceof jQuery){
				$el = data;
				data = undefined;
			}

			this.$el = $el || this.$el;
			this.data = data || this.data;

			var content = Mustache.render(tpl, this.data);

			if(this.$el) {
				//teardown previous view if template is different.
				var meta = this.$el.data();
				if(meta.view && (meta.view.template !== this.template))
					meta.view.teardown();

				//re-render but not registering the listeners again.
				this.$el.html(content);
				if(!this.$el.data('_events_')) {
					this.$el.on(this.events);
					this.$el.data('_events_', true);
				}
				this.$el.data('view', this);
			}
			else return content;

			this.trigger('render');
			return this;
		},

		teardown: function(){
			if(this.$el){
				this.$el.removeData('_events_', 'view');
				this.$el.empty();
				this.trigger('teardown');
				this.off();
			}
		},

		//dynamic instance events support .once, .trigger
		//use options.events for easy .on listener registration.
		once: function(){
			if(this.$el) {
				this.$el.one.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		on: function(){
			if(this.$el) {
				this.$el.on.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		off: function(){
			if(this.$el) {
				this.$el.off.apply(this.$el, arguments);
			}
		},

		trigger: function(){
			if(this.$el) {
				//note that we use triggerHandler instead of trigger to avoid custom event bubbling
				this.$el.triggerHandler.apply(this.$el, arguments);
			}
		},

		$trigger: function(){
			if(this.$el) {
				//allow event bubbling
				this.$el.trigger.apply(this.$el, arguments);
			}
		}
	});
	//static methods
	_.extend(View, {
		//class inheritance
		extend: function(configure, statics){
			var A = this.prototype.constructor;

			var B = function(){
				A.apply(this, arguments); //instead of A.call(this, arg1, arg2, ...)
			};

			B.prototype = new A(); //logic-free constructor
			_.extend(B.prototype, configure);
			_.extend(B, A, statics);
			//note that `prototype` and `constructor` are non-enumerable, thus won't be copied by _.extend()

			B.prototype.constructor = B;

			return B;
		}
	});

	//-----------------hooks into app infrastructure-------------------
	//convert templates into components
	app.coordinator.on('app.load', function(){

		_.each(app.templates, function(tpl, filename){
			var name = app.tplNameToCompName(filename, app.ve._tplSuffix);
			app.ve.component(name, {
				template: filename
			});

			app.debug('component registered:', name);
		});

		app.coordinator.trigger('app.loaded');
	});

	//----------------apis enhancement to app-------------------------
	app.ve.view = function(options){
		return new View(options);
	};

	app.ve.components = {};
	app.ve.component = function(name, configure){
		if(app.ve.components[name]) {
			//override
			app.ve.components[name] = app.ve.components[name].extend(configure);
		} else
			//register
			app.ve.components[name] = View.extend(configure);
		return app.ve.components[name];
	};

		//internal worker for ve.inject (single target, cb(err, result))
	function _inject (options, cb){
		if(!app.isAMDEnabled()) app.throw('AMD is not enabled, use task:dance before ve.inject()');
		if(_.isString(options))
			options = {path: options};
		if(_.isFunction(options)){
			cb = options;
			options = {};
		}
		options = _.extend({
			baseURL: 'vanilla/',
			tplOnly: false,
			forceName: ''
		}, options);
		var compName = options.forceName?options.forceName:app.tplNameToCompName(options.path);
		var tplTarget = _.endsWith(options.path, '/')?[options.baseURL, options.path, 'index', app.ve._tplSuffix].join(''):[options.baseURL, options.path, app.ve._tplSuffix].join(''),
		jsTarget = tplTarget.replace(app.ve._tplSuffix, '');
		var targets = ['text!' + tplTarget];
		if(!options.tplOnly) targets.push(jsTarget);
		//don't use define here... the cb will never gets invoked. (until what's define()-ed gets required)
		require(targets, function(tpl, js){
			js = js || {};
			//as success cb
			cb(null, app.ve.component(compName, _.extend(js, {template: tpl})));
		}, cb);//as error cb
	}
	//dynamically inject js + html to make a View or multiple View(s)
	app.ve.inject = function (options, cb){
		if(_.isArray(options)){
			app.coordinator.async.map(options, _inject, cb);
		} else {
			_inject(options, cb);
		}
	};

})(_, jQuery, Application, Mustache);<|endoftext|>


<commit_before>'use strict';

var AppDispatcher = require('../dispatchers/app-dispatcher');
var ActionTypes = require('../constants/scene-constants').ActionTypes;
var HubClient = require('../utils/HubClient');
var SceneActions = require('./scene-actions');

module.exports = {
    tryLogin: function(creds) {
    	AppDispatcher.handleViewAction({
            type: ActionTypes.HUB_LOGIN_ATTEMPT,
            authType: 'user'
        });
        // coming from envify
        HubClient.login(process.env.MEDIA_HUB, creds);
    },

    tryTokenLogin: function() {
        AppDispatcher.handleViewAction({
            type: ActionTypes.HUB_LOGIN_ATTEMPT,
            authType: 'token'
        });
        HubClient.login(process.env.MEDIA_HUB);
    },

    tryCreateScene: function(name, cb) {
    	var scene = {
    		'name': name,
    		'scene': []
    	};

    	HubClient.save(scene, function(newScene) {
            SceneActions.updateScene(newScene);
            // deffer the loading of AppRouter to prevent circular dependencies,
            // this would be better done with dependency injection
            // http://tomkit.wordpress.com/2013/02/05/circular-dependencies-dependency-injection-in-node-js/
            var AppRouter = require('../app-router.jsx');
            AppRouter.transitionTo('scene', {id: newScene._id});
        });
    },
    saveScene: function(scene) {
        HubClient.save(scene);
    },
    loadScene: HubClient.loadScene,
    subscribeScene: HubClient.subscribeScene,
    deleteScene: function(sceneId) {
        AppDispatcher.handleViewAction({
            type: ActionTypes.DELETE_SCENE,
            sceneId: sceneId
        });

        HubClient.deleteScene(sceneId);
        var AppRouter = require('../app-router.jsx');
        AppRouter.transitionTo('scenes');
    },
    unsubscribeScene: HubClient.unsubscribeScene
};<commit_msg>add themes property when makinga new scene. closes #30<commit_after>'use strict';

var AppDispatcher = require('../dispatchers/app-dispatcher');
var ActionTypes = require('../constants/scene-constants').ActionTypes;
var HubClient = require('../utils/HubClient');
var SceneActions = require('./scene-actions');

module.exports = {
    tryLogin: function(creds) {
    	AppDispatcher.handleViewAction({
            type: ActionTypes.HUB_LOGIN_ATTEMPT,
            authType: 'user'
        });
        // coming from envify
        HubClient.login(process.env.MEDIA_HUB, creds);
    },

    tryTokenLogin: function() {
        AppDispatcher.handleViewAction({
            type: ActionTypes.HUB_LOGIN_ATTEMPT,
            authType: 'token'
        });
        HubClient.login(process.env.MEDIA_HUB);
    },

    tryCreateScene: function(name, cb) {
    	var scene = {
    		'name': name,
            'themes': {},
    		'scene': []
    	};

    	HubClient.save(scene, function(newScene) {
            SceneActions.updateScene(newScene);
            // deffer the loading of AppRouter to prevent circular dependencies,
            // this would be better done with dependency injection
            // http://tomkit.wordpress.com/2013/02/05/circular-dependencies-dependency-injection-in-node-js/
            var AppRouter = require('../app-router.jsx');
            AppRouter.transitionTo('scene', {id: newScene._id});
        });
    },
    saveScene: function(scene) {
        HubClient.save(scene);
    },
    loadScene: HubClient.loadScene,
    subscribeScene: HubClient.subscribeScene,
    deleteScene: function(sceneId) {
        AppDispatcher.handleViewAction({
            type: ActionTypes.DELETE_SCENE,
            sceneId: sceneId
        });

        HubClient.deleteScene(sceneId);
        var AppRouter = require('../app-router.jsx');
        AppRouter.transitionTo('scenes');
    },
    unsubscribeScene: HubClient.unsubscribeScene
};<|endoftext|>


<commit_before>$.register({
  rule: {
    host: [
      /^mant[ae][pb]\.in$/,
      /^st\.oploverz\.net$/,
    ],
  },
  ready: function () {
    'use strict';

    var a = $('a.redirect, a[target=_blank][rel=nofollow]');
    $.openLink(a.href);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>Support for minidroid.net<commit_after>$.register({
  rule: {
    host: [
      /^mant[ae][pb]\.in$/,
      /^st\.oploverz\.net$/,
      /^minidroid\.net$/,
    ],
  },
  ready: function () {
    'use strict';

    var a = $('a.redirect, a[target=_blank][rel=nofollow]');
    $.openLink(a.href);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>import {Link} from 'react-router';
var React = require('react');

import Cluster from '../utils/Cluster';
var EventTypes = require('../constants/EventTypes');
import Framework from '../structs/Framework';
import HealthBar from './HealthBar';
import IconNewWindow from './icons/IconNewWindow';
var MarathonStore = require('../stores/MarathonStore');
var ResourceTableUtil = require('../utils/ResourceTableUtil');
var ServiceTableHeaderLabels = require('../constants/ServiceTableHeaderLabels');
import ServiceTableUtil from '../utils/ServiceTableUtil';
import ServiceTree from '../structs/ServiceTree';
import StringUtil from '../utils/StringUtil';
import {Table} from 'reactjs-components';
import TableUtil from '../utils/TableUtil';
var Units = require('../utils/Units');

const StatusMapping = {
  'Running': 'running-state'
};

var ServicesTable = React.createClass({

  displayName: 'ServicesTable',

  propTypes: {
    services: React.PropTypes.array.isRequired
  },

  componentDidMount: function () {
    MarathonStore.addChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  componentWillUnmount: function () {
    MarathonStore.removeChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  getDefaultProps: function () {
    return {
      services: []
    };
  },

  getOpenInNewWindowLink(service) {
    if (!(service instanceof Framework) || !service.getWebURL()) {
      return null;
    }

    return (

        <IconNewWindow className="icon icon-new-window icon-margin-left
          icon-margin-left-wide" />

    );
  },

  onMarathonAppsChange: function () {
    this.forceUpdate();
  },

  renderHeadline: function (prop, service) {
    const id = encodeURIComponent(service.getId());
    let itemImage = null;

    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      itemImage = (

      );
    }

    if (service instanceof Framework) {
      // Get framework image/icon
      itemImage = (

      );
    }

    return (

        <Link to="services-detail"
          className="table-cell-icon"
          params={{id}}>
          {itemImage}
        </Link>
        <Link to="services-detail"
          className="headline table-cell-value flex-box flex-box-col"
          params={{id}}>

            {service.getName()}

        </Link>
        {this.getOpenInNewWindowLink(service)}

    );
  },

  renderStatus: function (prop, service) {
    let instanceCount = service.getInstancesCount();
    let serviceStatus = service.getStatus();
    let serviceStatusClassSet = StatusMapping[serviceStatus] || '';
    let taskSummary = service.getTasksSummary();
    let {tasksRunning} = taskSummary;

    let text = ` (${tasksRunning} ${StringUtil.pluralize('Task', tasksRunning)})`;
    if (tasksRunning !== instanceCount) {
      text = ` (${tasksRunning} of ${instanceCount} Tasks)`;
    }

    return (

          <HealthBar tasksSummary={taskSummary} instancesCount={instanceCount} />

          {serviceStatus}
          {text}

    );
  },

  renderStats: function (prop, service) {
    return (

        {Units.formatResource(prop, service.getResources()[prop])}

    );
  },

  getColumns: function () {
    let className = ResourceTableUtil.getClassName;
    let heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);

    return [
      {
        className,
        headerClassName: className,
        prop: 'name',
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'status',
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'disk',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'cpus',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'mem',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      }
    ];
  },

  getColGroup: function () {
    return (
      <colgroup>
        <col />
        <col className="status-bar-column"/>
        <col style={{width: '100px'}} />
        <col className="hidden-mini" style={{width: '120px'}} />
        <col className="hidden-mini" style={{width: '120px'}} />
        <col className="hidden-mini" style={{width: '120px'}} />
      </colgroup>
    );
  },

  render: function () {
    return (

    );
  }
});

module.exports = ServicesTable;
<commit_msg>Adjust service table col widths<commit_after>import {Link} from 'react-router';
var React = require('react');

import Cluster from '../utils/Cluster';
var EventTypes = require('../constants/EventTypes');
import Framework from '../structs/Framework';
import HealthBar from './HealthBar';
import IconNewWindow from './icons/IconNewWindow';
var MarathonStore = require('../stores/MarathonStore');
var ResourceTableUtil = require('../utils/ResourceTableUtil');
var ServiceTableHeaderLabels = require('../constants/ServiceTableHeaderLabels');
import ServiceTableUtil from '../utils/ServiceTableUtil';
import ServiceTree from '../structs/ServiceTree';
import StringUtil from '../utils/StringUtil';
import {Table} from 'reactjs-components';
import TableUtil from '../utils/TableUtil';
var Units = require('../utils/Units');

const StatusMapping = {
  'Running': 'running-state'
};

var ServicesTable = React.createClass({

  displayName: 'ServicesTable',

  propTypes: {
    services: React.PropTypes.array.isRequired
  },

  componentDidMount: function () {
    MarathonStore.addChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  componentWillUnmount: function () {
    MarathonStore.removeChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  getDefaultProps: function () {
    return {
      services: []
    };
  },

  getOpenInNewWindowLink(service) {
    if (!(service instanceof Framework) || !service.getWebURL()) {
      return null;
    }

    return (

        <IconNewWindow className="icon icon-new-window icon-margin-left
          icon-margin-left-wide" />

    );
  },

  onMarathonAppsChange: function () {
    this.forceUpdate();
  },

  renderHeadline: function (prop, service) {
    const id = encodeURIComponent(service.getId());
    let itemImage = null;

    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      itemImage = (

      );
    }

    if (service instanceof Framework) {
      // Get framework image/icon
      itemImage = (

      );
    }

    return (

        <Link to="services-detail"
          className="table-cell-icon"
          params={{id}}>
          {itemImage}
        </Link>
        <Link to="services-detail"
          className="headline table-cell-value flex-box flex-box-col"
          params={{id}}>

            {service.getName()}

        </Link>
        {this.getOpenInNewWindowLink(service)}

    );
  },

  renderStatus: function (prop, service) {
    let instanceCount = service.getInstancesCount();
    let serviceStatus = service.getStatus();
    let serviceStatusClassSet = StatusMapping[serviceStatus] || '';
    let taskSummary = service.getTasksSummary();
    let {tasksRunning} = taskSummary;

    let text = ` (${tasksRunning} ${StringUtil.pluralize('Task', tasksRunning)})`;
    if (tasksRunning !== instanceCount) {
      text = ` (${tasksRunning} of ${instanceCount} Tasks)`;
    }

    return (

          <HealthBar tasksSummary={taskSummary} instancesCount={instanceCount} />

          {serviceStatus}
          {text}

    );
  },

  renderStats: function (prop, service) {
    return (

        {Units.formatResource(prop, service.getResources()[prop])}

    );
  },

  getColumns: function () {
    let className = ResourceTableUtil.getClassName;
    let heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);

    return [
      {
        className,
        headerClassName: className,
        prop: 'name',
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'status',
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'disk',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'cpus',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'mem',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      }
    ];
  },

  getColGroup: function () {
    return (
      <colgroup>
        <col />
        <col className="status-bar-column"/>
        <col className="hidden-mini" style={{width: '100px'}} />
        <col className="hidden-mini" style={{width: '100px'}} />
        <col className="hidden-mini" style={{width: '100px'}} />
      </colgroup>
    );
  },

  render: function () {
    return (

    );
  }
});

module.exports = ServicesTable;
<|endoftext|>


<commit_before>$.register({
  rule: [
    {
      host: /^(www\.)?sylnk\.net$/,
      query: /link=([^&]+)/,
    },
    {
      host: /^(www\.)?compul\.in$/,
      path: /^\/n\.php$/,
      query: /v=([^&]+)/,
    },
  ],
  start: function (m) {
    'use strict';
    var rawLink = atob(m.query[1]);

    $.openLink(rawLink);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>dlneko.com<commit_after>$.register({
  rule: [
    {
      host: [
        /^(www\.)?sylnk\.net$/,
        /^dlneko\.com$/,
      ],
      query: /link=([^&]+)/,
    },
    {
      host: /^(www\.)?compul\.in$/,
      path: /^\/n\.php$/,
      query: /v=([^&]+)/,
    },
  ],
  start: function (m) {
    'use strict';
    var rawLink = atob(m.query[1]);

    $.openLink(rawLink);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>/*!
 * Copyright 2018 Google LLC. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-baseline',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'src'
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2018 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: '@google-cloud/error-reporting',
    theme: 'lumen'
  },
  markdown: {
    idInHeadings: true
  }
};
<commit_msg>docs: use the jsdoc-fresh theme (#385)<commit_after>/*!
 * Copyright 2018 Google LLC. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-fresh',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'src'
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2018 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: '@google-cloud/error-reporting',
    theme: 'lumen'
  },
  markdown: {
    idInHeadings: true
  }
};
<|endoftext|>