pyk 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/app/assets/javascripts/lib/chardinjs.min.js +2 -0
- data/app/assets/javascripts/lib/crossfilter.js +1383 -1
- data/app/assets/javascripts/lib/{d3.js → d3.v3.js} +0 -0
- data/app/assets/javascripts/lib/dc.js +3492 -757
- data/app/assets/javascripts/lib/jquery.gridster.js +2 -3621
- data/app/assets/javascripts/lib/markermanager.js +2 -980
- data/app/assets/javascripts/lib/underscore.js +1276 -0
- data/app/assets/javascripts/nvd3/lib/colorbrewer.js +302 -0
- data/app/assets/javascripts/nvd3/lib/crossfilter.js +1180 -0
- data/app/assets/javascripts/nvd3/lib/crossfilter.min.js +1 -0
- data/app/assets/javascripts/nvd3/lib/d3.v2.js +7033 -0
- data/app/assets/javascripts/nvd3/lib/d3.v2.min.js +4 -0
- data/app/assets/javascripts/nvd3/lib/d3.v3.js +8436 -0
- data/app/assets/javascripts/nvd3/lib/fisheye.js +86 -0
- data/app/assets/javascripts/nvd3/lib/hive.js +80 -0
- data/app/assets/javascripts/nvd3/lib/horizon.js +192 -0
- data/app/assets/javascripts/nvd3/lib/sankey.js +292 -0
- data/app/assets/javascripts/nvd3/nv.d3.js +14312 -0
- data/app/assets/javascripts/nvd3/nv.d3.min.js +6 -0
- data/app/assets/javascripts/nvd3/src/core.js +122 -0
- data/app/assets/javascripts/nvd3/src/interactiveLayer.js +251 -0
- data/app/assets/javascripts/nvd3/src/models/axis.js +405 -0
- data/app/assets/javascripts/nvd3/src/models/backup/bullet.js +250 -0
- data/app/assets/javascripts/nvd3/src/models/backup/bulletChart.js +349 -0
- data/app/assets/javascripts/nvd3/src/models/boilerplate.js +104 -0
- data/app/assets/javascripts/nvd3/src/models/bullet.js +385 -0
- data/app/assets/javascripts/nvd3/src/models/bulletChart.js +343 -0
- data/app/assets/javascripts/nvd3/src/models/cumulativeLineChart.js +782 -0
- data/app/assets/javascripts/nvd3/src/models/discreteBar.js +349 -0
- data/app/assets/javascripts/nvd3/src/models/discreteBarChart.js +333 -0
- data/app/assets/javascripts/nvd3/src/models/distribution.js +148 -0
- data/app/assets/javascripts/nvd3/src/models/historicalBar.js +331 -0
- data/app/assets/javascripts/nvd3/src/models/historicalBarChart.js +419 -0
- data/app/assets/javascripts/nvd3/src/models/indentedTree.js +337 -0
- data/app/assets/javascripts/nvd3/src/models/legend.js +270 -0
- data/app/assets/javascripts/nvd3/src/models/line.js +284 -0
- data/app/assets/javascripts/nvd3/src/models/lineChart.js +465 -0
- data/app/assets/javascripts/nvd3/src/models/linePlusBarChart.js +433 -0
- data/app/assets/javascripts/nvd3/src/models/linePlusBarWithFocusChart.js +658 -0
- data/app/assets/javascripts/nvd3/src/models/lineWithFisheye.js +200 -0
- data/app/assets/javascripts/nvd3/src/models/lineWithFisheyeChart.js +297 -0
- data/app/assets/javascripts/nvd3/src/models/lineWithFocusChart.js +574 -0
- data/app/assets/javascripts/nvd3/src/models/multiBar.js +461 -0
- data/app/assets/javascripts/nvd3/src/models/multiBarChart.js +524 -0
- data/app/assets/javascripts/nvd3/src/models/multiBarHorizontal.js +424 -0
- data/app/assets/javascripts/nvd3/src/models/multiBarHorizontalChart.js +434 -0
- data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeries.js +384 -0
- data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeriesChart.js +405 -0
- data/app/assets/javascripts/nvd3/src/models/multiChart.js +452 -0
- data/app/assets/javascripts/nvd3/src/models/ohlcBar.js +380 -0
- data/app/assets/javascripts/nvd3/src/models/parallelCoordinates.js +239 -0
- data/app/assets/javascripts/nvd3/src/models/pie.js +398 -0
- data/app/assets/javascripts/nvd3/src/models/pieChart.js +292 -0
- data/app/assets/javascripts/nvd3/src/models/scatter.js +674 -0
- data/app/assets/javascripts/nvd3/src/models/scatterChart.js +628 -0
- data/app/assets/javascripts/nvd3/src/models/scatterPlusLineChart.js +620 -0
- data/app/assets/javascripts/nvd3/src/models/sparkline.js +194 -0
- data/app/assets/javascripts/nvd3/src/models/sparklinePlus.js +295 -0
- data/app/assets/javascripts/nvd3/src/models/stackedArea.js +368 -0
- data/app/assets/javascripts/nvd3/src/models/stackedAreaChart.js +629 -0
- data/app/assets/javascripts/nvd3/src/tooltip.js +490 -0
- data/app/assets/javascripts/nvd3/src/utils.js +152 -0
- data/app/assets/javascripts/pyk.js +1 -0
- data/app/assets/stylesheets/lib/chardinjs.css +82 -0
- data/app/assets/stylesheets/nvd3/nv.d3.css +769 -0
- data/app/assets/stylesheets/pyk.css.scss +1 -0
- metadata +61 -2
@@ -0,0 +1,343 @@
|
|
1
|
+
|
2
|
+
// Chart design based on the recommendations of Stephen Few. Implementation
|
3
|
+
// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
|
4
|
+
// http://projects.instantcognition.com/protovis/bulletchart/
|
5
|
+
nv.models.bulletChart = function() {
|
6
|
+
"use strict";
|
7
|
+
//============================================================
|
8
|
+
// Public Variables with Default Settings
|
9
|
+
//------------------------------------------------------------
|
10
|
+
|
11
|
+
var bullet = nv.models.bullet()
|
12
|
+
;
|
13
|
+
|
14
|
+
var orient = 'left' // TODO top & bottom
|
15
|
+
, reverse = false
|
16
|
+
, margin = {top: 5, right: 40, bottom: 20, left: 120}
|
17
|
+
, ranges = function(d) { return d.ranges }
|
18
|
+
, markers = function(d) { return d.markers }
|
19
|
+
, measures = function(d) { return d.measures }
|
20
|
+
, width = null
|
21
|
+
, height = 55
|
22
|
+
, tickFormat = null
|
23
|
+
, tooltips = true
|
24
|
+
, tooltip = function(key, x, y, e, graph) {
|
25
|
+
return '<h3>' + x + '</h3>' +
|
26
|
+
'<p>' + y + '</p>'
|
27
|
+
}
|
28
|
+
, noData = 'No Data Available.'
|
29
|
+
, dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
|
30
|
+
;
|
31
|
+
|
32
|
+
//============================================================
|
33
|
+
|
34
|
+
|
35
|
+
//============================================================
|
36
|
+
// Private Variables
|
37
|
+
//------------------------------------------------------------
|
38
|
+
|
39
|
+
var showTooltip = function(e, offsetElement) {
|
40
|
+
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ) + margin.left,
|
41
|
+
top = e.pos[1] + ( offsetElement.offsetTop || 0) + margin.top,
|
42
|
+
content = tooltip(e.key, e.label, e.value, e, chart);
|
43
|
+
|
44
|
+
nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement);
|
45
|
+
};
|
46
|
+
|
47
|
+
//============================================================
|
48
|
+
|
49
|
+
|
50
|
+
function chart(selection) {
|
51
|
+
selection.each(function(d, i) {
|
52
|
+
var container = d3.select(this);
|
53
|
+
|
54
|
+
var availableWidth = (width || parseInt(container.style('width')) || 960)
|
55
|
+
- margin.left - margin.right,
|
56
|
+
availableHeight = height - margin.top - margin.bottom,
|
57
|
+
that = this;
|
58
|
+
|
59
|
+
|
60
|
+
chart.update = function() { chart(selection) };
|
61
|
+
chart.container = this;
|
62
|
+
|
63
|
+
//------------------------------------------------------------
|
64
|
+
// Display No Data message if there's nothing to show.
|
65
|
+
|
66
|
+
if (!d || !ranges.call(this, d, i)) {
|
67
|
+
var noDataText = container.selectAll('.nv-noData').data([noData]);
|
68
|
+
|
69
|
+
noDataText.enter().append('text')
|
70
|
+
.attr('class', 'nvd3 nv-noData')
|
71
|
+
.attr('dy', '-.7em')
|
72
|
+
.style('text-anchor', 'middle');
|
73
|
+
|
74
|
+
noDataText
|
75
|
+
.attr('x', margin.left + availableWidth / 2)
|
76
|
+
.attr('y', 18 + margin.top + availableHeight / 2)
|
77
|
+
.text(function(d) { return d });
|
78
|
+
|
79
|
+
return chart;
|
80
|
+
} else {
|
81
|
+
container.selectAll('.nv-noData').remove();
|
82
|
+
}
|
83
|
+
|
84
|
+
//------------------------------------------------------------
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
|
89
|
+
markerz = markers.call(this, d, i).slice().sort(d3.descending),
|
90
|
+
measurez = measures.call(this, d, i).slice().sort(d3.descending);
|
91
|
+
|
92
|
+
|
93
|
+
//------------------------------------------------------------
|
94
|
+
// Setup containers and skeleton of chart
|
95
|
+
|
96
|
+
var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]);
|
97
|
+
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');
|
98
|
+
var gEnter = wrapEnter.append('g');
|
99
|
+
var g = wrap.select('g');
|
100
|
+
|
101
|
+
gEnter.append('g').attr('class', 'nv-bulletWrap');
|
102
|
+
gEnter.append('g').attr('class', 'nv-titles');
|
103
|
+
|
104
|
+
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
105
|
+
|
106
|
+
//------------------------------------------------------------
|
107
|
+
|
108
|
+
|
109
|
+
// Compute the new x-scale.
|
110
|
+
var x1 = d3.scale.linear()
|
111
|
+
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
|
112
|
+
.range(reverse ? [availableWidth, 0] : [0, availableWidth]);
|
113
|
+
|
114
|
+
// Retrieve the old x-scale, if this is an update.
|
115
|
+
var x0 = this.__chart__ || d3.scale.linear()
|
116
|
+
.domain([0, Infinity])
|
117
|
+
.range(x1.range());
|
118
|
+
|
119
|
+
// Stash the new scale.
|
120
|
+
this.__chart__ = x1;
|
121
|
+
|
122
|
+
/*
|
123
|
+
// Derive width-scales from the x-scales.
|
124
|
+
var w0 = bulletWidth(x0),
|
125
|
+
w1 = bulletWidth(x1);
|
126
|
+
|
127
|
+
function bulletWidth(x) {
|
128
|
+
var x0 = x(0);
|
129
|
+
return function(d) {
|
130
|
+
return Math.abs(x(d) - x(0));
|
131
|
+
};
|
132
|
+
}
|
133
|
+
|
134
|
+
function bulletTranslate(x) {
|
135
|
+
return function(d) {
|
136
|
+
return 'translate(' + x(d) + ',0)';
|
137
|
+
};
|
138
|
+
}
|
139
|
+
*/
|
140
|
+
|
141
|
+
var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
|
142
|
+
w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
|
143
|
+
|
144
|
+
|
145
|
+
var title = gEnter.select('.nv-titles').append('g')
|
146
|
+
.attr('text-anchor', 'end')
|
147
|
+
.attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');
|
148
|
+
title.append('text')
|
149
|
+
.attr('class', 'nv-title')
|
150
|
+
.text(function(d) { return d.title; });
|
151
|
+
|
152
|
+
title.append('text')
|
153
|
+
.attr('class', 'nv-subtitle')
|
154
|
+
.attr('dy', '1em')
|
155
|
+
.text(function(d) { return d.subtitle; });
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
bullet
|
160
|
+
.width(availableWidth)
|
161
|
+
.height(availableHeight)
|
162
|
+
|
163
|
+
var bulletWrap = g.select('.nv-bulletWrap');
|
164
|
+
|
165
|
+
d3.transition(bulletWrap).call(bullet);
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
// Compute the tick format.
|
170
|
+
var format = tickFormat || x1.tickFormat( availableWidth / 100 );
|
171
|
+
|
172
|
+
// Update the tick groups.
|
173
|
+
var tick = g.selectAll('g.nv-tick')
|
174
|
+
.data(x1.ticks( availableWidth / 50 ), function(d) {
|
175
|
+
return this.textContent || format(d);
|
176
|
+
});
|
177
|
+
|
178
|
+
// Initialize the ticks with the old scale, x0.
|
179
|
+
var tickEnter = tick.enter().append('g')
|
180
|
+
.attr('class', 'nv-tick')
|
181
|
+
.attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' })
|
182
|
+
.style('opacity', 1e-6);
|
183
|
+
|
184
|
+
tickEnter.append('line')
|
185
|
+
.attr('y1', availableHeight)
|
186
|
+
.attr('y2', availableHeight * 7 / 6);
|
187
|
+
|
188
|
+
tickEnter.append('text')
|
189
|
+
.attr('text-anchor', 'middle')
|
190
|
+
.attr('dy', '1em')
|
191
|
+
.attr('y', availableHeight * 7 / 6)
|
192
|
+
.text(format);
|
193
|
+
|
194
|
+
|
195
|
+
// Transition the updating ticks to the new scale, x1.
|
196
|
+
var tickUpdate = d3.transition(tick)
|
197
|
+
.attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
|
198
|
+
.style('opacity', 1);
|
199
|
+
|
200
|
+
tickUpdate.select('line')
|
201
|
+
.attr('y1', availableHeight)
|
202
|
+
.attr('y2', availableHeight * 7 / 6);
|
203
|
+
|
204
|
+
tickUpdate.select('text')
|
205
|
+
.attr('y', availableHeight * 7 / 6);
|
206
|
+
|
207
|
+
// Transition the exiting ticks to the new scale, x1.
|
208
|
+
d3.transition(tick.exit())
|
209
|
+
.attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
|
210
|
+
.style('opacity', 1e-6)
|
211
|
+
.remove();
|
212
|
+
|
213
|
+
|
214
|
+
//============================================================
|
215
|
+
// Event Handling/Dispatching (in chart's scope)
|
216
|
+
//------------------------------------------------------------
|
217
|
+
|
218
|
+
dispatch.on('tooltipShow', function(e) {
|
219
|
+
e.key = d.title;
|
220
|
+
if (tooltips) showTooltip(e, that.parentNode);
|
221
|
+
});
|
222
|
+
|
223
|
+
//============================================================
|
224
|
+
|
225
|
+
});
|
226
|
+
|
227
|
+
d3.timer.flush();
|
228
|
+
|
229
|
+
return chart;
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
//============================================================
|
234
|
+
// Event Handling/Dispatching (out of chart's scope)
|
235
|
+
//------------------------------------------------------------
|
236
|
+
|
237
|
+
bullet.dispatch.on('elementMouseover.tooltip', function(e) {
|
238
|
+
dispatch.tooltipShow(e);
|
239
|
+
});
|
240
|
+
|
241
|
+
bullet.dispatch.on('elementMouseout.tooltip', function(e) {
|
242
|
+
dispatch.tooltipHide(e);
|
243
|
+
});
|
244
|
+
|
245
|
+
dispatch.on('tooltipHide', function() {
|
246
|
+
if (tooltips) nv.tooltip.cleanup();
|
247
|
+
});
|
248
|
+
|
249
|
+
//============================================================
|
250
|
+
|
251
|
+
|
252
|
+
//============================================================
|
253
|
+
// Expose Public Variables
|
254
|
+
//------------------------------------------------------------
|
255
|
+
|
256
|
+
chart.dispatch = dispatch;
|
257
|
+
chart.bullet = bullet;
|
258
|
+
|
259
|
+
d3.rebind(chart, bullet, 'color');
|
260
|
+
|
261
|
+
chart.options = nv.utils.optionsFunc.bind(chart);
|
262
|
+
|
263
|
+
// left, right, top, bottom
|
264
|
+
chart.orient = function(x) {
|
265
|
+
if (!arguments.length) return orient;
|
266
|
+
orient = x;
|
267
|
+
reverse = orient == 'right' || orient == 'bottom';
|
268
|
+
return chart;
|
269
|
+
};
|
270
|
+
|
271
|
+
// ranges (bad, satisfactory, good)
|
272
|
+
chart.ranges = function(x) {
|
273
|
+
if (!arguments.length) return ranges;
|
274
|
+
ranges = x;
|
275
|
+
return chart;
|
276
|
+
};
|
277
|
+
|
278
|
+
// markers (previous, goal)
|
279
|
+
chart.markers = function(x) {
|
280
|
+
if (!arguments.length) return markers;
|
281
|
+
markers = x;
|
282
|
+
return chart;
|
283
|
+
};
|
284
|
+
|
285
|
+
// measures (actual, forecast)
|
286
|
+
chart.measures = function(x) {
|
287
|
+
if (!arguments.length) return measures;
|
288
|
+
measures = x;
|
289
|
+
return chart;
|
290
|
+
};
|
291
|
+
|
292
|
+
chart.width = function(x) {
|
293
|
+
if (!arguments.length) return width;
|
294
|
+
width = x;
|
295
|
+
return chart;
|
296
|
+
};
|
297
|
+
|
298
|
+
chart.height = function(x) {
|
299
|
+
if (!arguments.length) return height;
|
300
|
+
height = x;
|
301
|
+
return chart;
|
302
|
+
};
|
303
|
+
|
304
|
+
chart.margin = function(_) {
|
305
|
+
if (!arguments.length) return margin;
|
306
|
+
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
|
307
|
+
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
|
308
|
+
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
|
309
|
+
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
|
310
|
+
return chart;
|
311
|
+
};
|
312
|
+
|
313
|
+
chart.tickFormat = function(x) {
|
314
|
+
if (!arguments.length) return tickFormat;
|
315
|
+
tickFormat = x;
|
316
|
+
return chart;
|
317
|
+
};
|
318
|
+
|
319
|
+
chart.tooltips = function(_) {
|
320
|
+
if (!arguments.length) return tooltips;
|
321
|
+
tooltips = _;
|
322
|
+
return chart;
|
323
|
+
};
|
324
|
+
|
325
|
+
chart.tooltipContent = function(_) {
|
326
|
+
if (!arguments.length) return tooltip;
|
327
|
+
tooltip = _;
|
328
|
+
return chart;
|
329
|
+
};
|
330
|
+
|
331
|
+
chart.noData = function(_) {
|
332
|
+
if (!arguments.length) return noData;
|
333
|
+
noData = _;
|
334
|
+
return chart;
|
335
|
+
};
|
336
|
+
|
337
|
+
//============================================================
|
338
|
+
|
339
|
+
|
340
|
+
return chart;
|
341
|
+
};
|
342
|
+
|
343
|
+
|
@@ -0,0 +1,782 @@
|
|
1
|
+
|
2
|
+
nv.models.cumulativeLineChart = function() {
|
3
|
+
"use strict";
|
4
|
+
//============================================================
|
5
|
+
// Public Variables with Default Settings
|
6
|
+
//------------------------------------------------------------
|
7
|
+
|
8
|
+
var lines = nv.models.line()
|
9
|
+
, xAxis = nv.models.axis()
|
10
|
+
, yAxis = nv.models.axis()
|
11
|
+
, legend = nv.models.legend()
|
12
|
+
, controls = nv.models.legend()
|
13
|
+
, interactiveLayer = nv.interactiveGuideline()
|
14
|
+
;
|
15
|
+
|
16
|
+
var margin = {top: 30, right: 30, bottom: 50, left: 60}
|
17
|
+
, color = nv.utils.defaultColor()
|
18
|
+
, width = null
|
19
|
+
, height = null
|
20
|
+
, showLegend = true
|
21
|
+
, showXAxis = true
|
22
|
+
, showYAxis = true
|
23
|
+
, rightAlignYAxis = false
|
24
|
+
, tooltips = true
|
25
|
+
, showControls = true
|
26
|
+
, useInteractiveGuideline = false
|
27
|
+
, rescaleY = true
|
28
|
+
, tooltip = function(key, x, y, e, graph) {
|
29
|
+
return '<h3>' + key + '</h3>' +
|
30
|
+
'<p>' + y + ' at ' + x + '</p>'
|
31
|
+
}
|
32
|
+
, x //can be accessed via chart.xScale()
|
33
|
+
, y //can be accessed via chart.yScale()
|
34
|
+
, id = lines.id()
|
35
|
+
, state = { index: 0, rescaleY: rescaleY }
|
36
|
+
, defaultState = null
|
37
|
+
, noData = 'No Data Available.'
|
38
|
+
, average = function(d) { return d.average }
|
39
|
+
, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
|
40
|
+
, transitionDuration = 250
|
41
|
+
;
|
42
|
+
|
43
|
+
xAxis
|
44
|
+
.orient('bottom')
|
45
|
+
.tickPadding(7)
|
46
|
+
;
|
47
|
+
yAxis
|
48
|
+
.orient((rightAlignYAxis) ? 'right' : 'left')
|
49
|
+
;
|
50
|
+
|
51
|
+
//============================================================
|
52
|
+
controls.updateState(false);
|
53
|
+
|
54
|
+
//============================================================
|
55
|
+
// Private Variables
|
56
|
+
//------------------------------------------------------------
|
57
|
+
|
58
|
+
var dx = d3.scale.linear()
|
59
|
+
, index = {i: 0, x: 0}
|
60
|
+
;
|
61
|
+
|
62
|
+
var showTooltip = function(e, offsetElement) {
|
63
|
+
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
|
64
|
+
top = e.pos[1] + ( offsetElement.offsetTop || 0),
|
65
|
+
x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
|
66
|
+
y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),
|
67
|
+
content = tooltip(e.series.key, x, y, e, chart);
|
68
|
+
|
69
|
+
nv.tooltip.show([left, top], content, null, null, offsetElement);
|
70
|
+
};
|
71
|
+
|
72
|
+
/*
|
73
|
+
//Moved to see if we can get better behavior to fix issue #315
|
74
|
+
var indexDrag = d3.behavior.drag()
|
75
|
+
.on('dragstart', dragStart)
|
76
|
+
.on('drag', dragMove)
|
77
|
+
.on('dragend', dragEnd);
|
78
|
+
|
79
|
+
function dragStart(d,i) {
|
80
|
+
d3.select(chart.container)
|
81
|
+
.style('cursor', 'ew-resize');
|
82
|
+
}
|
83
|
+
|
84
|
+
function dragMove(d,i) {
|
85
|
+
d.x += d3.event.dx;
|
86
|
+
d.i = Math.round(dx.invert(d.x));
|
87
|
+
|
88
|
+
d3.select(this).attr('transform', 'translate(' + dx(d.i) + ',0)');
|
89
|
+
chart.update();
|
90
|
+
}
|
91
|
+
|
92
|
+
function dragEnd(d,i) {
|
93
|
+
d3.select(chart.container)
|
94
|
+
.style('cursor', 'auto');
|
95
|
+
chart.update();
|
96
|
+
}
|
97
|
+
*/
|
98
|
+
|
99
|
+
//============================================================
|
100
|
+
|
101
|
+
|
102
|
+
function chart(selection) {
|
103
|
+
selection.each(function(data) {
|
104
|
+
var container = d3.select(this).classed('nv-chart-' + id, true),
|
105
|
+
that = this;
|
106
|
+
|
107
|
+
var availableWidth = (width || parseInt(container.style('width')) || 960)
|
108
|
+
- margin.left - margin.right,
|
109
|
+
availableHeight = (height || parseInt(container.style('height')) || 400)
|
110
|
+
- margin.top - margin.bottom;
|
111
|
+
|
112
|
+
|
113
|
+
chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
|
114
|
+
chart.container = this;
|
115
|
+
|
116
|
+
//set state.disabled
|
117
|
+
state.disabled = data.map(function(d) { return !!d.disabled });
|
118
|
+
|
119
|
+
if (!defaultState) {
|
120
|
+
var key;
|
121
|
+
defaultState = {};
|
122
|
+
for (key in state) {
|
123
|
+
if (state[key] instanceof Array)
|
124
|
+
defaultState[key] = state[key].slice(0);
|
125
|
+
else
|
126
|
+
defaultState[key] = state[key];
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
var indexDrag = d3.behavior.drag()
|
131
|
+
.on('dragstart', dragStart)
|
132
|
+
.on('drag', dragMove)
|
133
|
+
.on('dragend', dragEnd);
|
134
|
+
|
135
|
+
|
136
|
+
function dragStart(d,i) {
|
137
|
+
d3.select(chart.container)
|
138
|
+
.style('cursor', 'ew-resize');
|
139
|
+
}
|
140
|
+
|
141
|
+
function dragMove(d,i) {
|
142
|
+
index.x = d3.event.x;
|
143
|
+
index.i = Math.round(dx.invert(index.x));
|
144
|
+
updateZero();
|
145
|
+
}
|
146
|
+
|
147
|
+
function dragEnd(d,i) {
|
148
|
+
d3.select(chart.container)
|
149
|
+
.style('cursor', 'auto');
|
150
|
+
|
151
|
+
// update state and send stateChange with new index
|
152
|
+
state.index = index.i;
|
153
|
+
dispatch.stateChange(state);
|
154
|
+
}
|
155
|
+
|
156
|
+
//------------------------------------------------------------
|
157
|
+
// Display No Data message if there's nothing to show.
|
158
|
+
|
159
|
+
if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
|
160
|
+
var noDataText = container.selectAll('.nv-noData').data([noData]);
|
161
|
+
|
162
|
+
noDataText.enter().append('text')
|
163
|
+
.attr('class', 'nvd3 nv-noData')
|
164
|
+
.attr('dy', '-.7em')
|
165
|
+
.style('text-anchor', 'middle');
|
166
|
+
|
167
|
+
noDataText
|
168
|
+
.attr('x', margin.left + availableWidth / 2)
|
169
|
+
.attr('y', margin.top + availableHeight / 2)
|
170
|
+
.text(function(d) { return d });
|
171
|
+
|
172
|
+
return chart;
|
173
|
+
} else {
|
174
|
+
container.selectAll('.nv-noData').remove();
|
175
|
+
}
|
176
|
+
|
177
|
+
//------------------------------------------------------------
|
178
|
+
|
179
|
+
|
180
|
+
//------------------------------------------------------------
|
181
|
+
// Setup Scales
|
182
|
+
|
183
|
+
x = lines.xScale();
|
184
|
+
y = lines.yScale();
|
185
|
+
|
186
|
+
|
187
|
+
if (!rescaleY) {
|
188
|
+
var seriesDomains = data
|
189
|
+
.filter(function(series) { return !series.disabled })
|
190
|
+
.map(function(series,i) {
|
191
|
+
var initialDomain = d3.extent(series.values, lines.y());
|
192
|
+
|
193
|
+
//account for series being disabled when losing 95% or more
|
194
|
+
if (initialDomain[0] < -.95) initialDomain[0] = -.95;
|
195
|
+
|
196
|
+
return [
|
197
|
+
(initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
|
198
|
+
(initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
|
199
|
+
];
|
200
|
+
});
|
201
|
+
|
202
|
+
var completeDomain = [
|
203
|
+
d3.min(seriesDomains, function(d) { return d[0] }),
|
204
|
+
d3.max(seriesDomains, function(d) { return d[1] })
|
205
|
+
]
|
206
|
+
|
207
|
+
lines.yDomain(completeDomain);
|
208
|
+
} else {
|
209
|
+
lines.yDomain(null);
|
210
|
+
}
|
211
|
+
|
212
|
+
|
213
|
+
dx .domain([0, data[0].values.length - 1]) //Assumes all series have same length
|
214
|
+
.range([0, availableWidth])
|
215
|
+
.clamp(true);
|
216
|
+
|
217
|
+
//------------------------------------------------------------
|
218
|
+
|
219
|
+
|
220
|
+
var data = indexify(index.i, data);
|
221
|
+
|
222
|
+
|
223
|
+
//------------------------------------------------------------
|
224
|
+
// Setup containers and skeleton of chart
|
225
|
+
var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";
|
226
|
+
var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
|
227
|
+
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
|
228
|
+
var g = wrap.select('g');
|
229
|
+
|
230
|
+
gEnter.append('g').attr('class', 'nv-interactive');
|
231
|
+
gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none");
|
232
|
+
gEnter.append('g').attr('class', 'nv-y nv-axis');
|
233
|
+
gEnter.append('g').attr('class', 'nv-background');
|
234
|
+
gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents);
|
235
|
+
gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none");
|
236
|
+
gEnter.append('g').attr('class', 'nv-legendWrap');
|
237
|
+
gEnter.append('g').attr('class', 'nv-controlsWrap');
|
238
|
+
|
239
|
+
|
240
|
+
//------------------------------------------------------------
|
241
|
+
// Legend
|
242
|
+
|
243
|
+
if (showLegend) {
|
244
|
+
legend.width(availableWidth);
|
245
|
+
|
246
|
+
g.select('.nv-legendWrap')
|
247
|
+
.datum(data)
|
248
|
+
.call(legend);
|
249
|
+
|
250
|
+
if ( margin.top != legend.height()) {
|
251
|
+
margin.top = legend.height();
|
252
|
+
availableHeight = (height || parseInt(container.style('height')) || 400)
|
253
|
+
- margin.top - margin.bottom;
|
254
|
+
}
|
255
|
+
|
256
|
+
g.select('.nv-legendWrap')
|
257
|
+
.attr('transform', 'translate(0,' + (-margin.top) +')')
|
258
|
+
}
|
259
|
+
|
260
|
+
//------------------------------------------------------------
|
261
|
+
|
262
|
+
|
263
|
+
//------------------------------------------------------------
|
264
|
+
// Controls
|
265
|
+
|
266
|
+
if (showControls) {
|
267
|
+
var controlsData = [
|
268
|
+
{ key: 'Re-scale y-axis', disabled: !rescaleY }
|
269
|
+
];
|
270
|
+
|
271
|
+
controls.width(140).color(['#444', '#444', '#444']);
|
272
|
+
g.select('.nv-controlsWrap')
|
273
|
+
.datum(controlsData)
|
274
|
+
.attr('transform', 'translate(0,' + (-margin.top) +')')
|
275
|
+
.call(controls);
|
276
|
+
}
|
277
|
+
|
278
|
+
//------------------------------------------------------------
|
279
|
+
|
280
|
+
|
281
|
+
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
282
|
+
|
283
|
+
if (rightAlignYAxis) {
|
284
|
+
g.select(".nv-y.nv-axis")
|
285
|
+
.attr("transform", "translate(" + availableWidth + ",0)");
|
286
|
+
}
|
287
|
+
|
288
|
+
// Show error if series goes below 100%
|
289
|
+
var tempDisabled = data.filter(function(d) { return d.tempDisabled });
|
290
|
+
|
291
|
+
wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
|
292
|
+
if (tempDisabled.length) {
|
293
|
+
wrap.append('text').attr('class', 'tempDisabled')
|
294
|
+
.attr('x', availableWidth / 2)
|
295
|
+
.attr('y', '-.71em')
|
296
|
+
.style('text-anchor', 'end')
|
297
|
+
.text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
|
298
|
+
}
|
299
|
+
|
300
|
+
//------------------------------------------------------------
|
301
|
+
// Main Chart Component(s)
|
302
|
+
|
303
|
+
//------------------------------------------------------------
|
304
|
+
//Set up interactive layer
|
305
|
+
if (useInteractiveGuideline) {
|
306
|
+
interactiveLayer
|
307
|
+
.width(availableWidth)
|
308
|
+
.height(availableHeight)
|
309
|
+
.margin({left:margin.left,top:margin.top})
|
310
|
+
.svgContainer(container)
|
311
|
+
.xScale(x);
|
312
|
+
wrap.select(".nv-interactive").call(interactiveLayer);
|
313
|
+
}
|
314
|
+
|
315
|
+
gEnter.select('.nv-background')
|
316
|
+
.append('rect');
|
317
|
+
|
318
|
+
g.select('.nv-background rect')
|
319
|
+
.attr('width', availableWidth)
|
320
|
+
.attr('height', availableHeight);
|
321
|
+
|
322
|
+
lines
|
323
|
+
//.x(function(d) { return d.x })
|
324
|
+
.y(function(d) { return d.display.y })
|
325
|
+
.width(availableWidth)
|
326
|
+
.height(availableHeight)
|
327
|
+
.color(data.map(function(d,i) {
|
328
|
+
return d.color || color(d, i);
|
329
|
+
}).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
var linesWrap = g.select('.nv-linesWrap')
|
334
|
+
.datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
|
335
|
+
|
336
|
+
//d3.transition(linesWrap).call(lines);
|
337
|
+
linesWrap.call(lines);
|
338
|
+
|
339
|
+
/*Handle average lines [AN-612] ----------------------------*/
|
340
|
+
|
341
|
+
//Store a series index number in the data array.
|
342
|
+
data.forEach(function(d,i) {
|
343
|
+
d.seriesIndex = i;
|
344
|
+
});
|
345
|
+
|
346
|
+
var avgLineData = data.filter(function(d) {
|
347
|
+
return !d.disabled && !!average(d);
|
348
|
+
});
|
349
|
+
|
350
|
+
var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
|
351
|
+
.data(avgLineData, function(d) { return d.key; });
|
352
|
+
|
353
|
+
var getAvgLineY = function(d) {
|
354
|
+
//If average lines go off the svg element, clamp them to the svg bounds.
|
355
|
+
var yVal = y(average(d));
|
356
|
+
if (yVal < 0) return 0;
|
357
|
+
if (yVal > availableHeight) return availableHeight;
|
358
|
+
return yVal;
|
359
|
+
};
|
360
|
+
|
361
|
+
avgLines.enter()
|
362
|
+
.append('line')
|
363
|
+
.style('stroke-width',2)
|
364
|
+
.style('stroke-dasharray','10,10')
|
365
|
+
.style('stroke',function (d,i) {
|
366
|
+
return lines.color()(d,d.seriesIndex);
|
367
|
+
})
|
368
|
+
.attr('x1',0)
|
369
|
+
.attr('x2',availableWidth)
|
370
|
+
.attr('y1', getAvgLineY)
|
371
|
+
.attr('y2', getAvgLineY);
|
372
|
+
|
373
|
+
avgLines
|
374
|
+
.style('stroke-opacity',function(d){
|
375
|
+
//If average lines go offscreen, make them transparent
|
376
|
+
var yVal = y(average(d));
|
377
|
+
if (yVal < 0 || yVal > availableHeight) return 0;
|
378
|
+
return 1;
|
379
|
+
})
|
380
|
+
.attr('x1',0)
|
381
|
+
.attr('x2',availableWidth)
|
382
|
+
.attr('y1', getAvgLineY)
|
383
|
+
.attr('y2', getAvgLineY);
|
384
|
+
|
385
|
+
avgLines.exit().remove();
|
386
|
+
|
387
|
+
//Create index line -----------------------------------------
|
388
|
+
|
389
|
+
var indexLine = linesWrap.selectAll('.nv-indexLine')
|
390
|
+
.data([index]);
|
391
|
+
indexLine.enter().append('rect').attr('class', 'nv-indexLine')
|
392
|
+
.attr('width', 3)
|
393
|
+
.attr('x', -2)
|
394
|
+
.attr('fill', 'red')
|
395
|
+
.attr('fill-opacity', .5)
|
396
|
+
.style("pointer-events","all")
|
397
|
+
.call(indexDrag)
|
398
|
+
|
399
|
+
indexLine
|
400
|
+
.attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })
|
401
|
+
.attr('height', availableHeight)
|
402
|
+
|
403
|
+
//------------------------------------------------------------
|
404
|
+
|
405
|
+
|
406
|
+
//------------------------------------------------------------
|
407
|
+
// Setup Axes
|
408
|
+
|
409
|
+
if (showXAxis) {
|
410
|
+
xAxis
|
411
|
+
.scale(x)
|
412
|
+
//Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)
|
413
|
+
.ticks( Math.min(data[0].values.length,availableWidth/70) )
|
414
|
+
.tickSize(-availableHeight, 0);
|
415
|
+
|
416
|
+
g.select('.nv-x.nv-axis')
|
417
|
+
.attr('transform', 'translate(0,' + y.range()[0] + ')');
|
418
|
+
d3.transition(g.select('.nv-x.nv-axis'))
|
419
|
+
.call(xAxis);
|
420
|
+
}
|
421
|
+
|
422
|
+
|
423
|
+
if (showYAxis) {
|
424
|
+
yAxis
|
425
|
+
.scale(y)
|
426
|
+
.ticks( availableHeight / 36 )
|
427
|
+
.tickSize( -availableWidth, 0);
|
428
|
+
|
429
|
+
d3.transition(g.select('.nv-y.nv-axis'))
|
430
|
+
.call(yAxis);
|
431
|
+
}
|
432
|
+
//------------------------------------------------------------
|
433
|
+
|
434
|
+
|
435
|
+
//============================================================
|
436
|
+
// Event Handling/Dispatching (in chart's scope)
|
437
|
+
//------------------------------------------------------------
|
438
|
+
|
439
|
+
|
440
|
+
function updateZero() {
|
441
|
+
indexLine
|
442
|
+
.data([index]);
|
443
|
+
|
444
|
+
//When dragging the index line, turn off line transitions.
|
445
|
+
// Then turn them back on when done dragging.
|
446
|
+
var oldDuration = chart.transitionDuration();
|
447
|
+
chart.transitionDuration(0);
|
448
|
+
chart.update();
|
449
|
+
chart.transitionDuration(oldDuration);
|
450
|
+
}
|
451
|
+
|
452
|
+
g.select('.nv-background rect')
|
453
|
+
.on('click', function() {
|
454
|
+
index.x = d3.mouse(this)[0];
|
455
|
+
index.i = Math.round(dx.invert(index.x));
|
456
|
+
|
457
|
+
// update state and send stateChange with new index
|
458
|
+
state.index = index.i;
|
459
|
+
dispatch.stateChange(state);
|
460
|
+
|
461
|
+
updateZero();
|
462
|
+
});
|
463
|
+
|
464
|
+
lines.dispatch.on('elementClick', function(e) {
|
465
|
+
index.i = e.pointIndex;
|
466
|
+
index.x = dx(index.i);
|
467
|
+
|
468
|
+
// update state and send stateChange with new index
|
469
|
+
state.index = index.i;
|
470
|
+
dispatch.stateChange(state);
|
471
|
+
|
472
|
+
updateZero();
|
473
|
+
});
|
474
|
+
|
475
|
+
controls.dispatch.on('legendClick', function(d,i) {
|
476
|
+
d.disabled = !d.disabled;
|
477
|
+
rescaleY = !d.disabled;
|
478
|
+
|
479
|
+
state.rescaleY = rescaleY;
|
480
|
+
dispatch.stateChange(state);
|
481
|
+
chart.update();
|
482
|
+
});
|
483
|
+
|
484
|
+
|
485
|
+
legend.dispatch.on('stateChange', function(newState) {
|
486
|
+
state.disabled = newState.disabled;
|
487
|
+
dispatch.stateChange(state);
|
488
|
+
chart.update();
|
489
|
+
});
|
490
|
+
|
491
|
+
interactiveLayer.dispatch.on('elementMousemove', function(e) {
|
492
|
+
lines.clearHighlights();
|
493
|
+
var singlePoint, pointIndex, pointXLocation, allData = [];
|
494
|
+
|
495
|
+
|
496
|
+
data
|
497
|
+
.filter(function(series, i) {
|
498
|
+
series.seriesIndex = i;
|
499
|
+
return !series.disabled;
|
500
|
+
})
|
501
|
+
.forEach(function(series,i) {
|
502
|
+
pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
|
503
|
+
lines.highlightPoint(i, pointIndex, true);
|
504
|
+
var point = series.values[pointIndex];
|
505
|
+
if (typeof point === 'undefined') return;
|
506
|
+
if (typeof singlePoint === 'undefined') singlePoint = point;
|
507
|
+
if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
|
508
|
+
allData.push({
|
509
|
+
key: series.key,
|
510
|
+
value: chart.y()(point, pointIndex),
|
511
|
+
color: color(series,series.seriesIndex)
|
512
|
+
});
|
513
|
+
});
|
514
|
+
|
515
|
+
//Highlight the tooltip entry based on which point the mouse is closest to.
|
516
|
+
if (allData.length > 2) {
|
517
|
+
var yValue = chart.yScale().invert(e.mouseY);
|
518
|
+
var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
|
519
|
+
var threshold = 0.03 * domainExtent;
|
520
|
+
var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
|
521
|
+
if (indexToHighlight !== null)
|
522
|
+
allData[indexToHighlight].highlight = true;
|
523
|
+
}
|
524
|
+
|
525
|
+
var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);
|
526
|
+
interactiveLayer.tooltip
|
527
|
+
.position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
|
528
|
+
.chartContainer(that.parentNode)
|
529
|
+
.enabled(tooltips)
|
530
|
+
.valueFormatter(function(d,i) {
|
531
|
+
return yAxis.tickFormat()(d);
|
532
|
+
})
|
533
|
+
.data(
|
534
|
+
{
|
535
|
+
value: xValue,
|
536
|
+
series: allData
|
537
|
+
}
|
538
|
+
)();
|
539
|
+
|
540
|
+
interactiveLayer.renderGuideLine(pointXLocation);
|
541
|
+
|
542
|
+
});
|
543
|
+
|
544
|
+
interactiveLayer.dispatch.on("elementMouseout",function(e) {
|
545
|
+
dispatch.tooltipHide();
|
546
|
+
lines.clearHighlights();
|
547
|
+
});
|
548
|
+
|
549
|
+
dispatch.on('tooltipShow', function(e) {
|
550
|
+
if (tooltips) showTooltip(e, that.parentNode);
|
551
|
+
});
|
552
|
+
|
553
|
+
|
554
|
+
// Update chart from a state object passed to event handler
|
555
|
+
dispatch.on('changeState', function(e) {
|
556
|
+
|
557
|
+
if (typeof e.disabled !== 'undefined') {
|
558
|
+
data.forEach(function(series,i) {
|
559
|
+
series.disabled = e.disabled[i];
|
560
|
+
});
|
561
|
+
|
562
|
+
state.disabled = e.disabled;
|
563
|
+
}
|
564
|
+
|
565
|
+
|
566
|
+
if (typeof e.index !== 'undefined') {
|
567
|
+
index.i = e.index;
|
568
|
+
index.x = dx(index.i);
|
569
|
+
|
570
|
+
state.index = e.index;
|
571
|
+
|
572
|
+
indexLine
|
573
|
+
.data([index]);
|
574
|
+
}
|
575
|
+
|
576
|
+
|
577
|
+
if (typeof e.rescaleY !== 'undefined') {
|
578
|
+
rescaleY = e.rescaleY;
|
579
|
+
}
|
580
|
+
|
581
|
+
chart.update();
|
582
|
+
});
|
583
|
+
|
584
|
+
//============================================================
|
585
|
+
|
586
|
+
});
|
587
|
+
|
588
|
+
return chart;
|
589
|
+
}
|
590
|
+
|
591
|
+
|
592
|
+
//============================================================
|
593
|
+
// Event Handling/Dispatching (out of chart's scope)
|
594
|
+
//------------------------------------------------------------
|
595
|
+
|
596
|
+
lines.dispatch.on('elementMouseover.tooltip', function(e) {
|
597
|
+
e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
|
598
|
+
dispatch.tooltipShow(e);
|
599
|
+
});
|
600
|
+
|
601
|
+
lines.dispatch.on('elementMouseout.tooltip', function(e) {
|
602
|
+
dispatch.tooltipHide(e);
|
603
|
+
});
|
604
|
+
|
605
|
+
dispatch.on('tooltipHide', function() {
|
606
|
+
if (tooltips) nv.tooltip.cleanup();
|
607
|
+
});
|
608
|
+
|
609
|
+
//============================================================
|
610
|
+
|
611
|
+
|
612
|
+
//============================================================
|
613
|
+
// Expose Public Variables
|
614
|
+
//------------------------------------------------------------
|
615
|
+
|
616
|
+
// expose chart's sub-components
|
617
|
+
chart.dispatch = dispatch;
|
618
|
+
chart.lines = lines;
|
619
|
+
chart.legend = legend;
|
620
|
+
chart.xAxis = xAxis;
|
621
|
+
chart.yAxis = yAxis;
|
622
|
+
chart.interactiveLayer = interactiveLayer;
|
623
|
+
|
624
|
+
d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'xScale','yScale', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi','useVoronoi', 'id');
|
625
|
+
|
626
|
+
chart.options = nv.utils.optionsFunc.bind(chart);
|
627
|
+
|
628
|
+
chart.margin = function(_) {
|
629
|
+
if (!arguments.length) return margin;
|
630
|
+
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
|
631
|
+
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
|
632
|
+
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
|
633
|
+
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
|
634
|
+
return chart;
|
635
|
+
};
|
636
|
+
|
637
|
+
chart.width = function(_) {
|
638
|
+
if (!arguments.length) return width;
|
639
|
+
width = _;
|
640
|
+
return chart;
|
641
|
+
};
|
642
|
+
|
643
|
+
chart.height = function(_) {
|
644
|
+
if (!arguments.length) return height;
|
645
|
+
height = _;
|
646
|
+
return chart;
|
647
|
+
};
|
648
|
+
|
649
|
+
chart.color = function(_) {
|
650
|
+
if (!arguments.length) return color;
|
651
|
+
color = nv.utils.getColor(_);
|
652
|
+
legend.color(color);
|
653
|
+
return chart;
|
654
|
+
};
|
655
|
+
|
656
|
+
chart.rescaleY = function(_) {
|
657
|
+
if (!arguments.length) return rescaleY;
|
658
|
+
rescaleY = _;
|
659
|
+
return chart;
|
660
|
+
};
|
661
|
+
|
662
|
+
chart.showControls = function(_) {
|
663
|
+
if (!arguments.length) return showControls;
|
664
|
+
showControls = _;
|
665
|
+
return chart;
|
666
|
+
};
|
667
|
+
|
668
|
+
chart.useInteractiveGuideline = function(_) {
|
669
|
+
if(!arguments.length) return useInteractiveGuideline;
|
670
|
+
useInteractiveGuideline = _;
|
671
|
+
if (_ === true) {
|
672
|
+
chart.interactive(false);
|
673
|
+
chart.useVoronoi(false);
|
674
|
+
}
|
675
|
+
return chart;
|
676
|
+
};
|
677
|
+
|
678
|
+
chart.showLegend = function(_) {
|
679
|
+
if (!arguments.length) return showLegend;
|
680
|
+
showLegend = _;
|
681
|
+
return chart;
|
682
|
+
};
|
683
|
+
|
684
|
+
chart.showXAxis = function(_) {
|
685
|
+
if (!arguments.length) return showXAxis;
|
686
|
+
showXAxis = _;
|
687
|
+
return chart;
|
688
|
+
};
|
689
|
+
|
690
|
+
chart.showYAxis = function(_) {
|
691
|
+
if (!arguments.length) return showYAxis;
|
692
|
+
showYAxis = _;
|
693
|
+
return chart;
|
694
|
+
};
|
695
|
+
|
696
|
+
chart.rightAlignYAxis = function(_) {
|
697
|
+
if(!arguments.length) return rightAlignYAxis;
|
698
|
+
rightAlignYAxis = _;
|
699
|
+
yAxis.orient( (_) ? 'right' : 'left');
|
700
|
+
return chart;
|
701
|
+
};
|
702
|
+
|
703
|
+
chart.tooltips = function(_) {
|
704
|
+
if (!arguments.length) return tooltips;
|
705
|
+
tooltips = _;
|
706
|
+
return chart;
|
707
|
+
};
|
708
|
+
|
709
|
+
chart.tooltipContent = function(_) {
|
710
|
+
if (!arguments.length) return tooltip;
|
711
|
+
tooltip = _;
|
712
|
+
return chart;
|
713
|
+
};
|
714
|
+
|
715
|
+
chart.state = function(_) {
|
716
|
+
if (!arguments.length) return state;
|
717
|
+
state = _;
|
718
|
+
return chart;
|
719
|
+
};
|
720
|
+
|
721
|
+
chart.defaultState = function(_) {
|
722
|
+
if (!arguments.length) return defaultState;
|
723
|
+
defaultState = _;
|
724
|
+
return chart;
|
725
|
+
};
|
726
|
+
|
727
|
+
chart.noData = function(_) {
|
728
|
+
if (!arguments.length) return noData;
|
729
|
+
noData = _;
|
730
|
+
return chart;
|
731
|
+
};
|
732
|
+
|
733
|
+
chart.average = function(_) {
|
734
|
+
if(!arguments.length) return average;
|
735
|
+
average = _;
|
736
|
+
return chart;
|
737
|
+
};
|
738
|
+
|
739
|
+
chart.transitionDuration = function(_) {
|
740
|
+
if (!arguments.length) return transitionDuration;
|
741
|
+
transitionDuration = _;
|
742
|
+
return chart;
|
743
|
+
};
|
744
|
+
|
745
|
+
//============================================================
|
746
|
+
|
747
|
+
|
748
|
+
//============================================================
|
749
|
+
// Functions
|
750
|
+
//------------------------------------------------------------
|
751
|
+
|
752
|
+
/* Normalize the data according to an index point. */
|
753
|
+
function indexify(idx, data) {
|
754
|
+
return data.map(function(line, i) {
|
755
|
+
if (!line.values) {
|
756
|
+
return line;
|
757
|
+
}
|
758
|
+
var v = lines.y()(line.values[idx], idx);
|
759
|
+
|
760
|
+
//TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
|
761
|
+
if (v < -.95) {
|
762
|
+
//if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
|
763
|
+
line.tempDisabled = true;
|
764
|
+
return line;
|
765
|
+
}
|
766
|
+
|
767
|
+
line.tempDisabled = false;
|
768
|
+
|
769
|
+
line.values = line.values.map(function(point, pointIndex) {
|
770
|
+
point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };
|
771
|
+
return point;
|
772
|
+
})
|
773
|
+
|
774
|
+
return line;
|
775
|
+
})
|
776
|
+
}
|
777
|
+
|
778
|
+
//============================================================
|
779
|
+
|
780
|
+
|
781
|
+
return chart;
|
782
|
+
}
|