pyk 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
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,292 @@
1
+ nv.models.pieChart = function() {
2
+ "use strict";
3
+ //============================================================
4
+ // Public Variables with Default Settings
5
+ //------------------------------------------------------------
6
+
7
+ var pie = nv.models.pie()
8
+ , legend = nv.models.legend()
9
+ ;
10
+
11
+ var margin = {top: 30, right: 20, bottom: 20, left: 20}
12
+ , width = null
13
+ , height = null
14
+ , showLegend = true
15
+ , color = nv.utils.defaultColor()
16
+ , tooltips = true
17
+ , tooltip = function(key, y, e, graph) {
18
+ return '<h3>' + key + '</h3>' +
19
+ '<p>' + y + '</p>'
20
+ }
21
+ , state = {}
22
+ , defaultState = null
23
+ , noData = "No Data Available."
24
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
25
+ ;
26
+
27
+ //============================================================
28
+
29
+
30
+ //============================================================
31
+ // Private Variables
32
+ //------------------------------------------------------------
33
+
34
+ var showTooltip = function(e, offsetElement) {
35
+ var tooltipLabel = pie.description()(e.point) || pie.x()(e.point)
36
+ var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ),
37
+ top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0),
38
+ y = pie.valueFormat()(pie.y()(e.point)),
39
+ content = tooltip(tooltipLabel, y, e, chart);
40
+
41
+ nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
42
+ };
43
+
44
+ //============================================================
45
+
46
+
47
+ function chart(selection) {
48
+ selection.each(function(data) {
49
+ var container = d3.select(this),
50
+ that = this;
51
+
52
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
53
+ - margin.left - margin.right,
54
+ availableHeight = (height || parseInt(container.style('height')) || 400)
55
+ - margin.top - margin.bottom;
56
+
57
+ chart.update = function() { container.transition().call(chart); };
58
+ chart.container = this;
59
+
60
+ //set state.disabled
61
+ state.disabled = data.map(function(d) { return !!d.disabled });
62
+
63
+ if (!defaultState) {
64
+ var key;
65
+ defaultState = {};
66
+ for (key in state) {
67
+ if (state[key] instanceof Array)
68
+ defaultState[key] = state[key].slice(0);
69
+ else
70
+ defaultState[key] = state[key];
71
+ }
72
+ }
73
+
74
+ //------------------------------------------------------------
75
+ // Display No Data message if there's nothing to show.
76
+
77
+ if (!data || !data.length) {
78
+ var noDataText = container.selectAll('.nv-noData').data([noData]);
79
+
80
+ noDataText.enter().append('text')
81
+ .attr('class', 'nvd3 nv-noData')
82
+ .attr('dy', '-.7em')
83
+ .style('text-anchor', 'middle');
84
+
85
+ noDataText
86
+ .attr('x', margin.left + availableWidth / 2)
87
+ .attr('y', margin.top + availableHeight / 2)
88
+ .text(function(d) { return d });
89
+
90
+ return chart;
91
+ } else {
92
+ container.selectAll('.nv-noData').remove();
93
+ }
94
+
95
+ //------------------------------------------------------------
96
+
97
+
98
+ //------------------------------------------------------------
99
+ // Setup containers and skeleton of chart
100
+
101
+ var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);
102
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');
103
+ var g = wrap.select('g');
104
+
105
+ gEnter.append('g').attr('class', 'nv-pieWrap');
106
+ gEnter.append('g').attr('class', 'nv-legendWrap');
107
+
108
+ //------------------------------------------------------------
109
+
110
+
111
+ //------------------------------------------------------------
112
+ // Legend
113
+
114
+ if (showLegend) {
115
+ legend
116
+ .width( availableWidth )
117
+ .key(pie.x());
118
+
119
+ wrap.select('.nv-legendWrap')
120
+ .datum(data)
121
+ .call(legend);
122
+
123
+ if ( margin.top != legend.height()) {
124
+ margin.top = legend.height();
125
+ availableHeight = (height || parseInt(container.style('height')) || 400)
126
+ - margin.top - margin.bottom;
127
+ }
128
+
129
+ wrap.select('.nv-legendWrap')
130
+ .attr('transform', 'translate(0,' + (-margin.top) +')');
131
+ }
132
+
133
+ //------------------------------------------------------------
134
+
135
+
136
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
137
+
138
+
139
+ //------------------------------------------------------------
140
+ // Main Chart Component(s)
141
+
142
+ pie
143
+ .width(availableWidth)
144
+ .height(availableHeight);
145
+
146
+
147
+ var pieWrap = g.select('.nv-pieWrap')
148
+ .datum([data]);
149
+
150
+ d3.transition(pieWrap).call(pie);
151
+
152
+ //------------------------------------------------------------
153
+
154
+
155
+ //============================================================
156
+ // Event Handling/Dispatching (in chart's scope)
157
+ //------------------------------------------------------------
158
+
159
+ legend.dispatch.on('stateChange', function(newState) {
160
+ state = newState;
161
+ dispatch.stateChange(state);
162
+ chart.update();
163
+ });
164
+
165
+ pie.dispatch.on('elementMouseout.tooltip', function(e) {
166
+ dispatch.tooltipHide(e);
167
+ });
168
+
169
+ // Update chart from a state object passed to event handler
170
+ dispatch.on('changeState', function(e) {
171
+
172
+ if (typeof e.disabled !== 'undefined') {
173
+ data.forEach(function(series,i) {
174
+ series.disabled = e.disabled[i];
175
+ });
176
+
177
+ state.disabled = e.disabled;
178
+ }
179
+
180
+ chart.update();
181
+ });
182
+
183
+ //============================================================
184
+
185
+
186
+ });
187
+
188
+ return chart;
189
+ }
190
+
191
+ //============================================================
192
+ // Event Handling/Dispatching (out of chart's scope)
193
+ //------------------------------------------------------------
194
+
195
+ pie.dispatch.on('elementMouseover.tooltip', function(e) {
196
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
197
+ dispatch.tooltipShow(e);
198
+ });
199
+
200
+ dispatch.on('tooltipShow', function(e) {
201
+ if (tooltips) showTooltip(e);
202
+ });
203
+
204
+ dispatch.on('tooltipHide', function() {
205
+ if (tooltips) nv.tooltip.cleanup();
206
+ });
207
+
208
+ //============================================================
209
+
210
+
211
+ //============================================================
212
+ // Expose Public Variables
213
+ //------------------------------------------------------------
214
+
215
+ // expose chart's sub-components
216
+ chart.legend = legend;
217
+ chart.dispatch = dispatch;
218
+ chart.pie = pie;
219
+
220
+ d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'description', 'id', 'showLabels', 'donutLabelsOutside', 'pieLabelsOutside', 'labelType', 'donut', 'donutRatio', 'labelThreshold');
221
+ chart.options = nv.utils.optionsFunc.bind(chart);
222
+
223
+ chart.margin = function(_) {
224
+ if (!arguments.length) return margin;
225
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
226
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
227
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
228
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
229
+ return chart;
230
+ };
231
+
232
+ chart.width = function(_) {
233
+ if (!arguments.length) return width;
234
+ width = _;
235
+ return chart;
236
+ };
237
+
238
+ chart.height = function(_) {
239
+ if (!arguments.length) return height;
240
+ height = _;
241
+ return chart;
242
+ };
243
+
244
+ chart.color = function(_) {
245
+ if (!arguments.length) return color;
246
+ color = nv.utils.getColor(_);
247
+ legend.color(color);
248
+ pie.color(color);
249
+ return chart;
250
+ };
251
+
252
+ chart.showLegend = function(_) {
253
+ if (!arguments.length) return showLegend;
254
+ showLegend = _;
255
+ return chart;
256
+ };
257
+
258
+ chart.tooltips = function(_) {
259
+ if (!arguments.length) return tooltips;
260
+ tooltips = _;
261
+ return chart;
262
+ };
263
+
264
+ chart.tooltipContent = function(_) {
265
+ if (!arguments.length) return tooltip;
266
+ tooltip = _;
267
+ return chart;
268
+ };
269
+
270
+ chart.state = function(_) {
271
+ if (!arguments.length) return state;
272
+ state = _;
273
+ return chart;
274
+ };
275
+
276
+ chart.defaultState = function(_) {
277
+ if (!arguments.length) return defaultState;
278
+ defaultState = _;
279
+ return chart;
280
+ };
281
+
282
+ chart.noData = function(_) {
283
+ if (!arguments.length) return noData;
284
+ noData = _;
285
+ return chart;
286
+ };
287
+
288
+ //============================================================
289
+
290
+
291
+ return chart;
292
+ }
@@ -0,0 +1,674 @@
1
+
2
+ nv.models.scatter = function() {
3
+ "use strict";
4
+ //============================================================
5
+ // Public Variables with Default Settings
6
+ //------------------------------------------------------------
7
+
8
+ var margin = {top: 0, right: 0, bottom: 0, left: 0}
9
+ , width = 960
10
+ , height = 500
11
+ , color = nv.utils.defaultColor() // chooses color
12
+ , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
13
+ , x = d3.scale.linear()
14
+ , y = d3.scale.linear()
15
+ , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
16
+ , getX = function(d) { return d.x } // accessor to get the x value
17
+ , getY = function(d) { return d.y } // accessor to get the y value
18
+ , getSize = function(d) { return d.size || 1} // accessor to get the point size
19
+ , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
20
+ , onlyCircles = true // Set to false to use shapes
21
+ , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
22
+ , forceY = [] // List of numbers to Force into the Y scale
23
+ , forceSize = [] // List of numbers to Force into the Size scale
24
+ , interactive = true // If true, plots a voronoi overlay for advanced point intersection
25
+ , pointKey = null
26
+ , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
27
+ , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
28
+ , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding
29
+ , clipEdge = false // if true, masks points within x and y scale
30
+ , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
31
+ , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
32
+ , xDomain = null // Override x domain (skips the calculation from data)
33
+ , yDomain = null // Override y domain
34
+ , xRange = null // Override x range
35
+ , yRange = null // Override y range
36
+ , sizeDomain = null // Override point size domain
37
+ , sizeRange = null
38
+ , singlePoint = false
39
+ , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
40
+ , useVoronoi = true
41
+ ;
42
+
43
+ //============================================================
44
+
45
+
46
+ //============================================================
47
+ // Private Variables
48
+ //------------------------------------------------------------
49
+
50
+ var x0, y0, z0 // used to store previous scales
51
+ , timeoutID
52
+ , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
53
+ ;
54
+
55
+ //============================================================
56
+
57
+
58
+ function chart(selection) {
59
+ selection.each(function(data) {
60
+ var availableWidth = width - margin.left - margin.right,
61
+ availableHeight = height - margin.top - margin.bottom,
62
+ container = d3.select(this);
63
+
64
+ //add series index to each data point for reference
65
+ data.forEach(function(series, i) {
66
+ series.values.forEach(function(point) {
67
+ point.series = i;
68
+ });
69
+ });
70
+
71
+ //------------------------------------------------------------
72
+ // Setup Scales
73
+
74
+ // remap and flatten the data for use in calculating the scales' domains
75
+ var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance
76
+ d3.merge(
77
+ data.map(function(d) {
78
+ return d.values.map(function(d,i) {
79
+ return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }
80
+ })
81
+ })
82
+ );
83
+
84
+ x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
85
+
86
+ if (padData && data[0])
87
+ x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
88
+ //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
89
+ else
90
+ x.range(xRange || [0, availableWidth]);
91
+
92
+ y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
93
+ .range(yRange || [availableHeight, 0]);
94
+
95
+ z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))
96
+ .range(sizeRange || [16, 256]);
97
+
98
+ // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
99
+ if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true;
100
+ if (x.domain()[0] === x.domain()[1])
101
+ x.domain()[0] ?
102
+ x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
103
+ : x.domain([-1,1]);
104
+
105
+ if (y.domain()[0] === y.domain()[1])
106
+ y.domain()[0] ?
107
+ y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01])
108
+ : y.domain([-1,1]);
109
+
110
+ if ( isNaN(x.domain()[0])) {
111
+ x.domain([-1,1]);
112
+ }
113
+
114
+ if ( isNaN(y.domain()[0])) {
115
+ y.domain([-1,1]);
116
+ }
117
+
118
+
119
+ x0 = x0 || x;
120
+ y0 = y0 || y;
121
+ z0 = z0 || z;
122
+
123
+ //------------------------------------------------------------
124
+
125
+
126
+ //------------------------------------------------------------
127
+ // Setup containers and skeleton of chart
128
+
129
+ var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);
130
+ var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id + (singlePoint ? ' nv-single-point' : ''));
131
+ var defsEnter = wrapEnter.append('defs');
132
+ var gEnter = wrapEnter.append('g');
133
+ var g = wrap.select('g');
134
+
135
+ gEnter.append('g').attr('class', 'nv-groups');
136
+ gEnter.append('g').attr('class', 'nv-point-paths');
137
+
138
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
139
+
140
+ //------------------------------------------------------------
141
+
142
+
143
+ defsEnter.append('clipPath')
144
+ .attr('id', 'nv-edge-clip-' + id)
145
+ .append('rect');
146
+
147
+ wrap.select('#nv-edge-clip-' + id + ' rect')
148
+ .attr('width', availableWidth)
149
+ .attr('height', availableHeight);
150
+
151
+ g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
152
+
153
+
154
+ function updateInteractiveLayer() {
155
+
156
+ if (!interactive) return false;
157
+
158
+ var eventElements;
159
+
160
+ var vertices = d3.merge(data.map(function(group, groupIndex) {
161
+ return group.values
162
+ .map(function(point, pointIndex) {
163
+ // *Adding noise to make duplicates very unlikely
164
+ // *Injecting series and point index for reference
165
+ /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.
166
+ */
167
+ var pX = getX(point,pointIndex);
168
+ var pY = getY(point,pointIndex);
169
+
170
+ return [x(pX)+ Math.random() * 1e-7,
171
+ y(pY)+ Math.random() * 1e-7,
172
+ groupIndex,
173
+ pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates
174
+ })
175
+ .filter(function(pointArray, pointIndex) {
176
+ return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!
177
+ })
178
+ })
179
+ );
180
+
181
+
182
+
183
+ //inject series and point index for reference into voronoi
184
+ if (useVoronoi === true) {
185
+
186
+ if (clipVoronoi) {
187
+ var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
188
+ .data([id])
189
+ .enter();
190
+
191
+ pointClipsEnter.append('clipPath')
192
+ .attr('class', 'nv-point-clips')
193
+ .attr('id', 'nv-points-clip-' + id);
194
+
195
+ var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
196
+ .data(vertices);
197
+ pointClips.enter().append('circle')
198
+ .attr('r', clipRadius);
199
+ pointClips.exit().remove();
200
+ pointClips
201
+ .attr('cx', function(d) { return d[0] })
202
+ .attr('cy', function(d) { return d[1] });
203
+
204
+ wrap.select('.nv-point-paths')
205
+ .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
206
+ }
207
+
208
+
209
+ if(vertices.length) {
210
+ // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
211
+ vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);
212
+ vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);
213
+ vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
214
+ vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
215
+ }
216
+
217
+ var bounds = d3.geom.polygon([
218
+ [-10,-10],
219
+ [-10,height + 10],
220
+ [width + 10,height + 10],
221
+ [width + 10,-10]
222
+ ]);
223
+
224
+ var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
225
+ return {
226
+ 'data': bounds.clip(d),
227
+ 'series': vertices[i][2],
228
+ 'point': vertices[i][3]
229
+ }
230
+ });
231
+
232
+
233
+ var pointPaths = wrap.select('.nv-point-paths').selectAll('path')
234
+ .data(voronoi);
235
+ pointPaths.enter().append('path')
236
+ .attr('class', function(d,i) { return 'nv-path-'+i; });
237
+ pointPaths.exit().remove();
238
+ pointPaths
239
+ .attr('d', function(d) {
240
+ if (d.data.length === 0)
241
+ return 'M 0 0'
242
+ else
243
+ return 'M' + d.data.join('L') + 'Z';
244
+ });
245
+
246
+ var mouseEventCallback = function(d,mDispatch) {
247
+ if (needsUpdate) return 0;
248
+ var series = data[d.series];
249
+ if (typeof series === 'undefined') return;
250
+
251
+ var point = series.values[d.point];
252
+
253
+ mDispatch({
254
+ point: point,
255
+ series: series,
256
+ pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
257
+ seriesIndex: d.series,
258
+ pointIndex: d.point
259
+ });
260
+ };
261
+
262
+ pointPaths
263
+ .on('click', function(d) {
264
+ mouseEventCallback(d, dispatch.elementClick);
265
+ })
266
+ .on('mouseover', function(d) {
267
+ mouseEventCallback(d, dispatch.elementMouseover);
268
+ })
269
+ .on('mouseout', function(d, i) {
270
+ mouseEventCallback(d, dispatch.elementMouseout);
271
+ });
272
+
273
+
274
+ } else {
275
+ /*
276
+ // bring data in form needed for click handlers
277
+ var dataWithPoints = vertices.map(function(d, i) {
278
+ return {
279
+ 'data': d,
280
+ 'series': vertices[i][2],
281
+ 'point': vertices[i][3]
282
+ }
283
+ });
284
+ */
285
+
286
+ // add event handlers to points instead voronoi paths
287
+ wrap.select('.nv-groups').selectAll('.nv-group')
288
+ .selectAll('.nv-point')
289
+ //.data(dataWithPoints)
290
+ //.style('pointer-events', 'auto') // recativate events, disabled by css
291
+ .on('click', function(d,i) {
292
+ //nv.log('test', d, i);
293
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
294
+ var series = data[d.series],
295
+ point = series.values[i];
296
+
297
+ dispatch.elementClick({
298
+ point: point,
299
+ series: series,
300
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
301
+ seriesIndex: d.series,
302
+ pointIndex: i
303
+ });
304
+ })
305
+ .on('mouseover', function(d,i) {
306
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
307
+ var series = data[d.series],
308
+ point = series.values[i];
309
+
310
+ dispatch.elementMouseover({
311
+ point: point,
312
+ series: series,
313
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
314
+ seriesIndex: d.series,
315
+ pointIndex: i
316
+ });
317
+ })
318
+ .on('mouseout', function(d,i) {
319
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
320
+ var series = data[d.series],
321
+ point = series.values[i];
322
+
323
+ dispatch.elementMouseout({
324
+ point: point,
325
+ series: series,
326
+ seriesIndex: d.series,
327
+ pointIndex: i
328
+ });
329
+ });
330
+ }
331
+
332
+ needsUpdate = false;
333
+ }
334
+
335
+ needsUpdate = true;
336
+
337
+ var groups = wrap.select('.nv-groups').selectAll('.nv-group')
338
+ .data(function(d) { return d }, function(d) { return d.key });
339
+ groups.enter().append('g')
340
+ .style('stroke-opacity', 1e-6)
341
+ .style('fill-opacity', 1e-6);
342
+ groups.exit()
343
+ .remove();
344
+ groups
345
+ .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
346
+ .classed('hover', function(d) { return d.hover });
347
+ groups
348
+ .transition()
349
+ .style('fill', function(d,i) { return color(d, i) })
350
+ .style('stroke', function(d,i) { return color(d, i) })
351
+ .style('stroke-opacity', 1)
352
+ .style('fill-opacity', .5);
353
+
354
+
355
+ if (onlyCircles) {
356
+
357
+ var points = groups.selectAll('circle.nv-point')
358
+ .data(function(d) { return d.values }, pointKey);
359
+ points.enter().append('circle')
360
+ .style('fill', function (d,i) { return d.color })
361
+ .style('stroke', function (d,i) { return d.color })
362
+ .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
363
+ .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
364
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
365
+ points.exit().remove();
366
+ groups.exit().selectAll('path.nv-point').transition()
367
+ .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
368
+ .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
369
+ .remove();
370
+ points.each(function(d,i) {
371
+ d3.select(this)
372
+ .classed('nv-point', true)
373
+ .classed('nv-point-' + i, true)
374
+ .classed('hover',false)
375
+ ;
376
+ });
377
+ points.transition()
378
+ .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
379
+ .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
380
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
381
+
382
+ } else {
383
+
384
+ var points = groups.selectAll('path.nv-point')
385
+ .data(function(d) { return d.values });
386
+ points.enter().append('path')
387
+ .style('fill', function (d,i) { return d.color })
388
+ .style('stroke', function (d,i) { return d.color })
389
+ .attr('transform', function(d,i) {
390
+ return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
391
+ })
392
+ .attr('d',
393
+ d3.svg.symbol()
394
+ .type(getShape)
395
+ .size(function(d,i) { return z(getSize(d,i)) })
396
+ );
397
+ points.exit().remove();
398
+ groups.exit().selectAll('path.nv-point')
399
+ .transition()
400
+ .attr('transform', function(d,i) {
401
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
402
+ })
403
+ .remove();
404
+ points.each(function(d,i) {
405
+ d3.select(this)
406
+ .classed('nv-point', true)
407
+ .classed('nv-point-' + i, true)
408
+ .classed('hover',false)
409
+ ;
410
+ });
411
+ points.transition()
412
+ .attr('transform', function(d,i) {
413
+ //nv.log(d,i,getX(d,i), x(getX(d,i)));
414
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
415
+ })
416
+ .attr('d',
417
+ d3.svg.symbol()
418
+ .type(getShape)
419
+ .size(function(d,i) { return z(getSize(d,i)) })
420
+ );
421
+ }
422
+
423
+
424
+ // Delay updating the invisible interactive layer for smoother animation
425
+ clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
426
+ timeoutID = setTimeout(updateInteractiveLayer, 300);
427
+ //updateInteractiveLayer();
428
+
429
+ //store old scales for use in transitions on update
430
+ x0 = x.copy();
431
+ y0 = y.copy();
432
+ z0 = z.copy();
433
+
434
+ });
435
+
436
+ return chart;
437
+ }
438
+
439
+
440
+ //============================================================
441
+ // Event Handling/Dispatching (out of chart's scope)
442
+ //------------------------------------------------------------
443
+ chart.clearHighlights = function() {
444
+ //Remove the 'hover' class from all highlighted points.
445
+ d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover",false);
446
+ };
447
+
448
+ chart.highlightPoint = function(seriesIndex,pointIndex,isHoverOver) {
449
+ d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
450
+ .classed("hover",isHoverOver);
451
+ };
452
+
453
+
454
+ dispatch.on('elementMouseover.point', function(d) {
455
+ if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,true);
456
+ });
457
+
458
+ dispatch.on('elementMouseout.point', function(d) {
459
+ if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,false);
460
+ });
461
+
462
+ //============================================================
463
+
464
+
465
+ //============================================================
466
+ // Expose Public Variables
467
+ //------------------------------------------------------------
468
+
469
+ chart.dispatch = dispatch;
470
+ chart.options = nv.utils.optionsFunc.bind(chart);
471
+
472
+ chart.x = function(_) {
473
+ if (!arguments.length) return getX;
474
+ getX = d3.functor(_);
475
+ return chart;
476
+ };
477
+
478
+ chart.y = function(_) {
479
+ if (!arguments.length) return getY;
480
+ getY = d3.functor(_);
481
+ return chart;
482
+ };
483
+
484
+ chart.size = function(_) {
485
+ if (!arguments.length) return getSize;
486
+ getSize = d3.functor(_);
487
+ return chart;
488
+ };
489
+
490
+ chart.margin = function(_) {
491
+ if (!arguments.length) return margin;
492
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
493
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
494
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
495
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
496
+ return chart;
497
+ };
498
+
499
+ chart.width = function(_) {
500
+ if (!arguments.length) return width;
501
+ width = _;
502
+ return chart;
503
+ };
504
+
505
+ chart.height = function(_) {
506
+ if (!arguments.length) return height;
507
+ height = _;
508
+ return chart;
509
+ };
510
+
511
+ chart.xScale = function(_) {
512
+ if (!arguments.length) return x;
513
+ x = _;
514
+ return chart;
515
+ };
516
+
517
+ chart.yScale = function(_) {
518
+ if (!arguments.length) return y;
519
+ y = _;
520
+ return chart;
521
+ };
522
+
523
+ chart.zScale = function(_) {
524
+ if (!arguments.length) return z;
525
+ z = _;
526
+ return chart;
527
+ };
528
+
529
+ chart.xDomain = function(_) {
530
+ if (!arguments.length) return xDomain;
531
+ xDomain = _;
532
+ return chart;
533
+ };
534
+
535
+ chart.yDomain = function(_) {
536
+ if (!arguments.length) return yDomain;
537
+ yDomain = _;
538
+ return chart;
539
+ };
540
+
541
+ chart.sizeDomain = function(_) {
542
+ if (!arguments.length) return sizeDomain;
543
+ sizeDomain = _;
544
+ return chart;
545
+ };
546
+
547
+ chart.xRange = function(_) {
548
+ if (!arguments.length) return xRange;
549
+ xRange = _;
550
+ return chart;
551
+ };
552
+
553
+ chart.yRange = function(_) {
554
+ if (!arguments.length) return yRange;
555
+ yRange = _;
556
+ return chart;
557
+ };
558
+
559
+ chart.sizeRange = function(_) {
560
+ if (!arguments.length) return sizeRange;
561
+ sizeRange = _;
562
+ return chart;
563
+ };
564
+
565
+ chart.forceX = function(_) {
566
+ if (!arguments.length) return forceX;
567
+ forceX = _;
568
+ return chart;
569
+ };
570
+
571
+ chart.forceY = function(_) {
572
+ if (!arguments.length) return forceY;
573
+ forceY = _;
574
+ return chart;
575
+ };
576
+
577
+ chart.forceSize = function(_) {
578
+ if (!arguments.length) return forceSize;
579
+ forceSize = _;
580
+ return chart;
581
+ };
582
+
583
+ chart.interactive = function(_) {
584
+ if (!arguments.length) return interactive;
585
+ interactive = _;
586
+ return chart;
587
+ };
588
+
589
+ chart.pointKey = function(_) {
590
+ if (!arguments.length) return pointKey;
591
+ pointKey = _;
592
+ return chart;
593
+ };
594
+
595
+ chart.pointActive = function(_) {
596
+ if (!arguments.length) return pointActive;
597
+ pointActive = _;
598
+ return chart;
599
+ };
600
+
601
+ chart.padData = function(_) {
602
+ if (!arguments.length) return padData;
603
+ padData = _;
604
+ return chart;
605
+ };
606
+
607
+ chart.padDataOuter = function(_) {
608
+ if (!arguments.length) return padDataOuter;
609
+ padDataOuter = _;
610
+ return chart;
611
+ };
612
+
613
+ chart.clipEdge = function(_) {
614
+ if (!arguments.length) return clipEdge;
615
+ clipEdge = _;
616
+ return chart;
617
+ };
618
+
619
+ chart.clipVoronoi= function(_) {
620
+ if (!arguments.length) return clipVoronoi;
621
+ clipVoronoi = _;
622
+ return chart;
623
+ };
624
+
625
+ chart.useVoronoi= function(_) {
626
+ if (!arguments.length) return useVoronoi;
627
+ useVoronoi = _;
628
+ if (useVoronoi === false) {
629
+ clipVoronoi = false;
630
+ }
631
+ return chart;
632
+ };
633
+
634
+ chart.clipRadius = function(_) {
635
+ if (!arguments.length) return clipRadius;
636
+ clipRadius = _;
637
+ return chart;
638
+ };
639
+
640
+ chart.color = function(_) {
641
+ if (!arguments.length) return color;
642
+ color = nv.utils.getColor(_);
643
+ return chart;
644
+ };
645
+
646
+ chart.shape = function(_) {
647
+ if (!arguments.length) return getShape;
648
+ getShape = _;
649
+ return chart;
650
+ };
651
+
652
+ chart.onlyCircles = function(_) {
653
+ if (!arguments.length) return onlyCircles;
654
+ onlyCircles = _;
655
+ return chart;
656
+ };
657
+
658
+ chart.id = function(_) {
659
+ if (!arguments.length) return id;
660
+ id = _;
661
+ return chart;
662
+ };
663
+
664
+ chart.singlePoint = function(_) {
665
+ if (!arguments.length) return singlePoint;
666
+ singlePoint = _;
667
+ return chart;
668
+ };
669
+
670
+ //============================================================
671
+
672
+
673
+ return chart;
674
+ }