/*** * This chart treats the X position as the INDEX, not the value * Each series at the same index MUST be the same x value for a valid representation * This is needed specifically for daily data where the gap between Friday and Monday * should be equal to the gap from Monday to Tuesday. (and of course, holidays can be * omitted without issue, as long as ALL series omit the same days). * An intentional side effect is that ALL ticks will land on actual data points, * so this visualization can also be used for Month End data points, showing Month End * ticks on the X axis ***/ nv.charts.stackedAreaChart = function() { var selector = null, data = [], duration = 500, tooltip = function(key, x, y, e, graph) { return '
' + y + ' at ' + x + '
' }; var graph = nv.models.stackedAreaWithLegend() .x(function(d,i) { return i }), showTooltip = function(e) { var offsetElement = document.getElementById(selector.substr(1)), left = e.pos[0] + offsetElement.offsetLeft, top = e.pos[1] + offsetElement.offsetTop, formatX = graph.xAxis.tickFormat(), formatY = graph.yAxis.tickFormat(), x = formatX(graph.x()(e, e.pointIndex)), //x = formatX(graph.x()(e.point)), y = formatY(graph.y()(e.point)), content = tooltip(e.series.key, x, y, e, graph); nv.tooltip.show([left, top], content); }; //setting component defaults //graph.xAxis.tickFormat(d3.format(',r')); graph.xAxis.tickFormat(function(d) { //return d3.time.format('%x')(new Date(d)) //log(d, data[0].values[d]); return d3.time.format('%x')(new Date(data[0].values[d].x)) }); //graph.yAxis.tickFormat(d3.format(',.2f')); graph.yAxis.tickFormat(d3.format(',.2%')); //TODO: consider a method more similar to how the models are built function chart() { if (!selector || !data.length) return chart; //do nothing if you have nothing to work with d3.select(selector).select('svg') .datum(data) .transition().duration(duration) .call(graph); //consider using transition chaining like in the models return chart; } // This should always only be called once, then update should be used after, // in which case should consider the 'd3 way' and merge this with update, // but simply do this on enter... should try anoter example that way chart.build = function() { if (!selector || !data.length) return chart; //do nothing if you have nothing to work with nv.addGraph({ generate: function() { var container = d3.select(selector), width = function() { return parseInt(container.style('width')) }, height = function() { return parseInt(container.style('height')) }, svg = container.append('svg'); graph .width(width) .height(height); svg .attr('width', width()) .attr('height', height()) .datum(data) .transition().duration(duration) .call(graph); return graph; }, callback: function(graph) { graph.dispatch.on('tooltipShow', showTooltip); graph.dispatch.on('tooltipHide', nv.tooltip.cleanup); //TODO: create resize queue and have nv core handle resize instead of binding all to window resize window.onresize = function() { // now that width and height are functions, should be automatic..of course you can always override them d3.select(selector + ' svg') .attr('width', graph.width()()) //need to set SVG dimensions, chart is not aware of the SVG component .attr('height', graph.height()()) .call(graph); }; } }); return chart; }; /* // moved to chart() chart.update = function() { if (!selector || !data.length) return chart; //do nothing if you have nothing to work with d3.select(selector).select('svg') .datum(data) .transition().duration(duration).call(graph); return chart; }; */ chart.data = function(_) { if (!arguments.length) return data; data = _; return chart; }; chart.selector = function(_) { if (!arguments.length) return selector; selector = _; return chart; }; chart.duration = function(_) { if (!arguments.length) return duration; duration = _; return chart; }; chart.tooltip = function(_) { if (!arguments.length) return tooltip; tooltip = _; return chart; }; chart.xTickFormat = function(_) { if (!arguments.length) return graph.xAxis.tickFormat(); graph.xAxis.tickFormat(typeof _ === 'function' ? _ : d3.format(_)); return chart; }; chart.yTickFormat = function(_) { if (!arguments.length) return graph.yAxis.tickFormat(); graph.yAxis.tickFormat(typeof _ === 'function' ? _ : d3.format(_)); return chart; }; chart.xAxisLabel = function(_) { if (!arguments.length) return graph.xAxis.axisLabel(); graph.xAxis.axisLabel(_); return chart; }; chart.yAxisLabel = function(_) { if (!arguments.length) return graph.yAxis.axisLabel(); graph.yAxis.axisLabel(_); return chart; }; d3.rebind(chart, graph, 'x', 'y'); chart.graph = graph; // Give direct access for getter/setters, and dispatchers return chart; };