chartx 0.0.1

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 (84) hide show
  1. data/.gitignore +17 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +145 -0
  6. data/Rakefile +1 -0
  7. data/chartx.gemspec +40 -0
  8. data/lib/chartx/engine.rb +11 -0
  9. data/lib/chartx/helper.rb +184 -0
  10. data/lib/chartx/version.rb +3 -0
  11. data/lib/chartx.rb +3 -0
  12. data/screenshots/barchart.png +0 -0
  13. data/screenshots/bulletchart.png +0 -0
  14. data/screenshots/horizontalbarchart.png +0 -0
  15. data/screenshots/linechart.png +0 -0
  16. data/screenshots/linewithfocuschart.png +0 -0
  17. data/screenshots/multibarchart2.png +0 -0
  18. data/screenshots/piechart.png +0 -0
  19. data/screenshots/scatterchart.png +0 -0
  20. data/screenshots/stackedareachart.png +0 -0
  21. data/screenshots/stackedareachart3.png +0 -0
  22. data/vendor/assets/javascripts/chartx-core.js +9 -0
  23. data/vendor/assets/javascripts/chartx-models.js +2 -0
  24. data/vendor/assets/javascripts/nvd3/.gitignore +27 -0
  25. data/vendor/assets/javascripts/nvd3/.jshintrc +3 -0
  26. data/vendor/assets/javascripts/nvd3/LICENSE.md +49 -0
  27. data/vendor/assets/javascripts/nvd3/README.md +1 -0
  28. data/vendor/assets/javascripts/nvd3/lib/cie.js +155 -0
  29. data/vendor/assets/javascripts/nvd3/lib/crossfilter.js +1180 -0
  30. data/vendor/assets/javascripts/nvd3/lib/crossfilter.min.js +1 -0
  31. data/vendor/assets/javascripts/nvd3/lib/d3.js +8798 -0
  32. data/vendor/assets/javascripts/nvd3/lib/d3.min.js +5 -0
  33. data/vendor/assets/javascripts/nvd3/lib/fisheye.js +86 -0
  34. data/vendor/assets/javascripts/nvd3/lib/hive.js +80 -0
  35. data/vendor/assets/javascripts/nvd3/lib/horizon.js +192 -0
  36. data/vendor/assets/javascripts/nvd3/lib/sankey.js +292 -0
  37. data/vendor/assets/javascripts/nvd3/nv.d3.js +13048 -0
  38. data/vendor/assets/javascripts/nvd3/nv.d3.min.js +6 -0
  39. data/vendor/assets/javascripts/nvd3/src/core.js +118 -0
  40. data/vendor/assets/javascripts/nvd3/src/intro.js +1 -0
  41. data/vendor/assets/javascripts/nvd3/src/models/axis.js +398 -0
  42. data/vendor/assets/javascripts/nvd3/src/models/boilerplate.js +102 -0
  43. data/vendor/assets/javascripts/nvd3/src/models/bullet.js +377 -0
  44. data/vendor/assets/javascripts/nvd3/src/models/bulletChart.js +341 -0
  45. data/vendor/assets/javascripts/nvd3/src/models/cumulativeLineChart.js +685 -0
  46. data/vendor/assets/javascripts/nvd3/src/models/discreteBar.js +327 -0
  47. data/vendor/assets/javascripts/nvd3/src/models/discreteBarChart.js +290 -0
  48. data/vendor/assets/javascripts/nvd3/src/models/distribution.js +146 -0
  49. data/vendor/assets/javascripts/nvd3/src/models/historicalBar.js +289 -0
  50. data/vendor/assets/javascripts/nvd3/src/models/historicalBarChart.js +421 -0
  51. data/vendor/assets/javascripts/nvd3/src/models/indentedTree.js +317 -0
  52. data/vendor/assets/javascripts/nvd3/src/models/legend.js +207 -0
  53. data/vendor/assets/javascripts/nvd3/src/models/line.js +284 -0
  54. data/vendor/assets/javascripts/nvd3/src/models/lineChart.js +421 -0
  55. data/vendor/assets/javascripts/nvd3/src/models/linePlusBarChart.js +455 -0
  56. data/vendor/assets/javascripts/nvd3/src/models/linePlusBarWithFocusChart.js +665 -0
  57. data/vendor/assets/javascripts/nvd3/src/models/lineWithFisheye.js +197 -0
  58. data/vendor/assets/javascripts/nvd3/src/models/lineWithFisheyeChart.js +319 -0
  59. data/vendor/assets/javascripts/nvd3/src/models/lineWithFocusChart.js +560 -0
  60. data/vendor/assets/javascripts/nvd3/src/models/multiBar.js +442 -0
  61. data/vendor/assets/javascripts/nvd3/src/models/multiBarChart.js +506 -0
  62. data/vendor/assets/javascripts/nvd3/src/models/multiBarHorizontal.js +420 -0
  63. data/vendor/assets/javascripts/nvd3/src/models/multiBarHorizontalChart.js +448 -0
  64. data/vendor/assets/javascripts/nvd3/src/models/multiBarTimeSeries.js +371 -0
  65. data/vendor/assets/javascripts/nvd3/src/models/multiBarTimeSeriesChart.js +403 -0
  66. data/vendor/assets/javascripts/nvd3/src/models/multiChart.js +444 -0
  67. data/vendor/assets/javascripts/nvd3/src/models/ohlcBar.js +365 -0
  68. data/vendor/assets/javascripts/nvd3/src/models/parallelCoordinates.js +238 -0
  69. data/vendor/assets/javascripts/nvd3/src/models/pie.js +386 -0
  70. data/vendor/assets/javascripts/nvd3/src/models/pieChart.js +302 -0
  71. data/vendor/assets/javascripts/nvd3/src/models/scatter.js +660 -0
  72. data/vendor/assets/javascripts/nvd3/src/models/scatterChart.js +614 -0
  73. data/vendor/assets/javascripts/nvd3/src/models/scatterPlusLineChart.js +610 -0
  74. data/vendor/assets/javascripts/nvd3/src/models/sparkline.js +179 -0
  75. data/vendor/assets/javascripts/nvd3/src/models/sparklinePlus.js +293 -0
  76. data/vendor/assets/javascripts/nvd3/src/models/stackedArea.js +336 -0
  77. data/vendor/assets/javascripts/nvd3/src/models/stackedAreaChart.js +490 -0
  78. data/vendor/assets/javascripts/nvd3/src/nv.d3.css +704 -0
  79. data/vendor/assets/javascripts/nvd3/src/outro.js +1 -0
  80. data/vendor/assets/javascripts/nvd3/src/tooltip.js +133 -0
  81. data/vendor/assets/javascripts/nvd3/src/utils.js +118 -0
  82. data/vendor/assets/javascripts/set-env.js.erb +1 -0
  83. data/vendor/assets/stylesheets/chartx.css +3 -0
  84. metadata +189 -0
@@ -0,0 +1,685 @@
1
+
2
+ nv.models.cumulativeLineChart = function() {
3
+
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
+ ;
14
+
15
+ var margin = {top: 30, right: 30, bottom: 50, left: 60}
16
+ , color = nv.utils.defaultColor()
17
+ , width = null
18
+ , height = null
19
+ , showLegend = true
20
+ , tooltips = true
21
+ , showControls = true
22
+ , rescaleY = true
23
+ , tooltip = function(key, x, y, e, graph) {
24
+ return '<h3>' + key + '</h3>' +
25
+ '<p>' + y + ' at ' + x + '</p>'
26
+ }
27
+ , x //can be accessed via chart.xScale()
28
+ , y //can be accessed via chart.yScale()
29
+ , id = lines.id()
30
+ , state = { index: 0, rescaleY: rescaleY }
31
+ , defaultState = null
32
+ , noData = 'No Data Available.'
33
+ , average = function(d) { return d.average }
34
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
35
+ ;
36
+
37
+ xAxis
38
+ .orient('bottom')
39
+ .tickPadding(7)
40
+ ;
41
+ yAxis
42
+ .orient('left')
43
+ ;
44
+
45
+ //============================================================
46
+
47
+
48
+ //============================================================
49
+ // Private Variables
50
+ //------------------------------------------------------------
51
+
52
+ var dx = d3.scale.linear()
53
+ , index = {i: 0, x: 0}
54
+ ;
55
+
56
+ var showTooltip = function(e, offsetElement) {
57
+ var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
58
+ top = e.pos[1] + ( offsetElement.offsetTop || 0),
59
+ x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
60
+ y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),
61
+ content = tooltip(e.series.key, x, y, e, chart);
62
+
63
+ nv.tooltip.show([left, top], content, null, null, offsetElement);
64
+ };
65
+
66
+ /*
67
+ //Moved to see if we can get better behavior to fix issue #315
68
+ var indexDrag = d3.behavior.drag()
69
+ .on('dragstart', dragStart)
70
+ .on('drag', dragMove)
71
+ .on('dragend', dragEnd);
72
+
73
+ function dragStart(d,i) {
74
+ d3.select(chart.container)
75
+ .style('cursor', 'ew-resize');
76
+ }
77
+
78
+ function dragMove(d,i) {
79
+ d.x += d3.event.dx;
80
+ d.i = Math.round(dx.invert(d.x));
81
+
82
+ d3.select(this).attr('transform', 'translate(' + dx(d.i) + ',0)');
83
+ chart.update();
84
+ }
85
+
86
+ function dragEnd(d,i) {
87
+ d3.select(chart.container)
88
+ .style('cursor', 'auto');
89
+ chart.update();
90
+ }
91
+ */
92
+
93
+ //============================================================
94
+
95
+
96
+ function chart(selection) {
97
+ selection.each(function(data) {
98
+ var container = d3.select(this).classed('nv-chart-' + id, true),
99
+ that = this;
100
+
101
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
102
+ - margin.left - margin.right,
103
+ availableHeight = (height || parseInt(container.style('height')) || 400)
104
+ - margin.top - margin.bottom;
105
+
106
+
107
+ chart.update = function() { container.transition().call(chart) };
108
+ chart.container = this;
109
+
110
+ //set state.disabled
111
+ state.disabled = data.map(function(d) { return !!d.disabled });
112
+
113
+ if (!defaultState) {
114
+ var key;
115
+ defaultState = {};
116
+ for (key in state) {
117
+ if (state[key] instanceof Array)
118
+ defaultState[key] = state[key].slice(0);
119
+ else
120
+ defaultState[key] = state[key];
121
+ }
122
+ }
123
+
124
+ var indexDrag = d3.behavior.drag()
125
+ .on('dragstart', dragStart)
126
+ .on('drag', dragMove)
127
+ .on('dragend', dragEnd);
128
+
129
+
130
+ function dragStart(d,i) {
131
+ d3.select(chart.container)
132
+ .style('cursor', 'ew-resize');
133
+ }
134
+
135
+ function dragMove(d,i) {
136
+ index.x = d3.event.x;
137
+ index.i = Math.round(dx.invert(index.x));
138
+ updateZero();
139
+ }
140
+
141
+ function dragEnd(d,i) {
142
+ d3.select(chart.container)
143
+ .style('cursor', 'auto');
144
+
145
+ // update state and send stateChange with new index
146
+ state.index = index.i;
147
+ dispatch.stateChange(state);
148
+ }
149
+
150
+
151
+
152
+
153
+ //------------------------------------------------------------
154
+ // Display No Data message if there's nothing to show.
155
+
156
+ if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
157
+ var noDataText = container.selectAll('.nv-noData').data([noData]);
158
+
159
+ noDataText.enter().append('text')
160
+ .attr('class', 'nvd3 nv-noData')
161
+ .attr('dy', '-.7em')
162
+ .style('text-anchor', 'middle');
163
+
164
+ noDataText
165
+ .attr('x', margin.left + availableWidth / 2)
166
+ .attr('y', margin.top + availableHeight / 2)
167
+ .text(function(d) { return d });
168
+
169
+ return chart;
170
+ } else {
171
+ container.selectAll('.nv-noData').remove();
172
+ }
173
+
174
+ //------------------------------------------------------------
175
+
176
+
177
+ //------------------------------------------------------------
178
+ // Setup Scales
179
+
180
+ x = lines.xScale();
181
+ y = lines.yScale();
182
+
183
+
184
+ if (!rescaleY) {
185
+ var seriesDomains = data
186
+ .filter(function(series) { return !series.disabled })
187
+ .map(function(series,i) {
188
+ var initialDomain = d3.extent(series.values, lines.y());
189
+
190
+ //account for series being disabled when losing 95% or more
191
+ if (initialDomain[0] < -.95) initialDomain[0] = -.95;
192
+
193
+ return [
194
+ (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
195
+ (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
196
+ ];
197
+ });
198
+
199
+ var completeDomain = [
200
+ d3.min(seriesDomains, function(d) { return d[0] }),
201
+ d3.max(seriesDomains, function(d) { return d[1] })
202
+ ]
203
+
204
+ lines.yDomain(completeDomain);
205
+ } else {
206
+ lines.yDomain(null);
207
+ }
208
+
209
+
210
+ dx .domain([0, data[0].values.length - 1]) //Assumes all series have same length
211
+ .range([0, availableWidth])
212
+ .clamp(true);
213
+
214
+ //------------------------------------------------------------
215
+
216
+
217
+ var data = indexify(index.i, data);
218
+
219
+
220
+ //------------------------------------------------------------
221
+ // Setup containers and skeleton of chart
222
+
223
+ var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
224
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
225
+ var g = wrap.select('g');
226
+
227
+ gEnter.append('g').attr('class', 'nv-x nv-axis');
228
+ gEnter.append('g').attr('class', 'nv-y nv-axis');
229
+ gEnter.append('g').attr('class', 'nv-background');
230
+ gEnter.append('g').attr('class', 'nv-linesWrap');
231
+ gEnter.append('g').attr('class', 'nv-avgLinesWrap');
232
+ gEnter.append('g').attr('class', 'nv-legendWrap');
233
+ gEnter.append('g').attr('class', 'nv-controlsWrap');
234
+
235
+ //------------------------------------------------------------
236
+
237
+
238
+ //------------------------------------------------------------
239
+ // Legend
240
+
241
+ if (showLegend) {
242
+ legend.width(availableWidth);
243
+
244
+ g.select('.nv-legendWrap')
245
+ .datum(data)
246
+ .call(legend);
247
+
248
+ if ( margin.top != legend.height()) {
249
+ margin.top = legend.height();
250
+ availableHeight = (height || parseInt(container.style('height')) || 400)
251
+ - margin.top - margin.bottom;
252
+ }
253
+
254
+ g.select('.nv-legendWrap')
255
+ .attr('transform', 'translate(0,' + (-margin.top) +')')
256
+ }
257
+
258
+ //------------------------------------------------------------
259
+
260
+
261
+ //------------------------------------------------------------
262
+ // Controls
263
+
264
+ if (showControls) {
265
+ var controlsData = [
266
+ { key: 'Re-scale y-axis', disabled: !rescaleY }
267
+ ];
268
+
269
+ controls.width(140).color(['#444', '#444', '#444']);
270
+ g.select('.nv-controlsWrap')
271
+ .datum(controlsData)
272
+ .attr('transform', 'translate(0,' + (-margin.top) +')')
273
+ .call(controls);
274
+ }
275
+
276
+ //------------------------------------------------------------
277
+
278
+
279
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
280
+
281
+
282
+ // Show error if series goes below 100%
283
+ var tempDisabled = data.filter(function(d) { return d.tempDisabled });
284
+
285
+ wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
286
+ if (tempDisabled.length) {
287
+ wrap.append('text').attr('class', 'tempDisabled')
288
+ .attr('x', availableWidth / 2)
289
+ .attr('y', '-.71em')
290
+ .style('text-anchor', 'end')
291
+ .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
292
+ }
293
+
294
+ //------------------------------------------------------------
295
+ // Main Chart Component(s)
296
+
297
+ gEnter.select('.nv-background')
298
+ .append('rect');
299
+
300
+ g.select('.nv-background rect')
301
+ .attr('width', availableWidth)
302
+ .attr('height', availableHeight);
303
+
304
+ lines
305
+ //.x(function(d) { return d.x })
306
+ .y(function(d) { return d.display.y })
307
+ .width(availableWidth)
308
+ .height(availableHeight)
309
+ .color(data.map(function(d,i) {
310
+ return d.color || color(d, i);
311
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
312
+
313
+
314
+
315
+ var linesWrap = g.select('.nv-linesWrap')
316
+ .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
317
+
318
+ //d3.transition(linesWrap).call(lines);
319
+ linesWrap.call(lines);
320
+
321
+ /*Handle average lines [AN-612] ----------------------------*/
322
+
323
+ //Store a series index number in the data array.
324
+ data.forEach(function(d,i) {
325
+ d.seriesIndex = i;
326
+ });
327
+
328
+ var avgLineData = data.filter(function(d) {
329
+ return !d.disabled && !!average(d);
330
+ });
331
+
332
+ var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
333
+ .data(avgLineData, function(d) { return d.key; });
334
+
335
+ avgLines.enter()
336
+ .append('line')
337
+ .style('stroke-width',2)
338
+ .style('stroke-dasharray','10,10')
339
+ .style('stroke',function (d,i) {
340
+ return lines.color()(d,d.seriesIndex);
341
+ })
342
+ .attr('x1',0)
343
+ .attr('x2',availableWidth)
344
+ .attr('y1', function(d) { return y(average(d)); })
345
+ .attr('y2', function(d) { return y(average(d)); });
346
+
347
+ avgLines
348
+ .attr('x1',0)
349
+ .attr('x2',availableWidth)
350
+ .attr('y1', function(d) { return y(average(d)); })
351
+ .attr('y2', function(d) { return y(average(d)); });
352
+
353
+ avgLines.exit().remove();
354
+
355
+ //Create index line -----------------------------------------
356
+
357
+ var indexLine = linesWrap.selectAll('.nv-indexLine')
358
+ .data([index]);
359
+ indexLine.enter().append('rect').attr('class', 'nv-indexLine')
360
+ .attr('width', 3)
361
+ .attr('x', -2)
362
+ .attr('fill', 'red')
363
+ .attr('fill-opacity', .5)
364
+ .call(indexDrag)
365
+
366
+ indexLine
367
+ .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })
368
+ .attr('height', availableHeight)
369
+
370
+ //------------------------------------------------------------
371
+
372
+
373
+ //------------------------------------------------------------
374
+ // Setup Axes
375
+
376
+ xAxis
377
+ .scale(x)
378
+ //Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)
379
+ .ticks( Math.min(data[0].values.length,availableWidth/70) )
380
+ .tickSize(-availableHeight, 0);
381
+
382
+ g.select('.nv-x.nv-axis')
383
+ .attr('transform', 'translate(0,' + y.range()[0] + ')');
384
+ d3.transition(g.select('.nv-x.nv-axis'))
385
+ .call(xAxis);
386
+
387
+
388
+ yAxis
389
+ .scale(y)
390
+ .ticks( availableHeight / 36 )
391
+ .tickSize( -availableWidth, 0);
392
+
393
+ d3.transition(g.select('.nv-y.nv-axis'))
394
+ .call(yAxis);
395
+
396
+ //------------------------------------------------------------
397
+
398
+
399
+ //============================================================
400
+ // Event Handling/Dispatching (in chart's scope)
401
+ //------------------------------------------------------------
402
+
403
+
404
+ function updateZero() {
405
+ indexLine
406
+ .data([index]);
407
+
408
+ container.call(chart);
409
+ }
410
+
411
+ g.select('.nv-background rect')
412
+ .on('click', function() {
413
+ index.x = d3.mouse(this)[0];
414
+ index.i = Math.round(dx.invert(index.x));
415
+
416
+ // update state and send stateChange with new index
417
+ state.index = index.i;
418
+ dispatch.stateChange(state);
419
+
420
+ updateZero();
421
+ });
422
+
423
+ lines.dispatch.on('elementClick', function(e) {
424
+ index.i = e.pointIndex;
425
+ index.x = dx(index.i);
426
+
427
+ // update state and send stateChange with new index
428
+ state.index = index.i;
429
+ dispatch.stateChange(state);
430
+
431
+ updateZero();
432
+ });
433
+
434
+ controls.dispatch.on('legendClick', function(d,i) {
435
+ d.disabled = !d.disabled;
436
+ rescaleY = !d.disabled;
437
+
438
+ state.rescaleY = rescaleY;
439
+ dispatch.stateChange(state);
440
+
441
+ //selection.transition().call(chart);
442
+ chart.update();
443
+ });
444
+
445
+
446
+ legend.dispatch.on('legendClick', function(d,i) {
447
+ d.disabled = !d.disabled;
448
+
449
+ if (!data.filter(function(d) { return !d.disabled }).length) {
450
+ data.map(function(d) {
451
+ d.disabled = false;
452
+ wrap.selectAll('.nv-series').classed('disabled', false);
453
+ return d;
454
+ });
455
+ }
456
+
457
+ state.disabled = data.map(function(d) { return !!d.disabled });
458
+ dispatch.stateChange(state);
459
+
460
+ //selection.transition().call(chart);
461
+ chart.update();
462
+ });
463
+
464
+ legend.dispatch.on('legendDblclick', function(d) {
465
+ //Double clicking should always enable current series, and disabled all others.
466
+ data.forEach(function(d) {
467
+ d.disabled = true;
468
+ });
469
+ d.disabled = false;
470
+
471
+ state.disabled = data.map(function(d) { return !!d.disabled });
472
+ dispatch.stateChange(state);
473
+ chart.update();
474
+ });
475
+
476
+
477
+ /*
478
+ //
479
+ legend.dispatch.on('legendMouseover', function(d, i) {
480
+ d.hover = true;
481
+ selection.transition().call(chart)
482
+ });
483
+
484
+ legend.dispatch.on('legendMouseout', function(d, i) {
485
+ d.hover = false;
486
+ selection.transition().call(chart)
487
+ });
488
+ */
489
+
490
+ dispatch.on('tooltipShow', function(e) {
491
+ if (tooltips) showTooltip(e, that.parentNode);
492
+ });
493
+
494
+
495
+ // Update chart from a state object passed to event handler
496
+ dispatch.on('changeState', function(e) {
497
+
498
+ if (typeof e.disabled !== 'undefined') {
499
+ data.forEach(function(series,i) {
500
+ series.disabled = e.disabled[i];
501
+ });
502
+
503
+ state.disabled = e.disabled;
504
+ }
505
+
506
+
507
+ if (typeof e.index !== 'undefined') {
508
+ index.i = e.index;
509
+ index.x = dx(index.i);
510
+
511
+ state.index = e.index;
512
+
513
+ indexLine
514
+ .data([index]);
515
+ }
516
+
517
+
518
+ if (typeof e.rescaleY !== 'undefined') {
519
+ rescaleY = e.rescaleY;
520
+ }
521
+
522
+ chart.update();
523
+ });
524
+
525
+ //============================================================
526
+
527
+ });
528
+
529
+ return chart;
530
+ }
531
+
532
+
533
+ //============================================================
534
+ // Event Handling/Dispatching (out of chart's scope)
535
+ //------------------------------------------------------------
536
+
537
+ lines.dispatch.on('elementMouseover.tooltip', function(e) {
538
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
539
+ dispatch.tooltipShow(e);
540
+ });
541
+
542
+ lines.dispatch.on('elementMouseout.tooltip', function(e) {
543
+ dispatch.tooltipHide(e);
544
+ });
545
+
546
+ dispatch.on('tooltipHide', function() {
547
+ if (tooltips) nv.tooltip.cleanup();
548
+ });
549
+
550
+ //============================================================
551
+
552
+
553
+ //============================================================
554
+ // Expose Public Variables
555
+ //------------------------------------------------------------
556
+
557
+ // expose chart's sub-components
558
+ chart.dispatch = dispatch;
559
+ chart.lines = lines;
560
+ chart.legend = legend;
561
+ chart.xAxis = xAxis;
562
+ chart.yAxis = yAxis;
563
+
564
+ d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
565
+
566
+ chart.margin = function(_) {
567
+ if (!arguments.length) return margin;
568
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
569
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
570
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
571
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
572
+ return chart;
573
+ };
574
+
575
+ chart.width = function(_) {
576
+ if (!arguments.length) return width;
577
+ width = _;
578
+ return chart;
579
+ };
580
+
581
+ chart.height = function(_) {
582
+ if (!arguments.length) return height;
583
+ height = _;
584
+ return chart;
585
+ };
586
+
587
+ chart.color = function(_) {
588
+ if (!arguments.length) return color;
589
+ color = nv.utils.getColor(_);
590
+ legend.color(color);
591
+ return chart;
592
+ };
593
+
594
+ chart.rescaleY = function(_) {
595
+ if (!arguments.length) return rescaleY;
596
+ rescaleY = _
597
+ return rescaleY;
598
+ };
599
+
600
+ chart.showControls = function(_) {
601
+ if (!arguments.length) return showControls;
602
+ showControls = _;
603
+ return chart;
604
+ };
605
+
606
+ chart.showLegend = function(_) {
607
+ if (!arguments.length) return showLegend;
608
+ showLegend = _;
609
+ return chart;
610
+ };
611
+
612
+ chart.tooltips = function(_) {
613
+ if (!arguments.length) return tooltips;
614
+ tooltips = _;
615
+ return chart;
616
+ };
617
+
618
+ chart.tooltipContent = function(_) {
619
+ if (!arguments.length) return tooltip;
620
+ tooltip = _;
621
+ return chart;
622
+ };
623
+
624
+ chart.state = function(_) {
625
+ if (!arguments.length) return state;
626
+ state = _;
627
+ return chart;
628
+ };
629
+
630
+ chart.defaultState = function(_) {
631
+ if (!arguments.length) return defaultState;
632
+ defaultState = _;
633
+ return chart;
634
+ };
635
+
636
+ chart.noData = function(_) {
637
+ if (!arguments.length) return noData;
638
+ noData = _;
639
+ return chart;
640
+ };
641
+
642
+ chart.average = function(_) {
643
+ if(!arguments.length) return average;
644
+ average = _;
645
+ return chart;
646
+ };
647
+
648
+ //============================================================
649
+
650
+
651
+ //============================================================
652
+ // Functions
653
+ //------------------------------------------------------------
654
+
655
+ /* Normalize the data according to an index point. */
656
+ function indexify(idx, data) {
657
+ return data.map(function(line, i) {
658
+ if (!line.values) {
659
+ return line;
660
+ }
661
+ var v = lines.y()(line.values[idx], idx);
662
+
663
+ //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
664
+ if (v < -.95) {
665
+ //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
666
+ line.tempDisabled = true;
667
+ return line;
668
+ }
669
+
670
+ line.tempDisabled = false;
671
+
672
+ line.values = line.values.map(function(point, pointIndex) {
673
+ point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };
674
+ return point;
675
+ })
676
+
677
+ return line;
678
+ })
679
+ }
680
+
681
+ //============================================================
682
+
683
+
684
+ return chart;
685
+ }