Source: components/chart.js

;(function () {
    'use strict';

    /**
     * Utility functions for charts
     * @namespace
     */
    db.libs.chart = (function($){

        var name = 'chart';

        /**
         * Converts a string formated time duration to milliseconds
         * @private
         * @memberof db.libs.chart
         * @param {string} string A string like '1s' or '60s'
         * @returns {number}
         */
        function asMilliseconds(string){
            return moment.duration(parseInt(string.replace(/\D/g, "")), string.replace(/[^a-z]/gi, "")).asMilliseconds();
        }

        /**
         * Parse a string formated as array into array
         * @private
         * @memberof db.libs.chart
         * @param {string} data
         * @returns {array}
         */
        function parse(data){
            if(typeof data == 'string'){
                data = JSON.parse(data);
            }
            if(!Array.isArray(data)){
                console.warn('db.libs.chart > invalid series data');
            }
            return data;
        }

        /**
         * Returns the sum of all values in an array
         * @private
         * @memberof db.libs.chart
         * @param {array}
         * @returns {number}
         */
        function sum(arr){
            var total = 0;
            for(var i=0; i < arr.length; i++){
                total += parseInt(arr[i]);
            }
            return total;
        }

        /**
         * Returns the highest number in an array
         * @private
         * @memberof db.libs.chart
         * @param {array}
         * @returns {number}
         */
        function max(arr){
            var highest = 0;
            for(var i=0; i < arr.length; i++){

                if(Array.isArray(arr[i])){
                    for(var x=0; x < arr[i].length; x++){
                        if(arr[i][x] > highest){
                            highest = arr[i][x];
                        }
                    }
                } else {
                    if(arr[i] > highest){
                        highest = arr[i];
                    }
                }
            }
            return highest;
        }

        /**
         * Returns the lowest number in an array
         * @private
         * @memberof db.libs.chart
         * @param {array}
         * @returns {number}
         */
        function min(arr){
            var lowest = 0;
            for(var i=0; i < arr.length; i++){
                if(arr[i] < lowest){
                    lowest = arr[i];
                }
            }
            return lowest;
        }

        function grid(steps, max){
            var lines = [];

            for(var i=0; i < steps; i++){
                lines.push({
                    height: 100 / steps,
                    label: Math.round((max / steps) * (i+1))
                });
            }

            lines.reverse();

            return lines;
        }

        function pattern(el, p){
            var patternId = p.getAttribute('id');
            var svg = getSvg(el);
            var defs = svg.querySelector('defs');
            defs.appendChild(p);
            el.style.setProperty('fill', 'url("#'+patternId+'")', 'important');
            return el;
        }

        function circles(options){
            var defaults = {
                id: db.utils.uniqueId('chart-pattern-'),
                size: 20,
                radius: 4,
                color: '#222',
                stroke: 0,
                background: 'transparent'
            };
            options = $.extend({}, defaults, options);

            var pattern, rect, circle;

            pattern = document.createElementNS('http://www.w3.org/2000/svg', 'pattern');
            pattern.setAttribute('id', options.id);
            pattern.setAttribute('class', 'pattern circles');
            pattern.setAttribute('patternUnits', 'userSpaceOnUse');
            pattern.setAttribute('width', options.size);
            pattern.setAttribute('height', options.size);

            rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            rect.setAttribute('width', options.size);
            rect.setAttribute('height', options.size);
            rect.setAttribute('fill', options.background);

            circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
            circle.setAttribute('cx', (options.size / 2));
            circle.setAttribute('cy', (options.size / 2));
            circle.setAttribute('r', options.radius);
            circle.setAttribute('fill', options.color);
            circle.setAttribute('stroke-width', options.stroke);

            pattern.appendChild(rect);
            pattern.appendChild(circle);

            return pattern;
        }

        function lines(options){
            var defaults = {
                id: db.utils.uniqueId('chart-pattern-'),
                size: 20,
                width: 3,
                rotation: 45,
                color: '#222',
                background: 'transparent'
            };
            options = $.extend({}, defaults, options);

            var pattern, background, line1, line2, line3;

            pattern = document.createElementNS('http://www.w3.org/2000/svg', 'pattern');
            pattern.setAttribute('id', options.id);
            pattern.setAttribute('class', 'pattern circles');
            pattern.setAttribute('patternUnits', 'userSpaceOnUse');
            pattern.setAttribute('width', options.size);
            pattern.setAttribute('height', options.size);

            background = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            background.setAttribute('width', options.size);
            background.setAttribute('height', options.size);
            background.setAttribute('fill', options.background);

            line1 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            line1.setAttribute('width', options.width);
            line1.setAttribute('height', (options.size * 2));
            line1.setAttribute('x', (options.width / 2) * -1);
            line1.setAttribute('y', options.size * -1);
            line1.setAttribute('fill', options.color);
            line1.setAttribute('transform', 'rotate(' + options.rotation + ' 0 0)');

            line2 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            line2.setAttribute('width', options.width);
            line2.setAttribute('height', (options.size * 2));
            line2.setAttribute('x', (options.size / 2) - (options.width / 2));
            line2.setAttribute('y', (options.size / 4) * -1);
            line2.setAttribute('fill', options.color);
            line2.setAttribute('transform', 'rotate(' + options.rotation + ' '+(options.size / 2)+' '+(options.size / 2)+')');

            line3 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            line3.setAttribute('width', options.width);
            line3.setAttribute('height', (options.size * 2));
            line3.setAttribute('x', options.size - (options.width / 2));
            line3.setAttribute('y', 0);
            line3.setAttribute('fill', options.color);
            line3.setAttribute('transform', 'rotate(' + options.rotation + ' '+options.size+' '+options.size+')');

            pattern.appendChild(background);
            pattern.appendChild(line1);
            pattern.appendChild(line2);
            pattern.appendChild(line3);

            return pattern;
        }

        function getSvg(el){
            for ( ; el && el !== document; el = el.parentNode ) {
                if ( el.tagName.toLowerCase() === 'svg' ) {
                    return el;
                }
            }
            return false;
        }

        function refresh(id, url, duration){
            var $chart = $(id);
            duration = asMilliseconds(duration);
            setInterval(function(){
                $.getJSON(url, function(data) {
                    if($chart.hasClass('line')){
                        $chart.lineChart('series', data).lineChart('update');
                    }
                    if($chart.hasClass('bars')){
                        $chart.barChart('series', data).barChart('update');
                    }
                    if($chart.hasClass('pie')){
                        $chart.pieChart('series', data).pieChart('update');
                    }
                });
            }, duration);
        }

        return {
            init: function(){},
            reflow: function(){},
            sum: sum,
            max: max,
            min: min,
            parse: parse,
            grid: grid,
            pattern: pattern,
            circles: circles,
            lines: lines,
            refresh: refresh
        };

    })(jQuery);
})();