<commit_before>/**
 * @description Google Chart Api Directive Module for AngularJS
 * @version 0.0.11
 * @author Nicolas Bouillon <nicolas@bouil.org>
 * @author GitHub contributors
 * @license MIT
 * @year 2013
 */
(function (document, window, angular) {
    'use strict';

    angular.module('googlechart', [])

        .value('googleChartApiConfig', {
            version: '1',
            optionalSettings: {
                packages: ['corechart']
            }
        })

        .provider('googleJsapiUrl', function () {
            var protocol = 'https:';
            var url = '//www.google.com/jsapi';

            this.setProtocol = function (newProtocol) {
                protocol = newProtocol;
            };

            this.setUrl = function (newUrl) {
                url = newUrl;
            };

            this.$get = function () {
                return (protocol ? protocol : '') + url;
            };
        })

        .factory('googleChartApiPromise', ['$rootScope', '$q', 'googleChartApiConfig', 'googleJsapiUrl', function ($rootScope, $q, apiConfig, googleJsapiUrl) {
            var apiReady = $q.defer();
            var onLoad = function () {
                // override callback function
                var settings = {
                    callback: function () {
                        var oldCb = apiConfig.optionalSettings.callback;
                        $rootScope.$apply(function () {
                            apiReady.resolve();
                        });

                        if (angular.isFunction(oldCb)) {
                            oldCb.call(this);
                        }
                    }
                };

                settings = angular.extend({}, apiConfig.optionalSettings, settings);

                window.google.load('visualization', apiConfig.version, settings);
            };
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');

            script.setAttribute('type', 'text/javascript');
            script.src = googleJsapiUrl;

            if (script.addEventListener) { // Standard browsers (including IE9+)
                script.addEventListener('load', onLoad, false);
            } else { // IE8 and below
                script.onreadystatechange = function () {
                    if (script.readyState === 'loaded' || script.readyState === 'complete') {
                        script.onreadystatechange = null;
                        onLoad();
                    }
                };
            }

            head.appendChild(script);

            return apiReady.promise;
        }])

        .directive('googleChart', ['$timeout', '$window', '$rootScope', 'googleChartApiPromise', function ($timeout, $window, $rootScope, googleChartApiPromise) {

            GoogleChartController.$inject = ['$scope', '$element', '$attrs', '$injector'];

            function GoogleChartController($scope, $element, $attrs, $injector){
                var self = this;
                var oldChartFormatters = {}, resizeHandler, wrapperListeners = {},
                    chartListeners = {}, innerVisualization = null;
                self.registerChartListener = registerChartListener;
                self.registerWrapperListener = registerWrapperListener;

                init();

                function applyFormat(formatType, FormatClass, dataTable) {
                    var i;
                    if (typeof (self.chart.formatters[formatType]) !== 'undefined') {
                        if (!angular.equals(self.chart.formatters[formatType], oldChartFormatters[formatType])) {
                            oldChartFormatters[formatType] = self.chart.formatters[formatType];
                            self.formatters[formatType] = [];

                            if (formatType === 'color') {
                                for (var cIdx = 0; cIdx < self.chart.formatters[formatType].length; cIdx++) {
                                    var colorFormat = new FormatClass();

                                    for (i = 0; i < self.chart.formatters[formatType][cIdx].formats.length; i++) {
                                        var data = self.chart.formatters[formatType][cIdx].formats[i];

                                        if (typeof (data.fromBgColor) !== 'undefined' && typeof (data.toBgColor) !== 'undefined') {
                                            colorFormat.addGradientRange(data.from, data.to, data.color, data.fromBgColor, data.toBgColor);
                                        } else {
                                            colorFormat.addRange(data.from, data.to, data.color, data.bgcolor);
                                        }
                                    }

                                    self.formatters[formatType].push(colorFormat);
                                }
                            } else {

                                for (i = 0; i < self.chart.formatters[formatType].length; i++) {
                                    self.formatters[formatType].push(new FormatClass(
                                        self.chart.formatters[formatType][i])
                                    );
                                }
                            }
                        }

                        //apply formats to dataTable
                        for (i = 0; i < self.formatters[formatType].length; i++) {
                            if (self.chart.formatters[formatType][i].columnNum < dataTable.getNumberOfColumns()) {
                                self.formatters[formatType][i].format(dataTable, self.chart.formatters[formatType][i].columnNum);
                            }
                        }

                        //Many formatters require HTML tags to display special formatting
                        if (formatType === 'arrow' || formatType === 'bar' || formatType === 'color') {
                            self.chart.options.allowHtml = true;
                        }
                    }
                }

                function cleanup(){
                    resizeHandler();
                }

                function draw() {
                    if (!draw.triggered && (self.chart !== undefined)) {
                        draw.triggered = true;
                        $timeout(setupAndDraw, 0, true);
                    } else if (self.chart !== undefined) {
                        $timeout.cancel(draw.recallTimeout);
                        draw.recallTimeout = $timeout(draw, 10);
                    }
                }

                function drawAsync() {
                    googleChartApiPromise.then(function () {
                        draw();
                    });
                }

                function drawChartWrapper(){
                    $scope.$eval($attrs.beforeDraw, { chartWrapper: $scope.chartWrapper });
                    self.chartWrapper.draw();
                    draw.triggered = false;
                }

                handleError.$inject = ['args'];
                function handleError(args) {
                    var error = args[0];
                    console.log("Chart not displayed due to error: '" + error.message + "' Full error object follows.");
                    console.log(error);
                }

                function handleReady() {
                    self.chart.displayed = true;
                    if (innerVisualization !== self.chartWrapper.getChart()){
                        innerVisualization = self.chartWrapper.getChart();
                        registerListenersWithGoogle(innerVisualization, chartListeners);
                    }
                }

                function init(){
                    /* Watches, to refresh the chart when its data, formatters, options, view,
                    or type change. All other values intentionally disregarded to avoid double
                    calls to the draw function. Please avoid making changes to these objects
                    directly from this directive.*/
                    $scope.$watch(watchValue, watchHandler, true); // true is for deep object equality checking

                    // Redraw the chart if the window is resized
                    resizeHandler = $rootScope.$on('resizeMsg', function () {
                        $timeout(function () {
                            // Not always defined yet in IE so check
                            if (self.chartWrapper) {
                                drawAsync();
                            }
                        });
                    });

                    //Cleanup resize handler.
                    $scope.$on('$destroy', cleanup());

                    registerWrapperListener('error', handleError, self);
                    registerWrapperListener('ready', handleReady, self);
                }

                function setupAndDraw(){
                    if (typeof (self.chartWrapper) === 'undefined') {
                        var chartWrapperArgs = {
                            chartType: self.chart.type,
                            dataTable: self.chart.data,
                            view: self.chart.view,
                            options: self.chart.options,
                            containerId: $element[0]
                        };

                        self.chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
                        registerListenersWithGoogle(self.chartWrapper, wrapperListeners);
                    } else {
                        self.chartWrapper.setChartType(self.chart.type);
                        self.chartWrapper.setDataTable(self.chart.data);
                        self.chartWrapper.setView(self.chart.view);
                        self.chartWrapper.setOptions(self.chart.options);
                    }

                    if (typeof (self.formatters) === 'undefined')
                        self.formatters = {};

                        if (typeof (self.chart.formatters) !== 'undefined') {
                            applyFormat("number", google.visualization.NumberFormat, self.chartWrapper.getDataTable());
                            applyFormat("arrow", google.visualization.ArrowFormat, self.chartWrapper.getDataTable());
                            applyFormat("date", google.visualization.DateFormat, self.chartWrapper.getDataTable());
                            applyFormat("bar", google.visualization.BarFormat, self.chartWrapper.getDataTable());
                            applyFormat("color", google.visualization.ColorFormat, self.chartWrapper.getDataTable());
                        }

                        var customFormatters = self.chart.customFormatters;
                        if (typeof (customFormatters) !== 'undefined') {
                            for (var name in customFormatters) {
                                if (customFormatters.hasOwnProperty(name)){
                                    applyFormat(name, customFormatters[name], self.chartWrapper.getDataTable());
                                }
                            }
                        }

                        $timeout(drawChartWrapper);
                    }

                    function watchHandler(){
                        self.chart = $scope.$eval($attrs.chart);
                        drawAsync();
                    }

                    function watchValue(){
                        var chartObject = $scope.$eval($attrs.chart);
                        if (angular.isDefined(chartObject) && angular.isObject(chartObject)){
                            return {
                                customFormatters: chartObject.customFormatters,
                                data: chartObject.data,
                                formatters: chartObject.formatters,
                                options: chartObject.options,
                                type: chartObject.type,
                                view: chartObject.view
                            };
                        }
                    }

                    // This function was written to genericize listener registration
                    // because I plan to implement different collections of listeners
                    // for events on the underlying chart object, and for
                    // directive-level events (ie. beforeDraw).
                    function registerListener(listenerCollection, eventName, listenerFn, listenerObject){
                        // This is the function that will be invoked by the charts API.
                        // Passing the wrapper function allows the use of DI for
                        // for the called function.
                        var listenerWrapper = function (){
                            var locals = {
                                chartWrapper: self.chartWrapper,
                                chart: self.chartWrapper.getChart(),
                                args: arguments
                            };
                            $injector.invoke(listenerFn, listenerObject || this, locals);
                        };

                        if (angular.isDefined(listenerCollection) && angular.isObject(listenerCollection)){
                            if (!angular.isArray(listenerCollection[eventName])){
                                listenerCollection[eventName] = [];
                            }
                            listenerCollection[eventName].push(listenerWrapper);
                            return function (){
                                if (angular.isDefined(listenerWrapper.googleListenerHandle)){
                                    google.visualization.events.removeListener(listenerWrapper.googleListenerHandle);
                                }
                                var fnIndex = listenerCollection[eventName].indexOf(listenerWrapper);
                                listenerCollection[eventName].splice(fnIndex,1);
                                if (listenerCollection[eventName].length === 0){
                                    listenerCollection[eventName] = undefined;
                                }
                            };
                        }
                    }

                    function registerListenersWithGoogle(eventSource, listenerCollection){
                        for (var eventName in listenerCollection){
                            if (listenerCollection.hasOwnProperty(eventName) && angular.isArray(listenerCollection[eventName])){
                                for (var fnIterator = 0; fnIterator < listenerCollection[eventName].length; fnIterator++){
                                    if (angular.isFunction(listenerCollection[eventName][fnIterator])){
                                        listenerCollection[eventName][fnIterator].googleListenerHandle =
                                        google.visualization.events.addListener(eventSource, eventName, listenerCollection[eventName][fnIterator]);
                                    }
                                }
                            }
                        }
                    }

                    function registerChartListener(eventName, listenerFn, listenerObject){
                        return registerListener(chartListeners, eventName, listenerFn, listenerObject);
                    }

                    function registerWrapperListener(eventName, listenerFn, listenerObject){
                        return registerListener(wrapperListeners, eventName, listenerFn, listenerObject);
                    }
            }

            return {
                restrict: 'A',
                scope: false,
                controller: GoogleChartController
            };
        }])

        .directive('onReady', function(){
            return {
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject=['chartWrapper'];
                    function callback(chartWrapper){
                        scope.$apply(function (){
                            scope.$eval(attrs.onReady, {chartWrapper: chartWrapper});
                        });
                    }
                    googleChartController.registerWrapperListener('ready', callback, this);
                }
            };
        })

        .directive('onSelect', function(){
            return {
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject = ['chartWrapper', 'chart'];
                    function callback(chartWrapper, chart){
                        var selectEventRetParams = { selectedItems: chart.getSelection() };
                        // This is for backwards compatibility for people using 'selectedItem' that only wanted the first selection.
                        selectEventRetParams.selectedItem = selectEventRetParams.selectedItems[0];
                        selectEventRetParams.chartWrapper = chartWrapper;
                        selectEventRetParams.chart = chart;
                        scope.$apply(function () {
                            scope.$eval(attrs.onSelect, selectEventRetParams);
                        });
                    }
                    googleChartController.registerWrapperListener('select', callback, this);
                }
            };
        })

        .directive('onError', function(){
            return{
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject = ['chartWrapper', 'chart', 'args'];
                    function callback(chartWrapper, chart, args){
                        var returnValues = {
                            chartWrapper: chartWrapper,
                            chart: chart,
                            args: args,
                            error: args[0],
                            err: args[0],
                            id: args[0].id,
                            message: args[0].message
                        };
                        scope.$apply(function(){
                            scope.$eval(attrs.onError, returnValues);
                        });
                    }
                    googleChartController.registerWrapperListener('error', callback, this);
                }
            };
        })

        .run(['$rootScope', '$window', function ($rootScope, $window) {
            angular.element($window).bind('resize', function () {
                $rootScope.$emit('resizeMsg');
            });
        }]);

})(document, window, window.angular);
<commit_msg>style(GoogleChartController): fix formatting issue caused by editor misinterpretting if statement without curly brackets<commit_after>/**
 * @description Google Chart Api Directive Module for AngularJS
 * @version 0.0.11
 * @author Nicolas Bouillon <nicolas@bouil.org>
 * @author GitHub contributors
 * @license MIT
 * @year 2013
 */
(function (document, window, angular) {
    'use strict';

    angular.module('googlechart', [])

        .value('googleChartApiConfig', {
            version: '1',
            optionalSettings: {
                packages: ['corechart']
            }
        })

        .provider('googleJsapiUrl', function () {
            var protocol = 'https:';
            var url = '//www.google.com/jsapi';

            this.setProtocol = function (newProtocol) {
                protocol = newProtocol;
            };

            this.setUrl = function (newUrl) {
                url = newUrl;
            };

            this.$get = function () {
                return (protocol ? protocol : '') + url;
            };
        })

        .factory('googleChartApiPromise', ['$rootScope', '$q', 'googleChartApiConfig', 'googleJsapiUrl', function ($rootScope, $q, apiConfig, googleJsapiUrl) {
            var apiReady = $q.defer();
            var onLoad = function () {
                // override callback function
                var settings = {
                    callback: function () {
                        var oldCb = apiConfig.optionalSettings.callback;
                        $rootScope.$apply(function () {
                            apiReady.resolve();
                        });

                        if (angular.isFunction(oldCb)) {
                            oldCb.call(this);
                        }
                    }
                };

                settings = angular.extend({}, apiConfig.optionalSettings, settings);

                window.google.load('visualization', apiConfig.version, settings);
            };
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');

            script.setAttribute('type', 'text/javascript');
            script.src = googleJsapiUrl;

            if (script.addEventListener) { // Standard browsers (including IE9+)
                script.addEventListener('load', onLoad, false);
            } else { // IE8 and below
                script.onreadystatechange = function () {
                    if (script.readyState === 'loaded' || script.readyState === 'complete') {
                        script.onreadystatechange = null;
                        onLoad();
                    }
                };
            }

            head.appendChild(script);

            return apiReady.promise;
        }])

        .directive('googleChart', ['$timeout', '$window', '$rootScope', 'googleChartApiPromise', function ($timeout, $window, $rootScope, googleChartApiPromise) {

            GoogleChartController.$inject = ['$scope', '$element', '$attrs', '$injector'];

            function GoogleChartController($scope, $element, $attrs, $injector){
                var self = this;
                var oldChartFormatters = {}, resizeHandler, wrapperListeners = {},
                    chartListeners = {}, innerVisualization = null;
                self.registerChartListener = registerChartListener;
                self.registerWrapperListener = registerWrapperListener;

                init();

                function applyFormat(formatType, FormatClass, dataTable) {
                    var i;
                    if (typeof (self.chart.formatters[formatType]) !== 'undefined') {
                        if (!angular.equals(self.chart.formatters[formatType], oldChartFormatters[formatType])) {
                            oldChartFormatters[formatType] = self.chart.formatters[formatType];
                            self.formatters[formatType] = [];

                            if (formatType === 'color') {
                                for (var cIdx = 0; cIdx < self.chart.formatters[formatType].length; cIdx++) {
                                    var colorFormat = new FormatClass();

                                    for (i = 0; i < self.chart.formatters[formatType][cIdx].formats.length; i++) {
                                        var data = self.chart.formatters[formatType][cIdx].formats[i];

                                        if (typeof (data.fromBgColor) !== 'undefined' && typeof (data.toBgColor) !== 'undefined') {
                                            colorFormat.addGradientRange(data.from, data.to, data.color, data.fromBgColor, data.toBgColor);
                                        } else {
                                            colorFormat.addRange(data.from, data.to, data.color, data.bgcolor);
                                        }
                                    }

                                    self.formatters[formatType].push(colorFormat);
                                }
                            } else {

                                for (i = 0; i < self.chart.formatters[formatType].length; i++) {
                                    self.formatters[formatType].push(new FormatClass(
                                        self.chart.formatters[formatType][i])
                                    );
                                }
                            }
                        }

                        //apply formats to dataTable
                        for (i = 0; i < self.formatters[formatType].length; i++) {
                            if (self.chart.formatters[formatType][i].columnNum < dataTable.getNumberOfColumns()) {
                                self.formatters[formatType][i].format(dataTable, self.chart.formatters[formatType][i].columnNum);
                            }
                        }

                        //Many formatters require HTML tags to display special formatting
                        if (formatType === 'arrow' || formatType === 'bar' || formatType === 'color') {
                            self.chart.options.allowHtml = true;
                        }
                    }
                }

                function cleanup(){
                    resizeHandler();
                }

                function draw() {
                    if (!draw.triggered && (self.chart !== undefined)) {
                        draw.triggered = true;
                        $timeout(setupAndDraw, 0, true);
                    } else if (self.chart !== undefined) {
                        $timeout.cancel(draw.recallTimeout);
                        draw.recallTimeout = $timeout(draw, 10);
                    }
                }

                function drawAsync() {
                    googleChartApiPromise.then(function () {
                        draw();
                    });
                }

                function drawChartWrapper(){
                    $scope.$eval($attrs.beforeDraw, { chartWrapper: $scope.chartWrapper });
                    self.chartWrapper.draw();
                    draw.triggered = false;
                }

                handleError.$inject = ['args'];
                function handleError(args) {
                    var error = args[0];
                    console.log("Chart not displayed due to error: '" + error.message + "' Full error object follows.");
                    console.log(error);
                }

                function handleReady() {
                    self.chart.displayed = true;
                    if (innerVisualization !== self.chartWrapper.getChart()){
                        innerVisualization = self.chartWrapper.getChart();
                        registerListenersWithGoogle(innerVisualization, chartListeners);
                    }
                }

                function init(){
                    /* Watches, to refresh the chart when its data, formatters, options, view,
                    or type change. All other values intentionally disregarded to avoid double
                    calls to the draw function. Please avoid making changes to these objects
                    directly from this directive.*/
                    $scope.$watch(watchValue, watchHandler, true); // true is for deep object equality checking

                    // Redraw the chart if the window is resized
                    resizeHandler = $rootScope.$on('resizeMsg', function () {
                        $timeout(function () {
                            // Not always defined yet in IE so check
                            if (self.chartWrapper) {
                                drawAsync();
                            }
                        });
                    });

                    //Cleanup resize handler.
                    $scope.$on('$destroy', cleanup());

                    registerWrapperListener('error', handleError, self);
                    registerWrapperListener('ready', handleReady, self);
                }

                function setupAndDraw(){
                    if (typeof (self.chartWrapper) === 'undefined') {
                        var chartWrapperArgs = {
                            chartType: self.chart.type,
                            dataTable: self.chart.data,
                            view: self.chart.view,
                            options: self.chart.options,
                            containerId: $element[0]
                        };

                        self.chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
                        registerListenersWithGoogle(self.chartWrapper, wrapperListeners);
                    } else {
                        self.chartWrapper.setChartType(self.chart.type);
                        self.chartWrapper.setDataTable(self.chart.data);
                        self.chartWrapper.setView(self.chart.view);
                        self.chartWrapper.setOptions(self.chart.options);
                    }

                    if (typeof (self.formatters) === 'undefined'){
                        self.formatters = {};
                    }

                    if (typeof (self.chart.formatters) !== 'undefined') {
                        applyFormat("number", google.visualization.NumberFormat, self.chartWrapper.getDataTable());
                        applyFormat("arrow", google.visualization.ArrowFormat, self.chartWrapper.getDataTable());
                        applyFormat("date", google.visualization.DateFormat, self.chartWrapper.getDataTable());
                        applyFormat("bar", google.visualization.BarFormat, self.chartWrapper.getDataTable());
                        applyFormat("color", google.visualization.ColorFormat, self.chartWrapper.getDataTable());
                    }

                    var customFormatters = self.chart.customFormatters;
                    if (typeof (customFormatters) !== 'undefined') {
                        for (var name in customFormatters) {
                            if (customFormatters.hasOwnProperty(name)){
                                applyFormat(name, customFormatters[name], self.chartWrapper.getDataTable());
                            }
                        }
                    }

                    $timeout(drawChartWrapper);
                }

                function watchHandler(){
                    self.chart = $scope.$eval($attrs.chart);
                    drawAsync();
                }

                function watchValue(){
                    var chartObject = $scope.$eval($attrs.chart);
                    if (angular.isDefined(chartObject) && angular.isObject(chartObject)){
                        return {
                            customFormatters: chartObject.customFormatters,
                            data: chartObject.data,
                            formatters: chartObject.formatters,
                            options: chartObject.options,
                            type: chartObject.type,
                            view: chartObject.view
                        };
                    }
                }

                // This function was written to genericize listener registration
                // because I plan to implement different collections of listeners
                // for events on the underlying chart object, and for
                // directive-level events (ie. beforeDraw).
                function registerListener(listenerCollection, eventName, listenerFn, listenerObject){
                    // This is the function that will be invoked by the charts API.
                    // Passing the wrapper function allows the use of DI for
                    // for the called function.
                    var listenerWrapper = function (){
                        var locals = {
                            chartWrapper: self.chartWrapper,
                            chart: self.chartWrapper.getChart(),
                            args: arguments
                        };
                        $injector.invoke(listenerFn, listenerObject || this, locals);
                    };

                    if (angular.isDefined(listenerCollection) && angular.isObject(listenerCollection)){
                        if (!angular.isArray(listenerCollection[eventName])){
                            listenerCollection[eventName] = [];
                        }
                        listenerCollection[eventName].push(listenerWrapper);
                        return function (){
                            if (angular.isDefined(listenerWrapper.googleListenerHandle)){
                                google.visualization.events.removeListener(listenerWrapper.googleListenerHandle);
                            }
                            var fnIndex = listenerCollection[eventName].indexOf(listenerWrapper);
                            listenerCollection[eventName].splice(fnIndex,1);
                            if (listenerCollection[eventName].length === 0){
                                listenerCollection[eventName] = undefined;
                            }
                        };
                    }
                }

                function registerListenersWithGoogle(eventSource, listenerCollection){
                    for (var eventName in listenerCollection){
                        if (listenerCollection.hasOwnProperty(eventName) && angular.isArray(listenerCollection[eventName])){
                            for (var fnIterator = 0; fnIterator < listenerCollection[eventName].length; fnIterator++){
                                if (angular.isFunction(listenerCollection[eventName][fnIterator])){
                                    listenerCollection[eventName][fnIterator].googleListenerHandle =
                                    google.visualization.events.addListener(eventSource, eventName, listenerCollection[eventName][fnIterator]);
                                }
                            }
                        }
                    }
                }

                function registerChartListener(eventName, listenerFn, listenerObject){
                    return registerListener(chartListeners, eventName, listenerFn, listenerObject);
                }

                function registerWrapperListener(eventName, listenerFn, listenerObject){
                    return registerListener(wrapperListeners, eventName, listenerFn, listenerObject);
                }
            }

            return {
                restrict: 'A',
                scope: false,
                controller: GoogleChartController
            };
        }])

        .directive('onReady', function(){
            return {
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject=['chartWrapper'];
                    function callback(chartWrapper){
                        scope.$apply(function (){
                            scope.$eval(attrs.onReady, {chartWrapper: chartWrapper});
                        });
                    }
                    googleChartController.registerWrapperListener('ready', callback, this);
                }
            };
        })

        .directive('onSelect', function(){
            return {
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject = ['chartWrapper', 'chart'];
                    function callback(chartWrapper, chart){
                        var selectEventRetParams = { selectedItems: chart.getSelection() };
                        // This is for backwards compatibility for people using 'selectedItem' that only wanted the first selection.
                        selectEventRetParams.selectedItem = selectEventRetParams.selectedItems[0];
                        selectEventRetParams.chartWrapper = chartWrapper;
                        selectEventRetParams.chart = chart;
                        scope.$apply(function () {
                            scope.$eval(attrs.onSelect, selectEventRetParams);
                        });
                    }
                    googleChartController.registerWrapperListener('select', callback, this);
                }
            };
        })

        .directive('onError', function(){
            return{
                restrict: 'A',
                scope: false,
                require: 'googleChart',
                link: function(scope, element, attrs, googleChartController){
                    callback.$inject = ['chartWrapper', 'chart', 'args'];
                    function callback(chartWrapper, chart, args){
                        var returnValues = {
                            chartWrapper: chartWrapper,
                            chart: chart,
                            args: args,
                            error: args[0],
                            err: args[0],
                            id: args[0].id,
                            message: args[0].message
                        };
                        scope.$apply(function(){
                            scope.$eval(attrs.onError, returnValues);
                        });
                    }
                    googleChartController.registerWrapperListener('error', callback, this);
                }
            };
        })

        .run(['$rootScope', '$window', function ($rootScope, $window) {
            angular.element($window).bind('resize', function () {
                $rootScope.$emit('resizeMsg');
            });
        }]);

})(document, window, window.angular);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { NomadLink } from '../components/link'

class Jobs extends Component {

    counterColumns() {
        return ['Queued', 'Complete', 'Failed', 'Running', 'Starting', 'Lost'];
    }

    getJobStatisticsHeader() {
        let output = [];
        this.counterColumns().forEach((key) => {
            output.push({key}	)
        });

        return output
    }

    getJobStatisticsRow(job) {
        let counter = {
            Queued: 0,
            Complete: 0,
            Failed: 0,
            Running: 0,
            Starting: 0,
            Lost: 0
        }

        let summary = job.JobSummary.Summary;
        Object.keys(summary).forEach(function(taskGroupID) {
            counter.Queued += summary[taskGroupID].Queued;
            counter.Complete += summary[taskGroupID].Complete;
            counter.Failed += summary[taskGroupID].Failed;
            counter.Running += summary[taskGroupID].Running;
            counter.Starting += summary[taskGroupID].Starting;
            counter.Lost += summary[taskGroupID].Lost;
        });

        let output = [];
        this.counterColumns().forEach((key) => {
            output.push({counter[key]}	)
        });

        return output
    }

    render() {
        return (

Jobs

                                        ID
                                        Status
                                        Jobs
                                        Type
                                        Priority
                                        {this.getJobStatisticsHeader()}

                                    {this.props.jobs.map((job) => {
                                        return (

                                                <NomadLink jobId={job.ID} short="true"/>
                                                {job.Status}
                                                {Object.keys(job.JobSummary.Summary).length}
                                                {job.Type}
                                                {job.Priority}
                                                {this.getJobStatisticsRow(job)}

                                        )
                                    })}

        );
    }
}

function mapStateToProps({ jobs }) {
    return { jobs }
}

export default connect(mapStateToProps)(Jobs)
<commit_msg>rename Jobs to Task Groups<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { NomadLink } from '../components/link'

class Jobs extends Component {

    counterColumns() {
        return ['Queued', 'Complete', 'Failed', 'Running', 'Starting', 'Lost'];
    }

    getJobStatisticsHeader() {
        let output = [];
        this.counterColumns().forEach((key) => {
            output.push({key}	)
        });

        return output
    }

    getJobStatisticsRow(job) {
        let counter = {
            Queued: 0,
            Complete: 0,
            Failed: 0,
            Running: 0,
            Starting: 0,
            Lost: 0
        }

        let summary = job.JobSummary.Summary;
        Object.keys(summary).forEach(function(taskGroupID) {
            counter.Queued += summary[taskGroupID].Queued;
            counter.Complete += summary[taskGroupID].Complete;
            counter.Failed += summary[taskGroupID].Failed;
            counter.Running += summary[taskGroupID].Running;
            counter.Starting += summary[taskGroupID].Starting;
            counter.Lost += summary[taskGroupID].Lost;
        });

        let output = [];
        this.counterColumns().forEach((key) => {
            output.push({counter[key]}	)
        });

        return output
    }

    render() {
        return (

Jobs

                                        ID
                                        Status
                                        Type
                                        Priority
                                        Task Groups
                                        {this.getJobStatisticsHeader()}

                                    {this.props.jobs.map((job) => {
                                        return (

                                                <NomadLink jobId={job.ID} short="true"/>
                                                {job.Status}
                                                {job.Type}
                                                {job.Priority}
                                                {Object.keys(job.JobSummary.Summary).length}
                                                {this.getJobStatisticsRow(job)}

                                        )
                                    })}

        );
    }
}

function mapStateToProps({ jobs }) {
    return { jobs }
}

export default connect(mapStateToProps)(Jobs)
<|endoftext|>


<commit_before>"use strict";

var _ = require("underscore");
var util = require("substance-util");
var Document = require("substance-document");
var $$ = require("substance-application").$$;

// Lens.Article
// -----------------

var Article = function(options) {
  options = options || {};

  // Check if format is compatible

  // Extend Schema
  // --------

  options.schema = util.deepclone(Document.schema);

  options.schema.id = "lens-article";
  options.schema.version = "0.3.0";

  // Merge in custom types
  _.each(Article.types, function(type, key) {
    options.schema.types[key] = type;
  });

  // Register annotation types
  _.each(Article.annotations, function(aType, key) {
    options.schema.types[key] = aType;
  });

  // Merge in node types
  _.each(Article.nodeTypes, function(nodeSpec, key) {
    options.schema.types[key] = nodeSpec.Model.type;
  });

  // Merge in custom indexes
  _.each(Article.indexes, function(index, key) {
    options.schema.indexes[key] = index;
  });

  // Call parent constructor
  // --------

  Document.call(this, options);

  // Index for easy mapping from NLM sourceIds to generated nodeIds
  // Needed for resolving figrefs / citationrefs etc.
  this.bySourceId = this.addIndex("by_source_id", {
    types: ["content"],
    property: "source_id"
  });

  this.nodeTypes = Article.nodeTypes;

  // Seed the doc
  // --------

  if (options.seed === undefined) {
    this.create({
      id: "document",
      type: "document",
      guid: options.id, // external global document id
      creator: options.creator,
      created_at: options.created_at,
      views: ["content", "figures", "citations", "info"], // is views really needed on the instance level
      title: "",
      abstract: "",
      authors: []
    });

    // Create views on the doc
    _.each(Article.views, function(view) {
      this.create({
        id: view,
        "type": "view",
        nodes: []
      });
    }, this);
  }
};

// Renders an article
// --------
//

Article.Renderer = function(docCtrl, options) {
  this.docCtrl = docCtrl;

  this.nodeTypes = Article.nodeTypes;

  this.options = options || {};

  // Collect all node views
  this.nodes = {};

  // Build views
  _.each(this.docCtrl.getNodes(), function(node) {
    this.nodes[node.id] = this.createView(node);
  }, this);

};

Article.Renderer.Prototype = function() {

  // Create a node view
  // --------
  //
  // Experimental: using a factory which creates a view for a given node type
  // As we want to be able to reuse views
  // However, as the matter is still under discussion consider the solution here only as provisional.
  // We should create views, not only elements, as we need more, e.g., event listening stuff
  // which needs to be disposed later.

  this.createView = function(node) {
    var NodeView = this.nodeTypes[node.type].View;

    if (!NodeView) {
      throw new Error('Node type "'+node.type+'" not supported');
    }

    // Note: passing the factory to the node views
    // to allow creation of nested views
    var nodeView = new NodeView(node, this);

    // we connect the listener here to avoid to pass the document itself into the nodeView
    nodeView.listenTo(this.docCtrl, "operation:applied", nodeView.onGraphUpdate);
    return nodeView;
  };

  // Render it
  // --------
  //

  this.render = function() {
    _.each(this.nodes, function(nodeView) {
      nodeView.dispose();
    });

    var frag = document.createDocumentFragment();

    var docNodes = this.docCtrl.container.getTopLevelNodes();
    _.each(docNodes, function(n) {
      this.renderNode(n, frag);
    }, this);

    return frag;
  };

  this.renderNode = function(n, frag) {
    var view = this.createView(n);
    frag.appendChild(view.render().el);

    if (n.type === "heading") {
      view.el.appendChild($$('a.top', {
        href: "#",
        html: ''
      }));
    }

    // Lets you customize the resulting DOM sticking on the el element
    // Example: Lens focus controls
    if (this.options.afterRender) this.options.afterRender(this.docCtrl, view);
  };

};

Article.Renderer.prototype = new Article.Renderer.Prototype();

Article.Prototype = function() {
  this.fromSnapshot = function(data, options) {
    return Article.fromSnapshot(data, options);
  };

  // For a given NLM source id, returns the corresponding node in the document graph
  // --------

  this.getNodeBySourceId = function(sourceId) {
    var nodes = this.bySourceId.get(sourceId);
    var nodeId = Object.keys(nodes)[0];
    var node = nodes[nodeId];
    return node;
  };
};

// Factory method
// --------
//
// TODO: Ensure the snapshot doesn't get chronicled

Article.fromSnapshot = function(data, options) {
  options = options || {};
  options.seed = data;
  return new Article(options);
};

// Define available views
// --------

Article.views = ["content", "figures", "citations", "definitions", "info"];

// Register node types
// --------

Article.nodeTypes = require("./nodes");

// Define annotation types
// --------

Article.annotations = {

  "strong": {
    "parent": "annotation",
    "properties": {
    }
  },

  "emphasis": {
    "properties": {
    },
    "parent": "annotation"
  },

  "subscript": {
    "properties": {
    },
    "parent": "annotation"
  },

  "superscript": {
    "properties": {
    },
    "parent": "annotation"
  },

  "underline": {
    "properties": {
    },
    "parent": "annotation"
  },

  "code": {
    "parent": "annotation",
    "properties": {
    }
  },

  "link": {
    "parent": "annotation",
    "properties": {
      "url": "string"
    }
  },

  "idea": {
    "parent": "annotation",
    "properties": {
    }
  },

  "error": {
    "parent": "annotation",
    "properties": {
    }
  },

  "question": {
    "parent": "annotation",
    "properties": {
    }
  },

  "resource_reference": {
    "parent": "annotation",
    "properties": {
      "target": "node"
    }
  },

  // Dark blueish contributor references in the cover
  // They should work everywhere else too

  "contributor_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "contributor"
    }
  },

  // Greenish figure references in the text

  "figure_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "figure"
    }
  },

  // Blueish citation references in the text

  "citation_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "content"
    }
  },

  "definition_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "content"
    }
  },

  "cross_reference": {
    "parent": "annotation",
    "properties": {
      "target": "content"
    }
  },

  "formula_reference": {
    "parent": "annotation",
    "properties": {
      "target": "content"
    }
  },

  "author_callout": {
    "parent": "annotation",
    "properties": {
      "style": "string"
    }
  }

};

// Custom type definitions
// --------
//
// Holds comments

Article.types = {

  // Abstarct Annotation Node
  // --------

  "annotation": {
    "properties": {
      "path": ["array", "string"], // -> e.g. ["text_1", "content"]
      "range": "object"
    }
  },

  // Abstract Figure Type
  // --------

  "figure": {
    "properties": {
    }
  },

  // "file": {
  //   "properties": {
  //   }
  // },

  "institution": {
    "properties": {
    }
  },

  "email": {
    "properties": {
    }
  },

  "funding": {
    "properties": {
    }
  },

  "caption": {
    "properties": {
    }
  },

  // Abstract Citation Type
  // --------

  "citation": {
    "properties": {
    }
  },

  // Document
  // --------

  "document": {
    "properties": {
      "views": ["array", "view"],
      "guid": "string",
      "creator": "string",
      "title": "string",
      "authors": ["array", "contributor"],
      "on_behalf_of": "string",
      "abstract": "string"
    }
  },

  // Comments
  // --------

  "comment": {
    "properties": {
      "content": "string",
      "created_at": "string", // should be date
      "creator": "string", // should be date
      "node": "node" // references either a content node or annotation
    }
  }
};

// From article definitions generate a nice reference document
// --------
//

var ARTICLE_DOC_SEED = {
  "id": "lens_article",
  "nodes": {
    "document": {
      "type": "document",
      "id": "document",
      "views": [
        "content"
      ],
      "title": "The Anatomy of a Lens Article",
      "authors": ["contributor_1", "contributor_2", "contributor_3"],
      "guid": "lens_article"
    },

    "content": {
      "type": "view",
      "id": "content",
      "nodes": [
        "cover",
      ]
    },

    "cover": {
      "id": "cover",
      "type": "cover"
    },

    "contributor_1": {
      "id": "contributor_1",
      "type": "contributor",
      "name": "Michael Aufreiter"
    },

    "contributor_2": {
      "id": "contributor_2",
      "type": "contributor",
      "name": "Ivan Grubisic"
    },

    "contributor_3": {
      "id": "contributor_3",
      "type": "contributor",
      "name": "Rebecca Close"
    }
  }
};

Article.describe = function() {
  var doc = new Article({seed: ARTICLE_DOC_SEED});

  var id = 0;

  _.each(Article.nodeTypes, function(nodeType) {
    nodeType = nodeType.Model;

    // Create a heading for each node type
    var headingId = "heading_"+nodeType.type.id;

    doc.create({
      id: headingId,
      type: "heading",
      content: nodeType.description.name,
      level: 1
    });

    // Turn remarks and description into an introduction paragraph
    var introText = nodeType.description.remarks.join(' ');
    var introId = "text_"+nodeType.type.id+"_intro";

    doc.create({
      id: introId,
      type: "text",
      content: introText,
    });

    // Show it in the content view
    doc.show("content", [headingId, introId], -1);

    // Include property description
    // --------
    //

    doc.create({
      id: headingId+"_properties",
      type: "text",
      content: nodeType.description.name+ " uses the following properties:"
    });

    doc.show("content", [headingId+"_properties"], -1);

    var items = [];

    _.each(nodeType.description.properties, function(propertyDescr, key) {

      var listItemId = "text_" + (++id);
      doc.create({
        id: listItemId,
        type: "text",
        content: key +": " + propertyDescr
      });

      // Create code annotation for the propertyName
      doc.create({
        "id": id+"_annotation",
        "type": "code",
        "path": [listItemId, "content"],
        "range":[0, key.length]
      });

      items.push(listItemId);
    });

    // Create list
    doc.create({
      id: headingId+"_property_list",
      type: "list",
      items: items,
      ordered: false
    });

    // And show it
    doc.show("content", [headingId+"_property_list"], -1);

    // Include example
    // --------
    //

    doc.create({
      id: headingId+"_example",
      type: "text",
      content: "Here's an example:"
    });

    doc.create({
      id: headingId+"_example_codeblock",
      type: "codeblock",
      content: JSON.stringify(nodeType.example, null, '  '),
    });

    doc.show("content", [headingId+"_example", headingId+"_example_codeblock"], -1);
  });

  return doc;
};

Article.Prototype.prototype = Document.prototype;
Article.prototype = new Article.Prototype();
Article.prototype.constructor = Article;

// Add convenience accessors for builtin document attributes
Object.defineProperties(Article.prototype, {
  id: {
    get: function () {
      return this.get("document").guid;
    },
    set: function(id) {
      this.get("document").guid = id;
    }
  },
  creator: {
    get: function () {
      return this.get("document").creator;
    },
    set: function(creator) {
      this.get("document").creator = creator;
    }
  },
  created_at: {
    get: function () {
      return this.get("document").created_at;
    },
    set: function(created_at) {
      this.get("document").created_at = created_at;
    }
  },
  title: {
    get: function () {

      return this.get("document").title;
    },
    set: function(title) {
      this.get("document").title = title;
    }
  },
  abstract: {
    get: function () {
      return this.get("document").abstract;
    },
    set: function(abstract) {
      this.get("document").abstract = abstract;
    }
  },
  on_behalf_of: {
    get: function () {
      return this.get("document").on_behalf_of;
    },
    set: function(on_behalf_of) {
      this.get("document").on_behalf_of = on_behalf_of;
    }
  },
  authors: {
    get: function () {
      var docNode = this.get("document");
      if (docNode.authors) {
        return _.map(docNode.authors, function(contributorId) {
          return this.get(contributorId);
        }, this);
      } else {
        return "";
      }
    },
    set: function(val) {
      var docNode = this.get("document");
      docNode.authors = _.clone(val);
    }
  },
  views: {
    get: function () {
      // Note: returing a copy to avoid inadvertent changes
      return this.get("document").views.slice(0);
    }
  },
});

module.exports = Article;
<commit_msg>Use defined list of views.<commit_after>"use strict";

var _ = require("underscore");
var util = require("substance-util");
var Document = require("substance-document");
var $$ = require("substance-application").$$;

// Lens.Article
// -----------------

var Article = function(options) {
  options = options || {};

  // Check if format is compatible

  // Extend Schema
  // --------

  options.schema = util.deepclone(Document.schema);

  options.schema.id = "lens-article";
  options.schema.version = "0.3.0";

  // Merge in custom types
  _.each(Article.types, function(type, key) {
    options.schema.types[key] = type;
  });

  // Register annotation types
  _.each(Article.annotations, function(aType, key) {
    options.schema.types[key] = aType;
  });

  // Merge in node types
  _.each(Article.nodeTypes, function(nodeSpec, key) {
    options.schema.types[key] = nodeSpec.Model.type;
  });

  // Merge in custom indexes
  _.each(Article.indexes, function(index, key) {
    options.schema.indexes[key] = index;
  });

  // Call parent constructor
  // --------

  Document.call(this, options);

  // Index for easy mapping from NLM sourceIds to generated nodeIds
  // Needed for resolving figrefs / citationrefs etc.
  this.bySourceId = this.addIndex("by_source_id", {
    types: ["content"],
    property: "source_id"
  });

  this.nodeTypes = Article.nodeTypes;

  // Seed the doc
  // --------

  if (options.seed === undefined) {
    this.create({
      id: "document",
      type: "document",
      guid: options.id, // external global document id
      creator: options.creator,
      created_at: options.created_at,
      views: Article.views, // is views really needed on the instance level
      title: "",
      abstract: "",
      authors: []
    });

    // Create views on the doc
    _.each(Article.views, function(view) {
      this.create({
        id: view,
        "type": "view",
        nodes: []
      });
    }, this);
  }
};

// Renders an article
// --------
//

Article.Renderer = function(docCtrl, options) {
  this.docCtrl = docCtrl;

  this.nodeTypes = Article.nodeTypes;

  this.options = options || {};

  // Collect all node views
  this.nodes = {};

  // Build views
  _.each(this.docCtrl.getNodes(), function(node) {
    this.nodes[node.id] = this.createView(node);
  }, this);

};

Article.Renderer.Prototype = function() {

  // Create a node view
  // --------
  //
  // Experimental: using a factory which creates a view for a given node type
  // As we want to be able to reuse views
  // However, as the matter is still under discussion consider the solution here only as provisional.
  // We should create views, not only elements, as we need more, e.g., event listening stuff
  // which needs to be disposed later.

  this.createView = function(node) {
    var NodeView = this.nodeTypes[node.type].View;

    if (!NodeView) {
      throw new Error('Node type "'+node.type+'" not supported');
    }

    // Note: passing the factory to the node views
    // to allow creation of nested views
    var nodeView = new NodeView(node, this);

    // we connect the listener here to avoid to pass the document itself into the nodeView
    nodeView.listenTo(this.docCtrl, "operation:applied", nodeView.onGraphUpdate);
    return nodeView;
  };

  // Render it
  // --------
  //

  this.render = function() {
    _.each(this.nodes, function(nodeView) {
      nodeView.dispose();
    });

    var frag = document.createDocumentFragment();

    var docNodes = this.docCtrl.container.getTopLevelNodes();
    _.each(docNodes, function(n) {
      this.renderNode(n, frag);
    }, this);

    return frag;
  };

  this.renderNode = function(n, frag) {
    var view = this.createView(n);
    frag.appendChild(view.render().el);

    if (n.type === "heading") {
      view.el.appendChild($$('a.top', {
        href: "#",
        html: ''
      }));
    }

    // Lets you customize the resulting DOM sticking on the el element
    // Example: Lens focus controls
    if (this.options.afterRender) this.options.afterRender(this.docCtrl, view);
  };

};

Article.Renderer.prototype = new Article.Renderer.Prototype();

Article.Prototype = function() {
  this.fromSnapshot = function(data, options) {
    return Article.fromSnapshot(data, options);
  };

  // For a given NLM source id, returns the corresponding node in the document graph
  // --------

  this.getNodeBySourceId = function(sourceId) {
    var nodes = this.bySourceId.get(sourceId);
    var nodeId = Object.keys(nodes)[0];
    var node = nodes[nodeId];
    return node;
  };
};

// Factory method
// --------
//
// TODO: Ensure the snapshot doesn't get chronicled

Article.fromSnapshot = function(data, options) {
  options = options || {};
  options.seed = data;
  return new Article(options);
};

// Define available views
// --------

Article.views = ["content", "figures", "citations", "definitions", "info"];

// Register node types
// --------

Article.nodeTypes = require("./nodes");

// Define annotation types
// --------

Article.annotations = {

  "strong": {
    "parent": "annotation",
    "properties": {
    }
  },

  "emphasis": {
    "properties": {
    },
    "parent": "annotation"
  },

  "subscript": {
    "properties": {
    },
    "parent": "annotation"
  },

  "superscript": {
    "properties": {
    },
    "parent": "annotation"
  },

  "underline": {
    "properties": {
    },
    "parent": "annotation"
  },

  "code": {
    "parent": "annotation",
    "properties": {
    }
  },

  "link": {
    "parent": "annotation",
    "properties": {
      "url": "string"
    }
  },

  "idea": {
    "parent": "annotation",
    "properties": {
    }
  },

  "error": {
    "parent": "annotation",
    "properties": {
    }
  },

  "question": {
    "parent": "annotation",
    "properties": {
    }
  },

  "resource_reference": {
    "parent": "annotation",
    "properties": {
      "target": "node"
    }
  },

  // Dark blueish contributor references in the cover
  // They should work everywhere else too

  "contributor_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "contributor"
    }
  },

  // Greenish figure references in the text

  "figure_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "figure"
    }
  },

  // Blueish citation references in the text

  "citation_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "content"
    }
  },

  "definition_reference": {
    "parent": "resource_reference",
    "properties": {
      "target": "content"
    }
  },

  "cross_reference": {
    "parent": "annotation",
    "properties": {
      "target": "content"
    }
  },

  "formula_reference": {
    "parent": "annotation",
    "properties": {
      "target": "content"
    }
  },

  "author_callout": {
    "parent": "annotation",
    "properties": {
      "style": "string"
    }
  }

};

// Custom type definitions
// --------
//
// Holds comments

Article.types = {

  // Abstarct Annotation Node
  // --------

  "annotation": {
    "properties": {
      "path": ["array", "string"], // -> e.g. ["text_1", "content"]
      "range": "object"
    }
  },

  // Abstract Figure Type
  // --------

  "figure": {
    "properties": {
    }
  },

  // "file": {
  //   "properties": {
  //   }
  // },

  "institution": {
    "properties": {
    }
  },

  "email": {
    "properties": {
    }
  },

  "funding": {
    "properties": {
    }
  },

  "caption": {
    "properties": {
    }
  },

  // Abstract Citation Type
  // --------

  "citation": {
    "properties": {
    }
  },

  // Document
  // --------

  "document": {
    "properties": {
      "views": ["array", "view"],
      "guid": "string",
      "creator": "string",
      "title": "string",
      "authors": ["array", "contributor"],
      "on_behalf_of": "string",
      "abstract": "string"
    }
  },

  // Comments
  // --------

  "comment": {
    "properties": {
      "content": "string",
      "created_at": "string", // should be date
      "creator": "string", // should be date
      "node": "node" // references either a content node or annotation
    }
  }
};

// From article definitions generate a nice reference document
// --------
//

var ARTICLE_DOC_SEED = {
  "id": "lens_article",
  "nodes": {
    "document": {
      "type": "document",
      "id": "document",
      "views": [
        "content"
      ],
      "title": "The Anatomy of a Lens Article",
      "authors": ["contributor_1", "contributor_2", "contributor_3"],
      "guid": "lens_article"
    },

    "content": {
      "type": "view",
      "id": "content",
      "nodes": [
        "cover",
      ]
    },

    "cover": {
      "id": "cover",
      "type": "cover"
    },

    "contributor_1": {
      "id": "contributor_1",
      "type": "contributor",
      "name": "Michael Aufreiter"
    },

    "contributor_2": {
      "id": "contributor_2",
      "type": "contributor",
      "name": "Ivan Grubisic"
    },

    "contributor_3": {
      "id": "contributor_3",
      "type": "contributor",
      "name": "Rebecca Close"
    }
  }
};

Article.describe = function() {
  var doc = new Article({seed: ARTICLE_DOC_SEED});

  var id = 0;

  _.each(Article.nodeTypes, function(nodeType) {
    nodeType = nodeType.Model;

    // Create a heading for each node type
    var headingId = "heading_"+nodeType.type.id;

    doc.create({
      id: headingId,
      type: "heading",
      content: nodeType.description.name,
      level: 1
    });

    // Turn remarks and description into an introduction paragraph
    var introText = nodeType.description.remarks.join(' ');
    var introId = "text_"+nodeType.type.id+"_intro";

    doc.create({
      id: introId,
      type: "text",
      content: introText,
    });

    // Show it in the content view
    doc.show("content", [headingId, introId], -1);

    // Include property description
    // --------
    //

    doc.create({
      id: headingId+"_properties",
      type: "text",
      content: nodeType.description.name+ " uses the following properties:"
    });

    doc.show("content", [headingId+"_properties"], -1);

    var items = [];

    _.each(nodeType.description.properties, function(propertyDescr, key) {

      var listItemId = "text_" + (++id);
      doc.create({
        id: listItemId,
        type: "text",
        content: key +": " + propertyDescr
      });

      // Create code annotation for the propertyName
      doc.create({
        "id": id+"_annotation",
        "type": "code",
        "path": [listItemId, "content"],
        "range":[0, key.length]
      });

      items.push(listItemId);
    });

    // Create list
    doc.create({
      id: headingId+"_property_list",
      type: "list",
      items: items,
      ordered: false
    });

    // And show it
    doc.show("content", [headingId+"_property_list"], -1);

    // Include example
    // --------
    //

    doc.create({
      id: headingId+"_example",
      type: "text",
      content: "Here's an example:"
    });

    doc.create({
      id: headingId+"_example_codeblock",
      type: "codeblock",
      content: JSON.stringify(nodeType.example, null, '  '),
    });

    doc.show("content", [headingId+"_example", headingId+"_example_codeblock"], -1);
  });

  return doc;
};

Article.Prototype.prototype = Document.prototype;
Article.prototype = new Article.Prototype();
Article.prototype.constructor = Article;

// Add convenience accessors for builtin document attributes
Object.defineProperties(Article.prototype, {
  id: {
    get: function () {
      return this.get("document").guid;
    },
    set: function(id) {
      this.get("document").guid = id;
    }
  },
  creator: {
    get: function () {
      return this.get("document").creator;
    },
    set: function(creator) {
      this.get("document").creator = creator;
    }
  },
  created_at: {
    get: function () {
      return this.get("document").created_at;
    },
    set: function(created_at) {
      this.get("document").created_at = created_at;
    }
  },
  title: {
    get: function () {

      return this.get("document").title;
    },
    set: function(title) {
      this.get("document").title = title;
    }
  },
  abstract: {
    get: function () {
      return this.get("document").abstract;
    },
    set: function(abstract) {
      this.get("document").abstract = abstract;
    }
  },
  on_behalf_of: {
    get: function () {
      return this.get("document").on_behalf_of;
    },
    set: function(on_behalf_of) {
      this.get("document").on_behalf_of = on_behalf_of;
    }
  },
  authors: {
    get: function () {
      var docNode = this.get("document");
      if (docNode.authors) {
        return _.map(docNode.authors, function(contributorId) {
          return this.get(contributorId);
        }, this);
      } else {
        return "";
      }
    },
    set: function(val) {
      var docNode = this.get("document");
      docNode.authors = _.clone(val);
    }
  },
  views: {
    get: function () {
      // Note: returing a copy to avoid inadvertent changes
      return this.get("document").views.slice(0);
    }
  },
});

module.exports = Article;
<|endoftext|>


<commit_before><commit_msg>Include format_time.js from previous commit.<commit_after>export function formatTime (seconds) {
  let date = new Date(seconds * 1000);
  let hh = date.getUTCHours();
  let mm = date.getUTCMinutes();
  let ss = date.getSeconds();

  if (mm < 10) {
    mm = '0' + mm;
  }
  if (ss < 10) {
    ss = '0' + ss;
  }

  if (hh > 0) {
    if (hh < 10) {
      hh = '0' + hh;
    }

    return hh + ':' + mm + ':' + ss;
  }

  return mm + ':' + ss;
}<|endoftext|>


<commit_before>"use strict";

const Module = require("module");
const path = require("path");

require("css.escape");
const Handlebars = require("handlebars/runtime");
const _ = require("lodash");

const handlebars = require("./handlebars");
const stub_i18n = require("./i18n");
const namespace = require("./namespace");
const test = require("./test");
const {make_zblueslip} = require("./zblueslip");

require("@babel/register")({
    extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"],
    only: [
        new RegExp("^" + _.escapeRegExp(path.resolve(__dirname, "../../static/js") + path.sep)),
        new RegExp(
            "^" + _.escapeRegExp(path.resolve(__dirname, "../../static/shared/js") + path.sep),
        ),
    ],
    plugins: ["rewire-ts"],
});

// Create a helper function to avoid sneaky delays in tests.
function immediate(f) {
    return () => f();
}

// Find the files we need to run.
const files = process.argv.slice(2);
if (files.length === 0) {
    throw new Error("No tests found");
}

// Set up our namespace helpers.
const window = new Proxy(global, {
    set: (obj, prop, value) => {
        namespace.set_global(prop, value);
        return true;
    },
});

// Set up Handlebars
handlebars.hook_require();

const noop = function () {};

// Set up fake module.hot
Module.prototype.hot = {
    accept: noop,
};

function short_tb(tb) {
    const lines = tb.split("\n");

    const i = lines.findIndex(
        (line) => line.includes("run_test") || line.includes("run_one_module"),
    );

    if (i === -1) {
        return tb;
    }

    return lines.splice(0, i + 1).join("\n") + "\n(...)\n";
}

function run_one_module(file) {
    console.info("running test " + path.basename(file, ".js"));
    test.set_current_file_name(file);
    require(file);
}

test.set_verbose(files.length === 1);

try {
    for (const file of files) {
        namespace.set_global("window", window);
        namespace.set_global("to_$", () => window);
        namespace.set_global("location", {
            hash: "#",
        });
        namespace.set_global("setTimeout", noop);
        namespace.set_global("setInterval", noop);
        _.throttle = immediate;
        _.debounce = immediate;

        const blueslip = namespace.set_global("blueslip", make_zblueslip());
        namespace.set_global("i18n", stub_i18n);
        namespace.clear_zulip_refs();

        run_one_module(file);

        if (blueslip.reset) {
            blueslip.reset();
        }

        namespace.restore();
        Handlebars.HandlebarsEnvironment.call(Handlebars);
    }
} catch (error) {
    if (error.stack) {
        console.info(short_tb(error.stack));
    } else {
        console.info(error);
    }
    process.exit(1);
}
<commit_msg>zjsunit: Show more of the traceback.<commit_after>"use strict";

const Module = require("module");
const path = require("path");

require("css.escape");
const Handlebars = require("handlebars/runtime");
const _ = require("lodash");

const handlebars = require("./handlebars");
const stub_i18n = require("./i18n");
const namespace = require("./namespace");
const test = require("./test");
const {make_zblueslip} = require("./zblueslip");

require("@babel/register")({
    extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"],
    only: [
        new RegExp("^" + _.escapeRegExp(path.resolve(__dirname, "../../static/js") + path.sep)),
        new RegExp(
            "^" + _.escapeRegExp(path.resolve(__dirname, "../../static/shared/js") + path.sep),
        ),
    ],
    plugins: ["rewire-ts"],
});

// Create a helper function to avoid sneaky delays in tests.
function immediate(f) {
    return () => f();
}

// Find the files we need to run.
const files = process.argv.slice(2);
if (files.length === 0) {
    throw new Error("No tests found");
}

// Set up our namespace helpers.
const window = new Proxy(global, {
    set: (obj, prop, value) => {
        namespace.set_global(prop, value);
        return true;
    },
});

// Set up Handlebars
handlebars.hook_require();

const noop = function () {};

// Set up fake module.hot
Module.prototype.hot = {
    accept: noop,
};

function short_tb(tb) {
    const lines = tb.split("\n");

    const i = lines.findIndex((line) => line.includes("Module._compile"));

    if (i === -1) {
        return tb;
    }

    return lines.splice(0, i + 1).join("\n") + "\n(...)\n";
}

function run_one_module(file) {
    console.info("running test " + path.basename(file, ".js"));
    test.set_current_file_name(file);
    require(file);
}

test.set_verbose(files.length === 1);

try {
    for (const file of files) {
        namespace.set_global("window", window);
        namespace.set_global("to_$", () => window);
        namespace.set_global("location", {
            hash: "#",
        });
        namespace.set_global("setTimeout", noop);
        namespace.set_global("setInterval", noop);
        _.throttle = immediate;
        _.debounce = immediate;

        const blueslip = namespace.set_global("blueslip", make_zblueslip());
        namespace.set_global("i18n", stub_i18n);
        namespace.clear_zulip_refs();

        run_one_module(file);

        if (blueslip.reset) {
            blueslip.reset();
        }

        namespace.restore();
        Handlebars.HandlebarsEnvironment.call(Handlebars);
    }
} catch (error) {
    if (error.stack) {
        console.info(short_tb(error.stack));
    } else {
        console.info(error);
    }
    process.exit(1);
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.pages['activity'].onload = function(wrapper) {
	wn.ui.make_app_page({
		parent: wrapper,
		title: "Activity",
		single_column: true
	})
	wrapper.appframe.add_module_icon("Activity");

	var list = new wn.ui.Listing({
		appframe: wrapper.appframe,
		method: 'home.page.activity.activity.get_feed',
		parent: $(wrapper).find(".layout-main"),
		render_row: function(row, data) {
			new erpnext.ActivityFeed(row, data);
		}
	});
	list.run();

	// Build Report Button
	if(wn.boot.profile.can_get_report.indexOf("Feed")!=-1) {
		wrapper.appframe.add_button('Build Report', function() {
			wn.set_route('Report', "Feed");
		}, 'icon-th')
	}
}

erpnext.last_feed_date = false;
erpnext.ActivityFeed = Class.extend({
	init: function(row, data) {
		this.scrub_data(data);
		this.add_date_separator(row, data);
		$(row).append(repl('
\
			 \
			%(feed_type)s\
			%(link)s %(subject)s %(by)s
', data));
	},
	scrub_data: function(data) {
		data.by = wn.user_info(data.owner).fullname;
		data.imgsrc = wn.utils.get_file_link(wn.user_info(data.owner).image);

		// feedtype
		if(!data.feed_type) {
			data.feed_type = wn._(data.doc_type);
			data.add_class = "label-info";
			data.onclick = repl('onclick="window.location.href=\'#!List/%(feed_type)s\';"', data)
		}

		// color for comment
		if(data.feed_type=='Comment') {
			data.add_class = "label-important";
		}

		if(data.feed_type=='Assignment') {
			data.add_class = "label-warning";
		}

		// link
		if(data.doc_name && data.feed_type!='Login') {
			data.link = wn.format(data.doc_name, {"fieldtype":"Link", "options":data.doc_type})
		} else {
			data.link = "";
		}
	},
	add_date_separator: function(row, data) {
		var date = dateutil.str_to_obj(data.modified);
		var last = erpnext.last_feed_date;

		if((last && dateutil.obj_to_str(last) != dateutil.obj_to_str(date)) || (!last)) {
			var diff = dateutil.get_day_diff(new Date(), date);
			if(diff < 1) {
				pdate = 'Today';
			} else if(diff < 2) {
				pdate = 'Yesterday';
			} else {
				pdate = dateutil.global_date_format(date);
			}
			$(row).html(repl('
%(date)s
', {date: pdate}));
		}
		erpnext.last_feed_date = date;
	}
})<commit_msg>[fix] [minor] feed label<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.pages['activity'].onload = function(wrapper) {
	wn.ui.make_app_page({
		parent: wrapper,
		title: "Activity",
		single_column: true
	})
	wrapper.appframe.add_module_icon("Activity");

	var list = new wn.ui.Listing({
		appframe: wrapper.appframe,
		method: 'home.page.activity.activity.get_feed',
		parent: $(wrapper).find(".layout-main"),
		render_row: function(row, data) {
			new erpnext.ActivityFeed(row, data);
		}
	});
	list.run();

	// Build Report Button
	if(wn.boot.profile.can_get_report.indexOf("Feed")!=-1) {
		wrapper.appframe.add_button('Build Report', function() {
			wn.set_route('Report', "Feed");
		}, 'icon-th')
	}
}

erpnext.last_feed_date = false;
erpnext.ActivityFeed = Class.extend({
	init: function(row, data) {
		this.scrub_data(data);
		this.add_date_separator(row, data);
		if(!data.add_class) data.add_class = "label-default";
		$(row).append(repl('
\
			 \
			%(feed_type)s\
			%(link)s %(subject)s %(by)s
', data));
	},
	scrub_data: function(data) {
		data.by = wn.user_info(data.owner).fullname;
		data.imgsrc = wn.utils.get_file_link(wn.user_info(data.owner).image);

		// feedtype
		if(!data.feed_type) {
			data.feed_type = wn._(data.doc_type);
			data.add_class = "label-info";
			data.onclick = repl('onclick="window.location.href=\'#!List/%(feed_type)s\';"', data)
		}

		// color for comment
		if(data.feed_type=='Comment') {
			data.add_class = "label-danger";
		}

		if(data.feed_type=='Assignment') {
			data.add_class = "label-warning";
		}

		// link
		if(data.doc_name && data.feed_type!='Login') {
			data.link = wn.format(data.doc_name, {"fieldtype":"Link", "options":data.doc_type})
		} else {
			data.link = "";
		}
	},
	add_date_separator: function(row, data) {
		var date = dateutil.str_to_obj(data.modified);
		var last = erpnext.last_feed_date;

		if((last && dateutil.obj_to_str(last) != dateutil.obj_to_str(date)) || (!last)) {
			var diff = dateutil.get_day_diff(new Date(), date);
			if(diff < 1) {
				pdate = 'Today';
			} else if(diff < 2) {
				pdate = 'Yesterday';
			} else {
				pdate = dateutil.global_date_format(date);
			}
			$(row).html(repl('
%(date)s
', {date: pdate}));
		}
		erpnext.last_feed_date = date;
	}
})<|endoftext|>


<commit_before>var fu_curr_files;
var fu_curr_file = 0;
var fu_curr_offset = 0;
var fu_curr_size;
var fu_total_size;
var fu_total_uploaded = 0;
const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
var incomplete_files = [];
var pending_uploads = [];
var chunk_multiplier = 1;

function init_uploader () {
  document.querySelector("#file_upload").addEventListener('change', function(e) {
      fu_curr_files = this.files;
      start_upload();
    }, false);
}

function start_upload () {
  if (fu_curr_files) {
    if (fu_curr_files.length > fu_curr_file) {

      var blob = fu_curr_files[fu_curr_file];
      const SIZE = blob.size;
      if (SIZE > 1024 * 1024 * 100) {
	chunk_multiplier = 10;
      } else {
	chunk_multiplier = 1;
      }
      fu_curr_size = blob.size;
      fu_total_size = 0;
      for (var i=0; i<fu_curr_files.length; i++) {
	fu_total_size += fu_curr_files[i].size;
      }

      var start = fu_curr_offset;
      if (incomplete_files[blob.name]) {
	alert("partial upload of file '"+blob.name+"' detected, resuming upload.");
	start = incomplete_files[blob.name];
	incomplete_files[blob.name] = null;
      }
      var end = start + (BYTES_PER_CHUNK * chunk_multiplier);
      var chunk;
      document.getElementById('progress_display').style.display = "";

      if (start < SIZE) {
	if ('mozSlice' in blob) {
	  chunk = blob.mozSlice(start, end);
	} else {
	  chunk = blob.webkitSlice(start, end);
	}

	document.getElementById("upload_progress").style.display = "";
	document.querySelector("#upload_status").innerHTML = "current file " + blob.name + "
file " + (fu_curr_file+1) + " of " + fu_curr_files.length + "
size " + pretty_size(blob.size) + "
type " + pretty_type(blob.type);
	fu_curr_offset = end;
	upload(chunk, blob.name);
      } else {
	var cfiles = document.getElementById("uploaded_files");
	cfiles.style.display = "";
	if (fu_curr_file == 0) {
	  cfiles.innerHTML = "
completed files
";
	}
	cfiles.innerHTML += "
"+blob.name+" ("+pretty_size(blob.size)+")
";

	fu_total_uploaded += fu_curr_files[fu_curr_file].size;
	fu_curr_file++;
	fu_curr_offset = 0;
	update_inbox(null, null, "upload_complete");
	start_upload();
      }
    } else {
      var cfiles = document.getElementById("uploaded_files");
      cfiles.style.display = "";
      if (fu_curr_file == 0) {
	cfiles.innerHTML = "
completed files
";
      }
      cfiles.innerHTML += "
upload complete
";
      document.getElementById('progress_display').style.display = "none";

      fu_curr_files = null;
      fu_curr_file = 0;
      fu_curr_offset = 0;
      fu_total_uploaded = 0;
      document.querySelector("#prog1").value = 100;
      document.querySelector("#prog2").value = 100;
    }
  }
}

function upload(blobOrFile, fn) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', "upload.cgi", true);
  xhr.onload = function(e) {
    if (this.status == 200) {
      console.log(this.response);
    }
  };
  var progressBar1 = document.querySelector("#prog1");
  var progressBar2 = document.querySelector("#prog2");
  xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
      progressBar1.value = ((e.loaded + fu_curr_offset + fu_total_uploaded - (BYTES_PER_CHUNK * chunk_multiplier)) / fu_total_size) * 100;
      progressBar2.value = ((e.loaded + fu_curr_offset - (BYTES_PER_CHUNK * chunk_multiplier)) / fu_curr_size) * 100;
    }
  };
  xhr.addEventListener("load", uploadComplete, false);
  xhr.addEventListener("error", uploadFailed, false);
  xhr.addEventListener("abort", uploadCanceled, false);

  var fd = new FormData();
  fd.append("upload_file", blobOrFile);
  fd.append('filename', fn);
  fd.append('auth', auth);
  if (fu_curr_offset >= fu_curr_size) {
    fd.append('last_chunk', 1);
  }

  xhr.send(fd);
  pending_uploads[pending_uploads.length] = xhr;
}

function cancel_upload () {
  if (confirm('Do you really want to cancel the current upload?')) {
    for (var i=0; i<pending_uploads.length; i++) {
      pending_uploads[i].abort();
    }
    fu_curr_files = null;
    fu_curr_file = 0;
    fu_curr_offset = 0;
    fu_total_uploaded = 0;
  }
}

function uploadComplete (evt) {
    var md5 = this.responseText;
    var msg = document.createElement('div');
    msg.setAttribute('id', 'md5_check');
    msg.innerHTML = '\

\

\
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>\

md5 check
\

\

\

To check the integrity of your uploaded file, paste its md5 sum into the box below and click \'check\'.
\
<input type="text" class="span3" id="usermd5"><input type="text" disabled value="'+md5+'" class="span3">\

\

\
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>\
<button class="btn btn-success" onclick="checkmd5(\''+md5+'\');">check</button>\

\

';
    document.body.appendChild(msg);
    jQuery('#md5check').modal('show');
    start_upload();
}

function checkmd5 (md5) {
    if (md5 == document.getElementById("usermd5").value) {
	jQuery('#md5check').modal('hide');
	alert('you uploaded file is OK');
	document.getElementById("usermd5").value = "";
    } else {
	alert('WARNING: md5sum does not match, your file is probably corrupted!');
    }
}

function uploadFailed (evt) {
  document.querySelector("#upload_status").innerHTML = "the upload has failed";
}

function uploadCanceled (evt) {
  document.querySelector("#upload_status").innerHTML = "the upload was canceled";
}

function pretty_size (size) {
  var magnitude = "B";
  if (size > 1024) {
    size = size / 1024;
    magnitude = "KB"
  }
  if (size > 1024) {
    size = size / 1024;
    magnitude = "MB";
  }
  if (size > 1024) {
    size = size / 1024;
    magnitude = "GB";
  }
  size = size.toFixed(1);
  size = addCommas(size);
  size = size + " " + magnitude;

  return size;
}

function pretty_type (type) {
  return type;
}

function addCommas(nStr)
{
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}
<commit_msg>added removal of old div<commit_after>var fu_curr_files;
var fu_curr_file = 0;
var fu_curr_offset = 0;
var fu_curr_size;
var fu_total_size;
var fu_total_uploaded = 0;
const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
var incomplete_files = [];
var pending_uploads = [];
var chunk_multiplier = 1;

function init_uploader () {
  document.querySelector("#file_upload").addEventListener('change', function(e) {
      fu_curr_files = this.files;
      start_upload();
    }, false);
}

function start_upload () {
  if (fu_curr_files) {
    if (fu_curr_files.length > fu_curr_file) {

      var blob = fu_curr_files[fu_curr_file];
      const SIZE = blob.size;
      if (SIZE > 1024 * 1024 * 100) {
	chunk_multiplier = 10;
      } else {
	chunk_multiplier = 1;
      }
      fu_curr_size = blob.size;
      fu_total_size = 0;
      for (var i=0; i<fu_curr_files.length; i++) {
	fu_total_size += fu_curr_files[i].size;
      }

      var start = fu_curr_offset;
      if (incomplete_files[blob.name]) {
	alert("partial upload of file '"+blob.name+"' detected, resuming upload.");
	start = incomplete_files[blob.name];
	incomplete_files[blob.name] = null;
      }
      var end = start + (BYTES_PER_CHUNK * chunk_multiplier);
      var chunk;
      document.getElementById('progress_display').style.display = "";

      if (start < SIZE) {
	if ('mozSlice' in blob) {
	  chunk = blob.mozSlice(start, end);
	} else {
	  chunk = blob.webkitSlice(start, end);
	}

	document.getElementById("upload_progress").style.display = "";
	document.querySelector("#upload_status").innerHTML = "current file " + blob.name + "
file " + (fu_curr_file+1) + " of " + fu_curr_files.length + "
size " + pretty_size(blob.size) + "
type " + pretty_type(blob.type);
	fu_curr_offset = end;
	upload(chunk, blob.name);
      } else {
	var cfiles = document.getElementById("uploaded_files");
	cfiles.style.display = "";
	if (fu_curr_file == 0) {
	  cfiles.innerHTML = "
completed files
";
	}
	cfiles.innerHTML += "
"+blob.name+" ("+pretty_size(blob.size)+")
";

	fu_total_uploaded += fu_curr_files[fu_curr_file].size;
	fu_curr_file++;
	fu_curr_offset = 0;
	update_inbox(null, null, "upload_complete");
	start_upload();
      }
    } else {
      var cfiles = document.getElementById("uploaded_files");
      cfiles.style.display = "";
      if (fu_curr_file == 0) {
	cfiles.innerHTML = "
completed files
";
      }
      cfiles.innerHTML += "
upload complete
";
      document.getElementById('progress_display').style.display = "none";

      fu_curr_files = null;
      fu_curr_file = 0;
      fu_curr_offset = 0;
      fu_total_uploaded = 0;
      document.querySelector("#prog1").value = 100;
      document.querySelector("#prog2").value = 100;
    }
  }
}

function upload(blobOrFile, fn) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', "upload.cgi", true);
  xhr.onload = function(e) {
    if (this.status == 200) {
      console.log(this.response);
    }
  };
  var progressBar1 = document.querySelector("#prog1");
  var progressBar2 = document.querySelector("#prog2");
  xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
      progressBar1.value = ((e.loaded + fu_curr_offset + fu_total_uploaded - (BYTES_PER_CHUNK * chunk_multiplier)) / fu_total_size) * 100;
      progressBar2.value = ((e.loaded + fu_curr_offset - (BYTES_PER_CHUNK * chunk_multiplier)) / fu_curr_size) * 100;
    }
  };
  xhr.addEventListener("load", uploadComplete, false);
  xhr.addEventListener("error", uploadFailed, false);
  xhr.addEventListener("abort", uploadCanceled, false);

  var fd = new FormData();
  fd.append("upload_file", blobOrFile);
  fd.append('filename', fn);
  fd.append('auth', auth);
  if (fu_curr_offset >= fu_curr_size) {
    fd.append('last_chunk', 1);
  }

  xhr.send(fd);
  pending_uploads[pending_uploads.length] = xhr;
}

function cancel_upload () {
  if (confirm('Do you really want to cancel the current upload?')) {
    for (var i=0; i<pending_uploads.length; i++) {
      pending_uploads[i].abort();
    }
    fu_curr_files = null;
    fu_curr_file = 0;
    fu_curr_offset = 0;
    fu_total_uploaded = 0;
  }
}

function uploadComplete (evt) {
    var md5 = this.responseText;
    var old = document.getElementById("md5check");
    if (old) {
	jQuery('#md5check').remove();
    }
    var msg = document.createElement('div');
    msg.setAttribute('id', 'md5_check');
    msg.innerHTML = '\

\

\
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>\

md5 check
\

\

\

To check the integrity of your uploaded file, paste its md5 sum into the box below and click \'check\'.
\
<input type="text" class="span3" id="usermd5"><input type="text" disabled value="'+md5+'" class="span3">\

\

\
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>\
<button class="btn btn-success" onclick="checkmd5(\''+md5+'\');">check</button>\

\

';
    document.body.appendChild(msg);
    jQuery('#md5check').modal('show');
    start_upload();
}

function checkmd5 (md5) {
    if (md5 == document.getElementById("usermd5").value) {
	jQuery('#md5check').modal('hide');
	alert('you uploaded file is OK');
    } else {
	alert('WARNING: md5sum does not match, your file is probably corrupted!');
    }
}

function uploadFailed (evt) {
  document.querySelector("#upload_status").innerHTML = "the upload has failed";
}

function uploadCanceled (evt) {
  document.querySelector("#upload_status").innerHTML = "the upload was canceled";
}

function pretty_size (size) {
  var magnitude = "B";
  if (size > 1024) {
    size = size / 1024;
    magnitude = "KB"
  }
  if (size > 1024) {
    size = size / 1024;
    magnitude = "MB";
  }
  if (size > 1024) {
    size = size / 1024;
    magnitude = "GB";
  }
  size = size.toFixed(1);
  size = addCommas(size);
  size = size + " " + magnitude;

  return size;
}

function pretty_type (type) {
  return type;
}

function addCommas(nStr)
{
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}
<|endoftext|>


<commit_before>const yeoman = require('yeoman-generator');
const yosay = require('yosay');
const _merge = require('lodash/merge');
const _includes = require('lodash/includes');

module.exports = yeoman.Base.extend({
  prompting: {
    taskrunner() {
      const self = this;

      this.log(yosay(
        'Configure Task Runner for Grunt'
      ));
      return this.prompt([{
        type: 'checkbox',
        name: 'selectedTaskRunner',
        message: 'Which Task Runner do you use?',
        choices: ['Grunt'],
        default: ['Grunt'],
        when: () => !self.config.get('selectedTaskRunner'),
      }])
      .then(answers => {
        self.selectedTaskRunner = self.config.get('selectedTaskRunner') ||
        answers.selectedTaskRunner;
      });
    },
  },
  writing() {
    // Read a package.json if it exists or create it
    const packageJSON = this.fs.readJSON(this.destinationPath('package.json'), {});
    // Task Runner
    if (_includes(this.selectedTaskRunner, 'Grunt')) {
      this.log('Configuring Gruntfile for Task Runner');
      _merge(packageJSON, {
        devDependencies: {
          'grunt': '^1.0.1',
          'load-grunt-config': '^0.19.2',
        },
      });
      this.fs.copyTpl(
        this.templatePath('grunt/aliases.js'),
        this.destinationPath('./grunt/aliases.js'), {}
      );
      this.fs.copyTpl(
        this.templatePath('Gruntfile.js'),
        this.destinationPath('./Gruntfile.js'), {}
      );
    }
    this.log('Writing to package.json');
    this.fs.writeJSON(this.destinationPath('package.json'), packageJSON);
    this.installDependencies();
  },
});
<commit_msg>resolve eslint error<commit_after>const yeoman = require('yeoman-generator');
const yosay = require('yosay');
const _merge = require('lodash/merge');
const _includes = require('lodash/includes');

module.exports = yeoman.Base.extend({
  prompting: {
    taskrunner() {
      const self = this;

      this.log(yosay(
        'Configure Task Runner for Grunt'
      ));
      return this.prompt([{
        type: 'checkbox',
        name: 'selectedTaskRunner',
        message: 'Which Task Runner do you use?',
        choices: ['Grunt'],
        default: ['Grunt'],
        when: () => !self.config.get('selectedTaskRunner'),
      }])
      .then(answers => {
        self.selectedTaskRunner = self.config.get('selectedTaskRunner') ||
        answers.selectedTaskRunner;
      });
    },
  },
  writing() {
    // Read a package.json if it exists or create it
    const packageJSON = this.fs.readJSON(this.destinationPath('package.json'), {});
    // Task Runner
    if (_includes(this.selectedTaskRunner, 'Grunt')) {
      this.log('Configuring Gruntfile for Task Runner');
      _merge(packageJSON, {
        devDependencies: {
          grunt: '^1.0.1',
          'load-grunt-config': '^0.19.2',
        },
      });
      this.fs.copyTpl(
        this.templatePath('grunt/aliases.js'),
        this.destinationPath('./grunt/aliases.js'), {}
      );
      this.fs.copyTpl(
        this.templatePath('Gruntfile.js'),
        this.destinationPath('./Gruntfile.js'), {}
      );
    }
    this.log('Writing to package.json');
    this.fs.writeJSON(this.destinationPath('package.json'), packageJSON);
    this.installDependencies();
  },
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name        GitHub Toggle Expanders
// @version     1.0.6
// @description A userscript that toggles all expanders when one expander is shift-clicked
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @icon        https://github.com/fluidicon.png
// @updateURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-expanders.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-expanders.user.js
// ==/UserScript==
(() => {
	"use strict";

	function toggle(el) {
		const state = closest(".commits-list-item, .js-details-container", el)
			.classList.contains("open"),
			// target buttons inside commits_bucket - fixes #8
			selectors = `
				.commits-listing .commits-list-item,
				#commits_bucket .js-details-container,
				.release-timeline-tags .js-details-container`;
		Array.from(document.querySelectorAll(selectors)).forEach(el => {
			el.classList.toggle("open", state);
		});
	}

	function closest(selector, el) {
		while (el && el.nodeType === 1) {
			if (el.matches(selector)) {
				return el;
			}
			el = el.parentNode;
		}
		return null;
	}

	document.body.addEventListener("click", event => {
		const target = event.target;
		if (
			target && event.getModifierState("Shift") &&
			target.matches(".ellipsis-expander")
		) {
			// give GitHub time to add the class
			setTimeout(() => {
				toggle(target);
			}, 100);
		}
	});

})();
<commit_msg>Github-toggle-expanders: handle PR comments<commit_after>// ==UserScript==
// @name        GitHub Toggle Expanders
// @version     1.1.0
// @description A userscript that toggles all expanders when one expander is shift-clicked
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @icon        https://github.com/fluidicon.png
// @updateURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-expanders.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-expanders.user.js
// ==/UserScript==
(() => {
	"use strict";

	function toggle(el, ctrlKeyPressed) {
		const stateNode = closest(".js-details-container", el),
			state = stateNode.classList.contains("open"),
			parentNode = closest(ctrlKeyPressed ?
				".container, .js-discussion" :
				".commits-listing, .discussion-item-body, .release-timeline-tags",
				stateNode
			),
			containerNodes = parentNode.querySelectorAll(".js-details-container");

		Array.from(containerNodes).forEach(node => {
			node.classList.toggle("open", state);
		});
	}

	function closest(selector, el) {
		while (el && el.nodeType === 1) {
			if (el.matches(selector)) {
				return el;
			}
			el = el.parentNode;
		}
		return null;
	}

	document.body.addEventListener("click", event => {
		const target = event.target;
		if (
			target && event.getModifierState("Shift") &&
			target.matches(".js-details-target")
		) {
			// give GitHub time to add the class
			setTimeout(() => {
				toggle(target, event.ctrlKey);
			}, 100);
		}
	});

})();
<|endoftext|>