<commit_before>/**
 * @class Oskari.analysis.bundle.analyse.AnalyseBundleInstance
 *
 * Main component and starting point for the analysis functionality. Analyse parameters dialog
 * is a layout down tool to configure analyse parameters .
 *
 * See Oskari.analysis.bundle.analyse.AnalyseBundle for bundle definition.
 *
 */
Oskari.clazz.define("Oskari.analysis.bundle.analyse.AnalyseBundleInstance",

    /**
     * @method create called automatically on construction
     * @static
     */

    function () {
        this.sandbox = undefined;
        this.started = false;
        this.plugins = {};
        this.localization = undefined;
        this.analyse = undefined;
        this.buttonGroup = 'viewtools';
        this.ignoreEvents = false;
        this.dialog = undefined;
        this.analyseHandler = undefined;
        this.analyseService = undefined;
        this.isMapStateChanged = true;
        this.state = undefined;
        this.conf = {};
        this.personalDataTab = undefined;
    }, {
        /**
         * @static
         * @property __name
         */
        __name: 'Analyse',
        /**
         * @method getName
         * @return {String} the name for the component
         */
        "getName": function () {
            return this.__name;
        },
        /**
         * @method getSandbox
         * @return {Oskari.mapframework.sandbox.Sandbox}
         */
        getSandbox: function () {
            return this.sandbox;
        },
        /**
         * @method getLocalization
         * Returns JSON presentation of bundles localization data for current language.
         * If key-parameter is not given, returns the whole localization data.
         *
         * @param {String} key (optional) if given, returns the value for key
         * @return {String/Object} returns single localization string or
         *      JSON object for complete data depending on localization
         *      structure and if parameter key is given
         */
        getLocalization: function (key) {
            if (!this._localization) {
                this._localization = Oskari.getLocalization(this.getName());
            }
            if (key) {
                return this._localization[key];
            }
            return this._localization;
        },
        /**
         * @method start
         * Implements BundleInstance protocol start method
         */
        "start": function () {
            var me = this;

            if (me.started) {
                return;
            }

            me.started = true;
            var conf = this.conf,
                sandboxName = (conf ? conf.sandbox : null) || 'sandbox',
                sandbox = Oskari.getSandbox(sandboxName),
                p;

            me.sandbox = sandbox;

            this.localization = Oskari.getLocalization(this.getName());

            sandbox.register(me);
            for (p in me.eventHandlers) {
                if (me.eventHandlers.hasOwnProperty(p)) {
                    sandbox.registerForEventByName(me, p);
                }
            }

            // requesthandler
            this.analyseHandler = Oskari.clazz.create('Oskari.analysis.bundle.analyse.request.AnalyseRequestHandler', me);
            sandbox.addRequestHandler('analyse.AnalyseRequest', this.analyseHandler);

            this.analyseService = Oskari.clazz.create('Oskari.analysis.bundle.analyse.service.AnalyseService', me);
            sandbox.registerService(this.analyseService);

            this.mapLayerService = sandbox.getService('Oskari.mapframework.service.MapLayerService');

            //Let's extend UI
            var request = sandbox.getRequestBuilder('userinterface.AddExtensionRequest')(this);
            sandbox.request(this, request);

            // draw ui
            me._createUi();

            // Load analysis layers
            this.analyseService.loadAnalyseLayers();

            /* stateful */
            if (conf && conf.stateful === true) {
                sandbox.registerAsStateful(this.mediator.bundleId, this);
            }

            // Request tab to be added to personal data
            var tab = Oskari.clazz.create('Oskari.mapframework.bundle.analyse.view.PersonalDataTab', this, this.localization.personalDataTab);
            var reqBuilder = sandbox.getRequestBuilder('PersonalData.AddTabRequest');

            if (reqBuilder) {
                sandbox.request(this, reqBuilder(this.localization.personalDataTab.title, tab.getContent()));
            }
            this.personalDataTab = tab;
        },
        /**
         * @method init
         * Implements Module protocol init method - does nothing atm
         */
        "init": function () {
            return null;
        },
        /**
         * @method update
         * Implements BundleInstance protocol update method - does nothing atm
         */
        "update": function () {

        },
        /**
         * @method onEvent
         * Event is handled forwarded to correct #eventHandlers if found or discarded if not.
         * @param {Oskari.mapframework.event.Event} event a Oskari event object
         */
        onEvent: function (event) {
            var handler = this.eventHandlers[event.getName()];
            if (!handler) {
                return;
            }
            return handler.apply(this, [event]);
        },
        /**
         * @property {Object} eventHandlers
         * @static
         */
        eventHandlers: {
            'MapLayerVisibilityChangedEvent': function (event) {
                if (this.analyse && this.analyse.isEnabled && this.isMapStateChanged) {
                    this.isMapStateChanged = false;
                    this.getSandbox().printDebug("ANALYSE REFRESH");
                    this.analyse.refreshAnalyseData(true);
                }
            },
            'AfterMapMoveEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
                this.isMapStateChanged = true;
            },
            'AfterMapLayerAddEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
            },
            'AfterMapLayerRemoveEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                    // Remove the filter JSON of the layer
                    var layer = event.getMapLayer();
                    this.analyse.removeFilterJson(layer.getId());
                }
            },
            'AfterChangeMapLayerStyleEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
            },
            /**
             * @method MapLayerEvent
             * @param {Oskari.mapframework.event.common.MapLayerEvent} event
             */
            'MapLayerEvent': function (event) {
                this._afterMapLayerEvent(event);
            },
            /**
             * @method userinterface.ExtensionUpdatedEvent
             */
            'userinterface.ExtensionUpdatedEvent': function (event) {

                var me = this;

                if (event.getExtension().getName() !== me.getName()) {
                    // not me -> do nothing
                    return;
                }

                var isOpen = event.getViewState() !== "close";

                me.displayContent(isOpen);

            }
        },
        /**
         * @method stop
         * Implements BundleInstance protocol stop method
         */
        "stop": function () {
            var me = this,
                sandbox = me.sandbox(),
                p;
            if (me.analyse) {
                me.analyse.destroy();
                me.analyse = undefined;
            }
            for (p in me.eventHandlers) {
                if (me.eventHandlers.hasOwnProperty(p)) {
                    sandbox.unregisterFromEventByName(me, p);
                }
            }

            sandbox.removeRequestHandler('analyse.AnalyseRequest', me.analyseHandler);
            me.analyseHandler = null;

            var request = sandbox.getRequestBuilder('userinterface.RemoveExtensionRequest')(me);
            sandbox.request(me, request);

            me.sandbox.unregisterStateful(me.mediator.bundleId);
            me.sandbox.unregister(me);
            me.started = false;
        },
        /**
         * @method startExtension
         * implements Oskari.userinterface.Extension protocol startExtension method
         * Creates a flyout
         * Oskari.analysis.bundle.analyse.Flyout
         */
        startExtension: function () {
            this.plugins['Oskari.userinterface.Flyout'] = Oskari.clazz.create('Oskari.analysis.bundle.analyse.Flyout', this);
            this.plugins['Oskari.userinterface.Tile'] = Oskari.clazz.create('Oskari.analysis.bundle.analyse.Tile', this);
        },
        /**
         * @method stopExtension
         * implements Oskari.userinterface.Extension protocol stopExtension method
         * Clears references to flyout and tile
         */
        stopExtension: function () {
            this.plugins['Oskari.userinterface.Flyout'] = null;
            this.plugins['Oskari.userinterface.Tile'] = null;
        },
        /**
         * @method getPlugins
         * implements Oskari.userinterface.Extension protocol getPlugins method
         * @return {Object} references to flyout and tile
         */
        getPlugins: function () {
            return this.plugins;
        },
        /**
         * @method getTitle
         * @return {String} localized text for the title of the component
         */
        getTitle: function () {
            return this.getLocalization('title');
        },
        /**
         * @method getDescription
         * @return {String} localized text for the description of the component
         */
        getDescription: function () {
            return this.getLocalization('desc');
        },
        /**
         * @method _createUi
         * @private
         * (re)creates the UI for "analyse" functionality
         */
        _createUi: function () {
            var me = this;
            this.plugins['Oskari.userinterface.Flyout'].createUi();
            this.plugins['Oskari.userinterface.Tile'].refresh();
        },
        /**
         * @method setAnalyseMode
         * Starts analyse mode
         *
         * @param {Boolean} blnEnabled
         */
        setAnalyseMode: function (blnEnabled) {
            var me = this,
                map = jQuery('#contentMap'),
                tools = jQuery('#maptools');

            if (blnEnabled) {

                // Hide flyout, it's not needed...
                jQuery(me.plugins['Oskari.userinterface.Flyout'].container).parent().parent().hide();
                /* Why would we close analyse here?
                // me.sandbox.postRequestByName('userinterface.UpdateExtensionRequest', [undefined, 'close']);
                var request = me.sandbox.getRequestBuilder('userinterface.UpdateExtensionRequest')(me, 'close', me.getName());
                me.sandbox.request(me.getName(), request);*/

                // proceed with analyse view
                if (!this.analyse) {
                    this.analyse = Oskari.clazz.create('Oskari.analysis.bundle.analyse.view.StartAnalyse', this, this.getLocalization('AnalyseView'));
                    this.analyse.render(map);
                } else {
                    // Update data UI
                    this.analyse.refreshAnalyseData();
                    this.analyse.refreshExtraParameters();
                }
                if (this.state) {
                    this.analyse.setState(this.state);
                }
                this.analyse.show();
                this.analyse.setEnabled(true);

            } else {
                if (this.analyse) {
                    // Reset tile state
                    var request = me.sandbox.getRequestBuilder('userinterface.UpdateExtensionRequest')(me, 'close', me.getName());
                    me.sandbox.request(me.getName(), request);
                    this.analyse.setEnabled(false);
                    this.analyse.hide();
                }
            }
        },
        displayContent: function (isOpen) {
            if (isOpen) {
                this.plugins['Oskari.userinterface.Flyout'].refresh();
            }
        },

        /**
         * @method setState
         * Sets the bundle state
         * bundle documentation for details.
         * @param {Object} state bundle state as JSON
         */
        setState: function (state) {
            this.state = state;
        },
        /**
         * @method getState
         * Returns bundle state as JSON. State is bundle specific, check the
         * bundle documentation for details.
         * @return {Object}
         */
        getState: function () {
            var state = this.state || {};

            if (this.analyse) {
                state = this.analyse.getState();
            }

            return state;
        },

        /**
         * @method showMessage
         * Shows user a message with ok button
         * @param {String} title popup title
         * @param {String} message popup message
         */
        showMessage: function (title, message) {
            var dialog = Oskari.clazz.create('Oskari.userinterface.component.Popup');
            dialog.show(title, message);
            dialog.fadeout(5000);
        },

        _afterMapLayerEvent: function (event) {
            var layerId = event.getLayerId(),
                loc = this.getLocalization('AnalyseView');
            // Let's show the user a dialog when the new analysislayer gets added to the map.
            if (event.getOperation() === 'add') {
                var layer = this.mapLayerService.findMapLayer(layerId);

                if (layer && layer.isLayerOfType('ANALYSIS')) {
                     this.showMessage(
                    loc.success.layerAdded.title,
                    loc.success.layerAdded.message.replace(/\{layer\}/, layer.getName())
                );
                }
            }
            // maplayers changed so update the tab content in personaldata
            this.personalDataTab.update();
        }
    }, {
        /**
         * @property {String[]} protocol
         * @static
         */
        "protocol": ["Oskari.bundle.BundleInstance", 'Oskari.mapframework.module.Module', 'Oskari.userinterface.Extension', 'Oskari.userinterface.Stateful']
    });<commit_msg>[AH-1100] analysis info fix<commit_after>/**
 * @class Oskari.analysis.bundle.analyse.AnalyseBundleInstance
 *
 * Main component and starting point for the analysis functionality. Analyse parameters dialog
 * is a layout down tool to configure analyse parameters .
 *
 * See Oskari.analysis.bundle.analyse.AnalyseBundle for bundle definition.
 *
 */
Oskari.clazz.define("Oskari.analysis.bundle.analyse.AnalyseBundleInstance",

    /**
     * @method create called automatically on construction
     * @static
     */

    function () {
        this.sandbox = undefined;
        this.started = false;
        this.plugins = {};
        this.localization = undefined;
        this.analyse = undefined;
        this.buttonGroup = 'viewtools';
        this.ignoreEvents = false;
        this.dialog = undefined;
        this.analyseHandler = undefined;
        this.analyseService = undefined;
        this.isMapStateChanged = true;
        this.state = undefined;
        this.conf = {};
        this.personalDataTab = undefined;
    }, {
        /**
         * @static
         * @property __name
         */
        __name: 'Analyse',
        /**
         * @method getName
         * @return {String} the name for the component
         */
        "getName": function () {
            return this.__name;
        },
        /**
         * @method getSandbox
         * @return {Oskari.mapframework.sandbox.Sandbox}
         */
        getSandbox: function () {
            return this.sandbox;
        },
        /**
         * @method getLocalization
         * Returns JSON presentation of bundles localization data for current language.
         * If key-parameter is not given, returns the whole localization data.
         *
         * @param {String} key (optional) if given, returns the value for key
         * @return {String/Object} returns single localization string or
         *      JSON object for complete data depending on localization
         *      structure and if parameter key is given
         */
        getLocalization: function (key) {
            if (!this._localization) {
                this._localization = Oskari.getLocalization(this.getName());
            }
            if (key) {
                return this._localization[key];
            }
            return this._localization;
        },
        /**
         * @method start
         * Implements BundleInstance protocol start method
         */
        "start": function () {
            var me = this;

            if (me.started) {
                return;
            }

            me.started = true;
            var conf = this.conf,
                sandboxName = (conf ? conf.sandbox : null) || 'sandbox',
                sandbox = Oskari.getSandbox(sandboxName),
                p;

            me.sandbox = sandbox;

            this.localization = Oskari.getLocalization(this.getName());

            sandbox.register(me);
            for (p in me.eventHandlers) {
                if (me.eventHandlers.hasOwnProperty(p)) {
                    sandbox.registerForEventByName(me, p);
                }
            }

            // requesthandler
            this.analyseHandler = Oskari.clazz.create('Oskari.analysis.bundle.analyse.request.AnalyseRequestHandler', me);
            sandbox.addRequestHandler('analyse.AnalyseRequest', this.analyseHandler);

            this.analyseService = Oskari.clazz.create('Oskari.analysis.bundle.analyse.service.AnalyseService', me);
            sandbox.registerService(this.analyseService);

            this.mapLayerService = sandbox.getService('Oskari.mapframework.service.MapLayerService');

            //Let's extend UI
            var request = sandbox.getRequestBuilder('userinterface.AddExtensionRequest')(this);
            sandbox.request(this, request);

            // draw ui
            me._createUi();

            // Load analysis layers
            this.analyseService.loadAnalyseLayers();

            /* stateful */
            if (conf && conf.stateful === true) {
                sandbox.registerAsStateful(this.mediator.bundleId, this);
            }

            // Request tab to be added to personal data
            var tab = Oskari.clazz.create('Oskari.mapframework.bundle.analyse.view.PersonalDataTab', this, this.localization.personalDataTab);
            var reqBuilder = sandbox.getRequestBuilder('PersonalData.AddTabRequest');

            if (reqBuilder) {
                sandbox.request(this, reqBuilder(this.localization.personalDataTab.title, tab.getContent()));
            }
            this.personalDataTab = tab;
        },
        /**
         * @method init
         * Implements Module protocol init method - does nothing atm
         */
        "init": function () {
            return null;
        },
        /**
         * @method update
         * Implements BundleInstance protocol update method - does nothing atm
         */
        "update": function () {

        },
        /**
         * @method onEvent
         * Event is handled forwarded to correct #eventHandlers if found or discarded if not.
         * @param {Oskari.mapframework.event.Event} event a Oskari event object
         */
        onEvent: function (event) {
            var handler = this.eventHandlers[event.getName()];
            if (!handler) {
                return;
            }
            return handler.apply(this, [event]);
        },
        /**
         * @property {Object} eventHandlers
         * @static
         */
        eventHandlers: {
            'MapLayerVisibilityChangedEvent': function (event) {
                if (this.analyse && this.analyse.isEnabled && this.isMapStateChanged) {
                    this.isMapStateChanged = false;
                    this.getSandbox().printDebug("ANALYSE REFRESH");
                    this.analyse.refreshAnalyseData(true);
                }
            },
            'AfterMapMoveEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
                this.isMapStateChanged = true;
            },
            'AfterMapLayerAddEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
            },
            'AfterMapLayerRemoveEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                    // Remove the filter JSON of the layer
                    var layer = event.getMapLayer();
                    this.analyse.removeFilterJson(layer.getId());
                }
            },
            'AfterChangeMapLayerStyleEvent': function (event) {
                this.isMapStateChanged = true;
                if (this.analyse && this.analyse.isEnabled) {
                    this.analyse.refreshAnalyseData(false);
                }
            },
            /**
             * @method MapLayerEvent
             * @param {Oskari.mapframework.event.common.MapLayerEvent} event
             */
            'MapLayerEvent': function (event) {
                this._afterMapLayerEvent(event);
            },
            /**
             * @method userinterface.ExtensionUpdatedEvent
             */
            'userinterface.ExtensionUpdatedEvent': function (event) {

                var me = this;

                if (event.getExtension().getName() !== me.getName()) {
                    // not me -> do nothing
                    return;
                }

                var isOpen = event.getViewState() !== "close";

                me.displayContent(isOpen);

            }
        },
        /**
         * @method stop
         * Implements BundleInstance protocol stop method
         */
        "stop": function () {
            var me = this,
                sandbox = me.sandbox(),
                p;
            if (me.analyse) {
                me.analyse.destroy();
                me.analyse = undefined;
            }
            for (p in me.eventHandlers) {
                if (me.eventHandlers.hasOwnProperty(p)) {
                    sandbox.unregisterFromEventByName(me, p);
                }
            }

            sandbox.removeRequestHandler('analyse.AnalyseRequest', me.analyseHandler);
            me.analyseHandler = null;

            var request = sandbox.getRequestBuilder('userinterface.RemoveExtensionRequest')(me);
            sandbox.request(me, request);

            me.sandbox.unregisterStateful(me.mediator.bundleId);
            me.sandbox.unregister(me);
            me.started = false;
        },
        /**
         * @method startExtension
         * implements Oskari.userinterface.Extension protocol startExtension method
         * Creates a flyout
         * Oskari.analysis.bundle.analyse.Flyout
         */
        startExtension: function () {
            this.plugins['Oskari.userinterface.Flyout'] = Oskari.clazz.create('Oskari.analysis.bundle.analyse.Flyout', this);
            this.plugins['Oskari.userinterface.Tile'] = Oskari.clazz.create('Oskari.analysis.bundle.analyse.Tile', this);
        },
        /**
         * @method stopExtension
         * implements Oskari.userinterface.Extension protocol stopExtension method
         * Clears references to flyout and tile
         */
        stopExtension: function () {
            this.plugins['Oskari.userinterface.Flyout'] = null;
            this.plugins['Oskari.userinterface.Tile'] = null;
        },
        /**
         * @method getPlugins
         * implements Oskari.userinterface.Extension protocol getPlugins method
         * @return {Object} references to flyout and tile
         */
        getPlugins: function () {
            return this.plugins;
        },
        /**
         * @method getTitle
         * @return {String} localized text for the title of the component
         */
        getTitle: function () {
            return this.getLocalization('title');
        },
        /**
         * @method getDescription
         * @return {String} localized text for the description of the component
         */
        getDescription: function () {
            return this.getLocalization('desc');
        },
        /**
         * @method _createUi
         * @private
         * (re)creates the UI for "analyse" functionality
         */
        _createUi: function () {
            var me = this;
            this.plugins['Oskari.userinterface.Flyout'].createUi();
            this.plugins['Oskari.userinterface.Tile'].refresh();
        },
        /**
         * @method setAnalyseMode
         * Starts analyse mode
         *
         * @param {Boolean} blnEnabled
         */
        setAnalyseMode: function (blnEnabled) {
            var me = this,
                map = jQuery('#contentMap'),
                tools = jQuery('#maptools');

            if (blnEnabled) {

                // Hide flyout, it's not needed...
                jQuery(me.plugins['Oskari.userinterface.Flyout'].container).parent().parent().hide();
                /* Why would we close analyse here?
                // me.sandbox.postRequestByName('userinterface.UpdateExtensionRequest', [undefined, 'close']);
                var request = me.sandbox.getRequestBuilder('userinterface.UpdateExtensionRequest')(me, 'close', me.getName());
                me.sandbox.request(me.getName(), request);*/

                // proceed with analyse view
                if (!this.analyse) {
                    this.analyse = Oskari.clazz.create('Oskari.analysis.bundle.analyse.view.StartAnalyse', this, this.getLocalization('AnalyseView'));
                    this.analyse.render(map);
                } else {
                    // Update data UI
                    this.analyse.refreshAnalyseData();
                    this.analyse.refreshExtraParameters();
                }
                if (this.state) {
                    this.analyse.setState(this.state);
                }
                this.analyse.show();
                this.analyse.setEnabled(true);

                // Show info
                this.analyse.showInfos();

            } else {
                if (this.analyse) {
                    // Reset tile state
                    var request = me.sandbox.getRequestBuilder('userinterface.UpdateExtensionRequest')(me, 'close', me.getName());
                    me.sandbox.request(me.getName(), request);
                    this.analyse.setEnabled(false);
                    this.analyse.hide();
                }
            }
        },
        displayContent: function (isOpen) {
            if (isOpen) {
                this.plugins['Oskari.userinterface.Flyout'].refresh();
            }
        },

        /**
         * @method setState
         * Sets the bundle state
         * bundle documentation for details.
         * @param {Object} state bundle state as JSON
         */
        setState: function (state) {
            this.state = state;
        },
        /**
         * @method getState
         * Returns bundle state as JSON. State is bundle specific, check the
         * bundle documentation for details.
         * @return {Object}
         */
        getState: function () {
            var state = this.state || {};

            if (this.analyse) {
                state = this.analyse.getState();
            }

            return state;
        },

        /**
         * @method showMessage
         * Shows user a message with ok button
         * @param {String} title popup title
         * @param {String} message popup message
         */
        showMessage: function (title, message) {
            var dialog = Oskari.clazz.create('Oskari.userinterface.component.Popup');
            dialog.show(title, message);
            dialog.fadeout(5000);
        },

        _afterMapLayerEvent: function (event) {
            var layerId = event.getLayerId(),
                loc = this.getLocalization('AnalyseView');
            // Let's show the user a dialog when the new analysislayer gets added to the map.
            if (event.getOperation() === 'add') {
                var layer = this.mapLayerService.findMapLayer(layerId);

                if (layer && layer.isLayerOfType('ANALYSIS')) {
                     this.showMessage(
                    loc.success.layerAdded.title,
                    loc.success.layerAdded.message.replace(/\{layer\}/, layer.getName())
                );
                }
            }
            // maplayers changed so update the tab content in personaldata
            this.personalDataTab.update();
        }
    }, {
        /**
         * @property {String[]} protocol
         * @static
         */
        "protocol": ["Oskari.bundle.BundleInstance", 'Oskari.mapframework.module.Module', 'Oskari.userinterface.Extension', 'Oskari.userinterface.Stateful']
    });<|endoftext|>


<commit_before>
var phet = phet || {};
phet.tests = phet.tests || {};

// TODO:
// consider clearRect under transformed bounds. may be more optimal
// optimizations from http://www.html5rocks.com/en/tutorials/canvas/performance/

$(document).ready( function() {
    // the main div where all testing content is rendered
    var main = $('#main');
    var buttonRow = $('#buttonrow');

    // constants
    var activeClass = 'ui-btn-active';
    var boxSizeRatio = 0.75;
    var boxTotalSize = 200;

    // all of the individual test code and data is here
    var tests = [{
        testName: 'Boxes',
        testId: 'test-boxes',
        types: [{
            typeName: 'Easel 5',
            typeId: 'easel5',
            init: function( main ) {
                return phet.tests.easelVariableBox( main, 5 );
            }
        },{
            typeName: 'Custom 5',
            typeId: 'custom5',
            init: function( main ) {
                return phet.tests.customVariableBox( main, 5 );
            }
        },{
            typeName: 'Scene 5',
            typeId: 'scene5',
            init: function( main ) {
                return phet.tests.sceneVariableBox( main, 5 );
            }
        },{
            typeName: 'SVG 5',
            typeId: 'svg5',
            init: function( main ) {
                return phet.tests.svgVariableBox( main, 5 );
            }
        },{
            typeName: 'Easel 50',
            typeId: 'easel50',
            init: function( main ) {
                return phet.tests.easelVariableBox( main, 50 );
            }
        },{
            typeName: 'Custom 50',
            typeId: 'custom50',
            init: function( main ) {
                return phet.tests.customVariableBox( main, 50 );
            }
        },{
            typeName: 'Scene 50',
            typeId: 'scene50',
            init: function( main ) {
                return phet.tests.sceneVariableBox( main, 50 );
            }
        },{
            typeName: 'SVG 50',
            typeId: 'svg50',
            init: function( main ) {
                return phet.tests.svgVariableBox( main, 50 );
            }
        }]
    },{
        testName: 'Misc',
        testId: 'test-misc',
        types: [{
            typeName: '50x Canvas Creation',
            typeId: 'canvasCreation',
            init: function( main ) {
                return function( timeElapsed ) {
                    for( var i = 0; i < 50; i++ ) {
                        main.empty();

                        var canvas = document.createElement( 'canvas' );
                        canvas.width = main.width();
                        canvas.height = main.height();
                        main.append( canvas );

                        var context = phet.canvas.initCanvas( canvas );
                    }
                };
            }
        },{
            typeName: 'Text Bounds',
            typeId: 'boundsTest',
            init: function( main ) {
                return phet.tests.textBounds( main )
            }
        },{
            typeName: 'Winding', // pure black and lighter blue will appear if the fillRule property exists in the Canvas 2d context
            typeId: 'winding',
            init: function( main ) {
                var baseCanvas = document.createElement( 'canvas' );
                baseCanvas.id = 'base-canvas';
                baseCanvas.width = main.width();
                baseCanvas.height = main.height();
                main.append( baseCanvas );

                var context = phet.canvas.initCanvas( baseCanvas );

                var x = baseCanvas.width / 2;
                var y = baseCanvas.height / 2;

                context.fillStyle = '#666666';
                var canvasPadding = 30;
                context.fillRect( canvasPadding, canvasPadding, baseCanvas.width - 2 * canvasPadding, baseCanvas.height - 2 * canvasPadding );

                function drawPattern( callbackAfterClose ) {
                    context.beginPath();
                    context.arc( x + 50, y, 100, 0, 2 * Math.PI, true );
                    context.arc( x + 100, y, 25, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x - 50, y, 100, 2 * Math.PI, 0, false );
                    context.arc( x - 100, y, 25, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FFFF00' ); }

                    context.arc( x + 200, y, 100, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x - 200, y, 100, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x, y - 100, 100, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x, y - 100, 50, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x, y + 100, 100, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x, y + 100, 50, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }
                }

                drawPattern();
                context.fillRule = 'nonzero';
                context.fillStyle = '#000000';
                context.fill();

                drawPattern();
                context.fillRule = 'evenodd';
                context.fillStyle = 'rgba( 0, 0, 255, 0.25 )';
                context.fill();

                drawPattern( function( style ) {
                    context.strokeStyle = style;
                    context.stroke();
                    context.beginPath();
                } );

                return function( timeElapsed ) {

                }
            }
        },{
            typeName: 'Clip',
            typeId: 'clipTest',
            init: function( main ) {
                var baseCanvas = document.createElement( 'canvas' );
                baseCanvas.id = 'base-canvas';
                baseCanvas.width = main.width();
                baseCanvas.height = main.height();
                main.append( baseCanvas );

                var context = phet.canvas.initCanvas( baseCanvas );

                var x = baseCanvas.width / 2;
                var y = baseCanvas.height / 2;

                var timer = { total: 0 };

                return function( timeElapsed ) {
                    timer.total += timeElapsed;

                    context.save();

                    // context.resetTransform(); // TODO: why is this not working?
                    context.setTransform( 1, 0, 0, 1, 0, 0 );
                    context.clearRect( 0, 0, baseCanvas.width, baseCanvas.height );

                    context.setTransform( 1, 0, 0, 1, x - 100, y - 100 );

                    context.beginPath();
                    context.rect( 90, 0, 20, 200 );
                    context.clip();

                    context.transform( 1, 0, 0, 1, Math.sin( timer.total ) * 100, 0 );

                    context.beginPath();
                    context.arc( 200, 200, 200, 0, 2 * Math.PI, true );
                    context.clip();
                    context.beginPath();
                    context.arc( 0, 0, 200, 0, 2 * Math.PI, true );
                    context.clip();
                    context.beginPath();
                    context.rect( 0, 0, 200, 200 );
                    context.fillStyle = '#000000';
                    context.fill();

                    context.restore();
                };
            }
        }]
    },{
        testName: 'Layers',
        testId: 'test-layers',
        types: [{
            typeName: 'Scene With',
            typeId: 'sceneWith',
            init: function( main ) {
                return phet.tests.sceneLayeringTests( main, true );
            }
        },{
            typeName: 'Scene Without',
            typeId: 'sceneWithout',
            init: function( main ) {
                return phet.tests.sceneLayeringTests( main, false );
            }
        },{
            typeName: 'Easel',
            typeId: 'easel',
            init: function( main ) {
                return phet.tests.easelLayeringTests( main, false );
            }
        },{
            typeName: 'Custom',
            typeId: 'custom',
            init: function( main ) {
                return phet.tests.customLayeringTests( main, false );
            }
        }]
    },{
        testName: 'Placebo',
        testId: 'test-placebo',
        types: [{
            typeName: 'FPS "Control": empty step function',
            typeId: 'nothingDone',
            init: function( main ) {
                return function( timeElapsed ) {};
            }
        }]
    }];

    function buildEaselStage() {
        var canvas = document.createElement( 'canvas' );
        canvas.id = 'easel-canvas';
        canvas.width = main.width();
        canvas.height = main.height();
        main.append( canvas );

        return new createjs.Stage( canvas );
    }

    function buildBaseContext() {
        var baseCanvas = document.createElement( 'canvas' );
        baseCanvas.id = 'base-canvas';
        baseCanvas.width = main.width();
        baseCanvas.height = main.height();
        main.append( baseCanvas );

        return phet.canvas.initCanvas( baseCanvas );
    }

    // var currentTest = tests[0];
    // var currentType = tests[0].types[0];
    var currentTest = tests[2];
    var currentType = tests[2].types[0];

    function createButtonGroup() {
        var result = $( document.createElement( 'span' ) );
        result.attr( 'data-role', 'controlgroup' );
        result.attr( 'data-type', 'horizontal' );
        result.attr( 'data-mini', 'true' );
        result.css( 'padding-right', '20px' );
        return result;
    }

    function createButton( title ) {
        var result = $( document.createElement( 'a' ) );
        result.attr( 'data-role', 'button' );
        result.attr( 'href', '#' );
        result.text( title );
        return result;
    }

    function updateHighlights() {
        // update the button highlights
        _.each( tests, function( otherTest ) {
            if( otherTest == currentTest ) {
                // select this button as active
                $( '#' + otherTest.testId ).addClass( activeClass );

                // display its types
                $( '#types-' + otherTest.testId ).css( 'display', 'inline' );

                // set the type selected
                _.each( otherTest.types, function( otherType ) {
                    if( otherType == currentType ) {
                        $( '#' + otherTest.testId + '-' + otherType.typeId ).addClass( activeClass );
                    } else {
                        $( '#' + otherTest.testId + '-' + otherType.typeId ).removeClass( activeClass );
                    }
                } );
            } else {
                // and set others as inactive
                $( '#' + otherTest.testId ).removeClass( activeClass );

                // hide their types
                $( '#types-' + otherTest.testId ).css( 'display', 'none' );
            }
        } );
    }

    // first group of buttons, one for each major test
    var testButtons = createButtonGroup();
    testButtons.attr( 'id', 'test-buttons' );
    buttonRow.append( testButtons );

    _.each( tests, function( test ) {
        // make a button for each test
        var testButton = createButton( test.testName );
        testButton.attr( 'id', test.testId );
        testButtons.append( testButton );

        testButton.on( 'click', function( event, ui ) {
            currentTest = test;
            currentType = test.types[0];

            updateHighlights();
            changeTest();
        } );

        // group of buttons to the right for each test
        var typeButtons = createButtonGroup();
        typeButtons.attr( 'id', 'types-' + test.testId );
        buttonRow.append( typeButtons );

        _.each( test.types, function( type ) {
            // add a type button for each type
            var typeButton = createButton( type.typeName );
            typeButton.attr( 'id', test.testId + '-' + type.typeId );
            typeButtons.append( typeButton );

            typeButton.on( 'click', function( event, ui ) {
                currentType = type;

                updateHighlights();
                changeTest();
            } );
        } );

        // don't show the type buttons at the start
        typeButtons.css( 'display', 'none' );
    } );

    buttonRow.trigger('create');

    updateHighlights();

    // closure used over this for running steps
    var step = function( timeElapsed ) {

    };

    // called whenever the test is supposed to change
    function changeTest() {
        // clear the main area
        main.empty();

        // run the initialization and change the step function
        step = currentType.init( main );
    }

    // set up averaging FPS meter and calling of the step() function
    (function(){
        // records the last #fpsCount timestamps, and displays the average FPS over that time
        var fpsReadout = $('#fps-readout');
        var fpsCount = 20;
        var fpsIndex = 0;
        // stuffs timestamps in a round-robin fashion into here
        var timeEntries = _.map( _.range( fpsCount ), function( a ) { return 0; } );
        function updateFps() {
            var timestamp = Date.now();
            timeEntries[ fpsIndex ] = timestamp;
            fpsIndex = ( fpsIndex + 1 ) % fpsCount;
            var timeChange = ( timestamp - timeEntries[ fpsIndex ] ) / 1000;
            var fps = fpsCount / timeChange;
            if( fps < 1 ) {
                fpsReadout.text( "-" );
            } else {
                fpsReadout.text( fps.toFixed( 1 ) );
            }
        }

        var lastTime = 0;
        var timeElapsed = 0;

        // setting up regular calls for step()
        function tick() {
            window.requestAnimationFrame( tick, main[0] );
            var timeNow = new Date().getTime();
            if ( lastTime != 0 ) {
                timeElapsed = (timeNow - lastTime) / 1000.0;
            }
            lastTime = timeNow;

            if( timeElapsed != 0 ) {
                step( timeElapsed );
            }
            updateFps();
        }
        window.requestAnimationFrame( tick, main[0] );
    })();

    // handle window resizing
    var resizer = function () {
        main.width( window.innerWidth );
        main.height( window.innerHeight );
        changeTest();
    };
    $( window ).resize( resizer );
    resizer();

} );
<commit_msg>Reset FPS meter on test change<commit_after>
var phet = phet || {};
phet.tests = phet.tests || {};

// TODO:
// consider clearRect under transformed bounds. may be more optimal
// optimizations from http://www.html5rocks.com/en/tutorials/canvas/performance/

$(document).ready( function() {
    // the main div where all testing content is rendered
    var main = $('#main');
    var buttonRow = $('#buttonrow');

    // constants
    var activeClass = 'ui-btn-active';
    var boxSizeRatio = 0.75;
    var boxTotalSize = 200;

    // all of the individual test code and data is here
    var tests = [{
        testName: 'Boxes',
        testId: 'test-boxes',
        types: [{
            typeName: 'Easel 5',
            typeId: 'easel5',
            init: function( main ) {
                return phet.tests.easelVariableBox( main, 5 );
            }
        },{
            typeName: 'Custom 5',
            typeId: 'custom5',
            init: function( main ) {
                return phet.tests.customVariableBox( main, 5 );
            }
        },{
            typeName: 'Scene 5',
            typeId: 'scene5',
            init: function( main ) {
                return phet.tests.sceneVariableBox( main, 5 );
            }
        },{
            typeName: 'SVG 5',
            typeId: 'svg5',
            init: function( main ) {
                return phet.tests.svgVariableBox( main, 5 );
            }
        },{
            typeName: 'Easel 50',
            typeId: 'easel50',
            init: function( main ) {
                return phet.tests.easelVariableBox( main, 50 );
            }
        },{
            typeName: 'Custom 50',
            typeId: 'custom50',
            init: function( main ) {
                return phet.tests.customVariableBox( main, 50 );
            }
        },{
            typeName: 'Scene 50',
            typeId: 'scene50',
            init: function( main ) {
                return phet.tests.sceneVariableBox( main, 50 );
            }
        },{
            typeName: 'SVG 50',
            typeId: 'svg50',
            init: function( main ) {
                return phet.tests.svgVariableBox( main, 50 );
            }
        }]
    },{
        testName: 'Misc',
        testId: 'test-misc',
        types: [{
            typeName: '50x Canvas Creation',
            typeId: 'canvasCreation',
            init: function( main ) {
                return function( timeElapsed ) {
                    for( var i = 0; i < 50; i++ ) {
                        main.empty();

                        var canvas = document.createElement( 'canvas' );
                        canvas.width = main.width();
                        canvas.height = main.height();
                        main.append( canvas );

                        var context = phet.canvas.initCanvas( canvas );
                    }
                };
            }
        },{
            typeName: 'Text Bounds',
            typeId: 'boundsTest',
            init: function( main ) {
                return phet.tests.textBounds( main )
            }
        },{
            typeName: 'Winding', // pure black and lighter blue will appear if the fillRule property exists in the Canvas 2d context
            typeId: 'winding',
            init: function( main ) {
                var baseCanvas = document.createElement( 'canvas' );
                baseCanvas.id = 'base-canvas';
                baseCanvas.width = main.width();
                baseCanvas.height = main.height();
                main.append( baseCanvas );

                var context = phet.canvas.initCanvas( baseCanvas );

                var x = baseCanvas.width / 2;
                var y = baseCanvas.height / 2;

                context.fillStyle = '#666666';
                var canvasPadding = 30;
                context.fillRect( canvasPadding, canvasPadding, baseCanvas.width - 2 * canvasPadding, baseCanvas.height - 2 * canvasPadding );

                function drawPattern( callbackAfterClose ) {
                    context.beginPath();
                    context.arc( x + 50, y, 100, 0, 2 * Math.PI, true );
                    context.arc( x + 100, y, 25, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x - 50, y, 100, 2 * Math.PI, 0, false );
                    context.arc( x - 100, y, 25, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FFFF00' ); }

                    context.arc( x + 200, y, 100, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x - 200, y, 100, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x, y - 100, 100, 0, 2 * Math.PI, true );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#FF0000' ); }

                    context.arc( x, y - 100, 50, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x, y + 100, 100, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }

                    context.arc( x, y + 100, 50, 2 * Math.PI, 0, false );
                    context.closePath();
                    if( callbackAfterClose ) { callbackAfterClose( '#00FF00' ); }
                }

                drawPattern();
                context.fillRule = 'nonzero';
                context.fillStyle = '#000000';
                context.fill();

                drawPattern();
                context.fillRule = 'evenodd';
                context.fillStyle = 'rgba( 0, 0, 255, 0.25 )';
                context.fill();

                drawPattern( function( style ) {
                    context.strokeStyle = style;
                    context.stroke();
                    context.beginPath();
                } );

                return function( timeElapsed ) {

                }
            }
        },{
            typeName: 'Clip',
            typeId: 'clipTest',
            init: function( main ) {
                var baseCanvas = document.createElement( 'canvas' );
                baseCanvas.id = 'base-canvas';
                baseCanvas.width = main.width();
                baseCanvas.height = main.height();
                main.append( baseCanvas );

                var context = phet.canvas.initCanvas( baseCanvas );

                var x = baseCanvas.width / 2;
                var y = baseCanvas.height / 2;

                var timer = { total: 0 };

                return function( timeElapsed ) {
                    timer.total += timeElapsed;

                    context.save();

                    // context.resetTransform(); // TODO: why is this not working?
                    context.setTransform( 1, 0, 0, 1, 0, 0 );
                    context.clearRect( 0, 0, baseCanvas.width, baseCanvas.height );

                    context.setTransform( 1, 0, 0, 1, x - 100, y - 100 );

                    context.beginPath();
                    context.rect( 90, 0, 20, 200 );
                    context.clip();

                    context.transform( 1, 0, 0, 1, Math.sin( timer.total ) * 100, 0 );

                    context.beginPath();
                    context.arc( 200, 200, 200, 0, 2 * Math.PI, true );
                    context.clip();
                    context.beginPath();
                    context.arc( 0, 0, 200, 0, 2 * Math.PI, true );
                    context.clip();
                    context.beginPath();
                    context.rect( 0, 0, 200, 200 );
                    context.fillStyle = '#000000';
                    context.fill();

                    context.restore();
                };
            }
        }]
    },{
        testName: 'Layers',
        testId: 'test-layers',
        types: [{
            typeName: 'Scene With',
            typeId: 'sceneWith',
            init: function( main ) {
                return phet.tests.sceneLayeringTests( main, true );
            }
        },{
            typeName: 'Scene Without',
            typeId: 'sceneWithout',
            init: function( main ) {
                return phet.tests.sceneLayeringTests( main, false );
            }
        },{
            typeName: 'Easel',
            typeId: 'easel',
            init: function( main ) {
                return phet.tests.easelLayeringTests( main, false );
            }
        },{
            typeName: 'Custom',
            typeId: 'custom',
            init: function( main ) {
                return phet.tests.customLayeringTests( main, false );
            }
        }]
    },{
        testName: 'Placebo',
        testId: 'test-placebo',
        types: [{
            typeName: 'FPS "Control": empty step function',
            typeId: 'nothingDone',
            init: function( main ) {
                return function( timeElapsed ) {};
            }
        }]
    }];

    function buildEaselStage() {
        var canvas = document.createElement( 'canvas' );
        canvas.id = 'easel-canvas';
        canvas.width = main.width();
        canvas.height = main.height();
        main.append( canvas );

        return new createjs.Stage( canvas );
    }

    function buildBaseContext() {
        var baseCanvas = document.createElement( 'canvas' );
        baseCanvas.id = 'base-canvas';
        baseCanvas.width = main.width();
        baseCanvas.height = main.height();
        main.append( baseCanvas );

        return phet.canvas.initCanvas( baseCanvas );
    }

    // var currentTest = tests[0];
    // var currentType = tests[0].types[0];
    var currentTest = tests[2];
    var currentType = tests[2].types[0];

    function createButtonGroup() {
        var result = $( document.createElement( 'span' ) );
        result.attr( 'data-role', 'controlgroup' );
        result.attr( 'data-type', 'horizontal' );
        result.attr( 'data-mini', 'true' );
        result.css( 'padding-right', '20px' );
        return result;
    }

    function createButton( title ) {
        var result = $( document.createElement( 'a' ) );
        result.attr( 'data-role', 'button' );
        result.attr( 'href', '#' );
        result.text( title );
        return result;
    }

    function updateHighlights() {
        // update the button highlights
        _.each( tests, function( otherTest ) {
            if( otherTest == currentTest ) {
                // select this button as active
                $( '#' + otherTest.testId ).addClass( activeClass );

                // display its types
                $( '#types-' + otherTest.testId ).css( 'display', 'inline' );

                // set the type selected
                _.each( otherTest.types, function( otherType ) {
                    if( otherType == currentType ) {
                        $( '#' + otherTest.testId + '-' + otherType.typeId ).addClass( activeClass );
                    } else {
                        $( '#' + otherTest.testId + '-' + otherType.typeId ).removeClass( activeClass );
                    }
                } );
            } else {
                // and set others as inactive
                $( '#' + otherTest.testId ).removeClass( activeClass );

                // hide their types
                $( '#types-' + otherTest.testId ).css( 'display', 'none' );
            }
        } );
    }

    // first group of buttons, one for each major test
    var testButtons = createButtonGroup();
    testButtons.attr( 'id', 'test-buttons' );
    buttonRow.append( testButtons );

    _.each( tests, function( test ) {
        // make a button for each test
        var testButton = createButton( test.testName );
        testButton.attr( 'id', test.testId );
        testButtons.append( testButton );

        testButton.on( 'click', function( event, ui ) {
            currentTest = test;
            currentType = test.types[0];

            updateHighlights();
            changeTest();
        } );

        // group of buttons to the right for each test
        var typeButtons = createButtonGroup();
        typeButtons.attr( 'id', 'types-' + test.testId );
        buttonRow.append( typeButtons );

        _.each( test.types, function( type ) {
            // add a type button for each type
            var typeButton = createButton( type.typeName );
            typeButton.attr( 'id', test.testId + '-' + type.typeId );
            typeButtons.append( typeButton );

            typeButton.on( 'click', function( event, ui ) {
                currentType = type;

                updateHighlights();
                changeTest();
            } );
        } );

        // don't show the type buttons at the start
        typeButtons.css( 'display', 'none' );
    } );

    buttonRow.trigger('create');

    updateHighlights();

    // closure used over this for running steps
    var step = function( timeElapsed ) {

    };

    // called whenever the test is supposed to change
    function changeTest() {
        // clear the main area
        main.empty();

        // run the initialization and change the step function
        step = currentType.init( main );
    }

    // set up averaging FPS meter and calling of the step() function
    (function(){
        // records the last #fpsCount timestamps, and displays the average FPS over that time
        var fpsReadout = $('#fps-readout');
        var fpsCount = 20;
        var fpsIndex = 0;
        // stuffs timestamps in a round-robin fashion into here
        var timeEntries = _.map( _.range( fpsCount ), function( a ) { return 0; } );

        // stored, so we can reset the FPS meter on a change
        var lastType = null;

        function updateFps() {
            // wipe the meter until we have all fresh readings whenever a test's type changes
            if( lastType != currentType ) {
                timeEntries = _.map( timeEntries, function( a ) { return 0; } );
                lastType = currentType;
            }

            var timestamp = Date.now();
            timeEntries[ fpsIndex ] = timestamp;
            fpsIndex = ( fpsIndex + 1 ) % fpsCount;
            var timeChange = ( timestamp - timeEntries[ fpsIndex ] ) / 1000;
            var fps = fpsCount / timeChange;
            if( fps < 1 ) {
                fpsReadout.text( "-" );
            } else {
                fpsReadout.text( fps.toFixed( 1 ) );
            }
        }

        var lastTime = 0;
        var timeElapsed = 0;

        // setting up regular calls for step()
        function tick() {
            window.requestAnimationFrame( tick, main[0] );
            var timeNow = new Date().getTime();
            if ( lastTime != 0 ) {
                timeElapsed = (timeNow - lastTime) / 1000.0;
            }
            lastTime = timeNow;

            if( timeElapsed != 0 ) {
                step( timeElapsed );
            }
            updateFps();
        }
        window.requestAnimationFrame( tick, main[0] );
    })();

    // handle window resizing
    var resizer = function () {
        main.width( window.innerWidth );
        main.height( window.innerHeight );
        changeTest();
    };
    $( window ).resize( resizer );
    resizer();

} );
<|endoftext|>


<commit_before>window.emlrip                               = window.emlrip || {};

(function(emlrip, $, ko, undefined) {
    'use strict';

    // This is the emlrip app constructor.  This file sets up the "run"
    // function to initialize the app - including all viewmodels and models

    function App() {

        this.run                            = function() {

            var fileDropVM                  = new emlrip.FileDropVM();

            ko.applyBindings(fileDropVM, $('#fileDropRegion')[0]);
        }
    }
    emlrip.App                              = App;

}) (window.emlrip = window.emlrip || {}, jQuery, ko);<commit_msg>Update eml-app.js<commit_after>window.emlrip                               = window.emlrip || {};

(function(emlrip, $, ko, undefined) {
    'use strict';

    // This is the emlrip app constructor.  This file sets up the "run"
    // function to initialize the app - including all viewmodels and models

    function App() {

        this.run                            = function() {

            var fileDropVM                  = new emlrip.FileDropVM();

    //        ko.applyBindings(fileDropVM, $('#fileDropRegion')[0]);
            ko.applyBindings(fileDropVM, $('#mainContainer')[0]);
        }
    }
    emlrip.App                              = App;

}) (window.emlrip = window.emlrip || {}, jQuery, ko);
<|endoftext|>


<commit_before><commit_msg>Added service for sending daily log files<commit_after><|endoftext|>


<commit_before>module.exports = function () {
 exports.setEventListener = exports.setDestroyEventListener = function (callback) {
  cordova.exec (callback, undefined, "OnDestroyPlugin", "setEventListener", [])
 }
 exports.addOnPauseEventListener = function (callback) {
  document.addEventListener("pause", callback, false)
 }
 return exports
} ()
<commit_msg>Update ondestroyplugin.js<commit_after>module.exports = function () {
 exports.setEventListener = exports.setDestroyEventListener = function (callback) {
  cordova.exec (callback, undefined, "OnDestroyPlugin", "setEventListener", [])
 }
 exports.addOnPauseEventListener = function (callback) {
  document.addEventListener("deviceready", function () {
   document.addEventListener("pause", callback, false)
  })
 }
 return exports
} ()
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Actor LLC. <https://actor.im>
 */

import _ from 'lodash';

import React from 'react';

import memoize from 'memoizee';

import { Path } from 'constants/ActorAppConstants';
import ActorClient from 'utils/ActorClient';

import { emoji } from 'utils/EmojiUtils';

const processText = (text) => {
  const markedText = ActorClient.renderMarkdown(text);
  const emojifiedText = emoji.replace_unified(markedText);
  return emojifiedText;
};

const memoizedProcessText = memoize(processText, {
  length: 1000,
  maxAge: 60 * 60 * 1000,
  max: 10000
});

class Text extends React.Component {
  static propTypes = {
    content: React.PropTypes.object.isRequired,
    className: React.PropTypes.string
  };

  constructor(props) {
    super(props);
  }

  render() {
    const { content, className } = this.props;

    const renderedContent = (

    );

    return renderedContent;
  }
}

export default Text;
<commit_msg>fix(web): replace emoji short names before render received messages<commit_after>/*
 * Copyright (C) 2015 Actor LLC. <https://actor.im>
 */

import React, { Component } from 'react';
import memoize from 'memoizee';
import ActorClient from 'utils/ActorClient';

import { Path } from 'constants/ActorAppConstants';
import { emoji } from 'utils/EmojiUtils';

const processText = (text) => {
  const markedText = ActorClient.renderMarkdown(text);
  const emojifiedText = emoji.replace_unified(emoji.replace_colons(markedText));
  return emojifiedText;
};

const memoizedProcessText = memoize(processText, {
  length: 1000,
  maxAge: 60 * 60 * 1000,
  max: 10000
});

export default class Text extends Component {
  static propTypes = {
    content: React.PropTypes.object.isRequired,
    className: React.PropTypes.string
  };

  constructor(props) {
    super(props);
  }

  render() {
    const { content, className } = this.props;

    return (

    );
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         denic WhoIs
// @namespace    https://github.com/psuet/usefulScripts/
// @version      1.0.0
// @description  Stops anoying questions
// @updateURL    https://raw.githubusercontent.com/psuet/usefulScripts/master/Denic.user.js
// @downloadURL  https://raw.githubusercontent.com/psuet/usefulScripts/master/Denic.user.js
// @author       Paul Sütterlin
// @match        https://www.denic.de/webwhois-web20/de
// @icon         https://www.denic.de/favicon.ico
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    document.getElementById("justification").innerHTML="Blah Blah Blah";
    document.getElementById("reason2").checked = true;
})();
<commit_msg>Denic changed its WHOIS Page once again :(<commit_after><|endoftext|>


<commit_before>//TODO: Change so date is also updated.   Combine all date and time into one function
//TODO: Make so the message is only visible for one second

function updateDisplay() {
          $.ajax({
              method: "GET",
              url: "message.txt",
              cache: false
          })
           .done(function( html ){
              $('#Message').html(html);});

          $.ajax({
              method: "GET",
              url: "users.txt",
              cache: false
          })
           .done(function( html ){
              $('#Users').html(html);});
  }

  $(document).ready(function() {
  // Create two variable with the names of the months and days in an array
  var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
  var dayNames= ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]

  // Create a newDate() object
  var newDate = new Date();
  // Extract the current date from Date object
  newDate.setDate(newDate.getDate());
  // Output the day, date, month and year
  $('#Date').html(dayNames[newDate.getDay()] + " " + newDate.getDate() + ' ' + monthNames[newDate.getMonth()] + ' ' + newDate.getFullYear());

  setInterval( function() {
      // Create a newDate() object and extract the seconds of the current time
      var seconds = new Date().getSeconds();
      // Add a leading zero to seconds value
      $("#sec").html(( seconds < 10 ? "0" : "" ) + seconds);
      },1000);

  setInterval( function() {
      // Create a newDate() object and extract the minutes of the current time
      var minutes = new Date().getMinutes();
      // Add a leading zero to the minutes value
      $("#min").html(( minutes < 10 ? "0" : "" ) + minutes);
      },1000);

  setInterval( function() {
      // Create a newDate() object and extract the hours of the current time
      var hours = new Date().getHours();
      // Add a leading zero to the hours value
      ampm = (hours > 12) ? " pm" : " am";
      hours = (hours > 12) ? hours - 12 : hours;
      $("#hours").html(( hours < 10 ? "0" : "" ) + hours);
      $("#ampm").html(ampm);
      }, 1000);

  setInterval(function(){updateDisplay()}, 250);

  });
<commit_msg>Cleaned up duplication<commit_after>//TODO: Change so date is also updated.   Combine all date and time into one function
//TODO: Make so the message is only visible for one second

  function updateDisplay() {
          $.ajax({
              method: "GET",
              url: "message.txt",
              cache: false
          })
           .done(function( html ){
              $('#Message').html(html);});

          $.ajax({
              method: "GET",
              url: "users.txt",
              cache: false
          })
           .done(function( html ){
              $('#Users').html(html);});
  }

  function updateDateTime(){
	  var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
	  var dayNames= ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]

	  // Create a newDate() object
	  var newDate = new Date();
  	  $('#Date').html(dayNames[newDate.getDay()] + " " + newDate.getDate() + ' ' + monthNames[newDate.getMonth()] + ' ' + newDate.getFullYear());

      var seconds = newDate.getSeconds();
      // Add a leading zero to seconds value
      $("#sec").html(( seconds < 10 ? "0" : "" ) + seconds);

      var minutes = newDate.getMinutes();
      // Add a leading zero to the minutes value
      $("#min").html(( minutes < 10 ? "0" : "" ) + minutes);

      var hours = newDate.getHours();
      // Add a leading zero to the hours value
      ampm = (hours > 12) ? " pm" : " am";
      hours = (hours > 12) ? hours - 12 : hours;
      $("#hours").html(( hours < 10 ? "0" : "" ) + hours);
      $("#ampm").html(ampm);
  }

  $(document).ready(function() {
	  updateDateTime();
	  updateDisplay();

  	  setInterval(function(){updateDateTime()}, 1000);
      setInterval(function(){updateDisplay()}, 250);
  });
<|endoftext|>


<commit_before>$(document).ready(function() {
	if (reorder = $('a.reorder')) {
		reorder.click(function(event) {
			$(this).parent().toggleClass('active');
			TableTree.toggle($('table.list'), this.id.replace('reorder_', ''), this.href);
			event.preventDefault();
			return false;
		})
	}
});<commit_msg>simplify table_tree js.<commit_after>$(function() {
	$('a.reorder').click(function(event) {
    event.preventDefault();
    $(this).parent().toggleClass('active');
    TableTree.toggle($('table.list'), this.id.replace('reorder_', ''), this.href);
  });
});
<|endoftext|>