highcharts-rails 5.0.10 → 5.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +48 -0
  3. data/app/assets/javascripts/highcharts.js +2395 -1517
  4. data/app/assets/javascripts/highcharts/highcharts-3d.js +212 -116
  5. data/app/assets/javascripts/highcharts/highcharts-more.js +17 -11
  6. data/app/assets/javascripts/highcharts/modules/accessibility.js +29 -16
  7. data/app/assets/javascripts/highcharts/modules/annotations.js +3 -4
  8. data/app/assets/javascripts/highcharts/modules/boost.js +392 -356
  9. data/app/assets/javascripts/highcharts/modules/broken-axis.js +42 -17
  10. data/app/assets/javascripts/highcharts/modules/data.js +6 -6
  11. data/app/assets/javascripts/highcharts/modules/drilldown.js +54 -27
  12. data/app/assets/javascripts/highcharts/modules/exporting.js +125 -102
  13. data/app/assets/javascripts/highcharts/modules/funnel.js +17 -9
  14. data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
  15. data/app/assets/javascripts/highcharts/modules/heatmap.js +12 -2
  16. data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +1 -1
  17. data/app/assets/javascripts/highcharts/modules/offline-exporting.js +12 -4
  18. data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +1 -1
  19. data/app/assets/javascripts/highcharts/modules/series-label.js +1 -1
  20. data/app/assets/javascripts/highcharts/modules/solid-gauge.js +2 -2
  21. data/app/assets/javascripts/highcharts/modules/stock.js +182 -101
  22. data/app/assets/javascripts/highcharts/modules/treemap.js +4 -7
  23. data/app/assets/javascripts/highcharts/modules/xrange-series.js +1 -1
  24. data/lib/highcharts/version.rb +1 -1
  25. metadata +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.10 (2017-03-31)
2
+ * @license Highcharts JS v5.0.11 (2017-05-04)
3
3
  *
4
4
  * (c) 2009-2016 Torstein Honsi
5
5
  *
@@ -87,13 +87,14 @@
87
87
  // Render the backgrounds
88
88
  if (backgroundOption) {
89
89
  backgroundOption = splat(backgroundOption);
90
+
90
91
  len = Math.max(
91
92
  backgroundOption.length,
92
93
  this.background.length || 0
93
94
  );
94
95
 
95
96
  for (i = 0; i < len; i++) {
96
- if (backgroundOption[i]) {
97
+ if (backgroundOption[i] && this.axis) { // #6641 - if axis exists, chart is circular and apply background
97
98
  this.renderBackground(
98
99
  merge(
99
100
  this.defaultBackgroundOptions,
@@ -1959,17 +1960,17 @@
1959
1960
  }
1960
1961
  // up points
1961
1962
  y = Math.max(previousY, previousY + point.y) + range[0];
1962
- shapeArgs.y = yAxis.toPixels(y, true);
1963
+ shapeArgs.y = yAxis.translate(y, 0, 1, 0, 1);
1963
1964
 
1964
1965
  // sum points
1965
1966
  if (point.isSum) {
1966
- shapeArgs.y = yAxis.toPixels(range[1], true);
1967
- shapeArgs.height = Math.min(yAxis.toPixels(range[0], true), yAxis.len) -
1967
+ shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1);
1968
+ shapeArgs.height = Math.min(yAxis.translate(range[0], 0, 1, 0, 1), yAxis.len) -
1968
1969
  shapeArgs.y; // #4256
1969
1970
 
1970
1971
  } else if (point.isIntermediateSum) {
1971
- shapeArgs.y = yAxis.toPixels(range[1], true);
1972
- shapeArgs.height = Math.min(yAxis.toPixels(previousIntermediate, true), yAxis.len) -
1972
+ shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1);
1973
+ shapeArgs.height = Math.min(yAxis.translate(previousIntermediate, 0, 1, 0, 1), yAxis.len) -
1973
1974
  shapeArgs.y;
1974
1975
  previousIntermediate = range[1];
1975
1976
 
@@ -1977,8 +1978,8 @@
1977
1978
  // shape height (#3886)
1978
1979
  } else {
1979
1980
  shapeArgs.height = yValue > 0 ?
1980
- yAxis.toPixels(previousY, true) - shapeArgs.y :
1981
- yAxis.toPixels(previousY, true) - yAxis.toPixels(previousY - yValue, true);
1981
+ yAxis.translate(previousY, 0, 1, 0, 1) - shapeArgs.y :
1982
+ yAxis.translate(previousY, 0, 1, 0, 1) - yAxis.translate(previousY - yValue, 0, 1, 0, 1);
1982
1983
 
1983
1984
  previousY += stack && stack[point.x] ? stack[point.x].total : yValue;
1984
1985
  }
@@ -2116,6 +2117,7 @@
2116
2117
  length = data.length,
2117
2118
  lineWidth = this.graph.strokeWidth() + this.borderWidth,
2118
2119
  normalizer = Math.round(lineWidth) % 2 / 2,
2120
+ reversedYAxis = this.yAxis.reversed,
2119
2121
  path = [],
2120
2122
  prevArgs,
2121
2123
  pointArgs,
@@ -2135,7 +2137,10 @@
2135
2137
  prevArgs.y + data[i - 1].minPointLengthOffset + normalizer
2136
2138
  ];
2137
2139
 
2138
- if (data[i - 1].y < 0) {
2140
+ if (
2141
+ (data[i - 1].y < 0 && !reversedYAxis) ||
2142
+ (data[i - 1].y > 0 && reversedYAxis)
2143
+ ) {
2139
2144
  d[2] += prevArgs.height;
2140
2145
  d[5] += prevArgs.height;
2141
2146
  }
@@ -2348,7 +2353,8 @@
2348
2353
  }, {
2349
2354
  pointArrayMap: ['y', 'z'],
2350
2355
  parallelArrays: ['x', 'y', 'z'],
2351
- trackerGroups: ['markerGroup', 'dataLabelsGroup'],
2356
+ trackerGroups: ['group', 'dataLabelsGroup'],
2357
+ specialGroup: 'group', // To allow clipping (#6296)
2352
2358
  bubblePadding: true,
2353
2359
  zoneAxis: 'z',
2354
2360
  directTouch: true,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.10 (2017-03-31)
2
+ * @license Highcharts JS v5.0.11 (2017-05-04)
3
3
  * Accessibility module
4
4
  *
5
5
  * (c) 2010-2017 Highsoft AS
@@ -410,9 +410,12 @@
410
410
  return false;
411
411
  }
412
412
 
413
- // Recursively skip null points
414
- if (newPoint.isNull && this.options.accessibility.keyboardNavigation &&
415
- this.options.accessibility.keyboardNavigation.skipNullPoints) {
413
+ // Recursively skip null points or points in series that should be skipped
414
+ if (
415
+ newPoint.isNull &&
416
+ this.options.accessibility.keyboardNavigation.skipNullPoints ||
417
+ newPoint.series.options.skipKeyboardNavigation // docs
418
+ ) {
416
419
  this.highlightedPoint = newPoint;
417
420
  return this.highlightAdjacentPoint(next);
418
421
  }
@@ -870,8 +873,10 @@
870
873
  ]
871
874
  ], {
872
875
  // Only run this module if we have at least one legend - wait for it - item.
876
+ // Don't run if the legend is populated by a colorAxis.
873
877
  validate: function() {
874
- return chart.legend && chart.legend.allItems && !chart.colorAxis;
878
+ return chart.legend && chart.legend.allItems &&
879
+ !(chart.colorAxis && chart.colorAxis.length);
875
880
  },
876
881
 
877
882
  // Make elements focusable and accessible
@@ -945,7 +950,7 @@
945
950
  (axesDesc.xAxis ? ('<div>' + axesDesc.xAxis + '</div>') : '') +
946
951
  (axesDesc.yAxis ? ('<div>' + axesDesc.yAxis + '</div>') : '');
947
952
 
948
- // Add shortcut to data table if export-csv is loaded
953
+ // Add shortcut to data table if export-data is loaded
949
954
  if (chart.getCSV) {
950
955
  tableShortcutAnchor.innerHTML = 'View as data table.';
951
956
  tableShortcutAnchor.href = '#' + tableId;
@@ -1037,31 +1042,38 @@
1037
1042
  chart.addScreenReaderRegion(hiddenSectionId, tableId);
1038
1043
 
1039
1044
  // Enable keyboard navigation
1040
- if (a11yOptions.keyboardNavigation) {
1045
+ if (a11yOptions.keyboardNavigation.enabled) {
1041
1046
  chart.addKeyboardNavEvents();
1042
1047
  }
1043
1048
 
1044
- /* Wrap table functionality from export-csv */
1049
+ /* Wrap table functionality from export-data */
1045
1050
 
1046
1051
  // Keep track of columns
1047
1052
  merge(true, options.exporting, {
1048
1053
  csv: {
1049
- columnHeaderFormatter: function(series, key, keyLength) {
1054
+ columnHeaderFormatter: function(item, key, keyLength) {
1055
+ if (!item) {
1056
+ return 'Category';
1057
+ }
1058
+ if (item instanceof H.Axis) {
1059
+ return (item.options.title && item.options.title.text) ||
1060
+ (item.isDatetimeAxis ? 'DateTime' : 'Category');
1061
+ }
1050
1062
  var prevCol = topLevelColumns[topLevelColumns.length - 1];
1051
1063
  if (keyLength > 1) {
1052
1064
  // We need multiple levels of column headers
1053
- // Populate a list of column headers to add in addition to the ones added by export-csv
1054
- if ((prevCol && prevCol.text) !== series.name) {
1065
+ // Populate a list of column headers to add in addition to the ones added by export-data
1066
+ if ((prevCol && prevCol.text) !== item.name) {
1055
1067
  topLevelColumns.push({
1056
- text: series.name,
1068
+ text: item.name,
1057
1069
  span: keyLength
1058
1070
  });
1059
1071
  }
1060
1072
  }
1061
1073
  if (oldColumnHeaderFormatter) {
1062
- return oldColumnHeaderFormatter.call(this, series, key, keyLength);
1074
+ return oldColumnHeaderFormatter.call(this, item, key, keyLength);
1063
1075
  }
1064
- return keyLength > 1 ? key : series.name;
1076
+ return keyLength > 1 ? key : item.name;
1065
1077
  }
1066
1078
  }
1067
1079
  });
@@ -1078,8 +1090,9 @@
1078
1090
  proceed.apply(this, Array.prototype.slice.call(arguments, 1));
1079
1091
 
1080
1092
  var table = doc.getElementById(tableId),
1093
+ head = table.getElementsByTagName('thead')[0],
1081
1094
  body = table.getElementsByTagName('tbody')[0],
1082
- firstRow = body.firstChild.children,
1095
+ firstRow = head.firstChild.children,
1083
1096
  columnHeaderRow = '<tr><td></td>',
1084
1097
  cell,
1085
1098
  newCell;
@@ -1108,7 +1121,7 @@
1108
1121
  each(topLevelColumns, function(col) {
1109
1122
  columnHeaderRow += '<th scope="col" colspan="' + col.span + '">' + col.text + '</th>';
1110
1123
  });
1111
- body.insertAdjacentHTML('afterbegin', columnHeaderRow);
1124
+ head.insertAdjacentHTML('afterbegin', columnHeaderRow);
1112
1125
  }
1113
1126
  }
1114
1127
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.10 (2017-03-31)
2
+ * @license Highcharts JS v5.0.11 (2017-05-04)
3
3
  *
4
4
  * (c) 2009-2017 Torstein Honsi
5
5
  *
@@ -172,7 +172,6 @@
172
172
  shapeParams,
173
173
  linkType,
174
174
  series,
175
- param,
176
175
  bbox,
177
176
  x,
178
177
  y;
@@ -215,13 +214,13 @@
215
214
  shapeParams = extend({}, options.shape.params);
216
215
 
217
216
  if (options.units === 'values') {
218
- for (param in shapeParams) {
217
+ H.objectEach(shapeParams, function(val, param) {
219
218
  if (inArray(param, ['width', 'x']) > -1) {
220
219
  shapeParams[param] = xAxis.translate(shapeParams[param]);
221
220
  } else if (inArray(param, ['height', 'y']) > -1) {
222
221
  shapeParams[param] = yAxis.translate(shapeParams[param]);
223
222
  }
224
- }
223
+ });
225
224
 
226
225
  if (shapeParams.width) {
227
226
  shapeParams.width -= xAxis.toPixels(0) - xAxis.left;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.10 (2017-03-31)
2
+ * @license Highcharts JS v5.0.11 (2017-05-04)
3
3
  * Boost module
4
4
  *
5
5
  * (c) 2010-2017 Highsoft AS
@@ -61,8 +61,8 @@
61
61
  *
62
62
  * Settings
63
63
  * There are two ways of setting the boost threshold:
64
- * - Per. series: boost based on number of points in individual series
65
- * - Per. chart: boost based on the number of series
64
+ * - Per. series: boost based on number of points in individual series
65
+ * - Per. chart: boost based on the number of series
66
66
  *
67
67
  * To set the series boost threshold, set seriesBoostThreshold on the chart object.
68
68
  * To set the series-specific threshold, set boostThreshold on the series object.
@@ -115,7 +115,7 @@
115
115
  * @apioption series.boostThreshold
116
116
  */
117
117
 
118
- /* global Float32Array, Image */
118
+ /* global Float32Array */
119
119
 
120
120
 
121
121
  var win = H.win,
@@ -1097,7 +1097,15 @@
1097
1097
  minVal,
1098
1098
  color,
1099
1099
  scolor,
1100
- sdata = isStacked ? series.data : (xData || rawData);
1100
+ sdata = isStacked ? series.data : (xData || rawData),
1101
+ closestLeft = {
1102
+ x: Number.MIN_VALUE,
1103
+ y: 0
1104
+ },
1105
+ closestRight = {
1106
+ x: Number.MIN_VALUE,
1107
+ y: 0
1108
+ };
1101
1109
 
1102
1110
  if (options.boostData && options.boostData.length > 0) {
1103
1111
  return;
@@ -1176,9 +1184,11 @@
1176
1184
 
1177
1185
  if (plotY !== undefined && !isNaN(plotY) && point.y !== null) {
1178
1186
  shapeArgs = point.shapeArgs;
1179
- pointAttr = (point.pointAttr && point.pointAttr['']) ||
1180
- point.series.pointAttribs(point);
1181
- swidth = pointAttr['stroke-width'];
1187
+
1188
+
1189
+ pointAttr = point.series.pointAttribs(point);
1190
+
1191
+ swidth = pointAttr['stroke-width'] || 0;
1182
1192
 
1183
1193
  // Handle point colors
1184
1194
  color = H.color(pointAttr.fill).rgba;
@@ -1344,7 +1354,17 @@
1344
1354
  isYInside = y >= yMin && y <= yMax;
1345
1355
  }
1346
1356
 
1347
- if ((!y || !isYInside)) {
1357
+ if (x > xMax && closestRight.x < xMax) {
1358
+ closestRight.x = x;
1359
+ closestRight.y = y;
1360
+ }
1361
+
1362
+ if (x < xMin && closestLeft.x < xMin) {
1363
+ closestLeft.x = x;
1364
+ closestLeft.y = y;
1365
+ }
1366
+
1367
+ if (y !== 0 && (!y || !isYInside)) {
1348
1368
  return;
1349
1369
  }
1350
1370
 
@@ -1427,6 +1447,30 @@
1427
1447
 
1428
1448
  //return true;
1429
1449
  });
1450
+
1451
+ function pushSupplementPoint(point) {
1452
+ if (!settings.useGPUTranslations) {
1453
+ inst.skipTranslation = true;
1454
+ point.x = xAxis.toPixels(point.x, true);
1455
+ point.y = yAxis.toPixels(point.y, true);
1456
+ }
1457
+
1458
+ // We should only do this for lines, and we should ignore markers
1459
+ // since there's no point here that would have a marker.
1460
+
1461
+ vertice(
1462
+ point.x,
1463
+ point.y,
1464
+ 0,
1465
+ 2
1466
+ );
1467
+ }
1468
+
1469
+ if (!lastX) {
1470
+ // There are no points within the selected range
1471
+ pushSupplementPoint(closestLeft);
1472
+ pushSupplementPoint(closestRight);
1473
+ }
1430
1474
  }
1431
1475
 
1432
1476
  /*
@@ -1566,7 +1610,9 @@
1566
1610
  gl.viewport(0, 0, width, height);
1567
1611
  shader.setPMatrix(orthoMatrix(width, height));
1568
1612
 
1569
- gl.lineWidth(settings.lineWidth);
1613
+ if (settings.lineWidth > 1 && !H.isMS) {
1614
+ gl.lineWidth(settings.lineWidth);
1615
+ }
1570
1616
 
1571
1617
  vbuffer.build(exports.data, 'aVertexPosition', 4);
1572
1618
  vbuffer.bind();
@@ -1628,8 +1674,9 @@
1628
1674
  gl.blendEquation(gl.FUNC_MIN);
1629
1675
 
1630
1676
  } else {
1631
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); //, gl.ONE, gl.ZERO);
1632
- gl.blendEquation(gl.FUNC_ADD);
1677
+ //gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);//, gl.ONE, gl.ZERO);
1678
+ //gl.blendEquation(gl.FUNC_ADD);
1679
+ gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
1633
1680
  }
1634
1681
 
1635
1682
  shader.reset();
@@ -1737,7 +1784,6 @@
1737
1784
  */
1738
1785
  function init(canvas, noFlush) {
1739
1786
  var i = 0,
1740
- activeContext,
1741
1787
  contexts = [
1742
1788
  'webgl',
1743
1789
  'experimental-webgl',
@@ -1758,7 +1804,6 @@
1758
1804
  for (; i < contexts.length; i++) {
1759
1805
  gl = canvas.getContext(contexts[i]);
1760
1806
  if (gl) {
1761
- activeContext = contexts[i];
1762
1807
  break;
1763
1808
  }
1764
1809
  }
@@ -2230,6 +2275,25 @@
2230
2275
  return false;
2231
2276
  }
2232
2277
 
2278
+ /* Used for treemap|heatmap.drawPoints */
2279
+ function pointDrawHandler(proceed) {
2280
+ if (!isSeriesBoosting(this)) {
2281
+ return proceed.call(this);
2282
+ }
2283
+
2284
+ //Make sure we have a valid OGL context
2285
+ var renderer = createAndAttachRenderer(this.chart, this);
2286
+
2287
+ if (renderer) {
2288
+ allocateIfNotSeriesBoosting(renderer, this);
2289
+ renderer.pushSeries(this);
2290
+ }
2291
+
2292
+ renderIfNotSeriesBoosting(renderer, this);
2293
+ }
2294
+
2295
+
2296
+
2233
2297
  ////////////////////////////////////////////////////////////////////////////////
2234
2298
  // We're wrapped in a closure, so just return if there's no webgl support
2235
2299
 
@@ -2240,404 +2304,376 @@
2240
2304
  } else {
2241
2305
  H.error(26);
2242
2306
  }
2243
- //eslint-disable
2244
- return;
2245
- //eslint-enable
2246
- }
2307
+ } else {
2247
2308
 
2248
- ////////////////////////////////////////////////////////////////////////////////
2249
- // GL-SPECIFIC WRAPPINGS FOLLOWS
2309
+ ////////////////////////////////////////////////////////////////////////////
2310
+ // GL-SPECIFIC WRAPPINGS FOLLOWS
2250
2311
 
2251
- /** If the series is a heatmap or treemap, or if the series is not boosting
2252
- * do the default behaviour. Otherwise, process if the series has no
2253
- * extremes.
2254
- */
2255
- wrap(Series.prototype, 'processData', function(proceed) {
2256
- // If this is a heatmap, do default behaviour
2257
- if (!isSeriesBoosting(this) ||
2258
- this.type === 'heatmap' ||
2259
- this.type === 'treemap') {
2260
- proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2261
- }
2312
+ /** If the series is a heatmap or treemap, or if the series is not boosting
2313
+ * do the default behaviour. Otherwise, process if the series has no
2314
+ * extremes.
2315
+ */
2316
+ wrap(Series.prototype, 'processData', function(proceed) {
2317
+ // If this is a heatmap, do default behaviour
2318
+ if (!isSeriesBoosting(this) ||
2319
+ this.type === 'heatmap' ||
2320
+ this.type === 'treemap') {
2321
+ proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2322
+ }
2262
2323
 
2263
- if (!this.hasExtremes || !this.hasExtremes(true)) {
2264
- proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2265
- }
2266
- });
2324
+ if (!this.hasExtremes || !this.hasExtremes(true)) {
2325
+ proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2326
+ }
2327
+ });
2267
2328
 
2268
- H.extend(Series.prototype, {
2269
- pointRange: 0,
2270
- directTouch: false,
2271
- allowDG: false, // No data grouping, let boost handle large data
2272
- hasExtremes: function(checkX) {
2273
- var options = this.options,
2274
- data = options.data,
2275
- xAxis = this.xAxis && this.xAxis.options,
2276
- yAxis = this.yAxis && this.yAxis.options;
2277
-
2278
- return data.length > (options.boostThreshold || Number.MAX_VALUE) &&
2279
- isNumber(yAxis.min) && isNumber(yAxis.max) &&
2280
- (!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
2281
- },
2329
+ H.extend(Series.prototype, {
2330
+ pointRange: 0,
2331
+ directTouch: false,
2332
+ allowDG: false, // No data grouping, let boost handle large data
2333
+ hasExtremes: function(checkX) {
2334
+ var options = this.options,
2335
+ data = options.data,
2336
+ xAxis = this.xAxis && this.xAxis.options,
2337
+ yAxis = this.yAxis && this.yAxis.options;
2338
+
2339
+ return data.length > (options.boostThreshold || Number.MAX_VALUE) &&
2340
+ isNumber(yAxis.min) && isNumber(yAxis.max) &&
2341
+ (!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
2342
+ },
2282
2343
 
2283
- /**
2284
- * If implemented in the core, parts of this can probably be
2285
- * shared with other similar methods in Highcharts.
2286
- */
2287
- destroyGraphics: function() {
2288
- var series = this,
2289
- points = this.points,
2290
- point,
2291
- i;
2292
-
2293
- if (points) {
2294
- for (i = 0; i < points.length; i = i + 1) {
2295
- point = points[i];
2296
- if (point && point.graphic) {
2297
- point.graphic = point.graphic.destroy();
2344
+ /**
2345
+ * If implemented in the core, parts of this can probably be
2346
+ * shared with other similar methods in Highcharts.
2347
+ */
2348
+ destroyGraphics: function() {
2349
+ var series = this,
2350
+ points = this.points,
2351
+ point,
2352
+ i;
2353
+
2354
+ if (points) {
2355
+ for (i = 0; i < points.length; i = i + 1) {
2356
+ point = points[i];
2357
+ if (point && point.graphic) {
2358
+ point.graphic = point.graphic.destroy();
2359
+ }
2298
2360
  }
2299
2361
  }
2300
- }
2301
2362
 
2302
- each(['graph', 'area', 'tracker'], function(prop) {
2303
- if (series[prop]) {
2304
- series[prop] = series[prop].destroy();
2305
- }
2306
- });
2307
- },
2363
+ each(['graph', 'area', 'tracker'], function(prop) {
2364
+ if (series[prop]) {
2365
+ series[prop] = series[prop].destroy();
2366
+ }
2367
+ });
2368
+ },
2308
2369
 
2309
- renderCanvas: function() {
2310
- var series = this,
2311
- options = series.options || {},
2312
- renderer = false,
2313
- chart = series.chart,
2314
- xAxis = this.xAxis,
2315
- yAxis = this.yAxis,
2316
- //ctx,
2317
- //c = 0,
2318
- xData = options.xData || series.processedXData,
2319
- yData = options.yData || series.processedYData,
2370
+ renderCanvas: function() {
2371
+ var series = this,
2372
+ options = series.options || {},
2373
+ renderer = false,
2374
+ chart = series.chart,
2375
+ xAxis = this.xAxis,
2376
+ yAxis = this.yAxis,
2377
+ //ctx,
2378
+ //c = 0,
2379
+ xData = options.xData || series.processedXData,
2380
+ yData = options.yData || series.processedYData,
2381
+
2382
+ rawData = options.data,
2383
+ xExtremes = xAxis.getExtremes(),
2384
+ xMin = xExtremes.min,
2385
+ xMax = xExtremes.max,
2386
+ yExtremes = yAxis.getExtremes(),
2387
+ yMin = yExtremes.min,
2388
+ yMax = yExtremes.max,
2389
+ pointTaken = {},
2390
+ lastClientX,
2391
+ sampling = !!series.sampling,
2392
+ points,
2393
+ enableMouseTracking = options.enableMouseTracking !== false,
2394
+ threshold = options.threshold,
2395
+ yBottom = yAxis.getThreshold(threshold),
2396
+ isRange = series.pointArrayMap &&
2397
+ series.pointArrayMap.join(',') === 'low,high',
2398
+ isStacked = !!options.stacking,
2399
+ cropStart = series.cropStart || 0,
2400
+ requireSorting = series.requireSorting,
2401
+ useRaw = !xData,
2402
+ minVal,
2403
+ maxVal,
2404
+ minI,
2405
+ maxI,
2406
+
2407
+ addKDPoint = function(clientX, plotY, i) {
2408
+ //Shaves off about 60ms compared to repeated concatination
2409
+ index = clientX + ',' + plotY;
2410
+
2411
+ // The k-d tree requires series points.
2412
+ // Reduce the amount of points, since the time to build the
2413
+ // tree increases exponentially.
2414
+ if (enableMouseTracking && !pointTaken[index]) {
2415
+ pointTaken[index] = true;
2416
+
2417
+ if (chart.inverted) {
2418
+ clientX = xAxis.len - clientX;
2419
+ plotY = yAxis.len - plotY;
2420
+ }
2320
2421
 
2321
- rawData = options.data,
2322
- xExtremes = xAxis.getExtremes(),
2323
- xMin = xExtremes.min,
2324
- xMax = xExtremes.max,
2325
- yExtremes = yAxis.getExtremes(),
2326
- yMin = yExtremes.min,
2327
- yMax = yExtremes.max,
2328
- pointTaken = {},
2329
- lastClientX,
2330
- sampling = !!series.sampling,
2331
- points,
2332
- // r = options.marker && options.marker.radius,
2333
- // cvsDrawPoint = this.cvsDrawPoint,
2334
- // cvsLineTo = options.lineWidth ? this.cvsLineTo : false,
2335
- // cvsMarker = r <= 1 ? this.cvsMarkerSquare : this.cvsMarkerCircle,
2336
- enableMouseTracking = options.enableMouseTracking !== false,
2337
- // lastPoint,
2338
- threshold = options.threshold,
2339
- yBottom = yAxis.getThreshold(threshold),
2340
- hasThreshold = isNumber(threshold),
2341
- // translatedThreshold = yBottom,
2342
- // doFill = this.fill,
2343
- isRange = series.pointArrayMap &&
2344
- series.pointArrayMap.join(',') === 'low,high',
2345
- isStacked = !!options.stacking,
2346
- cropStart = series.cropStart || 0,
2347
- requireSorting = series.requireSorting,
2348
- wasNull,
2349
- connectNulls = options.connectNulls,
2350
- useRaw = !xData,
2351
- minVal,
2352
- maxVal,
2353
- minI,
2354
- maxI,
2355
- // fillColor = series.fillOpacity ?
2356
- // new Color(series.color).setOpacity(
2357
- // pick(options.fillOpacity, 0.75)
2358
- // ).get() : series.color,
2359
-
2360
- addKDPoint = function(clientX, plotY, i) {
2361
- //Shaves off about 60ms compared to repeated concatination
2362
- index = clientX + ',' + plotY;
2363
-
2364
- // The k-d tree requires series points.
2365
- // Reduce the amount of points, since the time to build the
2366
- // tree increases exponentially.
2367
- if (enableMouseTracking && !pointTaken[index]) {
2368
- pointTaken[index] = true;
2369
-
2370
- if (chart.inverted) {
2371
- clientX = xAxis.len - clientX;
2372
- plotY = yAxis.len - plotY;
2422
+ points.push({
2423
+ clientX: clientX,
2424
+ plotX: clientX,
2425
+ plotY: plotY,
2426
+ i: cropStart + i
2427
+ });
2373
2428
  }
2429
+ };
2374
2430
 
2375
- points.push({
2376
- clientX: clientX,
2377
- plotX: clientX,
2378
- plotY: plotY,
2379
- i: cropStart + i
2431
+ // Get or create the renderer
2432
+ renderer = createAndAttachRenderer(chart, series);
2433
+
2434
+ if (!this.visible) {
2435
+ if (!isChartSeriesBoosting(chart) && renderer) {
2436
+ renderer.clear();
2437
+ this.image.attr({
2438
+ href: ''
2380
2439
  });
2381
2440
  }
2382
- };
2383
-
2384
- // Get or create the renderer
2385
- renderer = createAndAttachRenderer(chart, series);
2386
-
2387
- if (!this.visible) {
2388
- if (!isChartSeriesBoosting(chart) && renderer) {
2389
- renderer.clear();
2390
- this.image.attr({
2391
- href: ''
2392
- });
2441
+ return;
2393
2442
  }
2394
- return;
2395
- }
2396
-
2397
- // If we are zooming out from SVG mode, destroy the graphics
2398
- if (this.points || this.graph) {
2399
- this.destroyGraphics();
2400
- }
2401
2443
 
2402
- // If we're rendering per. series we should create the marker groups
2403
- // as usual.
2404
- if (!isChartSeriesBoosting(chart)) {
2405
- this.markerGroup = series.plotGroup(
2406
- 'markerGroup',
2407
- 'markers',
2408
- true,
2409
- 1,
2410
- chart.seriesGroup
2411
- );
2412
- } else {
2413
- //Use a single group for the markers
2414
- this.markerGroup = chart.markerGroup;
2415
- }
2416
-
2417
- points = this.points = [];
2444
+ // If we are zooming out from SVG mode, destroy the graphics
2445
+ if (this.points || this.graph) {
2446
+ this.destroyGraphics();
2447
+ }
2418
2448
 
2419
- // Do not start building while drawing
2420
- series.buildKDTree = noop;
2449
+ // If we're rendering per. series we should create the marker groups
2450
+ // as usual.
2451
+ if (!isChartSeriesBoosting(chart)) {
2452
+ this.markerGroup = series.plotGroup(
2453
+ 'markerGroup',
2454
+ 'markers',
2455
+ true,
2456
+ 1,
2457
+ chart.seriesGroup
2458
+ );
2459
+ } else {
2460
+ //Use a single group for the markers
2461
+ this.markerGroup = chart.markerGroup;
2462
+ }
2421
2463
 
2422
- if (renderer) {
2423
- allocateIfNotSeriesBoosting(renderer, this);
2424
- renderer.pushSeries(series);
2425
- // Perform the actual renderer if we're on series level
2426
- renderIfNotSeriesBoosting(renderer, this, chart);
2427
- //console.log(series, chart);
2428
- }
2464
+ points = this.points = [];
2429
2465
 
2430
- /* This builds the KD-tree */
2431
- function processPoint(d, i) {
2432
- var x,
2433
- y,
2434
- clientX,
2435
- plotY,
2436
- isNull,
2437
- low,
2438
- chartDestroyed = typeof chart.index === 'undefined',
2439
- isYInside = true;
2466
+ // Do not start building while drawing
2467
+ series.buildKDTree = noop;
2440
2468
 
2441
- if (!chartDestroyed) {
2442
- if (useRaw) {
2443
- x = d[0];
2444
- y = d[1];
2445
- } else {
2446
- x = d;
2447
- y = yData[i];
2448
- }
2469
+ if (renderer) {
2470
+ allocateIfNotSeriesBoosting(renderer, this);
2471
+ renderer.pushSeries(series);
2472
+ // Perform the actual renderer if we're on series level
2473
+ renderIfNotSeriesBoosting(renderer, this, chart);
2474
+ //console.log(series, chart);
2475
+ }
2449
2476
 
2450
- // Resolve low and high for range series
2451
- if (isRange) {
2477
+ /* This builds the KD-tree */
2478
+ function processPoint(d, i) {
2479
+ var x,
2480
+ y,
2481
+ clientX,
2482
+ plotY,
2483
+ isNull,
2484
+ low,
2485
+ chartDestroyed = typeof chart.index === 'undefined',
2486
+ isYInside = true;
2487
+
2488
+ if (!chartDestroyed) {
2452
2489
  if (useRaw) {
2453
- y = d.slice(1, 3);
2490
+ x = d[0];
2491
+ y = d[1];
2492
+ } else {
2493
+ x = d;
2494
+ y = yData[i];
2454
2495
  }
2455
- low = y[0];
2456
- y = y[1];
2457
- } else if (isStacked) {
2458
- x = d.x;
2459
- y = d.stackY;
2460
- low = y - d.y;
2461
- }
2462
2496
 
2463
- isNull = y === null;
2497
+ // Resolve low and high for range series
2498
+ if (isRange) {
2499
+ if (useRaw) {
2500
+ y = d.slice(1, 3);
2501
+ }
2502
+ low = y[0];
2503
+ y = y[1];
2504
+ } else if (isStacked) {
2505
+ x = d.x;
2506
+ y = d.stackY;
2507
+ low = y - d.y;
2508
+ }
2464
2509
 
2465
- // Optimize for scatter zooming
2466
- if (!requireSorting) {
2467
- isYInside = y >= yMin && y <= yMax;
2468
- }
2510
+ isNull = y === null;
2469
2511
 
2470
- if (!isNull && x >= xMin && x <= xMax && isYInside) {
2512
+ // Optimize for scatter zooming
2513
+ if (!requireSorting) {
2514
+ isYInside = y >= yMin && y <= yMax;
2515
+ }
2471
2516
 
2472
- // We use ceil to allow the KD tree to work with sub pixels,
2473
- // which can be used in boost to space pixels
2474
- clientX = Math.ceil(xAxis.toPixels(x, true));
2517
+ if (!isNull && x >= xMin && x <= xMax && isYInside) {
2475
2518
 
2476
- if (sampling) {
2477
- if (minI === undefined || clientX === lastClientX) {
2478
- if (!isRange) {
2479
- low = y;
2480
- }
2481
- if (maxI === undefined || y > maxVal) {
2482
- maxVal = y;
2483
- maxI = i;
2484
- }
2485
- if (minI === undefined || low < minVal) {
2486
- minVal = low;
2487
- minI = i;
2488
- }
2519
+ // We use ceil to allow the KD tree to work with sub
2520
+ // pixels, which can be used in boost to space pixels
2521
+ clientX = Math.ceil(xAxis.toPixels(x, true));
2489
2522
 
2490
- }
2491
- if (clientX !== lastClientX) { // Add points and reset
2492
- if (minI !== undefined) { // then maxI is also a number
2493
- plotY = yAxis.toPixels(maxVal, true);
2494
- yBottom = yAxis.toPixels(minVal, true);
2495
-
2496
- addKDPoint(clientX, plotY, maxI);
2497
- if (yBottom !== plotY) {
2498
- addKDPoint(clientX, yBottom, minI);
2523
+ if (sampling) {
2524
+ if (minI === undefined || clientX === lastClientX) {
2525
+ if (!isRange) {
2526
+ low = y;
2527
+ }
2528
+ if (maxI === undefined || y > maxVal) {
2529
+ maxVal = y;
2530
+ maxI = i;
2531
+ }
2532
+ if (minI === undefined || low < minVal) {
2533
+ minVal = low;
2534
+ minI = i;
2499
2535
  }
2536
+
2500
2537
  }
2538
+ if (clientX !== lastClientX) { // Add points and reset
2539
+ if (minI !== undefined) { // then maxI is also a number
2540
+ plotY = yAxis.toPixels(maxVal, true);
2541
+ yBottom = yAxis.toPixels(minVal, true);
2542
+
2543
+ addKDPoint(clientX, plotY, maxI);
2544
+ if (yBottom !== plotY) {
2545
+ addKDPoint(clientX, yBottom, minI);
2546
+ }
2547
+ }
2501
2548
 
2502
- minI = maxI = undefined;
2503
- lastClientX = clientX;
2549
+ minI = maxI = undefined;
2550
+ lastClientX = clientX;
2551
+ }
2552
+ } else {
2553
+ plotY = Math.ceil(yAxis.toPixels(y, true));
2554
+ addKDPoint(clientX, plotY, i);
2504
2555
  }
2505
- } else {
2506
- plotY = Math.ceil(yAxis.toPixels(y, true));
2507
- addKDPoint(clientX, plotY, i);
2508
2556
  }
2509
2557
  }
2510
- wasNull = isNull && !connectNulls;
2558
+
2559
+ return !chartDestroyed;
2511
2560
  }
2512
2561
 
2513
- return !chartDestroyed;
2514
- }
2562
+ function doneProcessing() {
2563
+ fireEvent(series, 'renderedCanvas');
2564
+ // Pass tests in Pointer.
2565
+ // Replace this with a single property, and replace when zooming
2566
+ // in below boostThreshold.
2567
+ series.directTouch = false;
2568
+ series.options.stickyTracking = true;
2569
+
2570
+ // Go back to prototype, ready to build
2571
+ delete series.buildKDTree;
2572
+ series.buildKDTree();
2573
+ }
2515
2574
 
2516
- function doneProcessing() {
2517
- fireEvent(series, 'renderedCanvas');
2518
- // Pass tests in Pointer.
2519
- // Replace this with a single property, and replace when zooming in
2520
- // below boostThreshold.
2521
- series.directTouch = false;
2522
- series.options.stickyTracking = true;
2575
+ // Loop over the points to build the k-d tree
2576
+ eachAsync(
2577
+ isStacked ? series.data : (xData || rawData),
2578
+ processPoint,
2579
+ doneProcessing,
2580
+ chart.renderer.forExport ? Number.MAX_VALUE : undefined
2581
+ );
2582
+ }
2583
+ });
2523
2584
 
2524
- delete series.buildKDTree; // Go back to prototype, ready to build
2525
- series.buildKDTree();
2585
+ /*
2586
+ * We need to handle heatmaps separatly, since we can't perform the
2587
+ * size/color calculations in the shader easily.
2588
+ *
2589
+ * This likely needs future optimization.
2590
+ *
2591
+ */
2592
+ each(['heatmap', 'treemap'],
2593
+ function(t) {
2594
+ if (seriesTypes[t]) {
2595
+ wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler);
2596
+ seriesTypes[t].prototype.directTouch = false; // Use k-d-tree
2597
+ }
2526
2598
  }
2599
+ );
2527
2600
 
2528
- // Loop over the points to build the k-d tree
2529
- eachAsync(
2530
- isStacked ? series.data : (xData || rawData),
2531
- processPoint,
2532
- doneProcessing,
2533
- chart.renderer.forExport ? Number.MAX_VALUE : undefined
2601
+ if (seriesTypes.bubble) {
2602
+ // By default, the bubble series does not use the KD-tree, so force it
2603
+ // to.
2604
+ delete seriesTypes.bubble.prototype.buildKDTree;
2605
+ seriesTypes.bubble.prototype.directTouch = false;
2606
+
2607
+ // Needed for markers to work correctly
2608
+ wrap(
2609
+ seriesTypes.bubble.prototype,
2610
+ 'markerAttribs',
2611
+ function(proceed) {
2612
+ if (isSeriesBoosting(this)) {
2613
+ return false;
2614
+ }
2615
+ return proceed.apply(this, [].slice.call(arguments, 1));
2616
+ }
2534
2617
  );
2535
2618
  }
2536
- });
2537
-
2538
- /* Used for treemap|heatmap.drawPoints */
2539
- function pointDrawHandler(proceed) {
2540
- if (!isSeriesBoosting(this)) {
2541
- return proceed.call(this);
2542
- }
2543
2619
 
2544
- //Make sure we have a valid OGL context
2545
- var renderer = createAndAttachRenderer(this.chart, this);
2546
-
2547
- if (renderer) {
2548
- allocateIfNotSeriesBoosting(renderer, this);
2549
- renderer.pushSeries(this);
2550
- }
2551
-
2552
- renderIfNotSeriesBoosting(renderer, this);
2553
- }
2620
+ seriesTypes.scatter.prototype.fill = true;
2554
2621
 
2555
- /*
2556
- * We need to handle heatmaps separatly, since we can't perform the size/color
2557
- * calculations in the shader easily.
2558
- *
2559
- * This likely needs future optimization.
2560
- *
2561
- */
2562
- each(['heatmap', 'treemap'],
2563
- function(t) {
2564
- if (seriesTypes[t]) {
2565
- wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler);
2566
- seriesTypes[t].prototype.directTouch = false; // Use k-d-tree
2567
- }
2568
- }
2569
- );
2622
+ extend(seriesTypes.area.prototype, {
2623
+ fill: true,
2624
+ fillOpacity: true,
2625
+ sampling: true
2626
+ });
2570
2627
 
2571
- if (seriesTypes.bubble) {
2572
- // By default, the bubble series does not use the KD-tree, so force it to.
2573
- delete seriesTypes.bubble.prototype.buildKDTree;
2574
- seriesTypes.bubble.prototype.directTouch = false;
2628
+ extend(seriesTypes.column.prototype, {
2629
+ fill: true,
2630
+ sampling: true
2631
+ });
2575
2632
 
2576
- // Needed for markers to work correctly
2577
- wrap(seriesTypes.bubble.prototype, 'markerAttribs', function(proceed) {
2578
- if (isSeriesBoosting(this)) {
2579
- return false;
2633
+ wrap(Series.prototype, 'setVisible', function(proceed, vis) {
2634
+ proceed.call(this, vis, false);
2635
+ if (this.visible === false && this.ogl && this.canvas && this.image) {
2636
+ this.ogl.clear();
2637
+ this.image.attr({
2638
+ href: ''
2639
+ });
2640
+ } else {
2641
+ this.chart.redraw();
2580
2642
  }
2581
- return proceed.apply(this, [].slice.call(arguments, 1));
2582
2643
  });
2583
- }
2584
2644
 
2585
- seriesTypes.scatter.prototype.fill = true;
2586
-
2587
- extend(seriesTypes.area.prototype, {
2588
- fill: true,
2589
- fillOpacity: true,
2590
- sampling: true
2591
- });
2592
-
2593
- extend(seriesTypes.column.prototype, {
2594
- fill: true,
2595
- sampling: true
2596
- });
2597
-
2598
- wrap(Series.prototype, 'setVisible', function(proceed, vis) {
2599
- proceed.call(this, vis, false);
2600
- if (this.visible === false && this.ogl && this.canvas && this.image) {
2601
- this.ogl.clear();
2602
- this.image.attr({
2603
- href: ''
2604
- });
2605
- } else {
2606
- this.chart.redraw();
2607
- }
2608
- });
2609
-
2610
- /**
2611
- * Take care of the canvas blitting
2612
- */
2613
- H.Chart.prototype.callbacks.push(function(chart) {
2645
+ /**
2646
+ * Take care of the canvas blitting
2647
+ */
2648
+ H.Chart.prototype.callbacks.push(function(chart) {
2614
2649
 
2615
- /* Convert chart-level canvas to image */
2616
- function canvasToSVG() {
2617
- if (chart.ogl && isChartSeriesBoosting(chart)) {
2618
- chart.ogl.render(chart);
2650
+ /* Convert chart-level canvas to image */
2651
+ function canvasToSVG() {
2652
+ if (chart.ogl && isChartSeriesBoosting(chart)) {
2653
+ chart.ogl.render(chart);
2654
+ }
2619
2655
  }
2620
- }
2621
2656
 
2622
- /* Clear chart-level canvas */
2623
- function preRender() {
2624
- if (chart.canvas && chart.ogl && isChartSeriesBoosting(chart)) {
2625
- // Allocate
2626
- chart.ogl.allocateBuffer(chart);
2627
- }
2657
+ /* Clear chart-level canvas */
2658
+ function preRender() {
2659
+ if (chart.canvas && chart.ogl && isChartSeriesBoosting(chart)) {
2660
+ // Allocate
2661
+ chart.ogl.allocateBuffer(chart);
2662
+ }
2628
2663
 
2629
- //see #6518
2630
- if (chart.markerGroup) {
2631
- chart.markerGroup.translate(
2632
- chart.xAxis[0].pos,
2633
- chart.yAxis[0].pos
2634
- );
2664
+ //see #6518
2665
+ if (chart.markerGroup) {
2666
+ chart.markerGroup.translate(
2667
+ chart.xAxis[0].pos,
2668
+ chart.yAxis[0].pos
2669
+ );
2670
+ }
2635
2671
  }
2636
- }
2637
2672
 
2638
- addEvent(chart, 'predraw', preRender);
2639
- addEvent(chart, 'render', canvasToSVG);
2640
- });
2673
+ addEvent(chart, 'predraw', preRender);
2674
+ addEvent(chart, 'render', canvasToSVG);
2675
+ });
2676
+ } // if hasCanvasSupport
2641
2677
 
2642
2678
  }(Highcharts));
2643
2679
  }));