highstock-rails 1.3.10 → 2.1.10

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