highcharts-rails 4.1.7 → 4.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4a6a629f316d30ec0202c1d30132ca75b330e5c
4
- data.tar.gz: b4159b1bce4ad88d4338a7743b8d659747cddf70
3
+ metadata.gz: b5d2613cbe4c6a3f1071f83ec6fe79c4f94e6d51
4
+ data.tar.gz: a505f22fce9e0075c5012d3f5a73dced8940673d
5
5
  SHA512:
6
- metadata.gz: 4ccdfb6d73da784b1e673e9a6ee7de7fa967cb6320a5926ea682f5d3a84dbd84f77cf764ac3c87886bb9a31ed44fd06d2a1b83f5b0b7b5b2a57c7ec41a9ef36c
7
- data.tar.gz: 86f0408ebf477bcdbd8b921b51e18e53ebe8abbdba1da92aa1ac2dd425e7f2082c4909929aa3a5214f06392bff582cbebcf46480dd2c299d9e82a929d2a356a5
6
+ metadata.gz: 9009c0a9b5bb8bcd42150a35838f3b45ea00917509ae8150b6054004be300301fd3512e3e55b8450217d2b82b8f23290c01a98318ea0a85ab046bf6061cf7201
7
+ data.tar.gz: bd615ab24486525622bb2e0d3038d49359ec7ddb4d2f478dea63f9fe6d6677672be96b0c5f7d7158a7f40e7982a8b35cade4ce80306e14e598bd5ddd875007cc
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,59 @@
1
+ # 4.1.8 / 2015-08-31
2
+
3
+ * Updated Highcharts to 4.1.8 (2015-08-20)
4
+ * Added experimental support for using HTML in exported charts through the exporting.allowHTML option. Discussed in #2473.
5
+ * Added new option, maxPointWidth, to the column chart type and its derivatives.
6
+ * Add %k, hours with no padding, in dateFormat.
7
+ * Don't cache undefined bounding box key. Closes #4328.
8
+ * Fixed #4448, which causes duplicated event calls for column series.
9
+ * Fixed #1498, minor ticks were missing when using column series.
10
+ * Fixed #1655, where setExtremes event could be called with undefined extremes.
11
+ * Fixed #2775, click on custom button propagated and caused JS errors when destroying chart.
12
+ * Fixed #3379, minPadding and maxPadding was wrong on color axis.
13
+ * Fixed #3737, points within a group were not reversed in a reversed bar chart X axis.
14
+ * Fixed #3879, where linked series didn't inherit initial visibility from a parent.
15
+ * Fixed #3909, HTML data label was invisible after drilling up.
16
+ * Fixed #4149, tooltip went off plot area when data was clipped.
17
+ * Fixed #4189, wrong position of the legend in IE7.
18
+ * Fixed #4219, enconding problem with ellipsis. Better fix for #4079.
19
+ * Fixed #4246, pie slices with null values should not be rendered.
20
+ * Fixed #4313, setting one of the extremes removed both, min and max, axis paddings for bubble series.
21
+ * Fixed #4320, stack items building up and creating memory leak when adding and removing points.
22
+ * Fixed #4333, data label overlapping detection was too aggressive. Don't handle padding when the label doesn't have a border or background.
23
+ * Fixed #4339, touch-dragging in IE11 on a zoom enabled chart caused JS errors.
24
+ * Fixed #4343, axis lines missing when 3D was loaded.
25
+ * Fixed #4347, legend item click of heatmap with data classes should hide items.
26
+ * Fixed #4349, updating point.x prevented point from being hidden from legend.
27
+ * Fixed #4350, pie chart failing with StockChart constructor.
28
+ * Fixed #4356, pointBreak wasn't called for values below the threshold.
29
+ * Fixed #4356, series with null threshold now calls breakPoint correctly
30
+ * Fixed #4359, drilldown pie selected slices had wrong color.
31
+ * Fixed #4360, float error on logarithmic axis label.
32
+ * Fixed #4364, chart click event fired when clicking menu items in the export menu.
33
+ * Fixed #4365, pie chart connectors were not hidden when data labels used HTML and hiding the series.
34
+ * Fixed #4371, where negative Axis offset miscalculated clip-path for series.
35
+ * Fixed #4390, JS error in some cases on updating a series with no data.
36
+ * Fixed #4396, different minSize and maxSize per separate series didn't work.
37
+ * Fixed #4401, better handling categories based on a point.name.
38
+ * Fixed #4410, a regression causing incorrect mouseover events in column charts.
39
+ * Fixed #4411, setting axis.labels.step to 1 didn't result in 1:1 labels.
40
+ * Fixed #4420, generic X axis gridline width with 3d columns.
41
+ * Fixed #4421, overlapping upper data labels on arearange series.
42
+ * Fixed #4430, point color was not set on positive points when negativeColor was set.
43
+ * Fixed #4434, regression causing failure with reversed solid gauge.
44
+ * Fixed #4443, auto rotation was not reset after widening chart when labels used HTML.
45
+ * Fixed #4449, a regression causing wrong alignment on legend items when rtl was combined with useHTML.
46
+ * Fixed #4477, too dense ticks when setting staggerLines, caused browser crash.
47
+ * Fixed #4313, setting one of the extremes removed both, min and max, paddings.
48
+ * Fixed #4351, setSize with standalone adapter didn't resize inner container.
49
+ * Fixed animation on updating map colors.
50
+ * Fixed issue with displayNegative not working with all data. Closes #4419
51
+ * Fixed issue with pie and data labels producing JS error in IE6.
52
+ * Fixed issue with updating mapbubble point to null.
53
+ * Fixed regression with JS error on updating pie slice value to null.
54
+ * Improve logic for pointBreaks, touch #4356
55
+ * Partial fix for #3861, bubble series not working with logarithmic axes. It now displays, but the bubbles are clipped unless the user sets a padding.
56
+
1
57
  # 4.1.7 / 2015-08-31
2
58
 
3
59
  * Updated Highcharts to 4.1.7 (2015-06-26)
data/Rakefile CHANGED
@@ -1 +1,37 @@
1
1
  require 'bundler/gem_tasks'
2
+
3
+ desc "Update to the latest version of Highcharts"
4
+ task :update, :version do |t, args|
5
+ version = args[:version]
6
+ url = "http://code.highcharts.com/zips/Highcharts-#{version}.zip"
7
+ puts "Fetching #{url}"
8
+ `curl -# #{url} -o tmp/#{version}.zip`
9
+ `unzip tmp/#{version}.zip -d tmp/#{version}`
10
+
11
+ mappings = {
12
+ "highcharts.src.js" => "highcharts.js",
13
+ "highcharts-more.src.js" => "highcharts/highcharts-more.js",
14
+ "highcharts-3d.src.js" => "highcharts/highcharts-3d.js",
15
+ "standalone-framework.src.js" => "highcharts/adapters/standalone-framework.js",
16
+ "annotations.src.js" => "highcharts/modules/annotations.js",
17
+ "canvas-tools.src.js" => "highcharts/modules/canvas-tools.js",
18
+ "data.src.js" => "highcharts/modules/data.js",
19
+ "drilldown.src.js" => "highcharts/modules/drilldown.js",
20
+ "exporting.src.js" => "highcharts/modules/exporting.js",
21
+ "funnel.src.js" => "highcharts/modules/funnel.js",
22
+ "heatmap.src.js" => "highcharts/modules/heatmap.js",
23
+ "no-data-to-display.src.js" => "highcharts/modules/no-data-to-display.js",
24
+ "solid-gauge.src.js" => "highcharts/modules/solid-gauge.js",
25
+ "treemap.src.js" => "highcharts/modules/treemap.js",
26
+ "broken-axis.src.js" => "highcharts/modules/broken-axis.js",
27
+ "boost.src.js" => "highcharts/modules/boost.js",
28
+ "offline-exporting.src.js" => "highcharts/modules/offline-exporting.js",
29
+ }
30
+ dest = "app/assets/javascripts/"
31
+ Dir.glob("tmp/#{version}/js/**/*.src.js").each do |file|
32
+ name = File.basename(file)
33
+ FileUtils.cp file, "#{dest}#{mappings[name]}", verbose: true
34
+ end
35
+ FileUtils.cp Dir.glob("tmp/#{version}/js/themes/*.js"), "#{dest}highcharts/themes/", verbose: true
36
+ FileUtils.cp Dir.glob("tmp/#{version}/graphics/*.png"), "app/assets/images/highcharts", verbose: true
37
+ end
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v4.1.7 (2015-06-26)
5
+ * @license Highcharts JS v4.1.8 (2015-08-20)
6
6
  *
7
7
  * (c) 2009-2014 Torstein Honsi
8
8
  *
@@ -49,14 +49,13 @@ var UNDEFINED,
49
49
  garbageBin,
50
50
  defaultOptions,
51
51
  dateFormat, // function
52
- globalAnimation,
53
52
  pathAnim,
54
53
  timeUnits,
55
54
  noop = function () { return UNDEFINED; },
56
55
  charts = [],
57
56
  chartCount = 0,
58
57
  PRODUCT = 'Highcharts',
59
- VERSION = '4.1.7',
58
+ VERSION = '4.1.8',
60
59
 
61
60
  // some constants for frequently used strings
62
61
  DIV = 'div',
@@ -405,7 +404,7 @@ function getTZOffset(timestamp) {
405
404
  */
406
405
  dateFormat = function (format, timestamp, capitalize) {
407
406
  if (!defined(timestamp) || isNaN(timestamp)) {
408
- return 'Invalid date';
407
+ return defaultOptions.lang.invalidDate || '';
409
408
  }
410
409
  format = pick(format, '%Y-%m-%d %H:%M:%S');
411
410
 
@@ -444,6 +443,7 @@ dateFormat = function (format, timestamp, capitalize) {
444
443
 
445
444
  // Time
446
445
  'H': pad(hours), // Two digits hours in 24h format, 00 through 23
446
+ 'k': hours, // Hours in 24h format, 0 through 23
447
447
  'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11
448
448
  'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12
449
449
  'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59
@@ -710,9 +710,9 @@ function error (code, stop) {
710
710
  * Fix JS round off float errors
711
711
  * @param {Number} num
712
712
  */
713
- function correctFloat(num) {
713
+ function correctFloat(num, prec) {
714
714
  return parseFloat(
715
- num.toPrecision(14)
715
+ num.toPrecision(prec || 14)
716
716
  );
717
717
  }
718
718
 
@@ -723,7 +723,7 @@ function correctFloat(num) {
723
723
  * @param {Object} chart
724
724
  */
725
725
  function setAnimation(animation, chart) {
726
- globalAnimation = pick(animation, chart.animation);
726
+ chart.renderer.globalAnimation = pick(animation, chart.animation);
727
727
  }
728
728
 
729
729
  /**
@@ -1259,6 +1259,7 @@ defaultOptions = {
1259
1259
  'August', 'September', 'October', 'November', 'December'],
1260
1260
  shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1261
1261
  weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1262
+ // invalidDate: '',
1262
1263
  decimalPoint: '.',
1263
1264
  numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'], // SI prefixes used in axis labels
1264
1265
  resetZoom: 'Reset zoom',
@@ -1268,8 +1269,8 @@ defaultOptions = {
1268
1269
  global: {
1269
1270
  useUTC: true,
1270
1271
  //timezoneOffset: 0,
1271
- canvasToolsURL: 'http://code.highcharts.com/4.1.7/modules/canvas-tools.js',
1272
- VMLRadialGradientURL: 'http://code.highcharts.com/4.1.7/gfx/vml-radial-gradient.png'
1272
+ canvasToolsURL: 'http://code.highcharts.com/4.1.8/modules/canvas-tools.js',
1273
+ VMLRadialGradientURL: 'http://code.highcharts.com/4.1.8/gfx/vml-radial-gradient.png'
1273
1274
  },
1274
1275
  chart: {
1275
1276
  //animation: true,
@@ -1796,7 +1797,7 @@ SVGElement.prototype = {
1796
1797
  opacity: 1,
1797
1798
  // For labels, these CSS properties are applied to the <text> node directly
1798
1799
  textProps: ['fontSize', 'fontWeight', 'fontFamily', 'fontStyle', 'color',
1799
- 'lineHeight', 'width', 'textDecoration', 'textShadow'],
1800
+ 'lineHeight', 'width', 'textDecoration', 'textOverflow', 'textShadow'],
1800
1801
 
1801
1802
  /**
1802
1803
  * Initialize the SVG renderer
@@ -1818,7 +1819,7 @@ SVGElement.prototype = {
1818
1819
  * @param {Function} complete Function to perform at the end of animation
1819
1820
  */
1820
1821
  animate: function (params, options, complete) {
1821
- var animOptions = pick(options, globalAnimation, true);
1822
+ var animOptions = pick(options, this.renderer.globalAnimation, true);
1822
1823
  stop(this); // stop regardless of animation actually running, or reverting to .attr (#607)
1823
1824
  if (animOptions) {
1824
1825
  animOptions = merge(animOptions, {}); //#2625
@@ -1827,10 +1828,7 @@ SVGElement.prototype = {
1827
1828
  }
1828
1829
  animate(this, params, animOptions);
1829
1830
  } else {
1830
- this.attr(params);
1831
- if (complete) {
1832
- complete();
1833
- }
1831
+ this.attr(params, null, complete);
1834
1832
  }
1835
1833
  return this;
1836
1834
  },
@@ -1943,9 +1941,9 @@ SVGElement.prototype = {
1943
1941
  * Apply a polyfill to the text-stroke CSS property, by copying the text element
1944
1942
  * and apply strokes to the copy.
1945
1943
  *
1944
+ * Contrast checks at http://jsfiddle.net/highcharts/43soe9m1/2/
1945
+ *
1946
1946
  * docs: update default, document the polyfill and the limitations on hex colors and pixel values, document contrast pseudo-color
1947
- * TODO:
1948
- * - update defaults
1949
1947
  */
1950
1948
  applyTextShadow: function (textShadow) {
1951
1949
  var elem = this.element,
@@ -2033,7 +2031,7 @@ SVGElement.prototype = {
2033
2031
  * @param {Object|String} hash
2034
2032
  * @param {Mixed|Undefined} val
2035
2033
  */
2036
- attr: function (hash, val) {
2034
+ attr: function (hash, val, complete) {
2037
2035
  var key,
2038
2036
  value,
2039
2037
  element = this.element,
@@ -2092,6 +2090,11 @@ SVGElement.prototype = {
2092
2090
 
2093
2091
  }
2094
2092
 
2093
+ // In accordance with animate, run a complete callback
2094
+ if (complete) {
2095
+ complete();
2096
+ }
2097
+
2095
2098
  return ret;
2096
2099
  },
2097
2100
 
@@ -2569,7 +2572,9 @@ SVGElement.prototype = {
2569
2572
  }
2570
2573
 
2571
2574
  // Cache it
2572
- renderer.cache[cacheKey] = bBox;
2575
+ if (cacheKey) {
2576
+ renderer.cache[cacheKey] = bBox;
2577
+ }
2573
2578
  }
2574
2579
  return bBox;
2575
2580
  },
@@ -2578,13 +2583,7 @@ SVGElement.prototype = {
2578
2583
  * Show the element
2579
2584
  */
2580
2585
  show: function (inherit) {
2581
- // IE9-11 doesn't handle visibilty:inherit well, so we remove the attribute instead (#2881)
2582
- if (inherit && this.element.namespaceURI === SVG_NS) {
2583
- this.element.removeAttribute('visibility');
2584
- } else {
2585
- this.attr({ visibility: inherit ? 'inherit' : VISIBLE });
2586
- }
2587
- return this;
2586
+ return this.attr({ visibility: inherit ? 'inherit' : VISIBLE });
2588
2587
  },
2589
2588
 
2590
2589
  /**
@@ -2867,6 +2866,14 @@ SVGElement.prototype = {
2867
2866
  this.colorGradient(value, key, element);
2868
2867
  }
2869
2868
  },
2869
+ visibilitySetter: function (value, key, element) {
2870
+ // IE9-11 doesn't handle visibilty:inherit well, so we remove the attribute instead (#2881, #3909)
2871
+ if (value === 'inherit') {
2872
+ element.removeAttribute(key);
2873
+ } else {
2874
+ element.setAttribute(key, value);
2875
+ }
2876
+ },
2870
2877
  zIndexSetter: function (value, key) {
2871
2878
  var renderer = this.renderer,
2872
2879
  parentGroup = this.parentGroup,
@@ -3491,9 +3498,9 @@ SVGRenderer.prototype = {
3491
3498
  };
3492
3499
 
3493
3500
  return label
3494
- .on('click', function () {
3501
+ .on('click', function (e) {
3495
3502
  if (curState !== 3) {
3496
- callback.call(label);
3503
+ callback.call(label, e);
3497
3504
  }
3498
3505
  })
3499
3506
  .attr(normalState)
@@ -4143,7 +4150,11 @@ SVGRenderer.prototype = {
4143
4150
  wrapper.box = box = shape ?
4144
4151
  renderer.symbol(shape, boxX, boxY, wrapper.width, wrapper.height, deferredAttr) :
4145
4152
  renderer.rect(boxX, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);
4146
- box.attr('fill', NONE).add(wrapper);
4153
+
4154
+ if (!box.isImg) { // #4324, fill "none" causes it to be ignored by mouse events in IE
4155
+ box.attr('fill', NONE);
4156
+ }
4157
+ box.add(wrapper);
4147
4158
  }
4148
4159
 
4149
4160
  // apply the box attributes
@@ -4466,7 +4477,7 @@ extend(SVGElement.prototype, {
4466
4477
  rotation = wrapper.rotation,
4467
4478
  baseline,
4468
4479
  textWidth = pInt(wrapper.textWidth),
4469
- currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(',');
4480
+ currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth, wrapper.textAlign].join(',');
4470
4481
 
4471
4482
  if (currentTextTransform !== wrapper.cTT) { // do the calculations and DOM access only if properties changed
4472
4483
 
@@ -4551,6 +4562,7 @@ extend(SVGRenderer.prototype, {
4551
4562
  delete this.bBox;
4552
4563
  }
4553
4564
  element.innerHTML = this.textStr = value;
4565
+ wrapper.htmlUpdateTransform();
4554
4566
  };
4555
4567
 
4556
4568
  // Various setters which rely on update transform
@@ -4638,11 +4650,12 @@ extend(SVGRenderer.prototype, {
4638
4650
  htmlGroupStyle.top = value + PX;
4639
4651
  parentGroup[key] = value;
4640
4652
  parentGroup.doTransform = true;
4641
- },
4642
- visibilitySetter: function (value, key) {
4643
- htmlGroupStyle[key] = value;
4644
4653
  }
4645
4654
  });
4655
+ wrap(parentGroup, 'visibilitySetter', function (proceed, value, key, elem) {
4656
+ proceed.call(this, value, key, elem);
4657
+ htmlGroupStyle[key] = value;
4658
+ });
4646
4659
  });
4647
4660
 
4648
4661
  }
@@ -6045,7 +6058,7 @@ Tick.prototype = {
6045
6058
  gridLineColor = options[gridPrefix + 'LineColor'],
6046
6059
  dashStyle = options[gridPrefix + 'LineDashStyle'],
6047
6060
  tickLength = options[tickPrefix + 'Length'],
6048
- tickWidth = options[tickPrefix + 'Width'] || 0,
6061
+ tickWidth = pick(options[tickPrefix + 'Width'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1
6049
6062
  tickColor = options[tickPrefix + 'Color'],
6050
6063
  tickPosition = options[tickPrefix + 'Position'],
6051
6064
  gridLinePath,
@@ -6516,7 +6529,7 @@ Axis.prototype = {
6516
6529
  tickmarkPlacement: 'between', // on or between
6517
6530
  tickPixelInterval: 100,
6518
6531
  tickPosition: 'outside',
6519
- tickWidth: 1,
6532
+ //tickWidth: 1,
6520
6533
  title: {
6521
6534
  //text: null,
6522
6535
  align: 'middle', // low, middle or high
@@ -6548,7 +6561,7 @@ Axis.prototype = {
6548
6561
  maxPadding: 0.05,
6549
6562
  minPadding: 0.05,
6550
6563
  startOnTick: true,
6551
- tickWidth: 0,
6564
+ //tickWidth: 0,
6552
6565
  title: {
6553
6566
  rotation: 270,
6554
6567
  text: 'Values'
@@ -6634,6 +6647,8 @@ Axis.prototype = {
6634
6647
  var isXAxis = userOptions.isX,
6635
6648
  axis = this;
6636
6649
 
6650
+ axis.chart = chart;
6651
+
6637
6652
  // Flag, is the axis horizontal
6638
6653
  axis.horiz = chart.inverted ? !isXAxis : isXAxis;
6639
6654
 
@@ -6664,7 +6679,6 @@ Axis.prototype = {
6664
6679
  //axis.ignoreMinPadding = UNDEFINED; // can be set to true by a column or bar series
6665
6680
  //axis.ignoreMaxPadding = UNDEFINED;
6666
6681
 
6667
- axis.chart = chart;
6668
6682
  axis.reversed = options.reversed;
6669
6683
  axis.zoomEnabled = options.zoomEnabled !== false;
6670
6684
 
@@ -6730,7 +6744,8 @@ Axis.prototype = {
6730
6744
  // Dictionary for stacks
6731
6745
  axis.stacks = {};
6732
6746
  axis.oldStacks = {};
6733
-
6747
+ axis.stacksTouched = 0;
6748
+
6734
6749
  // Min and max in the data
6735
6750
  //axis.dataMin = UNDEFINED,
6736
6751
  //axis.dataMax = UNDEFINED,
@@ -7104,8 +7119,9 @@ Axis.prototype = {
7104
7119
  minorTickPositions = [],
7105
7120
  pos,
7106
7121
  i,
7107
- min = axis.min,
7108
- max = axis.max,
7122
+ pointRangePadding = axis.pointRangePadding || 0,
7123
+ min = axis.min - pointRangePadding, // #1498
7124
+ max = axis.max + pointRangePadding, // #1498
7109
7125
  range = max - min,
7110
7126
  len;
7111
7127
 
@@ -7135,7 +7151,9 @@ Axis.prototype = {
7135
7151
  }
7136
7152
  }
7137
7153
 
7138
- axis.trimTicks(minorTickPositions); // #3652 #3743
7154
+ if(minorTickPositions.length !== 0) { // don't change the extremes, when there is no minor ticks
7155
+ axis.trimTicks(minorTickPositions, options.startOnTick, options.endOnTick); // #3652 #3743 #1498
7156
+ }
7139
7157
  return minorTickPositions;
7140
7158
  },
7141
7159
 
@@ -7300,6 +7318,10 @@ Axis.prototype = {
7300
7318
  axis.minPixelPadding = transA * minPointOffset;
7301
7319
  },
7302
7320
 
7321
+ minFromRange: function () {
7322
+ return this.max - this.range;
7323
+ },
7324
+
7303
7325
  /**
7304
7326
  * Set the tick positions to round values and optionally extend the extremes
7305
7327
  * to the nearest tick
@@ -7343,13 +7365,16 @@ Axis.prototype = {
7343
7365
  if (!secondPass && mathMin(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978
7344
7366
  error(10, 1); // Can't plot negative values on log axis
7345
7367
  }
7346
- axis.min = correctFloat(log2lin(axis.min)); // correctFloat cures #934
7347
- axis.max = correctFloat(log2lin(axis.max));
7368
+ // The correctFloat cures #934, float errors on full tens. But it
7369
+ // was too aggressive for #4360 because of conversion back to lin,
7370
+ // therefore use precision 15.
7371
+ axis.min = correctFloat(log2lin(axis.min), 15);
7372
+ axis.max = correctFloat(log2lin(axis.max), 15);
7348
7373
  }
7349
7374
 
7350
7375
  // handle zoomed range
7351
7376
  if (axis.range && defined(axis.max)) {
7352
- axis.userMin = axis.min = mathMax(axis.min, axis.max - axis.range); // #618
7377
+ axis.userMin = axis.min = mathMax(axis.min, axis.minFromRange()); // #618
7353
7378
  axis.userMax = axis.max;
7354
7379
 
7355
7380
  axis.range = null; // don't use it when running setExtremes
@@ -7497,6 +7522,11 @@ Axis.prototype = {
7497
7522
  tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max);
7498
7523
  }
7499
7524
 
7525
+ // Too dense ticks, keep only the first and last (#4477)
7526
+ if (tickPositions.length > this.len) {
7527
+ tickPositions = [tickPositions[0], tickPositions.pop()];
7528
+ }
7529
+
7500
7530
  this.tickPositions = tickPositions;
7501
7531
 
7502
7532
  // Run the tick positioner callback, that allows modifying auto tick positions.
@@ -7653,9 +7683,6 @@ Axis.prototype = {
7653
7683
  */
7654
7684
  setScale: function () {
7655
7685
  var axis = this,
7656
- stacks = axis.stacks,
7657
- type,
7658
- i,
7659
7686
  isDirtyData,
7660
7687
  isDirtyAxisLength;
7661
7688
 
@@ -7680,14 +7707,8 @@ Axis.prototype = {
7680
7707
  if (isDirtyAxisLength || isDirtyData || axis.isLinked || axis.forceRedraw ||
7681
7708
  axis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax) {
7682
7709
 
7683
- // reset stacks
7684
- if (!axis.isXAxis) {
7685
- for (type in stacks) {
7686
- for (i in stacks[type]) {
7687
- stacks[type][i].total = null;
7688
- stacks[type][i].cum = 0;
7689
- }
7690
- }
7710
+ if (axis.resetStacks) {
7711
+ axis.resetStacks();
7691
7712
  }
7692
7713
 
7693
7714
  axis.forceRedraw = false;
@@ -7706,17 +7727,8 @@ Axis.prototype = {
7706
7727
  if (!axis.isDirty) {
7707
7728
  axis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax;
7708
7729
  }
7709
- } else if (!axis.isXAxis) {
7710
- if (axis.oldStacks) {
7711
- stacks = axis.stacks = axis.oldStacks;
7712
- }
7713
-
7714
- // reset stacks
7715
- for (type in stacks) {
7716
- for (i in stacks[type]) {
7717
- stacks[type][i].cum = stacks[type][i].total;
7718
- }
7719
- }
7730
+ } else if (axis.cleanStacks) {
7731
+ axis.cleanStacks();
7720
7732
  }
7721
7733
  },
7722
7734
 
@@ -7753,10 +7765,6 @@ Axis.prototype = {
7753
7765
  axis.userMax = newMax;
7754
7766
  axis.eventArgs = eventArguments;
7755
7767
 
7756
- // Mark for running afterSetExtremes
7757
- axis.isDirtyExtremes = true;
7758
-
7759
- // redraw
7760
7768
  if (redraw) {
7761
7769
  chart.redraw(animation);
7762
7770
  }
@@ -7770,15 +7778,17 @@ Axis.prototype = {
7770
7778
  zoom: function (newMin, newMax) {
7771
7779
  var dataMin = this.dataMin,
7772
7780
  dataMax = this.dataMax,
7773
- options = this.options;
7781
+ options = this.options,
7782
+ min = mathMin(dataMin, pick(options.min, dataMin)),
7783
+ max = mathMax(dataMax, pick(options.max, dataMax));
7774
7784
 
7775
7785
  // Prevent pinch zooming out of range. Check for defined is for #1946. #1734.
7776
7786
  if (!this.allowZoomOutside) {
7777
- if (defined(dataMin) && newMin <= mathMin(dataMin, pick(options.min, dataMin))) {
7778
- newMin = UNDEFINED;
7787
+ if (defined(dataMin) && newMin <= min) {
7788
+ newMin = min;
7779
7789
  }
7780
- if (defined(dataMax) && newMax >= mathMax(dataMax, pick(options.max, dataMax))) {
7781
- newMax = UNDEFINED;
7790
+ if (defined(dataMax) && newMax >= max) {
7791
+ newMax = max;
7782
7792
  }
7783
7793
  }
7784
7794
 
@@ -7943,7 +7953,7 @@ Axis.prototype = {
7943
7953
  });
7944
7954
  }
7945
7955
 
7946
- } else {
7956
+ } else if (!labelOptions.step) { // #4411
7947
7957
  newTickInterval = getStep(labelMetrics.h);
7948
7958
  }
7949
7959
 
@@ -7977,7 +7987,7 @@ Axis.prototype = {
7977
7987
 
7978
7988
  // Set rotation option unless it is "auto", like in gauges
7979
7989
  if (!isString(labelOptions.rotation)) {
7980
- attr.rotation = labelOptions.rotation;
7990
+ attr.rotation = labelOptions.rotation || 0; // #4443
7981
7991
  }
7982
7992
 
7983
7993
  // Handle auto rotation on horizontal axis
@@ -8199,10 +8209,7 @@ Axis.prototype = {
8199
8209
  );
8200
8210
 
8201
8211
  // Decide the clipping needed to keep the graph inside the plot area and axis lines
8202
- clip = mathFloor(options.lineWidth / 2) * 2;
8203
- if (options.offset) {
8204
- clip = mathMax(0, clip - options.offset);
8205
- }
8212
+ clip = options.offset ? 0 : mathFloor(options.lineWidth / 2) * 2; // #4308, #4371
8206
8213
  clipOffset[invertedSide] = mathMax(clipOffset[invertedSide], clip);
8207
8214
  },
8208
8215
 
@@ -8303,6 +8310,7 @@ Axis.prototype = {
8303
8310
  hasRendered = chart.hasRendered,
8304
8311
  slideInTicks = hasRendered && defined(axis.oldMin) && !isNaN(axis.oldMin),
8305
8312
  showAxis = axis.showAxis,
8313
+ globalAnimation = renderer.globalAnimation,
8306
8314
  from,
8307
8315
  to;
8308
8316
 
@@ -9114,15 +9122,15 @@ Tooltip.prototype = {
9114
9122
  ret = {},
9115
9123
  h = point.h || 0, // #4117
9116
9124
  swapped,
9117
- first = ['y', chart.chartHeight, boxHeight, point.plotY + chart.plotTop],
9118
- second = ['x', chart.chartWidth, boxWidth, point.plotX + chart.plotLeft],
9125
+ first = ['y', chart.chartHeight, boxHeight, point.plotY + chart.plotTop, chart.plotTop, chart.plotTop + chart.plotHeight],
9126
+ second = ['x', chart.chartWidth, boxWidth, point.plotX + chart.plotLeft, chart.plotLeft, chart.plotLeft + chart.plotWidth],
9119
9127
  // The far side is right or bottom
9120
9128
  preferFarSide = pick(point.ttBelow, (chart.inverted && !point.negative) || (!chart.inverted && point.negative)),
9121
9129
  /**
9122
9130
  * Handle the preferred dimension. When the preferred dimension is tooltip
9123
9131
  * on top or bottom of the point, it will look for space there.
9124
9132
  */
9125
- firstDimension = function (dim, outerSize, innerSize, point) {
9133
+ firstDimension = function (dim, outerSize, innerSize, point, min, max) {
9126
9134
  var roomLeft = innerSize < point - distance,
9127
9135
  roomRight = point + distance + innerSize < outerSize,
9128
9136
  alignedLeft = point - distance - innerSize,
@@ -9133,9 +9141,9 @@ Tooltip.prototype = {
9133
9141
  } else if (!preferFarSide && roomLeft) {
9134
9142
  ret[dim] = alignedLeft;
9135
9143
  } else if (roomLeft) {
9136
- ret[dim] = alignedLeft - h < 0 ? alignedLeft : alignedLeft - h;
9144
+ ret[dim] = mathMin(max - innerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h);
9137
9145
  } else if (roomRight) {
9138
- ret[dim] = alignedRight + h + innerSize > outerSize ? alignedRight : alignedRight + h;
9146
+ ret[dim] = mathMax(min, alignedRight + h + innerSize > outerSize ? alignedRight : alignedRight + h);
9139
9147
  } else {
9140
9148
  return false;
9141
9149
  }
@@ -9631,19 +9639,17 @@ Pointer.prototype = {
9631
9639
  tooltip.refresh(kdpoints, e);
9632
9640
  }
9633
9641
 
9634
- // do mouseover on all points except the closest
9642
+ // Do mouseover on all points (#3919, #3985, #4410)
9635
9643
  each(kdpoints, function (point) {
9636
- if (point !== kdpoint) {
9637
- point.onMouseOver(e);
9638
- }
9639
- });
9640
- // #3919, #3985 do mouseover on the closest point last to ensure it is the hoverpoint
9641
- ((hoverSeries && hoverSeries.directTouch && hoverPoint) || kdpoint).onMouseOver(e);
9644
+ point.onMouseOver(e, point !== ((hoverSeries && hoverSeries.directTouch && hoverPoint) || kdpoint));
9645
+ });
9642
9646
  } else {
9643
9647
  if (tooltip) {
9644
9648
  tooltip.refresh(kdpoint, e);
9645
9649
  }
9646
- kdpoint.onMouseOver(e);
9650
+ if(!hoverSeries || !hoverSeries.directTouch) { // #4448
9651
+ kdpoint.onMouseOver(e);
9652
+ }
9647
9653
  }
9648
9654
  this.prevKDPoint = kdpoint;
9649
9655
 
@@ -9805,10 +9811,17 @@ Pointer.prototype = {
9805
9811
  plotHeight = chart.plotHeight,
9806
9812
  clickedInside,
9807
9813
  size,
9814
+ selectionMarker = this.selectionMarker,
9808
9815
  mouseDownX = this.mouseDownX,
9809
9816
  mouseDownY = this.mouseDownY,
9810
9817
  panKey = chartOptions.panKey && e[chartOptions.panKey + 'Key'];
9811
9818
 
9819
+ // If the device supports both touch and mouse (like IE11), and we are touch-dragging
9820
+ // inside the plot area, don't handle the mouse event. #4339.
9821
+ if (selectionMarker && selectionMarker.touch) {
9822
+ return;
9823
+ }
9824
+
9812
9825
  // If the mouse is outside the plot area, adjust to cooordinates
9813
9826
  // inside to prevent the selection marker from going outside
9814
9827
  if (chartX < plotLeft) {
@@ -9834,8 +9847,8 @@ Pointer.prototype = {
9834
9847
 
9835
9848
  // make a selection
9836
9849
  if (chart.hasCartesianSeries && (this.zoomX || this.zoomY) && clickedInside && !panKey) {
9837
- if (!this.selectionMarker) {
9838
- this.selectionMarker = chart.renderer.rect(
9850
+ if (!selectionMarker) {
9851
+ this.selectionMarker = selectionMarker = chart.renderer.rect(
9839
9852
  plotLeft,
9840
9853
  plotTop,
9841
9854
  zoomHor ? 1 : plotWidth,
@@ -9851,24 +9864,24 @@ Pointer.prototype = {
9851
9864
  }
9852
9865
 
9853
9866
  // adjust the width of the selection marker
9854
- if (this.selectionMarker && zoomHor) {
9867
+ if (selectionMarker && zoomHor) {
9855
9868
  size = chartX - mouseDownX;
9856
- this.selectionMarker.attr({
9869
+ selectionMarker.attr({
9857
9870
  width: mathAbs(size),
9858
9871
  x: (size > 0 ? 0 : size) + mouseDownX
9859
9872
  });
9860
9873
  }
9861
9874
  // adjust the height of the selection marker
9862
- if (this.selectionMarker && zoomVert) {
9875
+ if (selectionMarker && zoomVert) {
9863
9876
  size = chartY - mouseDownY;
9864
- this.selectionMarker.attr({
9877
+ selectionMarker.attr({
9865
9878
  height: mathAbs(size),
9866
9879
  y: (size > 0 ? 0 : size) + mouseDownY
9867
9880
  });
9868
9881
  }
9869
9882
 
9870
9883
  // panning
9871
- if (clickedInside && !this.selectionMarker && chartOptions.panning) {
9884
+ if (clickedInside && !selectionMarker && chartOptions.panning) {
9872
9885
  chart.pan(e, chartOptions.panning);
9873
9886
  }
9874
9887
  }
@@ -10294,7 +10307,8 @@ extend(Highcharts.Pointer.prototype, {
10294
10307
  // Set the marker
10295
10308
  if (!selectionMarker) {
10296
10309
  self.selectionMarker = selectionMarker = extend({
10297
- destroy: noop
10310
+ destroy: noop,
10311
+ touch: true
10298
10312
  }, chart.plotBox);
10299
10313
  }
10300
10314
 
@@ -10829,7 +10843,7 @@ Legend.prototype = {
10829
10843
  var chart = this.chart,
10830
10844
  options = this.options,
10831
10845
  // Use the first letter of each alignment option in order to detect the side
10832
- alignment = options.align[0] + options.verticalAlign[0] + options.layout[0];
10846
+ alignment = options.align.charAt(0) + options.verticalAlign.charAt(0) + options.layout.charAt(0); // #4189 - use charAt(x) notation instead of [x] for IE7
10833
10847
 
10834
10848
  if (this.display && !options.floating) {
10835
10849
 
@@ -11517,16 +11531,16 @@ Chart.prototype = {
11517
11531
 
11518
11532
  // redraw axes
11519
11533
  each(axes, function (axis) {
11520
-
11534
+
11521
11535
  // Fire 'afterSetExtremes' only if extremes are set
11522
- if (axis.isDirtyExtremes) { // #821
11523
- axis.isDirtyExtremes = false;
11536
+ var key = axis.min + ',' + axis.max;
11537
+ if (axis.extKey !== key) { // #821, #4452
11538
+ axis.extKey = key;
11524
11539
  afterRedraw.push(function () { // prevent a recursive call to chart.redraw() (#1119)
11525
11540
  fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751
11526
11541
  delete axis.eventArgs;
11527
11542
  });
11528
11543
  }
11529
-
11530
11544
  if (isDirtyBox || hasStackedSeries) {
11531
11545
  axis.redraw();
11532
11546
  }
@@ -11659,26 +11673,6 @@ Chart.prototype = {
11659
11673
  });
11660
11674
  },
11661
11675
 
11662
- /**
11663
- * Generate stacks for each series and calculate stacks total values
11664
- */
11665
- getStacks: function () {
11666
- var chart = this;
11667
-
11668
- // reset stacks for each yAxis
11669
- each(chart.yAxis, function (axis) {
11670
- if (axis.stacks && axis.hasVisibleSeries) {
11671
- axis.oldStacks = axis.stacks;
11672
- }
11673
- });
11674
-
11675
- each(chart.series, function (series) {
11676
- if (series.options.stacking && (series.visible === true || chart.options.chart.ignoreHiddenSeries === false)) {
11677
- series.stackKey = series.type + pick(series.options.stack, '');
11678
- }
11679
- });
11680
- },
11681
-
11682
11676
  /**
11683
11677
  * Show the title and subtitle of the chart
11684
11678
  *
@@ -12047,7 +12041,9 @@ Chart.prototype = {
12047
12041
  var chart = this,
12048
12042
  chartWidth,
12049
12043
  chartHeight,
12050
- fireEndResize;
12044
+ fireEndResize,
12045
+ renderer = chart.renderer,
12046
+ globalAnimation = renderer.globalAnimation;
12051
12047
 
12052
12048
  // Handle the isResizing counter
12053
12049
  chart.isResizing += 1;
@@ -12079,7 +12075,7 @@ Chart.prototype = {
12079
12075
  }, globalAnimation);
12080
12076
 
12081
12077
  chart.setChartSize(true);
12082
- chart.renderer.setSize(chartWidth, chartHeight, animation);
12078
+ renderer.setSize(chartWidth, chartHeight, animation);
12083
12079
 
12084
12080
  // handle axes
12085
12081
  chart.maxTicks = null;
@@ -12366,6 +12362,7 @@ Chart.prototype = {
12366
12362
  if (linkedTo) {
12367
12363
  linkedTo.linkedSeries.push(series);
12368
12364
  series.linkedParent = linkedTo;
12365
+ series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879
12369
12366
  }
12370
12367
  }
12371
12368
  });
@@ -12430,7 +12427,10 @@ Chart.prototype = {
12430
12427
  // Legend
12431
12428
  chart.legend = new Legend(chart, options.legend);
12432
12429
 
12433
- chart.getStacks(); // render stacks
12430
+ // Get stacks
12431
+ if (chart.getStacks) {
12432
+ chart.getStacks();
12433
+ }
12434
12434
 
12435
12435
  // Get chart margins
12436
12436
  chart.getMargins(true);
@@ -12895,15 +12895,15 @@ Point.prototype = {
12895
12895
  * Return the configuration hash needed for the data label and tooltip formatters
12896
12896
  */
12897
12897
  getLabelConfig: function () {
12898
- var point = this;
12899
12898
  return {
12900
- x: point.category,
12901
- y: point.y,
12902
- key: point.name || point.category,
12903
- series: point.series,
12904
- point: point,
12905
- percentage: point.percentage,
12906
- total: point.total || point.stackTotal
12899
+ x: this.category,
12900
+ y: this.y,
12901
+ color: this.color,
12902
+ key: this.name || this.category,
12903
+ series: this.series,
12904
+ point: this,
12905
+ percentage: this.percentage,
12906
+ total: this.total || this.stackTotal
12907
12907
  };
12908
12908
  },
12909
12909
 
@@ -13296,7 +13296,9 @@ Series.prototype = {
13296
13296
  * Get the series' color
13297
13297
  */
13298
13298
  getColor: function () {
13299
- if (!this.options.colorByPoint) {
13299
+ if (this.options.colorByPoint) {
13300
+ this.options.color = null; // #4359, selected slice got series.color even when colorByPoint was set.
13301
+ } else {
13300
13302
  this.getCyclic('color', this.options.color || defaultPlotOptions[this.type].color, this.chart.options.colors);
13301
13303
  }
13302
13304
  },
@@ -13412,7 +13414,7 @@ Series.prototype = {
13412
13414
  pt = { series: series };
13413
13415
  series.pointClass.prototype.applyOptions.apply(pt, [data[i]]);
13414
13416
  series.updateParallelArrays(pt, i);
13415
- if (hasCategories && pt.name) {
13417
+ if (hasCategories && defined(pt.name)) { // #4401
13416
13418
  xAxis.names[pt.x] = pt.name; // #2046
13417
13419
  }
13418
13420
  }
@@ -14028,6 +14030,8 @@ Series.prototype = {
14028
14030
  },
14029
14031
  points = series.points || [], // #927
14030
14032
  i,
14033
+ j,
14034
+ threshold,
14031
14035
  point,
14032
14036
  seriesPointAttr = [],
14033
14037
  pointAttr,
@@ -14087,13 +14091,15 @@ Series.prototype = {
14087
14091
  }
14088
14092
 
14089
14093
  if (zones.length) {
14090
- var j = 0,
14091
- threshold = zones[j];
14094
+ j = 0;
14095
+ threshold = zones[j];
14092
14096
  while (point[zoneAxis] >= threshold.value) {
14093
14097
  threshold = zones[++j];
14094
14098
  }
14095
14099
 
14096
- point.color = point.fillColor = threshold.color;
14100
+ if (threshold.color) {
14101
+ point.color = point.fillColor = threshold.color;
14102
+ }
14097
14103
  }
14098
14104
 
14099
14105
  hasPointSpecificOptions = seriesOptions.colorByPoint || point.color; // #868
@@ -14349,7 +14355,6 @@ Series.prototype = {
14349
14355
  attribs;
14350
14356
 
14351
14357
  if (graph) {
14352
- stop(graph); // cancel running animations, #459
14353
14358
  graph.animate({ d: graphPath });
14354
14359
 
14355
14360
  } else if ((lineWidth || fillColor) && graphPath.length) { // #1487
@@ -14388,8 +14393,7 @@ Series.prototype = {
14388
14393
  graph = this.graph,
14389
14394
  area = this.area,
14390
14395
  chartSizeMax = mathMax(chart.chartWidth, chart.chartHeight),
14391
- zoneAxis = this.zoneAxis || 'y',
14392
- axis = this[zoneAxis + 'Axis'],
14396
+ axis = this[(this.zoneAxis || 'y') + 'Axis'],
14393
14397
  extremes,
14394
14398
  reversed = axis.reversed,
14395
14399
  inverted = chart.inverted,
@@ -14399,7 +14403,7 @@ Series.prototype = {
14399
14403
  pxPosMax,
14400
14404
  ignoreZones = false;
14401
14405
 
14402
- if (zones.length && (graph || area)) {
14406
+ if (zones.length && (graph || area) && axis.min !== UNDEFINED) {
14403
14407
  // The use of the Color Threshold assumes there are no gaps
14404
14408
  // so it is safe to hide the original graph and area
14405
14409
  if (graph) {
@@ -14762,7 +14766,7 @@ Series.prototype = {
14762
14766
 
14763
14767
  // Start the recursive build process with a clone of the points array and null points filtered out (#3873)
14764
14768
  function startRecursive() {
14765
- var points = grep(series.points, function (point) {
14769
+ var points = grep(series.points || [], function (point) { // #4390
14766
14770
  return point.y !== null;
14767
14771
  });
14768
14772
 
@@ -14944,6 +14948,26 @@ StackItem.prototype = {
14944
14948
  }
14945
14949
  };
14946
14950
 
14951
+ /**
14952
+ * Generate stacks for each series and calculate stacks total values
14953
+ */
14954
+ Chart.prototype.getStacks = function () {
14955
+ var chart = this;
14956
+
14957
+ // reset stacks for each yAxis
14958
+ each(chart.yAxis, function (axis) {
14959
+ if (axis.stacks && axis.hasVisibleSeries) {
14960
+ axis.oldStacks = axis.stacks;
14961
+ }
14962
+ });
14963
+
14964
+ each(chart.series, function (series) {
14965
+ if (series.options.stacking && (series.visible === true || chart.options.chart.ignoreHiddenSeries === false)) {
14966
+ series.stackKey = series.type + pick(series.options.stack, '');
14967
+ }
14968
+ });
14969
+ };
14970
+
14947
14971
 
14948
14972
  // Stacking methods defined on the Axis prototype
14949
14973
 
@@ -15002,6 +15026,49 @@ Axis.prototype.renderStackTotals = function () {
15002
15026
  }
15003
15027
  };
15004
15028
 
15029
+ /**
15030
+ * Set all the stacks to initial states and destroy unused ones.
15031
+ */
15032
+ Axis.prototype.resetStacks = function () {
15033
+ var stacks = this.stacks,
15034
+ type,
15035
+ i;
15036
+ if (!this.isXAxis) {
15037
+ for (type in stacks) {
15038
+ for (i in stacks[type]) {
15039
+
15040
+ // Clean up memory after point deletion (#1044, #4320)
15041
+ if (stacks[type][i].touched < this.stacksTouched) {
15042
+ stacks[type][i].destroy();
15043
+ delete stacks[type][i];
15044
+
15045
+ // Reset stacks
15046
+ } else {
15047
+ stacks[type][i].total = null;
15048
+ stacks[type][i].cum = 0;
15049
+ }
15050
+ }
15051
+ }
15052
+ }
15053
+ };
15054
+
15055
+ Axis.prototype.cleanStacks = function () {
15056
+ var stacks, type, i;
15057
+
15058
+ if (!this.isXAxis) {
15059
+ if (this.oldStacks) {
15060
+ stacks = this.stacks = this.oldStacks;
15061
+ }
15062
+
15063
+ // reset stacks
15064
+ for (type in stacks) {
15065
+ for (i in stacks[type]) {
15066
+ stacks[type][i].cum = stacks[type][i].total;
15067
+ }
15068
+ }
15069
+ }
15070
+ };
15071
+
15005
15072
 
15006
15073
  // Stacking methods defnied for Series prototype
15007
15074
 
@@ -15038,6 +15105,9 @@ Series.prototype.setStackedPoints = function () {
15038
15105
  x,
15039
15106
  y;
15040
15107
 
15108
+
15109
+ yAxis.stacksTouched += 1;
15110
+
15041
15111
  // loop over the non-null y values and read them into a local array
15042
15112
  for (i = 0; i < yDataLength; i++) {
15043
15113
  x = xData[i];
@@ -15068,7 +15138,7 @@ Series.prototype.setStackedPoints = function () {
15068
15138
  stack = stacks[key][x];
15069
15139
  //stack.points[pointKey] = [stack.cum || stackThreshold];
15070
15140
  stack.points[pointKey] = [pick(stack.cum, stackThreshold)];
15071
-
15141
+ stack.touched = yAxis.stacksTouched;
15072
15142
 
15073
15143
 
15074
15144
  // Add value to the stack total
@@ -15306,11 +15376,9 @@ extend(Point.prototype, {
15306
15376
  if (isObject(options) && !isArray(options)) {
15307
15377
  // Defer the actual redraw until getAttribs has been called (#3260)
15308
15378
  point.redraw = function () {
15309
- if (graphic) {
15379
+ if (graphic && graphic.element) {
15310
15380
  if (options && options.marker && options.marker.symbol) {
15311
15381
  point.graphic = graphic.destroy();
15312
- } else {
15313
- graphic.attr(point.pointAttr[point.state || ''])[point.visible === false ? 'hide' : 'show'](); // #2430
15314
15382
  }
15315
15383
  }
15316
15384
  if (options && options.dataLabels && point.dataLabel) { // #2468
@@ -16157,10 +16225,11 @@ var ColumnSeries = extendClass(Series, {
16157
16225
  groupPadding = categoryWidth * options.groupPadding,
16158
16226
  groupWidth = categoryWidth - 2 * groupPadding,
16159
16227
  pointOffsetWidth = groupWidth / columnCount,
16160
- optionPointWidth = options.pointWidth,
16161
- pointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 :
16162
- pointOffsetWidth * options.pointPadding,
16163
- pointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), // exact point width, used in polar charts
16228
+ pointWidth = mathMin(
16229
+ options.maxPointWidth || xAxis.len,
16230
+ pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))
16231
+ ),
16232
+ pointPadding = (pointOffsetWidth - pointWidth) / 2,
16164
16233
  colIndex = (reversedXAxis ?
16165
16234
  columnCount - (series.columnIndex || 0) : // #1251
16166
16235
  series.columnIndex) || 0,
@@ -16415,7 +16484,7 @@ defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
16415
16484
  enabled: true // Overrides auto-enabling in line series (#3647)
16416
16485
  },
16417
16486
  tooltip: {
16418
- headerFormat: '<span style="color:{series.color}">\u25CF</span> <span style="font-size: 10px;"> {series.name}</span><br/>',
16487
+ headerFormat: '<span style="color:{point.color}">\u25CF</span> <span style="font-size: 10px;"> {series.name}</span><br/>',
16419
16488
  pointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>'
16420
16489
  }
16421
16490
  });
@@ -16457,7 +16526,7 @@ defaultPlotOptions.pie = merge(defaultSeriesOptions, {
16457
16526
  distance: 30,
16458
16527
  enabled: true,
16459
16528
  formatter: function () { // #2945
16460
- return this.point.name;
16529
+ return this.y === null ? undefined : this.point.name;
16461
16530
  },
16462
16531
  // softConnector: true,
16463
16532
  x: 0
@@ -16621,11 +16690,6 @@ var PieSeries = {
16621
16690
  fill: 'color'
16622
16691
  },
16623
16692
 
16624
- /**
16625
- * Pies have one color each point
16626
- */
16627
- getColor: noop,
16628
-
16629
16693
  /**
16630
16694
  * Animate the pies in
16631
16695
  */
@@ -16844,47 +16908,48 @@ var PieSeries = {
16844
16908
 
16845
16909
  // draw the slices
16846
16910
  each(series.points, function (point) {
16847
- graphic = point.graphic;
16848
- shapeArgs = point.shapeArgs;
16849
- shadowGroup = point.shadowGroup;
16850
-
16851
- // put the shadow behind all points
16852
- if (shadow && !shadowGroup) {
16853
- shadowGroup = point.shadowGroup = renderer.g('shadow')
16854
- .add(series.shadowGroup);
16855
- }
16911
+ if (point.y !== null) {
16912
+ graphic = point.graphic;
16913
+ shapeArgs = point.shapeArgs;
16914
+ shadowGroup = point.shadowGroup;
16856
16915
 
16857
- // if the point is sliced, use special translation, else use plot area traslation
16858
- groupTranslation = point.sliced ? point.slicedTranslation : {
16859
- translateX: 0,
16860
- translateY: 0
16861
- };
16916
+ // put the shadow behind all points
16917
+ if (shadow && !shadowGroup) {
16918
+ shadowGroup = point.shadowGroup = renderer.g('shadow')
16919
+ .add(series.shadowGroup);
16920
+ }
16862
16921
 
16863
- //group.translate(groupTranslation[0], groupTranslation[1]);
16864
- if (shadowGroup) {
16865
- shadowGroup.attr(groupTranslation);
16866
- }
16922
+ // if the point is sliced, use special translation, else use plot area traslation
16923
+ groupTranslation = point.sliced ? point.slicedTranslation : {
16924
+ translateX: 0,
16925
+ translateY: 0
16926
+ };
16867
16927
 
16868
- // draw the slice
16869
- if (graphic) {
16870
- graphic.animate(extend(shapeArgs, groupTranslation));
16871
- } else {
16872
- attr = { 'stroke-linejoin': 'round' };
16873
- if (!point.visible) {
16874
- attr.visibility = 'hidden';
16928
+ //group.translate(groupTranslation[0], groupTranslation[1]);
16929
+ if (shadowGroup) {
16930
+ shadowGroup.attr(groupTranslation);
16875
16931
  }
16876
16932
 
16877
- point.graphic = graphic = renderer[point.shapeType](shapeArgs)
16878
- .setRadialReference(series.center)
16879
- .attr(
16880
- point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]
16881
- )
16882
- .attr(attr)
16883
- .attr(groupTranslation)
16884
- .add(series.group)
16885
- .shadow(shadow, shadowGroup);
16886
- }
16933
+ // draw the slice
16934
+ if (graphic) {
16935
+ graphic.animate(extend(shapeArgs, groupTranslation));
16936
+ } else {
16937
+ attr = { 'stroke-linejoin': 'round' };
16938
+ if (!point.visible) {
16939
+ attr.visibility = 'hidden';
16940
+ }
16887
16941
 
16942
+ point.graphic = graphic = renderer[point.shapeType](shapeArgs)
16943
+ .setRadialReference(series.center)
16944
+ .attr(
16945
+ point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]
16946
+ )
16947
+ .attr(attr)
16948
+ .attr(groupTranslation)
16949
+ .add(series.group)
16950
+ .shadow(shadow, shadowGroup);
16951
+ }
16952
+ }
16888
16953
  });
16889
16954
 
16890
16955
  },
@@ -17680,7 +17745,7 @@ if (seriesTypes.column) {
17680
17745
 
17681
17746
 
17682
17747
  /**
17683
- * Highcharts JS v4.1.7 (2015-06-26)
17748
+ * Highcharts JS v4.1.8 (2015-08-20)
17684
17749
  * Highcharts module to hide overlapping data labels. This module is included by default in Highmaps.
17685
17750
  *
17686
17751
  * (c) 2010-2014 Torstein Honsi
@@ -17702,13 +17767,16 @@ if (seriesTypes.column) {
17702
17767
  var labels = [];
17703
17768
 
17704
17769
  each(chart.series, function (series) {
17705
- var dlOptions = series.options.dataLabels;
17770
+ var dlOptions = series.options.dataLabels,
17771
+ collections = series.dataLabelCollections || ['dataLabel']; // Range series have two collections
17706
17772
  if ((dlOptions.enabled || series._hasPointLabels) && !dlOptions.allowOverlap && series.visible) { // #3866
17707
- each(series.points, function (point) {
17708
- if (point.dataLabel) {
17709
- point.dataLabel.labelrank = pick(point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118
17710
- labels.push(point.dataLabel);
17711
- }
17773
+ each(collections, function (coll) {
17774
+ each(series.points, function (point) {
17775
+ if (point[coll]) {
17776
+ point[coll].labelrank = pick(point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118
17777
+ labels.push(point[coll]);
17778
+ }
17779
+ });
17712
17780
  });
17713
17781
  }
17714
17782
  });
@@ -17735,12 +17803,16 @@ if (seriesTypes.column) {
17735
17803
  j,
17736
17804
  label1,
17737
17805
  label2,
17738
- intersectRect = function (pos1, pos2, size1, size2) {
17806
+ isIntersecting,
17807
+ pos1,
17808
+ pos2,
17809
+ padding,
17810
+ intersectRect = function (x1, y1, w1, h1, x2, y2, w2, h2) {
17739
17811
  return !(
17740
- pos2.x > pos1.x + size1.width ||
17741
- pos2.x + size2.width < pos1.x ||
17742
- pos2.y > pos1.y + size1.height ||
17743
- pos2.y + size2.height < pos1.y
17812
+ x2 > x1 + w1 ||
17813
+ x2 + w2 < x1 ||
17814
+ y2 > y1 + h1 ||
17815
+ y2 + h2 < y1
17744
17816
  );
17745
17817
  };
17746
17818
 
@@ -17757,7 +17829,7 @@ if (seriesTypes.column) {
17757
17829
  // will hide the previous one because the previous one always has
17758
17830
  // lower rank.
17759
17831
  labels.sort(function (a, b) {
17760
- return b.labelrank - a.labelrank;
17832
+ return (b.labelrank || 0) - (a.labelrank || 0);
17761
17833
  });
17762
17834
 
17763
17835
  // Detect overlapping labels
@@ -17766,24 +17838,55 @@ if (seriesTypes.column) {
17766
17838
 
17767
17839
  for (j = i + 1; j < len; ++j) {
17768
17840
  label2 = labels[j];
17769
- if (label1 && label2 && label1.placed && label2.placed && label1.newOpacity !== 0 && label2.newOpacity !== 0 &&
17770
- intersectRect(label1.alignAttr, label2.alignAttr, label1, label2)) {
17771
- (label1.labelrank < label2.labelrank ? label1 : label2).newOpacity = 0;
17841
+ if (label1 && label2 && label1.placed && label2.placed && label1.newOpacity !== 0 && label2.newOpacity !== 0) {
17842
+ pos1 = label1.alignAttr;
17843
+ pos2 = label2.alignAttr;
17844
+ padding = 2 * (label1.box ? 0 : label1.padding); // Substract the padding if no background or border (#4333)
17845
+ isIntersecting = intersectRect(
17846
+ pos1.x,
17847
+ pos1.y,
17848
+ label1.width - padding,
17849
+ label1.height - padding,
17850
+ pos2.x,
17851
+ pos2.y,
17852
+ label2.width - padding,
17853
+ label2.height - padding
17854
+ );
17855
+
17856
+ if (isIntersecting) {
17857
+ (label1.labelrank < label2.labelrank ? label1 : label2).newOpacity = 0;
17858
+ }
17772
17859
  }
17773
17860
  }
17774
17861
  }
17775
17862
 
17776
17863
  // Hide or show
17777
- for (i = 0; i < len; i++) {
17778
- label = labels[i];
17864
+ each(labels, function (label) {
17865
+ var complete,
17866
+ newOpacity;
17867
+
17779
17868
  if (label) {
17780
- if (label.oldOpacity !== label.newOpacity && label.placed) {
17781
- label.alignAttr.opacity = label.newOpacity;
17782
- label[label.isOld && label.newOpacity ? 'animate' : 'attr'](label.alignAttr);
17869
+ newOpacity = label.newOpacity;
17870
+
17871
+ if (label.oldOpacity !== newOpacity && label.placed) {
17872
+
17873
+ // Make sure the label is completely hidden to avoid catching clicks (#4362)
17874
+ if (newOpacity) {
17875
+ label.show(true);
17876
+ } else {
17877
+ complete = function () {
17878
+ label.hide();
17879
+ };
17880
+ }
17881
+
17882
+ // Animate or set the opacity
17883
+ label.alignAttr.opacity = newOpacity;
17884
+ label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete);
17885
+
17783
17886
  }
17784
17887
  label.isOld = true;
17785
17888
  }
17786
- }
17889
+ });
17787
17890
  };
17788
17891
 
17789
17892
  }(Highcharts));/**
@@ -18187,8 +18290,12 @@ extend(Point.prototype, {
18187
18290
 
18188
18291
  /**
18189
18292
  * Runs on mouse over the point
18293
+ *
18294
+ * @param {Object} e The event arguments
18295
+ * @param {Boolean} byProximity Falsy for kd points that are closest to the mouse, or to
18296
+ * actually hovered points. True for other points in shared tooltip.
18190
18297
  */
18191
- onMouseOver: function (e) {
18298
+ onMouseOver: function (e, byProximity) {
18192
18299
  var point = this,
18193
18300
  series = point.series,
18194
18301
  chart = series.chart,
@@ -18216,7 +18323,9 @@ extend(Point.prototype, {
18216
18323
 
18217
18324
  // hover this
18218
18325
  point.setState(HOVER_STATE);
18219
- chart.hoverPoint = point;
18326
+ if (!byProximity) {
18327
+ chart.hoverPoint = point;
18328
+ }
18220
18329
  }
18221
18330
  },
18222
18331