highcharts_rails 0.1.0

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