zingchart/ZingChart-AngularJS

View on GitHub
src/zingchart-angularjs.js

Summary

Maintainability
B
5 hrs
Test Coverage
/**
* File: zingchart-angularjs.js
* Version: v1.1.0
*/

(function(){
    'use strict';
    angular.module('zingchart-angularjs', [] )
    .directive('zingchart', [function(){
        var currentAutoId = 1;

        return {
            restrict : 'EA',
            scope : {
                id : '@',
                zcValues : '=',
                zcJson : '=',
                zcRender : '=',
        zcLicense : '='
            },
            controller : ['$scope', '$element', '$attrs', function($scope, $element, $attrs){
                var id;
                // Get or generate id
                if(!$attrs.id){
                    id = 'zingchart-auto-' + currentAutoId;
                    currentAutoId++;
                    $attrs.id = id;
                    // newly generated id has to be put back on the element too to meet
                    // zingcharts requirements
                    $element.attr('id', id);
                }
                else{
                    if($attrs.id.indexOf('{{') > -1){
                        id=$scope.id;
                        $element.attr('id', id);
                    }
                    else{
                        id = $attrs.id;
                    }
                }

                var initializing = {
                    json : true,
                    values : true,
                    render : true
                };
                $scope.$watchCollection('zcValues', function(){
                    if(initializing.values){
                        initializing.values = !initializing.values;
                        return;
                    }
                    if($scope.zcValues){
                        if(isMultiArray($scope.zcValues)){
                            zingchart.exec(id, 'setseriesvalues', {
                                values : $scope.zcValues
                            });
                        }
                        else{
                            zingchart.exec(id, 'setseriesvalues', {
                                values : [$scope.zcValues]
                            });
                        }
                    }
                });

                $scope.$watch('zcLicense', function(newValue, oldValue, scope) {
                    if(initializing.license){
                        initializing.license = !initializing.license;
                        return;
                    }

                    ZC.LICENSE = scope.zcLicense;
                    scope.zcLicense = newValue;
                },true);

                $scope.$watch('zcJson', function(){
                    if(initializing.json){
                        initializing.json = !initializing.json;
                        return;
                    }
                    if($attrs.zcJson){
                        var _json = $scope.zcJson;

                        //Inject values
                        if($scope.zcValues){
                            injectValues($scope.zcValues, _json);
                        }
                        //Inject type
                        if(JSON.stringify(_json).indexOf('type') === -1){
                            _json.type = 'line';
                        }
                        else{
                            _json.type = ($attrs.zcType) ? $attrs.zcType : _json.type
                        }
                        zingchart.exec(id, 'setdata', {
                            data : _json
                        });
                    }
                },true);

                $scope.$watch('zcRender', function(newValue, oldValue, scope) {
                    if(initializing.render){
                        initializing.render = !initializing.render;
                        return;
                    }

                    // Destroy the chart and re-render it with changed attributes
                    zingchart.exec(scope.id, 'destroy');
                    scope.zcRender = newValue;
                    scope.renderChart();
                },true);

                $scope.renderChart = function (){
                    var id = $element.attr('id');
                    //Defaults
                    var _json = {
                        data : {
                            type : 'line',
                            series : []
                        },
                        width : 600,
                        height: 400
                    };
            
                    //Add render object.
                    if($scope.zcRender){
                        mergeObject($scope.zcRender, _json);
                    }

                    //Add JSON object
                    if($scope.zcJson){
                        mergeObject($scope.zcJson, _json.data);
                    }

                    //Add Values
                    if($scope.zcValues){
                        injectValues($scope.zcValues, _json.data);
                    }

                    //Add other properties
                    _json.data.type = ($attrs.zcType) ? $attrs.zcType : _json.data.type;
                    _json.height = ($attrs.zcHeight) ? $attrs.zcHeight : _json.height;
                    _json.width = ($attrs.zcWidth) ? $attrs.zcWidth : _json.width;
                    _json.id = id;

                    //Set the box-model of the container element if the height or width are defined as 100%.
                    if(_json.width === "100%" && !$element.css('width')){
                        $element.css('width', '100%');
                    }
                    if(_json.height === "100%" && !$element.css('height')){
                        $element.css('height', '100%');
                    }
            ZC.LICENSE = $scope.zcLicense;
                    zingchart.render(_json);
                }
                
                $scope.$on('$destroy', function() {
                    zingchart.exec($scope.id,'destroy');
                });
            }],
            link : function($scope){
                $scope.renderChart();
            }
        };
    }]);

    /**
    * Injects values into each series, and handles multi series cases.
    * @param the values to inject into the config object
    * @param the configuration object itself.
    */
    function injectValues(values, config) {
        if(typeof config.series === 'undefined'){
            config.series = [];
        }
        //Single Series
        if(!isMultiArray(values)){
            if(config.series[0]){
                config.series[0].values = values;
            }
            else{
                config.series.push({'values' : values});
            }
        }
        //Multi Series
        else{
            for(var i = 0; i < values.length; i++){
                if(config.series[i]){
                    config.series[i].values = values[i];
                }
                else{
                    config.series.push({'values' : values[i]});
                }
            }
        }
        return config;
    }

    /**
    *   Helper function to merge an object into another, overwriting properties.
    *   A shallow, not a recursive merge
    *   @param {object} fromObj - The object that has properties to be merged
    *   @param {object} intoObj - The object being merged into (Result)
    */
    function mergeObject(fromObj, intoObj){
        for(var property in fromObj){
            if (fromObj.hasOwnProperty(property)) {
                intoObj[property] = fromObj[property];
            }
        }
    }

    /**
    *   Determines whether an array is multidimensional or not.
    *   @param {array} _array - The array to test
    *   @returns {boolean} - true if the array is multidimensional, false otherwise
    */
    function isMultiArray(_array){
        return Array.isArray(_array[0]);
    }

})();