highcharts-rails 4.2.6 → 4.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f77a535a0b707c51c4f72e52ddf05fe4e3b911c3
4
- data.tar.gz: 6c75ffb6a157954665f1abd492d403529a3b557e
3
+ metadata.gz: 6c8a7e896fdcd7def1e83f3bcb1feb6872433807
4
+ data.tar.gz: b537b34e4eb511cc9990cf2849b906b5728ba8d1
5
5
  SHA512:
6
- metadata.gz: af2b1ec95756ae60312e86e5b7bbbfd3af55d35e9df0b0a910bfd7e8499d4304e859c7da71f8d2fe2ad7b951c3b28405cb5a31bed565485578050f7294d4dabb
7
- data.tar.gz: 76c61a2be05c827cf727b7ad23c99672f75d267646c977fc8f441365c6b6489d46d261001424be87d44e7a3e38155c1c7597bf466eff706b925a384bba00ae9b
6
+ metadata.gz: 42aed7fd6c6bd1bb90b4978307e5c2c025f4ede7fd283b09c12caf5313ec2d3741a8cd219c2541a5c38d91f9a3c43a4c23c9fa92b54a73c1ee86e4b14dd81bdc
7
+ data.tar.gz: 3642d9b1dc37b3f36a99972683ec45315091a1cc13db9487efdd435b0cfb25a02f9200142e14160b4564a6d14b9620e93a5856a3542a7698c3d43be9722b3b26
@@ -1,3 +1,49 @@
1
+ # 4.2.7 / 2017-01-25
2
+
3
+ * Updated Highcharts to 4.2.7 (2016-09-21)
4
+ * Added new feature, yAxis.angle, allowing positioning the axis line and labels in polar chart Y axes. This makes it practical to use multiple axes in polar charts.
5
+ * Added option, xAxis.nameToX, allowing points to have the same name but different axis positions on an axis of type category.
6
+ * Bug fixes
7
+ * Fixed #1011, ignoreHiddenSeries with ordinal axis caused artefacts on a chart.
8
+ * Fixed #1041, gaps in the area fill of stacked areasplines.
9
+ * Fixed #3169, error on drilldown from a null point.
10
+ * Fixed #3341, exceeded stack size on mutually linked series.
11
+ * Fixed #3571, NaN in the beginning of data broke series.
12
+ * Fixed #4778, wrong rendering waterfall series, when yAxis.max was set.
13
+ * Fixed #5186, gaps in the fill of areasplinerange.
14
+ * Fixed #5383, mouse position detection with pointPlacement.
15
+ * Fixed #5528, a regression causing polar arearanges to fail.
16
+ * Fixed #5533, stickyTracking when set to false caused highlighting wrong point.
17
+ * Fixed #5552, linejoins in boost module lines.
18
+ * Fixed #5556, JS error on polygon with empty data.
19
+ * Fixed #5563, JS error in treemap with zero values.
20
+ * Fixed #5568, pointIntervalUnit broke when using more data points than turboThreshold.
21
+ * Fixed #5569, generic options set on the yAxis affected the colorAxis.
22
+ * Fixed #5570 and #5590, regression causing blank export on Batik based export servers.
23
+ * Fixed #5572, pie slices were not hidden in 3D pie charts on legend click.
24
+ * Fixed #5595, HTML tooltip did not hide on point mouse out via the tooltip.
25
+ * Fixed #5605, error on async onload of destroyed chart.
26
+ * Fixed #5618, updating master series caused wrong visibility on linked series.
27
+ * Fixed #5619, the Series remove event was fired when updating a series.
28
+ * Fixed #5620, text was mispositioned when loading a chart in a hidden iframe in certain browsers.
29
+ * Fixed #5622, click event for line series point was not called when column was rendered below.
30
+ * Fixed #5631, zeroes in logarithmic chart made the whole graph crash.
31
+ * Fixed #5632, gaps were broken in arearange and areasplinerange.
32
+ * Fixed #5646, waterfall did not work correctly with logarithmic axis.
33
+ * Fixed #5647, xrange points disappeared if x was outside plot but x2 inside.
34
+ * Fixed #5647, xrange points disappeared when x was outside visible range.
35
+ * Fixed #5655, animation: true on a series config caused animation to jump from the middle.
36
+ * Fixed #5658, error on updating series from its own mouseOver event.
37
+ * Fixed #5662, setExtremes on polar chart caused padded max value.
38
+ * Fixed #5665, addPoint animation parameter was not used.
39
+ * Fixed #5679, handle isArray for ES6 iterator.
40
+ * Fixed #5681, JS error on adding custom group to points.
41
+ * Fixed #5689, text had soft line wraps when white-space: nowrap was used in combination with text-overflow: ellipsis.
42
+ * Fixed issue #4133, error bar data labels positions failing on redraw.
43
+ * Fixed issue #5205, color axis changed colors when legend was disabled.
44
+ * Fixed issue #5567, wrong clipping of offline exported SVG in IE11/Edge.
45
+ * Fixed wrong handling of minRange on logarithmic axis, related to #1227.
46
+
1
47
  # 4.2.6 / 2017-01-25
2
48
 
3
49
  * Updated Highcharts to 4.2.6 (2016-08-02)
data/Rakefile CHANGED
@@ -26,6 +26,7 @@ task :update, :version do |t, args|
26
26
  "broken-axis.src.js" => "highcharts/modules/broken-axis.js",
27
27
  "boost.src.js" => "highcharts/modules/boost.js",
28
28
  "offline-exporting.src.js" => "highcharts/modules/offline-exporting.js",
29
+ "series-label.src.js" => "highcharts/modules/series-label.js",
29
30
  }
30
31
  dest = "app/assets/javascripts/"
31
32
  Dir.glob("tmp/#{version}/js/**/*.src.js").each do |file|
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v4.2.6 (2016-08-02)
5
+ * @license Highcharts JS v4.2.7 (2016-09-21)
6
6
  *
7
7
  * (c) 2009-2016 Torstein Honsi
8
8
  *
@@ -59,7 +59,7 @@
59
59
  charts = [],
60
60
  chartCount = 0,
61
61
  PRODUCT = 'Highcharts',
62
- VERSION = '4.2.6',
62
+ VERSION = '4.2.7',
63
63
 
64
64
  // some constants for frequently used strings
65
65
  DIV = 'div',
@@ -72,7 +72,7 @@
72
72
  NONE = 'none',
73
73
  M = 'M',
74
74
  L = 'L',
75
- numRegex = /^[0-9]+$/,
75
+ numRegex = /[0-9]/g,
76
76
  NORMAL_STATE = '',
77
77
  HOVER_STATE = 'hover',
78
78
  SELECT_STATE = 'select',
@@ -481,7 +481,7 @@
481
481
  value = original[key];
482
482
 
483
483
  // Copy the contents of objects, but not arrays or DOM nodes
484
- if (value && typeof value === 'object' && Object.prototype.toString.call(value) !== '[object Array]' &&
484
+ if (Highcharts.isObject(value, true) &&
485
485
  key !== 'renderTo' && typeof value.nodeType !== 'number') {
486
486
  copy[key] = doCopy(copy[key] || {}, value);
487
487
 
@@ -531,7 +531,8 @@
531
531
  * @param {Object} obj
532
532
  */
533
533
  function isArray(obj) {
534
- return Object.prototype.toString.call(obj) === '[object Array]';
534
+ var str = Object.prototype.toString.call(obj);
535
+ return str === '[object Array]' || str === '[object Array Iterator]';
535
536
  }
536
537
 
537
538
  /**
@@ -1601,7 +1602,7 @@
1601
1602
  useUTC: true,
1602
1603
  //timezoneOffset: 0,
1603
1604
  canvasToolsURL: 'http://code.highcharts.com/modules/canvas-tools.js',
1604
- VMLRadialGradientURL: 'http://code.highcharts.com/4.2.6/gfx/vml-radial-gradient.png'
1605
+ VMLRadialGradientURL: 'http://code.highcharts.com/4.2.7/gfx/vml-radial-gradient.png'
1605
1606
  },
1606
1607
  chart: {
1607
1608
  //animation: true,
@@ -2871,19 +2872,16 @@
2871
2872
 
2872
2873
  if (textStr !== UNDEFINED) {
2873
2874
 
2874
- // Properties that affect bounding box
2875
- cacheKey = ['', rotation || 0, styles && styles.fontSize, element.style.width].join(',');
2875
+ cacheKey =
2876
2876
 
2877
- // Since numbers are monospaced, and numerical labels appear a lot in a chart,
2878
- // we assume that a label of n characters has the same bounding box as others
2879
- // of the same length.
2880
- if (textStr === '' || numRegex.test(textStr)) {
2881
- cacheKey = 'num:' + textStr.toString().length + cacheKey;
2877
+ // Since numbers are monospaced, and numerical labels appear a lot in a chart,
2878
+ // we assume that a label of n characters has the same bounding box as others
2879
+ // of the same length.
2880
+ textStr.toString().replace(numRegex, '0') +
2881
+
2882
+ // Properties that affect bounding box
2883
+ ['', rotation || 0, styles && styles.fontSize, element.style.width].join(',');
2882
2884
 
2883
- // Caching all strings reduces rendering time by 4-5%.
2884
- } else {
2885
- cacheKey = textStr + cacheKey;
2886
- }
2887
2885
  }
2888
2886
 
2889
2887
  if (cacheKey && !reload) {
@@ -2963,8 +2961,9 @@
2963
2961
  }
2964
2962
  }
2965
2963
 
2966
- // Cache it
2967
- if (cacheKey) {
2964
+ // Cache it. When loading a chart in a hidden iframe in Firefox and IE/Edge, the
2965
+ // bounding box height is 0, so don't cache it (#5620).
2966
+ if (cacheKey && bBox.height > 0) {
2968
2967
 
2969
2968
  // Rotate (#4681)
2970
2969
  while (cacheKeys.length > 250) {
@@ -3240,10 +3239,6 @@
3240
3239
  alignSetter: function (value) {
3241
3240
  this.element.setAttribute('text-anchor', { left: 'start', center: 'middle', right: 'end' }[value]);
3242
3241
  },
3243
- opacitySetter: function (value, key, element) {
3244
- this[key] = value;
3245
- element.setAttribute(key, value);
3246
- },
3247
3242
  titleSetter: function (value) {
3248
3243
  var titleNode = this.element.getElementsByTagName('title')[0];
3249
3244
  if (!titleNode) {
@@ -3355,6 +3350,13 @@
3355
3350
  this.doTransform = true;
3356
3351
  };
3357
3352
 
3353
+ // These setters both set the key on the instance itself plus as an attribute
3354
+ SVGElement.prototype.opacitySetter = SVGElement.prototype.displaySetter = function (value, key, element) {
3355
+ this[key] = value;
3356
+ element.setAttribute(key, value);
3357
+ };
3358
+
3359
+
3358
3360
  // WebKit and Batik have problems with a stroke-width of zero, so in this case we remove the
3359
3361
  // stroke attribute altogether. #1270, #1369, #3065, #3072.
3360
3362
  SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter = function (value, key, element) {
@@ -3380,7 +3382,6 @@
3380
3382
  };
3381
3383
  SVGRenderer.prototype = {
3382
3384
  Element: SVGElement,
3383
-
3384
3385
  /**
3385
3386
  * Initialize the SVGRenderer
3386
3387
  * @param {Object} container
@@ -3683,7 +3684,8 @@
3683
3684
  // Check width and apply soft breaks or ellipsis
3684
3685
  if (width) {
3685
3686
  var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
3686
- hasWhiteSpace = spans.length > 1 || lineNo || (words.length > 1 && textStyles.whiteSpace !== 'nowrap'),
3687
+ noWrap = textStyles.whiteSpace === 'nowrap',
3688
+ hasWhiteSpace = spans.length > 1 || lineNo || (words.length > 1 && !noWrap),
3687
3689
  tooLong,
3688
3690
  actualWidth,
3689
3691
  rest = [],
@@ -3727,7 +3729,7 @@
3727
3729
  words = rest;
3728
3730
  rest = [];
3729
3731
 
3730
- if (words.length) {
3732
+ if (words.length && !noWrap) {
3731
3733
  softLineNo++;
3732
3734
 
3733
3735
  tspan = doc.createElementNS(SVG_NS, 'tspan');
@@ -4158,7 +4160,6 @@
4158
4160
  height,
4159
4161
  options
4160
4162
  ),
4161
-
4162
4163
  imageRegex = /^url\((.*?)\)$/,
4163
4164
  imageSrc,
4164
4165
  imageSize,
@@ -4222,6 +4223,8 @@
4222
4223
  createElement('img', {
4223
4224
  onload: function () {
4224
4225
 
4226
+ var chart = charts[ren.chartIndex];
4227
+
4225
4228
  // Special case for SVGs on IE11, the width is not accessible until the image is
4226
4229
  // part of the DOM (#2854).
4227
4230
  if (this.width === 0) {
@@ -4242,8 +4245,8 @@
4242
4245
 
4243
4246
  // Fire the load event when all external images are loaded
4244
4247
  ren.imgCount--;
4245
- if (!ren.imgCount && charts[ren.chartIndex].onload) {
4246
- charts[ren.chartIndex].onload();
4248
+ if (!ren.imgCount && chart && chart.onload) {
4249
+ chart.onload();
4247
4250
  }
4248
4251
  },
4249
4252
  src: imageSrc
@@ -4564,7 +4567,8 @@
4564
4567
  crispAdjust = 0,
4565
4568
  deferredAttr = {},
4566
4569
  baselineOffset,
4567
- needsBox,
4570
+ hasBGImage = /^url\((.*?)\)$/.test(shape),
4571
+ needsBox = hasBGImage,
4568
4572
  updateBoxSize,
4569
4573
  updateTextPadding,
4570
4574
  boxAttr;
@@ -4594,7 +4598,7 @@
4594
4598
  // create the border box if it is not already present
4595
4599
  boxX = crispAdjust;
4596
4600
  boxY = (baseline ? -baselineOffset : 0) + crispAdjust;
4597
- wrapper.box = box = renderer.symbols[shape] ? // Symbol definition exists (#5324)
4601
+ wrapper.box = box = renderer.symbols[shape] || hasBGImage ? // Symbol definition exists (#5324)
4598
4602
  renderer.symbol(shape, boxX, boxY, wrapper.width, wrapper.height, deferredAttr) :
4599
4603
  renderer.rect(boxX, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);
4600
4604
 
@@ -5016,7 +5020,7 @@
5016
5020
  addSetters = function (element, style) {
5017
5021
  // These properties are set as attributes on the SVG group, and as
5018
5022
  // identical CSS properties on the div. (#3542)
5019
- each(['opacity', 'visibility'], function (prop) {
5023
+ each(['display', 'opacity', 'visibility'], function (prop) {
5020
5024
  wrap(element, prop + 'Setter', function (proceed, value, key, elem) {
5021
5025
  proceed.call(this, value, key, elem);
5022
5026
  style[key] = value;
@@ -5107,7 +5111,9 @@
5107
5111
  position: ABSOLUTE,
5108
5112
  left: (parentGroup.translateX || 0) + PX,
5109
5113
  top: (parentGroup.translateY || 0) + PX,
5110
- opacity: parentGroup.opacity // #5075
5114
+ display: parentGroup.display,
5115
+ opacity: parentGroup.opacity, // #5075
5116
+ pointerEvents: parentGroup.styles && parentGroup.styles.pointerEvents // #5595
5111
5117
  }, htmlGroup || container); // the top group is appended to container
5112
5118
 
5113
5119
  // Shortcut
@@ -5619,6 +5625,9 @@
5619
5625
  }
5620
5626
  element.style[key] = value;
5621
5627
  },
5628
+ displaySetter: function (value, key, element) {
5629
+ element.style[key] = value;
5630
+ },
5622
5631
  xSetter: function (value, key, element) {
5623
5632
  this[key] = value; // used in getter
5624
5633
 
@@ -7174,7 +7183,7 @@
7174
7183
 
7175
7184
  // Flag, isXAxis
7176
7185
  axis.isXAxis = isXAxis;
7177
- axis.coll = isXAxis ? 'xAxis' : 'yAxis';
7186
+ axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis');
7178
7187
 
7179
7188
  axis.opposite = userOptions.opposite; // needed in setOptions
7180
7189
  axis.side = userOptions.side || (axis.horiz ?
@@ -7202,7 +7211,8 @@
7202
7211
  axis.zoomEnabled = options.zoomEnabled !== false;
7203
7212
 
7204
7213
  // Initial categories
7205
- axis.categories = options.categories || type === 'category';
7214
+ axis.hasNames = type === 'category' || options.categories === true;
7215
+ axis.categories = options.categories || axis.hasNames;
7206
7216
  axis.names = axis.names || []; // Preserve on update (#3830)
7207
7217
 
7208
7218
  // Elements
@@ -7286,7 +7296,7 @@
7286
7296
 
7287
7297
  // Register
7288
7298
  if (inArray(axis, chart.axes) === -1) { // don't add it again on Axis.update()
7289
- if (isXAxis && !this.isColorAxis) { // #2713
7299
+ if (isXAxis) { // #2713
7290
7300
  chart.axes.splice(chart.xAxis.length, 0, axis);
7291
7301
  } else {
7292
7302
  chart.axes.push(axis);
@@ -7324,7 +7334,7 @@
7324
7334
  setOptions: function (userOptions) {
7325
7335
  this.options = merge(
7326
7336
  this.defaultOptions,
7327
- this.isXAxis ? {} : this.defaultYAxisOptions,
7337
+ this.coll === 'yAxis' && this.defaultYAxisOptions,
7328
7338
  [this.defaultTopAxisOptions, this.defaultRightAxisOptions,
7329
7339
  this.defaultBottomAxisOptions, this.defaultLeftAxisOptions][this.side],
7330
7340
  merge(
@@ -7740,13 +7750,13 @@
7740
7750
  // if min and max options have been set, don't go beyond it
7741
7751
  minArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)];
7742
7752
  if (spaceAvailable) { // if space is available, stay within the data range
7743
- minArgs[2] = axis.dataMin;
7753
+ minArgs[2] = axis.isLog ? axis.log2lin(axis.dataMin) : axis.dataMin;
7744
7754
  }
7745
7755
  min = arrayMax(minArgs);
7746
7756
 
7747
7757
  maxArgs = [min + minRange, pick(options.max, min + minRange)];
7748
7758
  if (spaceAvailable) { // if space is availabe, stay within the data range
7749
- maxArgs[2] = axis.dataMax;
7759
+ maxArgs[2] = axis.isLog ? axis.log2lin(axis.dataMax) : axis.dataMax;
7750
7760
  }
7751
7761
 
7752
7762
  max = arrayMin(maxArgs);
@@ -7785,6 +7795,68 @@
7785
7795
  return ret;
7786
7796
  },
7787
7797
 
7798
+ /**
7799
+ * When a point name is given and no x, search for the name in the existing categories,
7800
+ * or if categories aren't provided, search names or create a new category (#2522).
7801
+ */
7802
+ nameToX: function (point) {
7803
+ var explicitCategories = isArray(this.categories),
7804
+ names = explicitCategories ? this.categories : this.names,
7805
+ nameX = point.options.x,
7806
+ x;
7807
+
7808
+ point.series.requireSorting = false;
7809
+
7810
+ if (!defined(nameX)) {
7811
+ nameX = this.options.nameToX === false ?
7812
+ point.series.autoIncrement() :
7813
+ inArray(point.name, names);
7814
+ }
7815
+ if (nameX === -1) { // The name is not found in currenct categories
7816
+ if (!explicitCategories) {
7817
+ x = names.length;
7818
+ }
7819
+ } else {
7820
+ x = nameX;
7821
+ }
7822
+
7823
+ // Write the last point's name to the names array
7824
+ this.names[x] = point.name;
7825
+
7826
+ return x;
7827
+ },
7828
+
7829
+ /**
7830
+ * When changes have been done to series data, update the axis.names.
7831
+ */
7832
+ updateNames: function () {
7833
+ var axis = this;
7834
+
7835
+ if (this.names.length > 0) {
7836
+ this.names.length = 0;
7837
+ this.minRange = undefined;
7838
+ each(this.series || [], function (series) {
7839
+
7840
+ // When adding a series, points are not yet generated
7841
+ if (!series.processedXData) {
7842
+ series.processData();
7843
+ series.generatePoints();
7844
+ }
7845
+
7846
+ each(series.points, function (point, i) {
7847
+ var x;
7848
+ if (point.options && point.options.x === undefined) {
7849
+ x = axis.nameToX(point);
7850
+ if (x !== point.x) {
7851
+ point.x = x;
7852
+ series.xData[i] = x;
7853
+ }
7854
+ }
7855
+ });
7856
+ });
7857
+ }
7858
+ },
7859
+
7788
7860
  /**
7789
7861
  * Update translation information
7790
7862
  */
@@ -8065,7 +8137,7 @@
8065
8137
  }
8066
8138
 
8067
8139
  // Prevent ticks from getting so close that we can't draw the labels
8068
- if (!this.tickAmount && this.len) { // Color axis with disabled legend has no length
8140
+ if (!this.tickAmount) {
8069
8141
  axis.tickInterval = axis.unsquish();
8070
8142
  }
8071
8143
 
@@ -8637,7 +8709,7 @@
8637
8709
  labelMetrics = this.labelMetrics(),
8638
8710
  textOverflowOption = labelOptions.style.textOverflow,
8639
8711
  css,
8640
- labelLength = 0,
8712
+ maxLabelLength = 0,
8641
8713
  label,
8642
8714
  i,
8643
8715
  pos;
@@ -8647,20 +8719,22 @@
8647
8719
  attr.rotation = labelOptions.rotation || 0; // #4443
8648
8720
  }
8649
8721
 
8722
+ // Get the longest label length
8723
+ each(tickPositions, function (tick) {
8724
+ tick = ticks[tick];
8725
+ if (tick && tick.labelLength > maxLabelLength) {
8726
+ maxLabelLength = tick.labelLength;
8727
+ }
8728
+ });
8729
+ this.maxLabelLength = maxLabelLength;
8730
+
8731
+
8650
8732
  // Handle auto rotation on horizontal axis
8651
8733
  if (this.autoRotation) {
8652
8734
 
8653
- // Get the longest label length
8654
- each(tickPositions, function (tick) {
8655
- tick = ticks[tick];
8656
- if (tick && tick.labelLength > labelLength) {
8657
- labelLength = tick.labelLength;
8658
- }
8659
- });
8660
-
8661
8735
  // Apply rotation only if the label is too wide for the slot, and
8662
8736
  // the label is wider than its height.
8663
- if (labelLength > innerWidth && labelLength > labelMetrics.h) {
8737
+ if (maxLabelLength > innerWidth && maxLabelLength > labelMetrics.h) {
8664
8738
  attr.rotation = this.labelRotation;
8665
8739
  } else {
8666
8740
  this.labelRotation = 0;
@@ -8701,7 +8775,7 @@
8701
8775
  // Add ellipsis if the label length is significantly longer than ideal
8702
8776
  if (attr.rotation) {
8703
8777
  css = {
8704
- width: (labelLength > chart.chartHeight * 0.5 ? chart.chartHeight * 0.33 : chart.chartHeight) + PX
8778
+ width: (maxLabelLength > chart.chartHeight * 0.5 ? chart.chartHeight * 0.33 : chart.chartHeight) + PX
8705
8779
  };
8706
8780
  if (!textOverflowOption) {
8707
8781
  css.textOverflow = 'ellipsis';
@@ -9684,12 +9758,12 @@
9684
9758
  fill: options.backgroundColor,
9685
9759
  'stroke-width': borderWidth,
9686
9760
  r: options.borderRadius,
9687
- zIndex: 8
9761
+ zIndex: 8,
9762
+ display: 'none' // #2301, #2657, #3532, #5570
9688
9763
  })
9689
9764
  .css(style)
9690
9765
  .css({ padding: 0 }) // Remove it from VML, the padding is applied as an attribute instead (#1117)
9691
- .add()
9692
- .attr({ y: -9e9 }); // #2301, #2657, #3532
9766
+ .add();
9693
9767
 
9694
9768
  // When using canVG the shadow shows up as a gray circle
9695
9769
  // even if the tooltip is hidden.
@@ -10013,7 +10087,10 @@
10013
10087
  // show it
10014
10088
  if (tooltip.isHidden) {
10015
10089
  stop(label);
10016
- label.attr('opacity', 1).show();
10090
+ label.attr({
10091
+ opacity: 1,
10092
+ display: 'block'
10093
+ }).show();
10017
10094
  }
10018
10095
 
10019
10096
  // update text
@@ -10290,16 +10367,15 @@
10290
10367
  tooltip = chart.tooltip,
10291
10368
  shared = tooltip ? tooltip.shared : false,
10292
10369
  followPointer,
10370
+ updatePosition = true,
10293
10371
  hoverPoint = chart.hoverPoint,
10294
10372
  hoverSeries = chart.hoverSeries,
10295
10373
  i,
10296
- distance = [Number.MAX_VALUE, Number.MAX_VALUE], // #4511
10297
10374
  anchor,
10298
10375
  noSharedTooltip,
10299
10376
  stickToHoverSeries,
10300
10377
  directTouch,
10301
10378
  kdpoints = [],
10302
- kdpoint = [],
10303
10379
  kdpointT;
10304
10380
 
10305
10381
  // For hovering over the empty parts of the plot area (hoverSeries is undefined).
@@ -10317,10 +10393,15 @@
10317
10393
  // search the k-d tree.
10318
10394
  stickToHoverSeries = hoverSeries && (shared ? hoverSeries.noSharedTooltip : hoverSeries.directTouch);
10319
10395
  if (stickToHoverSeries && hoverPoint) {
10320
- kdpoint = [hoverPoint];
10396
+ kdpoints = [hoverPoint];
10321
10397
 
10322
10398
  // Handle shared tooltip or cases where a series is not yet hovered
10323
10399
  } else {
10400
+ // When we have non-shared tooltip and sticky tracking is disabled,
10401
+ // search for the closest point only on hovered series: #5533, #5476
10402
+ if (!shared && hoverSeries && !hoverSeries.options.stickyTracking) {
10403
+ series = [hoverSeries];
10404
+ }
10324
10405
  // Find nearest points on all series
10325
10406
  each(series, function (s) {
10326
10407
  // Skip hidden series
@@ -10333,25 +10414,22 @@
10333
10414
  }
10334
10415
  }
10335
10416
  });
10336
- // Find absolute nearest point
10337
- each(kdpoints, function (p) {
10338
- if (p) {
10339
- // Store both closest points, using point.dist and point.distX comparisons (#4645):
10340
- each(['dist', 'distX'], function (dist, k) {
10341
- if (isNumber(p[dist])) {
10342
- var
10343
- // It is closer than the reference point
10344
- isCloser = p[dist] < distance[k],
10345
- // It is equally close, but above the reference point (#4679)
10346
- isAbove = p[dist] === distance[k] && p.series.group.zIndex >= kdpoint[k].series.group.zIndex;
10347
-
10348
- if (isCloser || isAbove) {
10349
- distance[k] = p[dist];
10350
- kdpoint[k] = p;
10351
- }
10352
- }
10353
- });
10417
+
10418
+ // Sort kdpoints by distance to mouse pointer
10419
+ kdpoints.sort(function (p1, p2) {
10420
+ var isCloserX = p1.distX - p2.distX,
10421
+ isCloser = p1.dist - p2.dist,
10422
+ isAbove = p1.series.group.zIndex > p2.series.group.zIndex ? -1 : 1;
10423
+ // We have two points which are not in the same place on xAxis and shared tooltip:
10424
+ if (isCloserX !== 0) {
10425
+ return isCloserX;
10426
+ }
10427
+ // Points are not exactly in the same place on x/yAxis:
10428
+ if (isCloser !== 0) {
10429
+ return isCloser;
10354
10430
  }
10431
+ // The same xAxis and yAxis position, sort by z-index:
10432
+ return isAbove;
10355
10433
  });
10356
10434
  }
10357
10435
 
@@ -10359,37 +10437,43 @@
10359
10437
  if (shared) {
10360
10438
  i = kdpoints.length;
10361
10439
  while (i--) {
10362
- if (kdpoints[i].clientX !== kdpoint[1].clientX || kdpoints[i].series.noSharedTooltip) {
10440
+ if (kdpoints[i].clientX !== kdpoints[0].clientX || kdpoints[i].series.noSharedTooltip) {
10363
10441
  kdpoints.splice(i, 1);
10364
10442
  }
10365
10443
  }
10366
10444
  }
10367
10445
 
10368
10446
  // Refresh tooltip for kdpoint if new hover point or tooltip was hidden // #3926, #4200
10369
- if (kdpoint[0] && (kdpoint[0] !== this.prevKDPoint || (tooltip && tooltip.isHidden))) {
10447
+ if (kdpoints[0] && (kdpoints[0] !== pointer.hoverPoint || (tooltip && tooltip.isHidden))) {
10370
10448
  // Draw tooltip if necessary
10371
- if (shared && !kdpoint[0].series.noSharedTooltip) {
10449
+ if (shared && !kdpoints[0].series.noSharedTooltip) {
10450
+ // Do mouseover on all points (#3919, #3985, #4410)
10451
+ for (i = 0; i >= 0; i--) {
10452
+ kdpoints[i].onMouseOver(e, kdpoints[i] !== ((hoverSeries && hoverSeries.directTouch && hoverPoint) || kdpoints[0]));
10453
+ }
10454
+ // Make sure that the hoverPoint and hoverSeries are stored for events (e.g. click), #5622
10455
+ if (hoverSeries && hoverSeries.directTouch && hoverPoint && hoverPoint !== kdpoints[0]) {
10456
+ hoverPoint.onMouseOver(e, false);
10457
+ }
10372
10458
  if (kdpoints.length && tooltip) {
10373
- tooltip.refresh(kdpoints, e);
10459
+ // Keep the order of series in tooltip:
10460
+ tooltip.refresh(kdpoints.sort(function (p1, p2) {
10461
+ return p1.series.index - p2.series.index;
10462
+ }), e);
10374
10463
  }
10375
-
10376
- // Do mouseover on all points (#3919, #3985, #4410)
10377
- each(kdpoints, function (point) {
10378
- point.onMouseOver(e, point !== ((hoverSeries && hoverSeries.directTouch && hoverPoint) || kdpoint[0]));
10379
- });
10380
- this.prevKDPoint = kdpoint[1];
10381
10464
  } else {
10382
10465
  if (tooltip) {
10383
- tooltip.refresh(kdpoint[0], e);
10466
+ tooltip.refresh(kdpoints[0], e);
10384
10467
  }
10385
10468
  if (!hoverSeries || !hoverSeries.directTouch) { // #4448
10386
- kdpoint[0].onMouseOver(e);
10469
+ kdpoints[0].onMouseOver(e);
10387
10470
  }
10388
- this.prevKDPoint = kdpoint[0];
10389
10471
  }
10390
-
10472
+ pointer.prevKDPoint = kdpoints[0];
10473
+ updatePosition = false;
10474
+ }
10391
10475
  // Update positions (regardless of kdpoint or hoverPoint)
10392
- } else {
10476
+ if (updatePosition) {
10393
10477
  followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer;
10394
10478
  if (tooltip && followPointer && !tooltip.isHidden) {
10395
10479
  anchor = tooltip.getAnchor([{}], e);
@@ -10409,10 +10493,10 @@
10409
10493
 
10410
10494
  // Crosshair. For each hover point, loop over axes and draw cross if that point
10411
10495
  // belongs to the axis (#4927).
10412
- each(shared ? kdpoints : [pick(hoverPoint, kdpoint[1])], function (point) { // #5269
10413
- each(chart.axes, function (axis) {
10496
+ each(shared ? kdpoints : [pick(hoverPoint, kdpoints[0])], function drawPointCrosshair(point) { // #5269
10497
+ each(chart.axes, function drawAxisCrosshair(axis) {
10414
10498
  // In case of snap = false, point is undefined, and we draw the crosshair anyway (#5066)
10415
- if (!point || point.series[axis.coll] === axis) {
10499
+ if (!point || point.series && point.series[axis.coll] === axis) { // #5658
10416
10500
  axis.drawCrosshair(e, point);
10417
10501
  }
10418
10502
  });
@@ -12297,6 +12381,7 @@
12297
12381
 
12298
12382
  // set axes scales
12299
12383
  each(axes, function (axis) {
12384
+ axis.updateNames();
12300
12385
  axis.setScale();
12301
12386
  });
12302
12387
  }
@@ -12589,7 +12674,9 @@
12589
12674
  // Destroy the clone and bring the container back to the real renderTo div
12590
12675
  if (revert) {
12591
12676
  if (clone) {
12592
- this.renderTo.appendChild(container);
12677
+ while (clone.childNodes.length) { // #5231
12678
+ this.renderTo.appendChild(clone.firstChild);
12679
+ }
12593
12680
  discardElement(clone);
12594
12681
  delete this.renderToClone;
12595
12682
  }
@@ -13143,7 +13230,7 @@
13143
13230
  } else {
13144
13231
  linkedTo = chart.get(linkedTo);
13145
13232
  }
13146
- if (linkedTo) {
13233
+ if (linkedTo && linkedTo.linkedParent !== series) { // #3341 avoid mutual linking
13147
13234
  linkedTo.linkedSeries.push(series);
13148
13235
  series.linkedParent = linkedTo;
13149
13236
  series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879
@@ -13574,14 +13661,25 @@
13574
13661
  extend(point, options);
13575
13662
  point.options = point.options ? extend(point.options, options) : options;
13576
13663
 
13664
+ // Since options are copied into the Point instance, some accidental options must be shielded (#5681)
13665
+ if (options.group) {
13666
+ delete point.group;
13667
+ }
13668
+
13577
13669
  // For higher dimension series types. For instance, for ranges, point.y is mapped to point.low.
13578
13670
  if (pointValKey) {
13579
13671
  point.y = point[pointValKey];
13580
13672
  }
13581
- point.isNull = point.x === null || !isNumber(point.y, true); // #3571, check for NaN
13673
+ point.isNull = pick(
13674
+ point.isValid && !point.isValid(),
13675
+ point.x === null || !isNumber(point.y, true)
13676
+ ); // #3571, check for NaN
13582
13677
 
13583
13678
  // If no x is set by now, get auto incremented value. All points must have an
13584
13679
  // x value, however the y value can be null to create a gap in the series
13680
+ if ('name' in point && x === undefined && series.xAxis && series.xAxis.hasNames) {
13681
+ point.x = series.xAxis.nameToX(point);
13682
+ }
13585
13683
  if (point.x === undefined && series) {
13586
13684
  if (x === undefined) {
13587
13685
  point.x = series.autoIncrement(point);
@@ -13589,12 +13687,7 @@
13589
13687
  point.x = x;
13590
13688
  }
13591
13689
  }
13592
-
13593
- // Write the last point's name to the names array
13594
- if (series.xAxis && series.xAxis.names) {
13595
- series.xAxis.names[point.x] = point.name;
13596
- }
13597
-
13690
+
13598
13691
  return point;
13599
13692
  },
13600
13693
 
@@ -13780,7 +13873,8 @@
13780
13873
  fireEvent(this, eventType, eventArgs, defaultFunction);
13781
13874
  },
13782
13875
  visible: true
13783
- };/**
13876
+ };
13877
+ /**
13784
13878
  * @classDescription The base function which all other series types inherit from. The data in the series is stored
13785
13879
  * in various arrays.
13786
13880
  *
@@ -13959,38 +14053,18 @@
13959
14053
  * Return an auto incremented x value based on the pointStart and pointInterval options.
13960
14054
  * This is only used if an x value is not given for the point that calls autoIncrement.
13961
14055
  */
13962
- autoIncrement: function (point) {
14056
+ autoIncrement: function () {
13963
14057
 
13964
14058
  var options = this.options,
13965
14059
  xIncrement = this.xIncrement,
13966
14060
  date,
13967
14061
  pointInterval,
13968
- pointIntervalUnit = options.pointIntervalUnit,
13969
- xAxis = this.xAxis,
13970
- explicitCategories,
13971
- names,
13972
- nameX;
14062
+ pointIntervalUnit = options.pointIntervalUnit;
13973
14063
 
13974
14064
  xIncrement = pick(xIncrement, options.pointStart, 0);
13975
14065
 
13976
14066
  this.pointInterval = pointInterval = pick(this.pointInterval, options.pointInterval, 1);
13977
14067
 
13978
- // When a point name is given and no x, search for the name in the existing categories,
13979
- // or if categories aren't provided, search names or create a new category (#2522).
13980
- if (xAxis && xAxis.categories && point.name) {
13981
- this.requireSorting = false;
13982
- explicitCategories = isArray(xAxis.categories);
13983
- names = explicitCategories ? xAxis.categories : xAxis.names;
13984
- nameX = inArray(point.name, names); // #2522
13985
- if (nameX === -1) { // The name is not found in currenct categories
13986
- if (!explicitCategories) {
13987
- xIncrement = names.length;
13988
- }
13989
- } else {
13990
- xIncrement = nameX;
13991
- }
13992
- }
13993
-
13994
14068
  // Added code for pointInterval strings
13995
14069
  if (pointIntervalUnit) {
13996
14070
  date = new Date(xIncrement);
@@ -14178,15 +14252,10 @@
14178
14252
 
14179
14253
 
14180
14254
  if (isNumber(firstPoint)) { // assume all points are numbers
14181
- var x = pick(options.pointStart, 0),
14182
- pointInterval = pick(options.pointInterval, 1);
14183
-
14184
14255
  for (i = 0; i < dataLength; i++) {
14185
- xData[i] = x;
14256
+ xData[i] = this.autoIncrement();
14186
14257
  yData[i] = data[i];
14187
- x += pointInterval;
14188
14258
  }
14189
- series.xIncrement = x;
14190
14259
  } else if (isArray(firstPoint)) { // assume all points are arrays
14191
14260
  if (valueCount) { // [x, low, high] or [x, o, h, l, c]
14192
14261
  for (i = 0; i < dataLength; i++) {
@@ -14465,7 +14534,7 @@
14465
14534
 
14466
14535
  // For points within the visible range, including the first point outside the
14467
14536
  // visible range, consider y extremes
14468
- validValue = y !== null && y !== UNDEFINED && (!yAxis.isLog || (y.length || y > 0));
14537
+ validValue = (isNumber(y, true) || isArray(y)) && (!yAxis.isLog || (y.length || y > 0));
14469
14538
  withinRange = this.getExtremesFromAll || this.options.getExtremesFromAll || this.cropped ||
14470
14539
  ((xData[i + 1] || x) >= xMin && (xData[i - 1] || x) <= xMax);
14471
14540
 
@@ -14528,8 +14597,7 @@
14528
14597
 
14529
14598
  // Discard disallowed y values for log axes (#3434)
14530
14599
  if (yAxis.isLog && yValue !== null && yValue <= 0) {
14531
- point.y = yValue = null;
14532
- error(10);
14600
+ point.isNull = true;
14533
14601
  }
14534
14602
 
14535
14603
  // Get the plotX translation
@@ -14580,7 +14648,7 @@
14580
14648
 
14581
14649
 
14582
14650
  // Set client related positions for mouse tracking
14583
- point.clientX = dynamicallyPlaced ? correctFloat(xAxis.translate(xValue, 0, 0, 0, 1)) : plotX; // #1514
14651
+ point.clientX = dynamicallyPlaced ? correctFloat(xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)) : plotX; // #1514, #5383, #5518
14584
14652
 
14585
14653
  point.negative = point.y < (threshold || 0);
14586
14654
 
@@ -14685,14 +14753,9 @@
14685
14753
  var series = this,
14686
14754
  chart = series.chart,
14687
14755
  clipRect,
14688
- animation = series.options.animation,
14756
+ animation = animObject(series.options.animation),
14689
14757
  sharedClipKey;
14690
14758
 
14691
- // Animation option is set to true
14692
- if (animation && !isObject(animation)) {
14693
- animation = defaultPlotOptions[series.type].animation;
14694
- }
14695
-
14696
14759
  // Initialize the animation. Set up the clipping rectangle.
14697
14760
  if (init) {
14698
14761
 
@@ -15262,15 +15325,17 @@
15262
15325
  chartSizeMax = mathMax(chart.chartWidth, chart.chartHeight),
15263
15326
  axis = this[(this.zoneAxis || 'y') + 'Axis'],
15264
15327
  extremes,
15265
- reversed = axis.reversed,
15328
+ reversed,
15266
15329
  inverted = chart.inverted,
15267
- horiz = axis.horiz,
15330
+ horiz,
15268
15331
  pxRange,
15269
15332
  pxPosMin,
15270
15333
  pxPosMax,
15271
15334
  ignoreZones = false;
15272
15335
 
15273
- if (zones.length && (graph || area) && axis.min !== UNDEFINED) {
15336
+ if (zones.length && (graph || area) && axis && axis.min !== UNDEFINED) {
15337
+ reversed = axis.reversed;
15338
+ horiz = axis.horiz;
15274
15339
  // The use of the Color Threshold assumes there are no gaps
15275
15340
  // so it is safe to hide the original graph and area
15276
15341
  if (graph) {
@@ -15320,7 +15385,7 @@
15320
15385
  }
15321
15386
 
15322
15387
  /// VML SUPPPORT
15323
- if (chart.inverted && renderer.isVML) {
15388
+ if (inverted && renderer.isVML) {
15324
15389
  if (axis.isXAxis) {
15325
15390
  clipAttr = {
15326
15391
  x: 0,
@@ -16268,8 +16333,7 @@
16268
16333
  graphic = point.graphic,
16269
16334
  i,
16270
16335
  chart = series.chart,
16271
- seriesOptions = series.options,
16272
- names = series.xAxis && series.xAxis.names;
16336
+ seriesOptions = series.options;
16273
16337
 
16274
16338
  redraw = pick(redraw, true);
16275
16339
 
@@ -16299,10 +16363,7 @@
16299
16363
  // record changes in the parallel arrays
16300
16364
  i = point.index;
16301
16365
  series.updateParallelArrays(point, i);
16302
- if (names && point.name) {
16303
- names[point.x] = point.name;
16304
- }
16305
-
16366
+
16306
16367
  // Record the options to options.data. If there is an object from before,
16307
16368
  // use point options, otherwise use raw options. (#4701)
16308
16369
  seriesOptions.data[i] = isObject(seriesOptions.data[i], true) ? point.options : options;
@@ -16364,8 +16425,6 @@
16364
16425
  i,
16365
16426
  x;
16366
16427
 
16367
- setAnimation(animation, chart);
16368
-
16369
16428
  // Optional redraw, defaults to true
16370
16429
  redraw = pick(redraw, true);
16371
16430
 
@@ -16417,9 +16476,10 @@
16417
16476
  // redraw
16418
16477
  series.isDirty = true;
16419
16478
  series.isDirtyData = true;
16479
+
16420
16480
  if (redraw) {
16421
16481
  series.getAttribs(); // #1937
16422
- chart.redraw();
16482
+ chart.redraw(animation); // Animation is set anyway on redraw, #5665
16423
16483
  }
16424
16484
  },
16425
16485
 
@@ -16472,12 +16532,11 @@
16472
16532
  * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
16473
16533
  * configuration
16474
16534
  */
16475
- remove: function (redraw, animation) {
16535
+ remove: function (redraw, animation, withEvent) {
16476
16536
  var series = this,
16477
16537
  chart = series.chart;
16478
16538
 
16479
- // Fire the event with a default handler of removing the point
16480
- fireEvent(series, 'remove', null, function () {
16539
+ function remove() {
16481
16540
 
16482
16541
  // Destroy elements
16483
16542
  series.destroy();
@@ -16489,7 +16548,14 @@
16489
16548
  if (pick(redraw, true)) {
16490
16549
  chart.redraw(animation);
16491
16550
  }
16492
- });
16551
+ }
16552
+
16553
+ // Fire the event with a default handler of removing the point
16554
+ if (withEvent !== false) {
16555
+ fireEvent(series, 'remove', null, remove);
16556
+ } else {
16557
+ remove();
16558
+ }
16493
16559
  },
16494
16560
 
16495
16561
  /**
@@ -16526,7 +16592,7 @@
16526
16592
 
16527
16593
  // Destroy the series and delete all properties. Reinsert all methods
16528
16594
  // and properties from the new type prototype (#2270, #3719)
16529
- this.remove(false);
16595
+ this.remove(false, null, false);
16530
16596
  for (n in proto) {
16531
16597
  this[n] = UNDEFINED;
16532
16598
  }
@@ -16811,14 +16877,14 @@
16811
16877
  });
16812
16878
  bottomPoints.push({
16813
16879
  plotX: plotX,
16814
- plotY: bottom === null ? translatedThreshold : yAxis.getThreshold(bottom)
16880
+ plotY: bottom === null ? translatedThreshold : yAxis.getThreshold(bottom),
16881
+ doCurve: false // #1041, gaps in areaspline areas
16815
16882
  });
16816
16883
  }
16817
16884
  };
16818
16885
 
16819
16886
  // Find what points to use
16820
16887
  points = points || this.points;
16821
-
16822
16888
 
16823
16889
  // Fill in missing points
16824
16890
  if (stacking) {
@@ -16949,8 +17015,12 @@
16949
17015
  rightContY,
16950
17016
  ret;
16951
17017
 
17018
+ function doCurve(otherPoint) {
17019
+ return otherPoint && !otherPoint.isNull && otherPoint.doCurve !== false;
17020
+ }
17021
+
16952
17022
  // Find control points
16953
- if (lastPoint && !lastPoint.isNull && nextPoint && !nextPoint.isNull) {
17023
+ if (doCurve(lastPoint) && doCurve(nextPoint)) {
16954
17024
  var lastX = lastPoint.plotX,
16955
17025
  lastY = lastPoint.plotY,
16956
17026
  nextX = nextPoint.plotX,
@@ -17001,29 +17071,35 @@
17001
17071
  this.chart.renderer.circle(leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop, 2)
17002
17072
  .attr({
17003
17073
  stroke: 'red',
17004
- 'stroke-width': 1,
17005
- fill: 'none'
17074
+ 'stroke-width': 2,
17075
+ fill: 'none',
17076
+ zIndex: 9
17006
17077
  })
17007
17078
  .add();
17008
17079
  this.chart.renderer.path(['M', leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop,
17009
17080
  'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
17010
17081
  .attr({
17011
17082
  stroke: 'red',
17012
- 'stroke-width': 1
17083
+ 'stroke-width': 2,
17084
+ zIndex: 9
17013
17085
  })
17014
17086
  .add();
17087
+ }
17088
+ if (rightContX) {
17015
17089
  this.chart.renderer.circle(rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop, 2)
17016
17090
  .attr({
17017
17091
  stroke: 'green',
17018
- 'stroke-width': 1,
17019
- fill: 'none'
17092
+ 'stroke-width': 2,
17093
+ fill: 'none',
17094
+ zIndex: 9
17020
17095
  })
17021
17096
  .add();
17022
17097
  this.chart.renderer.path(['M', rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop,
17023
17098
  'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
17024
17099
  .attr({
17025
17100
  stroke: 'green',
17026
- 'stroke-width': 1
17101
+ 'stroke-width': 2,
17102
+ zIndex: 9
17027
17103
  })
17028
17104
  .add();
17029
17105
  }
@@ -17316,7 +17392,12 @@
17316
17392
 
17317
17393
  // Register shape type and arguments to be used in drawPoints
17318
17394
  point.shapeType = 'rect';
17319
- point.shapeArgs = series.crispCol(barX, barY, barW, barH);
17395
+ point.shapeArgs = series.crispCol.apply(
17396
+ series,
17397
+ point.isNull ?
17398
+ [point.plotX, yAxis.len / 2, 0, 0] : // #3169, drilldown from null must have a position to work from
17399
+ [barX, barY, barW, barH]
17400
+ );
17320
17401
  });
17321
17402
 
17322
17403
  },
@@ -19643,7 +19724,7 @@
19643
19724
  oldVisibility = series.visible;
19644
19725
 
19645
19726
  // if called without an argument, toggle visibility
19646
- series.visible = vis = series.userOptions.visible = vis === UNDEFINED ? !oldVisibility : vis;
19727
+ series.visible = vis = series.options.visible = series.userOptions.visible = vis === undefined ? !oldVisibility : vis; // #5618
19647
19728
  showOrHide = vis ? 'show' : 'hide';
19648
19729
 
19649
19730
  // show or hide elements