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.
Files changed (68) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/lib/chardinjs.min.js +2 -0
  3. data/app/assets/javascripts/lib/crossfilter.js +1383 -1
  4. data/app/assets/javascripts/lib/{d3.js → d3.v3.js} +0 -0
  5. data/app/assets/javascripts/lib/dc.js +3492 -757
  6. data/app/assets/javascripts/lib/jquery.gridster.js +2 -3621
  7. data/app/assets/javascripts/lib/markermanager.js +2 -980
  8. data/app/assets/javascripts/lib/underscore.js +1276 -0
  9. data/app/assets/javascripts/nvd3/lib/colorbrewer.js +302 -0
  10. data/app/assets/javascripts/nvd3/lib/crossfilter.js +1180 -0
  11. data/app/assets/javascripts/nvd3/lib/crossfilter.min.js +1 -0
  12. data/app/assets/javascripts/nvd3/lib/d3.v2.js +7033 -0
  13. data/app/assets/javascripts/nvd3/lib/d3.v2.min.js +4 -0
  14. data/app/assets/javascripts/nvd3/lib/d3.v3.js +8436 -0
  15. data/app/assets/javascripts/nvd3/lib/fisheye.js +86 -0
  16. data/app/assets/javascripts/nvd3/lib/hive.js +80 -0
  17. data/app/assets/javascripts/nvd3/lib/horizon.js +192 -0
  18. data/app/assets/javascripts/nvd3/lib/sankey.js +292 -0
  19. data/app/assets/javascripts/nvd3/nv.d3.js +14312 -0
  20. data/app/assets/javascripts/nvd3/nv.d3.min.js +6 -0
  21. data/app/assets/javascripts/nvd3/src/core.js +122 -0
  22. data/app/assets/javascripts/nvd3/src/interactiveLayer.js +251 -0
  23. data/app/assets/javascripts/nvd3/src/models/axis.js +405 -0
  24. data/app/assets/javascripts/nvd3/src/models/backup/bullet.js +250 -0
  25. data/app/assets/javascripts/nvd3/src/models/backup/bulletChart.js +349 -0
  26. data/app/assets/javascripts/nvd3/src/models/boilerplate.js +104 -0
  27. data/app/assets/javascripts/nvd3/src/models/bullet.js +385 -0
  28. data/app/assets/javascripts/nvd3/src/models/bulletChart.js +343 -0
  29. data/app/assets/javascripts/nvd3/src/models/cumulativeLineChart.js +782 -0
  30. data/app/assets/javascripts/nvd3/src/models/discreteBar.js +349 -0
  31. data/app/assets/javascripts/nvd3/src/models/discreteBarChart.js +333 -0
  32. data/app/assets/javascripts/nvd3/src/models/distribution.js +148 -0
  33. data/app/assets/javascripts/nvd3/src/models/historicalBar.js +331 -0
  34. data/app/assets/javascripts/nvd3/src/models/historicalBarChart.js +419 -0
  35. data/app/assets/javascripts/nvd3/src/models/indentedTree.js +337 -0
  36. data/app/assets/javascripts/nvd3/src/models/legend.js +270 -0
  37. data/app/assets/javascripts/nvd3/src/models/line.js +284 -0
  38. data/app/assets/javascripts/nvd3/src/models/lineChart.js +465 -0
  39. data/app/assets/javascripts/nvd3/src/models/linePlusBarChart.js +433 -0
  40. data/app/assets/javascripts/nvd3/src/models/linePlusBarWithFocusChart.js +658 -0
  41. data/app/assets/javascripts/nvd3/src/models/lineWithFisheye.js +200 -0
  42. data/app/assets/javascripts/nvd3/src/models/lineWithFisheyeChart.js +297 -0
  43. data/app/assets/javascripts/nvd3/src/models/lineWithFocusChart.js +574 -0
  44. data/app/assets/javascripts/nvd3/src/models/multiBar.js +461 -0
  45. data/app/assets/javascripts/nvd3/src/models/multiBarChart.js +524 -0
  46. data/app/assets/javascripts/nvd3/src/models/multiBarHorizontal.js +424 -0
  47. data/app/assets/javascripts/nvd3/src/models/multiBarHorizontalChart.js +434 -0
  48. data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeries.js +384 -0
  49. data/app/assets/javascripts/nvd3/src/models/multiBarTimeSeriesChart.js +405 -0
  50. data/app/assets/javascripts/nvd3/src/models/multiChart.js +452 -0
  51. data/app/assets/javascripts/nvd3/src/models/ohlcBar.js +380 -0
  52. data/app/assets/javascripts/nvd3/src/models/parallelCoordinates.js +239 -0
  53. data/app/assets/javascripts/nvd3/src/models/pie.js +398 -0
  54. data/app/assets/javascripts/nvd3/src/models/pieChart.js +292 -0
  55. data/app/assets/javascripts/nvd3/src/models/scatter.js +674 -0
  56. data/app/assets/javascripts/nvd3/src/models/scatterChart.js +628 -0
  57. data/app/assets/javascripts/nvd3/src/models/scatterPlusLineChart.js +620 -0
  58. data/app/assets/javascripts/nvd3/src/models/sparkline.js +194 -0
  59. data/app/assets/javascripts/nvd3/src/models/sparklinePlus.js +295 -0
  60. data/app/assets/javascripts/nvd3/src/models/stackedArea.js +368 -0
  61. data/app/assets/javascripts/nvd3/src/models/stackedAreaChart.js +629 -0
  62. data/app/assets/javascripts/nvd3/src/tooltip.js +490 -0
  63. data/app/assets/javascripts/nvd3/src/utils.js +152 -0
  64. data/app/assets/javascripts/pyk.js +1 -0
  65. data/app/assets/stylesheets/lib/chardinjs.css +82 -0
  66. data/app/assets/stylesheets/nvd3/nv.d3.css +769 -0
  67. data/app/assets/stylesheets/pyk.css.scss +1 -0
  68. 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
+ }