;(function () { 'use strict'; /** * Draw simple pie chart using svg. * @namespace */ db.libs.pieChart = (function($){ var name = 'pieChart'; /** * Animates chart to values to in series. * @public * @memberof db.libs.pieChart * @param {external:jQuery|string} id Selector or jQuery element * @return {external:jQuery} jQuery element */ function update(id){ var $id = $(id); var options = $id.data('options'); var slices = $id.get(0).querySelectorAll('.slice'); var animate, animateTransform; for(var i = 0; i < slices.length; i++){ animate = document.createElementNS('http://www.w3.org/2000/svg', 'animate'); animate.setAttribute('attributeName', 'd'); animate.setAttribute('from', slices[i].getAttribute('d')); animate.setAttribute('to', options.slices[i].path); animate.setAttribute('dur', '0.3s'); animate.setAttribute('begin', 'click'); animate.setAttribute('fill', 'freeze'); animate.setAttribute('keySplines', '0 0.75 0.25 1'); animate.setAttribute('calcMode','spline'); animate.setAttribute('keyTimes','0;1'); animateTransform = document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform'); animateTransform.setAttribute('attributeName', 'transform'); animateTransform.setAttribute('type', 'rotate'); animateTransform.setAttribute('from', slices[i].getAttribute('transform').replace('rotate(','').replace(')','')); animateTransform.setAttribute('to', options.slices[i].rotation + ' 200 200'); animateTransform.setAttribute('dur', '0.3s'); animateTransform.setAttribute('begin', 'click'); animateTransform.setAttribute('fill', 'freeze'); animateTransform.setAttribute('keySplines', '0 0.75 0.25 1'); animateTransform.setAttribute('calcMode','spline'); animateTransform.setAttribute('keyTimes','0;1'); slices[i].appendChild(animate); slices[i].appendChild(animateTransform); slices[i].dispatchEvent( new Event('click', {'bubbles':true, 'cancelable':false}) ); } // Clean up the once the animation is complete. setTimeout(function(){ for(var s = 0; s < slices.length; s++){ slices[s].setAttribute('d', options.slices[s].path); slices[s].setAttribute('transform', 'rotate(' + options.slices[s].rotation + ' 200 200)'); slices[s].innerHTML = ''; } }, 300); return $id; } /** * Updates data series. * @public * @memberof db.libs.pieChart * @param {external:jQuery|string} id Selector or jQuery element * @param {array|string} data Series data. Accepts array or string that can be parsed to array using JSON.parse * @return {external:jQuery} jQuery element */ function series(id, data){ var $id = $(id); var options = $id.data('options'); var rotation = 0; options.slices = []; options.series = db.libs.chart.parse(data); options.total = db.libs.chart.sum(options.series); for(var i=0; i < options.series.length; i++){ options.slices.push( slice(options.series[i], options.total, rotation) ); rotation += options.slices[options.slices.length - 1].degrees; } $id.data('options', options); return $id; } /** * Returns values for a slice * @private * @memberof db.libs.pieChart * @param {number} value The value for the slice * @param {number} total The total value for the chart * @param {number} rotation The rotation for the slice * @return {object} object containing data needed to draw the slice */ function slice(value, total, rotation){ var degrees = (value * 360) / total; var x1 = 200 + 180 * Math.cos( Math.PI * 0 / 180); var y1 = 200 + 180 * Math.sin( Math.PI * 0 / 180); var x2 = 200 + 180 * Math.cos( Math.PI * degrees / 180); var y2 = 200 + 180 * Math.sin( Math.PI * degrees / 180); return { degrees: degrees, rotation: rotation, path: "M 200 200 L " + x1 + " " + y1 + " A 180 180 0 0 1 " + x2 + " " + y2 + " Z" }; } /** * Render the chart * @public * @memberof db.libs.pieChart * @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'); options.donut = ((options.width / 2) / 100) * options.donut; $id.html( Mustache.render(db.templates['chart-pie'], options) ); $id.get(0).dispatchEvent( new Event('rendered') ); return $id; } /** * Initialize the component * @public * @example <caption>Initializing can be done with or without jQuery</caption> * db.libs.pieChart(document.getElementById('pieChartDemo'), { series: [113,100,50,28,27,44,68,52] }); * $('#pieChartDemo').pieChart({ series: [113,100,50,28,27,44,68,52] }); * @memberof db.libs.pieChart * @param {external:jQuery|string} [id] Selector or jQuery element * @param {object} [options] Options can be passed to init or read from the data-options attribute on the element * @param {number} [options.width=400] Width given as pixels * @param {number} [options.height=400] Height given as pixels * @param {number} [options.donut=0] Size of donut given as a percentage size of the chart * @param {array} [options.series] Values used to create the chart * @return {array} Returns array of all targeted elements */ function init(id, options){ var $targets; if(id !== undefined){ $targets = $(id); } else { $targets = $('.pie[data-options]'); } $targets.each(function(i, el){ if( !db.utils.isInitialized(el, name) ){ var $el = $(el); var defaults = { width: 400, height: 400, donut: 50, series: [], angles: [], paths: [], slices: [], total: 0 }; if(id === undefined){ options = Foundation.utils.data_options($el); } options = $.extend({}, defaults, options); $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); })();