UNPKG

nvd3-fork

Version:

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

284 lines (235 loc) 10.3 kB
nv.models.discreteBarChart = function() { "use strict"; //============================================================ // Public Variables with Default Settings //------------------------------------------------------------ var discretebar = nv.models.discreteBar() , xAxis = nv.models.axis() , yAxis = nv.models.axis() , legend = nv.models.legend() , tooltip = nv.models.tooltip() ; var margin = {top: 15, right: 10, bottom: 50, left: 60} , marginTop = null , width = null , height = null , color = nv.utils.getColor() , showLegend = false , showXAxis = true , showYAxis = true , rightAlignYAxis = false , staggerLabels = false , wrapLabels = false , rotateLabels = 0 , x , y , noData = null , dispatch = d3.dispatch('beforeUpdate','renderEnd') , duration = 250 ; xAxis .orient('bottom') .showMaxMin(false) .tickFormat(function(d) { return d }) ; yAxis .orient((rightAlignYAxis) ? 'right' : 'left') .tickFormat(d3.format(',.1f')) ; tooltip .duration(0) .headerEnabled(false) .valueFormatter(function(d, i) { return yAxis.tickFormat()(d, i); }) .keyFormatter(function(d, i) { return xAxis.tickFormat()(d, i); }); //============================================================ // Private Variables //------------------------------------------------------------ var renderWatch = nv.utils.renderWatch(dispatch, duration); function chart(selection) { renderWatch.reset(); renderWatch.models(discretebar); if (showXAxis) renderWatch.models(xAxis); if (showYAxis) renderWatch.models(yAxis); selection.each(function(data) { var container = d3.select(this), that = this; nv.utils.initSVG(container); var availableWidth = nv.utils.availableWidth(width, container, margin), availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { dispatch.beforeUpdate(); container.transition().duration(duration).call(chart); }; chart.container = this; // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); } // Setup Scales x = discretebar.xScale(); y = discretebar.yScale().clamp(true); // Setup containers and skeleton of chart var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]); var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g'); var defsEnter = gEnter.append('defs'); var g = wrap.select('g'); gEnter.append('g').attr('class', 'nv-x nv-axis'); gEnter.append('g').attr('class', 'nv-y nv-axis') .append('g').attr('class', 'nv-zeroLine') .append('line'); gEnter.append('g').attr('class', 'nv-barsWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); // Legend if (!showLegend) { g.select('.nv-legendWrap').selectAll('*').remove(); } else { legend.width(availableWidth); g.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) +')') } if (rightAlignYAxis) { g.select(".nv-y.nv-axis") .attr("transform", "translate(" + availableWidth + ",0)"); } // Main Chart Component(s) discretebar .width(availableWidth) .height(availableHeight); var barsWrap = g.select('.nv-barsWrap') .datum(data.filter(function(d) { return !d.disabled })); barsWrap.transition().call(discretebar); defsEnter.append('clipPath') .attr('id', 'nv-x-label-clip-' + discretebar.id()) .append('rect'); g.select('#nv-x-label-clip-' + discretebar.id() + ' rect') .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) .attr('height', 16) .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); // Setup Axes if (showXAxis) { xAxis .scale(x) ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')'); g.select('.nv-x.nv-axis').call(xAxis); var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); if (staggerLabels) { xTicks .selectAll('text') .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) } if (rotateLabels) { xTicks .selectAll('.tick text') .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); } if (wrapLabels) { g.selectAll('.tick text') .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) } } if (showYAxis) { yAxis .scale(y) ._ticks( nv.utils.calcTicksY(availableHeight/36, data, discretebar.y()) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis').call(yAxis); } // Zero line g.select(".nv-zeroLine line") .attr("x1",0) .attr("x2",(rightAlignYAxis) ? -availableWidth : availableWidth) .attr("y1", y(0)) .attr("y2", y(0)) ; }); renderWatch.renderEnd('discreteBar chart immediate'); return chart; } //============================================================ // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ discretebar.dispatch.on('elementMouseover.tooltip', function(evt) { evt['series'] = { key: chart.x()(evt.data), value: chart.y()(evt.data), color: evt.color }; tooltip.data(evt).hidden(false); }); discretebar.dispatch.on('elementMouseout.tooltip', function(evt) { tooltip.hidden(true); }); discretebar.dispatch.on('elementMousemove.tooltip', function(evt) { tooltip(); }); //============================================================ // Expose Public Variables //------------------------------------------------------------ chart.dispatch = dispatch; chart.discretebar = discretebar; chart.legend = legend; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); 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=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, // options that require extra logic in the setter 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; }}, duration: {get: function(){return duration;}, set: function(_){ duration = _; renderWatch.reset(duration); discretebar.duration(duration); xAxis.duration(duration); yAxis.duration(duration); }}, color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); discretebar.color(color); legend.color(color); }}, rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ rightAlignYAxis = _; yAxis.orient( (_) ? 'right' : 'left'); }} }); nv.utils.inheritOptions(chart, discretebar); nv.utils.initOptions(chart); return chart; }