highcharts-rails 4.2.7 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +34 -0
- data/Gemfile +4 -0
- data/Rakefile +53 -32
- data/app/assets/javascripts/highcharts.js +18775 -17176
- data/app/assets/javascripts/highcharts/highcharts-3d.js +1849 -1563
- data/app/assets/javascripts/highcharts/highcharts-more.js +2162 -1988
- data/app/assets/javascripts/highcharts/modules/accessibility.js +1005 -0
- data/app/assets/javascripts/highcharts/modules/annotations.js +408 -401
- data/app/assets/javascripts/highcharts/modules/boost.js +561 -546
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +330 -324
- data/app/assets/javascripts/highcharts/modules/data.js +973 -965
- data/app/assets/javascripts/highcharts/modules/drilldown.js +783 -723
- data/app/assets/javascripts/highcharts/modules/exporting.js +864 -785
- data/app/assets/javascripts/highcharts/modules/funnel.js +290 -306
- data/app/assets/javascripts/highcharts/modules/heatmap.js +701 -645
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +150 -132
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +414 -355
- data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +164 -0
- data/app/assets/javascripts/highcharts/modules/series-label.js +473 -448
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +279 -271
- data/app/assets/javascripts/highcharts/modules/treemap.js +921 -886
- data/app/assets/javascripts/highcharts/themes/dark-blue.js +307 -244
- data/app/assets/javascripts/highcharts/themes/dark-green.js +303 -244
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +231 -201
- data/app/assets/javascripts/highcharts/themes/gray.js +314 -245
- data/app/assets/javascripts/highcharts/themes/grid-light.js +91 -66
- data/app/assets/javascripts/highcharts/themes/grid.js +124 -96
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +119 -94
- data/app/assets/javascripts/highcharts/themes/skies.js +108 -85
- data/lib/highcharts/version.rb +1 -1
- metadata +13 -14
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +0 -1
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +0 -3115
- data/app/assets/javascripts/highcharts/modules/map.js +0 -2117
@@ -1,621 +1,636 @@
|
|
1
1
|
/**
|
2
|
-
*
|
3
|
-
*
|
4
|
-
*
|
5
|
-
* Compatible with HTML5 canvas compatible browsers (not IE < 9).
|
2
|
+
* @license Highcharts JS v5.0.0 (2016-09-29)
|
3
|
+
* Boost module
|
6
4
|
*
|
5
|
+
* (c) 2010-2016 Highsoft AS
|
7
6
|
* Author: Torstein Honsi
|
8
7
|
*
|
9
|
-
*
|
10
|
-
* Development plan
|
11
|
-
* - Column range.
|
12
|
-
* - Heatmap.
|
13
|
-
* - Treemap.
|
14
|
-
* - Check how it works with Highstock and data grouping. Currently it only works when navigator.adaptToUpdatedData
|
15
|
-
* is false. It is also recommended to set scrollbar.liveRedraw to false.
|
16
|
-
* - Check inverted charts.
|
17
|
-
* - Check reversed axes.
|
18
|
-
* - Chart callback should be async after last series is drawn. (But not necessarily, we don't do
|
19
|
-
that with initial series animation).
|
20
|
-
* - Cache full-size image so we don't have to redraw on hide/show and zoom up. But k-d-tree still
|
21
|
-
* needs to be built.
|
22
|
-
* - Test IE9 and IE10.
|
23
|
-
* - Stacking is not perhaps not correct since it doesn't use the translation given in
|
24
|
-
* the translate method. If this gets to complicated, a possible way out would be to
|
25
|
-
* have a simplified renderCanvas method that simply draws the areaPath on a canvas.
|
26
|
-
*
|
27
|
-
* If this module is taken in as part of the core
|
28
|
-
* - All the loading logic should be merged with core. Update styles in the core.
|
29
|
-
* - Most of the method wraps should probably be added directly in parent methods.
|
30
|
-
*
|
31
|
-
* Notes for boost mode
|
32
|
-
* - Area lines are not drawn
|
33
|
-
* - Point markers are not drawn on line-type series
|
34
|
-
* - Lines are not drawn on scatter charts
|
35
|
-
* - Zones and negativeColor don't work
|
36
|
-
* - Columns are always one pixel wide. Don't set the threshold too low.
|
37
|
-
*
|
38
|
-
* Optimizing tips for users
|
39
|
-
* - For scatter plots, use a marker.radius of 1 or less. It results in a rectangle being drawn, which is
|
40
|
-
* considerably faster than a circle.
|
41
|
-
* - Set extremes (min, max) explicitly on the axes in order for Highcharts to avoid computing extremes.
|
42
|
-
* - Set enableMouseTracking to false on the series to improve total rendering time.
|
43
|
-
* - The default threshold is set based on one series. If you have multiple, dense series, the combined
|
44
|
-
* number of points drawn gets higher, and you may want to set the threshold lower in order to
|
45
|
-
* use optimizations.
|
8
|
+
* License: www.highcharts.com/license
|
46
9
|
*/
|
47
|
-
|
48
|
-
/* eslint indent: [2, 4] */
|
49
|
-
(function (factory) {
|
10
|
+
(function(factory) {
|
50
11
|
if (typeof module === 'object' && module.exports) {
|
51
12
|
module.exports = factory;
|
52
13
|
} else {
|
53
14
|
factory(Highcharts);
|
54
15
|
}
|
55
|
-
}(function
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
});
|
106
|
-
|
107
|
-
/**
|
108
|
-
* Override a bunch of methods the same way. If the number of points is below the threshold,
|
109
|
-
* run the original method. If not, check for a canvas version or do nothing.
|
110
|
-
*/
|
111
|
-
each(['translate', 'generatePoints', 'drawTracker', 'drawPoints', 'render'], function (method) {
|
112
|
-
function branch(proceed) {
|
113
|
-
var letItPass = this.options.stacking && (method === 'translate' || method === 'generatePoints');
|
114
|
-
if ((this.processedXData || this.options.data).length < (this.options.boostThreshold || Number.MAX_VALUE) ||
|
115
|
-
letItPass) {
|
16
|
+
}(function(Highcharts) {
|
17
|
+
(function(H) {
|
18
|
+
/**
|
19
|
+
* License: www.highcharts.com/license
|
20
|
+
* Author: Torstein Honsi
|
21
|
+
*
|
22
|
+
* This is an experimental Highcharts module that draws long data series on a canvas
|
23
|
+
* in order to increase performance of the initial load time and tooltip responsiveness.
|
24
|
+
*
|
25
|
+
* Compatible with HTML5 canvas compatible browsers (not IE < 9).
|
26
|
+
*
|
27
|
+
*
|
28
|
+
*
|
29
|
+
* Development plan
|
30
|
+
* - Column range.
|
31
|
+
* - Heatmap.
|
32
|
+
* - Treemap.
|
33
|
+
* - Check how it works with Highstock and data grouping. Currently it only works when navigator.adaptToUpdatedData
|
34
|
+
* is false. It is also recommended to set scrollbar.liveRedraw to false.
|
35
|
+
* - Check inverted charts.
|
36
|
+
* - Check reversed axes.
|
37
|
+
* - Chart callback should be async after last series is drawn. (But not necessarily, we don't do
|
38
|
+
that with initial series animation).
|
39
|
+
* - Cache full-size image so we don't have to redraw on hide/show and zoom up. But k-d-tree still
|
40
|
+
* needs to be built.
|
41
|
+
* - Test IE9 and IE10.
|
42
|
+
* - Stacking is not perhaps not correct since it doesn't use the translation given in
|
43
|
+
* the translate method. If this gets to complicated, a possible way out would be to
|
44
|
+
* have a simplified renderCanvas method that simply draws the areaPath on a canvas.
|
45
|
+
*
|
46
|
+
* If this module is taken in as part of the core
|
47
|
+
* - All the loading logic should be merged with core. Update styles in the core.
|
48
|
+
* - Most of the method wraps should probably be added directly in parent methods.
|
49
|
+
*
|
50
|
+
* Notes for boost mode
|
51
|
+
* - Area lines are not drawn
|
52
|
+
* - Point markers are not drawn on line-type series
|
53
|
+
* - Lines are not drawn on scatter charts
|
54
|
+
* - Zones and negativeColor don't work
|
55
|
+
* - Columns are always one pixel wide. Don't set the threshold too low.
|
56
|
+
*
|
57
|
+
* Optimizing tips for users
|
58
|
+
* - For scatter plots, use a marker.radius of 1 or less. It results in a rectangle being drawn, which is
|
59
|
+
* considerably faster than a circle.
|
60
|
+
* - Set extremes (min, max) explicitly on the axes in order for Highcharts to avoid computing extremes.
|
61
|
+
* - Set enableMouseTracking to false on the series to improve total rendering time.
|
62
|
+
* - The default threshold is set based on one series. If you have multiple, dense series, the combined
|
63
|
+
* number of points drawn gets higher, and you may want to set the threshold lower in order to
|
64
|
+
* use optimizations.
|
65
|
+
*/
|
116
66
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
67
|
+
'use strict';
|
68
|
+
|
69
|
+
var win = H.win,
|
70
|
+
doc = win.document,
|
71
|
+
noop = function() {},
|
72
|
+
Color = H.Color,
|
73
|
+
Series = H.Series,
|
74
|
+
seriesTypes = H.seriesTypes,
|
75
|
+
each = H.each,
|
76
|
+
extend = H.extend,
|
77
|
+
addEvent = H.addEvent,
|
78
|
+
fireEvent = H.fireEvent,
|
79
|
+
grep = H.grep,
|
80
|
+
isNumber = H.isNumber,
|
81
|
+
merge = H.merge,
|
82
|
+
pick = H.pick,
|
83
|
+
wrap = H.wrap,
|
84
|
+
plotOptions = H.getOptions().plotOptions,
|
85
|
+
CHUNK_SIZE = 50000,
|
86
|
+
destroyLoadingDiv;
|
87
|
+
|
88
|
+
function eachAsync(arr, fn, finalFunc, chunkSize, i) {
|
89
|
+
i = i || 0;
|
90
|
+
chunkSize = chunkSize || CHUNK_SIZE;
|
91
|
+
|
92
|
+
var threshold = i + chunkSize,
|
93
|
+
proceed = true;
|
94
|
+
|
95
|
+
while (proceed && i < threshold && i < arr.length) {
|
96
|
+
proceed = fn(arr[i], i);
|
97
|
+
i = i + 1;
|
98
|
+
}
|
99
|
+
if (proceed) {
|
100
|
+
if (i < arr.length) {
|
101
|
+
setTimeout(function() {
|
102
|
+
eachAsync(arr, fn, finalFunc, chunkSize, i);
|
103
|
+
});
|
104
|
+
} else if (finalFunc) {
|
105
|
+
finalFunc();
|
121
106
|
}
|
122
|
-
|
123
|
-
proceed.call(this);
|
124
|
-
|
125
|
-
// If a canvas version of the method exists, like renderCanvas(), run
|
126
|
-
} else if (this[method + 'Canvas']) {
|
127
|
-
|
128
|
-
this[method + 'Canvas']();
|
129
107
|
}
|
130
108
|
}
|
131
|
-
wrap(Series.prototype, method, branch);
|
132
109
|
|
133
|
-
//
|
134
|
-
|
135
|
-
if (
|
136
|
-
|
137
|
-
}
|
138
|
-
if (seriesTypes.arearange) {
|
139
|
-
wrap(seriesTypes.arearange.prototype, method, branch);
|
110
|
+
// Set default options
|
111
|
+
each(['area', 'arearange', 'column', 'line', 'scatter'], function(type) {
|
112
|
+
if (plotOptions[type]) {
|
113
|
+
plotOptions[type].boostThreshold = 5000;
|
140
114
|
}
|
141
|
-
}
|
142
|
-
});
|
143
|
-
|
144
|
-
/**
|
145
|
-
* Do not compute extremes when min and max are set.
|
146
|
-
* If we use this in the core, we can add the hook to hasExtremes to the methods directly.
|
147
|
-
*/
|
148
|
-
wrap(Series.prototype, 'getExtremes', function (proceed) {
|
149
|
-
if (!this.hasExtremes()) {
|
150
|
-
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
151
|
-
}
|
152
|
-
});
|
153
|
-
wrap(Series.prototype, 'setData', function (proceed) {
|
154
|
-
if (!this.hasExtremes(true)) {
|
155
|
-
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
156
|
-
}
|
157
|
-
});
|
158
|
-
wrap(Series.prototype, 'processData', function (proceed) {
|
159
|
-
if (!this.hasExtremes(true)) {
|
160
|
-
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
161
|
-
}
|
162
|
-
});
|
163
|
-
|
164
|
-
|
165
|
-
H.extend(Series.prototype, {
|
166
|
-
pointRange: 0,
|
167
|
-
allowDG: false, // No data grouping, let boost handle large data
|
168
|
-
hasExtremes: function (checkX) {
|
169
|
-
var options = this.options,
|
170
|
-
data = options.data,
|
171
|
-
xAxis = this.xAxis && this.xAxis.options,
|
172
|
-
yAxis = this.yAxis && this.yAxis.options;
|
173
|
-
return data.length > (options.boostThreshold || Number.MAX_VALUE) && isNumber(yAxis.min) && isNumber(yAxis.max) &&
|
174
|
-
(!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
|
175
|
-
},
|
115
|
+
});
|
176
116
|
|
177
117
|
/**
|
178
|
-
*
|
179
|
-
*
|
118
|
+
* Override a bunch of methods the same way. If the number of points is below the threshold,
|
119
|
+
* run the original method. If not, check for a canvas version or do nothing.
|
180
120
|
*/
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
121
|
+
each(['translate', 'generatePoints', 'drawTracker', 'drawPoints', 'render'], function(method) {
|
122
|
+
function branch(proceed) {
|
123
|
+
var letItPass = this.options.stacking && (method === 'translate' || method === 'generatePoints');
|
124
|
+
if ((this.processedXData || this.options.data).length < (this.options.boostThreshold || Number.MAX_VALUE) ||
|
125
|
+
letItPass) {
|
126
|
+
|
127
|
+
// Clear image
|
128
|
+
if (method === 'render' && this.image) {
|
129
|
+
this.image.attr({
|
130
|
+
href: ''
|
131
|
+
});
|
132
|
+
this.animate = null; // We're zooming in, don't run animation
|
192
133
|
}
|
134
|
+
|
135
|
+
proceed.call(this);
|
136
|
+
|
137
|
+
// If a canvas version of the method exists, like renderCanvas(), run
|
138
|
+
} else if (this[method + 'Canvas']) {
|
139
|
+
|
140
|
+
this[method + 'Canvas']();
|
193
141
|
}
|
194
142
|
}
|
143
|
+
wrap(Series.prototype, method, branch);
|
195
144
|
|
196
|
-
|
197
|
-
|
198
|
-
|
145
|
+
// A special case for some types - its translate method is already wrapped
|
146
|
+
if (method === 'translate') {
|
147
|
+
if (seriesTypes.column) {
|
148
|
+
wrap(seriesTypes.column.prototype, method, branch);
|
149
|
+
}
|
150
|
+
if (seriesTypes.arearange) {
|
151
|
+
wrap(seriesTypes.arearange.prototype, method, branch);
|
199
152
|
}
|
200
|
-
}
|
201
|
-
}
|
153
|
+
}
|
154
|
+
});
|
202
155
|
|
203
156
|
/**
|
204
|
-
*
|
205
|
-
* to
|
157
|
+
* Do not compute extremes when min and max are set.
|
158
|
+
* If we use this in the core, we can add the hook to hasExtremes to the methods directly.
|
206
159
|
*/
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
height = chart.plotHeight,
|
211
|
-
ctx = this.ctx,
|
212
|
-
swapXY = function (proceed, x, y, a, b, c, d) {
|
213
|
-
proceed.call(this, y, x, a, b, c, d);
|
214
|
-
};
|
215
|
-
|
216
|
-
if (!this.canvas) {
|
217
|
-
this.canvas = doc.createElement('canvas');
|
218
|
-
this.image = chart.renderer.image('', 0, 0, width, height).add(this.group);
|
219
|
-
this.ctx = ctx = this.canvas.getContext('2d');
|
220
|
-
if (chart.inverted) {
|
221
|
-
each(['moveTo', 'lineTo', 'rect', 'arc'], function (fn) {
|
222
|
-
wrap(ctx, fn, swapXY);
|
223
|
-
});
|
224
|
-
}
|
225
|
-
} else {
|
226
|
-
ctx.clearRect(0, 0, width, height);
|
160
|
+
wrap(Series.prototype, 'getExtremes', function(proceed) {
|
161
|
+
if (!this.hasExtremes()) {
|
162
|
+
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
227
163
|
}
|
164
|
+
});
|
165
|
+
wrap(Series.prototype, 'setData', function(proceed) {
|
166
|
+
if (!this.hasExtremes(true)) {
|
167
|
+
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
168
|
+
}
|
169
|
+
});
|
170
|
+
wrap(Series.prototype, 'processData', function(proceed) {
|
171
|
+
if (!this.hasExtremes(true)) {
|
172
|
+
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
173
|
+
}
|
174
|
+
});
|
175
|
+
|
176
|
+
|
177
|
+
H.extend(Series.prototype, {
|
178
|
+
pointRange: 0,
|
179
|
+
allowDG: false, // No data grouping, let boost handle large data
|
180
|
+
hasExtremes: function(checkX) {
|
181
|
+
var options = this.options,
|
182
|
+
data = options.data,
|
183
|
+
xAxis = this.xAxis && this.xAxis.options,
|
184
|
+
yAxis = this.yAxis && this.yAxis.options;
|
185
|
+
return data.length > (options.boostThreshold || Number.MAX_VALUE) && isNumber(yAxis.min) && isNumber(yAxis.max) &&
|
186
|
+
(!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
|
187
|
+
},
|
188
|
+
|
189
|
+
/**
|
190
|
+
* If implemented in the core, parts of this can probably be shared with other similar
|
191
|
+
* methods in Highcharts.
|
192
|
+
*/
|
193
|
+
destroyGraphics: function() {
|
194
|
+
var series = this,
|
195
|
+
points = this.points,
|
196
|
+
point,
|
197
|
+
i;
|
198
|
+
|
199
|
+
if (points) {
|
200
|
+
for (i = 0; i < points.length; i = i + 1) {
|
201
|
+
point = points[i];
|
202
|
+
if (point && point.graphic) {
|
203
|
+
point.graphic = point.graphic.destroy();
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
228
207
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
}
|
208
|
+
each(['graph', 'area', 'tracker'], function(prop) {
|
209
|
+
if (series[prop]) {
|
210
|
+
series[prop] = series[prop].destroy();
|
211
|
+
}
|
212
|
+
});
|
213
|
+
},
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Create a hidden canvas to draw the graph on. The contents is later copied over
|
217
|
+
* to an SVG image element.
|
218
|
+
*/
|
219
|
+
getContext: function() {
|
220
|
+
var chart = this.chart,
|
221
|
+
width = chart.plotWidth,
|
222
|
+
height = chart.plotHeight,
|
223
|
+
ctx = this.ctx,
|
224
|
+
swapXY = function(proceed, x, y, a, b, c, d) {
|
225
|
+
proceed.call(this, y, x, a, b, c, d);
|
226
|
+
};
|
235
227
|
|
236
|
-
|
237
|
-
|
228
|
+
if (!this.canvas) {
|
229
|
+
this.canvas = doc.createElement('canvas');
|
230
|
+
this.image = chart.renderer.image('', 0, 0, width, height).add(this.group);
|
231
|
+
this.ctx = ctx = this.canvas.getContext('2d');
|
232
|
+
if (chart.inverted) {
|
233
|
+
each(['moveTo', 'lineTo', 'rect', 'arc'], function(fn) {
|
234
|
+
wrap(ctx, fn, swapXY);
|
235
|
+
});
|
236
|
+
}
|
237
|
+
} else {
|
238
|
+
ctx.clearRect(0, 0, width, height);
|
239
|
+
}
|
238
240
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
241
|
+
this.canvas.width = width;
|
242
|
+
this.canvas.height = height;
|
243
|
+
this.image.attr({
|
244
|
+
width: width,
|
245
|
+
height: height
|
246
|
+
});
|
245
247
|
|
246
|
-
|
247
|
-
|
248
|
-
},
|
248
|
+
return ctx;
|
249
|
+
},
|
249
250
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
xData = series.processedXData,
|
259
|
-
yData = series.processedYData,
|
260
|
-
rawData = options.data,
|
261
|
-
xExtremes = xAxis.getExtremes(),
|
262
|
-
xMin = xExtremes.min,
|
263
|
-
xMax = xExtremes.max,
|
264
|
-
yExtremes = yAxis.getExtremes(),
|
265
|
-
yMin = yExtremes.min,
|
266
|
-
yMax = yExtremes.max,
|
267
|
-
pointTaken = {},
|
268
|
-
lastClientX,
|
269
|
-
sampling = !!series.sampling,
|
270
|
-
points,
|
271
|
-
r = options.marker && options.marker.radius,
|
272
|
-
cvsDrawPoint = this.cvsDrawPoint,
|
273
|
-
cvsLineTo = options.lineWidth ? this.cvsLineTo : false,
|
274
|
-
cvsMarker = r <= 1 ? this.cvsMarkerSquare : this.cvsMarkerCircle,
|
275
|
-
enableMouseTracking = options.enableMouseTracking !== false,
|
276
|
-
lastPoint,
|
277
|
-
threshold = options.threshold,
|
278
|
-
yBottom = yAxis.getThreshold(threshold),
|
279
|
-
hasThreshold = isNumber(threshold),
|
280
|
-
translatedThreshold = yBottom,
|
281
|
-
doFill = this.fill,
|
282
|
-
isRange = series.pointArrayMap && series.pointArrayMap.join(',') === 'low,high',
|
283
|
-
isStacked = !!options.stacking,
|
284
|
-
cropStart = series.cropStart || 0,
|
285
|
-
loadingOptions = chart.options.loading,
|
286
|
-
requireSorting = series.requireSorting,
|
287
|
-
wasNull,
|
288
|
-
connectNulls = options.connectNulls,
|
289
|
-
useRaw = !xData,
|
290
|
-
minVal,
|
291
|
-
maxVal,
|
292
|
-
minI,
|
293
|
-
maxI,
|
294
|
-
fillColor = series.fillOpacity ?
|
295
|
-
new Color(series.color).setOpacity(pick(options.fillOpacity, 0.75)).get() :
|
296
|
-
series.color,
|
297
|
-
stroke = function () {
|
298
|
-
if (doFill) {
|
299
|
-
ctx.fillStyle = fillColor;
|
300
|
-
ctx.fill();
|
301
|
-
} else {
|
302
|
-
ctx.strokeStyle = series.color;
|
303
|
-
ctx.lineWidth = options.lineWidth;
|
304
|
-
ctx.stroke();
|
305
|
-
}
|
306
|
-
},
|
307
|
-
drawPoint = function (clientX, plotY, yBottom) {
|
308
|
-
if (c === 0) {
|
309
|
-
ctx.beginPath();
|
251
|
+
/**
|
252
|
+
* Draw the canvas image inside an SVG image
|
253
|
+
*/
|
254
|
+
canvasToSVG: function() {
|
255
|
+
this.image.attr({
|
256
|
+
href: this.canvas.toDataURL('image/png')
|
257
|
+
});
|
258
|
+
},
|
310
259
|
|
311
|
-
|
312
|
-
|
260
|
+
cvsLineTo: function(ctx, clientX, plotY) {
|
261
|
+
ctx.lineTo(clientX, plotY);
|
262
|
+
},
|
263
|
+
|
264
|
+
renderCanvas: function() {
|
265
|
+
var series = this,
|
266
|
+
options = series.options,
|
267
|
+
chart = series.chart,
|
268
|
+
xAxis = this.xAxis,
|
269
|
+
yAxis = this.yAxis,
|
270
|
+
ctx,
|
271
|
+
c = 0,
|
272
|
+
xData = series.processedXData,
|
273
|
+
yData = series.processedYData,
|
274
|
+
rawData = options.data,
|
275
|
+
xExtremes = xAxis.getExtremes(),
|
276
|
+
xMin = xExtremes.min,
|
277
|
+
xMax = xExtremes.max,
|
278
|
+
yExtremes = yAxis.getExtremes(),
|
279
|
+
yMin = yExtremes.min,
|
280
|
+
yMax = yExtremes.max,
|
281
|
+
pointTaken = {},
|
282
|
+
lastClientX,
|
283
|
+
sampling = !!series.sampling,
|
284
|
+
points,
|
285
|
+
r = options.marker && options.marker.radius,
|
286
|
+
cvsDrawPoint = this.cvsDrawPoint,
|
287
|
+
cvsLineTo = options.lineWidth ? this.cvsLineTo : false,
|
288
|
+
cvsMarker = r <= 1 ? this.cvsMarkerSquare : this.cvsMarkerCircle,
|
289
|
+
enableMouseTracking = options.enableMouseTracking !== false,
|
290
|
+
lastPoint,
|
291
|
+
threshold = options.threshold,
|
292
|
+
yBottom = yAxis.getThreshold(threshold),
|
293
|
+
hasThreshold = isNumber(threshold),
|
294
|
+
translatedThreshold = yBottom,
|
295
|
+
doFill = this.fill,
|
296
|
+
isRange = series.pointArrayMap && series.pointArrayMap.join(',') === 'low,high',
|
297
|
+
isStacked = !!options.stacking,
|
298
|
+
cropStart = series.cropStart || 0,
|
299
|
+
loadingOptions = chart.options.loading,
|
300
|
+
requireSorting = series.requireSorting,
|
301
|
+
wasNull,
|
302
|
+
connectNulls = options.connectNulls,
|
303
|
+
useRaw = !xData,
|
304
|
+
minVal,
|
305
|
+
maxVal,
|
306
|
+
minI,
|
307
|
+
maxI,
|
308
|
+
fillColor = series.fillOpacity ?
|
309
|
+
new Color(series.color).setOpacity(pick(options.fillOpacity, 0.75)).get() :
|
310
|
+
series.color,
|
311
|
+
stroke = function() {
|
312
|
+
if (doFill) {
|
313
|
+
ctx.fillStyle = fillColor;
|
314
|
+
ctx.fill();
|
315
|
+
} else {
|
316
|
+
ctx.strokeStyle = series.color;
|
317
|
+
ctx.lineWidth = options.lineWidth;
|
318
|
+
ctx.stroke();
|
313
319
|
}
|
314
|
-
}
|
320
|
+
},
|
321
|
+
drawPoint = function(clientX, plotY, yBottom) {
|
322
|
+
if (c === 0) {
|
323
|
+
ctx.beginPath();
|
315
324
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
if (cvsDrawPoint) {
|
320
|
-
cvsDrawPoint(ctx, clientX, plotY, yBottom, lastPoint);
|
321
|
-
} else if (cvsLineTo) {
|
322
|
-
cvsLineTo(ctx, clientX, plotY);
|
323
|
-
} else if (cvsMarker) {
|
324
|
-
cvsMarker(ctx, clientX, plotY, r);
|
325
|
+
if (cvsLineTo) {
|
326
|
+
ctx.lineJoin = 'round';
|
327
|
+
}
|
325
328
|
}
|
326
|
-
}
|
327
|
-
|
328
|
-
// We need to stroke the line for every 1000 pixels. It will crash the browser
|
329
|
-
// memory use if we stroke too infrequently.
|
330
|
-
c = c + 1;
|
331
|
-
if (c === 1000) {
|
332
|
-
stroke();
|
333
|
-
c = 0;
|
334
|
-
}
|
335
329
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
// tree increases exponentially.
|
348
|
-
if (enableMouseTracking && !pointTaken[clientX + ',' + plotY]) {
|
349
|
-
pointTaken[clientX + ',' + plotY] = true;
|
330
|
+
if (wasNull) {
|
331
|
+
ctx.moveTo(clientX, plotY);
|
332
|
+
} else {
|
333
|
+
if (cvsDrawPoint) {
|
334
|
+
cvsDrawPoint(ctx, clientX, plotY, yBottom, lastPoint);
|
335
|
+
} else if (cvsLineTo) {
|
336
|
+
cvsLineTo(ctx, clientX, plotY);
|
337
|
+
} else if (cvsMarker) {
|
338
|
+
cvsMarker(ctx, clientX, plotY, r);
|
339
|
+
}
|
340
|
+
}
|
350
341
|
|
351
|
-
|
352
|
-
|
353
|
-
|
342
|
+
// We need to stroke the line for every 1000 pixels. It will crash the browser
|
343
|
+
// memory use if we stroke too infrequently.
|
344
|
+
c = c + 1;
|
345
|
+
if (c === 1000) {
|
346
|
+
stroke();
|
347
|
+
c = 0;
|
354
348
|
}
|
355
349
|
|
356
|
-
|
350
|
+
// Area charts need to keep track of the last point
|
351
|
+
lastPoint = {
|
357
352
|
clientX: clientX,
|
358
|
-
plotX: clientX,
|
359
353
|
plotY: plotY,
|
360
|
-
|
361
|
-
}
|
362
|
-
}
|
363
|
-
};
|
354
|
+
yBottom: yBottom
|
355
|
+
};
|
356
|
+
},
|
364
357
|
|
365
|
-
|
366
|
-
if (this.points || this.graph) {
|
367
|
-
this.destroyGraphics();
|
368
|
-
}
|
358
|
+
addKDPoint = function(clientX, plotY, i) {
|
369
359
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
series.visible ? 'visible' : 'hidden',
|
375
|
-
options.zIndex,
|
376
|
-
chart.seriesGroup
|
377
|
-
);
|
360
|
+
// The k-d tree requires series points. Reduce the amount of points, since the time to build the
|
361
|
+
// tree increases exponentially.
|
362
|
+
if (enableMouseTracking && !pointTaken[clientX + ',' + plotY]) {
|
363
|
+
pointTaken[clientX + ',' + plotY] = true;
|
378
364
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
365
|
+
if (chart.inverted) {
|
366
|
+
clientX = xAxis.len - clientX;
|
367
|
+
plotY = yAxis.len - plotY;
|
368
|
+
}
|
369
|
+
|
370
|
+
points.push({
|
371
|
+
clientX: clientX,
|
372
|
+
plotX: clientX,
|
373
|
+
plotY: plotY,
|
374
|
+
i: cropStart + i
|
375
|
+
});
|
376
|
+
}
|
377
|
+
};
|
378
|
+
|
379
|
+
// If we are zooming out from SVG mode, destroy the graphics
|
380
|
+
if (this.points || this.graph) {
|
381
|
+
this.destroyGraphics();
|
382
|
+
}
|
383
|
+
|
384
|
+
// The group
|
385
|
+
series.plotGroup(
|
386
|
+
'group',
|
387
|
+
'series',
|
388
|
+
series.visible ? 'visible' : 'hidden',
|
389
|
+
options.zIndex,
|
390
|
+
chart.seriesGroup
|
391
|
+
);
|
392
|
+
|
393
|
+
series.markerGroup = series.group;
|
394
|
+
addEvent(series, 'destroy', function() {
|
395
|
+
series.markerGroup = null;
|
401
396
|
});
|
402
|
-
clearTimeout(destroyLoadingDiv);
|
403
|
-
chart.showLoading('Drawing...');
|
404
|
-
chart.options.loading = loadingOptions; // reset
|
405
|
-
}
|
406
397
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
398
|
+
points = this.points = [];
|
399
|
+
ctx = this.getContext();
|
400
|
+
series.buildKDTree = noop; // Do not start building while drawing
|
401
|
+
|
402
|
+
// Display a loading indicator
|
403
|
+
if (rawData.length > 99999) {
|
404
|
+
chart.options.loading = merge(loadingOptions, {
|
405
|
+
labelStyle: {
|
406
|
+
backgroundColor: H.color('#ffffff').setOpacity(0.75).get(),
|
407
|
+
padding: '1em',
|
408
|
+
borderRadius: '0.5em'
|
409
|
+
},
|
410
|
+
style: {
|
411
|
+
backgroundColor: 'none',
|
412
|
+
opacity: 1
|
413
|
+
}
|
414
|
+
});
|
415
|
+
clearTimeout(destroyLoadingDiv);
|
416
|
+
chart.showLoading('Drawing...');
|
417
|
+
chart.options.loading = loadingOptions; // reset
|
418
|
+
}
|
426
419
|
|
427
|
-
|
428
|
-
|
420
|
+
// Loop over the points
|
421
|
+
eachAsync(isStacked ? series.data : (xData || rawData), function(d, i) {
|
422
|
+
var x,
|
423
|
+
y,
|
424
|
+
clientX,
|
425
|
+
plotY,
|
426
|
+
isNull,
|
427
|
+
low,
|
428
|
+
chartDestroyed = typeof chart.index === 'undefined',
|
429
|
+
isYInside = true;
|
430
|
+
|
431
|
+
if (!chartDestroyed) {
|
429
432
|
if (useRaw) {
|
430
|
-
|
433
|
+
x = d[0];
|
434
|
+
y = d[1];
|
435
|
+
} else {
|
436
|
+
x = d;
|
437
|
+
y = yData[i];
|
431
438
|
}
|
432
|
-
low = y[0];
|
433
|
-
y = y[1];
|
434
|
-
} else if (isStacked) {
|
435
|
-
x = d.x;
|
436
|
-
y = d.stackY;
|
437
|
-
low = y - d.y;
|
438
|
-
}
|
439
439
|
|
440
|
-
|
440
|
+
// Resolve low and high for range series
|
441
|
+
if (isRange) {
|
442
|
+
if (useRaw) {
|
443
|
+
y = d.slice(1, 3);
|
444
|
+
}
|
445
|
+
low = y[0];
|
446
|
+
y = y[1];
|
447
|
+
} else if (isStacked) {
|
448
|
+
x = d.x;
|
449
|
+
y = d.stackY;
|
450
|
+
low = y - d.y;
|
451
|
+
}
|
441
452
|
|
442
|
-
|
443
|
-
if (!requireSorting) {
|
444
|
-
isYInside = y >= yMin && y <= yMax;
|
445
|
-
}
|
453
|
+
isNull = y === null;
|
446
454
|
|
447
|
-
|
455
|
+
// Optimize for scatter zooming
|
456
|
+
if (!requireSorting) {
|
457
|
+
isYInside = y >= yMin && y <= yMax;
|
458
|
+
}
|
448
459
|
|
449
|
-
|
460
|
+
if (!isNull && x >= xMin && x <= xMax && isYInside) {
|
450
461
|
|
451
|
-
|
452
|
-
if (minI === undefined || clientX === lastClientX) {
|
453
|
-
if (!isRange) {
|
454
|
-
low = y;
|
455
|
-
}
|
456
|
-
if (maxI === undefined || y > maxVal) {
|
457
|
-
maxVal = y;
|
458
|
-
maxI = i;
|
459
|
-
}
|
460
|
-
if (minI === undefined || low < minVal) {
|
461
|
-
minVal = low;
|
462
|
-
minI = i;
|
463
|
-
}
|
462
|
+
clientX = Math.round(xAxis.toPixels(x, true));
|
464
463
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
)
|
475
|
-
|
476
|
-
|
477
|
-
addKDPoint(clientX, yBottom, minI);
|
464
|
+
if (sampling) {
|
465
|
+
if (minI === undefined || clientX === lastClientX) {
|
466
|
+
if (!isRange) {
|
467
|
+
low = y;
|
468
|
+
}
|
469
|
+
if (maxI === undefined || y > maxVal) {
|
470
|
+
maxVal = y;
|
471
|
+
maxI = i;
|
472
|
+
}
|
473
|
+
if (minI === undefined || low < minVal) {
|
474
|
+
minVal = low;
|
475
|
+
minI = i;
|
478
476
|
}
|
477
|
+
|
479
478
|
}
|
479
|
+
if (clientX !== lastClientX) { // Add points and reset
|
480
|
+
if (minI !== undefined) { // then maxI is also a number
|
481
|
+
plotY = yAxis.toPixels(maxVal, true);
|
482
|
+
yBottom = yAxis.toPixels(minVal, true);
|
483
|
+
drawPoint(
|
484
|
+
clientX,
|
485
|
+
hasThreshold ? Math.min(plotY, translatedThreshold) : plotY,
|
486
|
+
hasThreshold ? Math.max(yBottom, translatedThreshold) : yBottom
|
487
|
+
);
|
488
|
+
addKDPoint(clientX, plotY, maxI);
|
489
|
+
if (yBottom !== plotY) {
|
490
|
+
addKDPoint(clientX, yBottom, minI);
|
491
|
+
}
|
492
|
+
}
|
480
493
|
|
481
494
|
|
482
|
-
|
483
|
-
|
495
|
+
minI = maxI = undefined;
|
496
|
+
lastClientX = clientX;
|
497
|
+
}
|
498
|
+
} else {
|
499
|
+
plotY = Math.round(yAxis.toPixels(y, true));
|
500
|
+
drawPoint(clientX, plotY, yBottom);
|
501
|
+
addKDPoint(clientX, plotY, i);
|
484
502
|
}
|
485
|
-
}
|
486
|
-
|
487
|
-
|
488
|
-
|
503
|
+
}
|
504
|
+
wasNull = isNull && !connectNulls;
|
505
|
+
|
506
|
+
if (i % CHUNK_SIZE === 0) {
|
507
|
+
series.canvasToSVG();
|
489
508
|
}
|
490
509
|
}
|
491
|
-
wasNull = isNull && !connectNulls;
|
492
510
|
|
493
|
-
|
494
|
-
|
511
|
+
return !chartDestroyed;
|
512
|
+
}, function() {
|
513
|
+
var loadingDiv = chart.loadingDiv,
|
514
|
+
loadingShown = chart.loadingShown;
|
515
|
+
stroke();
|
516
|
+
series.canvasToSVG();
|
517
|
+
|
518
|
+
fireEvent(series, 'renderedCanvas');
|
519
|
+
|
520
|
+
// Do not use chart.hideLoading, as it runs JS animation and will be blocked by buildKDTree.
|
521
|
+
// CSS animation looks good, but then it must be deleted in timeout. If we add the module to core,
|
522
|
+
// change hideLoading so we can skip this block.
|
523
|
+
if (loadingShown) {
|
524
|
+
extend(loadingDiv.style, {
|
525
|
+
transition: 'opacity 250ms',
|
526
|
+
opacity: 0
|
527
|
+
});
|
528
|
+
chart.loadingShown = false;
|
529
|
+
destroyLoadingDiv = setTimeout(function() {
|
530
|
+
if (loadingDiv.parentNode) { // In exporting it is falsy
|
531
|
+
loadingDiv.parentNode.removeChild(loadingDiv);
|
532
|
+
}
|
533
|
+
chart.loadingDiv = chart.loadingSpan = null;
|
534
|
+
}, 250);
|
495
535
|
}
|
496
|
-
}
|
497
536
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
537
|
+
// Pass tests in Pointer.
|
538
|
+
// Replace this with a single property, and replace when zooming in
|
539
|
+
// below boostThreshold.
|
540
|
+
series.directTouch = false;
|
541
|
+
series.options.stickyTracking = true;
|
542
|
+
|
543
|
+
delete series.buildKDTree; // Go back to prototype, ready to build
|
544
|
+
series.buildKDTree();
|
545
|
+
|
546
|
+
// Don't do async on export, the exportChart, getSVGForExport and getSVG methods are not chained for it.
|
547
|
+
}, chart.renderer.forExport ? Number.MAX_VALUE : undefined);
|
548
|
+
}
|
549
|
+
});
|
550
|
+
|
551
|
+
seriesTypes.scatter.prototype.cvsMarkerCircle = function(ctx, clientX, plotY, r) {
|
552
|
+
ctx.moveTo(clientX, plotY);
|
553
|
+
ctx.arc(clientX, plotY, r, 0, 2 * Math.PI, false);
|
554
|
+
};
|
555
|
+
|
556
|
+
// Rect is twice as fast as arc, should be used for small markers
|
557
|
+
seriesTypes.scatter.prototype.cvsMarkerSquare = function(ctx, clientX, plotY, r) {
|
558
|
+
ctx.rect(clientX - r, plotY - r, r * 2, r * 2);
|
559
|
+
};
|
560
|
+
seriesTypes.scatter.prototype.fill = true;
|
561
|
+
|
562
|
+
extend(seriesTypes.area.prototype, {
|
563
|
+
cvsDrawPoint: function(ctx, clientX, plotY, yBottom, lastPoint) {
|
564
|
+
if (lastPoint && clientX !== lastPoint.clientX) {
|
565
|
+
ctx.moveTo(lastPoint.clientX, lastPoint.yBottom);
|
566
|
+
ctx.lineTo(lastPoint.clientX, lastPoint.plotY);
|
567
|
+
ctx.lineTo(clientX, plotY);
|
568
|
+
ctx.lineTo(clientX, yBottom);
|
522
569
|
}
|
570
|
+
},
|
571
|
+
fill: true,
|
572
|
+
fillOpacity: true,
|
573
|
+
sampling: true
|
574
|
+
});
|
575
|
+
|
576
|
+
extend(seriesTypes.column.prototype, {
|
577
|
+
cvsDrawPoint: function(ctx, clientX, plotY, yBottom) {
|
578
|
+
ctx.rect(clientX - 1, plotY, 1, yBottom - plotY);
|
579
|
+
},
|
580
|
+
fill: true,
|
581
|
+
sampling: true
|
582
|
+
});
|
523
583
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
584
|
+
/**
|
585
|
+
* Return a full Point object based on the index. The boost module uses stripped point objects
|
586
|
+
* for performance reasons.
|
587
|
+
* @param {Number} boostPoint A stripped-down point object
|
588
|
+
* @returns {Object} A Point object as per http://api.highcharts.com/highcharts#Point
|
589
|
+
*/
|
590
|
+
Series.prototype.getPoint = function(boostPoint) {
|
591
|
+
var point = boostPoint;
|
529
592
|
|
530
|
-
|
531
|
-
|
593
|
+
if (boostPoint && !(boostPoint instanceof this.pointClass)) {
|
594
|
+
point = (new this.pointClass()).init(this, this.options.data[boostPoint.i]); // eslint-disable-line new-cap
|
595
|
+
point.category = point.x;
|
532
596
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
seriesTypes.scatter.prototype.cvsMarkerCircle = function (ctx, clientX, plotY, r) {
|
539
|
-
ctx.moveTo(clientX, plotY);
|
540
|
-
ctx.arc(clientX, plotY, r, 0, 2 * Math.PI, false);
|
541
|
-
};
|
542
|
-
|
543
|
-
// Rect is twice as fast as arc, should be used for small markers
|
544
|
-
seriesTypes.scatter.prototype.cvsMarkerSquare = function (ctx, clientX, plotY, r) {
|
545
|
-
ctx.rect(clientX - r, plotY - r, r * 2, r * 2);
|
546
|
-
};
|
547
|
-
seriesTypes.scatter.prototype.fill = true;
|
548
|
-
|
549
|
-
extend(seriesTypes.area.prototype, {
|
550
|
-
cvsDrawPoint: function (ctx, clientX, plotY, yBottom, lastPoint) {
|
551
|
-
if (lastPoint && clientX !== lastPoint.clientX) {
|
552
|
-
ctx.moveTo(lastPoint.clientX, lastPoint.yBottom);
|
553
|
-
ctx.lineTo(lastPoint.clientX, lastPoint.plotY);
|
554
|
-
ctx.lineTo(clientX, plotY);
|
555
|
-
ctx.lineTo(clientX, yBottom);
|
597
|
+
point.dist = boostPoint.dist;
|
598
|
+
point.distX = boostPoint.distX;
|
599
|
+
point.plotX = boostPoint.plotX;
|
600
|
+
point.plotY = boostPoint.plotY;
|
556
601
|
}
|
557
|
-
},
|
558
|
-
fill: true,
|
559
|
-
fillOpacity: true,
|
560
|
-
sampling: true
|
561
|
-
});
|
562
|
-
|
563
|
-
extend(seriesTypes.column.prototype, {
|
564
|
-
cvsDrawPoint: function (ctx, clientX, plotY, yBottom) {
|
565
|
-
ctx.rect(clientX - 1, plotY, 1, yBottom - plotY);
|
566
|
-
},
|
567
|
-
fill: true,
|
568
|
-
sampling: true
|
569
|
-
});
|
570
|
-
|
571
|
-
/**
|
572
|
-
* Return a full Point object based on the index. The boost module uses stripped point objects
|
573
|
-
* for performance reasons.
|
574
|
-
* @param {Number} boostPoint A stripped-down point object
|
575
|
-
* @returns {Object} A Point object as per http://api.highcharts.com/highcharts#Point
|
576
|
-
*/
|
577
|
-
Series.prototype.getPoint = function (boostPoint) {
|
578
|
-
var point = boostPoint;
|
579
|
-
|
580
|
-
if (boostPoint && !(boostPoint instanceof this.pointClass)) {
|
581
|
-
point = (new this.pointClass()).init(this, this.options.data[boostPoint.i]);
|
582
|
-
point.category = point.x;
|
583
|
-
|
584
|
-
point.dist = boostPoint.dist;
|
585
|
-
point.distX = boostPoint.distX;
|
586
|
-
point.plotX = boostPoint.plotX;
|
587
|
-
point.plotY = boostPoint.plotY;
|
588
|
-
}
|
589
602
|
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
/**
|
594
|
-
* Extend series.destroy to also remove the fake k-d-tree points (#5137). Normally
|
595
|
-
* this is handled by Series.destroy that calls Point.destroy, but the fake
|
596
|
-
* search points are not registered like that.
|
597
|
-
*/
|
598
|
-
wrap(Series.prototype, 'destroy', function (proceed) {
|
599
|
-
var series = this,
|
600
|
-
chart = series.chart;
|
601
|
-
if (chart.hoverPoints) {
|
602
|
-
chart.hoverPoints = grep(chart.hoverPoints, function (point) {
|
603
|
-
return point.series === series;
|
604
|
-
});
|
605
|
-
}
|
603
|
+
return point;
|
604
|
+
};
|
606
605
|
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
606
|
+
/**
|
607
|
+
* Extend series.destroy to also remove the fake k-d-tree points (#5137). Normally
|
608
|
+
* this is handled by Series.destroy that calls Point.destroy, but the fake
|
609
|
+
* search points are not registered like that.
|
610
|
+
*/
|
611
|
+
wrap(Series.prototype, 'destroy', function(proceed) {
|
612
|
+
var series = this,
|
613
|
+
chart = series.chart;
|
614
|
+
if (chart.hoverPoints) {
|
615
|
+
chart.hoverPoints = grep(chart.hoverPoints, function(point) {
|
616
|
+
return point.series === series;
|
617
|
+
});
|
618
|
+
}
|
619
|
+
|
620
|
+
if (chart.hoverPoint && chart.hoverPoint.series === series) {
|
621
|
+
chart.hoverPoint = null;
|
622
|
+
}
|
623
|
+
proceed.call(this);
|
624
|
+
});
|
625
|
+
|
626
|
+
/**
|
627
|
+
* Return a point instance from the k-d-tree
|
628
|
+
*/
|
629
|
+
wrap(Series.prototype, 'searchPoint', function(proceed) {
|
630
|
+
return this.getPoint(
|
631
|
+
proceed.apply(this, [].slice.call(arguments, 1))
|
632
|
+
);
|
633
|
+
});
|
634
|
+
|
635
|
+
}(Highcharts));
|
621
636
|
}));
|