/*! angular-google-chart 2015-11-29 */ 
 | 
/* 
 | 
* @description Google Chart Api Directive Module for AngularJS 
 | 
* @version 0.1.0 
 | 
* @author GitHub Contributors <https://github.com/angular-google-chart/angular-google-chart/graphs/contributors>  
 | 
* @license MIT 
 | 
* @year 2013 
 | 
*/ 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart', []) 
 | 
        .run(registerResizeEvent); 
 | 
         
 | 
    registerResizeEvent.$inject = ['$rootScope', '$window']; 
 | 
     
 | 
    function registerResizeEvent($rootScope, $window){ 
 | 
        angular.element($window).bind('resize', function () { 
 | 
                $rootScope.$emit('resizeMsg'); 
 | 
            }); 
 | 
    } 
 | 
})(); 
 | 
/* global angular, google */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .factory('FormatManager', formatManagerFactory); 
 | 
         
 | 
        function formatManagerFactory(){ 
 | 
            // Handles the processing of Google Charts API Formats 
 | 
            function FormatManager($google){ 
 | 
                var self = this; 
 | 
                var oldFormatTemplates = {}; 
 | 
                self.iFormats = {}; // Holds instances of formats (ie. self.iFormats.date[0] = new $google.visualization.DateFormat(params)) 
 | 
                self.applyFormats = applyFormats; 
 | 
                 
 | 
                // apply formats of type to datatable 
 | 
                function apply(tFormats, dataTable){ 
 | 
                    var i, formatType; 
 | 
                    for (formatType in tFormats){ 
 | 
                        if (tFormats.hasOwnProperty(formatType)){ 
 | 
                            for (i = 0; i < self.iFormats[formatType].length; i++) { 
 | 
                                if (tFormats[formatType][i].columnNum < dataTable.getNumberOfColumns()) { 
 | 
                                    self.iFormats[formatType][i].format(dataTable, tFormats[formatType][i].columnNum); 
 | 
                                } 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
                 
 | 
                function applyFormat(formatType, FormatClass, tFormats){ 
 | 
                    var i; 
 | 
                    if (angular.isArray(tFormats[formatType])) { 
 | 
                        // basic change detection; no need to run if no changes 
 | 
                        if (!angular.equals(tFormats[formatType], oldFormatTemplates[formatType])) { 
 | 
                            oldFormatTemplates[formatType] = tFormats[formatType]; 
 | 
                            self.iFormats[formatType] = []; 
 | 
             
 | 
                            if (formatType === 'color') { 
 | 
                                instantiateColorFormatters(tFormats); 
 | 
                            } else { 
 | 
                                for (i = 0; i < tFormats[formatType].length; i++) { 
 | 
                                    self.iFormats[formatType].push(new FormatClass( 
 | 
                                        tFormats[formatType][i]) 
 | 
                                    ); 
 | 
                                } 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
                 
 | 
                function applyFormats(dataTable, tFormats, customFormatters) { 
 | 
                    var formatType, FormatClass, requiresHtml = false; 
 | 
                    if (!angular.isDefined(tFormats) || !angular.isDefined(dataTable)){ 
 | 
                        return { requiresHtml: false }; 
 | 
                    } 
 | 
                    for (formatType in tFormats){ 
 | 
                        if (tFormats.hasOwnProperty(formatType)){ 
 | 
                            FormatClass = getFormatClass(formatType, customFormatters); 
 | 
                            if (!angular.isFunction(FormatClass)){ 
 | 
                                // if no class constructor was returned, 
 | 
                                // there's no point in completing cycle 
 | 
                                continue; 
 | 
                            } 
 | 
                            applyFormat(formatType, FormatClass, tFormats); 
 | 
                             
 | 
                            //Many formatters require HTML tags to display special formatting 
 | 
                            if (formatType === 'arrow' || formatType === 'bar' || formatType === 'color') { 
 | 
                                requiresHtml = true; 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                    apply(tFormats, dataTable); 
 | 
                    return { requiresHtml: requiresHtml }; 
 | 
                } 
 | 
                 
 | 
                function instantiateColorFormatters(tFormats){ 
 | 
                    var t, colorFormat, i, data, formatType = 'color'; 
 | 
                    for (t = 0; t < tFormats[formatType].length; t++) { 
 | 
                        colorFormat = new $google.visualization.ColorFormat(); 
 | 
  
 | 
                        for (i = 0; i < tFormats[formatType][t].formats.length; i++) { 
 | 
                            data = tFormats[formatType][t].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.iFormats[formatType].push(colorFormat); 
 | 
                    } 
 | 
                } 
 | 
                 
 | 
                function getFormatClass(formatType, customFormatters){ 
 | 
                    var className = formatType.charAt(0).toUpperCase() + formatType.slice(1).toLowerCase() + "Format"; 
 | 
                    if ($google.visualization.hasOwnProperty(className)){ 
 | 
                        return google.visualization[className]; 
 | 
                    } else if (angular.isDefined(customFormatters) && customFormatters.hasOwnProperty(formatType)) { 
 | 
                        return customFormatters[formatType]; 
 | 
                    } 
 | 
                    return; 
 | 
                } 
 | 
            } 
 | 
             
 | 
            return FormatManager; 
 | 
        } 
 | 
})(); 
 | 
/* global angular, google */ 
 | 
  
 | 
(function() { 
 | 
  
 | 
    angular.module('googlechart') 
 | 
        .controller('GoogleChartController', GoogleChartController); 
 | 
  
 | 
    GoogleChartController.$inject = ['$scope', '$element', '$attrs', '$injector', '$timeout', '$window', '$rootScope', 'GoogleChartService']; 
 | 
  
 | 
    function GoogleChartController($scope, $element, $attrs, $injector, $timeout, $window, $rootScope, GoogleChartService) { 
 | 
        var self = this; 
 | 
        var resizeHandler; 
 | 
        var googleChartService; 
 | 
  
 | 
        init(); 
 | 
  
 | 
        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); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        // Watch function calls this. 
 | 
        function drawAsync() { 
 | 
            googleChartService.getReadyPromise() 
 | 
                .then(draw); 
 | 
        } 
 | 
  
 | 
        //setupAndDraw() calls this. 
 | 
        function drawChartWrapper() { 
 | 
            googleChartService.draw(); 
 | 
            draw.triggered = false; 
 | 
        } 
 | 
  
 | 
        function init() { 
 | 
            // Instantiate service 
 | 
            googleChartService = new GoogleChartService(); 
 | 
             
 | 
            self.registerChartListener = googleChartService.registerChartListener; 
 | 
            self.registerWrapperListener = googleChartService.registerWrapperListener; 
 | 
            self.registerServiceListener = googleChartService.registerServiceListener; 
 | 
             
 | 
            /* 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', drawAsync); 
 | 
  
 | 
            //Cleanup resize handler. 
 | 
            $scope.$on('$destroy', cleanup); 
 | 
        } 
 | 
  
 | 
        function setupAndDraw() { 
 | 
            googleChartService.setup($element, 
 | 
            self.chart.type, 
 | 
            self.chart.data, 
 | 
            self.chart.view, 
 | 
            self.chart.options, 
 | 
            self.chart.formatters, 
 | 
            self.chart.customFormatters); 
 | 
  
 | 
            $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 
 | 
                }; 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcBeforeDraw', onReadyDirective); 
 | 
         
 | 
    function onReadyDirective(){ 
 | 
        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.agcBeforeDraw, {chartWrapper: chartWrapper}); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerServiceListener('beforeDraw', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnClick', onClickDirective); 
 | 
  
 | 
    function onClickDirective(){ 
 | 
        return { 
 | 
            restrict: 'A', 
 | 
            scope: false, 
 | 
            require: 'googleChart', 
 | 
            link: function(scope, element, attrs, googleChartController){ 
 | 
                callback.$inject = ['args', 'chart', 'chartWrapper']; 
 | 
                function callback(args, chart, chartWrapper){ 
 | 
                    scope.$apply(function (){ 
 | 
                        scope.$eval(attrs.agcOnClick, {args: args, chart: chart, chartWrapper: chartWrapper}); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerChartListener('click', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
  
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnError', onErrorDirective); 
 | 
    function onErrorDirective(){ 
 | 
        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.agcOnError, returnValues); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerWrapperListener('error', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
  
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnMouseout', agcOnMouseoutDirective); 
 | 
     
 | 
    function agcOnMouseoutDirective(){ 
 | 
        return { 
 | 
            restrict: 'A', 
 | 
            scope: false, 
 | 
            require: 'googleChart', 
 | 
            link: function(scope, element, attrs, googleChartController){ 
 | 
                callback.$inject = ['args', 'chart', 'chartWrapper']; 
 | 
                function callback(args, chart, chartWrapper){ 
 | 
                    var returnParams = { 
 | 
                        chartWrapper: chartWrapper, 
 | 
                        chart: chart, 
 | 
                        args: args, 
 | 
                        column: args[0].column, 
 | 
                        row: args[0].row 
 | 
                    }; 
 | 
                    scope.$apply(function () { 
 | 
                        scope.$eval(attrs.agcOnMouseout, returnParams); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerChartListener('onmouseout', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
  
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnMouseover', agcOnMouseoverDirective); 
 | 
     
 | 
    function agcOnMouseoverDirective(){ 
 | 
        return { 
 | 
            restrict: 'A', 
 | 
            scope: false, 
 | 
            require: 'googleChart', 
 | 
            link: function(scope, element, attrs, googleChartController){ 
 | 
                callback.$inject = ['args', 'chart', 'chartWrapper']; 
 | 
                function callback(args, chart, chartWrapper){ 
 | 
                    var returnParams = { 
 | 
                        chartWrapper: chartWrapper, 
 | 
                        chart: chart, 
 | 
                        args: args, 
 | 
                        column: args[0].column, 
 | 
                        row: args[0].row 
 | 
                    }; 
 | 
                    scope.$apply(function () { 
 | 
                        scope.$eval(attrs.agcOnMouseover, returnParams); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerChartListener('onmouseover', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnReady', onReadyDirective); 
 | 
         
 | 
    function onReadyDirective(){ 
 | 
        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.agcOnReady, {chartWrapper: chartWrapper}); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerWrapperListener('ready', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('agcOnSelect', onSelectDirective); 
 | 
         
 | 
    function onSelectDirective(){ 
 | 
        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.agcOnSelect, selectEventRetParams); 
 | 
                    }); 
 | 
                } 
 | 
                googleChartController.registerWrapperListener('select', callback, this); 
 | 
            } 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
/* global angular, google */ 
 | 
/* jshint -W072 */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .directive('googleChart', googleChartDirective); 
 | 
         
 | 
    googleChartDirective.$inject = []; 
 | 
         
 | 
    function googleChartDirective() { 
 | 
  
 | 
        return { 
 | 
            restrict: 'A', 
 | 
            scope: false, 
 | 
            controller: 'GoogleChartController' 
 | 
        }; 
 | 
    } 
 | 
})(); 
 | 
  
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .value('googleChartApiConfig', { 
 | 
            version: '1', 
 | 
            optionalSettings: { 
 | 
                packages: ['corechart'] 
 | 
            } 
 | 
        }); 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .factory('googleChartApiPromise', googleChartApiPromiseFactory); 
 | 
         
 | 
    googleChartApiPromiseFactory.$inject = ['$rootScope', '$q', 'googleChartApiConfig', 'googleJsapiUrl']; 
 | 
         
 | 
    function googleChartApiPromiseFactory($rootScope, $q, apiConfig, googleJsapiUrl) { 
 | 
        apiConfig.optionalSettings = apiConfig.optionalSettings || {}; 
 | 
        var apiReady = $q.defer(); 
 | 
        var onLoad = function () { 
 | 
            // override callback function 
 | 
            var settings = { 
 | 
                callback: function () { 
 | 
                    var oldCb = apiConfig.optionalSettings.callback; 
 | 
                    $rootScope.$apply(function () { 
 | 
                        apiReady.resolve(google); 
 | 
                    }); 
 | 
  
 | 
                    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; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function() { 
 | 
    angular.module('googlechart') 
 | 
        .factory('GoogleChartService', GoogleChartServiceFactory); 
 | 
  
 | 
    GoogleChartServiceFactory.$inject = ['googleChartApiPromise', '$injector', '$q', 'FormatManager']; 
 | 
  
 | 
    function GoogleChartServiceFactory(googleChartApiPromise, $injector, $q, FormatManager) { 
 | 
        function GoogleChartService() { 
 | 
            var self = this; 
 | 
            self.draw = draw; 
 | 
            self.getChartWrapper = getChartWrapper; 
 | 
            self.getData = getData; 
 | 
            self.getElement = getElement; 
 | 
            self.getOption = getOption; 
 | 
            self.getOptions = getOptions; 
 | 
            self.getView = getView; 
 | 
            self.getReadyPromise = getReadyPromise; 
 | 
            self.isApiReady = isApiReady; 
 | 
            self.registerChartListener = registerChartListener; 
 | 
            self.registerServiceListener = registerServiceListener; 
 | 
            self.registerWrapperListener = registerWrapperListener; 
 | 
            self.setData = setData; 
 | 
            self.setElement = setElement; 
 | 
            self.setOption = setOption; 
 | 
            self.setOptions = setOptions; 
 | 
            self.setup = setup; 
 | 
            self.setView = setView; 
 | 
  
 | 
            var $google, 
 | 
                _apiPromise, 
 | 
                _apiReady, 
 | 
                _chartWrapper, 
 | 
                _element, 
 | 
                _chartType, 
 | 
                _data, 
 | 
                _view, 
 | 
                _options, 
 | 
                _formatters, 
 | 
                _innerVisualization, 
 | 
                _formatManager, 
 | 
                _needsUpdate = true, 
 | 
                _customFormatters, 
 | 
                _serviceDeferred, 
 | 
                serviceListeners = {}, 
 | 
                wrapperListeners = {}, 
 | 
                chartListeners = {}; 
 | 
  
 | 
            _init(); 
 | 
  
 | 
            function _activateServiceEvent(eventName) { 
 | 
                var i; 
 | 
                if (angular.isArray(serviceListeners[eventName])) { 
 | 
                    for (i = 0; i < serviceListeners[eventName].length; i++) { 
 | 
                        serviceListeners[eventName][i](); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
  
 | 
            function _apiLoadFail(reason) { 
 | 
                // Not sure what to do if this does happen. 
 | 
                // Post your suggestions in the issues tracker at 
 | 
                // https://github.com/angular-google-chart/angular-google-chart/ 
 | 
                return reason; 
 | 
            } 
 | 
  
 | 
            function _apiLoadSuccess(g) { 
 | 
                $google = g; 
 | 
                _apiReady = true; 
 | 
                _serviceDeferred.resolve(); 
 | 
                return g; 
 | 
            } 
 | 
  
 | 
  
 | 
            function _continueSetup() { 
 | 
                if (!angular.isDefined(_chartWrapper)) { 
 | 
                    _chartWrapper = new $google.visualization.ChartWrapper({ 
 | 
                        chartType: _chartType, 
 | 
                        dataTable: _data, 
 | 
                        view: _view, 
 | 
                        options: _options, 
 | 
                        containerId: _element[0] 
 | 
                    }); 
 | 
                    _registerListenersWithGoogle(_chartWrapper, wrapperListeners); 
 | 
                } 
 | 
                else { 
 | 
                    _chartWrapper.setChartType(_chartType); 
 | 
                    _chartWrapper.setDataTable(_data); 
 | 
                    _chartWrapper.setView(_view); 
 | 
                    _chartWrapper.setOptions(_options); 
 | 
                } 
 | 
  
 | 
                if (!_formatManager) { 
 | 
                    _formatManager = new FormatManager($google); 
 | 
                } 
 | 
  
 | 
                if (_formatManager.applyFormats(_chartWrapper.getDataTable(), 
 | 
                        _formatters, _customFormatters).requiresHtml) { 
 | 
                    _chartWrapper.setOption('allowHtml', true); 
 | 
                } 
 | 
  
 | 
                _needsUpdate = false; 
 | 
            } 
 | 
  
 | 
            // Credit for this solution: 
 | 
            // http://stackoverflow.com/a/20125572/3771976 
 | 
            function _getSetDescendantProp(obj, desc, value) { 
 | 
                var arr = desc ? desc.split(".") : []; 
 | 
  
 | 
                while (arr.length && obj) { 
 | 
                    var comp = arr.shift(); 
 | 
                    var match = new RegExp("(.+)\\[([0-9]*)\\]").exec(comp); 
 | 
  
 | 
                    if (value) { 
 | 
                        if (obj[comp] === undefined) { 
 | 
                            obj[comp] = {}; 
 | 
                        } 
 | 
  
 | 
                        if (arr.length === 0) { 
 | 
                            obj[comp] = value; 
 | 
                        } 
 | 
                    } 
 | 
  
 | 
                    obj = obj[comp]; 
 | 
                } 
 | 
  
 | 
                return obj; 
 | 
            } 
 | 
  
 | 
            function _handleReady() { 
 | 
                // When the chartWrapper is ready, check to see if the inner chart 
 | 
                // has changed. If it has, re-register listeners onto that chart. 
 | 
                if (_innerVisualization !== _chartWrapper.getChart()) { 
 | 
                    _innerVisualization = _chartWrapper.getChart(); 
 | 
                    _registerListenersWithGoogle(_innerVisualization, chartListeners); 
 | 
                } 
 | 
            } 
 | 
  
 | 
            function _init() { 
 | 
                _apiReady = false; 
 | 
                _serviceDeferred = $q.defer(); 
 | 
                //keeps the resulting promise to chain on other actions 
 | 
                _apiPromise = googleChartApiPromise 
 | 
                    .then(_apiLoadSuccess) 
 | 
                    .catch(_apiLoadFail); 
 | 
  
 | 
                registerWrapperListener('ready', _handleReady, self); 
 | 
            } 
 | 
  
 | 
            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: _chartWrapper, 
 | 
                        chart: _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 _runDrawCycle() { 
 | 
                _activateServiceEvent('beforeDraw'); 
 | 
                _chartWrapper.draw(); 
 | 
            } 
 | 
  
 | 
            /* 
 | 
            This function does this: 
 | 
                - waits for API to load, if not already loaded 
 | 
                - sets up ChartWrapper object (create or update) 
 | 
                - schedules timeout event to draw chart 
 | 
            */ 
 | 
            function draw() { 
 | 
                if (_needsUpdate) { 
 | 
                    _apiPromise = _apiPromise.then(_continueSetup); 
 | 
                } 
 | 
                _apiPromise = _apiPromise.then(_runDrawCycle()); 
 | 
            } 
 | 
  
 | 
            function getChartWrapper() { 
 | 
                // Most get functions on this interface return copies, 
 | 
                // this one should return reference so as to expose the  
 | 
                //chart api to users 
 | 
                return _chartWrapper; 
 | 
            } 
 | 
  
 | 
            function getData() { 
 | 
                var data = _data || {}; 
 | 
                return angular.copy(data); 
 | 
            } 
 | 
  
 | 
            function getElement() { 
 | 
                return _element; 
 | 
            } 
 | 
  
 | 
            function getOption(name) { 
 | 
                var options = _options || {}; 
 | 
                return _getSetDescendantProp(options, name); 
 | 
            } 
 | 
  
 | 
            function getOptions() { 
 | 
                var options = _options || {}; 
 | 
                return angular.copy(options); 
 | 
            } 
 | 
  
 | 
            function getReadyPromise() { 
 | 
                return _serviceDeferred.promise; 
 | 
            } 
 | 
  
 | 
            function getView() { 
 | 
                var view = _view || {}; 
 | 
                return angular.copy(view); 
 | 
            } 
 | 
  
 | 
            function isApiReady() { 
 | 
                return _apiReady; 
 | 
            } 
 | 
  
 | 
            function registerChartListener(eventName, listenerFn, listenerObject) { 
 | 
                return _registerListener(chartListeners, eventName, listenerFn, listenerObject); 
 | 
            } 
 | 
  
 | 
            function registerServiceListener(eventName, listenerFn, listenerObject) { 
 | 
                return _registerListener(serviceListeners, eventName, listenerFn, listenerObject); 
 | 
            } 
 | 
  
 | 
            function registerWrapperListener(eventName, listenerFn, listenerObject) { 
 | 
                return _registerListener(wrapperListeners, eventName, listenerFn, listenerObject); 
 | 
            } 
 | 
  
 | 
            function setData(data) { 
 | 
                if (angular.isDefined(data)) { 
 | 
                    _data = angular.copy(data); 
 | 
                    _needsUpdate = true; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            function setElement(element) { 
 | 
                if (angular.isElement(element) && _element !== element) { 
 | 
                    _element = element; 
 | 
                    // clear out the chartWrapper because we're going to need a new one 
 | 
                    _chartWrapper = null; 
 | 
                    _needsUpdate = true; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            function setOption(name, value) { 
 | 
                _options = _options || {}; 
 | 
                _getSetDescendantProp(_options, name, angular.copy(value)); 
 | 
                _needsUpdate = true; 
 | 
            } 
 | 
  
 | 
            function setOptions(options) { 
 | 
                if (angular.isDefined(options)) { 
 | 
                    _options = angular.copy(options); 
 | 
                    _needsUpdate = true; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            function setup(element, chartType, data, view, options, formatters, customFormatters) { 
 | 
                // Keep values if already set, 
 | 
                // can call setup() with nulls to keep 
 | 
                // existing values 
 | 
                _element = element || _element; 
 | 
                _chartType = chartType || _chartType; 
 | 
                _data = data || _data; 
 | 
                _view = view || _view; 
 | 
                _options = options || _options; 
 | 
                _formatters = formatters || _formatters; 
 | 
                _customFormatters = customFormatters || _customFormatters; 
 | 
  
 | 
                _apiPromise = _apiPromise.then(_continueSetup); 
 | 
            } 
 | 
  
 | 
            function setView(view) { 
 | 
                _view = angular.copy(view); 
 | 
            } 
 | 
        } 
 | 
        return GoogleChartService; 
 | 
    } 
 | 
})(); 
 | 
/* global angular */ 
 | 
(function(){ 
 | 
    angular.module('googlechart') 
 | 
        .provider('googleJsapiUrl', googleJsapiUrlProvider); 
 | 
         
 | 
    function googleJsapiUrlProvider() { 
 | 
        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; 
 | 
        }; 
 | 
    } 
 | 
})(); 
 |