UNPKG

nvd3-fork

Version:

FORK! of NVD3, a reusable charting library written in d3.js

262 lines (223 loc) 9.98 kB
nv.models.pieChart = function() { "use strict"; //============================================================ // Public Variables with Default Settings //------------------------------------------------------------ var pie = nv.models.pie(); var legend = nv.models.legend(); var tooltip = nv.models.tooltip(); var margin = {top: 30, right: 20, bottom: 20, left: 20} , marginTop = null , width = null , height = null , showTooltipPercent = false , showLegend = true , legendPosition = "top" , color = nv.utils.defaultColor() , state = nv.utils.state() , defaultState = null , noData = null , duration = 250 , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') ; tooltip .duration(0) .headerEnabled(false) .valueFormatter(function(d, i) { return pie.valueFormat()(d, i); }); //============================================================ // Private Variables //------------------------------------------------------------ var renderWatch = nv.utils.renderWatch(dispatch); var stateGetter = function(data) { return function(){ return { active: data.map(function(d) { return !d.disabled }) }; } }; var stateSetter = function(data) { return function(state) { if (state.active !== undefined) { data.forEach(function (series, i) { series.disabled = !state.active[i]; }); } } }; //============================================================ // Chart function //------------------------------------------------------------ function chart(selection) { renderWatch.reset(); renderWatch.models(pie); selection.each(function(data) { var container = d3.select(this); nv.utils.initSVG(container); var that = this; var availableWidth = nv.utils.availableWidth(width, container, margin), availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().call(chart); }; chart.container = this; state.setter(stateSetter(data), chart.update) .getter(stateGetter(data)) .update(); //set state.disabled state.disabled = data.map(function(d) { return !!d.disabled }); if (!defaultState) { var key; defaultState = {}; for (key in state) { if (state[key] instanceof Array) defaultState[key] = state[key].slice(0); else defaultState[key] = state[key]; } } // Display No Data message if there's nothing to show. if (!data || !data.length) { nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); } // Setup containers and skeleton of chart var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]); var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g'); var g = wrap.select('g'); gEnter.append('g').attr('class', 'nv-pieWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); // Legend if (!showLegend) { g.select('.nv-legendWrap').selectAll('*').remove(); } else { if (legendPosition === "top") { legend.width( availableWidth ).key(pie.x()); wrap.select('.nv-legendWrap') .datum(data) .call(legend); if (!marginTop && legend.height() !== margin.top) { margin.top = legend.height(); availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') .attr('transform', 'translate(0,' + (-margin.top) +')'); } else if (legendPosition === "right") { var legendWidth = nv.models.legend().width(); if (availableWidth / 2 < legendWidth) { legendWidth = (availableWidth / 2) } legend.height(availableHeight).key(pie.x()); legend.width(legendWidth); availableWidth -= legend.width(); wrap.select('.nv-legendWrap') .datum(data) .call(legend) .attr('transform', 'translate(' + (availableWidth) +',0)'); } else if (legendPosition === "bottom") { legend.width( availableWidth ).key(pie.x()); wrap.select('.nv-legendWrap') .datum(data) .call(legend); margin.bottom = legend.height(); availableHeight = nv.utils.availableHeight(height, container, margin); wrap.select('.nv-legendWrap') .attr('transform', 'translate(0,' + availableHeight +')'); } } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); // Main Chart Component(s) pie.width(availableWidth).height(availableHeight); var pieWrap = g.select('.nv-pieWrap').datum([data]); d3.transition(pieWrap).call(pie); //============================================================ // Event Handling/Dispatching (in chart's scope) //------------------------------------------------------------ legend.dispatch.on('stateChange', function(newState) { for (var key in newState) { state[key] = newState[key]; } dispatch.stateChange(state); chart.update(); }); // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; }); state.disabled = e.disabled; } chart.update(); }); }); renderWatch.renderEnd('pieChart immediate'); return chart; } //============================================================ // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ pie.dispatch.on('elementMouseover.tooltip', function(evt) { evt['series'] = { key: chart.x()(evt.data), value: chart.y()(evt.data), color: evt.color, percent: evt.percent }; if (!showTooltipPercent) { delete evt.percent; delete evt.series.percent; } tooltip.data(evt).hidden(false); }); pie.dispatch.on('elementMouseout.tooltip', function(evt) { tooltip.hidden(true); }); pie.dispatch.on('elementMousemove.tooltip', function(evt) { tooltip(); }); //============================================================ // Expose Public Variables //------------------------------------------------------------ // expose chart's sub-components chart.legend = legend; chart.dispatch = dispatch; chart.pie = pie; chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); // use Object get/set functionality to map between vars and chart functions chart._options = Object.create({}, { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, // options that require extra logic in the setter color: {get: function(){return color;}, set: function(_){ color = _; legend.color(color); pie.color(color); }}, duration: {get: function(){return duration;}, set: function(_){ duration = _; renderWatch.reset(duration); pie.duration(duration); }}, margin: {get: function(){return margin;}, set: function(_){ if (_.top !== undefined) { margin.top = _.top; marginTop = _.top; } margin.right = _.right !== undefined ? _.right : margin.right; margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; margin.left = _.left !== undefined ? _.left : margin.left; }} }); nv.utils.inheritOptions(chart, pie); nv.utils.initOptions(chart); return chart; };