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
  * Highcharts funnel module
4
4
  *
5
5
  * (c) 2010-2017 Torstein Honsi
@@ -28,6 +28,7 @@
28
28
  var seriesType = Highcharts.seriesType,
29
29
  seriesTypes = Highcharts.seriesTypes,
30
30
  noop = Highcharts.noop,
31
+ pick = Highcharts.pick,
31
32
  each = Highcharts.each;
32
33
 
33
34
 
@@ -115,8 +116,8 @@
115
116
  neckWidth :
116
117
  neckWidth + (width - neckWidth) * (1 - (y - top) / (height - neckHeight));
117
118
  };
118
- series.getX = function(y, half) {
119
- return centerX + (half ? -1 : 1) * ((getWidthAt(reversed ? 2 * centerY - y : y) / 2) + options.dataLabels.distance);
119
+ series.getX = function(y, half, point) {
120
+ return centerX + (half ? -1 : 1) * ((getWidthAt(reversed ? 2 * centerY - y : y) / 2) + point.labelDistance);
120
121
  };
121
122
 
122
123
  // Expose
@@ -250,8 +251,9 @@
250
251
  * Extend the pie data label method
251
252
  */
252
253
  drawDataLabels: function() {
253
- var data = this.data,
254
- labelDistance = this.options.dataLabels.distance,
254
+ var series = this,
255
+ data = series.data,
256
+ labelDistance = series.options.dataLabels.distance,
255
257
  leftSide,
256
258
  sign,
257
259
  point,
@@ -262,7 +264,7 @@
262
264
  // In the original pie label anticollision logic, the slots are distributed
263
265
  // from one labelDistance above to one labelDistance below the pie. In funnels
264
266
  // we don't want this.
265
- this.center[2] -= 2 * labelDistance;
267
+ series.center[2] -= 2 * labelDistance;
266
268
 
267
269
  // Set the label position array for each point.
268
270
  while (i--) {
@@ -270,15 +272,21 @@
270
272
  leftSide = point.half;
271
273
  sign = leftSide ? 1 : -1;
272
274
  y = point.plotY;
273
- x = this.getX(y, leftSide);
275
+ point.labelDistance = pick(
276
+ point.options.dataLabels && point.options.dataLabels.distance,
277
+ labelDistance
278
+ );
279
+
280
+ series.maxLabelDistance = Math.max(point.labelDistance, series.maxLabelDistance || 0);
281
+ x = series.getX(y, leftSide, point);
274
282
 
275
283
  // set the anchor point for data labels
276
284
  point.labelPos = [
277
285
  0, // first break of connector
278
286
  y, // a/a
279
- x + (labelDistance - 5) * sign, // second break, right outside point shape
287
+ x + (point.labelDistance - 5) * sign, // second break, right outside point shape
280
288
  y, // a/a
281
- x + labelDistance * sign, // landing point for connector
289
+ x + point.labelDistance * sign, // landing point for connector
282
290
  y, // a/a
283
291
  leftSide ? 'right' : 'left', // alignment
284
292
  0 // center angle
@@ -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
  * GridAxis
4
4
  *
5
5
  * (c) 2016 Lars A. V. Cabrera
@@ -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
  *
@@ -440,7 +440,7 @@
440
440
  // When updating data classes, destroy old items and make sure new ones are created (#3207)
441
441
  if (newOptions.dataClasses && legend.allItems) {
442
442
  each(legend.allItems, function(item) {
443
- if (item.isDataClass) {
443
+ if (item.isDataClass && item.legendGroup) {
444
444
  item.legendGroup.destroy();
445
445
  }
446
446
  });
@@ -458,6 +458,16 @@
458
458
  }
459
459
  },
460
460
 
461
+ /**
462
+ * Extend basic axis remove by also removing the legend item.
463
+ */
464
+ remove: function() {
465
+ if (this.legendItem) {
466
+ this.chart.legend.destroyItem(this);
467
+ }
468
+ Axis.prototype.remove.call(this);
469
+ },
470
+
461
471
  /**
462
472
  * Get the legend item symbols for data classes
463
473
  */
@@ -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
  * Plugin for displaying a message when there is no data visible in chart.
4
4
  *
5
5
  * (c) 2010-2017 Highsoft AS
@@ -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
  * Client side exporting module
4
4
  *
5
5
  * (c) 2015 Torstein Honsi / Oystein Moseng
@@ -109,7 +109,6 @@
109
109
  if (a.download !== undefined) {
110
110
  a.href = dataURL;
111
111
  a.download = filename; // HTML5 download attribute
112
- a.target = '_blank';
113
112
  doc.body.appendChild(a);
114
113
  a.click();
115
114
  doc.body.removeChild(a);
@@ -443,7 +442,16 @@
443
442
  };
444
443
 
445
444
  /**
446
- * Add a new method to the Chart object to perform a local download
445
+ * Exporting and offline-exporting modules required. Export a chart to an image
446
+ * locally in the user's browser.
447
+ *
448
+ * @param {Object} exportingOptions
449
+ * Exporting options, the same as in {@link
450
+ * Highcharts.Chart#exportChart}.
451
+ * @param {Options} chartOptions
452
+ * Additional chart options for the exported chart. For example a
453
+ * different background color can be added here, or `dataLabels`
454
+ * for export only.
447
455
  */
448
456
  Highcharts.Chart.prototype.exportChartLocal = function(exportingOptions, chartOptions) {
449
457
  var chart = this,
@@ -500,7 +508,7 @@
500
508
 
501
509
  // Extend the default options to use the local exporter logic
502
510
  merge(true, Highcharts.getOptions().exporting, {
503
- libURL: 'https://code.highcharts.com/5.0.10/lib/',
511
+ libURL: 'https://code.highcharts.com/5.0.11/lib/',
504
512
  buttons: {
505
513
  contextButton: {
506
514
  menuItems: [{
@@ -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
  *
@@ -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
  *
@@ -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
  * Solid angular gauge module
4
4
  *
5
5
  * (c) 2010-2017 Torstein Honsi
@@ -313,7 +313,7 @@
313
313
  }
314
314
  } else {
315
315
  point.graphic = renderer.arc(shapeArgs)
316
- .addClass('highcharts-point')
316
+ .addClass(point.getClassName(), true)
317
317
  .attr({
318
318
  fill: toColor,
319
319
  'sweep-flag': 0
@@ -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
  * Highstock as a plugin for Highcharts
4
4
  *
5
5
  * (c) 2017 Torstein Honsi
@@ -687,37 +687,6 @@
687
687
  }
688
688
  });
689
689
 
690
-
691
-
692
- /**
693
- * Extend getGraphPath by identifying gaps in the ordinal data so that we can draw a gap in the
694
- * line or area
695
- */
696
- Series.prototype.gappedPath = function() {
697
- var gapSize = this.options.gapSize,
698
- points = this.points.slice(),
699
- i = points.length - 1;
700
-
701
- if (gapSize && i > 0) { // #5008
702
-
703
- // extension for ordinal breaks
704
- while (i--) {
705
- if (points[i + 1].x - points[i].x > this.closestPointRange * gapSize) {
706
- points.splice( // insert after this one
707
- i + 1,
708
- 0, {
709
- isNull: true
710
- }
711
- );
712
- }
713
- }
714
- }
715
-
716
- // Call base method
717
- //return proceed.call(this, points, a, b);
718
- return this.getGraphPath(points);
719
- };
720
-
721
690
  /* ****************************************************************************
722
691
  * End ordinal axis logic *
723
692
  *****************************************************************************/
@@ -879,17 +848,14 @@
879
848
  length = 0,
880
849
  inBrk,
881
850
  repeat,
882
- brk,
883
851
  min = axis.userMin || axis.min,
884
852
  max = axis.userMax || axis.max,
885
853
  pointRangePadding = pick(axis.pointRangePadding, 0),
886
854
  start,
887
- i,
888
- j;
855
+ i;
889
856
 
890
857
  // Min & max check (#4247)
891
- for (i in breaks) {
892
- brk = breaks[i];
858
+ each(breaks, function(brk) {
893
859
  repeat = brk.repeat || Infinity;
894
860
  if (axis.isInBreak(brk, min)) {
895
861
  min += (brk.to % repeat) - (min % repeat);
@@ -897,11 +863,10 @@
897
863
  if (axis.isInBreak(brk, max)) {
898
864
  max -= (max % repeat) - (brk.from % repeat);
899
865
  }
900
- }
866
+ });
901
867
 
902
868
  // Construct an array holding all breaks in the axis
903
- for (i in breaks) {
904
- brk = breaks[i];
869
+ each(breaks, function(brk) {
905
870
  start = brk.from;
906
871
  repeat = brk.repeat || Infinity;
907
872
 
@@ -912,18 +877,18 @@
912
877
  start += repeat;
913
878
  }
914
879
 
915
- for (j = start; j < max; j += repeat) {
880
+ for (i = start; i < max; i += repeat) {
916
881
  breakArrayT.push({
917
- value: j,
882
+ value: i,
918
883
  move: 'in'
919
884
  });
920
885
  breakArrayT.push({
921
- value: j + (brk.to - brk.from),
886
+ value: i + (brk.to - brk.from),
922
887
  move: 'out',
923
888
  size: brk.breakSize
924
889
  });
925
890
  }
926
- }
891
+ });
927
892
 
928
893
  breakArrayT.sort(function(a, b) {
929
894
  var ret;
@@ -939,8 +904,7 @@
939
904
  inBrk = 0;
940
905
  start = min;
941
906
 
942
- for (i in breakArrayT) {
943
- brk = breakArrayT[i];
907
+ each(breakArrayT, function(brk) {
944
908
  inBrk += (brk.move === 'in' ? 1 : -1);
945
909
 
946
910
  if (inBrk === 1 && brk.move === 'in') {
@@ -954,7 +918,7 @@
954
918
  });
955
919
  length += brk.value - start - (brk.size || 0);
956
920
  }
957
- }
921
+ });
958
922
 
959
923
  axis.breakArray = breakArray;
960
924
 
@@ -966,7 +930,7 @@
966
930
 
967
931
  if (axis.options.staticScale) {
968
932
  axis.transA = axis.options.staticScale;
969
- } else {
933
+ } else if (axis.unitLength) {
970
934
  axis.transA *= (max - axis.min + pointRangePadding) /
971
935
  axis.unitLength;
972
936
  }
@@ -1053,6 +1017,36 @@
1053
1017
  });
1054
1018
  };
1055
1019
 
1020
+
1021
+ /**
1022
+ * Extend getGraphPath by identifying gaps in the data so that we can draw a gap
1023
+ * in the line or area. This was moved from ordinal axis module to broken axis
1024
+ * module as of #5045.
1025
+ */
1026
+ H.Series.prototype.gappedPath = function() {
1027
+ var gapSize = this.options.gapSize,
1028
+ points = this.points.slice(),
1029
+ i = points.length - 1;
1030
+
1031
+ if (gapSize && i > 0) { // #5008
1032
+
1033
+ // extension for ordinal breaks
1034
+ while (i--) {
1035
+ if (points[i + 1].x - points[i].x > this.closestPointRange * gapSize) {
1036
+ points.splice( // insert after this one
1037
+ i + 1,
1038
+ 0, {
1039
+ isNull: true
1040
+ }
1041
+ );
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+ // Call base method
1047
+ return this.getGraphPath(points);
1048
+ };
1049
+
1056
1050
  wrap(H.seriesTypes.column.prototype, 'drawPoints', drawPointsWrapped);
1057
1051
  wrap(H.Series.prototype, 'drawPoints', drawPointsWrapped);
1058
1052
 
@@ -1173,9 +1167,10 @@
1173
1167
 
1174
1168
 
1175
1169
  /**
1176
- * Define the available approximation types. The data grouping approximations takes an array
1177
- * or numbers as the first parameter. In case of ohlc, four arrays are sent in as four parameters.
1178
- * Each array consists only of numbers. In case null values belong to the group, the property
1170
+ * Define the available approximation types. The data grouping
1171
+ * approximations takes an array or numbers as the first parameter. In case
1172
+ * of ohlc, four arrays are sent in as four parameters. Each array consists
1173
+ * only of numbers. In case null values belong to the group, the property
1179
1174
  * .hasNulls will be set to true on the array.
1180
1175
  */
1181
1176
  approximations = {
@@ -1202,14 +1197,25 @@
1202
1197
  var len = arr.length,
1203
1198
  ret = approximations.sum(arr);
1204
1199
 
1205
- // If we have a number, return it divided by the length. If not, return
1206
- // null or undefined based on what the sum method finds.
1200
+ // If we have a number, return it divided by the length. If not,
1201
+ // return null or undefined based on what the sum method finds.
1207
1202
  if (isNumber(ret) && len) {
1208
1203
  ret = ret / len;
1209
1204
  }
1210
1205
 
1211
1206
  return ret;
1212
1207
  },
1208
+ // The same as average, but for series with multiple values, like area
1209
+ // ranges.
1210
+ averages: function() { // #5479
1211
+ var ret = [];
1212
+
1213
+ each(arguments, function(arr) {
1214
+ ret.push(approximations.average(arr));
1215
+ });
1216
+
1217
+ return ret;
1218
+ },
1213
1219
  open: function(arr) {
1214
1220
  return arr.length ? arr[0] : (arr.hasNulls ? null : undefined);
1215
1221
  },
@@ -1247,8 +1253,8 @@
1247
1253
 
1248
1254
 
1249
1255
  /**
1250
- * Takes parallel arrays of x and y data and groups the data into intervals defined by groupPositions, a collection
1251
- * of starting x values for each group.
1256
+ * Takes parallel arrays of x and y data and groups the data into intervals
1257
+ * defined by groupPositions, a collection of starting x values for each group.
1252
1258
  */
1253
1259
  seriesProto.groupData = function(xData, yData, groupPositions, approximation) {
1254
1260
  var series = this,
@@ -1261,19 +1267,35 @@
1261
1267
  pointX,
1262
1268
  pointY,
1263
1269
  groupedY,
1264
- handleYData = !!yData, // when grouping the fake extended axis for panning, we don't need to consider y
1265
- values = [
1266
- [],
1267
- [],
1268
- [],
1269
- []
1270
- ],
1271
- approximationFn = typeof approximation === 'function' ? approximation : approximations[approximation],
1270
+ // when grouping the fake extended axis for panning,
1271
+ // we don't need to consider y
1272
+ handleYData = !!yData,
1273
+ values = [],
1274
+ approximationFn = typeof approximation === 'function' ?
1275
+ approximation :
1276
+ approximations[approximation] ||
1277
+ // if the approximation is not found use default series type
1278
+ // approximation (#2914)
1279
+ (
1280
+ specificOptions[series.type] &&
1281
+ approximations[specificOptions[series.type].approximation]
1282
+ ) || approximations[commonOptions.approximation],
1272
1283
  pointArrayMap = series.pointArrayMap,
1273
1284
  pointArrayMapLength = pointArrayMap && pointArrayMap.length,
1274
- i,
1275
1285
  pos = 0,
1276
- start = 0;
1286
+ start = 0,
1287
+ valuesLen,
1288
+ i, j;
1289
+
1290
+ // Calculate values array size from pointArrayMap length
1291
+ if (pointArrayMapLength) {
1292
+ each(pointArrayMap, function() {
1293
+ values.push([]);
1294
+ });
1295
+ } else {
1296
+ values.push([]);
1297
+ }
1298
+ valuesLen = pointArrayMapLength || 1;
1277
1299
 
1278
1300
  // Start with the first point within the X axis range (#2696)
1279
1301
  for (i = 0; i <= dataLength; i++) {
@@ -1284,9 +1306,12 @@
1284
1306
 
1285
1307
  for (i; i <= dataLength; i++) {
1286
1308
 
1287
- // when a new group is entered, summarize and initiate the previous group
1288
- while ((groupPositions[pos + 1] !== undefined && xData[i] >= groupPositions[pos + 1]) ||
1289
- i === dataLength) { // get the last group
1309
+ // when a new group is entered, summarize and initiate
1310
+ // the previous group
1311
+ while ((
1312
+ groupPositions[pos + 1] !== undefined &&
1313
+ xData[i] >= groupPositions[pos + 1]
1314
+ ) || i === dataLength) { // get the last group
1290
1315
 
1291
1316
  // get group x and y
1292
1317
  pointX = groupPositions[pos];
@@ -1305,10 +1330,10 @@
1305
1330
 
1306
1331
  // reset the aggregate arrays
1307
1332
  start = i;
1308
- values[0] = [];
1309
- values[1] = [];
1310
- values[2] = [];
1311
- values[3] = [];
1333
+ for (j = 0; j < valuesLen; j++) {
1334
+ values[j].length = 0; // faster than values[j] = []
1335
+ values[j].hasNulls = false;
1336
+ }
1312
1337
 
1313
1338
  // Advance on the group positions
1314
1339
  pos += 1;
@@ -1324,14 +1349,15 @@
1324
1349
  break;
1325
1350
  }
1326
1351
 
1327
- // for each raw data point, push it to an array that contains all values for this specific group
1352
+ // for each raw data point, push it to an array that contains all values
1353
+ // for this specific group
1328
1354
  if (pointArrayMap) {
1329
1355
 
1330
1356
  var index = series.cropStart + i,
1331
- point = (data && data[index]) || series.pointClass.prototype.applyOptions.apply({
1357
+ point = (data && data[index]) ||
1358
+ series.pointClass.prototype.applyOptions.apply({
1332
1359
  series: series
1333
1360
  }, [dataOptions[index]]),
1334
- j,
1335
1361
  val;
1336
1362
 
1337
1363
  for (j = 0; j < pointArrayMapLength; j++) {
@@ -1738,7 +1764,7 @@
1738
1764
  toYData: function(point) { // return a plain array for speedy calculation
1739
1765
  return [point.open, point.high, point.low, point.close];
1740
1766
  },
1741
- pointValKey: 'high',
1767
+ pointValKey: 'close',
1742
1768
 
1743
1769
 
1744
1770
  pointAttrToOptions: {
@@ -1791,6 +1817,10 @@
1791
1817
  point[translated[i]] = yAxis.toPixels(value, true);
1792
1818
  }
1793
1819
  });
1820
+
1821
+ // Align the tooltip to the high value to avoid covering the point
1822
+ point.tooltipPos[1] =
1823
+ point.plotHigh + yAxis.pos - series.chart.plotTop;
1794
1824
  });
1795
1825
  },
1796
1826
 
@@ -1835,7 +1865,7 @@
1835
1865
  'M',
1836
1866
  crispX, Math.round(point.yBottom),
1837
1867
  'L',
1838
- crispX, Math.round(point.plotY)
1868
+ crispX, Math.round(point.plotHigh)
1839
1869
  ];
1840
1870
 
1841
1871
  // open
@@ -2005,7 +2035,7 @@
2005
2035
  topBox = Math.min(plotOpen, plotClose);
2006
2036
  bottomBox = Math.max(plotOpen, plotClose);
2007
2037
  halfWidth = Math.round(point.shapeArgs.width / 2);
2008
- hasTopWhisker = Math.round(topBox) !== Math.round(point.plotY);
2038
+ hasTopWhisker = Math.round(topBox) !== Math.round(point.plotHigh);
2009
2039
  hasBottomWhisker = bottomBox !== point.yBottom;
2010
2040
  topBox = Math.round(topBox) + crispCorr;
2011
2041
  bottomBox = Math.round(bottomBox) + crispCorr;
@@ -2028,7 +2058,7 @@
2028
2058
  'M',
2029
2059
  crispX, topBox,
2030
2060
  'L',
2031
- crispX, hasTopWhisker ? Math.round(point.plotY) : topBox, // #460, #2094
2061
+ crispX, hasTopWhisker ? Math.round(point.plotHigh) : topBox, // #460, #2094
2032
2062
  'M',
2033
2063
  crispX, bottomBox,
2034
2064
  'L',
@@ -3052,7 +3082,7 @@
3052
3082
  each(this._events, function(args) {
3053
3083
  removeEvent.apply(null, args);
3054
3084
  });
3055
- this._events = undefined;
3085
+ this._events.length = 0;
3056
3086
  },
3057
3087
 
3058
3088
  /**
@@ -3124,6 +3154,7 @@
3124
3154
  scrollMin = Math.min(pick(axis.options.min, axis.min), axis.min, axis.dataMin),
3125
3155
  scrollMax = Math.max(pick(axis.options.max, axis.max), axis.max, axis.dataMax),
3126
3156
  scrollbar = axis.scrollbar,
3157
+ titleOffset = axis.titleOffset || 0,
3127
3158
  offsetsIndex,
3128
3159
  from,
3129
3160
  to;
@@ -3136,7 +3167,10 @@
3136
3167
  scrollbar.position(
3137
3168
  axis.left,
3138
3169
  axis.top + axis.height + 2 + axis.chart.scrollbarsOffsets[1] +
3139
- (axis.opposite ? 0 : axis.axisTitleMargin + axis.offset),
3170
+ (axis.opposite ?
3171
+ 0 :
3172
+ titleOffset + axis.axisTitleMargin + axis.offset
3173
+ ),
3140
3174
  axis.width,
3141
3175
  axis.height
3142
3176
  );
@@ -3144,7 +3178,10 @@
3144
3178
  } else {
3145
3179
  scrollbar.position(
3146
3180
  axis.left + axis.width + 2 + axis.chart.scrollbarsOffsets[0] +
3147
- (axis.opposite ? axis.axisTitleMargin + axis.offset : 0),
3181
+ (axis.opposite ?
3182
+ titleOffset + axis.axisTitleMargin + axis.offset :
3183
+ 0
3184
+ ),
3148
3185
  axis.top,
3149
3186
  axis.width,
3150
3187
  axis.height
@@ -3645,6 +3682,7 @@
3645
3682
  scrollbarHeight = navigator.scrollbarHeight,
3646
3683
  navigatorSize,
3647
3684
  xAxis = navigator.xAxis,
3685
+ scrollbarXAxis = xAxis.fake ? chart.xAxis[0] : xAxis,
3648
3686
  navigatorEnabled = navigator.navigatorEnabled,
3649
3687
  zoomedMin,
3650
3688
  zoomedMax,
@@ -3745,7 +3783,9 @@
3745
3783
  if (inverted) {
3746
3784
  scrollbarTop = navigator.top - scrollbarHeight;
3747
3785
  scrollbarLeft = navigator.left - scrollbarHeight +
3748
- (navigatorEnabled ? 0 : navigator.height);
3786
+ (navigatorEnabled ? 0 : (scrollbarXAxis.titleOffset || 0) +
3787
+ scrollbarXAxis.axisTitleMargin
3788
+ );
3749
3789
  scrollbarHeight = navigatorSize + 2 * scrollbarHeight;
3750
3790
  } else {
3751
3791
  scrollbarTop = navigator.top +
@@ -5522,15 +5562,15 @@
5522
5562
  * Destroys allocated elements.
5523
5563
  */
5524
5564
  destroy: function() {
5525
- var minInput = this.minInput,
5526
- maxInput = this.maxInput,
5527
- key;
5565
+ var rSelector = this,
5566
+ minInput = rSelector.minInput,
5567
+ maxInput = rSelector.maxInput;
5528
5568
 
5529
- this.unMouseDown();
5530
- this.unResize();
5569
+ rSelector.unMouseDown();
5570
+ rSelector.unResize();
5531
5571
 
5532
5572
  // Destroy elements in collections
5533
- destroyObjectProperties(this.buttons);
5573
+ destroyObjectProperties(rSelector.buttons);
5534
5574
 
5535
5575
  // Clear input element events
5536
5576
  if (minInput) {
@@ -5541,18 +5581,18 @@
5541
5581
  }
5542
5582
 
5543
5583
  // Destroy HTML and SVG elements
5544
- for (key in this) {
5545
- if (this[key] && key !== 'chart') {
5546
- if (this[key].destroy) { // SVGElement
5547
- this[key].destroy();
5548
- } else if (this[key].nodeType) { // HTML element
5584
+ H.objectEach(rSelector, function(val, key) {
5585
+ if (val && key !== 'chart') {
5586
+ if (val.destroy) { // SVGElement
5587
+ val.destroy();
5588
+ } else if (val.nodeType) { // HTML element
5549
5589
  discardElement(this[key]);
5550
5590
  }
5551
5591
  }
5552
- if (this[key] !== RangeSelector.prototype[key]) {
5553
- this[key] = null;
5592
+ if (val !== RangeSelector.prototype[key]) {
5593
+ rSelector[key] = null;
5554
5594
  }
5555
- }
5595
+ }, this);
5556
5596
  }
5557
5597
  };
5558
5598
 
@@ -5606,8 +5646,15 @@
5606
5646
  range,
5607
5647
  // Get the true range from a start date
5608
5648
  getTrueRange = function(base, count) {
5609
- var date = new Date(base);
5610
- date['set' + timeName](date['get' + timeName]() + count);
5649
+ var date = new Date(base),
5650
+ basePeriod = date['get' + timeName]();
5651
+
5652
+ date['set' + timeName](basePeriod + count);
5653
+
5654
+ if (basePeriod === date['get' + timeName]()) {
5655
+ date.setDate(0); // #6537
5656
+ }
5657
+
5611
5658
  return date.getTime() - base;
5612
5659
  };
5613
5660
 
@@ -5715,6 +5762,7 @@
5715
5762
  each = H.each,
5716
5763
  extend = H.extend,
5717
5764
  format = H.format,
5765
+ grep = H.grep,
5718
5766
  inArray = H.inArray,
5719
5767
  isNumber = H.isNumber,
5720
5768
  isString = H.isString,
@@ -5973,7 +6021,13 @@
5973
6021
  // lines (#2796).
5974
6022
  uniqueAxes = axes.length ? [] : [axis.isXAxis ? chart.yAxis[0] : chart.xAxis[0]]; //#3742
5975
6023
  each(axes, function(axis2) {
5976
- if (inArray(axis2, uniqueAxes) === -1) {
6024
+ if (
6025
+ inArray(axis2, uniqueAxes) === -1 &&
6026
+ // Do not draw on axis which overlap completely. #5424
6027
+ !H.find(uniqueAxes, function(unique) {
6028
+ return unique.pos === axis2.pos && unique.len && axis2.len;
6029
+ })
6030
+ ) {
5977
6031
  uniqueAxes.push(axis2);
5978
6032
  }
5979
6033
  });
@@ -6320,7 +6374,7 @@
6320
6374
 
6321
6375
  // find the first value for comparison
6322
6376
  for (i = 0; i < length - 1; i++) {
6323
- compareValue = keyIndex > -1 ?
6377
+ compareValue = processedYData[i] && keyIndex > -1 ?
6324
6378
  processedYData[i][keyIndex] :
6325
6379
  processedYData[i];
6326
6380
  if (isNumber(compareValue) && processedXData[i + 1] >= series.xAxis.min && compareValue !== 0) {
@@ -6416,5 +6470,32 @@
6416
6470
  proceed.call(this);
6417
6471
  });
6418
6472
 
6473
+ wrap(Chart.prototype, 'getSelectedPoints', function(proceed) {
6474
+ var points = proceed.call(this);
6475
+
6476
+ each(this.series, function(serie) {
6477
+ // series.points - for grouped points (#6445)
6478
+ if (serie.hasGroupedData) {
6479
+ points = points.concat(grep(serie.points || [], function(point) {
6480
+ return point.selected;
6481
+ }));
6482
+ }
6483
+ });
6484
+ return points;
6485
+ });
6486
+
6487
+ wrap(Chart.prototype, 'update', function(proceed, options) {
6488
+ // Use case: enabling scrollbar from a disabled state.
6489
+ // Scrollbar needs to be initialized from a controller, Navigator in this
6490
+ // case (#6615)
6491
+ if ('scrollbar' in options && this.navigator) {
6492
+ merge(true, this.options.scrollbar, options.scrollbar);
6493
+ this.navigator.update({}, false);
6494
+ delete options.scrollbar;
6495
+ }
6496
+
6497
+ return proceed.apply(this, Array.prototype.slice.call(arguments, 1));
6498
+ });
6499
+
6419
6500
  }(Highcharts));
6420
6501
  }));