highcharts-rails 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- checksums.yaml.gz.asc +18 -0
- data/CHANGELOG.markdown +4 -0
- data/Rakefile +29 -1
- data/app/assets/javascripts/highcharts/adapters/mootools.js +1 -1
- data/app/assets/javascripts/highcharts/adapters/prototype.js +1 -1
- data/app/assets/javascripts/highcharts/highcharts-more.js +118 -217
- data/app/assets/javascripts/highcharts/modules/annotations.js +74 -27
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +1 -1
- data/app/assets/javascripts/highcharts/modules/data.js +74 -29
- data/app/assets/javascripts/highcharts/modules/exporting.js +5 -8
- data/app/assets/javascripts/highcharts/modules/funnel.js +2 -2
- data/app/assets/javascripts/highcharts/modules/heatmap.js +57 -0
- data/app/assets/javascripts/highcharts/modules/map.js +576 -0
- data/app/assets/javascripts/highcharts.js +853 -497
- data/highcharts-rails.gemspec +1 -0
- data/lib/highcharts/version.rb +1 -1
- data.tar.gz.asc +14 -14
- metadata +18 -23
- metadata.gz.asc +14 -14
| @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            // @compilation_level SIMPLE_OPTIMIZATIONS
         | 
| 3 3 |  | 
| 4 4 | 
             
            /**
         | 
| 5 | 
            -
             * @license Highcharts JS v3.0. | 
| 5 | 
            +
             * @license Highcharts JS v3.0.3 (2013-07-31)
         | 
| 6 6 | 
             
             *
         | 
| 7 7 | 
             
             * (c) 2009-2013 Torstein Hønsi
         | 
| 8 8 | 
             
             *
         | 
| @@ -55,7 +55,7 @@ var UNDEFINED, | |
| 55 55 | 
             
            	noop = function () {},
         | 
| 56 56 | 
             
            	charts = [],
         | 
| 57 57 | 
             
            	PRODUCT = 'Highcharts',
         | 
| 58 | 
            -
            	VERSION = '3.0. | 
| 58 | 
            +
            	VERSION = '3.0.3',
         | 
| 59 59 |  | 
| 60 60 | 
             
            	// some constants for frequently used strings
         | 
| 61 61 | 
             
            	DIV = 'div',
         | 
| @@ -149,15 +149,15 @@ function merge() { | |
| 149 149 | 
             
            		doCopy = function (copy, original) {
         | 
| 150 150 | 
             
            			var value, key;
         | 
| 151 151 |  | 
| 152 | 
            +
            			// An object is replacing a primitive
         | 
| 153 | 
            +
            			if (typeof copy !== 'object') {
         | 
| 154 | 
            +
            				copy = {};
         | 
| 155 | 
            +
            			}
         | 
| 156 | 
            +
             | 
| 152 157 | 
             
            			for (key in original) {
         | 
| 153 158 | 
             
            				if (original.hasOwnProperty(key)) {
         | 
| 154 159 | 
             
            					value = original[key];
         | 
| 155 160 |  | 
| 156 | 
            -
            					// An object is replacing a primitive
         | 
| 157 | 
            -
            					if (typeof copy !== 'object') {
         | 
| 158 | 
            -
            						copy = {};
         | 
| 159 | 
            -
            					}
         | 
| 160 | 
            -
            						
         | 
| 161 161 | 
             
            					// Copy the contents of objects, but not arrays or DOM nodes
         | 
| 162 162 | 
             
            					if (value && typeof value === 'object' && Object.prototype.toString.call(value) !== '[object Array]'
         | 
| 163 163 | 
             
            							&& typeof value.nodeType !== 'number') {
         | 
| @@ -387,14 +387,14 @@ function extendClass(parent, members) { | |
| 387 387 | 
             
            function numberFormat(number, decimals, decPoint, thousandsSep) {
         | 
| 388 388 | 
             
            	var lang = defaultOptions.lang,
         | 
| 389 389 | 
             
            		// http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/
         | 
| 390 | 
            -
            		n = number,
         | 
| 390 | 
            +
            		n = +number || 0,
         | 
| 391 391 | 
             
            		c = decimals === -1 ?
         | 
| 392 | 
            -
            			( | 
| 392 | 
            +
            			(n.toString().split('.')[1] || '').length : // preserve decimals
         | 
| 393 393 | 
             
            			(isNaN(decimals = mathAbs(decimals)) ? 2 : decimals),
         | 
| 394 394 | 
             
            		d = decPoint === undefined ? lang.decimalPoint : decPoint,
         | 
| 395 395 | 
             
            		t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep,
         | 
| 396 396 | 
             
            		s = n < 0 ? "-" : "",
         | 
| 397 | 
            -
            		i = String(pInt(n = mathAbs( | 
| 397 | 
            +
            		i = String(pInt(n = mathAbs(n).toFixed(c))),
         | 
| 398 398 | 
             
            		j = i.length > 3 ? i.length % 3 : 0;
         | 
| 399 399 |  | 
| 400 400 | 
             
            	return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) +
         | 
| @@ -569,6 +569,13 @@ function format(str, ctx) { | |
| 569 569 | 
             
            	return ret.join('');
         | 
| 570 570 | 
             
            }
         | 
| 571 571 |  | 
| 572 | 
            +
            /**
         | 
| 573 | 
            +
             * Get the magnitude of a number
         | 
| 574 | 
            +
             */
         | 
| 575 | 
            +
            function getMagnitude(num) {
         | 
| 576 | 
            +
            	return math.pow(10, mathFloor(math.log(num) / math.LN10));
         | 
| 577 | 
            +
            }
         | 
| 578 | 
            +
             | 
| 572 579 | 
             
            /**
         | 
| 573 580 | 
             
             * Take an interval and normalize it to multiples of 1, 2, 2.5 and 5
         | 
| 574 581 | 
             
             * @param {Number} interval
         | 
| @@ -681,7 +688,11 @@ function normalizeTimeTickInterval(tickInterval, unitsOption) { | |
| 681 688 | 
             
            	}
         | 
| 682 689 |  | 
| 683 690 | 
             
            	// get the count
         | 
| 684 | 
            -
            	count = normalizeTickInterval( | 
| 691 | 
            +
            	count = normalizeTickInterval(
         | 
| 692 | 
            +
            		tickInterval / interval, 
         | 
| 693 | 
            +
            		multiples,
         | 
| 694 | 
            +
            		unit[0] === YEAR ? getMagnitude(tickInterval / interval) : 1 // #1913
         | 
| 695 | 
            +
            	);
         | 
| 685 696 |  | 
| 686 697 | 
             
            	return {
         | 
| 687 698 | 
             
            		unitRange: interval,
         | 
| @@ -1146,7 +1157,7 @@ pathAnim = { | |
| 1146 1157 |  | 
| 1147 1158 | 
             
            			// Extend the opacity getter, needed for fading opacity with IE9 and jQuery 1.10+
         | 
| 1148 1159 | 
             
            			wrap(opacityHook, 'get', function (proceed, elem, computed) {
         | 
| 1149 | 
            -
            				return elem.attr ? (elem.opacity || | 
| 1160 | 
            +
            				return elem.attr ? (elem.opacity || 0) : proceed.call(this, elem, computed);
         | 
| 1150 1161 | 
             
            			});
         | 
| 1151 1162 |  | 
| 1152 1163 |  | 
| @@ -1462,7 +1473,7 @@ var | |
| 1462 1473 | 
             
            defaultLabelOptions = {
         | 
| 1463 1474 | 
             
            	enabled: true,
         | 
| 1464 1475 | 
             
            	// rotation: 0,
         | 
| 1465 | 
            -
            	align: 'center',
         | 
| 1476 | 
            +
            	// align: 'center',
         | 
| 1466 1477 | 
             
            	x: 0,
         | 
| 1467 1478 | 
             
            	y: 15,
         | 
| 1468 1479 | 
             
            	/*formatter: function () {
         | 
| @@ -1494,8 +1505,8 @@ defaultOptions = { | |
| 1494 1505 | 
             
            	},
         | 
| 1495 1506 | 
             
            	global: {
         | 
| 1496 1507 | 
             
            		useUTC: true,
         | 
| 1497 | 
            -
            		canvasToolsURL: 'http://code.highcharts.com/3.0. | 
| 1498 | 
            -
            		VMLRadialGradientURL: 'http://code.highcharts.com/3.0. | 
| 1508 | 
            +
            		canvasToolsURL: 'http://code.highcharts.com/3.0.3/modules/canvas-tools.js',
         | 
| 1509 | 
            +
            		VMLRadialGradientURL: 'http://code.highcharts.com/3.0.3/gfx/vml-radial-gradient.png'
         | 
| 1499 1510 | 
             
            	},
         | 
| 1500 1511 | 
             
            	chart: {
         | 
| 1501 1512 | 
             
            		//animation: true,
         | 
| @@ -1546,10 +1557,10 @@ defaultOptions = { | |
| 1546 1557 | 
             
            		text: 'Chart title',
         | 
| 1547 1558 | 
             
            		align: 'center',
         | 
| 1548 1559 | 
             
            		// floating: false,
         | 
| 1549 | 
            -
            		 | 
| 1560 | 
            +
            		margin: 15,
         | 
| 1550 1561 | 
             
            		// x: 0,
         | 
| 1551 1562 | 
             
            		// verticalAlign: 'top',
         | 
| 1552 | 
            -
            		y:  | 
| 1563 | 
            +
            		// y: null,
         | 
| 1553 1564 | 
             
            		style: {
         | 
| 1554 1565 | 
             
            			color: '#274b6d',//#3E576F',
         | 
| 1555 1566 | 
             
            			fontSize: '16px'
         | 
| @@ -1562,7 +1573,7 @@ defaultOptions = { | |
| 1562 1573 | 
             
            		// floating: false
         | 
| 1563 1574 | 
             
            		// x: 0,
         | 
| 1564 1575 | 
             
            		// verticalAlign: 'top',
         | 
| 1565 | 
            -
            		y:  | 
| 1576 | 
            +
            		// y: null,
         | 
| 1566 1577 | 
             
            		style: {
         | 
| 1567 1578 | 
             
            			color: '#4d759e'
         | 
| 1568 1579 | 
             
            		}
         | 
| @@ -1608,9 +1619,10 @@ defaultOptions = { | |
| 1608 1619 | 
             
            				events: {}
         | 
| 1609 1620 | 
             
            			},
         | 
| 1610 1621 | 
             
            			dataLabels: merge(defaultLabelOptions, {
         | 
| 1622 | 
            +
            				align: 'center',
         | 
| 1611 1623 | 
             
            				enabled: false,
         | 
| 1612 1624 | 
             
            				formatter: function () {
         | 
| 1613 | 
            -
            					return numberFormat(this.y, -1);
         | 
| 1625 | 
            +
            					return this.y === null ? '' : numberFormat(this.y, -1);
         | 
| 1614 1626 | 
             
            				},
         | 
| 1615 1627 | 
             
            				verticalAlign: 'bottom', // above singular point
         | 
| 1616 1628 | 
             
            				y: 0
         | 
| @@ -2158,7 +2170,7 @@ SVGElement.prototype = { | |
| 2158 2170 |  | 
| 2159 2171 | 
             
            							i = value.length;
         | 
| 2160 2172 | 
             
            							while (i--) {
         | 
| 2161 | 
            -
            								value[i] = pInt(value[i]) * hash['stroke-width'];
         | 
| 2173 | 
            +
            								value[i] = pInt(value[i]) * pick(hash['stroke-width'], wrapper['stroke-width']);
         | 
| 2162 2174 | 
             
            							}
         | 
| 2163 2175 | 
             
            							value = value.join(',');
         | 
| 2164 2176 | 
             
            						}
         | 
| @@ -2216,7 +2228,7 @@ SVGElement.prototype = { | |
| 2216 2228 | 
             
            					}
         | 
| 2217 2229 |  | 
| 2218 2230 | 
             
            					// let the shadow follow the main element
         | 
| 2219 | 
            -
            					if (shadows && /^(width|height|visibility|x|y|d|transform)$/.test(key)) {
         | 
| 2231 | 
            +
            					if (shadows && /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) {
         | 
| 2220 2232 | 
             
            						i = shadows.length;
         | 
| 2221 2233 | 
             
            						while (i--) {
         | 
| 2222 2234 | 
             
            							attr(
         | 
| @@ -2271,7 +2283,12 @@ SVGElement.prototype = { | |
| 2271 2283 | 
             
            	 * Add a class name to an element
         | 
| 2272 2284 | 
             
            	 */
         | 
| 2273 2285 | 
             
            	addClass: function (className) {
         | 
| 2274 | 
            -
            		 | 
| 2286 | 
            +
            		var element = this.element,
         | 
| 2287 | 
            +
            			currentClassName = attr(element, 'class') || '';
         | 
| 2288 | 
            +
             | 
| 2289 | 
            +
            		if (currentClassName.indexOf(className) === -1) {
         | 
| 2290 | 
            +
            			attr(element, 'class', currentClassName + ' ' + className);
         | 
| 2291 | 
            +
            		}
         | 
| 2275 2292 | 
             
            		return this;
         | 
| 2276 2293 | 
             
            	},
         | 
| 2277 2294 | 
             
            	/* hasClass and removeClass are not (yet) needed
         | 
| @@ -2414,15 +2431,16 @@ SVGElement.prototype = { | |
| 2414 2431 | 
             
            	 * @param {Function} handler
         | 
| 2415 2432 | 
             
            	 */
         | 
| 2416 2433 | 
             
            	on: function (eventType, handler) {
         | 
| 2434 | 
            +
            		var element = this.element;
         | 
| 2417 2435 | 
             
            		// touch
         | 
| 2418 2436 | 
             
            		if (hasTouch && eventType === 'click') {
         | 
| 2419 | 
            -
            			 | 
| 2437 | 
            +
            			element.ontouchstart = function (e) {
         | 
| 2420 2438 | 
             
            				e.preventDefault();
         | 
| 2421 | 
            -
            				handler();
         | 
| 2439 | 
            +
            				handler.call(element, e);
         | 
| 2422 2440 | 
             
            			};
         | 
| 2423 2441 | 
             
            		}
         | 
| 2424 2442 | 
             
            		// simplest possible event model for internal use
         | 
| 2425 | 
            -
            		 | 
| 2443 | 
            +
            		element['on' + eventType] = handler;
         | 
| 2426 2444 | 
             
            		return this;
         | 
| 2427 2445 | 
             
            	},
         | 
| 2428 2446 |  | 
| @@ -2568,33 +2586,18 @@ SVGElement.prototype = { | |
| 2568 2586 | 
             
            				textWidth = pInt(wrapper.textWidth),
         | 
| 2569 2587 | 
             
            				xCorr = wrapper.xCorr || 0,
         | 
| 2570 2588 | 
             
            				yCorr = wrapper.yCorr || 0,
         | 
| 2571 | 
            -
            				currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(',') | 
| 2572 | 
            -
            				rotationStyle = {},
         | 
| 2573 | 
            -
            				cssTransformKey;
         | 
| 2589 | 
            +
            				currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(',');
         | 
| 2574 2590 |  | 
| 2575 2591 | 
             
            			if (currentTextTransform !== wrapper.cTT) { // do the calculations and DOM access only if properties changed
         | 
| 2576 2592 |  | 
| 2577 2593 | 
             
            				if (defined(rotation)) {
         | 
| 2578 2594 |  | 
| 2579 | 
            -
            					 | 
| 2580 | 
            -
             | 
| 2581 | 
            -
             | 
| 2582 | 
            -
             | 
| 2583 | 
            -
            					 | 
| 2584 | 
            -
             | 
| 2585 | 
            -
            						costheta = mathCos(radians);
         | 
| 2586 | 
            -
            						sintheta = mathSin(radians);
         | 
| 2587 | 
            -
            	
         | 
| 2588 | 
            -
            						// Adjust for alignment and rotation. Rotation of useHTML content is not yet implemented
         | 
| 2589 | 
            -
            						// but it can probably be implemented for Firefox 3.5+ on user request. FF3.5+
         | 
| 2590 | 
            -
            						// has support for CSS3 transform. The getBBox method also needs to be updated
         | 
| 2591 | 
            -
            						// to compensate for the rotation, like it currently does for SVG.
         | 
| 2592 | 
            -
            						// Test case: http://highcharts.com/tests/?file=text-rotation
         | 
| 2593 | 
            -
            						rotationStyle.filter = rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta,
         | 
| 2594 | 
            -
            								', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta,
         | 
| 2595 | 
            -
            								', sizingMethod=\'auto expand\')'].join('') : NONE;
         | 
| 2596 | 
            -
            					}
         | 
| 2597 | 
            -
            					css(elem, rotationStyle);
         | 
| 2595 | 
            +
            					radians = rotation * deg2rad; // deg to rad
         | 
| 2596 | 
            +
            					costheta = mathCos(radians);
         | 
| 2597 | 
            +
            					sintheta = mathSin(radians);
         | 
| 2598 | 
            +
            	
         | 
| 2599 | 
            +
            					wrapper.setSpanRotation(rotation, sintheta, costheta);
         | 
| 2600 | 
            +
            					
         | 
| 2598 2601 | 
             
            				}
         | 
| 2599 2602 |  | 
| 2600 2603 | 
             
            				width = pick(wrapper.elemWidth, elem.offsetWidth);
         | 
| @@ -2652,6 +2655,17 @@ SVGElement.prototype = { | |
| 2652 2655 | 
             
            		}
         | 
| 2653 2656 | 
             
            	},
         | 
| 2654 2657 |  | 
| 2658 | 
            +
            	/**
         | 
| 2659 | 
            +
            	 * Set the rotation of an individual HTML span
         | 
| 2660 | 
            +
            	 */
         | 
| 2661 | 
            +
            	setSpanRotation: function (rotation) {
         | 
| 2662 | 
            +
            		var rotationStyle = {},
         | 
| 2663 | 
            +
            			cssTransformKey = isIE ? '-ms-transform' : isWebKit ? '-webkit-transform' : isFirefox ? 'MozTransform' : isOpera ? '-o-transform' : '';
         | 
| 2664 | 
            +
            		
         | 
| 2665 | 
            +
            		rotationStyle[cssTransformKey] = rotationStyle.transform = 'rotate(' + rotation + 'deg)';
         | 
| 2666 | 
            +
            		css(this.element, rotationStyle);
         | 
| 2667 | 
            +
            	},
         | 
| 2668 | 
            +
             | 
| 2655 2669 | 
             
            	/**
         | 
| 2656 2670 | 
             
            	 * Private method to update the transform attribute based on internal
         | 
| 2657 2671 | 
             
            	 * properties
         | 
| @@ -2954,6 +2968,8 @@ SVGElement.prototype = { | |
| 2954 2968 | 
             
            		var wrapper = this,
         | 
| 2955 2969 | 
             
            			element = wrapper.element || {},
         | 
| 2956 2970 | 
             
            			shadows = wrapper.shadows,
         | 
| 2971 | 
            +
            			parentToClean = wrapper.renderer.isSVG && element.nodeName === 'SPAN' && element.parentNode,
         | 
| 2972 | 
            +
            			grandParent,
         | 
| 2957 2973 | 
             
            			key,
         | 
| 2958 2974 | 
             
            			i;
         | 
| 2959 2975 |  | 
| @@ -2983,6 +2999,13 @@ SVGElement.prototype = { | |
| 2983 2999 | 
             
            			});
         | 
| 2984 3000 | 
             
            		}
         | 
| 2985 3001 |  | 
| 3002 | 
            +
            		// In case of useHTML, clean up empty containers emulating SVG groups (#1960).
         | 
| 3003 | 
            +
            		while (parentToClean && parentToClean.childNodes.length === 0) {
         | 
| 3004 | 
            +
            			grandParent = parentToClean.parentNode;
         | 
| 3005 | 
            +
            			wrapper.safeRemoveChild(parentToClean);
         | 
| 3006 | 
            +
            			parentToClean = grandParent;
         | 
| 3007 | 
            +
            		}
         | 
| 3008 | 
            +
             | 
| 2986 3009 | 
             
            		// remove from alignObjects
         | 
| 2987 3010 | 
             
            		if (wrapper.alignTo) {
         | 
| 2988 3011 | 
             
            			erase(wrapper.renderer.alignedObjects, wrapper);
         | 
| @@ -3071,18 +3094,24 @@ SVGRenderer.prototype = { | |
| 3071 3094 | 
             
            		var renderer = this,
         | 
| 3072 3095 | 
             
            			loc = location,
         | 
| 3073 3096 | 
             
            			boxWrapper,
         | 
| 3097 | 
            +
            			element,
         | 
| 3074 3098 | 
             
            			desc;
         | 
| 3075 3099 |  | 
| 3076 3100 | 
             
            		boxWrapper = renderer.createElement('svg')
         | 
| 3077 3101 | 
             
            			.attr({
         | 
| 3078 | 
            -
            				xmlns: SVG_NS,
         | 
| 3079 3102 | 
             
            				version: '1.1'
         | 
| 3080 3103 | 
             
            			});
         | 
| 3081 | 
            -
            		 | 
| 3104 | 
            +
            		element = boxWrapper.element;
         | 
| 3105 | 
            +
            		container.appendChild(element);
         | 
| 3106 | 
            +
             | 
| 3107 | 
            +
            		// For browsers other than IE, add the namespace attribute (#1978)
         | 
| 3108 | 
            +
            		if (container.innerHTML.indexOf('xmlns') === -1) {
         | 
| 3109 | 
            +
            			attr(element, 'xmlns', SVG_NS);
         | 
| 3110 | 
            +
            		}
         | 
| 3082 3111 |  | 
| 3083 3112 | 
             
            		// object properties
         | 
| 3084 3113 | 
             
            		renderer.isSVG = true;
         | 
| 3085 | 
            -
            		renderer.box =  | 
| 3114 | 
            +
            		renderer.box = element;
         | 
| 3086 3115 | 
             
            		renderer.boxWrapper = boxWrapper;
         | 
| 3087 3116 | 
             
            		renderer.alignedObjects = [];
         | 
| 3088 3117 |  | 
| @@ -3203,7 +3232,7 @@ SVGRenderer.prototype = { | |
| 3203 3232 | 
             
            				.split(/<br.*?>/g),
         | 
| 3204 3233 | 
             
            			childNodes = textNode.childNodes,
         | 
| 3205 3234 | 
             
            			styleRegex = /style="([^"]+)"/,
         | 
| 3206 | 
            -
            			hrefRegex = /href="([^"]+)"/,
         | 
| 3235 | 
            +
            			hrefRegex = /href="(http[^"]+)"/,
         | 
| 3207 3236 | 
             
            			parentX = attr(textNode, 'x'),
         | 
| 3208 3237 | 
             
            			textStyles = wrapper.styles,
         | 
| 3209 3238 | 
             
            			width = textStyles && textStyles.width && pInt(textStyles.width),
         | 
| @@ -3249,82 +3278,86 @@ SVGRenderer.prototype = { | |
| 3249 3278 | 
             
            						.replace(/</g, '<')
         | 
| 3250 3279 | 
             
            						.replace(/>/g, '>');
         | 
| 3251 3280 |  | 
| 3252 | 
            -
            					//  | 
| 3253 | 
            -
            					 | 
| 3254 | 
            -
             | 
| 3255 | 
            -
             | 
| 3256 | 
            -
            						 | 
| 3257 | 
            -
            					} else {
         | 
| 3258 | 
            -
            						attributes.dx = 0; // #16
         | 
| 3259 | 
            -
            					}
         | 
| 3281 | 
            +
            					// Nested tags aren't supported, and cause crash in Safari (#1596)
         | 
| 3282 | 
            +
            					if (span !== ' ') {
         | 
| 3283 | 
            +
            					
         | 
| 3284 | 
            +
            						// add the text node
         | 
| 3285 | 
            +
            						tspan.appendChild(doc.createTextNode(span));
         | 
| 3260 3286 |  | 
| 3261 | 
            -
             | 
| 3262 | 
            -
             | 
| 3287 | 
            +
            						if (!spanNo) { // first span in a line, align it to the left
         | 
| 3288 | 
            +
            							attributes.x = parentX;
         | 
| 3289 | 
            +
            						} else {
         | 
| 3290 | 
            +
            							attributes.dx = 0; // #16
         | 
| 3291 | 
            +
            						}
         | 
| 3263 3292 |  | 
| 3264 | 
            -
             | 
| 3265 | 
            -
             | 
| 3293 | 
            +
            						// add attributes
         | 
| 3294 | 
            +
            						attr(tspan, attributes);
         | 
| 3266 3295 |  | 
| 3267 | 
            -
            						//  | 
| 3268 | 
            -
            						if (! | 
| 3269 | 
            -
            							css(tspan, { display: 'block' });
         | 
| 3270 | 
            -
            						}
         | 
| 3296 | 
            +
            						// first span on subsequent line, add the line height
         | 
| 3297 | 
            +
            						if (!spanNo && lineNo) {
         | 
| 3271 3298 |  | 
| 3272 | 
            -
             | 
| 3273 | 
            -
             | 
| 3274 | 
            -
             | 
| 3275 | 
            -
            							 | 
| 3276 | 
            -
            							'dy',
         | 
| 3277 | 
            -
            							textLineHeight || renderer.fontMetrics(
         | 
| 3278 | 
            -
            								/px$/.test(tspan.style.fontSize) ?
         | 
| 3279 | 
            -
            									tspan.style.fontSize : 
         | 
| 3280 | 
            -
            									textStyles.fontSize
         | 
| 3281 | 
            -
            							).h,
         | 
| 3282 | 
            -
            							// Safari 6.0.2 - too optimized for its own good (#1539)
         | 
| 3283 | 
            -
            							// TODO: revisit this with future versions of Safari
         | 
| 3284 | 
            -
            							isWebKit && tspan.offsetHeight
         | 
| 3285 | 
            -
            						);
         | 
| 3286 | 
            -
            					}
         | 
| 3299 | 
            +
            							// allow getting the right offset height in exporting in IE
         | 
| 3300 | 
            +
            							if (!hasSVG && forExport) {
         | 
| 3301 | 
            +
            								css(tspan, { display: 'block' });
         | 
| 3302 | 
            +
            							}
         | 
| 3287 3303 |  | 
| 3288 | 
            -
             | 
| 3289 | 
            -
             | 
| 3304 | 
            +
            							// Set the line height based on the font size of either 
         | 
| 3305 | 
            +
            							// the text element or the tspan element
         | 
| 3306 | 
            +
            							attr(
         | 
| 3307 | 
            +
            								tspan, 
         | 
| 3308 | 
            +
            								'dy',
         | 
| 3309 | 
            +
            								textLineHeight || renderer.fontMetrics(
         | 
| 3310 | 
            +
            									/px$/.test(tspan.style.fontSize) ?
         | 
| 3311 | 
            +
            										tspan.style.fontSize : 
         | 
| 3312 | 
            +
            										textStyles.fontSize
         | 
| 3313 | 
            +
            								).h,
         | 
| 3314 | 
            +
            								// Safari 6.0.2 - too optimized for its own good (#1539)
         | 
| 3315 | 
            +
            								// TODO: revisit this with future versions of Safari
         | 
| 3316 | 
            +
            								isWebKit && tspan.offsetHeight
         | 
| 3317 | 
            +
            							);
         | 
| 3318 | 
            +
            						}
         | 
| 3290 3319 |  | 
| 3291 | 
            -
             | 
| 3320 | 
            +
            						// Append it
         | 
| 3321 | 
            +
            						textNode.appendChild(tspan);
         | 
| 3292 3322 |  | 
| 3293 | 
            -
             | 
| 3294 | 
            -
            					if (width) {
         | 
| 3295 | 
            -
            						var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
         | 
| 3296 | 
            -
            							tooLong,
         | 
| 3297 | 
            -
            							actualWidth,
         | 
| 3298 | 
            -
            							rest = [];
         | 
| 3323 | 
            +
            						spanNo++;
         | 
| 3299 3324 |  | 
| 3300 | 
            -
            						 | 
| 3301 | 
            -
             | 
| 3302 | 
            -
            							 | 
| 3303 | 
            -
             | 
| 3304 | 
            -
             | 
| 3305 | 
            -
            								words = rest;
         | 
| 3325 | 
            +
            						// check width and apply soft breaks
         | 
| 3326 | 
            +
            						if (width) {
         | 
| 3327 | 
            +
            							var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
         | 
| 3328 | 
            +
            								tooLong,
         | 
| 3329 | 
            +
            								actualWidth,
         | 
| 3306 3330 | 
             
            								rest = [];
         | 
| 3307 | 
            -
            								if (words.length) {
         | 
| 3308 | 
            -
            									tspan = doc.createElementNS(SVG_NS, 'tspan');
         | 
| 3309 | 
            -
            									attr(tspan, {
         | 
| 3310 | 
            -
            										dy: textLineHeight || 16,
         | 
| 3311 | 
            -
            										x: parentX
         | 
| 3312 | 
            -
            									});
         | 
| 3313 | 
            -
            									if (spanStyle) { // #390
         | 
| 3314 | 
            -
            										attr(tspan, 'style', spanStyle);
         | 
| 3315 | 
            -
            									}
         | 
| 3316 | 
            -
            									textNode.appendChild(tspan);
         | 
| 3317 3331 |  | 
| 3318 | 
            -
             | 
| 3319 | 
            -
             | 
| 3332 | 
            +
            							while (words.length || rest.length) {
         | 
| 3333 | 
            +
            								delete wrapper.bBox; // delete cache
         | 
| 3334 | 
            +
            								actualWidth = wrapper.getBBox().width;
         | 
| 3335 | 
            +
            								tooLong = actualWidth > width;
         | 
| 3336 | 
            +
            								if (!tooLong || words.length === 1) { // new line needed
         | 
| 3337 | 
            +
            									words = rest;
         | 
| 3338 | 
            +
            									rest = [];
         | 
| 3339 | 
            +
            									if (words.length) {
         | 
| 3340 | 
            +
            										tspan = doc.createElementNS(SVG_NS, 'tspan');
         | 
| 3341 | 
            +
            										attr(tspan, {
         | 
| 3342 | 
            +
            											dy: textLineHeight || 16,
         | 
| 3343 | 
            +
            											x: parentX
         | 
| 3344 | 
            +
            										});
         | 
| 3345 | 
            +
            										if (spanStyle) { // #390
         | 
| 3346 | 
            +
            											attr(tspan, 'style', spanStyle);
         | 
| 3347 | 
            +
            										}
         | 
| 3348 | 
            +
            										textNode.appendChild(tspan);
         | 
| 3349 | 
            +
             | 
| 3350 | 
            +
            										if (actualWidth > width) { // a single word is pressing it out
         | 
| 3351 | 
            +
            											width = actualWidth;
         | 
| 3352 | 
            +
            										}
         | 
| 3320 3353 | 
             
            									}
         | 
| 3354 | 
            +
            								} else { // append to existing line tspan
         | 
| 3355 | 
            +
            									tspan.removeChild(tspan.firstChild);
         | 
| 3356 | 
            +
            									rest.unshift(words.pop());
         | 
| 3357 | 
            +
            								}
         | 
| 3358 | 
            +
            								if (words.length) {
         | 
| 3359 | 
            +
            									tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
         | 
| 3321 3360 | 
             
            								}
         | 
| 3322 | 
            -
            							} else { // append to existing line tspan
         | 
| 3323 | 
            -
            								tspan.removeChild(tspan.firstChild);
         | 
| 3324 | 
            -
            								rest.unshift(words.pop());
         | 
| 3325 | 
            -
            							}
         | 
| 3326 | 
            -
            							if (words.length) {
         | 
| 3327 | 
            -
            								tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
         | 
| 3328 3361 | 
             
            							}
         | 
| 3329 3362 | 
             
            						}
         | 
| 3330 3363 | 
             
            					}
         | 
| @@ -3402,12 +3435,12 @@ SVGRenderer.prototype = { | |
| 3402 3435 | 
             
            		pressedStyle = pressedState[STYLE];
         | 
| 3403 3436 | 
             
            		delete pressedState[STYLE];
         | 
| 3404 3437 |  | 
| 3405 | 
            -
            		//  | 
| 3406 | 
            -
            		addEvent(label.element, 'mouseenter', function () {
         | 
| 3438 | 
            +
            		// Add the events. IE9 and IE10 need mouseover and mouseout to funciton (#667).
         | 
| 3439 | 
            +
            		addEvent(label.element, isIE ? 'mouseover' : 'mouseenter', function () {
         | 
| 3407 3440 | 
             
            			label.attr(hoverState)
         | 
| 3408 3441 | 
             
            				.css(hoverStyle);
         | 
| 3409 3442 | 
             
            		});
         | 
| 3410 | 
            -
            		addEvent(label.element, 'mouseleave', function () {
         | 
| 3443 | 
            +
            		addEvent(label.element, isIE ? 'mouseout' : 'mouseleave', function () {
         | 
| 3411 3444 | 
             
            			stateOptions = [normalState, hoverState, pressedState][curState];
         | 
| 3412 3445 | 
             
            			stateStyle = [normalStyle, hoverStyle, pressedStyle][curState];
         | 
| 3413 3446 | 
             
            			label.attr(stateOptions)
         | 
| @@ -3496,8 +3529,7 @@ SVGRenderer.prototype = { | |
| 3496 3529 | 
             
            	 * @param {Number} end Ending angle
         | 
| 3497 3530 | 
             
            	 */
         | 
| 3498 3531 | 
             
            	arc: function (x, y, r, innerR, start, end) {
         | 
| 3499 | 
            -
            		 | 
| 3500 | 
            -
            		// attributes in attr and animate
         | 
| 3532 | 
            +
            		var arc;
         | 
| 3501 3533 |  | 
| 3502 3534 | 
             
            		if (isObject(x)) {
         | 
| 3503 3535 | 
             
            			y = x.y;
         | 
| @@ -3507,11 +3539,16 @@ SVGRenderer.prototype = { | |
| 3507 3539 | 
             
            			end = x.end;
         | 
| 3508 3540 | 
             
            			x = x.x;
         | 
| 3509 3541 | 
             
            		}
         | 
| 3510 | 
            -
            		 | 
| 3542 | 
            +
            		
         | 
| 3543 | 
            +
            		// Arcs are defined as symbols for the ability to set
         | 
| 3544 | 
            +
            		// attributes in attr and animate
         | 
| 3545 | 
            +
            		arc = this.symbol('arc', x || 0, y || 0, r || 0, r || 0, {
         | 
| 3511 3546 | 
             
            			innerR: innerR || 0,
         | 
| 3512 3547 | 
             
            			start: start || 0,
         | 
| 3513 3548 | 
             
            			end: end || 0
         | 
| 3514 3549 | 
             
            		});
         | 
| 3550 | 
            +
            		arc.r = r; // #959
         | 
| 3551 | 
            +
            		return arc;
         | 
| 3515 3552 | 
             
            	},
         | 
| 3516 3553 |  | 
| 3517 3554 | 
             
            	/**
         | 
| @@ -4537,6 +4574,22 @@ Highcharts.VMLElement = VMLElement = { | |
| 4537 4574 | 
             
            	 */
         | 
| 4538 4575 | 
             
            	updateTransform: SVGElement.prototype.htmlUpdateTransform,
         | 
| 4539 4576 |  | 
| 4577 | 
            +
            	/**
         | 
| 4578 | 
            +
            	 * Set the rotation of a span with oldIE's filter
         | 
| 4579 | 
            +
            	 */
         | 
| 4580 | 
            +
            	setSpanRotation: function (rotation, sintheta, costheta) {
         | 
| 4581 | 
            +
            		// Adjust for alignment and rotation. Rotation of useHTML content is not yet implemented
         | 
| 4582 | 
            +
            		// but it can probably be implemented for Firefox 3.5+ on user request. FF3.5+
         | 
| 4583 | 
            +
            		// has support for CSS3 transform. The getBBox method also needs to be updated
         | 
| 4584 | 
            +
            		// to compensate for the rotation, like it currently does for SVG.
         | 
| 4585 | 
            +
            		// Test case: http://highcharts.com/tests/?file=text-rotation
         | 
| 4586 | 
            +
            		css(this.element, {
         | 
| 4587 | 
            +
            			filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta,
         | 
| 4588 | 
            +
            				', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta,
         | 
| 4589 | 
            +
            				', sizingMethod=\'auto expand\')'].join('') : NONE
         | 
| 4590 | 
            +
            		});
         | 
| 4591 | 
            +
            	},
         | 
| 4592 | 
            +
             | 
| 4540 4593 | 
             
            	/**
         | 
| 4541 4594 | 
             
            	 * Get or set attributes
         | 
| 4542 4595 | 
             
            	 */
         | 
| @@ -4759,7 +4812,9 @@ Highcharts.VMLElement = VMLElement = { | |
| 4759 4812 |  | 
| 4760 4813 | 
             
            					// rotation on VML elements
         | 
| 4761 4814 | 
             
            					} else if (nodeName === 'shape' && key === 'rotation') {
         | 
| 4762 | 
            -
            						 | 
| 4815 | 
            +
            						
         | 
| 4816 | 
            +
            						wrapper[key] = element.style[key] = value; // style is for #1873
         | 
| 4817 | 
            +
             | 
| 4763 4818 | 
             
            						// Correction for the 1x1 size of the shape container. Used in gauge needles.
         | 
| 4764 4819 | 
             
            						element.style.left = -mathRound(mathSin(value * deg2rad) + 1) + PX;
         | 
| 4765 4820 | 
             
            						element.style.top = mathRound(mathCos(value * deg2rad)) + PX;
         | 
| @@ -5669,7 +5724,7 @@ Tick.prototype = { | |
| 5669 5724 | 
             
            				!labelOptions.step && !labelOptions.staggerLines &&
         | 
| 5670 5725 | 
             
            				!labelOptions.rotation &&
         | 
| 5671 5726 | 
             
            				chart.plotWidth / tickPositions.length) ||
         | 
| 5672 | 
            -
            				(!horiz && (chart.optionsMarginLeft || chart. | 
| 5727 | 
            +
            				(!horiz && (chart.optionsMarginLeft || chart.chartWidth * 0.33)), // #1580, #1931
         | 
| 5673 5728 | 
             
            			isFirst = pos === tickPositions[0],
         | 
| 5674 5729 | 
             
            			isLast = pos === tickPositions[tickPositions.length - 1],
         | 
| 5675 5730 | 
             
            			css,
         | 
| @@ -5708,7 +5763,7 @@ Tick.prototype = { | |
| 5708 5763 | 
             
            		// first call
         | 
| 5709 5764 | 
             
            		if (!defined(label)) {
         | 
| 5710 5765 | 
             
            			attr = {
         | 
| 5711 | 
            -
            				align:  | 
| 5766 | 
            +
            				align: axis.labelAlign
         | 
| 5712 5767 | 
             
            			};
         | 
| 5713 5768 | 
             
            			if (isNumber(labelOptions.rotation)) {
         | 
| 5714 5769 | 
             
            				attr.rotation = labelOptions.rotation;
         | 
| @@ -5757,7 +5812,7 @@ Tick.prototype = { | |
| 5757 5812 | 
             
            			options = axis.options,
         | 
| 5758 5813 | 
             
            			labelOptions = options.labels,
         | 
| 5759 5814 | 
             
            			width = bBox.width,
         | 
| 5760 | 
            -
            			leftSide = width * { left: 0, center: 0.5, right: 1 }[ | 
| 5815 | 
            +
            			leftSide = width * { left: 0, center: 0.5, right: 1 }[axis.labelAlign] - labelOptions.x;
         | 
| 5761 5816 |  | 
| 5762 5817 | 
             
            		return [-leftSide, width - leftSide];
         | 
| 5763 5818 | 
             
            	},
         | 
| @@ -5847,21 +5902,28 @@ Tick.prototype = { | |
| 5847 5902 | 
             
            		var axis = this.axis,
         | 
| 5848 5903 | 
             
            			transA = axis.transA,
         | 
| 5849 5904 | 
             
            			reversed = axis.reversed,
         | 
| 5850 | 
            -
            			staggerLines = axis.staggerLines | 
| 5905 | 
            +
            			staggerLines = axis.staggerLines,
         | 
| 5906 | 
            +
            			baseline = axis.chart.renderer.fontMetrics(labelOptions.style.fontSize).b,
         | 
| 5907 | 
            +
            			rotation = labelOptions.rotation;
         | 
| 5851 5908 |  | 
| 5852 5909 | 
             
            		x = x + labelOptions.x - (tickmarkOffset && horiz ?
         | 
| 5853 5910 | 
             
            			tickmarkOffset * transA * (reversed ? -1 : 1) : 0);
         | 
| 5854 5911 | 
             
            		y = y + labelOptions.y - (tickmarkOffset && !horiz ?
         | 
| 5855 5912 | 
             
            			tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
         | 
| 5913 | 
            +
             | 
| 5914 | 
            +
            		// Correct for rotation (#1764)
         | 
| 5915 | 
            +
            		if (rotation && axis.side === 2) {
         | 
| 5916 | 
            +
            			y -= baseline - baseline * mathCos(rotation * deg2rad);
         | 
| 5917 | 
            +
            		}
         | 
| 5856 5918 |  | 
| 5857 5919 | 
             
            		// Vertically centered
         | 
| 5858 | 
            -
            		if (!defined(labelOptions.y)) {
         | 
| 5859 | 
            -
            			y +=  | 
| 5920 | 
            +
            		if (!defined(labelOptions.y) && !rotation) { // #1951
         | 
| 5921 | 
            +
            			y += baseline - label.getBBox().height / 2;
         | 
| 5860 5922 | 
             
            		}
         | 
| 5861 5923 |  | 
| 5862 5924 | 
             
            		// Correct for staggered labels
         | 
| 5863 5925 | 
             
            		if (staggerLines) {
         | 
| 5864 | 
            -
            			y += (index / (step || 1) % staggerLines) *  | 
| 5926 | 
            +
            			y += (index / (step || 1) % staggerLines) * (axis.labelOffset / staggerLines);
         | 
| 5865 5927 | 
             
            		}
         | 
| 5866 5928 |  | 
| 5867 5929 | 
             
            		return {
         | 
| @@ -6160,7 +6222,8 @@ PlotLineOrBand.prototype = { | |
| 6160 6222 | 
             
            				plotLine.label = label = renderer.text(
         | 
| 6161 6223 | 
             
            						optionsLabel.text,
         | 
| 6162 6224 | 
             
            						0,
         | 
| 6163 | 
            -
            						0
         | 
| 6225 | 
            +
            						0,
         | 
| 6226 | 
            +
            						optionsLabel.useHTML // docs: useHTML for plotLines and plotBands
         | 
| 6164 6227 | 
             
            					)
         | 
| 6165 6228 | 
             
            					.attr({
         | 
| 6166 6229 | 
             
            						align: optionsLabel.textAlign || optionsLabel.align,
         | 
| @@ -6224,6 +6287,12 @@ function StackItem(axis, options, isNegative, x, stackOption, stacking) { | |
| 6224 6287 | 
             
            	// Save the x value to be able to position the label later
         | 
| 6225 6288 | 
             
            	this.x = x;
         | 
| 6226 6289 |  | 
| 6290 | 
            +
            	// Initialize total value
         | 
| 6291 | 
            +
            	this.total = 0;
         | 
| 6292 | 
            +
             | 
| 6293 | 
            +
            	// This will keep each points' extremes stored by series.index
         | 
| 6294 | 
            +
            	this.points = {};
         | 
| 6295 | 
            +
             | 
| 6227 6296 | 
             
            	// Save the stack option on the series configuration object, and whether to treat it as percent
         | 
| 6228 6297 | 
             
            	this.stack = stackOption;
         | 
| 6229 6298 | 
             
            	this.percent = stacking === 'percent';
         | 
| @@ -6255,12 +6324,19 @@ StackItem.prototype = { | |
| 6255 6324 | 
             
            		this.cum = total;
         | 
| 6256 6325 | 
             
            	},
         | 
| 6257 6326 |  | 
| 6327 | 
            +
            	/**
         | 
| 6328 | 
            +
            	 * Adds value to stack total, this method takes care of correcting floats
         | 
| 6329 | 
            +
            	 */
         | 
| 6330 | 
            +
            	addValue: function (y) {
         | 
| 6331 | 
            +
            		this.setTotal(correctFloat(this.total + y));
         | 
| 6332 | 
            +
            	},
         | 
| 6333 | 
            +
             | 
| 6258 6334 | 
             
            	/**
         | 
| 6259 6335 | 
             
            	 * Renders the stack total label and adds it to the stack label group.
         | 
| 6260 6336 | 
             
            	 */
         | 
| 6261 6337 | 
             
            	render: function (group) {
         | 
| 6262 6338 | 
             
            		var options = this.options,
         | 
| 6263 | 
            -
            			formatOption = options.format, | 
| 6339 | 
            +
            			formatOption = options.format,
         | 
| 6264 6340 | 
             
            			str = formatOption ?
         | 
| 6265 6341 | 
             
            				format(formatOption, this) : 
         | 
| 6266 6342 | 
             
            				options.formatter.call(this);  // format the text in the label
         | 
| @@ -6282,6 +6358,10 @@ StackItem.prototype = { | |
| 6282 6358 | 
             
            		}
         | 
| 6283 6359 | 
             
            	},
         | 
| 6284 6360 |  | 
| 6361 | 
            +
            	cacheExtremes: function (series, extremes) {
         | 
| 6362 | 
            +
            		this.points[series.index] = extremes;
         | 
| 6363 | 
            +
            	},
         | 
| 6364 | 
            +
             | 
| 6285 6365 | 
             
            	/**
         | 
| 6286 6366 | 
             
            	 * Sets the offset that the stack has from the x value and repositions the label.
         | 
| 6287 6367 | 
             
            	 */
         | 
| @@ -6421,7 +6501,6 @@ Axis.prototype = { | |
| 6421 6501 | 
             
            		tickPixelInterval: 72,
         | 
| 6422 6502 | 
             
            		showLastLabel: true,
         | 
| 6423 6503 | 
             
            		labels: {
         | 
| 6424 | 
            -
            			align: 'right',
         | 
| 6425 6504 | 
             
            			x: -8,
         | 
| 6426 6505 | 
             
            			y: 3
         | 
| 6427 6506 | 
             
            		},
         | 
| @@ -6454,7 +6533,6 @@ Axis.prototype = { | |
| 6454 6533 | 
             
            	 */
         | 
| 6455 6534 | 
             
            	defaultLeftAxisOptions: {
         | 
| 6456 6535 | 
             
            		labels: {
         | 
| 6457 | 
            -
            			align: 'right',
         | 
| 6458 6536 | 
             
            			x: -8,
         | 
| 6459 6537 | 
             
            			y: null
         | 
| 6460 6538 | 
             
            		},
         | 
| @@ -6468,7 +6546,6 @@ Axis.prototype = { | |
| 6468 6546 | 
             
            	 */
         | 
| 6469 6547 | 
             
            	defaultRightAxisOptions: {
         | 
| 6470 6548 | 
             
            		labels: {
         | 
| 6471 | 
            -
            			align: 'left',
         | 
| 6472 6549 | 
             
            			x: 8,
         | 
| 6473 6550 | 
             
            			y: null
         | 
| 6474 6551 | 
             
            		},
         | 
| @@ -6482,7 +6559,6 @@ Axis.prototype = { | |
| 6482 6559 | 
             
            	 */
         | 
| 6483 6560 | 
             
            	defaultBottomAxisOptions: {
         | 
| 6484 6561 | 
             
            		labels: {
         | 
| 6485 | 
            -
            			align: 'center',
         | 
| 6486 6562 | 
             
            			x: 0,
         | 
| 6487 6563 | 
             
            			y: 14
         | 
| 6488 6564 | 
             
            			// overflow: undefined,
         | 
| @@ -6497,7 +6573,6 @@ Axis.prototype = { | |
| 6497 6573 | 
             
            	 */
         | 
| 6498 6574 | 
             
            	defaultTopAxisOptions: {
         | 
| 6499 6575 | 
             
            		labels: {
         | 
| 6500 | 
            -
            			align: 'center',
         | 
| 6501 6576 | 
             
            			x: 0,
         | 
| 6502 6577 | 
             
            			y: -5
         | 
| 6503 6578 | 
             
            			// overflow: undefined
         | 
| @@ -6541,7 +6616,6 @@ Axis.prototype = { | |
| 6541 6616 |  | 
| 6542 6617 |  | 
| 6543 6618 | 
             
            		// Flag, stagger lines or not
         | 
| 6544 | 
            -
            		axis.staggerLines = axis.horiz && options.labels.staggerLines;
         | 
| 6545 6619 | 
             
            		axis.userOptions = userOptions;
         | 
| 6546 6620 |  | 
| 6547 6621 | 
             
            		//axis.axisTitleMargin = UNDEFINED,// = options.title.margin,
         | 
| @@ -6619,8 +6693,13 @@ Axis.prototype = { | |
| 6619 6693 |  | 
| 6620 6694 | 
             
            		// Dictionary for stacks
         | 
| 6621 6695 | 
             
            		axis.stacks = {};
         | 
| 6696 | 
            +
            		axis.oldStacks = {};
         | 
| 6697 | 
            +
             | 
| 6698 | 
            +
            		// Dictionary for stacks max values
         | 
| 6699 | 
            +
            		axis.stacksMax = {};
         | 
| 6700 | 
            +
             | 
| 6622 6701 | 
             
            		axis._stacksTouched = 0;
         | 
| 6623 | 
            -
             | 
| 6702 | 
            +
             | 
| 6624 6703 | 
             
            		// Min and max in the data
         | 
| 6625 6704 | 
             
            		//axis.dataMin = UNDEFINED,
         | 
| 6626 6705 | 
             
            		//axis.dataMax = UNDEFINED,
         | 
| @@ -6691,10 +6770,10 @@ Axis.prototype = { | |
| 6691 6770 |  | 
| 6692 6771 | 
             
            		newOptions = chart.options[this.xOrY + 'Axis'][this.options.index] = merge(this.userOptions, newOptions);
         | 
| 6693 6772 |  | 
| 6694 | 
            -
            		this.destroy();
         | 
| 6773 | 
            +
            		this.destroy(true);
         | 
| 6695 6774 | 
             
            		this._addedPlotLB = false; // #1611
         | 
| 6696 6775 |  | 
| 6697 | 
            -
            		this.init(chart, newOptions);
         | 
| 6776 | 
            +
            		this.init(chart, extend(newOptions, { events: UNDEFINED }));
         | 
| 6698 6777 |  | 
| 6699 6778 | 
             
            		chart.isDirtyBox = true;
         | 
| 6700 6779 | 
             
            		if (pick(redraw, true)) {
         | 
| @@ -6778,25 +6857,24 @@ Axis.prototype = { | |
| 6778 6857 |  | 
| 6779 6858 | 
             
            		return ret;
         | 
| 6780 6859 | 
             
            	},
         | 
| 6781 | 
            -
             | 
| 6860 | 
            +
             | 
| 6782 6861 | 
             
            	/**
         | 
| 6783 6862 | 
             
            	 * Get the minimum and maximum for the series of each axis
         | 
| 6784 6863 | 
             
            	 */
         | 
| 6785 6864 | 
             
            	getSeriesExtremes: function () {
         | 
| 6786 6865 | 
             
            		var axis = this,
         | 
| 6787 | 
            -
            			chart = axis.chart | 
| 6788 | 
            -
             | 
| 6789 | 
            -
            			posStack = [],
         | 
| 6790 | 
            -
            			negStack = [],
         | 
| 6791 | 
            -
            			stacksTouched = axis._stacksTouched = axis._stacksTouched + 1,
         | 
| 6792 | 
            -
            			type,
         | 
| 6793 | 
            -
            			i;
         | 
| 6794 | 
            -
            		
         | 
| 6866 | 
            +
            			chart = axis.chart;
         | 
| 6867 | 
            +
             | 
| 6795 6868 | 
             
            		axis.hasVisibleSeries = false;
         | 
| 6796 6869 |  | 
| 6797 6870 | 
             
            		// reset dataMin and dataMax in case we're redrawing
         | 
| 6798 6871 | 
             
            		axis.dataMin = axis.dataMax = null;
         | 
| 6799 6872 |  | 
| 6873 | 
            +
            		// reset cached stacking extremes
         | 
| 6874 | 
            +
            		axis.stacksMax = {};
         | 
| 6875 | 
            +
             | 
| 6876 | 
            +
            		axis.buildStacks();
         | 
| 6877 | 
            +
             | 
| 6800 6878 | 
             
            		// loop through this axis' series
         | 
| 6801 6879 | 
             
            		each(axis.series, function (series) {
         | 
| 6802 6880 |  | 
| @@ -6804,27 +6882,16 @@ Axis.prototype = { | |
| 6804 6882 |  | 
| 6805 6883 | 
             
            				var seriesOptions = series.options,
         | 
| 6806 6884 | 
             
            					stacking,
         | 
| 6807 | 
            -
            					posPointStack,
         | 
| 6808 | 
            -
            					negPointStack,
         | 
| 6809 | 
            -
            					stackKey,
         | 
| 6810 | 
            -
            					stackOption,
         | 
| 6811 | 
            -
            					negKey,
         | 
| 6812 6885 | 
             
            					xData,
         | 
| 6813 | 
            -
            					yData,
         | 
| 6814 | 
            -
            					x,
         | 
| 6815 | 
            -
            					y,
         | 
| 6816 6886 | 
             
            					threshold = seriesOptions.threshold,
         | 
| 6817 | 
            -
            					yDataLength,
         | 
| 6818 | 
            -
            					activeYData = [],
         | 
| 6819 6887 | 
             
            					seriesDataMin,
         | 
| 6820 | 
            -
            					seriesDataMax | 
| 6821 | 
            -
             | 
| 6822 | 
            -
             | 
| 6823 | 
            -
             | 
| 6824 | 
            -
            					
         | 
| 6888 | 
            +
            					seriesDataMax;
         | 
| 6889 | 
            +
             | 
| 6890 | 
            +
            				axis.hasVisibleSeries = true;
         | 
| 6891 | 
            +
             | 
| 6825 6892 | 
             
            				// Validate threshold in logarithmic axes
         | 
| 6826 6893 | 
             
            				if (axis.isLog && threshold <= 0) {
         | 
| 6827 | 
            -
            					threshold =  | 
| 6894 | 
            +
            					threshold = null;
         | 
| 6828 6895 | 
             
            				}
         | 
| 6829 6896 |  | 
| 6830 6897 | 
             
            				// Get dataMin and dataMax for X axes
         | 
| @@ -6837,112 +6904,27 @@ Axis.prototype = { | |
| 6837 6904 |  | 
| 6838 6905 | 
             
            				// Get dataMin and dataMax for Y axes, as well as handle stacking and processed data
         | 
| 6839 6906 | 
             
            				} else {
         | 
| 6840 | 
            -
            					var isNegative,
         | 
| 6841 | 
            -
            						pointStack,
         | 
| 6842 | 
            -
            						key,
         | 
| 6843 | 
            -
            						cropped = series.cropped,
         | 
| 6844 | 
            -
            						xExtremes = series.xAxis.getExtremes(),
         | 
| 6845 | 
            -
            						//findPointRange,
         | 
| 6846 | 
            -
            						//pointRange,
         | 
| 6847 | 
            -
            						j,
         | 
| 6848 | 
            -
            						hasModifyValue = !!series.modifyValue;
         | 
| 6849 6907 |  | 
| 6850 6908 | 
             
            					// Handle stacking
         | 
| 6851 6909 | 
             
            					stacking = seriesOptions.stacking;
         | 
| 6852 6910 | 
             
            					axis.usePercentage = stacking === 'percent';
         | 
| 6853 6911 |  | 
| 6854 6912 | 
             
            					// create a stack for this particular series type
         | 
| 6855 | 
            -
            					if (stacking) {
         | 
| 6856 | 
            -
            						stackOption = seriesOptions.stack;
         | 
| 6857 | 
            -
            						stackKey = series.type + pick(stackOption, '');
         | 
| 6858 | 
            -
            						negKey = '-' + stackKey;
         | 
| 6859 | 
            -
            						series.stackKey = stackKey; // used in translate
         | 
| 6860 | 
            -
             | 
| 6861 | 
            -
            						posPointStack = posStack[stackKey] || []; // contains the total values for each x
         | 
| 6862 | 
            -
            						posStack[stackKey] = posPointStack;
         | 
| 6863 | 
            -
             | 
| 6864 | 
            -
            						negPointStack = negStack[negKey] || [];
         | 
| 6865 | 
            -
            						negStack[negKey] = negPointStack;
         | 
| 6866 | 
            -
            					}
         | 
| 6867 6913 | 
             
            					if (axis.usePercentage) {
         | 
| 6868 6914 | 
             
            						axis.dataMin = 0;
         | 
| 6869 6915 | 
             
            						axis.dataMax = 99;
         | 
| 6870 6916 | 
             
            					}
         | 
| 6871 6917 |  | 
| 6872 | 
            -
            					 | 
| 6873 | 
            -
            					// | 
| 6874 | 
            -
             | 
| 6875 | 
            -
            					 | 
| 6876 | 
            -
            					 | 
| 6877 | 
            -
            					yDataLength = yData.length;
         | 
| 6878 | 
            -
             | 
| 6879 | 
            -
            					// loop over the non-null y values and read them into a local array
         | 
| 6880 | 
            -
            					for (i = 0; i < yDataLength; i++) {
         | 
| 6881 | 
            -
            						x = xData[i];
         | 
| 6882 | 
            -
            						y = yData[i];
         | 
| 6883 | 
            -
            						
         | 
| 6884 | 
            -
            						// Read stacked values into a stack based on the x value,
         | 
| 6885 | 
            -
            						// the sign of y and the stack key. Stacking is also handled for null values (#739)
         | 
| 6886 | 
            -
            						if (stacking) {
         | 
| 6887 | 
            -
            							isNegative = y < threshold;
         | 
| 6888 | 
            -
            							pointStack = isNegative ? negPointStack : posPointStack;
         | 
| 6889 | 
            -
            							key = isNegative ? negKey : stackKey;
         | 
| 6890 | 
            -
             | 
| 6891 | 
            -
            							// Set the stack value and y for extremes
         | 
| 6892 | 
            -
            							if (defined(pointStack[x])) { // we're adding to the stack
         | 
| 6893 | 
            -
            								pointStack[x] = correctFloat(pointStack[x] + y);
         | 
| 6894 | 
            -
            								y = [y, pointStack[x]]; // consider both the actual value and the stack (#1376)
         | 
| 6895 | 
            -
             | 
| 6896 | 
            -
            							} else { // it's the first point in the stack
         | 
| 6897 | 
            -
            								pointStack[x] = y;
         | 
| 6898 | 
            -
            							}
         | 
| 6899 | 
            -
             | 
| 6900 | 
            -
            							// add the series
         | 
| 6901 | 
            -
            							if (!stacks[key]) {
         | 
| 6902 | 
            -
            								stacks[key] = {};
         | 
| 6903 | 
            -
            							}
         | 
| 6904 | 
            -
             | 
| 6905 | 
            -
            							// If the StackItem is there, just update the values,
         | 
| 6906 | 
            -
            							// if not, create one first
         | 
| 6907 | 
            -
            							if (!stacks[key][x]) {
         | 
| 6908 | 
            -
            								stacks[key][x] = new StackItem(axis, axis.options.stackLabels, isNegative, x, stackOption, stacking);
         | 
| 6909 | 
            -
            							}
         | 
| 6910 | 
            -
            							stacks[key][x].setTotal(pointStack[x]);
         | 
| 6911 | 
            -
            							stacks[key][x].touched = stacksTouched;
         | 
| 6912 | 
            -
            						}
         | 
| 6913 | 
            -
            						
         | 
| 6914 | 
            -
            						// Handle non null values
         | 
| 6915 | 
            -
            						if (y !== null && y !== UNDEFINED && (!axis.isLog || (y.length || y > 0))) {							
         | 
| 6916 | 
            -
             | 
| 6917 | 
            -
            							// general hook, used for Highstock compare values feature
         | 
| 6918 | 
            -
            							if (hasModifyValue) {
         | 
| 6919 | 
            -
            								y = series.modifyValue(y);
         | 
| 6920 | 
            -
            							}
         | 
| 6921 | 
            -
             | 
| 6922 | 
            -
            							// For points within the visible range, including the first point outside the
         | 
| 6923 | 
            -
            							// visible range, consider y extremes
         | 
| 6924 | 
            -
            							if (series.getExtremesFromAll || cropped || ((xData[i + 1] || x) >= xExtremes.min && 
         | 
| 6925 | 
            -
            								(xData[i - 1] || x) <= xExtremes.max)) {
         | 
| 6926 | 
            -
             | 
| 6927 | 
            -
            								j = y.length;
         | 
| 6928 | 
            -
            								if (j) { // array, like ohlc or range data
         | 
| 6929 | 
            -
            									while (j--) {
         | 
| 6930 | 
            -
            										if (y[j] !== null) {
         | 
| 6931 | 
            -
            											activeYData[activeCounter++] = y[j];
         | 
| 6932 | 
            -
            										}
         | 
| 6933 | 
            -
            									}
         | 
| 6934 | 
            -
            								} else {
         | 
| 6935 | 
            -
            									activeYData[activeCounter++] = y;
         | 
| 6936 | 
            -
            								}
         | 
| 6937 | 
            -
            							}
         | 
| 6938 | 
            -
            						}
         | 
| 6939 | 
            -
            					}
         | 
| 6918 | 
            +
            					
         | 
| 6919 | 
            +
            					// get this particular series extremes
         | 
| 6920 | 
            +
            					series.getExtremes();
         | 
| 6921 | 
            +
            					seriesDataMax = series.dataMax;
         | 
| 6922 | 
            +
            					seriesDataMin = series.dataMin;
         | 
| 6940 6923 |  | 
| 6941 6924 | 
             
            					// Get the dataMin and dataMax so far. If percentage is used, the min and max are
         | 
| 6942 | 
            -
            					// always 0 and 100. If  | 
| 6943 | 
            -
            					 | 
| 6944 | 
            -
             | 
| 6945 | 
            -
            						series.dataMax = seriesDataMax = arrayMax(activeYData);
         | 
| 6925 | 
            +
            					// always 0 and 100. If seriesDataMin and seriesDataMax is null, then series
         | 
| 6926 | 
            +
            					// doesn't have active y data, we continue with nulls
         | 
| 6927 | 
            +
            					if (!axis.usePercentage && defined(seriesDataMin) && defined(seriesDataMax)) {
         | 
| 6946 6928 | 
             
            						axis.dataMin = mathMin(pick(axis.dataMin, seriesDataMin), seriesDataMin);
         | 
| 6947 6929 | 
             
            						axis.dataMax = mathMax(pick(axis.dataMax, seriesDataMax), seriesDataMax);
         | 
| 6948 6930 | 
             
            					}
         | 
| @@ -6960,24 +6942,13 @@ Axis.prototype = { | |
| 6960 6942 | 
             
            				}
         | 
| 6961 6943 | 
             
            			}
         | 
| 6962 6944 | 
             
            		});
         | 
| 6963 | 
            -
             | 
| 6964 | 
            -
            		// Destroy unused stacks (#1044)
         | 
| 6965 | 
            -
            		for (type in stacks) {
         | 
| 6966 | 
            -
            			for (i in stacks[type]) {
         | 
| 6967 | 
            -
            				if (stacks[type][i].touched < stacksTouched) {
         | 
| 6968 | 
            -
            					stacks[type][i].destroy();
         | 
| 6969 | 
            -
            					delete stacks[type][i];
         | 
| 6970 | 
            -
            				}
         | 
| 6971 | 
            -
            			}
         | 
| 6972 | 
            -
            		}
         | 
| 6973 | 
            -
            		
         | 
| 6974 6945 | 
             
            	},
         | 
| 6975 6946 |  | 
| 6976 6947 | 
             
            	/**
         | 
| 6977 6948 | 
             
            	 * Translate from axis value to pixel position on the chart, or back
         | 
| 6978 6949 | 
             
            	 *
         | 
| 6979 6950 | 
             
            	 */
         | 
| 6980 | 
            -
            	translate: function (val, backwards, cvsCoord, old, handleLog,  | 
| 6951 | 
            +
            	translate: function (val, backwards, cvsCoord, old, handleLog, pointPlacement) {
         | 
| 6981 6952 | 
             
            		var axis = this,
         | 
| 6982 6953 | 
             
            			axisLength = axis.len,
         | 
| 6983 6954 | 
             
            			sign = 1,
         | 
| @@ -7020,9 +6991,11 @@ Axis.prototype = { | |
| 7020 6991 | 
             
            			if (postTranslate) { // log and ordinal axes
         | 
| 7021 6992 | 
             
            				val = axis.val2lin(val);
         | 
| 7022 6993 | 
             
            			}
         | 
| 7023 | 
            -
             | 
| 6994 | 
            +
            			if (pointPlacement === 'between') {
         | 
| 6995 | 
            +
            				pointPlacement = 0.5;
         | 
| 6996 | 
            +
            			}
         | 
| 7024 6997 | 
             
            			returnValue = sign * (val - localMin) * localA + cvsOffset + (sign * minPixelPadding) +
         | 
| 7025 | 
            -
            				( | 
| 6998 | 
            +
            				(isNumber(pointPlacement) ? localA * pointPlacement * axis.pointRange : 0);
         | 
| 7026 6999 | 
             
            		}
         | 
| 7027 7000 |  | 
| 7028 7001 | 
             
            		return returnValue;
         | 
| @@ -7226,7 +7199,7 @@ Axis.prototype = { | |
| 7226 7199 | 
             
            			interval = normalizeTickInterval(
         | 
| 7227 7200 | 
             
            				interval, 
         | 
| 7228 7201 | 
             
            				null, 
         | 
| 7229 | 
            -
            				 | 
| 7202 | 
            +
            				getMagnitude(interval)
         | 
| 7230 7203 | 
             
            			);
         | 
| 7231 7204 |  | 
| 7232 7205 | 
             
            			positions = map(axis.getLinearTickPositions(
         | 
| @@ -7390,7 +7363,7 @@ Axis.prototype = { | |
| 7390 7363 | 
             
            					var seriesPointRange = series.pointRange,
         | 
| 7391 7364 | 
             
            						pointPlacement = series.options.pointPlacement,
         | 
| 7392 7365 | 
             
            						seriesClosestPointRange = series.closestPointRange;
         | 
| 7393 | 
            -
             | 
| 7366 | 
            +
             | 
| 7394 7367 | 
             
            					if (seriesPointRange > range) { // #1446
         | 
| 7395 7368 | 
             
            						seriesPointRange = 0;
         | 
| 7396 7369 | 
             
            					}
         | 
| @@ -7401,7 +7374,7 @@ Axis.prototype = { | |
| 7401 7374 | 
             
            					// is 'between' or 'on', this padding does not apply.
         | 
| 7402 7375 | 
             
            					minPointOffset = mathMax(
         | 
| 7403 7376 | 
             
            						minPointOffset, 
         | 
| 7404 | 
            -
            						pointPlacement ? 0 : seriesPointRange / 2
         | 
| 7377 | 
            +
            						isString(pointPlacement) ? 0 : seriesPointRange / 2
         | 
| 7405 7378 | 
             
            					);
         | 
| 7406 7379 |  | 
| 7407 7380 | 
             
            					// Determine the total padding needed to the length of the axis to make room for the 
         | 
| @@ -7456,7 +7429,6 @@ Axis.prototype = { | |
| 7456 7429 | 
             
            			isXAxis = axis.isXAxis,
         | 
| 7457 7430 | 
             
            			isLinked = axis.isLinked,
         | 
| 7458 7431 | 
             
            			tickPositioner = axis.options.tickPositioner,
         | 
| 7459 | 
            -
            			magnitude,
         | 
| 7460 7432 | 
             
            			maxPadding = options.maxPadding,
         | 
| 7461 7433 | 
             
            			minPadding = options.minPadding,
         | 
| 7462 7434 | 
             
            			length,
         | 
| @@ -7555,6 +7527,11 @@ Axis.prototype = { | |
| 7555 7527 | 
             
            		if (axis.postProcessTickInterval) {
         | 
| 7556 7528 | 
             
            			axis.tickInterval = axis.postProcessTickInterval(axis.tickInterval);
         | 
| 7557 7529 | 
             
            		}
         | 
| 7530 | 
            +
             | 
| 7531 | 
            +
            		// In column-like charts, don't cramp in more ticks than there are points (#1943)
         | 
| 7532 | 
            +
            		if (axis.pointRange) {
         | 
| 7533 | 
            +
            			axis.tickInterval = mathMax(axis.pointRange, axis.tickInterval);
         | 
| 7534 | 
            +
            		}
         | 
| 7558 7535 |  | 
| 7559 7536 | 
             
            		// Before normalizing the tick interval, handle minimum tick interval. This applies only if tickInterval is not defined.
         | 
| 7560 7537 | 
             
            		if (!tickIntervalOption && axis.tickInterval < minTickIntervalOption) {
         | 
| @@ -7563,9 +7540,8 @@ Axis.prototype = { | |
| 7563 7540 |  | 
| 7564 7541 | 
             
            		// for linear axes, get magnitude and normalize the interval
         | 
| 7565 7542 | 
             
            		if (!isDatetimeAxis && !isLog) { // linear
         | 
| 7566 | 
            -
            			magnitude = math.pow(10, mathFloor(math.log(axis.tickInterval) / math.LN10));
         | 
| 7567 7543 | 
             
            			if (!tickIntervalOption) {
         | 
| 7568 | 
            -
            				axis.tickInterval = normalizeTickInterval(axis.tickInterval, null,  | 
| 7544 | 
            +
            				axis.tickInterval = normalizeTickInterval(axis.tickInterval, null, getMagnitude(axis.tickInterval), options);
         | 
| 7569 7545 | 
             
            			}
         | 
| 7570 7546 | 
             
            		}
         | 
| 7571 7547 |  | 
| @@ -7706,10 +7682,20 @@ Axis.prototype = { | |
| 7706 7682 | 
             
            				isDirtyData = true;
         | 
| 7707 7683 | 
             
            			}
         | 
| 7708 7684 | 
             
            		});
         | 
| 7709 | 
            -
             | 
| 7685 | 
            +
             | 
| 7686 | 
            +
             | 
| 7710 7687 | 
             
            		// do we really need to go through all this?
         | 
| 7711 7688 | 
             
            		if (isDirtyAxisLength || isDirtyData || axis.isLinked || axis.forceRedraw ||
         | 
| 7712 7689 | 
             
            			axis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax) {
         | 
| 7690 | 
            +
            			
         | 
| 7691 | 
            +
            			// reset stacks
         | 
| 7692 | 
            +
            			if (!axis.isXAxis) {
         | 
| 7693 | 
            +
            				for (type in stacks) {
         | 
| 7694 | 
            +
            					for (i in stacks[type]) {
         | 
| 7695 | 
            +
            						stacks[type][i].total = null;
         | 
| 7696 | 
            +
            					}
         | 
| 7697 | 
            +
            				}
         | 
| 7698 | 
            +
            			}
         | 
| 7713 7699 |  | 
| 7714 7700 | 
             
            			axis.forceRedraw = false;
         | 
| 7715 7701 |  | 
| @@ -7727,11 +7713,12 @@ Axis.prototype = { | |
| 7727 7713 | 
             
            			if (!axis.isDirty) {
         | 
| 7728 7714 | 
             
            				axis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax;
         | 
| 7729 7715 | 
             
            			}
         | 
| 7730 | 
            -
            		}
         | 
| 7731 | 
            -
             | 
| 7732 | 
            -
             | 
| 7733 | 
            -
             | 
| 7734 | 
            -
             | 
| 7716 | 
            +
            		} else if (!axis.isXAxis) {
         | 
| 7717 | 
            +
            			if (axis.oldStacks) {
         | 
| 7718 | 
            +
            				stacks = axis.stacks = axis.oldStacks;
         | 
| 7719 | 
            +
            			}
         | 
| 7720 | 
            +
             | 
| 7721 | 
            +
            			// reset stacks
         | 
| 7735 7722 | 
             
            			for (type in stacks) {
         | 
| 7736 7723 | 
             
            				for (i in stacks[type]) {
         | 
| 7737 7724 | 
             
            					stacks[type][i].cum = stacks[type][i].total;
         | 
| @@ -7787,12 +7774,12 @@ Axis.prototype = { | |
| 7787 7774 | 
             
            	 */
         | 
| 7788 7775 | 
             
            	zoom: function (newMin, newMax) {
         | 
| 7789 7776 |  | 
| 7790 | 
            -
            		// Prevent pinch zooming out of range
         | 
| 7777 | 
            +
            		// Prevent pinch zooming out of range. Check for defined is for #1946.
         | 
| 7791 7778 | 
             
            		if (!this.allowZoomOutside) {
         | 
| 7792 | 
            -
            			if (newMin <= this.dataMin) {
         | 
| 7779 | 
            +
            			if (defined(this.dataMin) && newMin <= this.dataMin) {
         | 
| 7793 7780 | 
             
            				newMin = UNDEFINED;
         | 
| 7794 7781 | 
             
            			}
         | 
| 7795 | 
            -
            			if (newMax >= this.dataMax) {
         | 
| 7782 | 
            +
            			if (defined(this.dataMax) && newMax >= this.dataMax) {
         | 
| 7796 7783 | 
             
            				newMax = UNDEFINED;
         | 
| 7797 7784 | 
             
            			}
         | 
| 7798 7785 | 
             
            		}
         | 
| @@ -7903,6 +7890,24 @@ Axis.prototype = { | |
| 7903 7890 | 
             
            		return obj;
         | 
| 7904 7891 | 
             
            	},
         | 
| 7905 7892 |  | 
| 7893 | 
            +
            	/**
         | 
| 7894 | 
            +
            	 * Compute auto alignment for the axis label based on which side the axis is on 
         | 
| 7895 | 
            +
            	 * and the given rotation for the label
         | 
| 7896 | 
            +
            	 */
         | 
| 7897 | 
            +
            	autoLabelAlign: function (rotation) {
         | 
| 7898 | 
            +
            		var ret, 
         | 
| 7899 | 
            +
            			angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360;
         | 
| 7900 | 
            +
             | 
| 7901 | 
            +
            		if (angle > 15 && angle < 165) {
         | 
| 7902 | 
            +
            			ret = 'right';
         | 
| 7903 | 
            +
            		} else if (angle > 195 && angle < 345) {
         | 
| 7904 | 
            +
            			ret = 'left';
         | 
| 7905 | 
            +
            		} else {
         | 
| 7906 | 
            +
            			ret = 'center';
         | 
| 7907 | 
            +
            		}
         | 
| 7908 | 
            +
            		return ret;
         | 
| 7909 | 
            +
            	},
         | 
| 7910 | 
            +
             | 
| 7906 7911 | 
             
            	/**
         | 
| 7907 7912 | 
             
            	 * Render the tick labels to a preliminary position to get their sizes
         | 
| 7908 7913 | 
             
            	 */
         | 
| @@ -7927,11 +7932,24 @@ Axis.prototype = { | |
| 7927 7932 | 
             
            			axisOffset = chart.axisOffset,
         | 
| 7928 7933 | 
             
            			clipOffset = chart.clipOffset,
         | 
| 7929 7934 | 
             
            			directionFactor = [-1, 1, 1, -1][side],
         | 
| 7930 | 
            -
            			n | 
| 7935 | 
            +
            			n,
         | 
| 7936 | 
            +
            			i,
         | 
| 7937 | 
            +
            			autoStaggerLines = 1,
         | 
| 7938 | 
            +
            			maxStaggerLines = pick(labelOptions.maxStaggerLines, 5), // docs
         | 
| 7939 | 
            +
            			lastRight,
         | 
| 7940 | 
            +
            			overlap,
         | 
| 7941 | 
            +
            			pos,
         | 
| 7942 | 
            +
            			bBox,
         | 
| 7943 | 
            +
            			x,
         | 
| 7944 | 
            +
            			w,
         | 
| 7945 | 
            +
            			lineNo;
         | 
| 7931 7946 |  | 
| 7932 7947 | 
             
            		// For reuse in Axis.render
         | 
| 7933 7948 | 
             
            		axis.hasData = hasData = (axis.hasVisibleSeries || (defined(axis.min) && defined(axis.max) && !!tickPositions));
         | 
| 7934 7949 | 
             
            		axis.showAxis = showAxis = hasData || pick(options.showEmpty, true);
         | 
| 7950 | 
            +
             | 
| 7951 | 
            +
            		// Set/reset staggerLines
         | 
| 7952 | 
            +
            		axis.staggerLines = axis.horiz && labelOptions.staggerLines;
         | 
| 7935 7953 |  | 
| 7936 7954 | 
             
            		// Create the axisGroup and gridGroup elements on first iteration
         | 
| 7937 7955 | 
             
            		if (!axis.axisGroup) {
         | 
| @@ -7947,18 +7965,54 @@ Axis.prototype = { | |
| 7947 7965 | 
             
            		}
         | 
| 7948 7966 |  | 
| 7949 7967 | 
             
            		if (hasData || axis.isLinked) {
         | 
| 7968 | 
            +
            			
         | 
| 7969 | 
            +
            			// Set the explicit or automatic label alignment
         | 
| 7970 | 
            +
            			axis.labelAlign = pick(labelOptions.align || axis.autoLabelAlign(labelOptions.rotation));
         | 
| 7971 | 
            +
             | 
| 7950 7972 | 
             
            			each(tickPositions, function (pos) {
         | 
| 7951 7973 | 
             
            				if (!ticks[pos]) {
         | 
| 7952 7974 | 
             
            					ticks[pos] = new Tick(axis, pos);
         | 
| 7953 7975 | 
             
            				} else {
         | 
| 7954 7976 | 
             
            					ticks[pos].addLabel(); // update labels depending on tick interval
         | 
| 7955 7977 | 
             
            				}
         | 
| 7956 | 
            -
             | 
| 7957 7978 | 
             
            			});
         | 
| 7958 7979 |  | 
| 7980 | 
            +
            			// Handle automatic stagger lines
         | 
| 7981 | 
            +
            			if (axis.horiz && !axis.staggerLines && maxStaggerLines && !labelOptions.rotation) {
         | 
| 7982 | 
            +
            				while (autoStaggerLines < maxStaggerLines) {
         | 
| 7983 | 
            +
            					lastRight = [];
         | 
| 7984 | 
            +
            					overlap = false;
         | 
| 7985 | 
            +
            					
         | 
| 7986 | 
            +
            					for (i = 0; i < tickPositions.length; i++) {
         | 
| 7987 | 
            +
            						pos = tickPositions[i];
         | 
| 7988 | 
            +
            						bBox = ticks[pos].label && ticks[pos].label.bBox;
         | 
| 7989 | 
            +
            						w = bBox ? bBox.width : 0;
         | 
| 7990 | 
            +
            						lineNo = i % autoStaggerLines;
         | 
| 7991 | 
            +
            						
         | 
| 7992 | 
            +
            						if (w) {
         | 
| 7993 | 
            +
            							x = axis.translate(pos); // don't handle log
         | 
| 7994 | 
            +
            							if (lastRight[lineNo] !== UNDEFINED && x < lastRight[lineNo]) {
         | 
| 7995 | 
            +
            								overlap = true;
         | 
| 7996 | 
            +
            							}
         | 
| 7997 | 
            +
            							lastRight[lineNo] = x + w;
         | 
| 7998 | 
            +
            						}
         | 
| 7999 | 
            +
            					}
         | 
| 8000 | 
            +
            					if (overlap) {
         | 
| 8001 | 
            +
            						autoStaggerLines++;
         | 
| 8002 | 
            +
            					} else {
         | 
| 8003 | 
            +
            						break;
         | 
| 8004 | 
            +
            					}
         | 
| 8005 | 
            +
            				}
         | 
| 8006 | 
            +
             | 
| 8007 | 
            +
            				if (autoStaggerLines > 1) {
         | 
| 8008 | 
            +
            					axis.staggerLines = autoStaggerLines;
         | 
| 8009 | 
            +
            				}
         | 
| 8010 | 
            +
            			}
         | 
| 8011 | 
            +
             | 
| 8012 | 
            +
             | 
| 7959 8013 | 
             
            			each(tickPositions, function (pos) {
         | 
| 7960 8014 | 
             
            				// left side must be align: right and right side must have align: left for labels
         | 
| 7961 | 
            -
            				if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] ===  | 
| 8015 | 
            +
            				if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === axis.labelAlign) {
         | 
| 7962 8016 |  | 
| 7963 8017 | 
             
            					// get the highest offset
         | 
| 7964 8018 | 
             
            					labelOffset = mathMax(
         | 
| @@ -7968,10 +8022,11 @@ Axis.prototype = { | |
| 7968 8022 | 
             
            				}
         | 
| 7969 8023 |  | 
| 7970 8024 | 
             
            			});
         | 
| 7971 | 
            -
             | 
| 7972 8025 | 
             
            			if (axis.staggerLines) {
         | 
| 7973 | 
            -
            				labelOffset  | 
| 8026 | 
            +
            				labelOffset *= axis.staggerLines;
         | 
| 8027 | 
            +
            				axis.labelOffset = labelOffset;
         | 
| 7974 8028 | 
             
            			}
         | 
| 8029 | 
            +
            			
         | 
| 7975 8030 |  | 
| 7976 8031 | 
             
            		} else { // doesn't have data
         | 
| 7977 8032 | 
             
            			for (n in ticks) {
         | 
| @@ -8326,12 +8381,23 @@ Axis.prototype = { | |
| 8326 8381 | 
             
            	 */
         | 
| 8327 8382 | 
             
            	removePlotBandOrLine: function (id) {
         | 
| 8328 8383 | 
             
            		var plotLinesAndBands = this.plotLinesAndBands,
         | 
| 8384 | 
            +
            			options = this.options,
         | 
| 8385 | 
            +
            			userOptions = this.userOptions,
         | 
| 8329 8386 | 
             
            			i = plotLinesAndBands.length;
         | 
| 8330 8387 | 
             
            		while (i--) {
         | 
| 8331 8388 | 
             
            			if (plotLinesAndBands[i].id === id) {
         | 
| 8332 8389 | 
             
            				plotLinesAndBands[i].destroy();
         | 
| 8333 8390 | 
             
            			}
         | 
| 8334 8391 | 
             
            		}
         | 
| 8392 | 
            +
            		each([options.plotLines || [], userOptions.plotLines || [], options.plotBands || [], userOptions.plotBands || []], function (arr) {
         | 
| 8393 | 
            +
            			i = arr.length;
         | 
| 8394 | 
            +
            			while (i--) {
         | 
| 8395 | 
            +
            				if (arr[i].id === id) {
         | 
| 8396 | 
            +
            					erase(arr, arr[i]);
         | 
| 8397 | 
            +
            				}
         | 
| 8398 | 
            +
            			}
         | 
| 8399 | 
            +
            		});
         | 
| 8400 | 
            +
             | 
| 8335 8401 | 
             
            	},
         | 
| 8336 8402 |  | 
| 8337 8403 | 
             
            	/**
         | 
| @@ -8369,6 +8435,22 @@ Axis.prototype = { | |
| 8369 8435 |  | 
| 8370 8436 | 
             
            	},
         | 
| 8371 8437 |  | 
| 8438 | 
            +
            	/**
         | 
| 8439 | 
            +
            	 *
         | 
| 8440 | 
            +
            	 */
         | 
| 8441 | 
            +
            	buildStacks: function () {
         | 
| 8442 | 
            +
            		if (this.isXAxis) {
         | 
| 8443 | 
            +
            			return;
         | 
| 8444 | 
            +
            		}
         | 
| 8445 | 
            +
             | 
| 8446 | 
            +
            		var series = this.series,
         | 
| 8447 | 
            +
            				last = series.length - 1;
         | 
| 8448 | 
            +
             | 
| 8449 | 
            +
            		each(series, function (serie, i) {
         | 
| 8450 | 
            +
            			serie.setStackedPoints(i === last);
         | 
| 8451 | 
            +
            		});
         | 
| 8452 | 
            +
            	},
         | 
| 8453 | 
            +
             | 
| 8372 8454 | 
             
            	/**
         | 
| 8373 8455 | 
             
            	 * Set new axis categories and optionally redraw
         | 
| 8374 8456 | 
             
            	 * @param {Array} categories
         | 
| @@ -8381,13 +8463,15 @@ Axis.prototype = { | |
| 8381 8463 | 
             
            	/**
         | 
| 8382 8464 | 
             
            	 * Destroys an Axis instance.
         | 
| 8383 8465 | 
             
            	 */
         | 
| 8384 | 
            -
            	destroy: function () {
         | 
| 8466 | 
            +
            	destroy: function (keepEvents) {
         | 
| 8385 8467 | 
             
            		var axis = this,
         | 
| 8386 8468 | 
             
            			stacks = axis.stacks,
         | 
| 8387 8469 | 
             
            			stackKey;
         | 
| 8388 8470 |  | 
| 8389 8471 | 
             
            		// Remove the events
         | 
| 8390 | 
            -
            		 | 
| 8472 | 
            +
            		if (!keepEvents) {
         | 
| 8473 | 
            +
            			removeEvent(axis);
         | 
| 8474 | 
            +
            		}
         | 
| 8391 8475 |  | 
| 8392 8476 | 
             
            		// Destroy each stack total
         | 
| 8393 8477 | 
             
            		for (stackKey in stacks) {
         | 
| @@ -8798,15 +8882,20 @@ Tooltip.prototype = { | |
| 8798 8882 | 
             
            				i = crosshairsOptions.length,
         | 
| 8799 8883 | 
             
            				attribs,
         | 
| 8800 8884 | 
             
            				axis,
         | 
| 8801 | 
            -
            				val | 
| 8885 | 
            +
            				val,
         | 
| 8886 | 
            +
            				series;
         | 
| 8802 8887 |  | 
| 8803 8888 | 
             
            			while (i--) {
         | 
| 8804 | 
            -
            				 | 
| 8889 | 
            +
            				series = point.series;
         | 
| 8890 | 
            +
            				axis = series[i ? 'yAxis' : 'xAxis'];
         | 
| 8805 8891 | 
             
            				if (crosshairsOptions[i] && axis) {
         | 
| 8806 8892 | 
             
            					val = i ? pick(point.stackY, point.y) : point.x; // #814
         | 
| 8807 8893 | 
             
            					if (axis.isLog) { // #1671
         | 
| 8808 8894 | 
             
            						val = log2lin(val);
         | 
| 8809 8895 | 
             
            					}
         | 
| 8896 | 
            +
            					if (series.modifyValue) { // #1205
         | 
| 8897 | 
            +
            						val = series.modifyValue(val);
         | 
| 8898 | 
            +
            					}
         | 
| 8810 8899 |  | 
| 8811 8900 | 
             
            					path = axis.getPlotLinePath(
         | 
| 8812 8901 | 
             
            						val,
         | 
| @@ -8908,8 +8997,6 @@ Pointer.prototype = { | |
| 8908 8997 | 
             
            	 */
         | 
| 8909 8998 | 
             
            	normalize: function (e) {
         | 
| 8910 8999 | 
             
            		var chartPosition,
         | 
| 8911 | 
            -
            			chartX,
         | 
| 8912 | 
            -
            			chartY,
         | 
| 8913 9000 | 
             
            			ePos;
         | 
| 8914 9001 |  | 
| 8915 9002 | 
             
            		// common IE normalizing
         | 
| @@ -8927,18 +9014,10 @@ Pointer.prototype = { | |
| 8927 9014 | 
             
            		// get mouse position
         | 
| 8928 9015 | 
             
            		this.chartPosition = chartPosition = offset(this.chart.container);
         | 
| 8929 9016 |  | 
| 8930 | 
            -
            		//  | 
| 8931 | 
            -
            		if (ePos.pageX === UNDEFINED) { // IE < 9. #886.
         | 
| 8932 | 
            -
            			chartX = e.x;
         | 
| 8933 | 
            -
            			chartY = e.y;
         | 
| 8934 | 
            -
            		} else {
         | 
| 8935 | 
            -
            			chartX = ePos.pageX - chartPosition.left;
         | 
| 8936 | 
            -
            			chartY = ePos.pageY - chartPosition.top;
         | 
| 8937 | 
            -
            		}
         | 
| 8938 | 
            -
             | 
| 9017 | 
            +
            		// Old IE and compatibility mode use clientX. #886, #2005.
         | 
| 8939 9018 | 
             
            		return extend(e, {
         | 
| 8940 | 
            -
            			chartX: mathRound( | 
| 8941 | 
            -
            			chartY: mathRound( | 
| 9019 | 
            +
            			chartX: mathRound(pick(ePos.pageX, ePos.clientX) - chartPosition.left),
         | 
| 9020 | 
            +
            			chartY: mathRound(pick(ePos.pageY, ePos.clientY) - chartPosition.top)
         | 
| 8942 9021 | 
             
            		});
         | 
| 8943 9022 | 
             
            	},
         | 
| 8944 9023 |  | 
| @@ -9097,18 +9176,20 @@ Pointer.prototype = { | |
| 9097 9176 | 
             
            	 */
         | 
| 9098 9177 | 
             
            	scaleGroups: function (attribs, clip) {
         | 
| 9099 9178 |  | 
| 9100 | 
            -
            		var chart = this.chart | 
| 9179 | 
            +
            		var chart = this.chart,
         | 
| 9180 | 
            +
            			seriesAttribs;
         | 
| 9101 9181 |  | 
| 9102 9182 | 
             
            		// Scale each series
         | 
| 9103 9183 | 
             
            		each(chart.series, function (series) {
         | 
| 9184 | 
            +
            			seriesAttribs = attribs || series.getPlotBox(); // #1701
         | 
| 9104 9185 | 
             
            			if (series.xAxis && series.xAxis.zoomEnabled) {
         | 
| 9105 | 
            -
            				series.group.attr( | 
| 9186 | 
            +
            				series.group.attr(seriesAttribs);
         | 
| 9106 9187 | 
             
            				if (series.markerGroup) {
         | 
| 9107 | 
            -
            					series.markerGroup.attr( | 
| 9188 | 
            +
            					series.markerGroup.attr(seriesAttribs);
         | 
| 9108 9189 | 
             
            					series.markerGroup.clip(clip ? chart.clipRect : null);
         | 
| 9109 9190 | 
             
            				}
         | 
| 9110 9191 | 
             
            				if (series.dataLabelsGroup) {
         | 
| 9111 | 
            -
            					series.dataLabelsGroup.attr( | 
| 9192 | 
            +
            					series.dataLabelsGroup.attr(seriesAttribs);
         | 
| 9112 9193 | 
             
            				}
         | 
| 9113 9194 | 
             
            			}
         | 
| 9114 9195 | 
             
            		});
         | 
| @@ -9428,12 +9509,7 @@ Pointer.prototype = { | |
| 9428 9509 |  | 
| 9429 9510 | 
             
            			// Reset scaling preview
         | 
| 9430 9511 | 
             
            			if (hasPinched) {
         | 
| 9431 | 
            -
            				this.scaleGroups( | 
| 9432 | 
            -
            					translateX: chart.plotLeft,
         | 
| 9433 | 
            -
            					translateY: chart.plotTop,
         | 
| 9434 | 
            -
            					scaleX: 1,
         | 
| 9435 | 
            -
            					scaleY: 1
         | 
| 9436 | 
            -
            				});
         | 
| 9512 | 
            +
            				this.scaleGroups();
         | 
| 9437 9513 | 
             
            			}
         | 
| 9438 9514 | 
             
            		}
         | 
| 9439 9515 |  | 
| @@ -9612,6 +9688,10 @@ Pointer.prototype = { | |
| 9612 9688 | 
             
            				this.runPointActions(e);
         | 
| 9613 9689 |  | 
| 9614 9690 | 
             
            				this.pinch(e);
         | 
| 9691 | 
            +
             | 
| 9692 | 
            +
            			} else {
         | 
| 9693 | 
            +
            				// Hide the tooltip on touching outside the plot area (#1203)
         | 
| 9694 | 
            +
            				this.reset();
         | 
| 9615 9695 | 
             
            			}
         | 
| 9616 9696 |  | 
| 9617 9697 | 
             
            		} else if (e.touches.length === 2) {
         | 
| @@ -9763,7 +9843,6 @@ Legend.prototype = { | |
| 9763 9843 | 
             
            			},
         | 
| 9764 9844 | 
             
            			key,
         | 
| 9765 9845 | 
             
            			val;
         | 
| 9766 | 
            -
             | 
| 9767 9846 |  | 
| 9768 9847 | 
             
            		if (legendItem) {
         | 
| 9769 9848 | 
             
            			legendItem.css({ fill: textColor, color: textColor }); // color for #1553, oldIE
         | 
| @@ -9775,7 +9854,7 @@ Legend.prototype = { | |
| 9775 9854 | 
             
            		if (legendSymbol) {
         | 
| 9776 9855 |  | 
| 9777 9856 | 
             
            			// Apply marker options
         | 
| 9778 | 
            -
            			if (markerOptions) {
         | 
| 9857 | 
            +
            			if (markerOptions && legendSymbol.isMarker) { // #585
         | 
| 9779 9858 | 
             
            				markerOptions = item.convertAttribs(markerOptions);
         | 
| 9780 9859 | 
             
            				for (key in markerOptions) {
         | 
| 9781 9860 | 
             
            					val = markerOptions[key];
         | 
| @@ -9826,7 +9905,7 @@ Legend.prototype = { | |
| 9826 9905 | 
             
            		// destroy SVG elements
         | 
| 9827 9906 | 
             
            		each(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function (key) {
         | 
| 9828 9907 | 
             
            			if (item[key]) {
         | 
| 9829 | 
            -
            				item[key].destroy();
         | 
| 9908 | 
            +
            				item[key] = item[key].destroy();
         | 
| 9830 9909 | 
             
            			}
         | 
| 9831 9910 | 
             
            		});
         | 
| 9832 9911 |  | 
| @@ -9885,7 +9964,8 @@ Legend.prototype = { | |
| 9885 9964 | 
             
            		var options = this.options,
         | 
| 9886 9965 | 
             
            			padding = this.padding,
         | 
| 9887 9966 | 
             
            			titleOptions = options.title,
         | 
| 9888 | 
            -
            			titleHeight = 0 | 
| 9967 | 
            +
            			titleHeight = 0,
         | 
| 9968 | 
            +
            			bBox;
         | 
| 9889 9969 |  | 
| 9890 9970 | 
             
            		if (titleOptions.text) {
         | 
| 9891 9971 | 
             
            			if (!this.title) {
         | 
| @@ -9894,7 +9974,9 @@ Legend.prototype = { | |
| 9894 9974 | 
             
            					.css(titleOptions.style)
         | 
| 9895 9975 | 
             
            					.add(this.group);
         | 
| 9896 9976 | 
             
            			}
         | 
| 9897 | 
            -
            			 | 
| 9977 | 
            +
            			bBox = this.title.getBBox();
         | 
| 9978 | 
            +
            			titleHeight = bBox.height;
         | 
| 9979 | 
            +
            			this.offsetWidth = bBox.width; // #1717
         | 
| 9898 9980 | 
             
            			this.contentGroup.attr({ translateY: titleHeight });
         | 
| 9899 9981 | 
             
            		}
         | 
| 9900 9982 | 
             
            		this.titleHeight = titleHeight;
         | 
| @@ -9915,6 +9997,7 @@ Legend.prototype = { | |
| 9915 9997 | 
             
            			itemStyle = legend.itemStyle,
         | 
| 9916 9998 | 
             
            			itemHiddenStyle = legend.itemHiddenStyle,
         | 
| 9917 9999 | 
             
            			padding = legend.padding,
         | 
| 10000 | 
            +
            			itemDistance = horizontal ? pick(options.itemDistance, 8) : 0, // docs
         | 
| 9918 10001 | 
             
            			ltr = !options.rtl,
         | 
| 9919 10002 | 
             
            			itemHeight,
         | 
| 9920 10003 | 
             
            			widthOption = options.width,
         | 
| @@ -10010,7 +10093,7 @@ Legend.prototype = { | |
| 10010 10093 | 
             
            		bBox = li.getBBox();
         | 
| 10011 10094 |  | 
| 10012 10095 | 
             
            		itemWidth = item.legendItemWidth =
         | 
| 10013 | 
            -
            			options.itemWidth || symbolWidth + symbolPadding + bBox.width +  | 
| 10096 | 
            +
            			options.itemWidth || symbolWidth + symbolPadding + bBox.width + itemDistance +
         | 
| 10014 10097 | 
             
            			(showCheckbox ? 20 : 0);
         | 
| 10015 10098 | 
             
            		legend.itemHeight = itemHeight = bBox.height;
         | 
| 10016 10099 |  | 
| @@ -10048,7 +10131,7 @@ Legend.prototype = { | |
| 10048 10131 |  | 
| 10049 10132 | 
             
            		// the width of the widest item
         | 
| 10050 10133 | 
             
            		legend.offsetWidth = widthOption || mathMax(
         | 
| 10051 | 
            -
            			horizontal ? legend.itemX - initialItemX : itemWidth,
         | 
| 10134 | 
            +
            			(horizontal ? legend.itemX - initialItemX - itemDistance : itemWidth) + padding,
         | 
| 10052 10135 | 
             
            			legend.offsetWidth
         | 
| 10053 10136 | 
             
            		);
         | 
| 10054 10137 | 
             
            	},
         | 
| @@ -10385,7 +10468,7 @@ Chart.prototype = { | |
| 10385 10468 |  | 
| 10386 10469 | 
             
            		var chartEvents = optionsChart.events;
         | 
| 10387 10470 |  | 
| 10388 | 
            -
            		this.runChartClick = chartEvents && !!chartEvents.click;
         | 
| 10471 | 
            +
            		//this.runChartClick = chartEvents && !!chartEvents.click;
         | 
| 10389 10472 | 
             
            		this.bounds = { h: {}, v: {} }; // Pixel data bounds for touch zoom
         | 
| 10390 10473 |  | 
| 10391 10474 | 
             
            		this.callback = callback;
         | 
| @@ -10520,7 +10603,8 @@ Chart.prototype = { | |
| 10520 10603 |  | 
| 10521 10604 | 
             
            		/*jslint unused: false*/
         | 
| 10522 10605 | 
             
            		axis = new Axis(this, merge(options, {
         | 
| 10523 | 
            -
            			index: this[key].length
         | 
| 10606 | 
            +
            			index: this[key].length,
         | 
| 10607 | 
            +
            			isX: isX
         | 
| 10524 10608 | 
             
            		}));
         | 
| 10525 10609 | 
             
            		/*jslint unused: true*/
         | 
| 10526 10610 |  | 
| @@ -10576,6 +10660,7 @@ Chart.prototype = { | |
| 10576 10660 | 
             
            			legend = chart.legend,
         | 
| 10577 10661 | 
             
            			redrawLegend = chart.isDirtyLegend,
         | 
| 10578 10662 | 
             
            			hasStackedSeries,
         | 
| 10663 | 
            +
            			hasDirtyStacks,
         | 
| 10579 10664 | 
             
            			isDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed?
         | 
| 10580 10665 | 
             
            			seriesLength = series.length,
         | 
| 10581 10666 | 
             
            			i = seriesLength,
         | 
| @@ -10590,15 +10675,23 @@ Chart.prototype = { | |
| 10590 10675 | 
             
            			chart.cloneRenderTo();
         | 
| 10591 10676 | 
             
            		}
         | 
| 10592 10677 |  | 
| 10678 | 
            +
            		// Adjust title layout (reflow multiline text)
         | 
| 10679 | 
            +
            		chart.layOutTitles();
         | 
| 10680 | 
            +
             | 
| 10593 10681 | 
             
            		// link stacked series
         | 
| 10594 10682 | 
             
            		while (i--) {
         | 
| 10595 10683 | 
             
            			serie = series[i];
         | 
| 10596 | 
            -
             | 
| 10684 | 
            +
             | 
| 10685 | 
            +
            			if (serie.options.stacking) {
         | 
| 10597 10686 | 
             
            				hasStackedSeries = true;
         | 
| 10598 | 
            -
            				 | 
| 10687 | 
            +
            				
         | 
| 10688 | 
            +
            				if (serie.isDirty) {
         | 
| 10689 | 
            +
            					hasDirtyStacks = true;
         | 
| 10690 | 
            +
            					break;
         | 
| 10691 | 
            +
            				}
         | 
| 10599 10692 | 
             
            			}
         | 
| 10600 10693 | 
             
            		}
         | 
| 10601 | 
            -
            		if ( | 
| 10694 | 
            +
            		if (hasDirtyStacks) { // mark others as dirty
         | 
| 10602 10695 | 
             
            			i = seriesLength;
         | 
| 10603 10696 | 
             
            			while (i--) {
         | 
| 10604 10697 | 
             
            				serie = series[i];
         | 
| @@ -10625,6 +10718,11 @@ Chart.prototype = { | |
| 10625 10718 | 
             
            			chart.isDirtyLegend = false;
         | 
| 10626 10719 | 
             
            		}
         | 
| 10627 10720 |  | 
| 10721 | 
            +
            		// reset stacks
         | 
| 10722 | 
            +
            		if (hasStackedSeries) {
         | 
| 10723 | 
            +
            			chart.getStacks();
         | 
| 10724 | 
            +
            		}
         | 
| 10725 | 
            +
             | 
| 10628 10726 |  | 
| 10629 10727 | 
             
            		if (chart.hasCartesianSeries) {
         | 
| 10630 10728 | 
             
            			if (!chart.isResizing) {
         | 
| @@ -10636,6 +10734,11 @@ Chart.prototype = { | |
| 10636 10734 | 
             
            				each(axes, function (axis) {
         | 
| 10637 10735 | 
             
            					axis.setScale();
         | 
| 10638 10736 | 
             
            				});
         | 
| 10737 | 
            +
            			} else {
         | 
| 10738 | 
            +
            				// build stacks
         | 
| 10739 | 
            +
            				each(axes, function (axis) {
         | 
| 10740 | 
            +
            					axis.buildStacks();
         | 
| 10741 | 
            +
            				});
         | 
| 10639 10742 | 
             
            			}
         | 
| 10640 10743 | 
             
            			chart.adjustTickAmounts();
         | 
| 10641 10744 | 
             
            			chart.getMargins();
         | 
| @@ -10665,7 +10768,6 @@ Chart.prototype = { | |
| 10665 10768 | 
             
            		}
         | 
| 10666 10769 |  | 
| 10667 10770 |  | 
| 10668 | 
            -
             | 
| 10669 10771 | 
             
            		// redraw affected series
         | 
| 10670 10772 | 
             
            		each(series, function (serie) {
         | 
| 10671 10773 | 
             
            			if (serie.isDirty && serie.visible &&
         | 
| @@ -10861,6 +10963,26 @@ Chart.prototype = { | |
| 10861 10963 | 
             
            		});
         | 
| 10862 10964 | 
             
            	},
         | 
| 10863 10965 |  | 
| 10966 | 
            +
            	/**
         | 
| 10967 | 
            +
            	 * Generate stacks for each series and calculate stacks total values
         | 
| 10968 | 
            +
            	 */
         | 
| 10969 | 
            +
            	getStacks: function () {
         | 
| 10970 | 
            +
            		var chart = this;
         | 
| 10971 | 
            +
             | 
| 10972 | 
            +
            		// reset stacks for each yAxis
         | 
| 10973 | 
            +
            		each(chart.yAxis, function (axis) {
         | 
| 10974 | 
            +
            			if (axis.stacks && axis.hasVisibleSeries) {
         | 
| 10975 | 
            +
            				axis.oldStacks = axis.stacks;
         | 
| 10976 | 
            +
            			}
         | 
| 10977 | 
            +
            		});
         | 
| 10978 | 
            +
             | 
| 10979 | 
            +
            		each(chart.series, function (series) {
         | 
| 10980 | 
            +
            			if (series.options.stacking && (series.visible === true || chart.options.chart.ignoreHiddenSeries === false)) {
         | 
| 10981 | 
            +
            				series.stackKey = series.type + pick(series.options.stack, '');
         | 
| 10982 | 
            +
            			}
         | 
| 10983 | 
            +
            		});
         | 
| 10984 | 
            +
            	},
         | 
| 10985 | 
            +
             | 
| 10864 10986 | 
             
            	/**
         | 
| 10865 10987 | 
             
            	 * Display the zoom button
         | 
| 10866 10988 | 
             
            	 */
         | 
| @@ -11013,11 +11135,49 @@ Chart.prototype = { | |
| 11013 11135 | 
             
            					zIndex: chartTitleOptions.zIndex || 4
         | 
| 11014 11136 | 
             
            				})
         | 
| 11015 11137 | 
             
            				.css(chartTitleOptions.style)
         | 
| 11016 | 
            -
            				.add()
         | 
| 11017 | 
            -
             | 
| 11018 | 
            -
            			}
         | 
| 11138 | 
            +
            				.add();
         | 
| 11139 | 
            +
            			}	
         | 
| 11019 11140 | 
             
            		});
         | 
| 11141 | 
            +
            		chart.layOutTitles();
         | 
| 11142 | 
            +
            	},
         | 
| 11143 | 
            +
             | 
| 11144 | 
            +
            	/**
         | 
| 11145 | 
            +
            	 * Lay out the chart titles and cache the full offset height for use in getMargins
         | 
| 11146 | 
            +
            	 */
         | 
| 11147 | 
            +
            	layOutTitles: function () {
         | 
| 11148 | 
            +
            		var titleOffset = 0,
         | 
| 11149 | 
            +
            			title = this.title,
         | 
| 11150 | 
            +
            			subtitle = this.subtitle,
         | 
| 11151 | 
            +
            			options = this.options,
         | 
| 11152 | 
            +
            			titleOptions = options.title,
         | 
| 11153 | 
            +
            			subtitleOptions = options.subtitle,
         | 
| 11154 | 
            +
            			autoWidth = this.spacingBox.width - 44; // 44 makes room for default context button
         | 
| 11155 | 
            +
             | 
| 11156 | 
            +
            		if (title) {
         | 
| 11157 | 
            +
            			title
         | 
| 11158 | 
            +
            				.css({ width: (titleOptions.width || autoWidth) + PX })
         | 
| 11159 | 
            +
            				.align(extend({ y: 15 }, titleOptions), false, 'spacingBox');
         | 
| 11160 | 
            +
            			
         | 
| 11161 | 
            +
            			if (!titleOptions.floating && !titleOptions.verticalAlign) {
         | 
| 11162 | 
            +
            				titleOffset = title.getBBox().height;
         | 
| 11163 | 
            +
             | 
| 11164 | 
            +
            				// Adjust for browser consistency + backwards compat after #776 fix
         | 
| 11165 | 
            +
            				if (titleOffset >= 18 && titleOffset <= 25) {
         | 
| 11166 | 
            +
            					titleOffset = 15; 
         | 
| 11167 | 
            +
            				}
         | 
| 11168 | 
            +
            			}
         | 
| 11169 | 
            +
            		}
         | 
| 11170 | 
            +
            		if (subtitle) {
         | 
| 11171 | 
            +
            			subtitle
         | 
| 11172 | 
            +
            				.css({ width: (subtitleOptions.width || autoWidth) + PX })
         | 
| 11173 | 
            +
            				.align(extend({ y: titleOffset + titleOptions.margin }, subtitleOptions), false, 'spacingBox');
         | 
| 11174 | 
            +
            			
         | 
| 11175 | 
            +
            			if (!subtitleOptions.floating && !subtitleOptions.verticalAlign) {
         | 
| 11176 | 
            +
            				titleOffset = mathCeil(titleOffset + subtitle.getBBox().height);
         | 
| 11177 | 
            +
            			}
         | 
| 11178 | 
            +
            		}
         | 
| 11020 11179 |  | 
| 11180 | 
            +
            		this.titleOffset = titleOffset; // used in getMargins
         | 
| 11021 11181 | 
             
            	},
         | 
| 11022 11182 |  | 
| 11023 11183 | 
             
            	/**
         | 
| @@ -11056,7 +11216,7 @@ Chart.prototype = { | |
| 11056 11216 |  | 
| 11057 11217 | 
             
            		// Set up the clone
         | 
| 11058 11218 | 
             
            		} else {
         | 
| 11059 | 
            -
            			if (container) {
         | 
| 11219 | 
            +
            			if (container && container.parentNode === this.renderTo) {
         | 
| 11060 11220 | 
             
            				this.renderTo.removeChild(container); // do not clone this
         | 
| 11061 11221 | 
             
            			}
         | 
| 11062 11222 | 
             
            			this.renderToClone = clone = this.renderTo.cloneNode(0);
         | 
| @@ -11176,30 +11336,23 @@ Chart.prototype = { | |
| 11176 11336 | 
             
            			optionsMarginLeft = chart.optionsMarginLeft,
         | 
| 11177 11337 | 
             
            			optionsMarginRight = chart.optionsMarginRight,
         | 
| 11178 11338 | 
             
            			optionsMarginBottom = chart.optionsMarginBottom,
         | 
| 11179 | 
            -
            			chartTitleOptions = chart.options.title,
         | 
| 11180 | 
            -
            			chartSubtitleOptions = chart.options.subtitle,
         | 
| 11181 11339 | 
             
            			legendOptions = chart.options.legend,
         | 
| 11182 11340 | 
             
            			legendMargin = pick(legendOptions.margin, 10),
         | 
| 11183 11341 | 
             
            			legendX = legendOptions.x,
         | 
| 11184 11342 | 
             
            			legendY = legendOptions.y,
         | 
| 11185 11343 | 
             
            			align = legendOptions.align,
         | 
| 11186 11344 | 
             
            			verticalAlign = legendOptions.verticalAlign,
         | 
| 11187 | 
            -
            			titleOffset;
         | 
| 11345 | 
            +
            			titleOffset = chart.titleOffset;
         | 
| 11188 11346 |  | 
| 11189 11347 | 
             
            		chart.resetMargins();
         | 
| 11190 11348 | 
             
            		axisOffset = chart.axisOffset;
         | 
| 11191 11349 |  | 
| 11192 | 
            -
            		//  | 
| 11193 | 
            -
            		if ( | 
| 11194 | 
            -
            			 | 
| 11195 | 
            -
            				(chart.title && !chartTitleOptions.floating && !chartTitleOptions.verticalAlign && chartTitleOptions.y) || 0,
         | 
| 11196 | 
            -
            				(chart.subtitle && !chartSubtitleOptions.floating && !chartSubtitleOptions.verticalAlign && chartSubtitleOptions.y) || 0
         | 
| 11197 | 
            -
            			);
         | 
| 11198 | 
            -
            			if (titleOffset) {
         | 
| 11199 | 
            -
            				chart.plotTop = mathMax(chart.plotTop, titleOffset + pick(chartTitleOptions.margin, 15) + spacingTop);
         | 
| 11200 | 
            -
            			}
         | 
| 11350 | 
            +
            		// Adjust for title and subtitle
         | 
| 11351 | 
            +
            		if (titleOffset && !defined(optionsMarginTop)) {
         | 
| 11352 | 
            +
            			chart.plotTop = mathMax(chart.plotTop, titleOffset + chart.options.title.margin + spacingTop);
         | 
| 11201 11353 | 
             
            		}
         | 
| 11202 | 
            -
            		 | 
| 11354 | 
            +
            		
         | 
| 11355 | 
            +
            		// Adjust for legend
         | 
| 11203 11356 | 
             
            		if (legend.display && !legendOptions.floating) {
         | 
| 11204 11357 | 
             
            			if (align === 'right') { // horizontal alignment handled first
         | 
| 11205 11358 | 
             
            				if (!defined(optionsMarginRight)) {
         | 
| @@ -11630,11 +11783,14 @@ Chart.prototype = { | |
| 11630 11783 | 
             
            		// Legend
         | 
| 11631 11784 | 
             
            		chart.legend = new Legend(chart, options.legend);
         | 
| 11632 11785 |  | 
| 11786 | 
            +
            		chart.getStacks(); // render stacks
         | 
| 11787 | 
            +
             | 
| 11633 11788 | 
             
            		// Get margins by pre-rendering axes
         | 
| 11634 11789 | 
             
            		// set axes scales
         | 
| 11635 11790 | 
             
            		each(axes, function (axis) {
         | 
| 11636 11791 | 
             
            			axis.setScale();
         | 
| 11637 11792 | 
             
            		});
         | 
| 11793 | 
            +
             | 
| 11638 11794 | 
             
            		chart.getMargins();
         | 
| 11639 11795 |  | 
| 11640 11796 | 
             
            		chart.maxTicks = null; // reset for second pass
         | 
| @@ -12177,7 +12333,8 @@ Point.prototype = { | |
| 12177 12333 | 
             
            			graphic = point.graphic,
         | 
| 12178 12334 | 
             
            			i,
         | 
| 12179 12335 | 
             
            			data = series.data,
         | 
| 12180 | 
            -
            			chart = series.chart | 
| 12336 | 
            +
            			chart = series.chart,
         | 
| 12337 | 
            +
            			seriesOptions = series.options;
         | 
| 12181 12338 |  | 
| 12182 12339 | 
             
            		redraw = pick(redraw, true);
         | 
| 12183 12340 |  | 
| @@ -12199,11 +12356,13 @@ Point.prototype = { | |
| 12199 12356 | 
             
            			series.xData[i] = point.x;
         | 
| 12200 12357 | 
             
            			series.yData[i] = series.toYData ? series.toYData(point) : point.y;
         | 
| 12201 12358 | 
             
            			series.zData[i] = point.z;
         | 
| 12202 | 
            -
            			 | 
| 12359 | 
            +
            			seriesOptions.data[i] = point.options;
         | 
| 12203 12360 |  | 
| 12204 12361 | 
             
            			// redraw
         | 
| 12205 | 
            -
            			series.isDirty = true;
         | 
| 12206 | 
            -
            			 | 
| 12362 | 
            +
            			series.isDirty = series.isDirtyData = chart.isDirtyBox = true;
         | 
| 12363 | 
            +
            			if (seriesOptions.legendType === 'point') { // #1831, #1885
         | 
| 12364 | 
            +
            				chart.legend.destroyItem(point);
         | 
| 12365 | 
            +
            			}
         | 
| 12207 12366 | 
             
            			if (redraw) {
         | 
| 12208 12367 | 
             
            				chart.redraw(animation);
         | 
| 12209 12368 | 
             
            			}
         | 
| @@ -12612,6 +12771,7 @@ Series.prototype = { | |
| 12612 12771 | 
             
            		// register it
         | 
| 12613 12772 | 
             
            		series.segments = segments;
         | 
| 12614 12773 | 
             
            	},
         | 
| 12774 | 
            +
            	
         | 
| 12615 12775 | 
             
            	/**
         | 
| 12616 12776 | 
             
            	 * Set the series options by merging from the options tree
         | 
| 12617 12777 | 
             
            	 * @param {Object} itemOptions
         | 
| @@ -12714,7 +12874,7 @@ Series.prototype = { | |
| 12714 12874 | 
             
            			symbolWidth = legendOptions.symbolWidth,
         | 
| 12715 12875 | 
             
            			renderer = this.chart.renderer,
         | 
| 12716 12876 | 
             
            			legendItemGroup = this.legendGroup,
         | 
| 12717 | 
            -
            			 | 
| 12877 | 
            +
            			verticalCenter = legend.baseline - mathRound(renderer.fontMetrics(legendOptions.itemStyle.fontSize).b * 0.3),
         | 
| 12718 12878 | 
             
            			attr;
         | 
| 12719 12879 |  | 
| 12720 12880 | 
             
            		// Draw the line
         | 
| @@ -12728,10 +12888,10 @@ Series.prototype = { | |
| 12728 12888 | 
             
            			this.legendLine = renderer.path([
         | 
| 12729 12889 | 
             
            				M,
         | 
| 12730 12890 | 
             
            				0,
         | 
| 12731 | 
            -
            				 | 
| 12891 | 
            +
            				verticalCenter,
         | 
| 12732 12892 | 
             
            				L,
         | 
| 12733 12893 | 
             
            				symbolWidth,
         | 
| 12734 | 
            -
            				 | 
| 12894 | 
            +
            				verticalCenter
         | 
| 12735 12895 | 
             
            			])
         | 
| 12736 12896 | 
             
            			.attr(attr)
         | 
| 12737 12897 | 
             
            			.add(legendItemGroup);
         | 
| @@ -12743,11 +12903,12 @@ Series.prototype = { | |
| 12743 12903 | 
             
            			this.legendSymbol = legendSymbol = renderer.symbol(
         | 
| 12744 12904 | 
             
            				this.symbol,
         | 
| 12745 12905 | 
             
            				(symbolWidth / 2) - radius,
         | 
| 12746 | 
            -
            				 | 
| 12906 | 
            +
            				verticalCenter - radius,
         | 
| 12747 12907 | 
             
            				2 * radius,
         | 
| 12748 12908 | 
             
            				2 * radius
         | 
| 12749 12909 | 
             
            			)
         | 
| 12750 12910 | 
             
            			.add(legendItemGroup);
         | 
| 12911 | 
            +
            			legendSymbol.isMarker = true;
         | 
| 12751 12912 | 
             
            		}
         | 
| 12752 12913 | 
             
            	},
         | 
| 12753 12914 |  | 
| @@ -12778,13 +12939,14 @@ Series.prototype = { | |
| 12778 12939 | 
             
            		setAnimation(animation, chart);
         | 
| 12779 12940 |  | 
| 12780 12941 | 
             
            		// Make graph animate sideways
         | 
| 12781 | 
            -
            		if ( | 
| 12782 | 
            -
            			graph. | 
| 12942 | 
            +
            		if (shift) {
         | 
| 12943 | 
            +
            			each([graph, area, series.graphNeg, series.areaNeg], function (shape) {
         | 
| 12944 | 
            +
            				if (shape) {
         | 
| 12945 | 
            +
            					shape.shift = currentShift + 1;
         | 
| 12946 | 
            +
            				}
         | 
| 12947 | 
            +
            			});
         | 
| 12783 12948 | 
             
            		}
         | 
| 12784 12949 | 
             
            		if (area) {
         | 
| 12785 | 
            -
            			if (shift) { // #780
         | 
| 12786 | 
            -
            				area.shift = currentShift + 1;
         | 
| 12787 | 
            -
            			}
         | 
| 12788 12950 | 
             
            			area.isArea = true; // needed in animation, both with and without shift
         | 
| 12789 12951 | 
             
            		}
         | 
| 12790 12952 |  | 
| @@ -12821,12 +12983,12 @@ Series.prototype = { | |
| 12821 12983 | 
             
            				dataOptions.shift();
         | 
| 12822 12984 | 
             
            			}
         | 
| 12823 12985 | 
             
            		}
         | 
| 12824 | 
            -
            		series.getAttribs();
         | 
| 12825 12986 |  | 
| 12826 12987 | 
             
            		// redraw
         | 
| 12827 12988 | 
             
            		series.isDirty = true;
         | 
| 12828 12989 | 
             
            		series.isDirtyData = true;
         | 
| 12829 12990 | 
             
            		if (redraw) {
         | 
| 12991 | 
            +
            			series.getAttribs(); // #1937
         | 
| 12830 12992 | 
             
            			chart.redraw();
         | 
| 12831 12993 | 
             
            		}
         | 
| 12832 12994 | 
             
            	},
         | 
| @@ -12857,7 +13019,7 @@ Series.prototype = { | |
| 12857 13019 | 
             
            			yData = [],
         | 
| 12858 13020 | 
             
            			zData = [],
         | 
| 12859 13021 | 
             
            			dataLength = data ? data.length : [],
         | 
| 12860 | 
            -
            			turboThreshold = options.turboThreshold  | 
| 13022 | 
            +
            			turboThreshold = pick(options.turboThreshold, 1000), // docs: 0 to disable
         | 
| 12861 13023 | 
             
            			pt,
         | 
| 12862 13024 | 
             
            			pointArrayMap = series.pointArrayMap,
         | 
| 12863 13025 | 
             
            			valueCount = pointArrayMap && pointArrayMap.length,
         | 
| @@ -12867,7 +13029,7 @@ Series.prototype = { | |
| 12867 13029 | 
             
            		// first value is tested, and we assume that all the rest are defined the same
         | 
| 12868 13030 | 
             
            		// way. Although the 'for' loops are similar, they are repeated inside each
         | 
| 12869 13031 | 
             
            		// if-else conditional for max performance.
         | 
| 12870 | 
            -
            		if (dataLength > turboThreshold) {
         | 
| 13032 | 
            +
            		if (turboThreshold && dataLength > turboThreshold) { 
         | 
| 12871 13033 |  | 
| 12872 13034 | 
             
            			// find the first non-null point
         | 
| 12873 13035 | 
             
            			i = 0;
         | 
| @@ -12913,18 +13075,12 @@ Series.prototype = { | |
| 12913 13075 | 
             
            					yData[i] = hasToYData ? series.toYData(pt) : pt.y;
         | 
| 12914 13076 | 
             
            					zData[i] = pt.z;
         | 
| 12915 13077 | 
             
            					if (names && pt.name) {
         | 
| 12916 | 
            -
            						names[ | 
| 13078 | 
            +
            						names[pt.x] = pt.name; // #2046
         | 
| 12917 13079 | 
             
            					}
         | 
| 12918 13080 | 
             
            				}
         | 
| 12919 13081 | 
             
            			}
         | 
| 12920 13082 | 
             
            		}
         | 
| 12921 13083 |  | 
| 12922 | 
            -
            		// Unsorted data is not supported by the line tooltip as well as data grouping and 
         | 
| 12923 | 
            -
            		// navigation in Stock charts (#725)
         | 
| 12924 | 
            -
            		if (series.requireSorting && xData.length > 1 && xData[1] < xData[0]) {
         | 
| 12925 | 
            -
            			error(15);
         | 
| 12926 | 
            -
            		}
         | 
| 12927 | 
            -
             | 
| 12928 13084 | 
             
            		// Forgetting to cast strings to numbers is a common caveat when handling CSV or JSON		
         | 
| 12929 13085 | 
             
            		if (isString(yData[0])) {
         | 
| 12930 13086 | 
             
            			error(14, true);
         | 
| @@ -13002,8 +13158,8 @@ Series.prototype = { | |
| 13002 13158 | 
             
            			processedXData = series.xData, // copied during slice operation below
         | 
| 13003 13159 | 
             
            			processedYData = series.yData,
         | 
| 13004 13160 | 
             
            			dataLength = processedXData.length,
         | 
| 13161 | 
            +
            			croppedData,
         | 
| 13005 13162 | 
             
            			cropStart = 0,
         | 
| 13006 | 
            -
            			cropEnd = dataLength,
         | 
| 13007 13163 | 
             
            			cropped,
         | 
| 13008 13164 | 
             
            			distance,
         | 
| 13009 13165 | 
             
            			closestPointRange,
         | 
| @@ -13018,12 +13174,12 @@ Series.prototype = { | |
| 13018 13174 | 
             
            		if (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) {
         | 
| 13019 13175 | 
             
            			return false;
         | 
| 13020 13176 | 
             
            		}
         | 
| 13177 | 
            +
            		
         | 
| 13021 13178 |  | 
| 13022 13179 | 
             
            		// optionally filter out points outside the plot area
         | 
| 13023 13180 | 
             
            		if (isCartesian && series.sorted && (!cropThreshold || dataLength > cropThreshold || series.forceCrop)) {
         | 
| 13024 | 
            -
            			var  | 
| 13025 | 
            -
            				 | 
| 13026 | 
            -
            				max = extremes.max;
         | 
| 13181 | 
            +
            			var min = xAxis.min,
         | 
| 13182 | 
            +
            				max = xAxis.max;
         | 
| 13027 13183 |  | 
| 13028 13184 | 
             
            			// it's outside current extremes
         | 
| 13029 13185 | 
             
            			if (processedXData[dataLength - 1] < min || processedXData[0] > max) {
         | 
| @@ -13032,43 +13188,34 @@ Series.prototype = { | |
| 13032 13188 |  | 
| 13033 13189 | 
             
            			// only crop if it's actually spilling out
         | 
| 13034 13190 | 
             
            			} else if (processedXData[0] < min || processedXData[dataLength - 1] > max) {
         | 
| 13035 | 
            -
             | 
| 13036 | 
            -
            				 | 
| 13037 | 
            -
            				 | 
| 13038 | 
            -
             | 
| 13039 | 
            -
            						cropStart = mathMax(0, i - 1);
         | 
| 13040 | 
            -
            						break;
         | 
| 13041 | 
            -
            					}
         | 
| 13042 | 
            -
            				}
         | 
| 13043 | 
            -
            				// proceed to find slice end
         | 
| 13044 | 
            -
            				for (; i < dataLength; i++) {
         | 
| 13045 | 
            -
            					if (processedXData[i] > max) {
         | 
| 13046 | 
            -
            						cropEnd = i + 1;
         | 
| 13047 | 
            -
            						break;
         | 
| 13048 | 
            -
            					}
         | 
| 13049 | 
            -
            					
         | 
| 13050 | 
            -
            				}
         | 
| 13051 | 
            -
            				processedXData = processedXData.slice(cropStart, cropEnd);
         | 
| 13052 | 
            -
            				processedYData = processedYData.slice(cropStart, cropEnd);
         | 
| 13191 | 
            +
            				croppedData = this.cropData(series.xData, series.yData, min, max);
         | 
| 13192 | 
            +
            				processedXData = croppedData.xData;
         | 
| 13193 | 
            +
            				processedYData = croppedData.yData;
         | 
| 13194 | 
            +
            				cropStart = croppedData.start;
         | 
| 13053 13195 | 
             
            				cropped = true;
         | 
| 13054 13196 | 
             
            			}
         | 
| 13055 13197 | 
             
            		}
         | 
| 13056 13198 |  | 
| 13057 13199 |  | 
| 13058 13200 | 
             
            		// Find the closest distance between processed points
         | 
| 13059 | 
            -
            		for (i = processedXData.length - 1; i  | 
| 13201 | 
            +
            		for (i = processedXData.length - 1; i >= 0; i--) {
         | 
| 13060 13202 | 
             
            			distance = processedXData[i] - processedXData[i - 1];
         | 
| 13061 13203 | 
             
            			if (distance > 0 && (closestPointRange === UNDEFINED || distance < closestPointRange)) {
         | 
| 13062 13204 | 
             
            				closestPointRange = distance;
         | 
| 13205 | 
            +
             | 
| 13206 | 
            +
            			// Unsorted data is not supported by the line tooltip, as well as data grouping and 
         | 
| 13207 | 
            +
            			// navigation in Stock charts (#725) and width calculation of columns (#1900)
         | 
| 13208 | 
            +
            			} else if (distance < 0 && series.requireSorting) {
         | 
| 13209 | 
            +
            				error(15);
         | 
| 13063 13210 | 
             
            			}
         | 
| 13064 13211 | 
             
            		}
         | 
| 13065 | 
            -
             | 
| 13212 | 
            +
             | 
| 13066 13213 | 
             
            		// Record the properties
         | 
| 13067 13214 | 
             
            		series.cropped = cropped; // undefined or true
         | 
| 13068 13215 | 
             
            		series.cropStart = cropStart;
         | 
| 13069 13216 | 
             
            		series.processedXData = processedXData;
         | 
| 13070 13217 | 
             
            		series.processedYData = processedYData;
         | 
| 13071 | 
            -
             | 
| 13218 | 
            +
             | 
| 13072 13219 | 
             
            		if (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC
         | 
| 13073 13220 | 
             
            			series.pointRange = closestPointRange || 1;
         | 
| 13074 13221 | 
             
            		}
         | 
| @@ -13076,6 +13223,41 @@ Series.prototype = { | |
| 13076 13223 |  | 
| 13077 13224 | 
             
            	},
         | 
| 13078 13225 |  | 
| 13226 | 
            +
            	/**
         | 
| 13227 | 
            +
            	 * Iterate over xData and crop values between min and max. Returns object containing crop start/end
         | 
| 13228 | 
            +
            	 * cropped xData with corresponding part of yData, dataMin and dataMax within the cropped range
         | 
| 13229 | 
            +
            	 */
         | 
| 13230 | 
            +
            	cropData: function (xData, yData, min, max) {
         | 
| 13231 | 
            +
            		var dataLength = xData.length,
         | 
| 13232 | 
            +
            			cropStart = 0,
         | 
| 13233 | 
            +
            			cropEnd = dataLength,
         | 
| 13234 | 
            +
            			i;
         | 
| 13235 | 
            +
             | 
| 13236 | 
            +
            		// iterate up to find slice start
         | 
| 13237 | 
            +
            		for (i = 0; i < dataLength; i++) {
         | 
| 13238 | 
            +
            			if (xData[i] >= min) {
         | 
| 13239 | 
            +
            				cropStart = mathMax(0, i - 1);
         | 
| 13240 | 
            +
            				break;
         | 
| 13241 | 
            +
            			}
         | 
| 13242 | 
            +
            		}
         | 
| 13243 | 
            +
             | 
| 13244 | 
            +
            		// proceed to find slice end
         | 
| 13245 | 
            +
            		for (; i < dataLength; i++) {
         | 
| 13246 | 
            +
            			if (xData[i] > max) {
         | 
| 13247 | 
            +
            				cropEnd = i + 1;
         | 
| 13248 | 
            +
            				break;
         | 
| 13249 | 
            +
            			}
         | 
| 13250 | 
            +
            		}
         | 
| 13251 | 
            +
             | 
| 13252 | 
            +
            		return {
         | 
| 13253 | 
            +
            			xData: xData.slice(cropStart, cropEnd),
         | 
| 13254 | 
            +
            			yData: yData.slice(cropStart, cropEnd),
         | 
| 13255 | 
            +
            			start: cropStart,
         | 
| 13256 | 
            +
            			end: cropEnd
         | 
| 13257 | 
            +
            		};
         | 
| 13258 | 
            +
            	},
         | 
| 13259 | 
            +
             | 
| 13260 | 
            +
             | 
| 13079 13261 | 
             
            	/**
         | 
| 13080 13262 | 
             
            	 * Generate the data point after the data has been processed by cropping away
         | 
| 13081 13263 | 
             
            	 * unused points and optionally grouped in Highcharts Stock.
         | 
| @@ -13136,6 +13318,154 @@ Series.prototype = { | |
| 13136 13318 | 
             
            		series.points = points;
         | 
| 13137 13319 | 
             
            	},
         | 
| 13138 13320 |  | 
| 13321 | 
            +
            	/**
         | 
| 13322 | 
            +
            	 * Adds series' points value to corresponding stack
         | 
| 13323 | 
            +
            	 */
         | 
| 13324 | 
            +
            	setStackedPoints: function () {
         | 
| 13325 | 
            +
            		if (!this.options.stacking || (this.visible !== true && this.chart.options.chart.ignoreHiddenSeries !== false)) {
         | 
| 13326 | 
            +
            			return;
         | 
| 13327 | 
            +
            		}
         | 
| 13328 | 
            +
             | 
| 13329 | 
            +
            		var series = this,
         | 
| 13330 | 
            +
            			xData = series.processedXData,
         | 
| 13331 | 
            +
            			yData = series.processedYData,
         | 
| 13332 | 
            +
            			yDataLength = yData.length,
         | 
| 13333 | 
            +
            			seriesOptions = series.options,
         | 
| 13334 | 
            +
            			threshold = seriesOptions.threshold,
         | 
| 13335 | 
            +
            			stackOption = seriesOptions.stack,
         | 
| 13336 | 
            +
            			stacking = seriesOptions.stacking,
         | 
| 13337 | 
            +
            			stackKey = series.stackKey,
         | 
| 13338 | 
            +
            			negKey = '-' + stackKey,
         | 
| 13339 | 
            +
            			yAxis = series.yAxis,
         | 
| 13340 | 
            +
            			stacks = yAxis.stacks,
         | 
| 13341 | 
            +
            			oldStacks = yAxis.oldStacks,
         | 
| 13342 | 
            +
            			stacksMax = yAxis.stacksMax,
         | 
| 13343 | 
            +
            			isNegative,
         | 
| 13344 | 
            +
            			total,
         | 
| 13345 | 
            +
            			stack,
         | 
| 13346 | 
            +
            			key,
         | 
| 13347 | 
            +
            			i,
         | 
| 13348 | 
            +
            			x,
         | 
| 13349 | 
            +
            			y;
         | 
| 13350 | 
            +
             | 
| 13351 | 
            +
            		// loop over the non-null y values and read them into a local array
         | 
| 13352 | 
            +
            		for (i = 0; i < yDataLength; i++) {
         | 
| 13353 | 
            +
            			x = xData[i];
         | 
| 13354 | 
            +
            			y = yData[i];
         | 
| 13355 | 
            +
             | 
| 13356 | 
            +
            			// Read stacked values into a stack based on the x value,
         | 
| 13357 | 
            +
            			// the sign of y and the stack key. Stacking is also handled for null values (#739)
         | 
| 13358 | 
            +
            			isNegative = y < threshold;
         | 
| 13359 | 
            +
            			key = isNegative ? negKey : stackKey;
         | 
| 13360 | 
            +
             | 
| 13361 | 
            +
            			// Set default stacksMax value for this stack
         | 
| 13362 | 
            +
            			if (!stacksMax[key]) {
         | 
| 13363 | 
            +
            				stacksMax[key] = y;
         | 
| 13364 | 
            +
            			}
         | 
| 13365 | 
            +
             | 
| 13366 | 
            +
            			// Create empty object for this stack if it doesn't exist yet
         | 
| 13367 | 
            +
            			if (!stacks[key]) {
         | 
| 13368 | 
            +
            				stacks[key] = {};
         | 
| 13369 | 
            +
            			}
         | 
| 13370 | 
            +
             | 
| 13371 | 
            +
            			// Initialize StackItem for this x
         | 
| 13372 | 
            +
            			if (oldStacks[key] && oldStacks[key][x]) {
         | 
| 13373 | 
            +
            				stacks[key][x] = oldStacks[key][x];
         | 
| 13374 | 
            +
            				stacks[key][x].total = null;
         | 
| 13375 | 
            +
            			} else if (!stacks[key][x]) {
         | 
| 13376 | 
            +
            				stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption, stacking);
         | 
| 13377 | 
            +
            			}
         | 
| 13378 | 
            +
             | 
| 13379 | 
            +
            			// If the StackItem doesn't exist, create it first
         | 
| 13380 | 
            +
            			stack = stacks[key][x];
         | 
| 13381 | 
            +
            			total = stack.total;
         | 
| 13382 | 
            +
             | 
| 13383 | 
            +
             | 
| 13384 | 
            +
            			// add value to the stack total
         | 
| 13385 | 
            +
            			stack.addValue(y);
         | 
| 13386 | 
            +
             | 
| 13387 | 
            +
            			stack.cacheExtremes(series, [total, total + y]);
         | 
| 13388 | 
            +
             | 
| 13389 | 
            +
             | 
| 13390 | 
            +
            			if (stack.total > stacksMax[key] && !isNegative) {
         | 
| 13391 | 
            +
            				stacksMax[key] = stack.total;
         | 
| 13392 | 
            +
            			} else if (stack.total < stacksMax[key] && isNegative) {
         | 
| 13393 | 
            +
            				stacksMax[key] = stack.total;
         | 
| 13394 | 
            +
            			}
         | 
| 13395 | 
            +
            		}
         | 
| 13396 | 
            +
             | 
| 13397 | 
            +
            		// reset old stacks
         | 
| 13398 | 
            +
            		yAxis.oldStacks = {};
         | 
| 13399 | 
            +
            	},
         | 
| 13400 | 
            +
             | 
| 13401 | 
            +
            	/**
         | 
| 13402 | 
            +
            	 * Calculate x and y extremes for visible data
         | 
| 13403 | 
            +
            	 */
         | 
| 13404 | 
            +
            	getExtremes: function () {
         | 
| 13405 | 
            +
            		var xAxis = this.xAxis,
         | 
| 13406 | 
            +
            			yAxis = this.yAxis,
         | 
| 13407 | 
            +
            			stackKey = this.stackKey,
         | 
| 13408 | 
            +
            			options = this.options,
         | 
| 13409 | 
            +
            			threshold = options.threshold,
         | 
| 13410 | 
            +
            			xData = this.processedXData,
         | 
| 13411 | 
            +
            			yData = this.processedYData,
         | 
| 13412 | 
            +
            			yDataLength = yData.length,
         | 
| 13413 | 
            +
            			activeYData = [],
         | 
| 13414 | 
            +
            			activeCounter = 0,
         | 
| 13415 | 
            +
            			xMin = xAxis.min,
         | 
| 13416 | 
            +
            			xMax = xAxis.max,
         | 
| 13417 | 
            +
            			validValue,
         | 
| 13418 | 
            +
            			withinRange,
         | 
| 13419 | 
            +
            			dataMin,
         | 
| 13420 | 
            +
            			dataMax,
         | 
| 13421 | 
            +
            			x,
         | 
| 13422 | 
            +
            			y,
         | 
| 13423 | 
            +
            			i,
         | 
| 13424 | 
            +
            			j;
         | 
| 13425 | 
            +
             | 
| 13426 | 
            +
            		// For stacked series, get the value from the stack
         | 
| 13427 | 
            +
            		if (options.stacking) {
         | 
| 13428 | 
            +
            			dataMin = yAxis.stacksMax['-' + stackKey] || threshold;
         | 
| 13429 | 
            +
            			dataMax = yAxis.stacksMax[stackKey] || threshold;
         | 
| 13430 | 
            +
            		}
         | 
| 13431 | 
            +
             | 
| 13432 | 
            +
            		// If not stacking or threshold is null, iterate over values that are within the visible range
         | 
| 13433 | 
            +
            		if (!defined(dataMin) || !defined(dataMax)) {
         | 
| 13434 | 
            +
             | 
| 13435 | 
            +
            			for (i = 0; i < yDataLength; i++) {
         | 
| 13436 | 
            +
            				
         | 
| 13437 | 
            +
            				x = xData[i];
         | 
| 13438 | 
            +
            				y = yData[i];
         | 
| 13439 | 
            +
             | 
| 13440 | 
            +
            				// For points within the visible range, including the first point outside the
         | 
| 13441 | 
            +
            				// visible range, consider y extremes
         | 
| 13442 | 
            +
            				validValue = y !== null && y !== UNDEFINED && (!yAxis.isLog || (y.length || y > 0));
         | 
| 13443 | 
            +
            				withinRange = this.getExtremesFromAll || this.cropped || ((xData[i + 1] || x) >= xMin && 
         | 
| 13444 | 
            +
            					(xData[i - 1] || x) <= xMax);
         | 
| 13445 | 
            +
             | 
| 13446 | 
            +
            				if (validValue && withinRange) {
         | 
| 13447 | 
            +
             | 
| 13448 | 
            +
            					j = y.length;
         | 
| 13449 | 
            +
            					if (j) { // array, like ohlc or range data
         | 
| 13450 | 
            +
            						while (j--) {
         | 
| 13451 | 
            +
            							if (y[j] !== null) {
         | 
| 13452 | 
            +
            								activeYData[activeCounter++] = y[j];
         | 
| 13453 | 
            +
            							}
         | 
| 13454 | 
            +
            						}
         | 
| 13455 | 
            +
            					} else {
         | 
| 13456 | 
            +
            						activeYData[activeCounter++] = y;
         | 
| 13457 | 
            +
            					}
         | 
| 13458 | 
            +
            				}
         | 
| 13459 | 
            +
            			}
         | 
| 13460 | 
            +
            			dataMin = pick(dataMin, arrayMin(activeYData));
         | 
| 13461 | 
            +
            			dataMax = pick(dataMax, arrayMax(activeYData));
         | 
| 13462 | 
            +
            		}
         | 
| 13463 | 
            +
             | 
| 13464 | 
            +
            		// Set
         | 
| 13465 | 
            +
            		this.dataMin = dataMin;
         | 
| 13466 | 
            +
            		this.dataMax = dataMax;
         | 
| 13467 | 
            +
            	},
         | 
| 13468 | 
            +
             | 
| 13139 13469 | 
             
            	/**
         | 
| 13140 13470 | 
             
            	 * Translate data points from raw data values to chart specific positioning data
         | 
| 13141 13471 | 
             
            	 * needed later in drawPoints, drawGraph and drawTracker.
         | 
| @@ -13154,27 +13484,11 @@ Series.prototype = { | |
| 13154 13484 | 
             
            			points = series.points,
         | 
| 13155 13485 | 
             
            			dataLength = points.length,
         | 
| 13156 13486 | 
             
            			hasModifyValue = !!series.modifyValue,
         | 
| 13157 | 
            -
            			isBottomSeries,
         | 
| 13158 | 
            -
            			allStackSeries,
         | 
| 13159 13487 | 
             
            			i,
         | 
| 13160 | 
            -
            			 | 
| 13488 | 
            +
            			pointPlacement = options.pointPlacement, // docs: accept numbers
         | 
| 13489 | 
            +
            			dynamicallyPlaced = pointPlacement === 'between' || isNumber(pointPlacement),
         | 
| 13161 13490 | 
             
            			threshold = options.threshold;
         | 
| 13162 | 
            -
             | 
| 13163 | 
            -
            			
         | 
| 13164 | 
            -
            		// Is it the last visible series? (#809, #1722).
         | 
| 13165 | 
            -
            		// TODO: After merging in the 'stacking' branch, this logic should probably be moved to Chart.getStacks
         | 
| 13166 | 
            -
            		allStackSeries = yAxis.series.sort(function (a, b) {
         | 
| 13167 | 
            -
            			return a.index - b.index;
         | 
| 13168 | 
            -
            		});
         | 
| 13169 | 
            -
            		i = allStackSeries.length;
         | 
| 13170 | 
            -
            		while (i--) {
         | 
| 13171 | 
            -
            			if (allStackSeries[i].visible) {
         | 
| 13172 | 
            -
            				if (allStackSeries[i] === series) { // #809
         | 
| 13173 | 
            -
            					isBottomSeries = true;
         | 
| 13174 | 
            -
            				}
         | 
| 13175 | 
            -
            				break;
         | 
| 13176 | 
            -
            			}
         | 
| 13177 | 
            -
            		}
         | 
| 13491 | 
            +
             | 
| 13178 13492 |  | 
| 13179 13493 | 
             
            		// Translate each point
         | 
| 13180 13494 | 
             
            		for (i = 0; i < dataLength; i++) {
         | 
| @@ -13192,16 +13506,18 @@ Series.prototype = { | |
| 13192 13506 | 
             
            			}
         | 
| 13193 13507 |  | 
| 13194 13508 | 
             
            			// Get the plotX translation
         | 
| 13195 | 
            -
            			point.plotX = xAxis.translate(xValue, 0, 0, 0, 1,  | 
| 13509 | 
            +
            			point.plotX = xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement); // Math.round fixes #591
         | 
| 13196 13510 |  | 
| 13197 13511 | 
             
            			// Calculate the bottom y value for stacked series
         | 
| 13198 13512 | 
             
            			if (stacking && series.visible && stack && stack[xValue]) {
         | 
| 13513 | 
            +
             | 
| 13514 | 
            +
             | 
| 13199 13515 | 
             
            				pointStack = stack[xValue];
         | 
| 13200 13516 | 
             
            				pointStackTotal = pointStack.total;
         | 
| 13201 13517 | 
             
            				pointStack.cum = yBottom = pointStack.cum - yValue; // start from top
         | 
| 13202 13518 | 
             
            				yValue = yBottom + yValue;
         | 
| 13203 13519 |  | 
| 13204 | 
            -
            				if ( | 
| 13520 | 
            +
            				if (pointStack.cum === 0) {
         | 
| 13205 13521 | 
             
            					yBottom = pick(threshold, yAxis.min);
         | 
| 13206 13522 | 
             
            				}
         | 
| 13207 13523 |  | 
| @@ -13217,6 +13533,10 @@ Series.prototype = { | |
| 13217 13533 | 
             
            				point.percentage = pointStackTotal ? point.y * 100 / pointStackTotal : 0;
         | 
| 13218 13534 | 
             
            				point.total = point.stackTotal = pointStackTotal;
         | 
| 13219 13535 | 
             
            				point.stackY = yValue;
         | 
| 13536 | 
            +
             | 
| 13537 | 
            +
            				// Place the stack label
         | 
| 13538 | 
            +
            				pointStack.setOffset(series.pointXOffset || 0, series.barW || 0);
         | 
| 13539 | 
            +
            				
         | 
| 13220 13540 | 
             
            			}
         | 
| 13221 13541 |  | 
| 13222 13542 | 
             
            			// Set translated yBottom or remove it
         | 
| @@ -13235,7 +13555,7 @@ Series.prototype = { | |
| 13235 13555 | 
             
            				UNDEFINED;
         | 
| 13236 13556 |  | 
| 13237 13557 | 
             
            			// Set client related positions for mouse tracking
         | 
| 13238 | 
            -
            			point.clientX =  | 
| 13558 | 
            +
            			point.clientX = dynamicallyPlaced ? xAxis.translate(xValue, 0, 0, 0, 1) : point.plotX; // #1514
         | 
| 13239 13559 |  | 
| 13240 13560 | 
             
            			point.negative = point.y < (threshold || 0);
         | 
| 13241 13561 |  | 
| @@ -13261,6 +13581,7 @@ Series.prototype = { | |
| 13261 13581 | 
             
            			xAxis = series.xAxis,
         | 
| 13262 13582 | 
             
            			axisLength = xAxis ? (xAxis.tooltipLen || xAxis.len) : series.chart.plotSizeX, // tooltipLen and tooltipPosName used in polar
         | 
| 13263 13583 | 
             
            			point,
         | 
| 13584 | 
            +
            			nextPoint,
         | 
| 13264 13585 | 
             
            			i,
         | 
| 13265 13586 | 
             
            			tooltipPoints = []; // a lookup array for each pixel in the x dimension
         | 
| 13266 13587 |  | 
| @@ -13284,15 +13605,24 @@ Series.prototype = { | |
| 13284 13605 | 
             
            			points = points.reverse();
         | 
| 13285 13606 | 
             
            		}
         | 
| 13286 13607 |  | 
| 13608 | 
            +
            		// Polar needs additional shaping
         | 
| 13609 | 
            +
            		if (series.orderTooltipPoints) {
         | 
| 13610 | 
            +
            			series.orderTooltipPoints(points);
         | 
| 13611 | 
            +
            		}
         | 
| 13612 | 
            +
             | 
| 13287 13613 | 
             
            		// Assign each pixel position to the nearest point
         | 
| 13288 13614 | 
             
            		pointsLength = points.length;
         | 
| 13289 13615 | 
             
            		for (i = 0; i < pointsLength; i++) {
         | 
| 13290 13616 | 
             
            			point = points[i];
         | 
| 13617 | 
            +
            			nextPoint = points[i + 1];
         | 
| 13618 | 
            +
            			
         | 
| 13291 13619 | 
             
            			// Set this range's low to the last range's high plus one
         | 
| 13292 13620 | 
             
            			low = points[i - 1] ? high + 1 : 0;
         | 
| 13293 13621 | 
             
            			// Now find the new high
         | 
| 13294 13622 | 
             
            			high = points[i + 1] ?
         | 
| 13295 | 
            -
            				mathMax(0, mathFloor( | 
| 13623 | 
            +
            				mathMin(mathMax(0, mathFloor( // #2070
         | 
| 13624 | 
            +
            					(point.clientX + (nextPoint ? (nextPoint.wrappedClientX || nextPoint.clientX) : axisLength)) / 2
         | 
| 13625 | 
            +
            				)), axisLength) :
         | 
| 13296 13626 | 
             
            				axisLength;
         | 
| 13297 13627 |  | 
| 13298 13628 | 
             
            			while (low >= 0 && low <= high) {
         | 
| @@ -13512,7 +13842,7 @@ Series.prototype = { | |
| 13512 13842 | 
             
            			i = points.length;
         | 
| 13513 13843 | 
             
            			while (i--) {
         | 
| 13514 13844 | 
             
            				point = points[i];
         | 
| 13515 | 
            -
            				plotX = point.plotX;
         | 
| 13845 | 
            +
            				plotX = mathFloor(point.plotX); // #1843
         | 
| 13516 13846 | 
             
            				plotY = point.plotY;
         | 
| 13517 13847 | 
             
            				graphic = point.graphic;
         | 
| 13518 13848 | 
             
            				pointMarkerOptions = point.marker || {};
         | 
| @@ -13738,7 +14068,7 @@ Series.prototype = { | |
| 13738 14068 | 
             
            			animation: false,
         | 
| 13739 14069 | 
             
            			index: this.index,
         | 
| 13740 14070 | 
             
            			pointStart: this.xData[0] // when updating after addPoint
         | 
| 13741 | 
            -
            		}, newOptions);
         | 
| 14071 | 
            +
            		}, { data: this.options.data }, newOptions);
         | 
| 13742 14072 |  | 
| 13743 14073 | 
             
            		// Destroy the series and reinsert methods from the type prototype
         | 
| 13744 14074 | 
             
            		this.remove(false);
         | 
| @@ -13879,12 +14209,12 @@ Series.prototype = { | |
| 13879 14209 | 
             
            				// in the point options, or if they fall outside the plot area.
         | 
| 13880 14210 | 
             
            				} else if (enabled) {
         | 
| 13881 14211 |  | 
| 13882 | 
            -
            					rotation = options.rotation;
         | 
| 13883 | 
            -
            					
         | 
| 13884 14212 | 
             
            					// Create individual options structure that can be extended without 
         | 
| 13885 14213 | 
             
            					// affecting others
         | 
| 13886 14214 | 
             
            					options = merge(generalOptions, pointOptions);
         | 
| 13887 | 
            -
             | 
| 14215 | 
            +
             | 
| 14216 | 
            +
            					rotation = options.rotation;
         | 
| 14217 | 
            +
            					
         | 
| 13888 14218 | 
             
            					// Get the string
         | 
| 13889 14219 | 
             
            					labelConfig = point.getLabelConfig();
         | 
| 13890 14220 | 
             
            					str = options.format ?
         | 
| @@ -13980,7 +14310,7 @@ Series.prototype = { | |
| 13980 14310 | 
             
            			width: bBox.width,
         | 
| 13981 14311 | 
             
            			height: bBox.height
         | 
| 13982 14312 | 
             
            		});
         | 
| 13983 | 
            -
             | 
| 14313 | 
            +
             | 
| 13984 14314 | 
             
            		// Allow a hook for changing alignment in the last moment, then do the alignment
         | 
| 13985 14315 | 
             
            		if (options.rotation) { // Fancy box alignment isn't supported for rotated text
         | 
| 13986 14316 | 
             
            			alignAttr = {
         | 
| @@ -13996,7 +14326,8 @@ Series.prototype = { | |
| 13996 14326 |  | 
| 13997 14327 | 
             
            		// Show or hide based on the final aligned position
         | 
| 13998 14328 | 
             
            		dataLabel.attr({
         | 
| 13999 | 
            -
            			visibility: options.crop === false || | 
| 14329 | 
            +
            			visibility: options.crop === false ||
         | 
| 14330 | 
            +
            					(chart.isInsidePlot(alignAttr.x, alignAttr.y) && chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height)) ?
         | 
| 14000 14331 | 
             
            				(chart.renderer.isSVG ? 'inherit' : VISIBLE) : 
         | 
| 14001 14332 | 
             
            				HIDDEN
         | 
| 14002 14333 | 
             
            		});
         | 
| @@ -14143,7 +14474,7 @@ Series.prototype = { | |
| 14143 14474 | 
             
            		var options = this.options,
         | 
| 14144 14475 | 
             
            			chart = this.chart,
         | 
| 14145 14476 | 
             
            			renderer = chart.renderer,
         | 
| 14146 | 
            -
            			negativeColor = options.negativeColor,
         | 
| 14477 | 
            +
            			negativeColor = options.negativeColor || options.negativeFillColor,
         | 
| 14147 14478 | 
             
            			translatedThreshold,
         | 
| 14148 14479 | 
             
            			posAttr,
         | 
| 14149 14480 | 
             
            			negAttr,
         | 
| @@ -14154,11 +14485,12 @@ Series.prototype = { | |
| 14154 14485 | 
             
            			chartWidth = chart.chartWidth,
         | 
| 14155 14486 | 
             
            			chartHeight = chart.chartHeight,
         | 
| 14156 14487 | 
             
            			chartSizeMax = mathMax(chartWidth, chartHeight),
         | 
| 14488 | 
            +
            			yAxis = this.yAxis,
         | 
| 14157 14489 | 
             
            			above,
         | 
| 14158 14490 | 
             
            			below;
         | 
| 14159 14491 |  | 
| 14160 14492 | 
             
            		if (negativeColor && (graph || area)) {
         | 
| 14161 | 
            -
            			translatedThreshold =  | 
| 14493 | 
            +
            			translatedThreshold = mathRound(yAxis.toPixels(options.threshold || 0, true));
         | 
| 14162 14494 | 
             
            			above = {
         | 
| 14163 14495 | 
             
            				x: 0,
         | 
| 14164 14496 | 
             
            				y: 0,
         | 
| @@ -14169,25 +14501,29 @@ Series.prototype = { | |
| 14169 14501 | 
             
            				x: 0,
         | 
| 14170 14502 | 
             
            				y: translatedThreshold,
         | 
| 14171 14503 | 
             
            				width: chartSizeMax,
         | 
| 14172 | 
            -
            				height: chartSizeMax | 
| 14504 | 
            +
            				height: chartSizeMax
         | 
| 14173 14505 | 
             
            			};
         | 
| 14174 14506 |  | 
| 14175 | 
            -
            			if (chart.inverted | 
| 14176 | 
            -
             | 
| 14177 | 
            -
             | 
| 14178 | 
            -
             | 
| 14179 | 
            -
            					 | 
| 14180 | 
            -
             | 
| 14181 | 
            -
             | 
| 14182 | 
            -
             | 
| 14183 | 
            -
             | 
| 14184 | 
            -
            					 | 
| 14185 | 
            -
            					 | 
| 14186 | 
            -
             | 
| 14187 | 
            -
             | 
| 14507 | 
            +
            			if (chart.inverted) {
         | 
| 14508 | 
            +
             | 
| 14509 | 
            +
            				above.height = below.y = chart.plotWidth - translatedThreshold;
         | 
| 14510 | 
            +
            				if (renderer.isVML) {
         | 
| 14511 | 
            +
            					above = {
         | 
| 14512 | 
            +
            						x: chart.plotWidth - translatedThreshold - chart.plotLeft,
         | 
| 14513 | 
            +
            						y: 0,
         | 
| 14514 | 
            +
            						width: chartWidth,
         | 
| 14515 | 
            +
            						height: chartHeight
         | 
| 14516 | 
            +
            					};
         | 
| 14517 | 
            +
            					below = {
         | 
| 14518 | 
            +
            						x: translatedThreshold + chart.plotLeft - chartWidth,
         | 
| 14519 | 
            +
            						y: 0,
         | 
| 14520 | 
            +
            						width: chart.plotLeft + translatedThreshold,
         | 
| 14521 | 
            +
            						height: chartWidth
         | 
| 14522 | 
            +
            					};
         | 
| 14523 | 
            +
            				}
         | 
| 14188 14524 | 
             
            			}
         | 
| 14189 14525 |  | 
| 14190 | 
            -
            			if ( | 
| 14526 | 
            +
            			if (yAxis.reversed) {
         | 
| 14191 14527 | 
             
            				posAttr = below;
         | 
| 14192 14528 | 
             
            				negAttr = above;
         | 
| 14193 14529 | 
             
            			} else {
         | 
| @@ -14203,7 +14539,7 @@ Series.prototype = { | |
| 14203 14539 | 
             
            				this.posClip = posClip = renderer.clipRect(posAttr);
         | 
| 14204 14540 | 
             
            				this.negClip = negClip = renderer.clipRect(negAttr);
         | 
| 14205 14541 |  | 
| 14206 | 
            -
            				if (graph) {
         | 
| 14542 | 
            +
            				if (graph && this.graphNeg) {
         | 
| 14207 14543 | 
             
            					graph.clip(posClip);
         | 
| 14208 14544 | 
             
            					this.graphNeg.clip(negClip);	
         | 
| 14209 14545 | 
             
            				}
         | 
| @@ -14260,14 +14596,11 @@ Series.prototype = { | |
| 14260 14596 | 
             
            	 */
         | 
| 14261 14597 | 
             
            	plotGroup: function (prop, name, visibility, zIndex, parent) {
         | 
| 14262 14598 | 
             
            		var group = this[prop],
         | 
| 14263 | 
            -
            			isNew = !group | 
| 14264 | 
            -
            			chart = this.chart,
         | 
| 14265 | 
            -
            			xAxis = this.xAxis,
         | 
| 14266 | 
            -
            			yAxis = this.yAxis;
         | 
| 14599 | 
            +
            			isNew = !group;
         | 
| 14267 14600 |  | 
| 14268 14601 | 
             
            		// Generate it on first call
         | 
| 14269 14602 | 
             
            		if (isNew) {	
         | 
| 14270 | 
            -
            			this[prop] = group = chart.renderer.g(name)
         | 
| 14603 | 
            +
            			this[prop] = group = this.chart.renderer.g(name)
         | 
| 14271 14604 | 
             
            				.attr({
         | 
| 14272 14605 | 
             
            					visibility: visibility,
         | 
| 14273 14606 | 
             
            					zIndex: zIndex || 0.1 // IE8 needs this
         | 
| @@ -14275,14 +14608,20 @@ Series.prototype = { | |
| 14275 14608 | 
             
            				.add(parent);
         | 
| 14276 14609 | 
             
            		}
         | 
| 14277 14610 | 
             
            		// Place it on first and subsequent (redraw) calls
         | 
| 14278 | 
            -
            		group[isNew ? 'attr' : 'animate']( | 
| 14279 | 
            -
             | 
| 14280 | 
            -
             | 
| 14611 | 
            +
            		group[isNew ? 'attr' : 'animate'](this.getPlotBox());
         | 
| 14612 | 
            +
            		return group;		
         | 
| 14613 | 
            +
            	},
         | 
| 14614 | 
            +
             | 
| 14615 | 
            +
            	/**
         | 
| 14616 | 
            +
            	 * Get the translation and scale for the plot area of this series
         | 
| 14617 | 
            +
            	 */
         | 
| 14618 | 
            +
            	getPlotBox: function () {
         | 
| 14619 | 
            +
            		return {
         | 
| 14620 | 
            +
            			translateX: this.xAxis ? this.xAxis.left : this.chart.plotLeft, 
         | 
| 14621 | 
            +
            			translateY: this.yAxis ? this.yAxis.top : this.chart.plotTop,
         | 
| 14281 14622 | 
             
            			scaleX: 1, // #1623
         | 
| 14282 14623 | 
             
            			scaleY: 1
         | 
| 14283 | 
            -
            		} | 
| 14284 | 
            -
            		return group;
         | 
| 14285 | 
            -
            		
         | 
| 14624 | 
            +
            		};
         | 
| 14286 14625 | 
             
            	},
         | 
| 14287 14626 |  | 
| 14288 14627 | 
             
            	/**
         | 
| @@ -14661,6 +15000,7 @@ var AreaSeries = extendClass(Series, { | |
| 14661 15000 | 
             
            			plotX,
         | 
| 14662 15001 | 
             
            			plotY,
         | 
| 14663 15002 | 
             
            			points = this.points,
         | 
| 15003 | 
            +
            			val,
         | 
| 14664 15004 | 
             
            			i,
         | 
| 14665 15005 | 
             
            			x;
         | 
| 14666 15006 |  | 
| @@ -14688,7 +15028,8 @@ var AreaSeries = extendClass(Series, { | |
| 14688 15028 | 
             
            				// correctly.
         | 
| 14689 15029 | 
             
            				} else {
         | 
| 14690 15030 | 
             
            					plotX = xAxis.translate(x);
         | 
| 14691 | 
            -
            					 | 
| 15031 | 
            +
            					val = stack[x].percent ? (stack[x].total ? stack[x].cum * 100 / stack[x].total : 0) : stack[x].cum; // #1991
         | 
| 15032 | 
            +
            					plotY = yAxis.toPixels(val, true);
         | 
| 14692 15033 | 
             
            					segment.push({ 
         | 
| 14693 15034 | 
             
            						y: null, 
         | 
| 14694 15035 | 
             
            						plotX: plotX,
         | 
| @@ -14784,10 +15125,11 @@ var AreaSeries = extendClass(Series, { | |
| 14784 15125 | 
             
            			areaPath = this.areaPath,
         | 
| 14785 15126 | 
             
            			options = this.options,
         | 
| 14786 15127 | 
             
            			negativeColor = options.negativeColor,
         | 
| 15128 | 
            +
            			negativeFillColor = options.negativeFillColor,
         | 
| 14787 15129 | 
             
            			props = [['area', this.color, options.fillColor]]; // area name, main color, fill color
         | 
| 14788 15130 |  | 
| 14789 | 
            -
            		if (negativeColor) {
         | 
| 14790 | 
            -
            			props.push(['areaNeg',  | 
| 15131 | 
            +
            		if (negativeColor || negativeFillColor) {
         | 
| 15132 | 
            +
            			props.push(['areaNeg', negativeColor, negativeFillColor]);
         | 
| 14791 15133 | 
             
            		}
         | 
| 14792 15134 |  | 
| 14793 15135 | 
             
            		each(props, function (prop) {
         | 
| @@ -14803,7 +15145,7 @@ var AreaSeries = extendClass(Series, { | |
| 14803 15145 | 
             
            					.attr({
         | 
| 14804 15146 | 
             
            						fill: pick(
         | 
| 14805 15147 | 
             
            							prop[2],
         | 
| 14806 | 
            -
            							Color(prop[1]).setOpacity(options.fillOpacity  | 
| 15148 | 
            +
            							Color(prop[1]).setOpacity(pick(options.fillOpacity, 0.75)).get()
         | 
| 14807 15149 | 
             
            						),
         | 
| 14808 15150 | 
             
            						zIndex: 0 // #1069
         | 
| 14809 15151 | 
             
            					}).add(series.group);
         | 
| @@ -14973,7 +15315,8 @@ var areaProto = AreaSeries.prototype, | |
| 14973 15315 | 
             
            		// Mix in methods from the area series
         | 
| 14974 15316 | 
             
            		getSegmentPath: areaProto.getSegmentPath,
         | 
| 14975 15317 | 
             
            		closeSegment: areaProto.closeSegment,
         | 
| 14976 | 
            -
            		drawGraph: areaProto.drawGraph
         | 
| 15318 | 
            +
            		drawGraph: areaProto.drawGraph,
         | 
| 15319 | 
            +
            		drawLegendSymbol: areaProto.drawLegendSymbol
         | 
| 14977 15320 | 
             
            	});
         | 
| 14978 15321 | 
             
            seriesTypes.areaspline = AreaSplineSeries;
         | 
| 14979 15322 |  | 
| @@ -15019,7 +15362,6 @@ defaultPlotOptions.column = merge(defaultSeriesOptions, { | |
| 15019 15362 | 
             
            var ColumnSeries = extendClass(Series, {
         | 
| 15020 15363 | 
             
            	type: 'column',
         | 
| 15021 15364 | 
             
            	tooltipOutsidePlot: true,
         | 
| 15022 | 
            -
            	requireSorting: false,
         | 
| 15023 15365 | 
             
            	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
         | 
| 15024 15366 | 
             
            		stroke: 'borderColor',
         | 
| 15025 15367 | 
             
            		'stroke-width': 'borderWidth',
         | 
| @@ -15055,7 +15397,6 @@ var ColumnSeries = extendClass(Series, { | |
| 15055 15397 | 
             
            	getColumnMetrics: function () {
         | 
| 15056 15398 |  | 
| 15057 15399 | 
             
            		var series = this,
         | 
| 15058 | 
            -
            			chart = series.chart,
         | 
| 15059 15400 | 
             
            			options = series.options,
         | 
| 15060 15401 | 
             
            			xAxis = this.xAxis,
         | 
| 15061 15402 | 
             
            			reversedXAxis = xAxis.reversed,
         | 
| @@ -15070,7 +15411,7 @@ var ColumnSeries = extendClass(Series, { | |
| 15070 15411 | 
             
            		if (options.grouping === false) {
         | 
| 15071 15412 | 
             
            			columnCount = 1;
         | 
| 15072 15413 | 
             
            		} else {
         | 
| 15073 | 
            -
            			each( | 
| 15414 | 
            +
            			each(series.yAxis.series, function (otherSeries) { // use Y axes separately, #642
         | 
| 15074 15415 | 
             
            				var otherOptions = otherSeries.options;
         | 
| 15075 15416 | 
             
            				if (otherSeries.type === series.type && otherSeries.visible &&
         | 
| 15076 15417 | 
             
            						series.options.group === otherOptions.group) { // used in Stock charts navigator series
         | 
| @@ -15121,7 +15462,6 @@ var ColumnSeries = extendClass(Series, { | |
| 15121 15462 | 
             
            		var series = this,
         | 
| 15122 15463 | 
             
            			chart = series.chart,
         | 
| 15123 15464 | 
             
            			options = series.options,
         | 
| 15124 | 
            -
            			stacking = options.stacking,
         | 
| 15125 15465 | 
             
            			borderWidth = options.borderWidth,
         | 
| 15126 15466 | 
             
            			yAxis = series.yAxis,
         | 
| 15127 15467 | 
             
            			threshold = options.threshold,
         | 
| @@ -15129,8 +15469,8 @@ var ColumnSeries = extendClass(Series, { | |
| 15129 15469 | 
             
            			minPointLength = pick(options.minPointLength, 5),
         | 
| 15130 15470 | 
             
            			metrics = series.getColumnMetrics(),
         | 
| 15131 15471 | 
             
            			pointWidth = metrics.width,
         | 
| 15132 | 
            -
            			barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width
         | 
| 15133 | 
            -
            			pointXOffset = metrics.offset;
         | 
| 15472 | 
            +
            			barW = series.barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width
         | 
| 15473 | 
            +
            			pointXOffset = series.pointXOffset = metrics.offset;
         | 
| 15134 15474 |  | 
| 15135 15475 | 
             
            		Series.prototype.translate.apply(series);
         | 
| 15136 15476 |  | 
| @@ -15141,22 +15481,16 @@ var ColumnSeries = extendClass(Series, { | |
| 15141 15481 | 
             
            				barX = point.plotX + pointXOffset,
         | 
| 15142 15482 | 
             
            				barY = mathCeil(mathMin(plotY, yBottom)),
         | 
| 15143 15483 | 
             
            				barH = mathCeil(mathMax(plotY, yBottom) - barY),
         | 
| 15144 | 
            -
            				stack = yAxis.stacks[(point.y < 0 ? '-' : '') + series.stackKey],
         | 
| 15145 15484 | 
             
            				shapeArgs;
         | 
| 15146 15485 |  | 
| 15147 | 
            -
            			// Record the offset'ed position and width of the bar to be able to align the stacking total correctly
         | 
| 15148 | 
            -
            			if (stacking && series.visible && stack && stack[point.x]) {
         | 
| 15149 | 
            -
            				stack[point.x].setOffset(pointXOffset, barW);
         | 
| 15150 | 
            -
            			}
         | 
| 15151 | 
            -
             | 
| 15152 15486 | 
             
            			// handle options.minPointLength
         | 
| 15153 15487 | 
             
            			if (mathAbs(barH) < minPointLength) {
         | 
| 15154 15488 | 
             
            				if (minPointLength) {
         | 
| 15155 15489 | 
             
            					barH = minPointLength;
         | 
| 15156 15490 | 
             
            					barY =
         | 
| 15157 | 
            -
            						mathAbs(barY - translatedThreshold) > minPointLength ? // stacked
         | 
| 15491 | 
            +
            						mathRound(mathAbs(barY - translatedThreshold) > minPointLength ? // stacked
         | 
| 15158 15492 | 
             
            							yBottom - minPointLength : // keep position
         | 
| 15159 | 
            -
            							translatedThreshold - (yAxis.translate(point.y, 0, 1, 0, 1) <= translatedThreshold ? minPointLength : 0); // use exact yAxis.translation (#1485)
         | 
| 15493 | 
            +
            							translatedThreshold - (yAxis.translate(point.y, 0, 1, 0, 1) <= translatedThreshold ? minPointLength : 0)); // use exact yAxis.translation (#1485)
         | 
| 15160 15494 | 
             
            				}
         | 
| 15161 15495 | 
             
            			}
         | 
| 15162 15496 |  | 
| @@ -15232,20 +15566,22 @@ var ColumnSeries = extendClass(Series, { | |
| 15232 15566 | 
             
            	 */
         | 
| 15233 15567 | 
             
            	drawTracker: function () {
         | 
| 15234 15568 | 
             
            		var series = this,
         | 
| 15235 | 
            -
            			 | 
| 15569 | 
            +
            			chart = series.chart,
         | 
| 15570 | 
            +
            			pointer = chart.pointer,
         | 
| 15236 15571 | 
             
            			cursor = series.options.cursor,
         | 
| 15237 15572 | 
             
            			css = cursor && { cursor: cursor },
         | 
| 15238 15573 | 
             
            			onMouseOver = function (e) {
         | 
| 15239 15574 | 
             
            				var target = e.target,
         | 
| 15240 15575 | 
             
            					point;
         | 
| 15241 15576 |  | 
| 15242 | 
            -
            				series | 
| 15243 | 
            -
             | 
| 15577 | 
            +
            				if (chart.hoverSeries !== series) {
         | 
| 15578 | 
            +
            					series.onMouseOver();
         | 
| 15579 | 
            +
            				}
         | 
| 15244 15580 | 
             
            				while (target && !point) {
         | 
| 15245 15581 | 
             
            					point = target.point;
         | 
| 15246 15582 | 
             
            					target = target.parentNode;
         | 
| 15247 15583 | 
             
            				}
         | 
| 15248 | 
            -
            				if (point !== UNDEFINED) { // undefined on graph in scatterchart
         | 
| 15584 | 
            +
            				if (point !== UNDEFINED && point !== chart.hoverPoint) { // undefined on graph in scatterchart
         | 
| 15249 15585 | 
             
            					point.onMouseOver(e);
         | 
| 15250 15586 | 
             
            				}
         | 
| 15251 15587 | 
             
            			};
         | 
| @@ -15495,8 +15831,8 @@ var PiePoint = extendClass(Point, { | |
| 15495 15831 | 
             
            		});
         | 
| 15496 15832 |  | 
| 15497 15833 | 
             
            		// add event listener for select
         | 
| 15498 | 
            -
            		toggleSlice = function () {
         | 
| 15499 | 
            -
            			point.slice();
         | 
| 15834 | 
            +
            		toggleSlice = function (e) {
         | 
| 15835 | 
            +
            			point.slice(e.type === 'select');
         | 
| 15500 15836 | 
             
            		};
         | 
| 15501 15837 | 
             
            		addEvent(point, 'select', toggleSlice);
         | 
| 15502 15838 | 
             
            		addEvent(point, 'unselect', toggleSlice);
         | 
| @@ -15641,6 +15977,39 @@ var PieSeries = { | |
| 15641 15977 | 
             
            			this.chart.redraw();
         | 
| 15642 15978 | 
             
            		} 
         | 
| 15643 15979 | 
             
            	},
         | 
| 15980 | 
            +
             | 
| 15981 | 
            +
            	/**
         | 
| 15982 | 
            +
            	 * Extend the generatePoints method by adding total and percentage properties to each point
         | 
| 15983 | 
            +
            	 */
         | 
| 15984 | 
            +
            	generatePoints: function () {
         | 
| 15985 | 
            +
            		var i,
         | 
| 15986 | 
            +
            			total = 0,
         | 
| 15987 | 
            +
            			points,
         | 
| 15988 | 
            +
            			len,
         | 
| 15989 | 
            +
            			point,
         | 
| 15990 | 
            +
            			ignoreHiddenPoint = this.options.ignoreHiddenPoint;
         | 
| 15991 | 
            +
             | 
| 15992 | 
            +
            		Series.prototype.generatePoints.call(this);
         | 
| 15993 | 
            +
             | 
| 15994 | 
            +
            		// Populate local vars
         | 
| 15995 | 
            +
            		points = this.points;
         | 
| 15996 | 
            +
            		len = points.length;
         | 
| 15997 | 
            +
            		
         | 
| 15998 | 
            +
            		// Get the total sum
         | 
| 15999 | 
            +
            		for (i = 0; i < len; i++) {
         | 
| 16000 | 
            +
            			point = points[i];
         | 
| 16001 | 
            +
            			total += (ignoreHiddenPoint && !point.visible) ? 0 : point.y;
         | 
| 16002 | 
            +
            		}
         | 
| 16003 | 
            +
            		this.total = total;
         | 
| 16004 | 
            +
             | 
| 16005 | 
            +
            		// Set each point's properties
         | 
| 16006 | 
            +
            		for (i = 0; i < len; i++) {
         | 
| 16007 | 
            +
            			point = points[i];
         | 
| 16008 | 
            +
            			point.percentage = (point.y / total) * 100;
         | 
| 16009 | 
            +
            			point.total = total;
         | 
| 16010 | 
            +
            		}
         | 
| 16011 | 
            +
            		
         | 
| 16012 | 
            +
            	},
         | 
| 15644 16013 |  | 
| 15645 16014 | 
             
            	/**
         | 
| 15646 16015 | 
             
            	 * Get the center of the pie based on the size and center options relative to the  
         | 
| @@ -15679,8 +16048,7 @@ var PieSeries = { | |
| 15679 16048 | 
             
            	translate: function (positions) {
         | 
| 15680 16049 | 
             
            		this.generatePoints();
         | 
| 15681 16050 |  | 
| 15682 | 
            -
            		var  | 
| 15683 | 
            -
            			series = this,
         | 
| 16051 | 
            +
            		var series = this,
         | 
| 15684 16052 | 
             
            			cumulative = 0,
         | 
| 15685 16053 | 
             
            			precision = 1000, // issue #172
         | 
| 15686 16054 | 
             
            			options = series.options,
         | 
| @@ -15692,7 +16060,6 @@ var PieSeries = { | |
| 15692 16060 | 
             
            			startAngleRad = series.startAngleRad = mathPI / 180 * ((options.startAngle || 0) % 360 - 90),
         | 
| 15693 16061 | 
             
            			points = series.points,
         | 
| 15694 16062 | 
             
            			circ = 2 * mathPI,
         | 
| 15695 | 
            -
            			fraction,
         | 
| 15696 16063 | 
             
            			radiusX, // the x component of the radius vector for a given point
         | 
| 15697 16064 | 
             
            			radiusY,
         | 
| 15698 16065 | 
             
            			labelDistance = options.dataLabels.distance,
         | 
| @@ -15718,22 +16085,15 @@ var PieSeries = { | |
| 15718 16085 | 
             
            				(mathCos(angle) * (positions[2] / 2 + labelDistance));
         | 
| 15719 16086 | 
             
            		};
         | 
| 15720 16087 |  | 
| 15721 | 
            -
            		// get the total sum
         | 
| 15722 | 
            -
            		for (i = 0; i < len; i++) {
         | 
| 15723 | 
            -
            			point = points[i];
         | 
| 15724 | 
            -
            			total += (ignoreHiddenPoint && !point.visible) ? 0 : point.y;
         | 
| 15725 | 
            -
            		}
         | 
| 15726 | 
            -
             | 
| 15727 16088 | 
             
            		// Calculate the geometry for each point
         | 
| 15728 16089 | 
             
            		for (i = 0; i < len; i++) {
         | 
| 15729 16090 |  | 
| 15730 16091 | 
             
            			point = points[i];
         | 
| 15731 16092 |  | 
| 15732 16093 | 
             
            			// set start and end angle
         | 
| 15733 | 
            -
            			fraction = total ? point.y / total : 0;
         | 
| 15734 16094 | 
             
            			start = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;
         | 
| 15735 16095 | 
             
            			if (!ignoreHiddenPoint || point.visible) {
         | 
| 15736 | 
            -
            				cumulative +=  | 
| 16096 | 
            +
            				cumulative += point.percentage / 100;
         | 
| 15737 16097 | 
             
            			}
         | 
| 15738 16098 | 
             
            			end = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;
         | 
| 15739 16099 |  | 
| @@ -15783,10 +16143,6 @@ var PieSeries = { | |
| 15783 16143 | 
             
            					point.half ? 'right' : 'left', // alignment
         | 
| 15784 16144 | 
             
            				angle // center angle
         | 
| 15785 16145 | 
             
            			];
         | 
| 15786 | 
            -
            			
         | 
| 15787 | 
            -
            			// API properties
         | 
| 15788 | 
            -
            			point.percentage = fraction * 100;
         | 
| 15789 | 
            -
            			point.total = total;
         | 
| 15790 16146 |  | 
| 15791 16147 | 
             
            		}
         | 
| 15792 16148 |  | 
| @@ -15909,7 +16265,7 @@ var PieSeries = { | |
| 15909 16265 | 
             
            			};
         | 
| 15910 16266 |  | 
| 15911 16267 | 
             
            		// get out if not enabled
         | 
| 15912 | 
            -
            		if (!options.enabled && !series._hasPointLabels) {
         | 
| 16268 | 
            +
            		if (!series.visible || (!options.enabled && !series._hasPointLabels)) {
         | 
| 15913 16269 | 
             
            			return;
         | 
| 15914 16270 | 
             
            		}
         | 
| 15915 16271 |  |