<commit_before>// (function(context){

var Is = require('neuro-is').Is,
    Silence = require('../mixins/silence').Silence,
    Connector = require('../mixins/connector').Connector,
    Butler = require('../mixins/butler').Butler,
    signalFactory = require('../utils/signalFactory');

var cloneVal = function(val){
    switch(typeOf(val)){
        // Dereference the new val if it's an Array
        case 'array': val = val.slice(); break;
        // Or an Object but not an instance of Class
        case 'object':
            if (!val.$constructor || (val.$constructor && !instanceOf(val.$constructor, Class))){
                val = Object.clone(val);
            }
            break;
    }

    return val;
};

var curryGetter = function(type){
    /**
     * isPrevious is a parameter to be passed into custom getter accessors.
     * This will allow the getter to know whether it should be retrieving from _data or _previousData.
     * @type {Boolean}
     */
    var isPrevious = type == '_previousData' || void 0;

    return function(prop){
        var accessor = this.getAccessor(prop, isPrevious ? 'getPrevious' : 'get'),
            // accessing = this.isAccessing(),
            accessorName = this._accessorName;

        /**
         * Prevent recursive get calls by checking if it's currently accessing
         * and if the accessor name is the same as the property arg. If all positive,
         * then return the value from _data/_previousData, otherwise return from
         * the accessor function. Fallback to returning from the _data/_previousData
         * if an accessor function does not exist.
         */
        if (accessor) {
            if (accessorName != prop) {
                return accessor();
            }
        }

        return this[type][prop];

        // return accessor && accessorName != prop ? accessor() : this[type][prop];
    }.overloadGetter();
};

var curryGetData = function(type){
    return function(){
        var props = this.keys(),
            obj = {};

        props.each(function(prop){
            // cloneVal will return a cloned of an Array or Object that is not a Class or the val itself
            obj[prop] = cloneVal(this[type](prop));
        }.bind(this));

        return obj;
    };
};

var Signals = new Class(
    signalFactory(
        ['change', 'destroy', 'reset'],
        {
            signalChangeProperty: function(prop, newVal, oldVal){
                !this.isSilent() && this.fireEvent('change:' + prop, [this, prop, newVal, oldVal]);
                return this;
            }
        }
    )
);

var Model = new Class({
    Implements: [Connector, Butler, Events, Options, Silence, Signals],

    primaryKey: undefined,

    _data: {},

    // _defaults: {},

    _changed: false,

    _changedProperties: {},

    _previousData: {},

    _setting: 0,

    options: {
        // onChange: function(){},
        // 'onChange:key': function(){},
        // onDestroy: function(){},
        // onReset: function(){},
        primaryKey: undefined,
        defaults: {}
    },

    initialize: function(data, options){
        if (instanceOf(data, this.constructor)) {
            return data;
        }

        this.setup(data, options);
    },

    setup: function(data, options){
        this.setOptions(options);

        this.primaryKey = this.options.primaryKey;

        this.setupAccessors();

        // properly set the defaults object
        // Object.merge(this._defaults, this.options.defaults);

        // Set the _data defaults silently because listeners shouldn't need to know that the defaults have been defined
        this.silence(function(){
            this.set(this.options.defaults);
        }.bind(this));

        // Just set the data instead of Object merging. This will skip cloning Class instances.
        if (data) { this.set(data); }

        return this;
    },

    /**
     * Store the key/value pair in the Model instance
     * Signal to property referenced change listener if property value is changed
     *
     * @param  {String} prop Property name to be stored
     * @param  {Array|Function|Number|Object|String} val Property value to be stored
     * @return {Class} The Model instance
     */
    __set: function(prop, val){
        /**
         * Use the custom setter accessor if it exists.
         * Otherwise, set the property in the regular fashion.
         */
        var accessor = this.getAccessor(prop, 'set');
        /**
         * If the accessor is true, then run it, and return false
         * to the if statement to prevent it from continuing to
         * run through the code block
         */
        if (accessor && this._accessorName != prop) {
            return accessor.apply(this, arguments);
        }

        // Store the older prop
        var old = this.get(prop);

        if (!Is.Equal(old, val)) {
            this._changed = true;

            // cloneVal will return a cloned of an Array or Object that is not a Class or the val itself
            this._data[prop] = this._changedProperties[prop] = cloneVal(val);
        }

        return this;
    }.overloadSetter(),

    _set: function(prop, val){
        /**
         * Increment/decrement _setting value so that calls to set method in
         * custom setters won't trigger change and setPrevious. Doing so during
         * setting would cause discrepancies in previously stored data.
         */
        this._setting++;

        this.__set(prop, val);

        this._setting--;

        return this;
    },

    /**
     * Store the key/value pair in the Model instance
     *
     * @param  {String} prop Property name to be stored
     * @param  {Array|Function|Number|Object|String} val Property value to be stored
     *         Function property will be invoked with 'call', bound to the Model instance
     * @return {Class} The Model instance
     */
    set: function(prop, val){
        var isSetting;

        if (prop) {

            isSetting = this.isSetting();

            // store the previously changed property
            !isSetting && this._setPrevious(this.getData());

            /**
             * If the prop arg is a Model, then we should get all the data to set
             */
            prop = instanceOf(prop, Model) ? prop.getData() : prop;

            this._set(prop, val);

            if (!isSetting) {
                // Signal any changed properties
                this.changeProperty(this._changedProperties);

                // Signal change
                this.change();

                // reset changed and changed properties
                this._resetChanged();
            }
        }

        return this;
    },

    isSetting: function(){
        return !! this._setting;
    },

    /**
     * Unset a data property. It can not be erased so it will be set to undefined
     *
     * @param  {String|Array} prop Property name/names to be unset
     * @return {Class} The Model instance
     */
    unset: function(prop){
        var props = {},
            len, i = 0, item;

        prop = Array.from(prop);
        len = prop.length;

        while(len--){
            props[prop[i++]] = void 0;
        }

        // void 0 is used because 'undefined' is a var that can be changed in some browsers
        this.set(props);

        return this;
    },

    reset: function(prop){
        var props = {},
            defaults = this.options.defaults,
            len, i = 0, item;

        if (prop) {
            prop = Array.from(prop);
            len = prop.length;

            while(len--){
                item = prop[i++];
                props[item] = defaults[item];
            }
        } else {
            props = defaults;
        }

        this.set(props);

        this.signalReset();

        return this;
    },

    /**
     * Retrieve the stored property
     *
     * @param  {String} prop Property name to retrieve
     * @return Value referenced by prop param
     */
    get: curryGetter('_data'),

    /**
     * Retrieve entire data object in Model instance
     *
     * @return {Object}
     */
    getData: curryGetData('get'),

    _setPrevious: function(prop, val){
        this._previousData[prop] = val;
        return this;
    }.overloadSetter(),

    getPrevious: curryGetter('_previousData'),

    getPreviousData: curryGetData('getPrevious'),

    _resetChanged: function(){
        if (this._changed) {
            // reset the changed
            this._changed = false;

            // reset changed properties
            this._changedProperties = {};
        }

        return this;
    },

    /**
     * Signal to 'change' listener if model has changed
     *
     * @return {[type]}
     */
    change: function(){
        if (this._changed) {
            this.signalChange();
        }

        return this;
    },

    /**
     * Signal to 'change:prop' listener if model property has changed
     * @param  {String} prop Name of property
     * @return {[type]}
     */
    changeProperty: function(prop, val){
        if (this._changed) {
            this.signalChangeProperty(prop, val, this.getPrevious(prop));
        }

        return this;
    }.overloadSetter(),

    /**
     * Signal to 'destroy' listener if model is to be destroyed
     *
     * @return {[type]}
     */
    destroy: function(){
        this.signalDestroy();

        return this;
    },

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

    /**
     * Add a listener to the property change
     * @param  {String|Object}  prop    String or object of string/function pairs
     * @param  {Function}   callback    Function that is executed upon event firing
     * @return {Class}  Class instance
     */
    spy: function(prop, callback){
        if ((Type.isString(prop) && prop in this._data) && Type.isFunction(callback)) {
            this.addEvent('change:' + prop, callback);
        }

        return this;
    }.overloadSetter(),

    /**
     * Remove a listener to the property change
     * @param  {String|Object}  prop    String or object of string/function pairs
     * @param  {Function}   callback    Function that is executed upon event firing.
     * @return {Class}  Class instance
     */
    unspy: function(prop, callback){
        if ((Type.isString(prop) && prop in this._data)) {
            this.removeEvents('change:' + prop, callback);
        }

        return this;
    }.overloadSetter(),

    setAccessor: function(name, val){
        var set;

        if (name && val) {

            /**
             * Create a getPrevious method that is the get method,
             * but passed a true arg to signify it should access _previousData
             * while the get method gets passed a false value to signify it
             * should access _data.
             */
            if (val.get && !val.getPrevious) {
                val.getPrevious = val.get;
            }

            // Kind of hack because implementing a class only copies the methods.
            Butler.prototype.setAccessor.call(this, name, val);
        }

        return this;
    }.overloadSetter()
});

['each', 'subset', 'map', 'filter', 'every', 'some', 'keys', 'values', 'getLength', 'keyOf', 'contains', 'toQueryString'].each(function(method){
    Model.implement(method, function(){
        return Object[method].apply( Object, [this._data].append( Array.from(arguments) ) );
    });
});

exports.Model = Model;
// }(typeof exports != 'undefined' ? exports : window));
<commit_msg>Fix space.<commit_after>// (function(context){

var Is = require('neuro-is').Is,
    Silence = require('../mixins/silence').Silence,
    Connector = require('../mixins/connector').Connector,
    Butler = require('../mixins/butler').Butler,
    signalFactory = require('../utils/signalFactory');

var cloneVal = function(val){
    switch(typeOf(val)){
        // Dereference the new val if it's an Array
        case 'array': val = val.slice(); break;
        // Or an Object but not an instance of Class
        case 'object':
            if (!val.$constructor || (val.$constructor && !instanceOf(val.$constructor, Class))){
                val = Object.clone(val);
            }
            break;
    }

    return val;
};

var curryGetter = function(type){
    /**
     * isPrevious is a parameter to be passed into custom getter accessors.
     * This will allow the getter to know whether it should be retrieving from _data or _previousData.
     * @type {Boolean}
     */
    var isPrevious = type == '_previousData' || void 0;

    return function(prop){
        var accessor = this.getAccessor(prop, isPrevious ? 'getPrevious' : 'get'),
            // accessing = this.isAccessing(),
            accessorName = this._accessorName;

        /**
         * Prevent recursive get calls by checking if it's currently accessing
         * and if the accessor name is the same as the property arg. If all positive,
         * then return the value from _data/_previousData, otherwise return from
         * the accessor function. Fallback to returning from the _data/_previousData
         * if an accessor function does not exist.
         */
        if (accessor) {
            if (accessorName != prop) {
                return accessor();
            }
        }

        return this[type][prop];

        // return accessor && accessorName != prop ? accessor() : this[type][prop];
    }.overloadGetter();
};

var curryGetData = function(type){
    return function(){
        var props = this.keys(),
            obj = {};

        props.each(function(prop){
            // cloneVal will return a cloned of an Array or Object that is not a Class or the val itself
            obj[prop] = cloneVal(this[type](prop));
        }.bind(this));

        return obj;
    };
};

var Signals = new Class(
    signalFactory(
        ['change', 'destroy', 'reset'],
        {
            signalChangeProperty: function(prop, newVal, oldVal){
                !this.isSilent() && this.fireEvent('change:' + prop, [this, prop, newVal, oldVal]);
                return this;
            }
        }
    )
);

var Model = new Class({
    Implements: [Connector, Butler, Events, Options, Silence, Signals],

    primaryKey: undefined,

    _data: {},

    // _defaults: {},

    _changed: false,

    _changedProperties: {},

    _previousData: {},

    _setting: 0,

    options: {
        // onChange: function(){},
        // 'onChange:key': function(){},
        // onDestroy: function(){},
        // onReset: function(){},
        primaryKey: undefined,
        defaults: {}
    },

    initialize: function(data, options){
        if (instanceOf(data, this.constructor)) {
            return data;
        }

        this.setup(data, options);
    },

    setup: function(data, options){
        this.setOptions(options);

        this.primaryKey = this.options.primaryKey;

        this.setupAccessors();

        // properly set the defaults object
        // Object.merge(this._defaults, this.options.defaults);

        // Set the _data defaults silently because listeners shouldn't need to know that the defaults have been defined
        this.silence(function(){
            this.set(this.options.defaults);
        }.bind(this));

        // Just set the data instead of Object merging. This will skip cloning Class instances.
        if (data) { this.set(data); }

        return this;
    },

    /**
     * Store the key/value pair in the Model instance
     * Signal to property referenced change listener if property value is changed
     *
     * @param  {String} prop Property name to be stored
     * @param  {Array|Function|Number|Object|String} val Property value to be stored
     * @return {Class} The Model instance
     */
    __set: function(prop, val){
        /**
         * Use the custom setter accessor if it exists.
         * Otherwise, set the property in the regular fashion.
         */
        var accessor = this.getAccessor(prop, 'set');
        /**
         * If the accessor is true, then run it, and return false
         * to the if statement to prevent it from continuing to
         * run through the code block
         */
        if (accessor && this._accessorName != prop) {
            return accessor.apply(this, arguments);
        }

        // Store the older prop
        var old = this.get(prop);

        if (!Is.Equal(old, val)) {
            this._changed = true;

            // cloneVal will return a cloned of an Array or Object that is not a Class or the val itself
            this._data[prop] = this._changedProperties[prop] = cloneVal(val);
        }

        return this;
    }.overloadSetter(),

    _set: function(prop, val){
        /**
         * Increment/decrement _setting value so that calls to set method in
         * custom setters won't trigger change and setPrevious. Doing so during
         * setting would cause discrepancies in previously stored data.
         */
        this._setting++;

        this.__set(prop, val);

        this._setting--;

        return this;
    },

    /**
     * Store the key/value pair in the Model instance
     *
     * @param  {String} prop Property name to be stored
     * @param  {Array|Function|Number|Object|String} val Property value to be stored
     *         Function property will be invoked with 'call', bound to the Model instance
     * @return {Class} The Model instance
     */
    set: function(prop, val){
        var isSetting;

        if (prop) {

            isSetting = this.isSetting();

            // store the previously changed property
            !isSetting && this._setPrevious(this.getData());

            /**
             * If the prop arg is a Model, then we should get all the data to set
             */
            prop = instanceOf(prop, Model) ? prop.getData() : prop;

            this._set(prop, val);

            if (!isSetting) {
                // Signal any changed properties
                this.changeProperty(this._changedProperties);

                // Signal change
                this.change();

                // reset changed and changed properties
                this._resetChanged();
            }
        }

        return this;
    },

    isSetting: function(){
        return !!this._setting;
    },

    /**
     * Unset a data property. It can not be erased so it will be set to undefined
     *
     * @param  {String|Array} prop Property name/names to be unset
     * @return {Class} The Model instance
     */
    unset: function(prop){
        var props = {},
            len, i = 0, item;

        prop = Array.from(prop);
        len = prop.length;

        while(len--){
            props[prop[i++]] = void 0;
        }

        // void 0 is used because 'undefined' is a var that can be changed in some browsers
        this.set(props);

        return this;
    },

    reset: function(prop){
        var props = {},
            defaults = this.options.defaults,
            len, i = 0, item;

        if (prop) {
            prop = Array.from(prop);
            len = prop.length;

            while(len--){
                item = prop[i++];
                props[item] = defaults[item];
            }
        } else {
            props = defaults;
        }

        this.set(props);

        this.signalReset();

        return this;
    },

    /**
     * Retrieve the stored property
     *
     * @param  {String} prop Property name to retrieve
     * @return Value referenced by prop param
     */
    get: curryGetter('_data'),

    /**
     * Retrieve entire data object in Model instance
     *
     * @return {Object}
     */
    getData: curryGetData('get'),

    _setPrevious: function(prop, val){
        this._previousData[prop] = val;
        return this;
    }.overloadSetter(),

    getPrevious: curryGetter('_previousData'),

    getPreviousData: curryGetData('getPrevious'),

    _resetChanged: function(){
        if (this._changed) {
            // reset the changed
            this._changed = false;

            // reset changed properties
            this._changedProperties = {};
        }

        return this;
    },

    /**
     * Signal to 'change' listener if model has changed
     *
     * @return {[type]}
     */
    change: function(){
        if (this._changed) {
            this.signalChange();
        }

        return this;
    },

    /**
     * Signal to 'change:prop' listener if model property has changed
     * @param  {String} prop Name of property
     * @return {[type]}
     */
    changeProperty: function(prop, val){
        if (this._changed) {
            this.signalChangeProperty(prop, val, this.getPrevious(prop));
        }

        return this;
    }.overloadSetter(),

    /**
     * Signal to 'destroy' listener if model is to be destroyed
     *
     * @return {[type]}
     */
    destroy: function(){
        this.signalDestroy();

        return this;
    },

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

    /**
     * Add a listener to the property change
     * @param  {String|Object}  prop    String or object of string/function pairs
     * @param  {Function}   callback    Function that is executed upon event firing
     * @return {Class}  Class instance
     */
    spy: function(prop, callback){
        if ((Type.isString(prop) && prop in this._data) && Type.isFunction(callback)) {
            this.addEvent('change:' + prop, callback);
        }

        return this;
    }.overloadSetter(),

    /**
     * Remove a listener to the property change
     * @param  {String|Object}  prop    String or object of string/function pairs
     * @param  {Function}   callback    Function that is executed upon event firing.
     * @return {Class}  Class instance
     */
    unspy: function(prop, callback){
        if ((Type.isString(prop) && prop in this._data)) {
            this.removeEvents('change:' + prop, callback);
        }

        return this;
    }.overloadSetter(),

    setAccessor: function(name, val){
        var set;

        if (name && val) {

            /**
             * Create a getPrevious method that is the get method,
             * but passed a true arg to signify it should access _previousData
             * while the get method gets passed a false value to signify it
             * should access _data.
             */
            if (val.get && !val.getPrevious) {
                val.getPrevious = val.get;
            }

            // Kind of hack because implementing a class only copies the methods.
            Butler.prototype.setAccessor.call(this, name, val);
        }

        return this;
    }.overloadSetter()
});

['each', 'subset', 'map', 'filter', 'every', 'some', 'keys', 'values', 'getLength', 'keyOf', 'contains', 'toQueryString'].each(function(method){
    Model.implement(method, function(){
        return Object[method].apply( Object, [this._data].append( Array.from(arguments) ) );
    });
});

exports.Model = Model;
// }(typeof exports != 'undefined' ? exports : window));
<|endoftext|>


<commit_before>define([
    'angular',
    'vis'
], function(angular, vis) {
    'use strict';

    angular.module('ngVis', [])

        .factory('VisDataSet', function () {
            'use strict';
            return function (data, options) {
                // Create the new dataSets
                return new vis.DataSet(data, options);
            };
        })

    /**
     * TimeLine directive
     */
        .directive('visTimeline', function () {
            'use strict';
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var timelineEvents = [
                        'rangechange',
                        'rangechanged',
                        'timechange',
                        'timechanged',
                        'select',
                        'doubleClick',
                        'click',
                        'contextmenu'
                    ];

                    // Declare the timeline
                    var timeline = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (timeline != null) {
                            timeline.destroy();
                        }

                        // Create the timeline object
                        timeline = new vis.Timeline(element[0], scope.data.items, scope.data.groups, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (timelineEvents.indexOf(String(event)) >= 0) {
                                timeline.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(timeline);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (timeline == null) {
                            return;
                        }
                        timeline.setOptions(options);
                    });
                }
            };
        })

    /**
     * Directive for network chart.
     */
        .directive('visNetwork', function() {
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var networkEvents = [
                        'click',
                        'doubleClick',
                        'oncontext',
                        'hold',
                        'release',
                        'selectNode',
                        'selectEdge',
                        'deselectNode',
                        'deselectEdge',
                        'dragStart',
                        'dragging',
                        'dragEnd',
                        'hoverNode',
                        'blurNode',
                        'zoom',
                        'showPopup',
                        'hidePopup',
                        'startStabilizing',
                        'stabilizationProgress',
                        'stabilizationIterationsDone',
                        'stabilized',
                        'resize',
                        'initRedraw',
                        'beforeDrawing',
                        'afterDrawing',
                        'animationFinished'

                    ];

                    var network = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (network != null) {
                            network.destroy();
                        }

                        // Create the graph2d object
                        network = new vis.Network(element[0], scope.data, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (networkEvents.indexOf(String(event)) >= 0) {
                                network.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(network);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (network == null) {
                            return;
                        }
                        // This watch is not fired immediately! Do not rely on it and
                        // change options manually with the network that is provided
                        // in the onload callback.
                        // network.setOptions(options);
                    });
                }
            };
        })

    /**
     * Directive for graph2d.
     */
        .directive('visGraph2d', function () {
            'use strict';
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var graphEvents = [
                        'rangechange',
                        'rangechanged',
                        'timechange',
                        'timechanged',
                        'finishedRedraw'
                    ];

                    // Create the chart
                    var graph = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (graph != null) {
                            graph.destroy();
                        }

                        // Create the graph2d object
                        graph = new vis.Graph2d(element[0], scope.data.items, scope.data.groups, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (graphEvents.indexOf(String(event)) >= 0) {
                                graph.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(graph);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (graph == null) {
                            return;
                        }
                        graph.setOptions(options);
                    });
                }
            };
        })
    ;
});
<commit_msg>Add missing hoverEdge event to the network component<commit_after>define([
    'angular',
    'vis'
], function(angular, vis) {
    'use strict';

    angular.module('ngVis', [])

        .factory('VisDataSet', function () {
            'use strict';
            return function (data, options) {
                // Create the new dataSets
                return new vis.DataSet(data, options);
            };
        })

    /**
     * TimeLine directive
     */
        .directive('visTimeline', function () {
            'use strict';
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var timelineEvents = [
                        'rangechange',
                        'rangechanged',
                        'timechange',
                        'timechanged',
                        'select',
                        'doubleClick',
                        'click',
                        'contextmenu'
                    ];

                    // Declare the timeline
                    var timeline = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (timeline != null) {
                            timeline.destroy();
                        }

                        // Create the timeline object
                        timeline = new vis.Timeline(element[0], scope.data.items, scope.data.groups, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (timelineEvents.indexOf(String(event)) >= 0) {
                                timeline.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(timeline);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (timeline == null) {
                            return;
                        }
                        timeline.setOptions(options);
                    });
                }
            };
        })

    /**
     * Directive for network chart.
     */
        .directive('visNetwork', function() {
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var networkEvents = [
                        'click',
                        'doubleClick',
                        'oncontext',
                        'hold',
                        'release',
                        'selectNode',
                        'selectEdge',
                        'deselectNode',
                        'deselectEdge',
                        'dragStart',
                        'dragging',
                        'dragEnd',
                        'hoverNode',
                        'hoverEdge',
                        'blurNode',
                        'zoom',
                        'showPopup',
                        'hidePopup',
                        'startStabilizing',
                        'stabilizationProgress',
                        'stabilizationIterationsDone',
                        'stabilized',
                        'resize',
                        'initRedraw',
                        'beforeDrawing',
                        'afterDrawing',
                        'animationFinished'

                    ];

                    var network = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (network != null) {
                            network.destroy();
                        }

                        // Create the graph2d object
                        network = new vis.Network(element[0], scope.data, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (networkEvents.indexOf(String(event)) >= 0) {
                                network.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(network);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (network == null) {
                            return;
                        }
                        // This watch is not fired immediately! Do not rely on it and
                        // change options manually with the network that is provided
                        // in the onload callback.
                        // network.setOptions(options);
                    });
                }
            };
        })

    /**
     * Directive for graph2d.
     */
        .directive('visGraph2d', function () {
            'use strict';
            return {
                restrict: 'EA',
                transclude: false,
                scope: {
                    data: '=',
                    options: '=',
                    events: '='
                },
                link: function (scope, element, attr) {
                    var graphEvents = [
                        'rangechange',
                        'rangechanged',
                        'timechange',
                        'timechanged',
                        'finishedRedraw'
                    ];

                    // Create the chart
                    var graph = null;

                    scope.$watch('data', function () {
                        // Sanity check
                        if (scope.data == null) {
                            return;
                        }

                        // If we've actually changed the data set, then recreate the graph
                        // We can always update the data by adding more data to the existing data set
                        if (graph != null) {
                            graph.destroy();
                        }

                        // Create the graph2d object
                        graph = new vis.Graph2d(element[0], scope.data.items, scope.data.groups, scope.options);

                        // Attach an event handler if defined
                        angular.forEach(scope.events, function (callback, event) {
                            if (graphEvents.indexOf(String(event)) >= 0) {
                                graph.on(event, callback);
                            }
                        });

                        // onLoad callback
                        if (scope.events != null && scope.events.onload != null &&
                            angular.isFunction(scope.events.onload)) {
                            scope.events.onload(graph);
                        }
                    });

                    scope.$watchCollection('options', function (options) {
                        if (graph == null) {
                            return;
                        }
                        graph.setOptions(options);
                    });
                }
            };
        })
    ;
});
<|endoftext|>


<commit_before>moj.Modules.CaseClosure = {
    init: function () {
        $('.js-de-escalate-link').on('click', function(e) {
            var $link = $(this)[0];
            $.ajax({
                url: $link.href,
                method: 'patch',
                statusCode: {
                    204: function() {
                        $td = $($link.closest('td'));
                        $td.find('.escalated-container').hide();
                        $td.find('.de-escalated-container').show();
                    }
                }
            });
            return false;
        });

        $('.js-undo-de-escalate-link').on('click', function(e) {
            var $link = $(this)[0];
            $.ajax({
                url: $link.href,
                method: 'patch',
                statusCode: {
                    204: function() {
                        $td = $($link.closest('td'));
                        $td.find('.de-escalated-container').hide();
                        $td.find('.escalated-container').show();
                    }
                }
            });
            return false;
        });
   }
};
<commit_msg>CT-699 stylistic tweaks to DeEscalateCase.js<commit_after>moj.Modules.CaseClosure = {
  init: function () {
    function toggleEscalatedContainers() {
      var $link = $(this);
      $.ajax({
        url: $link.attr('href'),
        method: 'patch',
        statusCode: {
          204: function() {
            var $td = $link.closest('td');
            $td.find('.escalated-container').toggle();
            $td.find('.de-escalated-container').toggle();
          }
        }
      });
      return false;
    }

    $('.js-de-escalate-link, .js-undo-de-escalate-link').on(
      'click', toggleEscalatedContainers
    );
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import {NavLink, navigateAction} from 'fluxible-router';
import { FormattedMessage, defineMessages } from 'react-intl';

class UserMenu extends React.Component {
    constructor(props){
        super(props);
        this.styles = {'backgroundColor': '#2185D0', 'color': 'white'};
        this.messages = this.getIntlMessages();
    }
    getIntlMessages(){
        return defineMessages({
            myDecks: {
                id: 'UserMenu.myDecks',
                defaultMessage: 'My Decks'
            },
            ownedDecks: {
                id: 'UserMenu.ownedDecks',
                defaultMessage: 'Owned Decks'
            },
            sharedDecks: {
                id: 'UserMenu.sharedDecks',
                defaultMessage: 'Shared Decks'
            },
            collections: {
                id: 'UserMenu.collections',
                defaultMessage: 'Playlists'
            },
            ownedCollections: {
                id: 'UserMenu.ownedCollections',
                defaultMessage: 'Owned Playlists'
            },
            recommendedDecks: {
                id: 'UserMenu.recommendedDecks',
                defaultMessage: 'Recommended Decks'
            }
        });
    }
    render() {
      let deckRecommendationsMsg = this.context.intl.formatMessage(this.messages.recommendedDecks);
      let deckRecommendationNavLink = (
            <NavLink className="item" href={'/user/' + this.props.user.uname + '/recommendations'} activeStyle={this.styles}>

 {deckRecommendationsMsg}

            </NavLink>
        );

        let decksMsg = this.context.intl.formatMessage(this.messages.myDecks);
        let sharedDecksMsg = this.context.intl.formatMessage(this.messages.sharedDecks);
        let deckCollectionsMsg = this.context.intl.formatMessage(this.messages.collections);

        if(this.props.user.uname !== this.props.loggedinuser){
            decksMsg = this.context.intl.formatMessage(this.messages.ownedDecks);
            deckCollectionsMsg = this.context.intl.formatMessage(this.messages.ownedCollections);
            deckRecommendationNavLink = '';
        }

        return (

                  <NavLink className="item" href={'/user/' + this.props.user.uname } activeStyle={this.styles} role="menuitem">

 {decksMsg}

                  </NavLink>
                  { (this.props.user.uname === this.props.loggedinuser) &&
                    <NavLink className="item" href={'/user/' + this.props.user.uname + '/decks/shared'} activeStyle={this.styles} role="menuitem">

                                 {sharedDecksMsg}

                    </NavLink>
                  }
                  <NavLink className="item" href={'/user/' + this.props.user.uname + '/playlists'} activeStyle={this.styles} role="menuitem">

 {deckCollectionsMsg}

                  </NavLink>
                  {deckRecommendationNavLink}

        );
    }
}

UserMenu.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

export default UserMenu;
<commit_msg>SWIK-1945 Corrected indentation<commit_after>import React from 'react';
import {NavLink, navigateAction} from 'fluxible-router';
import { FormattedMessage, defineMessages } from 'react-intl';

class UserMenu extends React.Component {
    constructor(props){
        super(props);
        this.styles = {'backgroundColor': '#2185D0', 'color': 'white'};
        this.messages = this.getIntlMessages();
    }
    getIntlMessages(){
        return defineMessages({
            myDecks: {
                id: 'UserMenu.myDecks',
                defaultMessage: 'My Decks'
            },
            ownedDecks: {
                id: 'UserMenu.ownedDecks',
                defaultMessage: 'Owned Decks'
            },
            sharedDecks: {
                id: 'UserMenu.sharedDecks',
                defaultMessage: 'Shared Decks'
            },
            collections: {
                id: 'UserMenu.collections',
                defaultMessage: 'Playlists'
            },
            ownedCollections: {
                id: 'UserMenu.ownedCollections',
                defaultMessage: 'Owned Playlists'
            },
            recommendedDecks: {
                id: 'UserMenu.recommendedDecks',
                defaultMessage: 'Recommended Decks'
            }
        });
    }
    render() {
        let deckRecommendationsMsg = this.context.intl.formatMessage(this.messages.recommendedDecks);
        let deckRecommendationNavLink = (
            <NavLink className="item" href={'/user/' + this.props.user.uname + '/recommendations'} activeStyle={this.styles}>

 {deckRecommendationsMsg}

            </NavLink>
        );

        let decksMsg = this.context.intl.formatMessage(this.messages.myDecks);
        let sharedDecksMsg = this.context.intl.formatMessage(this.messages.sharedDecks);
        let deckCollectionsMsg = this.context.intl.formatMessage(this.messages.collections);

        if(this.props.user.uname !== this.props.loggedinuser){
            decksMsg = this.context.intl.formatMessage(this.messages.ownedDecks);
            deckCollectionsMsg = this.context.intl.formatMessage(this.messages.ownedCollections);
            deckRecommendationNavLink = '';
        }

        return (

                  <NavLink className="item" href={'/user/' + this.props.user.uname } activeStyle={this.styles} role="menuitem">

 {decksMsg}

                  </NavLink>
                  { (this.props.user.uname === this.props.loggedinuser) &&
                    <NavLink className="item" href={'/user/' + this.props.user.uname + '/decks/shared'} activeStyle={this.styles} role="menuitem">

                                 {sharedDecksMsg}

                    </NavLink>
                  }
                  <NavLink className="item" href={'/user/' + this.props.user.uname + '/playlists'} activeStyle={this.styles} role="menuitem">

 {deckCollectionsMsg}

                  </NavLink>
                  {deckRecommendationNavLink}

        );
    }
}

UserMenu.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

export default UserMenu;
<|endoftext|>


<commit_before>'use strict';
import React from 'react';
import { connect } from 'react-redux';
import { t } from '../utils/i18n';

import AATable from '../components/aa-table-vpromms';
import Headerdrop from '../components/headerdrop';

import { fetchVProMMSids } from '../actions/action-creators';
import config from '../config';

var AnalyticsAA = React.createClass({
  displayName: 'AnalyticsAA',

  propTypes: {
    children: React.PropTypes.object,
    routeParams: React.PropTypes.object,
    _fetchVProMMSids: React.PropTypes.func,
    VProMMSids: React.PropTypes.object
  },

  componentDidMount: function () {
    this.props._fetchVProMMSids();
  },

  renderDataDumpLinks: function (provinceId) {
    return (
        <Headerdrop
          id='datadump-selector'
          className='drop-road-network'
          triggerClassName='drop-toggle drop-road-network caret bttn bttn-secondary bttn-road-network'
          triggerText={`${t('Download')} ${t('Roads')}`}
          triggerElement='a'
          direction='down'
          alignment='right'>

            {
            ['CSV', 'GeoJSON'].map((type, i) => {
              let cl = 'drop-menu-item bttn bttn-m bttn-base-light bttn-road-network bttn-road-network-drop';
              return (
                <a className={cl} href={`${config.provinceDumpBaseUrl}${provinceId}.${type.toLowerCase()}`}>
                  {`${t('Download')} ${type}`}

              );
            })
            }

        </Headerdrop>
    );
  },

  render: function () {
    const provinceId = this.props.routeParams.aaId;
    const data = this.props.VProMMSids.data[provinceId];
    const ids = data.vpromms;
    const done = ids.filter(v => v.inTheDatabase).length;
    const total = ids.length;
    const completion = total !== 0 ? ((done / total) * 100) : 0;
    let completionMainText;
    let completionTailText = t('Information on VPRoMMS roads is not available');
    if (total !== 0) {
      completionMainText = completion.toFixed(2);
      completionTailText = `% ${t('of VProMMS Ids added')} ${done.toLocaleString()} of ${total.toLocaleString()}`;
    }
    return (

{data.provinceName} {t('Province')}

        { completion ? this.renderDataDumpLinks(provinceId) : '' }

{completionMainText}{completionTailText}

         <div className='meter__internal' style={{width: `${completion}%`}}>

        {total ? <AATable data={ids} /> : ''}

    );
  }
});

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function selector (state) {
  return {
    VProMMSids: state.VProMMSids
  };
}

function dispatcher (dispatch) {
  return {
    _fetchVProMMSids: (aaid) => dispatch(fetchVProMMSids())
  };
}

module.exports = connect(selector, dispatcher)(AnalyticsAA);
<commit_msg>#103 - remove non-existant class<commit_after>'use strict';
import React from 'react';
import { connect } from 'react-redux';
import { t } from '../utils/i18n';

import AATable from '../components/aa-table-vpromms';
import Headerdrop from '../components/headerdrop';

import { fetchVProMMSids } from '../actions/action-creators';
import config from '../config';

var AnalyticsAA = React.createClass({
  displayName: 'AnalyticsAA',

  propTypes: {
    children: React.PropTypes.object,
    routeParams: React.PropTypes.object,
    _fetchVProMMSids: React.PropTypes.func,
    VProMMSids: React.PropTypes.object
  },

  componentDidMount: function () {
    this.props._fetchVProMMSids();
  },

  renderDataDumpLinks: function (provinceId) {
    return (
        <Headerdrop
          id='datadump-selector'
          className='drop-road-network'
          triggerClassName='drop-toggle drop-road-network caret bttn bttn-secondary bttn-road-network'
          triggerText={`${t('Download')} ${t('Roads')}`}
          triggerElement='a'
          direction='down'
          alignment='right'>

            {
            ['CSV', 'GeoJSON'].map((type, i) => {
              let cl = 'drop-menu-item bttn bttn-m bttn-base-light bttn-road-network';
              return (
                <a className={cl} href={`${config.provinceDumpBaseUrl}${provinceId}.${type.toLowerCase()}`}>
                  {`${t('Download')} ${type}`}

              );
            })
            }

        </Headerdrop>
    );
  },

  render: function () {
    const provinceId = this.props.routeParams.aaId;
    const data = this.props.VProMMSids.data[provinceId];
    const ids = data.vpromms;
    const done = ids.filter(v => v.inTheDatabase).length;
    const total = ids.length;
    const completion = total !== 0 ? ((done / total) * 100) : 0;
    let completionMainText;
    let completionTailText = t('Information on VPRoMMS roads is not available');
    if (total !== 0) {
      completionMainText = completion.toFixed(2);
      completionTailText = `% ${t('of VProMMS Ids added')} ${done.toLocaleString()} of ${total.toLocaleString()}`;
    }
    return (

{data.provinceName} {t('Province')}

        { completion ? this.renderDataDumpLinks(provinceId) : '' }

{completionMainText}{completionTailText}

         <div className='meter__internal' style={{width: `${completion}%`}}>

        {total ? <AATable data={ids} /> : ''}

    );
  }
});

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function selector (state) {
  return {
    VProMMSids: state.VProMMSids
  };
}

function dispatcher (dispatch) {
  return {
    _fetchVProMMSids: (aaid) => dispatch(fetchVProMMSids())
  };
}

module.exports = connect(selector, dispatcher)(AnalyticsAA);
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */
function _FirebugConsole()
{
    //this.firebug = Firebug.version;

    this.userObjects = [];

    this.notifyFirebug = function(objs, methodName)
    {
        var element = this.getFirebugElement();
        var event = document.createEvent("Events");
        event.initEvent("firebugAppendConsole", true, false);

        element.setAttribute("methodName", methodName);

        element.setAttribute("firstAddition", this.userObjects.length + "");
        for (var i = 0; i < objs.length; i++)
        {
            this.userObjects.push(objs[i]);
        }
        element.setAttribute("lastAddition", this.userObjects.length - 1 + "");
        element.dispatchEvent(event);
        //dump("FirebugConsole dispatched event "+methodName+"\n");
    };

    this.getFirebugElement = function()
    {
        var element = document.getElementById("_firebugConsole");
        if (!element)
        {
            element = document.createElement("div");
            element.setAttribute("id", "_firebugConsole");
            element.firebugIgnore = true;
            element.setAttribute("style", "display:none");

            var self = this;
            element.addEventListener("firebugCommandLine", function(event)
            {
                var element = event.target;
                var expr = element.getAttribute("expr"); // see commandLine.js
                self.evaluate(expr);
            }, true);

            document.documentElement.appendChild(element);

            var event = document.createEvent("Events");
            event.initEvent("firebugAppendConsole", true, false);
            element.setAttribute("methodName", "init");
            element.setAttribute("firstAddition", "0");
            element.setAttribute("lastAddition", "-1");
            element.dispatchEvent(event);
        }
        return element;
    };

    // ***********************************************************************
    // Console API

    this.firebugVersion = function()
    {
        return this.getFirebugElement().getAttribute("FirebugVersion");
    };

    this.log = function()
    {
        this.notifyFirebug(arguments, "log");
    };

    this.debug = function()
    {
        this.notifyFirebug(arguments, "debug");
    };

    this.info = function()
    {
        this.notifyFirebug(arguments, "info");
    };

    this.warn = function()
    {
        this.notifyFirebug(arguments, "warn");
    };

    this.error = function()
    {
        this.notifyFirebug(arguments, "error" );
    };

    this.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            this.notifyFirebug(rest, "assert");
        }
    };

    this.dir = function(o)
    {
        this.notifyFirebug(arguments, "dir");
    };

    this.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        this.notifyFirebug(arguments, "dirxml");
    };

    this.trace = function()
    {
        this.notifyFirebug(arguments, "trace");
    };

    this.group = function()
    {
        this.notifyFirebug(arguments, "group");
    };

    this.groupEnd = function()
    {
        this.notifyFirebug(arguments, "groupEnd");
    };

    this.groupCollapsed = function()
    {
        this.notifyFirebug(arguments, "groupCollapsed");
    };

    this.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        if (!reset && this.timeCounters.hasOwnProperty(name))
            return;

        this.timeCounters[name] = time;
    };

    this.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var timeCounter = this.timeCounters[name];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.notifyFirebug([label], "info");

            delete this.timeCounters[name];
        }
        return diff;
    };

    this.profile = function(title)
    {
        this.notifyFirebug(arguments, "profile");
    };

    this.profileEnd = function()
    {
        this.notifyFirebug(arguments, "profileEnd");
    };

    this.count = function(key)
    {
        this.notifyFirebug(arguments, "count");
    };

    this.evaluate = function(expr)
    {
        try
        {
            var result = eval(expr);
            this.notifyFirebug([result], "evaluated");
        }
        catch(exc)
        {
            var result = exc;
            result.source = expr;
            this.notifyFirebug([result], "evaluateError");
        }
    };
}
//window.dump("============================>>>> Setting _firebug <<<< ====================================\n");
window._firebug =  new _FirebugConsole();
//window.dump("============================>>>> Set _firebug "+window._firebug+" "+window._FirebugConsole+" <<<< ====================================\n");
//for (var p in window.firebug)
//    window.dump(p+"="+window.console[p]+"\n");
<commit_msg>If there is no result from evaluation of the command line script, don't print "undefined" to the console.<commit_after>/* See license.txt for terms of usage */
function _FirebugConsole()
{
    //this.firebug = Firebug.version;

    this.userObjects = [];

    this.notifyFirebug = function(objs, methodName)
    {
        var element = this.getFirebugElement();
        var event = document.createEvent("Events");
        event.initEvent("firebugAppendConsole", true, false);

        element.setAttribute("methodName", methodName);

        element.setAttribute("firstAddition", this.userObjects.length + "");
        for (var i = 0; i < objs.length; i++)
        {
            this.userObjects.push(objs[i]);
        }
        element.setAttribute("lastAddition", this.userObjects.length - 1 + "");
        element.dispatchEvent(event);
        //dump("FirebugConsole dispatched event "+methodName+"\n");
    };

    this.getFirebugElement = function()
    {
        var element = document.getElementById("_firebugConsole");
        if (!element)
        {
            element = document.createElement("div");
            element.setAttribute("id", "_firebugConsole");
            element.firebugIgnore = true;
            element.setAttribute("style", "display:none");

            var self = this;
            element.addEventListener("firebugCommandLine", function(event)
            {
                var element = event.target;
                var expr = element.getAttribute("expr"); // see commandLine.js
                self.evaluate(expr);
            }, true);

            document.documentElement.appendChild(element);

            var event = document.createEvent("Events");
            event.initEvent("firebugAppendConsole", true, false);
            element.setAttribute("methodName", "init");
            element.setAttribute("firstAddition", "0");
            element.setAttribute("lastAddition", "-1");
            element.dispatchEvent(event);
        }
        return element;
    };

    // ***********************************************************************
    // Console API

    this.firebugVersion = function()
    {
        return this.getFirebugElement().getAttribute("FirebugVersion");
    };

    this.log = function()
    {
        this.notifyFirebug(arguments, "log");
    };

    this.debug = function()
    {
        this.notifyFirebug(arguments, "debug");
    };

    this.info = function()
    {
        this.notifyFirebug(arguments, "info");
    };

    this.warn = function()
    {
        this.notifyFirebug(arguments, "warn");
    };

    this.error = function()
    {
        this.notifyFirebug(arguments, "error" );
    };

    this.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            this.notifyFirebug(rest, "assert");
        }
    };

    this.dir = function(o)
    {
        this.notifyFirebug(arguments, "dir");
    };

    this.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        this.notifyFirebug(arguments, "dirxml");
    };

    this.trace = function()
    {
        this.notifyFirebug(arguments, "trace");
    };

    this.group = function()
    {
        this.notifyFirebug(arguments, "group");
    };

    this.groupEnd = function()
    {
        this.notifyFirebug(arguments, "groupEnd");
    };

    this.groupCollapsed = function()
    {
        this.notifyFirebug(arguments, "groupCollapsed");
    };

    this.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        if (!reset && this.timeCounters.hasOwnProperty(name))
            return;

        this.timeCounters[name] = time;
    };

    this.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var timeCounter = this.timeCounters[name];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.notifyFirebug([label], "info");

            delete this.timeCounters[name];
        }
        return diff;
    };

    this.profile = function(title)
    {
        this.notifyFirebug(arguments, "profile");
    };

    this.profileEnd = function()
    {
        this.notifyFirebug(arguments, "profileEnd");
    };

    this.count = function(key)
    {
        this.notifyFirebug(arguments, "count");
    };

    this.evaluate = function(expr)
    {
        try
        {
            var result = eval(expr);
            if (result)
                this.notifyFirebug([result], "evaluated");
        }
        catch(exc)
        {
            var result = exc;
            result.source = expr;
            this.notifyFirebug([result], "evaluateError");
        }
    };
}
//window.dump("============================>>>> Setting _firebug <<<< ====================================\n");
window._firebug =  new _FirebugConsole();
//window.dump("============================>>>> Set _firebug "+window._firebug+" "+window._FirebugConsole+" <<<< ====================================\n");
//for (var p in window.firebug)
//    window.dump(p+"="+window.console[p]+"\n");
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

//
FBL.ns(function() { with (FBL) {

// ************************************************************************************************
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

top.Firebug.Console.injector =
{
    isAttached: function(context, win)
    {
        if (win.wrappedJSObject)
        {
            var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject));

            return attached;
        }
        else
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement);
            return (win._getFirebugConsoleElement ? true : false);
        }
    },

    attachIfNeeded: function(context, win)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") );

        if (this.isAttached(context, win))
            return true;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded found isAttached false " +
                safeGetWindowLocation(win));

        this.attachConsoleInjector(context, win);
        this.addConsoleListener(context, win);

        Firebug.Console.clearReloadWarning(context);

        var attached =  this.isAttached(context, win);
        if (attached)
            dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]);

        return attached;
    },

    attachConsoleInjector: function(context, win)
    {
        var consoleInjection = this.getConsoleInjectionScript();  // Do it all here.

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection);

        Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location);
    },

    getConsoleInjectionScript: function() {
        if (!this.consoleInjectionScript)
        {
            var script = "";
            script += "window.__defineGetter__('console', function console() {\n";
            script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n";

            script += "window.loadFirebugConsole = function loadFirebugConsole() {\n";
            script += "window._firebug =  new _FirebugConsole();";

            if (FBTrace.DBG_CONSOLE)
                script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n";

            script += " return window._firebug };\n";

            var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");
            script += theFirebugConsoleScript;

            this.consoleInjectionScript = script;
        }
        return this.consoleInjectionScript;
    },

    forceConsoleCompilationInPage: function(context, win)
    {
        if (!win)
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("no win in forceConsoleCompilationInPage!");
            return;
        }

        var consoleForcer = "window.loadFirebugConsole();";

        if (context.stopped)
            Firebug.Console.injector.evaluateConsoleScript(context);  // todo evaluate consoleForcer on stack
        else
            Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer);
    },

    evaluateConsoleScript: function(context)
    {
        var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript
        Firebug.Debugger.evaluate(scriptSource, context);
    },

    addConsoleListener: function(context, win)
    {
        if (!context.activeConsoleHandlers)  // then we have not been this way before
            context.activeConsoleHandlers = {};

        if (!win)
            win = context.window;

        if (win.wrappedJSObject)
            win = win.wrappedJSObject;

        if (context.activeConsoleHandlers[win])
            return;

        // We need the element to attach our event listener.
        var element = Firebug.Console.getFirebugConsoleElement(context, win);
        if (element)
            element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version.
        else
            return false;

        var handler = createConsoleHandler(context, win);
        handler.attachTo(element);

        context.activeConsoleHandlers[win] = handler;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n");
        return true;
    },

    detachConsole: function(context, win)
    {
        if (!win)
            win = context.window;

        if (win.wrappedJSObject)
            win = win.wrappedJSObject;

        if (context.activeConsoleHandlers)
        {
            if (context.activeConsoleHandlers[win])
                context.activeConsoleHandlers[win].detach();
            delete context.activeConsoleHandlers[win];
        }

    },
}

var total_handlers = 0;
function createConsoleHandler(context, win)
{
	var handler = {};
	handler.console = createConsole(context, win),

    handler.attachTo = function(element)
    {
        this.element = element;
        // When raised on our injected element, callback to Firebug and append to console
        this.boundHandler = bind(this.handleEvent, this);
        this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector FirebugConsoleHandler addEventListener "+this.handler_name);
    };

    handler.detach = function()
    {
        this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector FirebugConsoleHandler removeEventListener "+this.handler_name);
    };

    handler.handler_name = ++total_handlers;
    handler.handleEvent = function(event)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event);
        if (!Firebug.CommandLine.CommandHandler.handle(event, this.console, win))
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("FirebugConsoleHandler", this);

            var methodName = event.target.getAttribute("methodName");
            Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
        }
    };

    handler.firebug = Firebug.version;

    handler.init = function()
    {
        var consoleElement = win.document.getElementById('_firebugConsole');
        consoleElement.setAttribute("FirebugVersion", Firebug.version);
    };

    return handler;
}

function createConsole(context, win)
{
	var console = {};
    console.log = function()
    {
        logFormatted(arguments, "log");
    };

    console.debug = function()
    {
        logFormatted(arguments, "debug", true);
    };

    console.info = function()
    {
        logFormatted(arguments, "info", true);
    };

    console.warn = function()
    {
        logFormatted(arguments, "warn", true);
    };

    console.error = function()
    {
        if (arguments.length == 1)
        {
            logAssert("error", arguments);  // add more info based on stack trace
        }
        else
        {
            Firebug.Errors.increaseCount(context);
            logFormatted(arguments, "error", true);  // user already added info
        }
    };

    console.exception = function()
    {
        logAssert("error", arguments);
    };

    console.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            logAssert("assert", rest);
        }
    };

    console.dir = function(o)
    {
        Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
    };

    console.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
    };

    console.group = function()
    {
        var sourceLink = getStackLink();
        Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
    };

    console.groupEnd = function()
    {
        Firebug.Console.closeGroup(context);
    };

    console.groupCollapsed = function()
    {
        var sourceLink = getStackLink();
        // noThrottle true is probably ok, openGroups will likely be short strings.
        var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
        removeClass(row, "opened");
    };

    console.profile = function(title)
    {
        Firebug.Profiler.startProfiling(context, title);
    };

    console.profileEnd = function()
    {
        Firebug.Profiler.stopProfiling(context);
    };

    console.count = function(key)
    {
        var frameId = FBL.getStackFrameId();
        if (frameId)
        {
            if (!context.frameCounters)
                context.frameCounters = {};

            if (key != undefined)
                frameId += key;

            var frameCounter = context.frameCounters[frameId];
            if (!frameCounter)
            {
                var logRow = logFormatted(["0"], null, true, true);

                frameCounter = {logRow: logRow, count: 1};
                context.frameCounters[frameId] = frameCounter;
            }
            else
                ++frameCounter.count;

            var label = key == undefined
                ? frameCounter.count
                : key + " " + frameCounter.count;

            frameCounter.logRow.firstChild.firstChild.nodeValue = label;
        }
    };

    console.clear = function()
    {
        Firebug.Console.clear(context);
    };

    console.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        var key = "KEY"+name.toString();

        if (!reset && this.timeCounters[key])
            return;

        this.timeCounters[key] = time;
    };

    console.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var key = "KEY"+name.toString();

        var timeCounter = this.timeCounters[key];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.info(label);

            delete this.timeCounters[key];
        }
        return diff;
    };

    console.table = function(data, columns)
    {
        FirebugReps.Table.log(data, columns, context);
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    // These functions are over-ridden by commandLine
    console.evaluated = function(result, context)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result);

        Firebug.Console.log(result, context);
    };

    console.evaluateError = function(result, context)
    {
        Firebug.Console.log(result, context, "errorMessage");
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    function logFormatted(args, className, linkToSource, noThrottle)
    {
        var sourceLink = linkToSource ? getStackLink() : null;
        return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
    }

    function logAssert(category, args)
    {
        Firebug.Errors.increaseCount(context);

        if (!args || !args.length || args.length == 0)
            var msg = [FBL.$STR("Assertion")];
        else
            var msg = args[0];

        if (Firebug.errorStackTrace)
        {
            var trace = Firebug.errorStackTrace;
            delete Firebug.errorStackTrace;
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from errorStackTrace", trace);
        }
        else if (msg.stack)
        {
            var trace = parseToStackTrace(msg.stack);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from msg.stack", trace);
        }
        else if (context.stackTrace)
        {
            var trace = context.stackTrace
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from context.window.stackTrace", trace);
        }
        else
        {
            var trace = getJSDUserStack();
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from getJSDUserStack", trace);
        }

        var url = msg.fileName ? msg.fileName : win.location.href;
        var lineNo = msg.lineNumber ? msg.lineNumber : 0;
        var errorObject = new FBL.ErrorMessage(msg, url, lineNo, "", category, context, trace);

        if (trace && trace.frames && trace.frames[0])
           errorObject.correctWithStackTrace(trace);

        errorObject.resetSource();

        if (args.length > 1)
        {
            errorObject.objects = []
            for (var i = 1; i < args.length; i++)
                errorObject.objects.push(args[i]);
        }

        var row = Firebug.Console.log(errorObject, context, "errorMessage", null, true); // noThrottle
        row.scrollIntoView();
    }

    function getComponentsStackDump()
    {
        // Starting with our stack, walk back to the user-level code
        var frame = Components.stack;
        var userURL = win.location.href.toString();

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame);

        // Drop frames until we get into user code.
        while (frame && FBL.isSystemURL(frame.filename) )
            frame = frame.caller;

        // Drop two more frames, the injected console function and firebugAppendConsole()
        if (frame)
            frame = frame.caller;
        if (frame)
            frame = frame.caller;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame);

        return frame;
    }

    function getStackLink()
    {
        return FBL.getFrameSourceLink(getComponentsStackDump());
    }

    function getJSDUserStack()
    {
        var trace = FBL.getCurrentStackTrace(context);

        var frames = trace ? trace.frames : null;
        if (frames && (frames.length > 0) )
        {
            var oldest = frames.length - 1;  // 6 - 1 = 5
            for (var i = 0; i < frames.length; i++)
            {
                if (frames[oldest - i].href.indexOf("chrome:") == 0) break;
                var fn = frames[oldest - i].fn + "";
                if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break;  // command line
            }
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace);
            trace.frames = trace.frames.slice(2 - i);  // take the oldest frames, leave 2 behind they are injection code

            return trace;
        }
        else
            return "Firebug failed to get stack trace with any frames";
    }

    return console;
}

}});
<commit_msg>expose createConsole as a property of Firebug.Console<commit_after>/* See license.txt for terms of usage */

//
FBL.ns(function() { with (FBL) {

// ************************************************************************************************
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

top.Firebug.Console.injector =
{
    isAttached: function(context, win)
    {
        if (win.wrappedJSObject)
        {
            var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject));

            return attached;
        }
        else
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement);
            return (win._getFirebugConsoleElement ? true : false);
        }
    },

    attachIfNeeded: function(context, win)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") );

        if (this.isAttached(context, win))
            return true;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded found isAttached false " +
                safeGetWindowLocation(win));

        this.attachConsoleInjector(context, win);
        this.addConsoleListener(context, win);

        Firebug.Console.clearReloadWarning(context);

        var attached =  this.isAttached(context, win);
        if (attached)
            dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]);

        return attached;
    },

    attachConsoleInjector: function(context, win)
    {
        var consoleInjection = this.getConsoleInjectionScript();  // Do it all here.

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection);

        Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location);
    },

    getConsoleInjectionScript: function() {
        if (!this.consoleInjectionScript)
        {
            var script = "";
            script += "window.__defineGetter__('console', function console() {\n";
            script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n";

            script += "window.loadFirebugConsole = function loadFirebugConsole() {\n";
            script += "window._firebug =  new _FirebugConsole();";

            if (FBTrace.DBG_CONSOLE)
                script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n";

            script += " return window._firebug };\n";

            var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");
            script += theFirebugConsoleScript;

            this.consoleInjectionScript = script;
        }
        return this.consoleInjectionScript;
    },

    forceConsoleCompilationInPage: function(context, win)
    {
        if (!win)
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("no win in forceConsoleCompilationInPage!");
            return;
        }

        var consoleForcer = "window.loadFirebugConsole();";

        if (context.stopped)
            Firebug.Console.injector.evaluateConsoleScript(context);  // todo evaluate consoleForcer on stack
        else
            Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer);
    },

    evaluateConsoleScript: function(context)
    {
        var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript
        Firebug.Debugger.evaluate(scriptSource, context);
    },

    addConsoleListener: function(context, win)
    {
        if (!context.activeConsoleHandlers)  // then we have not been this way before
            context.activeConsoleHandlers = {};

        if (!win)
            win = context.window;

        if (win.wrappedJSObject)
            win = win.wrappedJSObject;

        if (context.activeConsoleHandlers[win])
            return;

        // We need the element to attach our event listener.
        var element = Firebug.Console.getFirebugConsoleElement(context, win);
        if (element)
            element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version.
        else
            return false;

        var handler = createConsoleHandler(context, win);
        handler.attachTo(element);

        context.activeConsoleHandlers[win] = handler;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n");
        return true;
    },

    detachConsole: function(context, win)
    {
        if (!win)
            win = context.window;

        if (win.wrappedJSObject)
            win = win.wrappedJSObject;

        if (context.activeConsoleHandlers)
        {
            if (context.activeConsoleHandlers[win])
                context.activeConsoleHandlers[win].detach();
            delete context.activeConsoleHandlers[win];
        }

    },
}

var total_handlers = 0;
function createConsoleHandler(context, win)
{
	var handler = {};
	handler.console = Firebug.Console.createConsole(context, win),

    handler.attachTo = function(element)
    {
        this.element = element;
        // When raised on our injected element, callback to Firebug and append to console
        this.boundHandler = bind(this.handleEvent, this);
        this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector FirebugConsoleHandler addEventListener "+this.handler_name);
    };

    handler.detach = function()
    {
        this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector FirebugConsoleHandler removeEventListener "+this.handler_name);
    };

    handler.handler_name = ++total_handlers;
    handler.handleEvent = function(event)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event);
        if (!Firebug.CommandLine.CommandHandler.handle(event, this.console, win))
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("FirebugConsoleHandler", this);

            var methodName = event.target.getAttribute("methodName");
            Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
        }
    };

    handler.firebug = Firebug.version;

    handler.init = function()
    {
        var consoleElement = win.document.getElementById('_firebugConsole');
        consoleElement.setAttribute("FirebugVersion", Firebug.version);
    };

    return handler;
}

Firebug.Console.createConsole = function createConsole(context, win)
{
	var console = {};
    console.log = function()
    {
        logFormatted(arguments, "log");
    };

    console.debug = function()
    {
        logFormatted(arguments, "debug", true);
    };

    console.info = function()
    {
        logFormatted(arguments, "info", true);
    };

    console.warn = function()
    {
        logFormatted(arguments, "warn", true);
    };

    console.error = function()
    {
        if (arguments.length == 1)
        {
            logAssert("error", arguments);  // add more info based on stack trace
        }
        else
        {
            Firebug.Errors.increaseCount(context);
            logFormatted(arguments, "error", true);  // user already added info
        }
    };

    console.exception = function()
    {
        logAssert("error", arguments);
    };

    console.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            logAssert("assert", rest);
        }
    };

    console.dir = function(o)
    {
        Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
    };

    console.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
    };

    console.group = function()
    {
        var sourceLink = getStackLink();
        Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
    };

    console.groupEnd = function()
    {
        Firebug.Console.closeGroup(context);
    };

    console.groupCollapsed = function()
    {
        var sourceLink = getStackLink();
        // noThrottle true is probably ok, openGroups will likely be short strings.
        var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
        removeClass(row, "opened");
    };

    console.profile = function(title)
    {
        Firebug.Profiler.startProfiling(context, title);
    };

    console.profileEnd = function()
    {
        Firebug.Profiler.stopProfiling(context);
    };

    console.count = function(key)
    {
        var frameId = FBL.getStackFrameId();
        if (frameId)
        {
            if (!context.frameCounters)
                context.frameCounters = {};

            if (key != undefined)
                frameId += key;

            var frameCounter = context.frameCounters[frameId];
            if (!frameCounter)
            {
                var logRow = logFormatted(["0"], null, true, true);

                frameCounter = {logRow: logRow, count: 1};
                context.frameCounters[frameId] = frameCounter;
            }
            else
                ++frameCounter.count;

            var label = key == undefined
                ? frameCounter.count
                : key + " " + frameCounter.count;

            frameCounter.logRow.firstChild.firstChild.nodeValue = label;
        }
    };

    console.clear = function()
    {
        Firebug.Console.clear(context);
    };

    console.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        var key = "KEY"+name.toString();

        if (!reset && this.timeCounters[key])
            return;

        this.timeCounters[key] = time;
    };

    console.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var key = "KEY"+name.toString();

        var timeCounter = this.timeCounters[key];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.info(label);

            delete this.timeCounters[key];
        }
        return diff;
    };

    console.table = function(data, columns)
    {
        FirebugReps.Table.log(data, columns, context);
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    // These functions are over-ridden by commandLine
    console.evaluated = function(result, context)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result);

        Firebug.Console.log(result, context);
    };

    console.evaluateError = function(result, context)
    {
        Firebug.Console.log(result, context, "errorMessage");
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    function logFormatted(args, className, linkToSource, noThrottle)
    {
        var sourceLink = linkToSource ? getStackLink() : null;
        return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
    }

    function logAssert(category, args)
    {
        Firebug.Errors.increaseCount(context);

        if (!args || !args.length || args.length == 0)
            var msg = [FBL.$STR("Assertion")];
        else
            var msg = args[0];

        if (Firebug.errorStackTrace)
        {
            var trace = Firebug.errorStackTrace;
            delete Firebug.errorStackTrace;
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from errorStackTrace", trace);
        }
        else if (msg.stack)
        {
            var trace = parseToStackTrace(msg.stack);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from msg.stack", trace);
        }
        else if (context.stackTrace)
        {
            var trace = context.stackTrace
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from context.window.stackTrace", trace);
        }
        else
        {
            var trace = getJSDUserStack();
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("logAssert trace from getJSDUserStack", trace);
        }

        var url = msg.fileName ? msg.fileName : win.location.href;
        var lineNo = msg.lineNumber ? msg.lineNumber : 0;
        var errorObject = new FBL.ErrorMessage(msg, url, lineNo, "", category, context, trace);

        if (trace && trace.frames && trace.frames[0])
           errorObject.correctWithStackTrace(trace);

        errorObject.resetSource();

        if (args.length > 1)
        {
            errorObject.objects = []
            for (var i = 1; i < args.length; i++)
                errorObject.objects.push(args[i]);
        }

        var row = Firebug.Console.log(errorObject, context, "errorMessage", null, true); // noThrottle
        row.scrollIntoView();
    }

    function getComponentsStackDump()
    {
        // Starting with our stack, walk back to the user-level code
        var frame = Components.stack;
        var userURL = win.location.href.toString();

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame);

        // Drop frames until we get into user code.
        while (frame && FBL.isSystemURL(frame.filename) )
            frame = frame.caller;

        // Drop two more frames, the injected console function and firebugAppendConsole()
        if (frame)
            frame = frame.caller;
        if (frame)
            frame = frame.caller;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame);

        return frame;
    }

    function getStackLink()
    {
        return FBL.getFrameSourceLink(getComponentsStackDump());
    }

    function getJSDUserStack()
    {
        var trace = FBL.getCurrentStackTrace(context);

        var frames = trace ? trace.frames : null;
        if (frames && (frames.length > 0) )
        {
            var oldest = frames.length - 1;  // 6 - 1 = 5
            for (var i = 0; i < frames.length; i++)
            {
                if (frames[oldest - i].href.indexOf("chrome:") == 0) break;
                var fn = frames[oldest - i].fn + "";
                if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break;  // command line
            }
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace);
            trace.frames = trace.frames.slice(2 - i);  // take the oldest frames, leave 2 behind they are injection code

            return trace;
        }
        else
            return "Firebug failed to get stack trace with any frames";
    }

    return console;
}

}});
<|endoftext|>