2
nv.models.lineWithLegend = function() {
3
var margin = {top: 30, right: 20, bottom: 50, left: 60},
4
getWidth = function() { return 960 },
5
getHeight = function() { return 500 },
6
dotRadius = function() { return 2.5 },
7
color = d3.scale.category10().range(),
8
dispatch = d3.dispatch('tooltipShow', 'tooltipHide');
10
var x = d3.scale.linear(),
11
y = d3.scale.linear(),
12
getX = function(d) { return d.x },
13
getY = function(d) { return d.y },
14
xAxis = nv.models.xaxis().scale(x),
15
yAxis = nv.models.yaxis().scale(y),
16
legend = nv.models.legend().height(30),
17
lines = nv.models.line();
20
function chart(selection) {
21
selection.each(function(data) {
22
var width = getWidth(),
24
availableWidth = width - margin.left - margin.right,
25
availableHeight = height - margin.top - margin.bottom;
27
var series = data.filter(function(d) { return !d.disabled })
28
.map(function(d) { return d.values });
30
x .domain(d3.extent(d3.merge(series), getX ))
31
.range([0, availableWidth]);
33
y .domain(d3.extent(d3.merge(series), getY ))
34
.range([availableHeight, 0]);
37
.width(availableWidth)
38
.height(availableHeight)
39
.color(data.map(function(d,i) {
40
return d.color || color[i % 10];
41
}).filter(function(d,i) { return !data[i].disabled }))
44
var wrap = d3.select(this).selectAll('g.wrap').data([data]);
45
var gEnter = wrap.enter().append('g').attr('class', 'wrap d3lineWithLegend').append('g');
47
gEnter.append('g').attr('class', 'x axis');
48
gEnter.append('g').attr('class', 'y axis');
49
gEnter.append('g').attr('class', 'linesWrap');
50
gEnter.append('g').attr('class', 'legendWrap');
53
legend.dispatch.on('legendClick', function(d,i) {
54
d.disabled = !d.disabled;
56
if (!data.filter(function(d) { return !d.disabled }).length) {
57
data.map(function(d) {
59
wrap.selectAll('.series').classed('disabled', false);
64
selection.transition().call(chart);
69
legend.dispatch.on('legendMouseover', function(d, i) {
71
selection.transition().call(chart)
74
legend.dispatch.on('legendMouseout', function(d, i) {
76
selection.transition().call(chart)
80
lines.dispatch.on('pointMouseover.tooltip', function(e) {
81
dispatch.tooltipShow({
84
pos: [e.pos[0] + margin.left, e.pos[1] + margin.top],
85
seriesIndex: e.seriesIndex,
86
pointIndex: e.pointIndex
90
lines.dispatch.on('pointMouseout.tooltip', function(e) {
91
dispatch.tooltipHide(e);
95
//TODO: margins should be adjusted based on what components are used: axes, axis labels, legend
96
margin.top = legend.height();
98
var g = wrap.select('g')
99
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
102
legend.width(width/2 - margin.right);
104
g.select('.legendWrap')
106
.attr('transform', 'translate(' + (width/2 - margin.left) + ',' + (-margin.top) +')')
110
var linesWrap = g.select('.linesWrap')
111
.datum(data.filter(function(d) { return !d.disabled }))
114
d3.transition(linesWrap).call(lines);
116
var timeSeries = (data.length > 0 && data[0].values.length > 0 &&
117
data[0].values[0].x instanceof Date);
122
.scale(d3.time.scale())
123
.ticks(d3.time.days, 0)
124
.tickSize(-availableHeight, 0);
129
.ticks( width / 100 )
130
.tickSize(-availableHeight, 0);
134
.attr('transform', 'translate(0,' + y.range()[0] + ')');
135
d3.transition(g.select('.x.axis'))
141
.ticks( height / 36 )
142
.tickSize(-availableWidth, 0);
144
d3.transition(g.select('.y.axis'))
152
chart.dispatch = dispatch;
153
chart.legend = legend;
157
chart.x = function(_) {
158
if (!arguments.length) return getX;
164
chart.y = function(_) {
165
if (!arguments.length) return getY;
171
chart.margin = function(_) {
172
if (!arguments.length) return margin;
177
chart.width = function(_) {
178
if (!arguments.length) return getWidth;
179
getWidth = d3.functor(_);
183
chart.height = function(_) {
184
if (!arguments.length) return getHeight;
185
getHeight = d3.functor(_);
189
chart.dotRadius = function(_) {
190
if (!arguments.length) return dotRadius;
191
dotRadius = d3.functor(_);