highcharts-js-rails 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## v0.1.6 (2012-05-16) ##
2
+
3
+ * Update Highcharts to 2.2.3.
4
+
1
5
  ## v0.1.5 (2012-04-30) ##
2
6
 
3
7
  * Update Highcharts to 2.2.2.
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'highcharts-js-rails'
6
- s.version = '0.1.5'
6
+ s.version = '0.1.6'
7
7
  s.authors = ['Alex Robbin']
8
8
  s.email = ['agrobbin@gmail.com']
9
9
  s.homepage = 'https://github.com/agrobbin/highcharts-js-rails'
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license @product.name@ JS v@product.version@ (@product.date@)
2
+ * @license Highcharts JS v2.2.3 (2012-05-07)
3
3
  * MooTools adapter
4
4
  *
5
5
  * (c) 2010-2011 Torstein Hønsi
@@ -284,7 +284,7 @@ win.HighchartsAdapter = {
284
284
  defaultFunction(event);
285
285
  }
286
286
  },
287
-
287
+
288
288
  /**
289
289
  * Set back e.pageX and e.pageY that MooTools has abstracted away
290
290
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license @product.name@ JS v@product.version@ (@product.date@)
2
+ * @license Highcharts JS v2.2.3 (2012-05-07)
3
3
  * Prototype adapter
4
4
  *
5
5
  * @author Michael Nelson, Torstein Hønsi.
@@ -84,13 +84,13 @@ return {
84
84
 
85
85
  if (element.attr) { // SVGElement
86
86
  element.attr(this.options.attribute, position);
87
-
87
+
88
88
  } else { // HTML, #409
89
89
  obj = {};
90
90
  obj[this.options.attribute] = position;
91
91
  $(element).setStyle(obj);
92
92
  }
93
-
93
+
94
94
  },
95
95
  finish: function () {
96
96
  // Delete the property that holds this animation now that it is finished.
@@ -229,7 +229,7 @@ return {
229
229
  el._highcharts_stop_observing(event, handler);
230
230
  }
231
231
  },
232
-
232
+
233
233
  washMouseEvent: function (e) {
234
234
  return e;
235
235
  },
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v2.2.2 (2012-04-26)
5
+ * @license Highcharts JS v2.2.3 (2012-05-07)
6
6
  *
7
7
  * (c) 2009-2011 Torstein Hønsi
8
8
  *
@@ -498,10 +498,10 @@ function normalizeTickInterval(interval, multiples, magnitude, options) {
498
498
 
499
499
  /**
500
500
  * Get a normalized tick interval for dates. Returns a configuration object with
501
- * unit range (interval), count and name. Used to prepare data for getTimeTicks.
501
+ * unit range (interval), count and name. Used to prepare data for getTimeTicks.
502
502
  * Previously this logic was part of getTimeTicks, but as getTimeTicks now runs
503
- * of segments in stock charts, the normalizing logic was extracted in order to
504
- * prevent it for running over again for each segment having the same interval.
503
+ * of segments in stock charts, the normalizing logic was extracted in order to
504
+ * prevent it for running over again for each segment having the same interval.
505
505
  * #662, #697.
506
506
  */
507
507
  function normalizeTimeTickInterval(tickInterval, unitsOption) {
@@ -535,7 +535,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
535
535
  multiples = unit[1],
536
536
  count,
537
537
  i;
538
-
538
+
539
539
  // loop through the units to find the one that best fits the tickInterval
540
540
  for (i = 0; i < units.length; i++) {
541
541
  unit = units[i];
@@ -559,7 +559,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
559
559
  if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {
560
560
  multiples = [1, 2, 5];
561
561
  }
562
-
562
+
563
563
  // prevent 2.5 years intervals, though 25, 250 etc. are allowed
564
564
  if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {
565
565
  multiples = [1, 2, 5];
@@ -567,7 +567,7 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) {
567
567
 
568
568
  // get the count
569
569
  count = normalizeTickInterval(tickInterval / interval, multiples);
570
-
570
+
571
571
  return {
572
572
  unitRange: interval,
573
573
  count: count,
@@ -596,7 +596,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
596
596
  interval = normalizedInterval.unitRange,
597
597
  count = normalizedInterval.count;
598
598
 
599
-
599
+
600
600
 
601
601
  if (interval >= timeUnits[SECOND]) { // second
602
602
  minDate.setMilliseconds(0);
@@ -666,7 +666,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
666
666
  // else, the interval is fixed and we use simple addition
667
667
  } else {
668
668
  time += interval * count;
669
-
669
+
670
670
  // mark new days if the time is dividable by day
671
671
  if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === 0) {
672
672
  higherRanks[time] = DAY;
@@ -675,7 +675,7 @@ function getTimeTicks(normalizedInterval, min, max, startOfWeek) {
675
675
 
676
676
  i++;
677
677
  }
678
-
678
+
679
679
  // push the last time
680
680
  tickPositions.push(time);
681
681
 
@@ -721,7 +721,7 @@ ChartCounters.prototype = {
721
721
  * and not covering the point it self.
722
722
  */
723
723
  function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point, distance, preferRight) {
724
-
724
+
725
725
  // keep the box within the chart area
726
726
  var pointX = point.x,
727
727
  pointY = point.y,
@@ -750,14 +750,14 @@ function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHei
750
750
  if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) {
751
751
  y = pointY + outerTop + distance; // below
752
752
  }
753
- }
753
+ }
754
754
 
755
755
  // Now if the tooltip is below the chart, move it up. It's better to cover the
756
756
  // point than to disappear outside the chart. #834.
757
757
  if (y + boxHeight > outerTop + outerHeight) {
758
758
  y = outerTop + outerHeight - boxHeight - distance; // below
759
759
  }
760
-
760
+
761
761
 
762
762
  return {x: x, y: y};
763
763
  }
@@ -859,7 +859,7 @@ function discardElement(element) {
859
859
  }
860
860
 
861
861
  /**
862
- * Provide error messages for debugging, with links to online explanation
862
+ * Provide error messages for debugging, with links to online explanation
863
863
  */
864
864
  function error(code, stop) {
865
865
  var msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code;
@@ -1151,7 +1151,7 @@ if (!globalAdapter && win.jQuery) {
1151
1151
  defaultFunction(event);
1152
1152
  }
1153
1153
  };
1154
-
1154
+
1155
1155
  /**
1156
1156
  * Extension method needed for MooTools
1157
1157
  */
@@ -1284,7 +1284,7 @@ defaultOptions = {
1284
1284
  },
1285
1285
  global: {
1286
1286
  useUTC: true,
1287
- canvasToolsURL: 'http://code.highcharts.com/2.2.2/modules/canvas-tools.js'
1287
+ canvasToolsURL: 'http://code.highcharts.com/2.2.3/modules/canvas-tools.js'
1288
1288
  },
1289
1289
  chart: {
1290
1290
  //animation: true,
@@ -1432,7 +1432,7 @@ defaultOptions = {
1432
1432
  //valueDecimals: null,
1433
1433
  //xDateFormat: '%A, %b %e, %Y',
1434
1434
  //valuePrefix: '',
1435
- //ySuffix: ''
1435
+ //ySuffix: ''
1436
1436
  //}
1437
1437
  // turboThreshold: 1000
1438
1438
  // zIndex: null
@@ -1845,15 +1845,15 @@ function setTimeMethods() {
1845
1845
  * @param {Object} options The new custom options
1846
1846
  */
1847
1847
  function setOptions(options) {
1848
-
1849
- // Pull out axis options and apply them to the respective default axis options
1848
+
1849
+ // Pull out axis options and apply them to the respective default axis options
1850
1850
  defaultXAxisOptions = merge(defaultXAxisOptions, options.xAxis);
1851
1851
  defaultYAxisOptions = merge(defaultYAxisOptions, options.yAxis);
1852
1852
  options.xAxis = options.yAxis = UNDEFINED;
1853
-
1853
+
1854
1854
  // Merge in the default options
1855
1855
  defaultOptions = merge(defaultOptions, options);
1856
-
1856
+
1857
1857
  // Apply UTC
1858
1858
  setTimeMethods();
1859
1859
 
@@ -2218,14 +2218,14 @@ SVGElement.prototype = {
2218
2218
  }
2219
2219
 
2220
2220
  }
2221
-
2221
+
2222
2222
  // Workaround for our #732, WebKit's issue https://bugs.webkit.org/show_bug.cgi?id=78385
2223
2223
  // TODO: If the WebKit team fix this bug before the final release of Chrome 18, remove the workaround.
2224
2224
  if (isWebKit && /Chrome\/(18|19)/.test(userAgent)) {
2225
2225
  if (nodeName === 'text' && (hash.x !== UNDEFINED || hash.y !== UNDEFINED)) {
2226
2226
  var parent = element.parentNode,
2227
2227
  next = element.nextSibling;
2228
-
2228
+
2229
2229
  if (parent) {
2230
2230
  parent.removeChild(element);
2231
2231
  if (next) {
@@ -2237,7 +2237,7 @@ SVGElement.prototype = {
2237
2237
  }
2238
2238
  }
2239
2239
  // End of workaround for #732
2240
-
2240
+
2241
2241
  return ret;
2242
2242
  },
2243
2243
 
@@ -2696,7 +2696,7 @@ SVGElement.prototype = {
2696
2696
  // SVG elements
2697
2697
  if (element.namespaceURI === SVG_NS) {
2698
2698
  try { // Fails in Firefox if the container has display: none.
2699
-
2699
+
2700
2700
  bBox = element.getBBox ?
2701
2701
  // SVG: use extend because IE9 is not allowed to change width and height in case
2702
2702
  // of rotation (below)
@@ -2707,13 +2707,13 @@ SVGElement.prototype = {
2707
2707
  height: element.offsetHeight
2708
2708
  };
2709
2709
  } catch (e) {}
2710
-
2710
+
2711
2711
  // If the bBox is not set, the try-catch block above failed. The other condition
2712
2712
  // is for Opera that returns a width of -Infinity on hidden elements.
2713
2713
  if (!bBox || bBox.width < 0) {
2714
2714
  bBox = { width: 0, height: 0 };
2715
2715
  }
2716
-
2716
+
2717
2717
  width = bBox.width;
2718
2718
  height = bBox.height;
2719
2719
 
@@ -2969,8 +2969,8 @@ SVGRenderer.prototype = {
2969
2969
  renderer.gradients = {}; // Object where gradient SvgElements are stored
2970
2970
 
2971
2971
  renderer.setSize(width, height, false);
2972
-
2973
-
2972
+
2973
+
2974
2974
 
2975
2975
  // Issue 110 workaround:
2976
2976
  // In Firefox, if a div is positioned by percentage, its pixel position may land
@@ -2988,7 +2988,7 @@ SVGRenderer.prototype = {
2988
2988
  top: (-(rect.top - pInt(rect.top))) + PX
2989
2989
  });
2990
2990
  };
2991
-
2991
+
2992
2992
  // run the fix now
2993
2993
  subPixelFix();
2994
2994
 
@@ -3015,7 +3015,7 @@ SVGRenderer.prototype = {
3015
3015
  if (rendererDefs) {
3016
3016
  renderer.defs = rendererDefs.destroy();
3017
3017
  }
3018
-
3018
+
3019
3019
  // Remove sub pixel fix handler
3020
3020
  removeEvent(win, 'resize', renderer.subPixelFix);
3021
3021
 
@@ -3063,13 +3063,13 @@ SVGRenderer.prototype = {
3063
3063
  GET_COMPUTED_STYLE = 'getComputedStyle',
3064
3064
  i = childNodes.length,
3065
3065
  linePositions = [];
3066
-
3066
+
3067
3067
  // Needed in IE9 because it doesn't report tspan's offsetHeight (#893)
3068
3068
  function getLineHeightByBBox(lineNo) {
3069
3069
  linePositions[lineNo] = textNode.getBBox().height;
3070
3070
  return mathRound(linePositions[lineNo] - (linePositions[lineNo - 1] || 0));
3071
3071
  }
3072
-
3072
+
3073
3073
  // remove old text
3074
3074
  while (i--) {
3075
3075
  textNode.removeChild(childNodes[i]);
@@ -3535,7 +3535,7 @@ SVGRenderer.prototype = {
3535
3535
  width: size[0],
3536
3536
  height: size[1]
3537
3537
  });
3538
-
3538
+
3539
3539
  if (!img.alignByTranslate) { // #185
3540
3540
  img.translate(
3541
3541
  -mathRound(size[0] / 2),
@@ -3925,14 +3925,14 @@ SVGRenderer.prototype = {
3925
3925
  */
3926
3926
  fontMetrics: function (fontSize) {
3927
3927
  fontSize = pInt(fontSize || 11);
3928
-
3928
+
3929
3929
  // Empirical values found by comparing font size and bounding box height.
3930
3930
  // Applies to the default font family. http://jsfiddle.net/highcharts/7xvn7/
3931
3931
  var lineHeight = fontSize < 24 ? fontSize + 4 : mathRound(fontSize * 1.2),
3932
3932
  baseline = mathRound(lineHeight * 0.8);
3933
-
3933
+
3934
3934
  return {
3935
- h: lineHeight,
3935
+ h: lineHeight,
3936
3936
  b: baseline
3937
3937
  };
3938
3938
  },
@@ -3948,8 +3948,8 @@ SVGRenderer.prototype = {
3948
3948
  * coordinates it should be pinned to
3949
3949
  * @param {Number} anchorY
3950
3950
  * @param {Boolean} baseline Whether to position the label relative to the text baseline,
3951
- * like renderer.text, or to the upper border of the rectangle.
3952
- * @param {String} className Class name for the group
3951
+ * like renderer.text, or to the upper border of the rectangle.
3952
+ * @param {String} className Class name for the group
3953
3953
  */
3954
3954
  label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
3955
3955
 
@@ -3981,20 +3981,20 @@ SVGRenderer.prototype = {
3981
3981
  function updateBoxSize() {
3982
3982
  var boxY,
3983
3983
  style = text.element.style;
3984
-
3984
+
3985
3985
  bBox = (width === undefined || height === undefined || wrapper.styles.textAlign) &&
3986
3986
  text.getBBox(true);
3987
3987
  wrapper.width = (width || bBox.width || 0) + 2 * padding;
3988
3988
  wrapper.height = (height || bBox.height || 0) + 2 * padding;
3989
-
3989
+
3990
3990
  // update the label-scoped y offset
3991
3991
  baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b;
3992
-
3993
-
3992
+
3993
+
3994
3994
  // create the border box if it is not already present
3995
3995
  if (!box) {
3996
3996
  boxY = baseline ? -baselineOffset : 0;
3997
-
3997
+
3998
3998
  wrapper.box = box = shape ?
3999
3999
  renderer.symbol(shape, -alignFactor * padding, boxY, wrapper.width, wrapper.height) :
4000
4000
  renderer.rect(-alignFactor * padding, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);
@@ -4017,7 +4017,7 @@ SVGRenderer.prototype = {
4017
4017
  textAlign = styles && styles.textAlign,
4018
4018
  x = padding * (1 - alignFactor),
4019
4019
  y;
4020
-
4020
+
4021
4021
  // determin y based on the baseline
4022
4022
  y = baseline ? 0 : baselineOffset;
4023
4023
 
@@ -4095,7 +4095,7 @@ SVGRenderer.prototype = {
4095
4095
  alignFactor = { left: 0, center: 0.5, right: 1 }[value];
4096
4096
  return false; // prevent setting text-anchor on the group
4097
4097
  };
4098
-
4098
+
4099
4099
  // apply these to the box and the text alike
4100
4100
  attrSetters.text = function (value, key) {
4101
4101
  text.attr(key, value);
@@ -4124,13 +4124,13 @@ SVGRenderer.prototype = {
4124
4124
  boxAttr(key, value - wrapperY);
4125
4125
  return false;
4126
4126
  };
4127
-
4127
+
4128
4128
  // rename attributes
4129
4129
  attrSetters.x = function (value) {
4130
4130
  wrapper.x = value; // for animation getter
4131
4131
  value -= alignFactor * ((width || bBox.width) + padding);
4132
- wrapperX = mathRound(value);
4133
-
4132
+ wrapperX = mathRound(value);
4133
+
4134
4134
  wrapper.attr('translateX', wrapperX);
4135
4135
  return false;
4136
4136
  };
@@ -4301,12 +4301,12 @@ var VMLElement = {
4301
4301
  toggleChildren: function (element, visibility) {
4302
4302
  var childNodes = element.childNodes,
4303
4303
  i = childNodes.length;
4304
-
4304
+
4305
4305
  while (i--) {
4306
-
4306
+
4307
4307
  // apply the visibility
4308
4308
  css(childNodes[i], { visibility: visibility });
4309
-
4309
+
4310
4310
  // we have a nested group, apply it to its children again
4311
4311
  if (childNodes[i].nodeName === 'DIV') {
4312
4312
  this.toggleChildren(childNodes[i], visibility);
@@ -4439,9 +4439,9 @@ var VMLElement = {
4439
4439
 
4440
4440
  // width and height
4441
4441
  } else if (key === 'width' || key === 'height') {
4442
-
4442
+
4443
4443
  value = mathMax(0, value); // don't set width or height below zero (#311)
4444
-
4444
+
4445
4445
  this[key] = value; // used in getter
4446
4446
 
4447
4447
  // clipping rectangle special
@@ -4556,12 +4556,12 @@ var VMLElement = {
4556
4556
  wrapper.destroyClip = function () {
4557
4557
  erase(clipMembers, wrapper);
4558
4558
  };
4559
-
4559
+
4560
4560
  // Issue #863 workaround - related to #140, #61, #74
4561
4561
  if (element.parentNode.className === 'highcharts-tracker' && !docMode8) {
4562
4562
  css(element, { visibility: HIDDEN });
4563
4563
  }
4564
-
4564
+
4565
4565
  return wrapper.css(clipRect.getCSS(wrapper.inverted));
4566
4566
  },
4567
4567
 
@@ -4775,7 +4775,7 @@ var VMLRendererExtension = { // inherit SVGRenderer
4775
4775
  height: bottom + PX
4776
4776
  });
4777
4777
  }
4778
-
4778
+
4779
4779
  return ret;
4780
4780
  },
4781
4781
 
@@ -4842,15 +4842,15 @@ var VMLRendererExtension = { // inherit SVGRenderer
4842
4842
  (y2 - y1) / // y vector
4843
4843
  (x2 - x1) // x vector
4844
4844
  ) * 180 / mathPI;
4845
-
4846
-
4845
+
4846
+
4847
4847
  // when colors attribute is used, the meanings of opacity and o:opacity2
4848
4848
  // are reversed.
4849
4849
  markup = ['<fill colors="0% ', color1, ',100% ', color2, '" angle="', angle,
4850
4850
  '" opacity="', opacity2, '" o:opacity2="', opacity1,
4851
4851
  '" type="gradient" focus="100%" method="sigma" />'];
4852
4852
  createElement(this.prepVML(markup), null, null, elem);
4853
-
4853
+
4854
4854
  // Gradients are not supported for VML stroke, return the first color. #722.
4855
4855
  } else {
4856
4856
  return stopColor;
@@ -5245,7 +5245,7 @@ function Chart(userOptions, callback) {
5245
5245
  userOptions.series = null;
5246
5246
  options = merge(defaultOptions, userOptions); // do the merge
5247
5247
  options.series = userOptions.series = seriesOptions; // set back the series data
5248
-
5248
+
5249
5249
  var optionsChart = options.chart,
5250
5250
  optionsMargin = optionsChart.margin,
5251
5251
  margin = isObject(optionsMargin) ?
@@ -5524,7 +5524,7 @@ function Chart(userOptions, callback) {
5524
5524
  ((this.labelBBox = label.getBBox(true)))[horiz ? 'height' : 'width'] :
5525
5525
  0;
5526
5526
  },
5527
-
5527
+
5528
5528
  /**
5529
5529
  * Find how far the labels extend to the right and left of the tick's x position. Used for anti-collision
5530
5530
  * detection with overflow logic.
@@ -5534,10 +5534,10 @@ function Chart(userOptions, callback) {
5534
5534
  labelOptions = options.labels,
5535
5535
  width = bBox.width,
5536
5536
  leftSide = width * { left: 0, center: 0.5, right: 1 }[labelOptions.align] - labelOptions.x;
5537
-
5538
- return [-leftSide, width - leftSide];
5537
+
5538
+ return [-leftSide, width - leftSide];
5539
5539
  },
5540
-
5540
+
5541
5541
  /**
5542
5542
  * Handle the label overflow by adjusting the labels to the left and right edge, or
5543
5543
  * hide them if they collide into the neighbour label.
@@ -5548,9 +5548,9 @@ function Chart(userOptions, callback) {
5548
5548
  isLast = this.isLast,
5549
5549
  label = this.label,
5550
5550
  x = label.x;
5551
-
5551
+
5552
5552
  if (isFirst || isLast) {
5553
-
5553
+
5554
5554
  var sides = this.getLabelSides(),
5555
5555
  leftSide = sides[0],
5556
5556
  rightSide = sides[1],
@@ -5558,41 +5558,41 @@ function Chart(userOptions, callback) {
5558
5558
  plotRight = plotLeft + axis.len,
5559
5559
  neighbour = ticks[tickPositions[index + (isFirst ? 1 : -1)]],
5560
5560
  neighbourEdge = neighbour && neighbour.label.x + neighbour.getLabelSides()[isFirst ? 0 : 1];
5561
-
5561
+
5562
5562
  if ((isFirst && !reversed) || (isLast && reversed)) {
5563
5563
  // Is the label spilling out to the left of the plot area?
5564
5564
  if (x + leftSide < plotLeft) {
5565
-
5565
+
5566
5566
  // Align it to plot left
5567
5567
  x = plotLeft - leftSide;
5568
-
5568
+
5569
5569
  // Hide it if it now overlaps the neighbour label
5570
5570
  if (neighbour && x + rightSide > neighbourEdge) {
5571
5571
  show = false;
5572
5572
  }
5573
5573
  }
5574
-
5574
+
5575
5575
  } else {
5576
5576
  // Is the label spilling out to the right of the plot area?
5577
5577
  if (x + rightSide > plotRight) {
5578
-
5578
+
5579
5579
  // Align it to plot right
5580
5580
  x = plotRight - rightSide;
5581
-
5581
+
5582
5582
  // Hide it if it now overlaps the neighbour label
5583
5583
  if (neighbour && x + leftSide < neighbourEdge) {
5584
5584
  show = false;
5585
5585
  }
5586
-
5586
+
5587
5587
  }
5588
5588
  }
5589
-
5589
+
5590
5590
  // Set the modified x position of the label
5591
5591
  label.x = x;
5592
5592
  }
5593
5593
  return show;
5594
5594
  },
5595
-
5595
+
5596
5596
  /**
5597
5597
  * Put everything in place
5598
5598
  *
@@ -5716,7 +5716,7 @@ function Chart(userOptions, callback) {
5716
5716
  if (staggerLines) {
5717
5717
  y += (index / (step || 1) % staggerLines) * 16;
5718
5718
  }
5719
-
5719
+
5720
5720
  // Cache x and y to be able to read final position before animation
5721
5721
  label.x = x;
5722
5722
  label.y = y;
@@ -5725,9 +5725,9 @@ function Chart(userOptions, callback) {
5725
5725
  if ((tick.isFirst && !pick(options.showFirstLabel, 1)) ||
5726
5726
  (tick.isLast && !pick(options.showLastLabel, 1))) {
5727
5727
  show = false;
5728
-
5728
+
5729
5729
  // Handle label overflow and show or hide accordingly
5730
- } else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index)) {
5730
+ } else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index)) {
5731
5731
  show = false;
5732
5732
  }
5733
5733
 
@@ -5736,7 +5736,7 @@ function Chart(userOptions, callback) {
5736
5736
  // show those indices dividable by step
5737
5737
  show = false;
5738
5738
  }
5739
-
5739
+
5740
5740
  // Set the new position, and show or hide
5741
5741
  if (show) {
5742
5742
  label[tick.isNew ? 'attr' : 'animate']({
@@ -5750,9 +5750,9 @@ function Chart(userOptions, callback) {
5750
5750
  }
5751
5751
  }
5752
5752
 
5753
-
5753
+
5754
5754
  },
5755
-
5755
+
5756
5756
  /**
5757
5757
  * Destructor for the tick prototype
5758
5758
  */
@@ -6067,7 +6067,7 @@ function Chart(userOptions, callback) {
6067
6067
  yDataLength,
6068
6068
  activeYData = [],
6069
6069
  activeCounter = 0;
6070
-
6070
+
6071
6071
  // Validate threshold in logarithmic axes
6072
6072
  if (isLog && threshold <= 0) {
6073
6073
  threshold = seriesOptions.threshold = null;
@@ -6218,7 +6218,7 @@ function Chart(userOptions, callback) {
6218
6218
  *
6219
6219
  */
6220
6220
  translate = function (val, backwards, cvsCoord, old, handleLog) {
6221
-
6221
+
6222
6222
  var sign = 1,
6223
6223
  cvsOffset = 0,
6224
6224
  localA = old ? oldTransA : transA,
@@ -6333,28 +6333,28 @@ function Chart(userOptions, callback) {
6333
6333
  }
6334
6334
  return tickPositions;
6335
6335
  }
6336
-
6336
+
6337
6337
  /**
6338
6338
  * Set the tick positions of a logarithmic axis
6339
6339
  */
6340
6340
  function getLogTickPositions(interval, min, max, minor) {
6341
-
6341
+
6342
6342
  // Since we use this method for both major and minor ticks,
6343
6343
  // use a local variable and return the result
6344
- var positions = [];
6345
-
6344
+ var positions = [];
6345
+
6346
6346
  // Reset
6347
6347
  if (!minor) {
6348
6348
  axis._minorAutoInterval = null;
6349
6349
  }
6350
-
6350
+
6351
6351
  // First case: All ticks fall on whole logarithms: 1, 10, 100 etc.
6352
6352
  if (interval >= 0.5) {
6353
6353
  interval = mathRound(interval);
6354
6354
  positions = getLinearTickPositions(interval, min, max);
6355
-
6356
- // Second case: We need intermediary ticks. For example
6357
- // 1, 2, 4, 6, 8, 10, 20, 40 etc.
6355
+
6356
+ // Second case: We need intermediary ticks. For example
6357
+ // 1, 2, 4, 6, 8, 10, 20, 40 etc.
6358
6358
  } else if (interval >= 0.08) {
6359
6359
  var roundedMin = mathFloor(min),
6360
6360
  intermediate,
@@ -6364,7 +6364,7 @@ function Chart(userOptions, callback) {
6364
6364
  pos,
6365
6365
  lastPos,
6366
6366
  break2;
6367
-
6367
+
6368
6368
  if (interval > 0.3) {
6369
6369
  intermediate = [1, 2, 4];
6370
6370
  } else if (interval > 0.15) { // 0.2 equals five minor ticks per 1, 10, 100 etc
@@ -6372,23 +6372,23 @@ function Chart(userOptions, callback) {
6372
6372
  } else { // 0.1 equals ten minor ticks per 1, 10, 100 etc
6373
6373
  intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
6374
6374
  }
6375
-
6375
+
6376
6376
  for (i = roundedMin; i < max + 1 && !break2; i++) {
6377
6377
  len = intermediate.length;
6378
6378
  for (j = 0; j < len && !break2; j++) {
6379
6379
  pos = log2lin(lin2log(i) * intermediate[j]);
6380
-
6380
+
6381
6381
  if (pos > min) {
6382
6382
  positions.push(lastPos);
6383
6383
  }
6384
-
6384
+
6385
6385
  if (lastPos > max) {
6386
6386
  break2 = true;
6387
6387
  }
6388
6388
  lastPos = pos;
6389
6389
  }
6390
6390
  }
6391
-
6391
+
6392
6392
  // Third case: We are so deep in between whole logarithmic values that
6393
6393
  // we might as well handle the tick positions like a linear axis. For
6394
6394
  // example 1.01, 1.02, 1.03, 1.04.
@@ -6399,37 +6399,37 @@ function Chart(userOptions, callback) {
6399
6399
  filteredTickIntervalOption = tickIntervalOption === 'auto' ? null : tickIntervalOption,
6400
6400
  tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1),
6401
6401
  totalPixelLength = minor ? axisLength / tickPositions.length : axisLength;
6402
-
6402
+
6403
6403
  interval = pick(
6404
6404
  filteredTickIntervalOption,
6405
6405
  axis._minorAutoInterval,
6406
6406
  (realMax - realMin) * tickPixelIntervalOption / (totalPixelLength || 1)
6407
6407
  );
6408
-
6408
+
6409
6409
  interval = normalizeTickInterval(
6410
- interval,
6411
- null,
6410
+ interval,
6411
+ null,
6412
6412
  math.pow(10, mathFloor(math.log(interval) / math.LN10))
6413
6413
  );
6414
-
6414
+
6415
6415
  positions = map(getLinearTickPositions(
6416
- interval,
6416
+ interval,
6417
6417
  realMin,
6418
- realMax
6418
+ realMax
6419
6419
  ), log2lin);
6420
-
6420
+
6421
6421
  if (!minor) {
6422
6422
  axis._minorAutoInterval = interval / 5;
6423
6423
  }
6424
6424
  }
6425
-
6426
- // Set the axis-level tickInterval variable
6425
+
6426
+ // Set the axis-level tickInterval variable
6427
6427
  if (!minor) {
6428
6428
  tickInterval = interval;
6429
6429
  }
6430
6430
  return positions;
6431
6431
  }
6432
-
6432
+
6433
6433
  /**
6434
6434
  * Return the minor tick positions. For logarithmic axes, reuse the same logic
6435
6435
  * as for major ticks.
@@ -6439,27 +6439,27 @@ function Chart(userOptions, callback) {
6439
6439
  pos,
6440
6440
  i,
6441
6441
  len;
6442
-
6442
+
6443
6443
  if (isLog) {
6444
6444
  len = tickPositions.length;
6445
6445
  for (i = 1; i < len; i++) {
6446
6446
  minorTickPositions = minorTickPositions.concat(
6447
6447
  getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true)
6448
- );
6448
+ );
6449
6449
  }
6450
-
6451
- } else {
6450
+
6451
+ } else {
6452
6452
  for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) {
6453
- minorTickPositions.push(pos);
6453
+ minorTickPositions.push(pos);
6454
6454
  }
6455
6455
  }
6456
-
6456
+
6457
6457
  return minorTickPositions;
6458
6458
  }
6459
6459
 
6460
6460
  /**
6461
- * Adjust the min and max for the minimum range. Keep in mind that the series data is
6462
- * not yet processed, so we don't have information on data cropping and grouping, or
6461
+ * Adjust the min and max for the minimum range. Keep in mind that the series data is
6462
+ * not yet processed, so we don't have information on data cropping and grouping, or
6463
6463
  * updated axis.pointRange or series.pointRange. The data can't be processed until
6464
6464
  * we have finally established min and max.
6465
6465
  */
@@ -6473,10 +6473,10 @@ function Chart(userOptions, callback) {
6473
6473
  loopLength,
6474
6474
  minArgs,
6475
6475
  maxArgs;
6476
-
6476
+
6477
6477
  // Set the automatic minimum range based on the closest point distance
6478
6478
  if (isXAxis && minRange === UNDEFINED && !isLog) {
6479
-
6479
+
6480
6480
  if (defined(options.min) || defined(options.max)) {
6481
6481
  minRange = null; // don't do this again
6482
6482
 
@@ -6496,14 +6496,14 @@ function Chart(userOptions, callback) {
6496
6496
  });
6497
6497
  minRange = mathMin(closestDataRange * 5, dataMax - dataMin);
6498
6498
  }
6499
-
6499
+
6500
6500
  // A hook for resetting the minRange in series.setData (#878)
6501
6501
  // TODO: remove this in protofy, where xAxis.minRange can be set directly
6502
6502
  axis.setMinRange = function (newMinRange) {
6503
6503
  minRange = newMinRange;
6504
6504
  };
6505
6505
  }
6506
-
6506
+
6507
6507
  // if minRange is exceeded, adjust
6508
6508
  if (max - min < minRange) {
6509
6509
 
@@ -6520,7 +6520,7 @@ function Chart(userOptions, callback) {
6520
6520
  if (spaceAvailable) { // if space is availabe, stay within the data range
6521
6521
  maxArgs[2] = dataMax;
6522
6522
  }
6523
-
6523
+
6524
6524
  max = arrayMin(maxArgs);
6525
6525
 
6526
6526
  // now if the max is adjusted, adjust the min back
@@ -6604,10 +6604,10 @@ function Chart(userOptions, callback) {
6604
6604
  }
6605
6605
 
6606
6606
  // Now we're finished detecting min and max, crop and group series data. This
6607
- // is in turn needed in order to find tick positions in ordinal axes.
6607
+ // is in turn needed in order to find tick positions in ordinal axes.
6608
6608
  if (isXAxis && !secondPass) {
6609
6609
  each(axis.series, function (series) {
6610
- series.processData(min !== oldMin || max !== oldMax);
6610
+ series.processData(min !== oldMin || max !== oldMax);
6611
6611
  });
6612
6612
  }
6613
6613
 
@@ -6618,10 +6618,10 @@ function Chart(userOptions, callback) {
6618
6618
  if (axis.beforeSetTickPositions) {
6619
6619
  axis.beforeSetTickPositions();
6620
6620
  }
6621
-
6621
+
6622
6622
  // hook for extensions, used in Highstock ordinal axes
6623
6623
  if (axis.postProcessTickInterval) {
6624
- tickInterval = axis.postProcessTickInterval(tickInterval);
6624
+ tickInterval = axis.postProcessTickInterval(tickInterval);
6625
6625
  }
6626
6626
 
6627
6627
  // for linear axes, get magnitude and normalize the interval
@@ -6676,20 +6676,26 @@ function Chart(userOptions, callback) {
6676
6676
  } else if (max < roundedMax) {
6677
6677
  tickPositions.pop();
6678
6678
  }
6679
+ }
6680
+ }
6681
+
6682
+ /**
6683
+ * Set the max ticks of either the x and y axis collection. #840.
6684
+ */
6685
+ axis.setMaxTicks = function () {
6679
6686
 
6680
- // record the greatest number of ticks for multi axis
6681
- if (!maxTicks) { // first call, or maxTicks have been reset after a zoom operation
6682
- maxTicks = {
6683
- x: 0,
6684
- y: 0
6685
- };
6686
- }
6687
+ // record the greatest number of ticks for multi axis
6688
+ if (!maxTicks) { // first call, or maxTicks have been reset after a zoom operation
6689
+ maxTicks = {
6690
+ x: 0,
6691
+ y: 0
6692
+ };
6693
+ }
6687
6694
 
6688
- if (!isDatetimeAxis && tickPositions.length > maxTicks[xOrY] && options.alignTicks !== false) {
6689
- maxTicks[xOrY] = tickPositions.length;
6690
- }
6695
+ if (!isLinked && !isDatetimeAxis && tickPositions.length > maxTicks[xOrY] && options.alignTicks !== false) {
6696
+ maxTicks[xOrY] = tickPositions.length;
6691
6697
  }
6692
- }
6698
+ };
6693
6699
 
6694
6700
  /**
6695
6701
  * When using multiple axes, adjust the number of ticks to match the highest
@@ -6730,7 +6736,7 @@ function Chart(userOptions, callback) {
6730
6736
  i,
6731
6737
  isDirtyData,
6732
6738
  isDirtyAxisLength;
6733
-
6739
+
6734
6740
  oldMin = min;
6735
6741
  oldMax = max;
6736
6742
  oldAxisLength = axisLength;
@@ -6757,7 +6763,7 @@ function Chart(userOptions, callback) {
6757
6763
 
6758
6764
  // get fixed positions based on tickInterval
6759
6765
  setTickPositions();
6760
-
6766
+
6761
6767
  // record old values to decide whether a rescale is necessary later on (#540)
6762
6768
  oldUserMin = userMin;
6763
6769
  oldUserMax = userMax;
@@ -6776,6 +6782,8 @@ function Chart(userOptions, callback) {
6776
6782
  axis.isDirty = isDirtyAxisLength || min !== oldMin || max !== oldMax;
6777
6783
  }
6778
6784
  }
6785
+
6786
+ axis.setMaxTicks();
6779
6787
  }
6780
6788
 
6781
6789
  /**
@@ -6785,13 +6793,13 @@ function Chart(userOptions, callback) {
6785
6793
  * @param {Boolean} redraw
6786
6794
  * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
6787
6795
  * configuration
6788
- * @param {Object} eventArguments
6796
+ * @param {Object} eventArguments
6789
6797
  *
6790
6798
  */
6791
6799
  function setExtremes(newMin, newMax, redraw, animation, eventArguments) {
6792
6800
 
6793
6801
  redraw = pick(redraw, true); // defaults to true
6794
-
6802
+
6795
6803
  // Extend the arguments with min and max
6796
6804
  eventArguments = extend(eventArguments, {
6797
6805
  min: newMin,
@@ -6803,17 +6811,17 @@ function Chart(userOptions, callback) {
6803
6811
 
6804
6812
  userMin = newMin;
6805
6813
  userMax = newMax;
6806
-
6814
+
6807
6815
  // Mark for running afterSetExtremes
6808
6816
  axis.isDirtyExtremes = true;
6809
-
6817
+
6810
6818
  // redraw
6811
6819
  if (redraw) {
6812
6820
  chart.redraw(animation);
6813
6821
  }
6814
6822
  });
6815
6823
  }
6816
-
6824
+
6817
6825
  /**
6818
6826
  * Update translation information
6819
6827
  */
@@ -6822,7 +6830,7 @@ function Chart(userOptions, callback) {
6822
6830
  pointRange = 0,
6823
6831
  closestPointRange,
6824
6832
  seriesClosestPointRange;
6825
-
6833
+
6826
6834
  // adjust translation for padding
6827
6835
  if (isXAxis) {
6828
6836
  if (isLinked) {
@@ -6838,7 +6846,7 @@ function Chart(userOptions, callback) {
6838
6846
  }
6839
6847
  });
6840
6848
  }
6841
-
6849
+
6842
6850
  // pointRange means the width reserved for each point, like in a column chart
6843
6851
  axis.pointRange = pointRange;
6844
6852
 
@@ -6900,7 +6908,7 @@ function Chart(userOptions, callback) {
6900
6908
  function getThreshold(threshold) {
6901
6909
  var realMin = isLog ? lin2log(min) : min,
6902
6910
  realMax = isLog ? lin2log(max) : max;
6903
-
6911
+
6904
6912
  if (realMin > threshold || threshold === null) {
6905
6913
  threshold = realMin;
6906
6914
  } else if (realMax < threshold) {
@@ -7071,10 +7079,10 @@ function Chart(userOptions, callback) {
7071
7079
  // Major ticks. Pull out the first item and render it last so that
7072
7080
  // we can get the position of the neighbour label. #808.
7073
7081
  each(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) {
7074
-
7082
+
7075
7083
  // Reorganize the indices
7076
7084
  i = (i === tickPositions.length - 1) ? 0 : i + 1;
7077
-
7085
+
7078
7086
  // linked axes need an extra check to find out if
7079
7087
  if (!isLinked || (pos >= min && pos <= max)) {
7080
7088
 
@@ -7257,16 +7265,16 @@ function Chart(userOptions, callback) {
7257
7265
  }
7258
7266
  }
7259
7267
  }
7260
-
7268
+
7261
7269
  /**
7262
7270
  * Update the axis title by options
7263
7271
  */
7264
7272
  function setTitle(newTitleOptions, redraw) {
7265
7273
  options.title = merge(options.title, newTitleOptions);
7266
-
7274
+
7267
7275
  axisTitle = axisTitle.destroy();
7268
7276
  axis.isDirty = true;
7269
-
7277
+
7270
7278
  if (pick(redraw, true)) {
7271
7279
  chart.redraw();
7272
7280
  }
@@ -7486,10 +7494,10 @@ function Chart(userOptions, callback) {
7486
7494
  s.push((series.tooltipFormatter && series.tooltipFormatter(item)) ||
7487
7495
  item.point.tooltipFormatter(series.tooltipOptions.pointFormat));
7488
7496
  });
7489
-
7497
+
7490
7498
  // footer
7491
7499
  s.push(options.footerFormat || '');
7492
-
7500
+
7493
7501
  return s.join('');
7494
7502
  }
7495
7503
 
@@ -7672,7 +7680,7 @@ function Chart(userOptions, callback) {
7672
7680
  axis = point.series[i ? 'yAxis' : 'xAxis'];
7673
7681
  if (crosshairsOptions[i] && axis) {
7674
7682
  path = axis.getPlotLinePath(
7675
- i ? pick(point.stackY, point.y) : point.x, // #814
7683
+ i ? pick(point.stackY, point.y) : point.x, // #814
7676
7684
  1
7677
7685
  );
7678
7686
  if (crosshairs[i]) {
@@ -7770,7 +7778,7 @@ function Chart(userOptions, callback) {
7770
7778
  chartX = ePos.pageX - chartPosition.left;
7771
7779
  chartY = ePos.pageY - chartPosition.top;
7772
7780
  }
7773
-
7781
+
7774
7782
  return extend(e, {
7775
7783
  chartX: mathRound(chartX),
7776
7784
  chartY: mathRound(chartY)
@@ -7816,7 +7824,7 @@ function Chart(userOptions, callback) {
7816
7824
  i,
7817
7825
  j,
7818
7826
  distance = chartWidth,
7819
- // the index in the tooltipPoints array, corresponding to pixel position in plot area
7827
+ // the index in the tooltipPoints array, corresponding to pixel position in plot area
7820
7828
  index = inverted ? plotHeight + plotTop - e.chartY : e.chartX - plotLeft;
7821
7829
 
7822
7830
  // shared tooltip
@@ -7874,29 +7882,29 @@ function Chart(userOptions, callback) {
7874
7882
  var hoverSeries = chart.hoverSeries,
7875
7883
  hoverPoint = chart.hoverPoint,
7876
7884
  tooltipPoints = chart.hoverPoints || hoverPoint;
7877
-
7885
+
7878
7886
  // Just move the tooltip, #349
7879
7887
  if (allowMove && tooltip && tooltipPoints) {
7880
7888
  tooltip.refresh(tooltipPoints);
7881
-
7889
+
7882
7890
  // Full reset
7883
7891
  } else {
7884
-
7892
+
7885
7893
  if (hoverPoint) {
7886
7894
  hoverPoint.onMouseOut();
7887
7895
  }
7888
-
7896
+
7889
7897
  if (hoverSeries) {
7890
7898
  hoverSeries.onMouseOut();
7891
7899
  }
7892
-
7900
+
7893
7901
  if (tooltip) {
7894
7902
  tooltip.hide();
7895
7903
  tooltip.hideCrosshairs();
7896
7904
  }
7897
-
7905
+
7898
7906
  hoverX = null;
7899
-
7907
+
7900
7908
  }
7901
7909
  }
7902
7910
 
@@ -7959,7 +7967,7 @@ function Chart(userOptions, callback) {
7959
7967
  }
7960
7968
  selectionMarker = selectionMarker.destroy();
7961
7969
  }
7962
-
7970
+
7963
7971
  if (chart) { // it may be destroyed on mouse up - #877
7964
7972
  css(container, { cursor: 'auto' });
7965
7973
  chart.cancelClick = hasDragged; // #370
@@ -7974,9 +7982,9 @@ function Chart(userOptions, callback) {
7974
7982
  * Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea.
7975
7983
  */
7976
7984
  function hideTooltipOnMouseMove(e) {
7977
-
7985
+
7978
7986
  // Get e.pageX and e.pageY back in MooTools
7979
- washMouseEvent(e);
7987
+ washMouseEvent(e);
7980
7988
 
7981
7989
  // If we're outside, hide the tooltip
7982
7990
  if (chartPosition &&
@@ -8185,8 +8193,8 @@ function Chart(userOptions, callback) {
8185
8193
 
8186
8194
 
8187
8195
  if (!chart.cancelClick) {
8188
-
8189
- // Detect clicks on trackers or tracker groups, #783
8196
+
8197
+ // Detect clicks on trackers or tracker groups, #783
8190
8198
  if (hoverPoint && (attr(e.target, 'isTracker') || attr(e.target.parentNode, 'isTracker'))) {
8191
8199
  var plotX = hoverPoint.plotX,
8192
8200
  plotY = hoverPoint.plotY;
@@ -8236,15 +8244,15 @@ function Chart(userOptions, callback) {
8236
8244
  container.onclick = container.onmousedown = container.onmousemove = container.ontouchstart = container.ontouchend = container.ontouchmove = null;
8237
8245
  }
8238
8246
 
8239
-
8247
+
8240
8248
  // Run MouseTracker
8241
-
8249
+
8242
8250
  if (!trackerGroup) {
8243
8251
  chart.trackerGroup = trackerGroup = renderer.g('tracker')
8244
8252
  .attr({ zIndex: 9 })
8245
8253
  .add();
8246
8254
  }
8247
-
8255
+
8248
8256
  if (options.enabled) {
8249
8257
  chart.tooltip = tooltip = Tooltip(options);
8250
8258
 
@@ -8353,7 +8361,7 @@ function Chart(userOptions, callback) {
8353
8361
  legendSymbol = item.legendSymbol,
8354
8362
  symbolX,
8355
8363
  checkbox = item.checkbox;
8356
-
8364
+
8357
8365
  if (legendItem) {
8358
8366
  legendItem.attr({
8359
8367
  x: ltr ? itemX : legendWidth - itemX,
@@ -8521,11 +8529,11 @@ function Chart(userOptions, callback) {
8521
8529
  //'stroke-width': 0,
8522
8530
  zIndex: 3
8523
8531
  }).add(legendGroup);
8524
-
8532
+
8525
8533
  if (!ltr) {
8526
8534
  symbolX += symbolWidth;
8527
8535
  }
8528
-
8536
+
8529
8537
  } else if (itemOptions && itemOptions.marker && itemOptions.marker.enabled) { // draw the marker
8530
8538
  radius = itemOptions.marker.radius;
8531
8539
  legendSymbol = renderer.symbol(
@@ -8538,14 +8546,14 @@ function Chart(userOptions, callback) {
8538
8546
  .attr(item.pointAttr[NORMAL_STATE])
8539
8547
  .attr({ zIndex: 3 })
8540
8548
  .add(legendGroup);
8541
-
8549
+
8542
8550
  if (!ltr) {
8543
8551
  symbolX += symbolWidth / 2;
8544
8552
  }
8545
8553
 
8546
8554
  }
8547
8555
  if (legendSymbol) {
8548
-
8556
+
8549
8557
  legendSymbol.xOff = symbolX + (strokeWidth % 2 / 2);
8550
8558
  legendSymbol.yOff = symbolY + (strokeWidth % 2 / 2);
8551
8559
  }
@@ -8591,7 +8599,7 @@ function Chart(userOptions, callback) {
8591
8599
  itemX = initialItemX;
8592
8600
  itemY += itemMarginTop + itemHeight + itemMarginBottom;
8593
8601
  }
8594
-
8602
+
8595
8603
  // If the item exceeds the height, start a new column
8596
8604
  if (!horizontal && itemY + options.y + itemHeight > chartHeight - spacingTop - spacingBottom) {
8597
8605
  itemY = initialItemY;
@@ -8602,7 +8610,7 @@ function Chart(userOptions, callback) {
8602
8610
  // Set the edge positions
8603
8611
  maxItemWidth = mathMax(maxItemWidth, itemWidth);
8604
8612
  lastItemY = mathMax(lastItemY, itemY + itemMarginBottom);
8605
-
8613
+
8606
8614
  // cache the position of the newly generated or reordered items
8607
8615
  item._legendItemPos = [itemX, itemY];
8608
8616
 
@@ -8634,10 +8642,10 @@ function Chart(userOptions, callback) {
8634
8642
 
8635
8643
  if (!legendGroup) {
8636
8644
  legendGroup = renderer.g('legend')
8637
- // #414, #759. Trackers will be drawn above the legend, but we have
8645
+ // #414, #759. Trackers will be drawn above the legend, but we have
8638
8646
  // to sacrifice that because tooltips need to be above the legend
8639
8647
  // and trackers above tooltips
8640
- .attr({ zIndex: 7 })
8648
+ .attr({ zIndex: 7 })
8641
8649
  .add();
8642
8650
  }
8643
8651
 
@@ -8710,8 +8718,8 @@ function Chart(userOptions, callback) {
8710
8718
  // hide the border if no items
8711
8719
  box[allItems.length ? 'show' : 'hide']();
8712
8720
  }
8713
-
8714
- // Now that the legend width and height are extablished, put the items in the
8721
+
8722
+ // Now that the legend width and height are extablished, put the items in the
8715
8723
  // final position
8716
8724
  each(allItems, positionItem);
8717
8725
 
@@ -8920,13 +8928,13 @@ function Chart(userOptions, callback) {
8920
8928
 
8921
8929
  // redraw axes
8922
8930
  each(axes, function (axis) {
8923
-
8931
+
8924
8932
  // Fire 'afterSetExtremes' only if extremes are set
8925
8933
  if (axis.isDirtyExtremes) { // #821
8926
8934
  axis.isDirtyExtremes = false;
8927
8935
  fireEvent(axis, 'afterSetExtremes', axis.getExtremes()); // #747, #751
8928
8936
  }
8929
-
8937
+
8930
8938
  if (axis.isDirty || isDirtyBox || hasStackedSeries) {
8931
8939
  axis.redraw();
8932
8940
  isDirtyBox = true; // #792
@@ -9193,7 +9201,7 @@ function Chart(userOptions, callback) {
9193
9201
 
9194
9202
  // Redraw
9195
9203
  if (hasZoomed) {
9196
- redraw(
9204
+ redraw(
9197
9205
  pick(optionsChart.animation, chart.pointCount < 100) // animation
9198
9206
  );
9199
9207
  }
@@ -9299,19 +9307,19 @@ function Chart(userOptions, callback) {
9299
9307
  if (isString(renderTo)) {
9300
9308
  renderTo = doc.getElementById(renderTo);
9301
9309
  }
9302
-
9310
+
9303
9311
  // Display an error if the renderTo is wrong
9304
9312
  if (!renderTo) {
9305
9313
  error(13, true);
9306
9314
  }
9307
9315
 
9308
9316
  // remove previous chart
9309
- renderTo.innerHTML = '';
9317
+ renderTo.innerHTML = '';
9310
9318
 
9311
9319
  // If the container doesn't have an offsetWidth, it ha s or is a child of a node
9312
9320
  // that has display:none. We need to temporarily move it out to a visible
9313
9321
  // state to determine the size, else the legend and tooltips won't render
9314
- // properly
9322
+ // properly
9315
9323
  if (!renderTo.offsetWidth) {
9316
9324
  renderToClone = renderTo.cloneNode(0);
9317
9325
  css(renderToClone, {
@@ -9457,11 +9465,11 @@ function Chart(userOptions, callback) {
9457
9465
  var width = optionsChart.width || renderTo.offsetWidth,
9458
9466
  height = optionsChart.height || renderTo.offsetHeight,
9459
9467
  target = e ? e.target : win; // #805 - MooTools doesn't supply e
9460
-
9468
+
9461
9469
  // Width and height checks for display:none. Target is doc in IE8 and Opera,
9462
9470
  // win in Firefox, Chrome and IE9.
9463
9471
  if (width && height && (target === win || target === doc)) {
9464
-
9472
+
9465
9473
  if (width !== containerWidth || height !== containerHeight) {
9466
9474
  clearTimeout(reflowTimeout);
9467
9475
  reflowTimeout = setTimeout(function () {
@@ -9729,10 +9737,11 @@ function Chart(userOptions, callback) {
9729
9737
  axis.setScale();
9730
9738
  });
9731
9739
  getMargins();
9732
-
9740
+
9733
9741
  maxTicks = null; // reset for second pass
9734
9742
  each(axes, function (axis) {
9735
9743
  axis.setTickPositions(true); // update to reflect the new margins
9744
+ axis.setMaxTicks();
9736
9745
  });
9737
9746
  adjustTickAmounts();
9738
9747
  getMargins(); // second pass to check for new labels
@@ -9961,8 +9970,8 @@ function Chart(userOptions, callback) {
9961
9970
  each(chart.callbacks, function (fn) {
9962
9971
  fn.apply(chart, [chart]);
9963
9972
  });
9964
-
9965
-
9973
+
9974
+
9966
9975
  // If the chart was rendered outside the top container, put it back in
9967
9976
  if (renderToClone) {
9968
9977
  renderTo.appendChild(container);
@@ -10118,8 +10127,8 @@ Point.prototype = {
10118
10127
  // copy options directly to point
10119
10128
  extend(point, options);
10120
10129
  point.options = options;
10121
-
10122
- // This is the fastest way to detect if there are individual point dataLabels that need
10130
+
10131
+ // This is the fastest way to detect if there are individual point dataLabels that need
10123
10132
  // to be considered in drawDataLabels. These can only occur in object configs.
10124
10133
  if (options.dataLabels) {
10125
10134
  series._hasPointLabels = true;
@@ -10128,7 +10137,7 @@ Point.prototype = {
10128
10137
  point.name = options[0];
10129
10138
  point.y = options[1];
10130
10139
  }
10131
-
10140
+
10132
10141
  /*
10133
10142
  * If no x is set by now, get auto incremented value. All points must have an
10134
10143
  * x value, however the y value can be null to create a gap in the series
@@ -10137,8 +10146,8 @@ Point.prototype = {
10137
10146
  if (point.x === UNDEFINED) {
10138
10147
  point.x = x === UNDEFINED ? series.autoIncrement() : x;
10139
10148
  }
10140
-
10141
-
10149
+
10150
+
10142
10151
 
10143
10152
  },
10144
10153
 
@@ -10165,7 +10174,7 @@ Point.prototype = {
10165
10174
  if (point === chart.hoverPoint) {
10166
10175
  point.onMouseOut();
10167
10176
  }
10168
-
10177
+
10169
10178
  // remove all events
10170
10179
  if (point.graphic || point.dataLabel) { // removeEvent and destroyElements are performance expensive
10171
10180
  removeEvent(point);
@@ -10303,28 +10312,28 @@ Point.prototype = {
10303
10312
  for (i in match) {
10304
10313
  key = match[i];
10305
10314
  if (isString(key) && key !== pointFormat) { // IE matches more than just the variables
10306
-
10315
+
10307
10316
  // Split it further into parts
10308
10317
  parts = (' ' + key).split(splitter); // add empty string because IE and the rest handles it differently
10309
10318
  obj = { 'point': point, 'series': series }[parts[1]];
10310
10319
  prop = parts[2];
10311
-
10320
+
10312
10321
  // Add some preformatting
10313
- if (obj === point && (prop === 'y' || prop === 'open' || prop === 'high' ||
10314
- prop === 'low' || prop === 'close')) {
10315
- replacement = (seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix || '') +
10322
+ if (obj === point && (prop === 'y' || prop === 'open' || prop === 'high' ||
10323
+ prop === 'low' || prop === 'close')) {
10324
+ replacement = (seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix || '') +
10316
10325
  numberFormat(point[prop], pick(seriesTooltipOptions.valueDecimals, seriesTooltipOptions.yDecimals, originalDecimals)) +
10317
10326
  (seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix || '');
10318
-
10327
+
10319
10328
  // Automatic replacement
10320
10329
  } else {
10321
10330
  replacement = obj[prop];
10322
10331
  }
10323
-
10332
+
10324
10333
  pointFormat = pointFormat.replace(key, replacement);
10325
10334
  }
10326
10335
  }
10327
-
10336
+
10328
10337
  return pointFormat;
10329
10338
  },
10330
10339
 
@@ -10597,7 +10606,7 @@ Series.prototype = {
10597
10606
 
10598
10607
  series.chart = chart;
10599
10608
  series.options = options = series.setOptions(options); // merge with plotOptions
10600
-
10609
+
10601
10610
  // bind the axes
10602
10611
  series.bindAxes();
10603
10612
 
@@ -10610,7 +10619,7 @@ Series.prototype = {
10610
10619
  visible: options.visible !== false, // true by default
10611
10620
  selected: options.selected === true // false by default
10612
10621
  });
10613
-
10622
+
10614
10623
  // special
10615
10624
  if (useCanVG) {
10616
10625
  options.animation = false;
@@ -10636,9 +10645,9 @@ Series.prototype = {
10636
10645
  series.setData(options.data, false);
10637
10646
 
10638
10647
  },
10639
-
10640
-
10641
-
10648
+
10649
+
10650
+
10642
10651
  /**
10643
10652
  * Set the xAxis and yAxis properties of cartesian series, and register the series
10644
10653
  * in the axis.series array
@@ -10648,31 +10657,31 @@ Series.prototype = {
10648
10657
  seriesOptions = series.options,
10649
10658
  chart = series.chart,
10650
10659
  axisOptions;
10651
-
10660
+
10652
10661
  if (series.isCartesian) {
10653
-
10662
+
10654
10663
  each(['xAxis', 'yAxis'], function (AXIS) { // repeat for xAxis and yAxis
10655
-
10664
+
10656
10665
  each(chart[AXIS], function (axis) { // loop through the chart's axis objects
10657
-
10666
+
10658
10667
  axisOptions = axis.options;
10659
-
10660
- // apply if the series xAxis or yAxis option mathches the number of the
10668
+
10669
+ // apply if the series xAxis or yAxis option mathches the number of the
10661
10670
  // axis, or if undefined, use the first axis
10662
10671
  if ((seriesOptions[AXIS] === axisOptions.index) ||
10663
10672
  (seriesOptions[AXIS] === UNDEFINED && axisOptions.index === 0)) {
10664
-
10673
+
10665
10674
  // register this series in the axis.series lookup
10666
10675
  axis.series.push(series);
10667
-
10676
+
10668
10677
  // set this series.xAxis or series.yAxis reference
10669
10678
  series[AXIS] = axis;
10670
-
10679
+
10671
10680
  // mark dirty for redraw
10672
10681
  axis.isDirty = true;
10673
10682
  }
10674
10683
  });
10675
-
10684
+
10676
10685
  });
10677
10686
  }
10678
10687
  },
@@ -10707,7 +10716,7 @@ Series.prototype = {
10707
10716
  pointsLength = points.length;
10708
10717
 
10709
10718
  if (pointsLength) { // no action required for []
10710
-
10719
+
10711
10720
  // if connect nulls, just remove null points
10712
10721
  if (series.options.connectNulls) {
10713
10722
  i = pointsLength;
@@ -10719,7 +10728,7 @@ Series.prototype = {
10719
10728
  if (points.length) {
10720
10729
  segments = [points];
10721
10730
  }
10722
-
10731
+
10723
10732
  // else, split on null points
10724
10733
  } else {
10725
10734
  each(points, function (point, i) {
@@ -10734,7 +10743,7 @@ Series.prototype = {
10734
10743
  });
10735
10744
  }
10736
10745
  }
10737
-
10746
+
10738
10747
  // register it
10739
10748
  series.segments = segments;
10740
10749
  },
@@ -10757,13 +10766,13 @@ Series.prototype = {
10757
10766
  plotOptions.series,
10758
10767
  itemOptions
10759
10768
  );
10760
-
10769
+
10761
10770
  // Re-insert the data array to the options and the original config (#717)
10762
10771
  options.data = itemOptions.data = data;
10763
-
10772
+
10764
10773
  // the tooltip options are merged between global and series specific options
10765
10774
  series.tooltipOptions = merge(chartOptions.tooltip, options.tooltip);
10766
-
10775
+
10767
10776
  return options;
10768
10777
 
10769
10778
  },
@@ -10786,7 +10795,7 @@ Series.prototype = {
10786
10795
  defaultSymbols = chart.options.symbols,
10787
10796
  counters = chart.counters;
10788
10797
  series.symbol = seriesMarkerOption.symbol || defaultSymbols[counters.symbol++];
10789
-
10798
+
10790
10799
  // don't substract radius in image symbols (#604)
10791
10800
  if (/^url/.test(series.symbol)) {
10792
10801
  seriesMarkerOption.radius = 0;
@@ -10819,7 +10828,7 @@ Series.prototype = {
10819
10828
  setAnimation(animation, chart);
10820
10829
 
10821
10830
  // Make graph animate sideways
10822
- if (graph && shift) {
10831
+ if (graph && shift) {
10823
10832
  graph.shift = currentShift + 1;
10824
10833
  }
10825
10834
  if (area) {
@@ -10828,7 +10837,7 @@ Series.prototype = {
10828
10837
  }
10829
10838
  area.isArea = true; // needed in animation, both with and without shift
10830
10839
  }
10831
-
10840
+
10832
10841
  // Optional redraw, defaults to true
10833
10842
  redraw = pick(redraw, true);
10834
10843
 
@@ -10881,11 +10890,11 @@ Series.prototype = {
10881
10890
  // reset properties
10882
10891
  series.xIncrement = null;
10883
10892
  series.pointRange = (xAxis && xAxis.categories && 1) || options.pointRange;
10884
-
10893
+
10885
10894
  if (defined(initialColor)) { // reset colors for pie
10886
10895
  chart.counters.color = initialColor;
10887
10896
  }
10888
-
10897
+
10889
10898
  // parallel arrays
10890
10899
  var xData = [],
10891
10900
  yData = [],
@@ -10899,15 +10908,15 @@ Series.prototype = {
10899
10908
  // way. Although the 'for' loops are similar, they are repeated inside each
10900
10909
  // if-else conditional for max performance.
10901
10910
  if (dataLength > turboThreshold) {
10902
-
10911
+
10903
10912
  // find the first non-null point
10904
10913
  i = 0;
10905
10914
  while (firstPoint === null && i < dataLength) {
10906
10915
  firstPoint = data[i];
10907
10916
  i++;
10908
10917
  }
10909
-
10910
-
10918
+
10919
+
10911
10920
  if (isNumber(firstPoint)) { // assume all points are numbers
10912
10921
  var x = pick(options.pointStart, 0),
10913
10922
  pointInterval = pick(options.pointInterval, 1);
@@ -10956,7 +10965,7 @@ Series.prototype = {
10956
10965
  oldData[i].destroy();
10957
10966
  }
10958
10967
  }
10959
-
10968
+
10960
10969
  // reset minRange (#878)
10961
10970
  // TODO: In protofy, run this code instead:
10962
10971
  // if (xAxis) xAxis.minRange = UNDEFINED;
@@ -11028,7 +11037,7 @@ Series.prototype = {
11028
11037
  isCartesian = series.isCartesian;
11029
11038
 
11030
11039
  // If the series data or axes haven't changed, don't go through this. Return false to pass
11031
- // the message on to override methods like in data grouping.
11040
+ // the message on to override methods like in data grouping.
11032
11041
  if (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) {
11033
11042
  return false;
11034
11043
  }
@@ -11043,7 +11052,7 @@ Series.prototype = {
11043
11052
  if (processedXData[dataLength - 1] < min || processedXData[0] > max) {
11044
11053
  processedXData = [];
11045
11054
  processedYData = [];
11046
-
11055
+
11047
11056
  // only crop if it's actually spilling out
11048
11057
  } else if (processedXData[0] < min || processedXData[dataLength - 1] > max) {
11049
11058
 
@@ -11060,15 +11069,15 @@ Series.prototype = {
11060
11069
  cropEnd = i + 1;
11061
11070
  break;
11062
11071
  }
11063
-
11072
+
11064
11073
  }
11065
11074
  processedXData = processedXData.slice(cropStart, cropEnd);
11066
11075
  processedYData = processedYData.slice(cropStart, cropEnd);
11067
11076
  cropped = true;
11068
11077
  }
11069
11078
  }
11070
-
11071
-
11079
+
11080
+
11072
11081
  // Find the closest distance between processed points
11073
11082
  for (i = processedXData.length - 1; i > 0; i--) {
11074
11083
  distance = processedXData[i] - processedXData[i - 1];
@@ -11076,18 +11085,18 @@ Series.prototype = {
11076
11085
  closestPointRange = distance;
11077
11086
  }
11078
11087
  }
11079
-
11088
+
11080
11089
  // Record the properties
11081
11090
  series.cropped = cropped; // undefined or true
11082
11091
  series.cropStart = cropStart;
11083
11092
  series.processedXData = processedXData;
11084
11093
  series.processedYData = processedYData;
11085
-
11094
+
11086
11095
  if (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC
11087
11096
  series.pointRange = closestPointRange || 1;
11088
11097
  }
11089
11098
  series.closestPointRange = closestPointRange;
11090
-
11099
+
11091
11100
  },
11092
11101
 
11093
11102
  /**
@@ -11133,7 +11142,7 @@ Series.prototype = {
11133
11142
  }
11134
11143
 
11135
11144
  // Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when
11136
- // swithching view from non-grouped data to grouped data (#637)
11145
+ // swithching view from non-grouped data to grouped data (#637)
11137
11146
  if (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) {
11138
11147
  for (i = 0; i < dataLength; i++) {
11139
11148
  if (i === cropStart && !hasGroupedData) { // when has grouped data, clear all points
@@ -11171,7 +11180,7 @@ Series.prototype = {
11171
11180
  isLastSeries,
11172
11181
  allStackSeries = yAxis.series,
11173
11182
  i = allStackSeries.length;
11174
-
11183
+
11175
11184
  // Is it the last visible series?
11176
11185
  while (i--) {
11177
11186
  if (allStackSeries[i].visible) {
@@ -11181,7 +11190,7 @@ Series.prototype = {
11181
11190
  break;
11182
11191
  }
11183
11192
  }
11184
-
11193
+
11185
11194
  // Translate each point
11186
11195
  for (i = 0; i < dataLength; i++) {
11187
11196
  var point = points[i],
@@ -11191,7 +11200,7 @@ Series.prototype = {
11191
11200
  stack = yAxis.stacks[(yValue < options.threshold ? '-' : '') + series.stackKey],
11192
11201
  pointStack,
11193
11202
  pointStackTotal;
11194
-
11203
+
11195
11204
  // get the plotX translation
11196
11205
  point.plotX = mathRound(xAxis.translate(xValue, 0, 0, 0, 1) * 10) / 10; // Math.round fixes #591
11197
11206
 
@@ -11201,11 +11210,11 @@ Series.prototype = {
11201
11210
  pointStackTotal = pointStack.total;
11202
11211
  pointStack.cum = yBottom = pointStack.cum - yValue; // start from top
11203
11212
  yValue = yBottom + yValue;
11204
-
11213
+
11205
11214
  if (isLastSeries) {
11206
11215
  yBottom = options.threshold;
11207
11216
  }
11208
-
11217
+
11209
11218
  if (stacking === 'percent') {
11210
11219
  yBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0;
11211
11220
  yValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0;
@@ -11217,17 +11226,17 @@ Series.prototype = {
11217
11226
  }
11218
11227
 
11219
11228
  // Set translated yBottom or remove it
11220
- point.yBottom = defined(yBottom) ?
11229
+ point.yBottom = defined(yBottom) ?
11221
11230
  yAxis.translate(yBottom, 0, 1, 0, 1) :
11222
11231
  null;
11223
-
11232
+
11224
11233
  // general hook, used for Highstock compare mode
11225
11234
  if (hasModifyValue) {
11226
11235
  yValue = series.modifyValue(yValue, point);
11227
11236
  }
11228
11237
 
11229
11238
  // Set the the plotY value, reset it for redraws
11230
- point.plotY = (typeof yValue === 'number') ?
11239
+ point.plotY = (typeof yValue === 'number') ?
11231
11240
  mathRound(yAxis.translate(yValue, 0, 1, 0, 1) * 10) / 10 : // Math.round fixes #591
11232
11241
  UNDEFINED;
11233
11242
 
@@ -11308,7 +11317,7 @@ Series.prototype = {
11308
11317
  xDateFormat = tooltipOptions.xDateFormat || '%A, %b %e, %Y',
11309
11318
  xAxis = series.xAxis,
11310
11319
  isDateTime = xAxis && xAxis.options.type === 'datetime';
11311
-
11320
+
11312
11321
  return tooltipOptions.headerFormat
11313
11322
  .replace('{point.key}', isDateTime ? dateFormat(xDateFormat, key) : key)
11314
11323
  .replace('{series.name}', series.name)
@@ -11635,7 +11644,7 @@ Series.prototype = {
11635
11644
 
11636
11645
  // remove all events
11637
11646
  removeEvent(series);
11638
-
11647
+
11639
11648
  // erase from axes
11640
11649
  each(['xAxis', 'yAxis'], function (AXIS) {
11641
11650
  axis = series[AXIS];
@@ -11695,11 +11704,11 @@ Series.prototype = {
11695
11704
  * Draw the data labels
11696
11705
  */
11697
11706
  drawDataLabels: function () {
11698
-
11707
+
11699
11708
  var series = this,
11700
11709
  seriesOptions = series.options,
11701
11710
  options = seriesOptions.dataLabels;
11702
-
11711
+
11703
11712
  if (options.enabled || series._hasPointLabels) {
11704
11713
  var x,
11705
11714
  y,
@@ -11728,8 +11737,8 @@ Series.prototype = {
11728
11737
 
11729
11738
  if (isBarLike) {
11730
11739
  var defaultYs = {
11731
- top: fontBaseline,
11732
- middle: fontBaseline - fontLineHeight / 2,
11740
+ top: fontBaseline,
11741
+ middle: fontBaseline - fontLineHeight / 2,
11733
11742
  bottom: -fontLineHeight + fontBaseline
11734
11743
  };
11735
11744
  if (stacking) {
@@ -11746,12 +11755,12 @@ Series.prototype = {
11746
11755
  // In non stacked series the default label placement is on top of the bars
11747
11756
  if (vAlignIsNull) {
11748
11757
  options = merge(options, {verticalAlign: 'top'});
11749
-
11758
+
11750
11759
  // If no y delta is specified, try to create a good default (like default bar)
11751
11760
  } else if (yIsNull) {
11752
11761
  options = merge(options, { y: defaultYs[options.verticalAlign]});
11753
11762
  }
11754
-
11763
+
11755
11764
  }
11756
11765
  }
11757
11766
 
@@ -11769,13 +11778,13 @@ Series.prototype = {
11769
11778
  } else {
11770
11779
  dataLabelsGroup.translate(groupLeft, groupTop);
11771
11780
  }
11772
-
11781
+
11773
11782
  // make the labels for each point
11774
11783
  generalOptions = options;
11775
11784
  each(points, function (point) {
11776
-
11785
+
11777
11786
  dataLabel = point.dataLabel;
11778
-
11787
+
11779
11788
  // Merge in individual options from point
11780
11789
  options = generalOptions; // reset changes from previous points
11781
11790
  pointOptions = point.options;
@@ -11783,52 +11792,52 @@ Series.prototype = {
11783
11792
  options = merge(options, pointOptions.dataLabels);
11784
11793
  }
11785
11794
  enabled = options.enabled;
11786
-
11795
+
11787
11796
  // Get the positions
11788
11797
  if (enabled) {
11789
11798
  var plotX = (point.barX && point.barX + point.barW / 2) || pick(point.plotX, -999),
11790
11799
  plotY = pick(point.plotY, -999),
11791
-
11800
+
11792
11801
  // if options.y is null, which happens by default on column charts, set the position
11793
11802
  // above or below the column depending on the threshold
11794
- individualYDelta = options.y === null ?
11795
- (point.y >= seriesOptions.threshold ?
11796
- -fontLineHeight + fontBaseline : // below the threshold
11803
+ individualYDelta = options.y === null ?
11804
+ (point.y >= seriesOptions.threshold ?
11805
+ -fontLineHeight + fontBaseline : // below the threshold
11797
11806
  fontBaseline) : // above the threshold
11798
11807
  options.y;
11799
-
11808
+
11800
11809
  x = (inverted ? chart.plotWidth - plotY : plotX) + options.x;
11801
11810
  y = mathRound((inverted ? chart.plotHeight - plotX : plotY) + individualYDelta);
11802
-
11811
+
11803
11812
  }
11804
-
11813
+
11805
11814
  // If the point is outside the plot area, destroy it. #678, #820
11806
11815
  if (dataLabel && series.isCartesian && (!chart.isInsidePlot(x, y) || !enabled)) {
11807
11816
  point.dataLabel = dataLabel.destroy();
11808
-
11809
- // Individual labels are disabled if the are explicitly disabled
11817
+
11818
+ // Individual labels are disabled if the are explicitly disabled
11810
11819
  // in the point options, or if they fall outside the plot area.
11811
11820
  } else if (enabled) {
11812
-
11821
+
11813
11822
  var align = options.align;
11814
-
11823
+
11815
11824
  // Get the string
11816
11825
  str = options.formatter.call(point.getLabelConfig(), options);
11817
-
11826
+
11818
11827
  // in columns, align the string to the column
11819
11828
  if (seriesType === 'column') {
11820
11829
  x += { left: -1, right: 1 }[align] * point.barW / 2 || 0;
11821
11830
  }
11822
-
11831
+
11823
11832
  if (!stacking && inverted && point.y < 0) {
11824
11833
  align = 'right';
11825
11834
  x -= 10;
11826
11835
  }
11827
-
11836
+
11828
11837
  // Determine the color
11829
11838
  options.style.color = pick(options.color, options.style.color, series.color, 'black');
11830
-
11831
-
11839
+
11840
+
11832
11841
  // update existing label
11833
11842
  if (dataLabel) {
11834
11843
  // vertically centered
@@ -11865,13 +11874,13 @@ Series.prototype = {
11865
11874
  .add(dataLabelsGroup)
11866
11875
  .shadow(options.shadow);
11867
11876
  }
11868
-
11877
+
11869
11878
  if (isBarLike && seriesOptions.stacking && dataLabel) {
11870
11879
  var barX = point.barX,
11871
11880
  barY = point.barY,
11872
11881
  barW = point.barW,
11873
11882
  barH = point.barH;
11874
-
11883
+
11875
11884
  dataLabel.align(options, null,
11876
11885
  {
11877
11886
  x: inverted ? chart.plotWidth - barY - barH : barX,
@@ -11880,8 +11889,8 @@ Series.prototype = {
11880
11889
  height: inverted ? barW : barH
11881
11890
  });
11882
11891
  }
11883
-
11884
-
11892
+
11893
+
11885
11894
  }
11886
11895
  });
11887
11896
  }
@@ -11962,17 +11971,17 @@ Series.prototype = {
11962
11971
  areaSegmentPath.push(L, segmentPath[1], segmentPath[2]);
11963
11972
  }
11964
11973
  if (options.stacking && series.type !== 'areaspline') {
11965
-
11966
- // Follow stack back. Todo: implement areaspline. A general solution could be to
11974
+
11975
+ // Follow stack back. Todo: implement areaspline. A general solution could be to
11967
11976
  // reverse the entire graphPath of the previous series, though may be hard with
11968
11977
  // splines and with series with different extremes
11969
11978
  for (i = segment.length - 1; i >= 0; i--) {
11970
-
11979
+
11971
11980
  // step line?
11972
11981
  if (i < segment.length - 1 && options.step) {
11973
11982
  areaSegmentPath.push(segment[i + 1].plotX, segment[i].yBottom);
11974
11983
  }
11975
-
11984
+
11976
11985
  areaSegmentPath.push(segment[i].plotX, segment[i].yBottom);
11977
11986
  }
11978
11987
 
@@ -12041,17 +12050,17 @@ Series.prototype = {
12041
12050
  group = series.group,
12042
12051
  trackerGroup = series.trackerGroup,
12043
12052
  chart = series.chart;
12044
-
12053
+
12045
12054
  // A fixed size is needed for inversion to work
12046
- function setInvert() {
12055
+ function setInvert() {
12047
12056
  var size = {
12048
12057
  width: series.yAxis.len,
12049
12058
  height: series.xAxis.len
12050
12059
  };
12051
-
12060
+
12052
12061
  // Set the series.group size
12053
12062
  group.attr(size).invert();
12054
-
12063
+
12055
12064
  // Set the tracker group size
12056
12065
  if (trackerGroup) {
12057
12066
  trackerGroup.attr(size).invert();
@@ -12065,7 +12074,7 @@ Series.prototype = {
12065
12074
 
12066
12075
  // Do it now
12067
12076
  setInvert(); // do it now
12068
-
12077
+
12069
12078
  // On subsequent render and redraw, just do setInvert without setting up events again
12070
12079
  series.invertGroups = setInvert;
12071
12080
  },
@@ -12100,7 +12109,7 @@ Series.prototype = {
12100
12109
  chart.clipRect = clipRect;
12101
12110
  }
12102
12111
  }
12103
-
12112
+
12104
12113
 
12105
12114
  // the group
12106
12115
  if (!series.group) {
@@ -12136,12 +12145,12 @@ Series.prototype = {
12136
12145
  if (series.options.enableMouseTracking !== false) {
12137
12146
  series.drawTracker();
12138
12147
  }
12139
-
12148
+
12140
12149
  // Handle inverted series and tracker groups
12141
12150
  if (chart.inverted) {
12142
12151
  series.invertGroups();
12143
12152
  }
12144
-
12153
+
12145
12154
  // Do the initial clipping. This must be done after inverting for VML.
12146
12155
  if (doClip && !series.hasRendered) {
12147
12156
  group.clip(clipRect);
@@ -12149,7 +12158,7 @@ Series.prototype = {
12149
12158
  series.trackerGroup.clip(chart.clipRect);
12150
12159
  }
12151
12160
  }
12152
-
12161
+
12153
12162
 
12154
12163
  // run the animation
12155
12164
  if (doAnimation) {
@@ -12350,26 +12359,26 @@ Series.prototype = {
12350
12359
  drawTrackerGroup: function () {
12351
12360
  var trackerGroup = this.trackerGroup,
12352
12361
  chart = this.chart;
12353
-
12362
+
12354
12363
  if (this.isCartesian) {
12355
-
12364
+
12356
12365
  // Generate it on first call
12357
- if (!trackerGroup) {
12366
+ if (!trackerGroup) {
12358
12367
  this.trackerGroup = trackerGroup = chart.renderer.g()
12359
12368
  .attr({
12360
12369
  zIndex: this.options.zIndex || 1
12361
12370
  })
12362
12371
  .add(chart.trackerGroup);
12363
-
12372
+
12364
12373
  }
12365
12374
  // Place it on first and subsequent (redraw) calls
12366
12375
  trackerGroup.translate(this.xAxis.left, this.yAxis.top);
12367
-
12376
+
12368
12377
  }
12369
-
12378
+
12370
12379
  return trackerGroup;
12371
12380
  },
12372
-
12381
+
12373
12382
  /**
12374
12383
  * Draw the tracker object that sits above all data labels and markers to
12375
12384
  * track mouse events on the graph or points. For the line type charts
@@ -12412,15 +12421,15 @@ Series.prototype = {
12412
12421
  trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY,
12413
12422
  L, singlePoint.plotX + snap, singlePoint.plotY);
12414
12423
  }
12415
-
12416
-
12424
+
12425
+
12417
12426
 
12418
12427
  // draw the tracker
12419
12428
  if (tracker) {
12420
12429
  tracker.attr({ d: trackerPath });
12421
12430
 
12422
12431
  } else { // create
12423
-
12432
+
12424
12433
  series.tracker = renderer.path(trackerPath)
12425
12434
  .attr({
12426
12435
  isTracker: true,
@@ -12691,7 +12700,7 @@ var ColumnSeries = extendClass(Series, {
12691
12700
  r: options.borderRadius,
12692
12701
  strokeWidth: borderWidth
12693
12702
  };
12694
-
12703
+
12695
12704
  if (borderWidth % 2) { // correct for shorting in crisp method, visible in stacked columns with 1px border
12696
12705
  shapeArgs.y -= 1;
12697
12706
  shapeArgs.height += 1;
@@ -12749,7 +12758,7 @@ var ColumnSeries = extendClass(Series, {
12749
12758
  .attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE])
12750
12759
  .add(series.group)
12751
12760
  .shadow(options.shadow);
12752
-
12761
+
12753
12762
  }
12754
12763
 
12755
12764
  }
@@ -12773,7 +12782,7 @@ var ColumnSeries = extendClass(Series, {
12773
12782
  rel,
12774
12783
  plotY,
12775
12784
  validPlotY;
12776
-
12785
+
12777
12786
  each(series.points, function (point) {
12778
12787
  tracker = point.tracker;
12779
12788
  shapeArgs = point.trackerArgs || point.shapeArgs;
@@ -12844,7 +12853,7 @@ var ColumnSeries = extendClass(Series, {
12844
12853
  // start values
12845
12854
  graphic.attr({
12846
12855
  height: 0,
12847
- y: defined(threshold) ?
12856
+ y: defined(threshold) ?
12848
12857
  yAxis.getThreshold(threshold) :
12849
12858
  yAxis.translate(yAxis.getExtremes().min, 0, 1, 0, 1)
12850
12859
  });
@@ -12935,10 +12944,10 @@ var ScatterSeries = extendClass(Series, {
12935
12944
  while (i--) {
12936
12945
  graphic = points[i].graphic;
12937
12946
  if (graphic) { // doesn't exist for null points
12938
- graphic.element._i = i;
12947
+ graphic.element._i = i;
12939
12948
  }
12940
12949
  }
12941
-
12950
+
12942
12951
  // Add the event listeners, we need to do this only once
12943
12952
  if (!series._hasTracking) {
12944
12953
  series.group
@@ -13129,14 +13138,14 @@ var PieSeries = extendClass(Series, {
13129
13138
  this.generatePoints();
13130
13139
  if (pick(redraw, true)) {
13131
13140
  this.chart.redraw();
13132
- }
13141
+ }
13133
13142
  },
13134
13143
  /**
13135
13144
  * Do translation for pie slices
13136
13145
  */
13137
13146
  translate: function () {
13138
13147
  this.generatePoints();
13139
-
13148
+
13140
13149
  var total = 0,
13141
13150
  series = this,
13142
13151
  cumulative = -0.25, // start at top
@@ -13238,7 +13247,7 @@ var PieSeries = extendClass(Series, {
13238
13247
  angle < circ / 4 ? 'left' : 'right', // alignment
13239
13248
  angle // center angle
13240
13249
  ];
13241
-
13250
+
13242
13251
  // API properties
13243
13252
  point.percentage = fraction * 100;
13244
13253
  point.total = total;
@@ -13416,7 +13425,7 @@ var PieSeries = extendClass(Series, {
13416
13425
 
13417
13426
  // Only do anti-collision when we are outside the pie and have connectors (#856)
13418
13427
  if (distanceOption > 0) {
13419
-
13428
+
13420
13429
  // build the slots
13421
13430
  for (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) {
13422
13431
  slots.push(pos);
@@ -13439,7 +13448,7 @@ var PieSeries = extendClass(Series, {
13439
13448
  // */
13440
13449
  }
13441
13450
  slotsLength = slots.length;
13442
-
13451
+
13443
13452
  // if there are more values than available slots, remove lowest values
13444
13453
  if (length > slotsLength) {
13445
13454
  // create an array for sorting and ranking the points within each quarter
@@ -13457,18 +13466,18 @@ var PieSeries = extendClass(Series, {
13457
13466
  }
13458
13467
  length = points.length;
13459
13468
  }
13460
-
13469
+
13461
13470
  // The label goes to the nearest open slot, but not closer to the edge than
13462
13471
  // the label's index.
13463
13472
  for (j = 0; j < length; j++) {
13464
-
13473
+
13465
13474
  point = points[j];
13466
13475
  labelPos = point.labelPos;
13467
-
13476
+
13468
13477
  var closest = 9999,
13469
13478
  distance,
13470
13479
  slotI;
13471
-
13480
+
13472
13481
  // find the closest slot index
13473
13482
  for (slotI = 0; slotI < slotsLength; slotI++) {
13474
13483
  distance = mathAbs(slots[slotI] - labelPos[1]);
@@ -13477,7 +13486,7 @@ var PieSeries = extendClass(Series, {
13477
13486
  slotIndex = slotI;
13478
13487
  }
13479
13488
  }
13480
-
13489
+
13481
13490
  // if that slot index is closer to the edges of the slots, move it
13482
13491
  // to the closest appropriate slot
13483
13492
  if (slotIndex < j && slots[j] !== null) { // cluster at the top
@@ -13494,7 +13503,7 @@ var PieSeries = extendClass(Series, {
13494
13503
  slotIndex++;
13495
13504
  }
13496
13505
  }
13497
-
13506
+
13498
13507
  usedSlots.push({ i: slotIndex, y: slots[slotIndex] });
13499
13508
  slots[slotIndex] = null; // mark as taken
13500
13509
  }
@@ -13504,7 +13513,7 @@ var PieSeries = extendClass(Series, {
13504
13513
 
13505
13514
  // now the used slots are sorted, fill them up sequentially
13506
13515
  for (j = 0; j < length; j++) {
13507
-
13516
+
13508
13517
  var slot, naturalY;
13509
13518
 
13510
13519
  point = points[j];
@@ -13512,7 +13521,7 @@ var PieSeries = extendClass(Series, {
13512
13521
  dataLabel = point.dataLabel;
13513
13522
  visibility = point.visible === false ? HIDDEN : VISIBLE;
13514
13523
  naturalY = labelPos[1];
13515
-
13524
+
13516
13525
  if (distanceOption > 0) {
13517
13526
  slot = usedSlots.pop();
13518
13527
  slotIndex = slot.i;
@@ -13524,17 +13533,17 @@ var PieSeries = extendClass(Series, {
13524
13533
  (naturalY < y && slots[slotIndex - 1] !== null)) {
13525
13534
  y = naturalY;
13526
13535
  }
13527
-
13536
+
13528
13537
  } else {
13529
13538
  y = naturalY;
13530
13539
  }
13531
13540
 
13532
13541
  // get the x - use the natural x position for first and last slot, to prevent the top
13533
13542
  // and botton slice connectors from touching each other on either side
13534
- x = options.justify ?
13543
+ x = options.justify ?
13535
13544
  seriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) :
13536
13545
  series.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i);
13537
-
13546
+
13538
13547
  // move or place the data label
13539
13548
  dataLabel
13540
13549
  .attr({
@@ -13635,6 +13644,6 @@ extend(Highcharts, {
13635
13644
  extendClass: extendClass,
13636
13645
  placeBox: placeBox,
13637
13646
  product: 'Highcharts',
13638
- version: '2.2.2'
13647
+ version: '2.2.3'
13639
13648
  });
13640
13649
  }());