Source: components/chart-bar.js

;(function () {
    'use strict';

    /**
     * Draw simple pie bar chart.
     * @namespace
     */
    db.libs.barChart = (function($){

        var name = 'barChart';

        /**
         * Updates the chart with data in series
         * @public
         * @memberof db.libs.barChart
         * @param {external:jQuery} [id] Selector or jQuery element
         * @return {external:jQuery} jQuery element
         */
        function update(id){
            var $id = $(id);
            var options = $id.data('options');
            var bars = $id.get(0).querySelectorAll('.bar');
            var animate, animateHeight, animateY;

            for(var i = 0; i < bars.length; i++){
                animateHeight = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
                animateHeight.setAttribute('attributeName', 'height');
                animateHeight.setAttribute('from', bars[i].getAttribute('height'));
                animateHeight.setAttribute('to', options.bars[i].height);
                animateHeight.setAttribute('dur', '0.3s');
                animateHeight.setAttribute('begin', 'click');
                animateHeight.setAttribute('fill', 'freeze');
                animateHeight.setAttribute('keySplines', '0 0.75 0.25 1');
                animateHeight.setAttribute('calcMode','spline');
                animateHeight.setAttribute('keyTimes','0;1');

                animateY = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
                animateY.setAttribute('attributeName', 'y');
                animateY.setAttribute('from', bars[i].getAttribute('y'));
                animateY.setAttribute('to', options.bars[i].y);
                animateY.setAttribute('dur', '0.3s');
                animateY.setAttribute('begin', 'click');
                animateY.setAttribute('fill', 'freeze');
                animateY.setAttribute('keySplines', '0 0.75 0.25 1');
                animateY.setAttribute('calcMode','spline');
                animateY.setAttribute('keyTimes','0;1');

                bars[i].appendChild(animateHeight);
                bars[i].appendChild(animateY);
                bars[i].dispatchEvent( new Event("click", {"bubbles":true, "cancelable":false}) );
            }

            //Clean up the once the animation is complete.
            setTimeout(function(){
                for(var b = 0; b < bars.length; b++){
                    bars[b].setAttribute('height', options.bars[b].height);
                    bars[b].setAttribute('y', options.bars[b].y);
                    bars[b].innerHTML = '';
                }
            }, 300);

            return $id;
        }

        /**
         * Updates data for the chart
         * @public
         * @memberof db.libs.barChart
         * @param {external:jQuery|string} id Selector or jQuery element
         * @param {string|array} data An array of values or string JSON can parse to array
         * @return {external:jQuery} jQuery element
         */
        function series(id, data){
            var $id = $(id);
            var options = $id.data('options');

            options.bars = [];
            options.series = db.libs.chart.parse(data);

            if(options.max === null){
                options.max = db.libs.chart.max(options.series);
            }

            for(var b=0; b < options.series.length; b++){
                options.bars.push( bar(options, b) );
            }

            $id.data('options', options);

            return $id;
        }

        /**
         * Calculates size and position for a bar
         * @private
         * @memberof db.libs.barChart
         * @param {object} options
         * @param {number} i Index for bar to calculate
         * @return {object} height, width, x and y for bar
         */
        function bar(options, i){
            var rect = {};
            var value = options.series[i];
            var percentage = Math.round((100 / options.max) * value);
            var gutter = (options.series.length - 1) * options.gutter;

            rect.width = ( options.width - gutter ) / options.series.length;
            rect.height = ( options.height / 100 ) * percentage;
            rect.x = (i * rect.width) + (options.gutter * i);
            rect.y = options.height - rect.height;

            return rect;
        }

        /**
         * Render the chart
         * @public
         * @memberof db.libs.barChart
         * @param {external:jQuery|string} id Selector or jQuery element
         * @fires rendered
         * @return {external:jQuery} jQuery element
         */
        function render(id){
            var $id = $(id);
            var options = $id.data('options');

            if(options.gridSteps !== null){
                options.gridLines = db.libs.chart.grid(options.gridSteps, options.max);
            }

            if(options.gridStepEvery !== null){
                options.gridLines = db.libs.chart.grid(( options.max / options.gridStepEvery ), options.max);
            }

            $id.html( Mustache.render(db.templates['chart-bars'], options) );

            $id.get(0).dispatchEvent( new Event('rendered') );

            return $id;
        }

        /**
         * Initialize the component
         * @public
         * @memberof db.libs.barChart
         * @param {external:jQuery|string} [id] Selector or jQuery element
         * @return {array} Returns array of all targeted elements
         */
        function init(id, options){
            var $targets;

            if(id !== undefined){
                $targets = $(id);
            } else {
                $targets = $('.bars[data-options]');
            }

            $targets.each(function(i, el){
                if( !db.utils.isInitialized(el, name) ){
                    var $el = $(el);

                    var defaults = {
                        series: [],
                        gutter: 3,
                        max: null,
                        gridSteps: null,
                        gridStepEvery: null
                    };

                    if(id === undefined){
                        options = Foundation.utils.data_options($el);
                    }
                    options = $.extend({}, defaults, options);

                    options.width = $el.width();
                    options.height = $el.outerHeight();
                    options.gutter = (options.width / 100) * options.gutter;

                    $el.data('options', options);

                    series($el, options.series);
                    render($el);

                    db.utils.initialized(el, name);
                }
            });

            return $targets;
        }

        return {
            init: init,
            reflow: function(){},
            series: series,
            render: render,
            update: update
        };

    })(jQuery);
})();