From 554de444b87aab5f93cb1593a8095612cf9479a7 Mon Sep 17 00:00:00 2001
From: yujian <yujian@163.com>
Date: 星期二, 09 六月 2020 17:34:30 +0800
Subject: [PATCH] 订单

---
 fanli/src/main/webapp/admin/new/js/third-party/highcharts/highcharts-more.src.js | 4860 ++++++++++++++++++++++++++++++------------------------------
 1 files changed, 2,430 insertions(+), 2,430 deletions(-)

diff --git a/fanli/src/main/webapp/admin/new/js/third-party/highcharts/highcharts-more.src.js b/fanli/src/main/webapp/admin/new/js/third-party/highcharts/highcharts-more.src.js
index 39d4941..c8c5160 100644
--- a/fanli/src/main/webapp/admin/new/js/third-party/highcharts/highcharts-more.src.js
+++ b/fanli/src/main/webapp/admin/new/js/third-party/highcharts/highcharts-more.src.js
@@ -1,2430 +1,2430 @@
-// ==ClosureCompiler==
-// @compilation_level SIMPLE_OPTIMIZATIONS
-
-/**
- * @license Highcharts JS v3.0.6 (2013-10-04)
- *
- * (c) 2009-2013 Torstein H酶nsi
- *
- * License: www.highcharts.com/license
- */
-
-// JSLint options:
-/*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
-
-(function (Highcharts, UNDEFINED) {
-var arrayMin = Highcharts.arrayMin,
-	arrayMax = Highcharts.arrayMax,
-	each = Highcharts.each,
-	extend = Highcharts.extend,
-	merge = Highcharts.merge,
-	map = Highcharts.map,
-	pick = Highcharts.pick,
-	pInt = Highcharts.pInt,
-	defaultPlotOptions = Highcharts.getOptions().plotOptions,
-	seriesTypes = Highcharts.seriesTypes,
-	extendClass = Highcharts.extendClass,
-	splat = Highcharts.splat,
-	wrap = Highcharts.wrap,
-	Axis = Highcharts.Axis,
-	Tick = Highcharts.Tick,
-	Series = Highcharts.Series,
-	colProto = seriesTypes.column.prototype,
-	math = Math,
-	mathRound = math.round,
-	mathFloor = math.floor,
-	mathMax = math.max,
-	noop = function () {};/**
- * The Pane object allows options that are common to a set of X and Y axes.
- * 
- * In the future, this can be extended to basic Highcharts and Highstock.
- */
-function Pane(options, chart, firstAxis) {
-	this.init.call(this, options, chart, firstAxis);
-}
-
-// Extend the Pane prototype
-extend(Pane.prototype, {
-	
-	/**
-	 * Initiate the Pane object
-	 */
-	init: function (options, chart, firstAxis) {
-		var pane = this,
-			backgroundOption,
-			defaultOptions = pane.defaultOptions;
-		
-		pane.chart = chart;
-		
-		// Set options
-		if (chart.angular) { // gauges
-			defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions
-		}
-		pane.options = options = merge(defaultOptions, options);
-		
-		backgroundOption = options.background;
-		
-		// To avoid having weighty logic to place, update and remove the backgrounds,
-		// push them to the first axis' plot bands and borrow the existing logic there.
-		if (backgroundOption) {
-			each([].concat(splat(backgroundOption)).reverse(), function (config) {
-				var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)
-				config = merge(pane.defaultBackgroundOptions, config);
-				if (backgroundColor) {
-					config.backgroundColor = backgroundColor;
-				}
-				config.color = config.backgroundColor; // due to naming in plotBands
-				firstAxis.options.plotBands.unshift(config);
-			});
-		}
-	},
-	
-	/**
-	 * The default options object
-	 */
-	defaultOptions: {
-		// background: {conditional},
-		center: ['50%', '50%'],
-		size: '85%',
-		startAngle: 0
-		//endAngle: startAngle + 360
-	},	
-	
-	/**
-	 * The default background options
-	 */
-	defaultBackgroundOptions: {
-		shape: 'circle',
-		borderWidth: 1,
-		borderColor: 'silver',
-		backgroundColor: {
-			linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
-			stops: [
-				[0, '#FFF'],
-				[1, '#DDD']
-			]
-		},
-		from: Number.MIN_VALUE, // corrected to axis min
-		innerRadius: 0,
-		to: Number.MAX_VALUE, // corrected to axis max
-		outerRadius: '105%'
-	}
-	
-});
-var axisProto = Axis.prototype,
-	tickProto = Tick.prototype;
-	
-/**
- * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
- */
-var hiddenAxisMixin = {
-	getOffset: noop,
-	redraw: function () {
-		this.isDirty = false; // prevent setting Y axis dirty
-	},
-	render: function () {
-		this.isDirty = false; // prevent setting Y axis dirty
-	},
-	setScale: noop,
-	setCategories: noop,
-	setTitle: noop
-};
-
-/**
- * Augmented methods for the value axis
- */
-/*jslint unparam: true*/
-var radialAxisMixin = {
-	isRadial: true,
-	
-	/**
-	 * The default options extend defaultYAxisOptions
-	 */
-	defaultRadialGaugeOptions: {
-		labels: {
-			align: 'center',
-			x: 0,
-			y: null // auto
-		},
-		minorGridLineWidth: 0,
-		minorTickInterval: 'auto',
-		minorTickLength: 10,
-		minorTickPosition: 'inside',
-		minorTickWidth: 1,
-		plotBands: [],
-		tickLength: 10,
-		tickPosition: 'inside',
-		tickWidth: 2,
-		title: {
-			rotation: 0
-		},
-		zIndex: 2 // behind dials, points in the series group
-	},
-	
-	// Circular axis around the perimeter of a polar chart
-	defaultRadialXOptions: {
-		gridLineWidth: 1, // spokes
-		labels: {
-			align: null, // auto
-			distance: 15,
-			x: 0,
-			y: null // auto
-		},
-		maxPadding: 0,
-		minPadding: 0,
-		plotBands: [],
-		showLastLabel: false, 
-		tickLength: 0
-	},
-	
-	// Radial axis, like a spoke in a polar chart
-	defaultRadialYOptions: {
-		gridLineInterpolation: 'circle',
-		labels: {
-			align: 'right',
-			x: -3,
-			y: -2
-		},
-		plotBands: [],
-		showLastLabel: false,
-		title: {
-			x: 4,
-			text: null,
-			rotation: 90
-		}
-	},
-	
-	/**
-	 * Merge and set options
-	 */
-	setOptions: function (userOptions) {
-		
-		this.options = merge(
-			this.defaultOptions,
-			this.defaultRadialOptions,
-			userOptions
-		);
-		
-	},
-	
-	/**
-	 * Wrap the getOffset method to return zero offset for title or labels in a radial 
-	 * axis
-	 */
-	getOffset: function () {
-		// Call the Axis prototype method (the method we're in now is on the instance)
-		axisProto.getOffset.call(this);
-		
-		// Title or label offsets are not counted
-		this.chart.axisOffset[this.side] = 0;
-	},
-
-
-	/**
-	 * Get the path for the axis line. This method is also referenced in the getPlotLinePath
-	 * method.
-	 */
-	getLinePath: function (lineWidth, radius) {
-		var center = this.center;
-		radius = pick(radius, center[2] / 2 - this.offset);
-		
-		return this.chart.renderer.symbols.arc(
-			this.left + center[0],
-			this.top + center[1],
-			radius,
-			radius, 
-			{
-				start: this.startAngleRad,
-				end: this.endAngleRad,
-				open: true,
-				innerR: 0
-			}
-		);
-	},
-
-	/**
-	 * Override setAxisTranslation by setting the translation to the difference
-	 * in rotation. This allows the translate method to return angle for 
-	 * any given value.
-	 */
-	setAxisTranslation: function () {
-		
-		// Call uber method		
-		axisProto.setAxisTranslation.call(this);
-			
-		// Set transA and minPixelPadding
-		if (this.center) { // it's not defined the first time
-			if (this.isCircular) {
-				
-				this.transA = (this.endAngleRad - this.startAngleRad) / 
-					((this.max - this.min) || 1);
-					
-				
-			} else { 
-				this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
-			}
-			
-			if (this.isXAxis) {
-				this.minPixelPadding = this.transA * this.minPointOffset +
-					(this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
-			}
-		}
-	},
-	
-	/**
-	 * In case of auto connect, add one closestPointRange to the max value right before
-	 * tickPositions are computed, so that ticks will extend passed the real max.
-	 */
-	beforeSetTickPositions: function () {
-		if (this.autoConnect) {
-			this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260
-		}
-	},
-	
-	/**
-	 * Override the setAxisSize method to use the arc's circumference as length. This
-	 * allows tickPixelInterval to apply to pixel lengths along the perimeter
-	 */
-	setAxisSize: function () {
-		
-		axisProto.setAxisSize.call(this);
-
-		if (this.isRadial) {
-
-			// Set the center array
-			this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);
-			
-			this.len = this.width = this.height = this.isCircular ?
-				this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
-				this.center[2] / 2;
-		}
-	},
-	
-	/**
-	 * Returns the x, y coordinate of a point given by a value and a pixel distance
-	 * from center
-	 */
-	getPosition: function (value, length) {
-		if (!this.isCircular) {
-			length = this.translate(value);
-			value = this.min;	
-		}
-		
-		return this.postTranslate(
-			this.translate(value),
-			pick(length, this.center[2] / 2) - this.offset
-		);		
-	},
-	
-	/**
-	 * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates. 
-	 */
-	postTranslate: function (angle, radius) {
-		
-		var chart = this.chart,
-			center = this.center;
-			
-		angle = this.startAngleRad + angle;
-		
-		return {
-			x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
-			y: chart.plotTop + center[1] + Math.sin(angle) * radius
-		}; 
-		
-	},
-	
-	/**
-	 * Find the path for plot bands along the radial axis
-	 */
-	getPlotBandPath: function (from, to, options) {
-		var center = this.center,
-			startAngleRad = this.startAngleRad,
-			fullRadius = center[2] / 2,
-			radii = [
-				pick(options.outerRadius, '100%'),
-				options.innerRadius,
-				pick(options.thickness, 10)
-			],
-			percentRegex = /%$/,
-			start,
-			end,
-			open,
-			isCircular = this.isCircular, // X axis in a polar chart
-			ret;
-			
-		// Polygonal plot bands
-		if (this.options.gridLineInterpolation === 'polygon') {
-			ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
-		
-		// Circular grid bands
-		} else {
-			
-			// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
-			if (!isCircular) {
-				radii[0] = this.translate(from);
-				radii[1] = this.translate(to);
-			}
-			
-			// Convert percentages to pixel values
-			radii = map(radii, function (radius) {
-				if (percentRegex.test(radius)) {
-					radius = (pInt(radius, 10) * fullRadius) / 100;
-				}
-				return radius;
-			});
-			
-			// Handle full circle
-			if (options.shape === 'circle' || !isCircular) {
-				start = -Math.PI / 2;
-				end = Math.PI * 1.5;
-				open = true;
-			} else {
-				start = startAngleRad + this.translate(from);
-				end = startAngleRad + this.translate(to);
-			}
-		
-		
-			ret = this.chart.renderer.symbols.arc(
-				this.left + center[0],
-				this.top + center[1],
-				radii[0],
-				radii[0],
-				{
-					start: start,
-					end: end,
-					innerR: pick(radii[1], radii[0] - radii[2]),
-					open: open
-				}
-			);
-		}
-		 
-		return ret;
-	},
-	
-	/**
-	 * Find the path for plot lines perpendicular to the radial axis.
-	 */
-	getPlotLinePath: function (value, reverse) {
-		var axis = this,
-			center = axis.center,
-			chart = axis.chart,
-			end = axis.getPosition(value),
-			xAxis,
-			xy,
-			tickPositions,
-			ret;
-		
-		// Spokes
-		if (axis.isCircular) {
-			ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
-		
-		// Concentric circles			
-		} else if (axis.options.gridLineInterpolation === 'circle') {
-			value = axis.translate(value);
-			if (value) { // a value of 0 is in the center
-				ret = axis.getLinePath(0, value);
-			}
-		// Concentric polygons 
-		} else {
-			xAxis = chart.xAxis[0];
-			ret = [];
-			value = axis.translate(value);
-			tickPositions = xAxis.tickPositions;
-			if (xAxis.autoConnect) {
-				tickPositions = tickPositions.concat([tickPositions[0]]);
-			}
-			// Reverse the positions for concatenation of polygonal plot bands
-			if (reverse) {
-				tickPositions = [].concat(tickPositions).reverse();
-			}
-				
-			each(tickPositions, function (pos, i) {
-				xy = xAxis.getPosition(pos, value);
-				ret.push(i ? 'L' : 'M', xy.x, xy.y);
-			});
-			
-		}
-		return ret;
-	},
-	
-	/**
-	 * Find the position for the axis title, by default inside the gauge
-	 */
-	getTitlePosition: function () {
-		var center = this.center,
-			chart = this.chart,
-			titleOptions = this.options.title;
-		
-		return { 
-			x: chart.plotLeft + center[0] + (titleOptions.x || 0), 
-			y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] * 
-				center[2]) + (titleOptions.y || 0)  
-		};
-	}
-	
-};
-/*jslint unparam: false*/
-
-/**
- * Override axisProto.init to mix in special axis instance functions and function overrides
- */
-wrap(axisProto, 'init', function (proceed, chart, userOptions) {
-	var axis = this,
-		angular = chart.angular,
-		polar = chart.polar,
-		isX = userOptions.isX,
-		isHidden = angular && isX,
-		isCircular,
-		startAngleRad,
-		endAngleRad,
-		options,
-		chartOptions = chart.options,
-		paneIndex = userOptions.pane || 0,
-		pane,
-		paneOptions;
-		
-	// Before prototype.init
-	if (angular) {
-		extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
-		isCircular =  !isX;
-		if (isCircular) {
-			this.defaultRadialOptions = this.defaultRadialGaugeOptions;
-		}
-		
-	} else if (polar) {
-		//extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);
-		extend(this, radialAxisMixin);
-		isCircular = isX;
-		this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
-		
-	}
-	
-	// Run prototype.init
-	proceed.call(this, chart, userOptions);
-	
-	if (!isHidden && (angular || polar)) {
-		options = this.options;
-		
-		// Create the pane and set the pane options.
-		if (!chart.panes) {
-			chart.panes = [];
-		}
-		this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
-			splat(chartOptions.pane)[paneIndex],
-			chart,
-			axis
-		);
-		paneOptions = pane.options;
-		
-			
-		// Disable certain features on angular and polar axes
-		chart.inverted = false;
-		chartOptions.chart.zoomType = null;
-		
-		// Start and end angle options are
-		// given in degrees relative to top, while internal computations are
-		// in radians relative to right (like SVG).
-		this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
-		this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360)  - 90) * Math.PI / 180;
-		this.offset = options.offset || 0;
-		
-		this.isCircular = isCircular;
-		
-		// Automatically connect grid lines?
-		if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {
-			this.autoConnect = true;
-		}
-	}
-	
-});
-
-/**
- * Add special cases within the Tick class' methods for radial axes.
- */	
-wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
-	var axis = this.axis;
-	
-	return axis.getPosition ? 
-		axis.getPosition(pos) :
-		proceed.call(this, horiz, pos, tickmarkOffset, old);	
-});
-
-/**
- * Wrap the getLabelPosition function to find the center position of the label
- * based on the distance option
- */	
-wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
-	var axis = this.axis,
-		optionsY = labelOptions.y,
-		ret,
-		align = labelOptions.align,
-		angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
-	
-	if (axis.isRadial) {
-		ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
-		
-		// Automatically rotated
-		if (labelOptions.rotation === 'auto') {
-			label.attr({ 
-				rotation: angle
-			});
-		
-		// Vertically centered
-		} else if (optionsY === null) {
-			optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
-		
-		}
-		
-		// Automatic alignment
-		if (align === null) {
-			if (axis.isCircular) {
-				if (angle > 20 && angle < 160) {
-					align = 'left'; // right hemisphere
-				} else if (angle > 200 && angle < 340) {
-					align = 'right'; // left hemisphere
-				} else {
-					align = 'center'; // top or bottom
-				}
-			} else {
-				align = 'center';
-			}
-			label.attr({
-				align: align
-			});
-		}
-		
-		ret.x += labelOptions.x;
-		ret.y += optionsY;
-		
-	} else {
-		ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
-	}
-	return ret;
-});
-
-/**
- * Wrap the getMarkPath function to return the path of the radial marker
- */
-wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
-	var axis = this.axis,
-		endPoint,
-		ret;
-		
-	if (axis.isRadial) {
-		endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
-		ret = [
-			'M',
-			x,
-			y,
-			'L',
-			endPoint.x,
-			endPoint.y
-		];
-	} else {
-		ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
-	}
-	return ret;
-});/* 
- * The AreaRangeSeries class
- * 
- */
-
-/**
- * Extend the default options with map options
- */
-defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
-	lineWidth: 1,
-	marker: null,
-	threshold: null,
-	tooltip: {
-		pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>' 
-	},
-	trackByArea: true,
-	dataLabels: {
-		verticalAlign: null,
-		xLow: 0,
-		xHigh: 0,
-		yLow: 0,
-		yHigh: 0	
-	}
-});
-
-/**
- * Add the series type
- */
-seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {
-	type: 'arearange',
-	pointArrayMap: ['low', 'high'],
-	toYData: function (point) {
-		return [point.low, point.high];
-	},
-	pointValKey: 'low',
-	
-	/**
-	 * Extend getSegments to force null points if the higher value is null. #1703.
-	 */
-	getSegments: function () {
-		var series = this;
-
-		each(series.points, function (point) {
-			if (!series.options.connectNulls && (point.low === null || point.high === null)) {
-				point.y = null;
-			} else if (point.low === null && point.high !== null) {
-				point.y = point.high;
-			}
-		});
-		Series.prototype.getSegments.call(this);
-	},
-	
-	/**
-	 * Translate data points from raw values x and y to plotX and plotY
-	 */
-	translate: function () {
-		var series = this,
-			yAxis = series.yAxis;
-
-		seriesTypes.area.prototype.translate.apply(series);
-
-		// Set plotLow and plotHigh
-		each(series.points, function (point) {
-
-			var low = point.low,
-				high = point.high,
-				plotY = point.plotY;
-
-			if (high === null && low === null) {
-				point.y = null;
-			} else if (low === null) {
-				point.plotLow = point.plotY = null;
-				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
-			} else if (high === null) {
-				point.plotLow = plotY;
-				point.plotHigh = null;
-			} else {
-				point.plotLow = plotY;
-				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
-			}
-		});
-	},
-	
-	/**
-	 * Extend the line series' getSegmentPath method by applying the segment
-	 * path to both lower and higher values of the range
-	 */
-	getSegmentPath: function (segment) {
-		
-		var lowSegment,
-			highSegment = [],
-			i = segment.length,
-			baseGetSegmentPath = Series.prototype.getSegmentPath,
-			point,
-			linePath,
-			lowerPath,
-			options = this.options,
-			step = options.step,
-			higherPath;
-			
-		// Remove nulls from low segment
-		lowSegment = HighchartsAdapter.grep(segment, function (point) {
-			return point.plotLow !== null;
-		});
-		
-		// Make a segment with plotX and plotY for the top values
-		while (i--) {
-			point = segment[i];
-			if (point.plotHigh !== null) {
-				highSegment.push({
-					plotX: point.plotX,
-					plotY: point.plotHigh
-				});
-			}
-		}
-		
-		// Get the paths
-		lowerPath = baseGetSegmentPath.call(this, lowSegment);
-		if (step) {
-			if (step === true) {
-				step = 'left';
-			}
-			options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath
-		}
-		higherPath = baseGetSegmentPath.call(this, highSegment);
-		options.step = step;
-		
-		// Create a line on both top and bottom of the range
-		linePath = [].concat(lowerPath, higherPath);
-		
-		// For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
-		higherPath[0] = 'L'; // this probably doesn't work for spline			
-		this.areaPath = this.areaPath.concat(lowerPath, higherPath);
-		
-		return linePath;
-	},
-	
-	/**
-	 * Extend the basic drawDataLabels method by running it for both lower and higher
-	 * values.
-	 */
-	drawDataLabels: function () {
-		
-		var data = this.data,
-			length = data.length,
-			i,
-			originalDataLabels = [],
-			seriesProto = Series.prototype,
-			dataLabelOptions = this.options.dataLabels,
-			point,
-			inverted = this.chart.inverted;
-			
-		if (dataLabelOptions.enabled || this._hasPointLabels) {
-			
-			// Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
-			i = length;
-			while (i--) {
-				point = data[i];
-				
-				// Set preliminary values
-				point.y = point.high;
-				point.plotY = point.plotHigh;
-				
-				// Store original data labels and set preliminary label objects to be picked up 
-				// in the uber method
-				originalDataLabels[i] = point.dataLabel;
-				point.dataLabel = point.dataLabelUpper;
-				
-				// Set the default offset
-				point.below = false;
-				if (inverted) {
-					dataLabelOptions.align = 'left';
-					dataLabelOptions.x = dataLabelOptions.xHigh;								
-				} else {
-					dataLabelOptions.y = dataLabelOptions.yHigh;
-				}
-			}
-			seriesProto.drawDataLabels.apply(this, arguments); // #1209
-			
-			// Step 2: reorganize and handle data labels for the lower values
-			i = length;
-			while (i--) {
-				point = data[i];
-				
-				// Move the generated labels from step 1, and reassign the original data labels
-				point.dataLabelUpper = point.dataLabel;
-				point.dataLabel = originalDataLabels[i];
-				
-				// Reset values
-				point.y = point.low;
-				point.plotY = point.plotLow;
-				
-				// Set the default offset
-				point.below = true;
-				if (inverted) {
-					dataLabelOptions.align = 'right';
-					dataLabelOptions.x = dataLabelOptions.xLow;
-				} else {
-					dataLabelOptions.y = dataLabelOptions.yLow;
-				}
-			}
-			seriesProto.drawDataLabels.apply(this, arguments);
-		}
-	
-	},
-	
-	alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
-	
-	getSymbol: seriesTypes.column.prototype.getSymbol,
-	
-	drawPoints: noop
-});/**
- * The AreaSplineRangeSeries class
- */
-
-defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);
-
-/**
- * AreaSplineRangeSeries object
- */
-seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
-	type: 'areasplinerange',
-	getPointSpline: seriesTypes.spline.prototype.getPointSpline
-});/**
- * The ColumnRangeSeries class
- */
-defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
-	lineWidth: 1,
-	pointRange: null
-});
-
-/**
- * ColumnRangeSeries object
- */
-seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
-	type: 'columnrange',
-	/**
-	 * Translate data points from raw values x and y to plotX and plotY
-	 */
-	translate: function () {
-		var series = this,
-			yAxis = series.yAxis,
-			plotHigh;
-
-		colProto.translate.apply(series);
-
-		// Set plotLow and plotHigh
-		each(series.points, function (point) {
-			var shapeArgs = point.shapeArgs,
-				minPointLength = series.options.minPointLength,
-				heightDifference,
-				height,
-				y;
-
-			point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
-			point.plotLow = point.plotY;
-
-			// adjust shape
-			y = plotHigh;
-			height = point.plotY - plotHigh;
-
-			if (height < minPointLength) {
-				heightDifference = (minPointLength - height);
-				height += heightDifference;
-				y -= heightDifference / 2;
-			}
-			shapeArgs.height = height;
-			shapeArgs.y = y;
-		});
-	},
-	trackerGroups: ['group', 'dataLabels'],
-	drawGraph: noop,
-	pointAttrToOptions: colProto.pointAttrToOptions,
-	drawPoints: colProto.drawPoints,
-	drawTracker: colProto.drawTracker,
-	animate: colProto.animate,
-	getColumnMetrics: colProto.getColumnMetrics
-});
-/* 
- * The GaugeSeries class
- */
-
-
-
-/**
- * Extend the default options
- */
-defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
-	dataLabels: {
-		enabled: true,
-		y: 15,
-		borderWidth: 1,
-		borderColor: 'silver',
-		borderRadius: 3,
-		style: {
-			fontWeight: 'bold'
-		},
-		verticalAlign: 'top',
-		zIndex: 2
-	},
-	dial: {
-		// radius: '80%',
-		// backgroundColor: 'black',
-		// borderColor: 'silver',
-		// borderWidth: 0,
-		// baseWidth: 3,
-		// topWidth: 1,
-		// baseLength: '70%' // of radius
-		// rearLength: '10%'
-	},
-	pivot: {
-		//radius: 5,
-		//borderWidth: 0
-		//borderColor: 'silver',
-		//backgroundColor: 'black'
-	},
-	tooltip: {
-		headerFormat: ''
-	},
-	showInLegend: false
-});
-
-/**
- * Extend the point object
- */
-var GaugePoint = Highcharts.extendClass(Highcharts.Point, {
-	/**
-	 * Don't do any hover colors or anything
-	 */
-	setState: function (state) {
-		this.state = state;
-	}
-});
-
-
-/**
- * Add the series type
- */
-var GaugeSeries = {
-	type: 'gauge',
-	pointClass: GaugePoint,
-	
-	// chart.angular will be set to true when a gauge series is present, and this will
-	// be used on the axes
-	angular: true, 
-	drawGraph: noop,
-	fixedBox: true,
-	trackerGroups: ['group', 'dataLabels'],
-	
-	/**
-	 * Calculate paths etc
-	 */
-	translate: function () {
-		
-		var series = this,
-			yAxis = series.yAxis,
-			options = series.options,
-			center = yAxis.center;
-			
-		series.generatePoints();
-		
-		each(series.points, function (point) {
-			
-			var dialOptions = merge(options.dial, point.dial),
-				radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
-				baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
-				rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
-				baseWidth = dialOptions.baseWidth || 3,
-				topWidth = dialOptions.topWidth || 1,
-				rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
-
-			// Handle the wrap option
-			if (options.wrap === false) {
-				rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
-			}
-			rotation = rotation * 180 / Math.PI;
-				
-			point.shapeType = 'path';
-			point.shapeArgs = {
-				d: dialOptions.path || [
-					'M', 
-					-rearLength, -baseWidth / 2, 
-					'L', 
-					baseLength, -baseWidth / 2,
-					radius, -topWidth / 2,
-					radius, topWidth / 2,
-					baseLength, baseWidth / 2,
-					-rearLength, baseWidth / 2,
-					'z'
-				],
-				translateX: center[0],
-				translateY: center[1],
-				rotation: rotation
-			};
-			
-			// Positions for data label
-			point.plotX = center[0];
-			point.plotY = center[1];
-		});
-	},
-	
-	/**
-	 * Draw the points where each point is one needle
-	 */
-	drawPoints: function () {
-		
-		var series = this,
-			center = series.yAxis.center,
-			pivot = series.pivot,
-			options = series.options,
-			pivotOptions = options.pivot,
-			renderer = series.chart.renderer;
-		
-		each(series.points, function (point) {
-			
-			var graphic = point.graphic,
-				shapeArgs = point.shapeArgs,
-				d = shapeArgs.d,
-				dialOptions = merge(options.dial, point.dial); // #1233
-			
-			if (graphic) {
-				graphic.animate(shapeArgs);
-				shapeArgs.d = d; // animate alters it
-			} else {
-				point.graphic = renderer[point.shapeType](shapeArgs)
-					.attr({
-						stroke: dialOptions.borderColor || 'none',
-						'stroke-width': dialOptions.borderWidth || 0,
-						fill: dialOptions.backgroundColor || 'black',
-						rotation: shapeArgs.rotation // required by VML when animation is false
-					})
-					.add(series.group);
-			}
-		});
-		
-		// Add or move the pivot
-		if (pivot) {
-			pivot.animate({ // #1235
-				translateX: center[0],
-				translateY: center[1]
-			});
-		} else {
-			series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
-				.attr({
-					'stroke-width': pivotOptions.borderWidth || 0,
-					stroke: pivotOptions.borderColor || 'silver',
-					fill: pivotOptions.backgroundColor || 'black'
-				})
-				.translate(center[0], center[1])
-				.add(series.group);
-		}
-	},
-	
-	/**
-	 * Animate the arrow up from startAngle
-	 */
-	animate: function (init) {
-		var series = this;
-
-		if (!init) {
-			each(series.points, function (point) {
-				var graphic = point.graphic;
-
-				if (graphic) {
-					// start value
-					graphic.attr({
-						rotation: series.yAxis.startAngleRad * 180 / Math.PI
-					});
-
-					// animate
-					graphic.animate({
-						rotation: point.shapeArgs.rotation
-					}, series.options.animation);
-				}
-			});
-
-			// delete this function to allow it only once
-			series.animate = null;
-		}
-	},
-	
-	render: function () {
-		this.group = this.plotGroup(
-			'group', 
-			'series', 
-			this.visible ? 'visible' : 'hidden', 
-			this.options.zIndex, 
-			this.chart.seriesGroup
-		);
-		seriesTypes.pie.prototype.render.call(this);
-		this.group.clip(this.chart.clipRect);
-	},
-	
-	setData: seriesTypes.pie.prototype.setData,
-	drawTracker: seriesTypes.column.prototype.drawTracker
-};
-seriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* ****************************************************************************
- * Start Box plot series code											      *
- *****************************************************************************/
-
-// Set default options
-defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
-	fillColor: '#FFFFFF',
-	lineWidth: 1,
-	//medianColor: null,
-	medianWidth: 2,
-	states: {
-		hover: {
-			brightness: -0.3
-		}
-	},
-	//stemColor: null,
-	//stemDashStyle: 'solid'
-	//stemWidth: null,
-	threshold: null,
-	tooltip: {
-		pointFormat: '<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>' +
-			'Maximum: {point.high}<br/>' +
-			'Upper quartile: {point.q3}<br/>' +
-			'Median: {point.median}<br/>' +
-			'Lower quartile: {point.q1}<br/>' +
-			'Minimum: {point.low}<br/>'
-			
-	},
-	//whiskerColor: null,
-	whiskerLength: '50%',
-	whiskerWidth: 2
-});
-
-// Create the series object
-seriesTypes.boxplot = extendClass(seriesTypes.column, {
-	type: 'boxplot',
-	pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
-	toYData: function (point) { // return a plain array for speedy calculation
-		return [point.low, point.q1, point.median, point.q3, point.high];
-	},
-	pointValKey: 'high', // defines the top of the tracker
-	
-	/**
-	 * One-to-one mapping from options to SVG attributes
-	 */
-	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
-		fill: 'fillColor',
-		stroke: 'color',
-		'stroke-width': 'lineWidth'
-	},
-	
-	/**
-	 * Disable data labels for box plot
-	 */
-	drawDataLabels: noop,
-
-	/**
-	 * Translate data points from raw values x and y to plotX and plotY
-	 */
-	translate: function () {
-		var series = this,
-			yAxis = series.yAxis,
-			pointArrayMap = series.pointArrayMap;
-
-		seriesTypes.column.prototype.translate.apply(series);
-
-		// do the translation on each point dimension
-		each(series.points, function (point) {
-			each(pointArrayMap, function (key) {
-				if (point[key] !== null) {
-					point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);
-				}
-			});
-		});
-	},
-
-	/**
-	 * Draw the data points
-	 */
-	drawPoints: function () {
-		var series = this,  //state = series.state,
-			points = series.points,
-			options = series.options,
-			chart = series.chart,
-			renderer = chart.renderer,
-			pointAttr,
-			q1Plot,
-			q3Plot,
-			highPlot,
-			lowPlot,
-			medianPlot,
-			crispCorr,
-			crispX,
-			graphic,
-			stemPath,
-			stemAttr,
-			boxPath,
-			whiskersPath,
-			whiskersAttr,
-			medianPath,
-			medianAttr,
-			width,
-			left,
-			right,
-			halfWidth,
-			shapeArgs,
-			color,
-			doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
-			whiskerLength = parseInt(series.options.whiskerLength, 10) / 100;
-
-
-		each(points, function (point) {
-
-			graphic = point.graphic;
-			shapeArgs = point.shapeArgs; // the box
-			stemAttr = {};
-			whiskersAttr = {};
-			medianAttr = {};
-			color = point.color || series.color;
-			
-			if (point.plotY !== UNDEFINED) {
-
-				pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
-
-				// crisp vector coordinates
-				width = shapeArgs.width;
-				left = mathFloor(shapeArgs.x);
-				right = left + width;
-				halfWidth = mathRound(width / 2);
-				//crispX = mathRound(left + halfWidth) + crispCorr;
-				q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;
-				q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;
-				highPlot = mathFloor(point.highPlot);// + crispCorr;
-				lowPlot = mathFloor(point.lowPlot);// + crispCorr;
-				
-				// Stem attributes
-				stemAttr.stroke = point.stemColor || options.stemColor || color;
-				stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
-				stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
-				
-				// Whiskers attributes
-				whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
-				whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
-				
-				// Median attributes
-				medianAttr.stroke = point.medianColor || options.medianColor || color;
-				medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
-				
-				
-				// The stem
-				crispCorr = (stemAttr['stroke-width'] % 2) / 2;
-				crispX = left + halfWidth + crispCorr;				
-				stemPath = [
-					// stem up
-					'M',
-					crispX, q3Plot,
-					'L',
-					crispX, highPlot,
-					
-					// stem down
-					'M',
-					crispX, q1Plot,
-					'L',
-					crispX, lowPlot,
-					'z'
-				];
-				
-				// The box
-				if (doQuartiles) {
-					crispCorr = (pointAttr['stroke-width'] % 2) / 2;
-					crispX = mathFloor(crispX) + crispCorr;
-					q1Plot = mathFloor(q1Plot) + crispCorr;
-					q3Plot = mathFloor(q3Plot) + crispCorr;
-					left += crispCorr;
-					right += crispCorr;
-					boxPath = [
-						'M',
-						left, q3Plot,
-						'L',
-						left, q1Plot,
-						'L',
-						right, q1Plot,
-						'L',
-						right, q3Plot,
-						'L',
-						left, q3Plot,
-						'z'
-					];
-				}
-				
-				// The whiskers
-				if (whiskerLength) {
-					crispCorr = (whiskersAttr['stroke-width'] % 2) / 2;
-					highPlot = highPlot + crispCorr;
-					lowPlot = lowPlot + crispCorr;
-					whiskersPath = [
-						// High whisker
-						'M',
-						crispX - halfWidth * whiskerLength, 
-						highPlot,
-						'L',
-						crispX + halfWidth * whiskerLength, 
-						highPlot,
-						
-						// Low whisker
-						'M',
-						crispX - halfWidth * whiskerLength, 
-						lowPlot,
-						'L',
-						crispX + halfWidth * whiskerLength, 
-						lowPlot
-					];
-				}
-				
-				// The median
-				crispCorr = (medianAttr['stroke-width'] % 2) / 2;				
-				medianPlot = mathRound(point.medianPlot) + crispCorr;
-				medianPath = [
-					'M',
-					left, 
-					medianPlot,
-					'L',
-					right, 
-					medianPlot,
-					'z'
-				];
-				
-				// Create or update the graphics
-				if (graphic) { // update
-					
-					point.stem.animate({ d: stemPath });
-					if (whiskerLength) {
-						point.whiskers.animate({ d: whiskersPath });
-					}
-					if (doQuartiles) {
-						point.box.animate({ d: boxPath });
-					}
-					point.medianShape.animate({ d: medianPath });
-					
-				} else { // create new
-					point.graphic = graphic = renderer.g()
-						.add(series.group);
-					
-					point.stem = renderer.path(stemPath)
-						.attr(stemAttr)
-						.add(graphic);
-						
-					if (whiskerLength) {
-						point.whiskers = renderer.path(whiskersPath) 
-							.attr(whiskersAttr)
-							.add(graphic);
-					}
-					if (doQuartiles) {
-						point.box = renderer.path(boxPath)
-							.attr(pointAttr)
-							.add(graphic);
-					}	
-					point.medianShape = renderer.path(medianPath)
-						.attr(medianAttr)
-						.add(graphic);
-				}
-			}
-		});
-
-	}
-
-
-});
-
-/* ****************************************************************************
- * End Box plot series code												*
- *****************************************************************************/
-/* ****************************************************************************
- * Start error bar series code                                                *
- *****************************************************************************/
-
-// 1 - set default options
-defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
-	color: '#000000',
-	grouping: false,
-	linkedTo: ':previous',
-	tooltip: {
-		pointFormat: defaultPlotOptions.arearange.tooltip.pointFormat
-	},
-	whiskerWidth: null
-});
-
-// 2 - Create the series object
-seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
-	type: 'errorbar',
-	pointArrayMap: ['low', 'high'], // array point configs are mapped to this
-	toYData: function (point) { // return a plain array for speedy calculation
-		return [point.low, point.high];
-	},
-	pointValKey: 'high', // defines the top of the tracker
-	doQuartiles: false,
-
-	/**
-	 * Get the width and X offset, either on top of the linked series column
-	 * or standalone
-	 */
-	getColumnMetrics: function () {
-		return (this.linkedParent && this.linkedParent.columnMetrics) || 
-			seriesTypes.column.prototype.getColumnMetrics.call(this);
-	}
-});
-
-/* ****************************************************************************
- * End error bar series code                                                  *
- *****************************************************************************/
-/* ****************************************************************************
- * Start Waterfall series code                                                *
- *****************************************************************************/
-
-// 1 - set default options
-defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {
-	lineWidth: 1,
-	lineColor: '#333',
-	dashStyle: 'dot',
-	borderColor: '#333'
-});
-
-
-// 2 - Create the series object
-seriesTypes.waterfall = extendClass(seriesTypes.column, {
-	type: 'waterfall',
-
-	upColorProp: 'fill',
-
-	pointArrayMap: ['low', 'y'],
-
-	pointValKey: 'y',
-
-	/**
-	 * Init waterfall series, force stacking
-	 */
-	init: function (chart, options) {
-		// force stacking
-		options.stacking = true;
-
-		seriesTypes.column.prototype.init.call(this, chart, options);
-	},
-
-
-	/**
-	 * Translate data points from raw values
-	 */
-	translate: function () {
-		var series = this,
-			options = series.options,
-			axis = series.yAxis,
-			len,
-			i,
-			points,
-			point,
-			shapeArgs,
-			stack,
-			y,
-			previousY,
-			stackPoint,
-			threshold = options.threshold,
-			crispCorr = (options.borderWidth % 2) / 2;
-
-		// run column series translate
-		seriesTypes.column.prototype.translate.apply(this);
-
-		previousY = threshold;
-		points = series.points;
-
-		for (i = 0, len = points.length; i < len; i++) {
-			// cache current point object
-			point = points[i];
-			shapeArgs = point.shapeArgs;
-
-			// get current stack
-			stack = series.getStack(i);
-			stackPoint = stack.points[series.index];
-
-			// override point value for sums
-			if (isNaN(point.y)) {
-				point.y = series.yData[i];
-			}
-
-			// up points
-			y = mathMax(previousY, previousY + point.y) + stackPoint[0];
-			shapeArgs.y = axis.translate(y, 0, 1);
-
-
-			// sum points
-			if (point.isSum || point.isIntermediateSum) {
-				shapeArgs.y = axis.translate(stackPoint[1], 0, 1);
-				shapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y;
-
-			// if it's not the sum point, update previous stack end position
-			} else {
-				previousY += stack.total;
-			}
-
-			// negative points
-			if (shapeArgs.height < 0) {
-				shapeArgs.y += shapeArgs.height;
-				shapeArgs.height *= -1;
-			}
-
-			point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;
-			shapeArgs.height = mathRound(shapeArgs.height);
-			point.yBottom = shapeArgs.y + shapeArgs.height;
-		}
-	},
-
-	/**
-	 * Call default processData then override yData to reflect waterfall's extremes on yAxis
-	 */
-	processData: function (force) {
-		var series = this,
-			options = series.options,
-			yData = series.yData,
-			points = series.points,
-			point,
-			dataLength = yData.length,
-			threshold = options.threshold || 0,
-			subSum,
-			sum,
-			dataMin,
-			dataMax,
-			y,
-			i;
-
-		sum = subSum = dataMin = dataMax = threshold;
-
-		for (i = 0; i < dataLength; i++) {
-			y = yData[i];
-			point = points && points[i] ? points[i] : {};
-
-			if (y === "sum" || point.isSum) {
-				yData[i] = sum;
-			} else if (y === "intermediateSum" || point.isIntermediateSum) {
-				yData[i] = subSum;
-				subSum = threshold;
-			} else {
-				sum += y;
-				subSum += y;
-			}
-			dataMin = Math.min(sum, dataMin);
-			dataMax = Math.max(sum, dataMax);
-		}
-
-		Series.prototype.processData.call(this, force);
-
-		// Record extremes
-		series.dataMin = dataMin;
-		series.dataMax = dataMax;
-	},
-
-	/**
-	 * Return y value or string if point is sum
-	 */
-	toYData: function (pt) {
-		if (pt.isSum) {
-			return "sum";
-		} else if (pt.isIntermediateSum) {
-			return "intermediateSum";
-		}
-
-		return pt.y;
-	},
-
-	/**
-	 * Postprocess mapping between options and SVG attributes
-	 */
-	getAttribs: function () {
-		seriesTypes.column.prototype.getAttribs.apply(this, arguments);
-
-		var series = this,
-			options = series.options,
-			stateOptions = options.states,
-			upColor = options.upColor || series.color,
-			hoverColor = Highcharts.Color(upColor).brighten(0.1).get(),
-			seriesDownPointAttr = merge(series.pointAttr),
-			upColorProp = series.upColorProp;
-
-		seriesDownPointAttr[''][upColorProp] = upColor;
-		seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;
-		seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;
-
-		each(series.points, function (point) {
-			if (point.y > 0 && !point.color) {
-				point.pointAttr = seriesDownPointAttr;
-				point.color = upColor;
-			}
-		});
-	},
-
-	/**
-	 * Draw columns' connector lines
-	 */
-	getGraphPath: function () {
-
-		var data = this.data,
-			length = data.length,
-			lineWidth = this.options.lineWidth + this.options.borderWidth,
-			normalizer = mathRound(lineWidth) % 2 / 2,
-			path = [],
-			M = 'M',
-			L = 'L',
-			prevArgs,
-			pointArgs,
-			i,
-			d;
-
-		for (i = 1; i < length; i++) {
-			pointArgs = data[i].shapeArgs;
-			prevArgs = data[i - 1].shapeArgs;
-
-			d = [
-				M,
-				prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
-				L,
-				pointArgs.x, prevArgs.y + normalizer
-			];
-
-			if (data[i - 1].y < 0) {
-				d[2] += prevArgs.height;
-				d[5] += prevArgs.height;
-			}
-
-			path = path.concat(d);
-		}
-
-		return path;
-	},
-
-	/**
-	 * Extremes are recorded in processData
-	 */
-	getExtremes: noop,
-
-	/**
-	 * Return stack for given index
-	 */
-	getStack: function (i) {
-		var axis = this.yAxis,
-			stacks = axis.stacks,
-			key = this.stackKey;
-
-		if (this.processedYData[i] < this.options.threshold) {
-			key = '-' + key;
-		}
-
-		return stacks[key][i];
-	},
-
-	drawGraph: Series.prototype.drawGraph
-});
-
-/* ****************************************************************************
- * End Waterfall series code                                                  *
- *****************************************************************************/
-/* ****************************************************************************
- * Start Bubble series code											          *
- *****************************************************************************/
-
-// 1 - set default options
-defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
-	dataLabels: {
-		inside: true,
-		style: {
-			color: 'white',
-			textShadow: '0px 0px 3px black'
-		},
-		verticalAlign: 'middle'
-	},
-	// displayNegative: true,
-	marker: {
-		// fillOpacity: 0.5,
-		lineColor: null, // inherit from series.color
-		lineWidth: 1
-	},
-	minSize: 8,
-	maxSize: '20%',
-	// negativeColor: null,
-	tooltip: {
-		pointFormat: '({point.x}, {point.y}), Size: {point.z}'
-	},
-	turboThreshold: 0,
-	zThreshold: 0
-});
-
-// 2 - Create the series object
-seriesTypes.bubble = extendClass(seriesTypes.scatter, {
-	type: 'bubble',
-	pointArrayMap: ['y', 'z'],
-	trackerGroups: ['group', 'dataLabelsGroup'],
-	
-	/**
-	 * Mapping between SVG attributes and the corresponding options
-	 */
-	pointAttrToOptions: { 
-		stroke: 'lineColor',
-		'stroke-width': 'lineWidth',
-		fill: 'fillColor'
-	},
-	
-	/**
-	 * Apply the fillOpacity to all fill positions
-	 */
-	applyOpacity: function (fill) {
-		var markerOptions = this.options.marker,
-			fillOpacity = pick(markerOptions.fillOpacity, 0.5);
-		
-		// When called from Legend.colorizeItem, the fill isn't predefined
-		fill = fill || markerOptions.fillColor || this.color; 
-		
-		if (fillOpacity !== 1) {
-			fill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba');
-		}
-		return fill;
-	},
-	
-	/**
-	 * Extend the convertAttribs method by applying opacity to the fill
-	 */
-	convertAttribs: function () {
-		var obj = Series.prototype.convertAttribs.apply(this, arguments);
-		
-		obj.fill = this.applyOpacity(obj.fill);
-		
-		return obj;
-	},
-
-	/**
-	 * Get the radius for each point based on the minSize, maxSize and each point's Z value. This
-	 * must be done prior to Series.translate because the axis needs to add padding in 
-	 * accordance with the point sizes.
-	 */
-	getRadii: function (zMin, zMax, minSize, maxSize) {
-		var len,
-			i,
-			pos,
-			zData = this.zData,
-			radii = [],
-			zRange;
-		
-		// Set the shape type and arguments to be picked up in drawPoints
-		for (i = 0, len = zData.length; i < len; i++) {
-			zRange = zMax - zMin;
-			pos = zRange > 0 ? // relative size, a number between 0 and 1
-				(zData[i] - zMin) / (zMax - zMin) : 
-				0.5;
-			radii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2);
-		}
-		this.radii = radii;
-	},
-	
-	/**
-	 * Perform animation on the bubbles
-	 */
-	animate: function (init) {
-		var animation = this.options.animation;
-		
-		if (!init) { // run the animation
-			each(this.points, function (point) {
-				var graphic = point.graphic,
-					shapeArgs = point.shapeArgs;
-
-				if (graphic && shapeArgs) {
-					// start values
-					graphic.attr('r', 1);
-
-					// animate
-					graphic.animate({
-						r: shapeArgs.r
-					}, animation);
-				}
-			});
-
-			// delete this function to allow it only once
-			this.animate = null;
-		}
-	},
-	
-	/**
-	 * Extend the base translate method to handle bubble size
-	 */
-	translate: function () {
-		
-		var i,
-			data = this.data,
-			point,
-			radius,
-			radii = this.radii;
-		
-		// Run the parent method
-		seriesTypes.scatter.prototype.translate.call(this);
-		
-		// Set the shape type and arguments to be picked up in drawPoints
-		i = data.length;
-		
-		while (i--) {
-			point = data[i];
-			radius = radii ? radii[i] : 0; // #1737
-
-			// Flag for negativeColor to be applied in Series.js
-			point.negative = point.z < (this.options.zThreshold || 0);
-			
-			if (radius >= this.minPxSize / 2) {
-				// Shape arguments
-				point.shapeType = 'circle';
-				point.shapeArgs = {
-					x: point.plotX,
-					y: point.plotY,
-					r: radius
-				};
-				
-				// Alignment box for the data label
-				point.dlBox = {
-					x: point.plotX - radius,
-					y: point.plotY - radius,
-					width: 2 * radius,
-					height: 2 * radius
-				};
-			} else { // below zThreshold
-				point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691
-			}
-		}
-	},
-	
-	/**
-	 * Get the series' symbol in the legend
-	 * 
-	 * @param {Object} legend The legend object
-	 * @param {Object} item The series (this) or point
-	 */
-	drawLegendSymbol: function (legend, item) {
-		var radius = pInt(legend.itemStyle.fontSize) / 2;
-		
-		item.legendSymbol = this.chart.renderer.circle(
-			radius,
-			legend.baseline - radius,
-			radius
-		).attr({
-			zIndex: 3
-		}).add(item.legendGroup);
-		item.legendSymbol.isMarker = true;	
-		
-	},
-	
-	drawPoints: seriesTypes.column.prototype.drawPoints,
-	alignDataLabel: seriesTypes.column.prototype.alignDataLabel
-});
-
-/**
- * Add logic to pad each axis with the amount of pixels
- * necessary to avoid the bubbles to overflow.
- */
-Axis.prototype.beforePadding = function () {
-	var axis = this,
-		axisLength = this.len,
-		chart = this.chart,
-		pxMin = 0, 
-		pxMax = axisLength,
-		isXAxis = this.isXAxis,
-		dataKey = isXAxis ? 'xData' : 'yData',
-		min = this.min,
-		extremes = {},
-		smallestSize = math.min(chart.plotWidth, chart.plotHeight),
-		zMin = Number.MAX_VALUE,
-		zMax = -Number.MAX_VALUE,
-		range = this.max - min,
-		transA = axisLength / range,
-		activeSeries = [];
-
-	// Handle padding on the second pass, or on redraw
-	if (this.tickPositions) {
-		each(this.series, function (series) {
-
-			var seriesOptions = series.options,
-				zData;
-
-			if (series.type === 'bubble' && series.visible) {
-
-				// Correction for #1673
-				axis.allowZoomOutside = true;
-
-				// Cache it
-				activeSeries.push(series);
-
-				if (isXAxis) { // because X axis is evaluated first
-				
-					// For each series, translate the size extremes to pixel values
-					each(['minSize', 'maxSize'], function (prop) {
-						var length = seriesOptions[prop],
-							isPercent = /%$/.test(length);
-						
-						length = pInt(length);
-						extremes[prop] = isPercent ?
-							smallestSize * length / 100 :
-							length;
-						
-					});
-					series.minPxSize = extremes.minSize;
-					
-					// Find the min and max Z
-					zData = series.zData;
-					if (zData.length) { // #1735
-						zMin = math.min(
-							zMin,
-							math.max(
-								arrayMin(zData), 
-								seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE
-							)
-						);
-						zMax = math.max(zMax, arrayMax(zData));
-					}
-				}
-			}
-		});
-
-		each(activeSeries, function (series) {
-
-			var data = series[dataKey],
-				i = data.length,
-				radius;
-
-			if (isXAxis) {
-				series.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize);
-			}
-			
-			if (range > 0) {
-				while (i--) {
-					radius = series.radii[i];
-					pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
-					pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
-				}
-			}
-		});
-		
-		if (activeSeries.length && range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) {
-			pxMax -= axisLength;
-			transA *= (axisLength + pxMin - pxMax) / axisLength;
-			this.min += pxMin / transA;
-			this.max += pxMax / transA;
-		}
-	}
-};
-
-/* ****************************************************************************
- * End Bubble series code                                                     *
- *****************************************************************************/
-/**
- * Extensions for polar charts. Additionally, much of the geometry required for polar charts is
- * gathered in RadialAxes.js.
- * 
- */
-
-var seriesProto = Series.prototype,
-	pointerProto = Highcharts.Pointer.prototype;
-
-
-
-/**
- * Translate a point's plotX and plotY from the internal angle and radius measures to 
- * true plotX, plotY coordinates
- */
-seriesProto.toXY = function (point) {
-	var xy,
-		chart = this.chart,
-		plotX = point.plotX,
-		plotY = point.plotY;
-	
-	// Save rectangular plotX, plotY for later computation
-	point.rectPlotX = plotX;
-	point.rectPlotY = plotY;
-	
-	// Record the angle in degrees for use in tooltip
-	point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
-	
-	// Find the polar plotX and plotY
-	xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
-	point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
-	point.plotY = point.polarPlotY = xy.y - chart.plotTop;
-};
-
-/** 
- * Order the tooltip points to get the mouse capture ranges correct. #1915. 
- */
-seriesProto.orderTooltipPoints = function (points) {
-	if (this.chart.polar) {
-		points.sort(function (a, b) {
-			return a.clientX - b.clientX;
-		});
-
-		// Wrap mouse tracking around to capture movement on the segment to the left
-		// of the north point (#1469, #2093).
-		if (points[0]) {
-			points[0].wrappedClientX = points[0].clientX + 360;
-			points.push(points[0]);
-		}
-	}
-};
-
-
-/**
- * Add some special init logic to areas and areasplines
- */
-function initArea(proceed, chart, options) {
-	proceed.call(this, chart, options);
-	if (this.chart.polar) {
-		
-		/**
-		 * Overridden method to close a segment path. While in a cartesian plane the area 
-		 * goes down to the threshold, in the polar chart it goes to the center.
-		 */
-		this.closeSegment = function (path) {
-			var center = this.xAxis.center;
-			path.push(
-				'L',
-				center[0],
-				center[1]
-			);			
-		};
-		
-		// Instead of complicated logic to draw an area around the inner area in a stack,
-		// just draw it behind
-		this.closedStacks = true;
-	}
-}
-wrap(seriesTypes.area.prototype, 'init', initArea);
-wrap(seriesTypes.areaspline.prototype, 'init', initArea);
-		
-
-/**
- * Overridden method for calculating a spline from one point to the next
- */
-wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) {
-	
-	var ret,
-		smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;
-		denom = smoothing + 1,
-		plotX, 
-		plotY,
-		lastPoint,
-		nextPoint,
-		lastX,
-		lastY,
-		nextX,
-		nextY,
-		leftContX,
-		leftContY,
-		rightContX,
-		rightContY,
-		distanceLeftControlPoint,
-		distanceRightControlPoint,
-		leftContAngle,
-		rightContAngle,
-		jointAngle;
-		
-		
-	if (this.chart.polar) {
-		
-		plotX = point.plotX;
-		plotY = point.plotY;
-		lastPoint = segment[i - 1];
-		nextPoint = segment[i + 1];
-			
-		// Connect ends
-		if (this.connectEnds) {
-			if (!lastPoint) {
-				lastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected
-			}
-			if (!nextPoint) {
-				nextPoint = segment[1];
-			}	
-		}
-
-		// find control points
-		if (lastPoint && nextPoint) {
-		
-			lastX = lastPoint.plotX;
-			lastY = lastPoint.plotY;
-			nextX = nextPoint.plotX;
-			nextY = nextPoint.plotY;
-			leftContX = (smoothing * plotX + lastX) / denom;
-			leftContY = (smoothing * plotY + lastY) / denom;
-			rightContX = (smoothing * plotX + nextX) / denom;
-			rightContY = (smoothing * plotY + nextY) / denom;
-			distanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2));
-			distanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2));
-			leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
-			rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
-			jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
-				
-				
-			// Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle
-			if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
-				jointAngle -= Math.PI;
-			}
-			
-			// Find the corrected control points for a spline straight through the point
-			leftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint;
-			leftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint;
-			rightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint;
-			rightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint;
-			
-			// Record for drawing in next point
-			point.rightContX = rightContX;
-			point.rightContY = rightContY;
-
-		}
-		
-		
-		// moveTo or lineTo
-		if (!i) {
-			ret = ['M', plotX, plotY];
-		} else { // curve from last point to this
-			ret = [
-				'C',
-				lastPoint.rightContX || lastPoint.plotX,
-				lastPoint.rightContY || lastPoint.plotY,
-				leftContX || plotX,
-				leftContY || plotY,
-				plotX,
-				plotY
-			];
-			lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later
-		}
-		
-		
-	} else {
-		ret = proceed.call(this, segment, point, i);
-	}
-	return ret;
-});
-
-/**
- * Extend translate. The plotX and plotY values are computed as if the polar chart were a
- * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from
- * center. 
- */
-wrap(seriesProto, 'translate', function (proceed) {
-		
-	// Run uber method
-	proceed.call(this);
-	
-	// Postprocess plot coordinates
-	if (this.chart.polar && !this.preventPostTranslate) {
-		var points = this.points,
-			i = points.length;
-		while (i--) {
-			// Translate plotX, plotY from angle and radius to true plot coordinates
-			this.toXY(points[i]);
-		}
-	}
-});
-
-/** 
- * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in 
- * line-like series.
- */
-wrap(seriesProto, 'getSegmentPath', function (proceed, segment) {
-		
-	var points = this.points;
-	
-	// Connect the path
-	if (this.chart.polar && this.options.connectEnds !== false && 
-			segment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) {
-		this.connectEnds = true; // re-used in splines
-		segment = [].concat(segment, [points[0]]);
-	}
-	
-	// Run uber method
-	return proceed.call(this, segment);
-	
-});
-
-
-function polarAnimate(proceed, init) {
-	var chart = this.chart,
-		animation = this.options.animation,
-		group = this.group,
-		markerGroup = this.markerGroup,
-		center = this.xAxis.center,
-		plotLeft = chart.plotLeft,
-		plotTop = chart.plotTop,
-		attribs;
-
-	// Specific animation for polar charts
-	if (chart.polar) {
-		
-		// Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation
-		// would be so slow it would't matter.
-		if (chart.renderer.isSVG) {
-
-			if (animation === true) {
-				animation = {};
-			}
-	
-			// Initialize the animation
-			if (init) {
-				
-				// Scale down the group and place it in the center
-				attribs = {
-					translateX: center[0] + plotLeft,
-					translateY: center[1] + plotTop,
-					scaleX: 0.001, // #1499
-					scaleY: 0.001
-				};
-					
-				group.attr(attribs);
-				if (markerGroup) {
-					markerGroup.attrSetters = group.attrSetters;
-					markerGroup.attr(attribs);
-				}
-				
-			// Run the animation
-			} else {
-				attribs = {
-					translateX: plotLeft,
-					translateY: plotTop,
-					scaleX: 1,
-					scaleY: 1
-				};
-				group.animate(attribs, animation);
-				if (markerGroup) {
-					markerGroup.animate(attribs, animation);
-				}
-				
-				// Delete this function to allow it only once
-				this.animate = null;
-			}
-		}
-	
-	// For non-polar charts, revert to the basic animation
-	} else {
-		proceed.call(this, init);
-	} 
-}
-
-// Define the animate method for both regular series and column series and their derivatives
-wrap(seriesProto, 'animate', polarAnimate);
-wrap(colProto, 'animate', polarAnimate);
-
-
-/**
- * Throw in a couple of properties to let setTooltipPoints know we're indexing the points
- * in degrees (0-360), not plot pixel width.
- */
-wrap(seriesProto, 'setTooltipPoints', function (proceed, renew) {
-		
-	if (this.chart.polar) {
-		extend(this.xAxis, {
-			tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array
-		});	
-	}
-	
-	// Run uber method
-	return proceed.call(this, renew);
-});
-
-
-/**
- * Extend the column prototype's translate method
- */
-wrap(colProto, 'translate', function (proceed) {
-		
-	var xAxis = this.xAxis,
-		len = this.yAxis.len,
-		center = xAxis.center,
-		startAngleRad = xAxis.startAngleRad,
-		renderer = this.chart.renderer,
-		start,
-		points,
-		point,
-		i;
-	
-	this.preventPostTranslate = true;
-	
-	// Run uber method
-	proceed.call(this);
-	
-	// Postprocess plot coordinates
-	if (xAxis.isRadial) {
-		points = this.points;
-		i = points.length;
-		while (i--) {
-			point = points[i];
-			start = point.barX + startAngleRad;
-			point.shapeType = 'path';
-			point.shapeArgs = {
-				d: renderer.symbols.arc(
-					center[0],
-					center[1],
-					len - point.plotY,
-					null, 
-					{
-						start: start,
-						end: start + point.pointWidth,
-						innerR: len - pick(point.yBottom, len)
-					}
-				)
-			};
-			this.toXY(point); // provide correct plotX, plotY for tooltip
-		}
-	}
-});
-
-
-/**
- * Align column data labels outside the columns. #1199.
- */
-wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) {
-	
-	if (this.chart.polar) {
-		var angle = point.rectPlotX / Math.PI * 180,
-			align,
-			verticalAlign;
-		
-		// Align nicely outside the perimeter of the columns
-		if (options.align === null) {
-			if (angle > 20 && angle < 160) {
-				align = 'left'; // right hemisphere
-			} else if (angle > 200 && angle < 340) {
-				align = 'right'; // left hemisphere
-			} else {
-				align = 'center'; // top or bottom
-			}
-			options.align = align;
-		}
-		if (options.verticalAlign === null) {
-			if (angle < 45 || angle > 315) {
-				verticalAlign = 'bottom'; // top part
-			} else if (angle > 135 && angle < 225) {
-				verticalAlign = 'top'; // bottom part
-			} else {
-				verticalAlign = 'middle'; // left or right
-			}
-			options.verticalAlign = verticalAlign;
-		}
-		
-		seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
-	} else {
-		proceed.call(this, point, dataLabel, options, alignTo, isNew);
-	}
-	
-});
-
-/**
- * Extend the mouse tracker to return the tooltip position index in terms of
- * degrees rather than pixels
- */
-wrap(pointerProto, 'getIndex', function (proceed, e) {
-	var ret,
-		chart = this.chart,
-		center,
-		x,
-		y;
-	
-	if (chart.polar) {
-		center = chart.xAxis[0].center;
-		x = e.chartX - center[0] - chart.plotLeft;
-		y = e.chartY - center[1] - chart.plotTop;
-		
-		ret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180);
-	
-	} else {
-	
-		// Run uber method
-		ret = proceed.call(this, e);
-	}
-	return ret;
-});
-
-/**
- * Extend getCoordinates to prepare for polar axis values
- */
-wrap(pointerProto, 'getCoordinates', function (proceed, e) {
-	var chart = this.chart,
-		ret = {
-			xAxis: [],
-			yAxis: []
-		};
-	
-	if (chart.polar) {	
-
-		each(chart.axes, function (axis) {
-			var isXAxis = axis.isXAxis,
-				center = axis.center,
-				x = e.chartX - center[0] - chart.plotLeft,
-				y = e.chartY - center[1] - chart.plotTop;
-			
-			ret[isXAxis ? 'xAxis' : 'yAxis'].push({
-				axis: axis,
-				value: axis.translate(
-					isXAxis ?
-						Math.PI - Math.atan2(x, y) : // angle 
-						Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center
-					true
-				)
-			});
-		});
-		
-	} else {
-		ret = proceed.call(this, e);
-	}
-	
-	return ret;
-});
-}(Highcharts));
+// ==ClosureCompiler==
+// @compilation_level SIMPLE_OPTIMIZATIONS
+
+/**
+ * @license Highcharts JS v3.0.6 (2013-10-04)
+ *
+ * (c) 2009-2013 Torstein H酶nsi
+ *
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
+
+(function (Highcharts, UNDEFINED) {
+var arrayMin = Highcharts.arrayMin,
+	arrayMax = Highcharts.arrayMax,
+	each = Highcharts.each,
+	extend = Highcharts.extend,
+	merge = Highcharts.merge,
+	map = Highcharts.map,
+	pick = Highcharts.pick,
+	pInt = Highcharts.pInt,
+	defaultPlotOptions = Highcharts.getOptions().plotOptions,
+	seriesTypes = Highcharts.seriesTypes,
+	extendClass = Highcharts.extendClass,
+	splat = Highcharts.splat,
+	wrap = Highcharts.wrap,
+	Axis = Highcharts.Axis,
+	Tick = Highcharts.Tick,
+	Series = Highcharts.Series,
+	colProto = seriesTypes.column.prototype,
+	math = Math,
+	mathRound = math.round,
+	mathFloor = math.floor,
+	mathMax = math.max,
+	noop = function () {};/**
+ * The Pane object allows options that are common to a set of X and Y axes.
+ * 
+ * In the future, this can be extended to basic Highcharts and Highstock.
+ */
+function Pane(options, chart, firstAxis) {
+	this.init.call(this, options, chart, firstAxis);
+}
+
+// Extend the Pane prototype
+extend(Pane.prototype, {
+	
+	/**
+	 * Initiate the Pane object
+	 */
+	init: function (options, chart, firstAxis) {
+		var pane = this,
+			backgroundOption,
+			defaultOptions = pane.defaultOptions;
+		
+		pane.chart = chart;
+		
+		// Set options
+		if (chart.angular) { // gauges
+			defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions
+		}
+		pane.options = options = merge(defaultOptions, options);
+		
+		backgroundOption = options.background;
+		
+		// To avoid having weighty logic to place, update and remove the backgrounds,
+		// push them to the first axis' plot bands and borrow the existing logic there.
+		if (backgroundOption) {
+			each([].concat(splat(backgroundOption)).reverse(), function (config) {
+				var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)
+				config = merge(pane.defaultBackgroundOptions, config);
+				if (backgroundColor) {
+					config.backgroundColor = backgroundColor;
+				}
+				config.color = config.backgroundColor; // due to naming in plotBands
+				firstAxis.options.plotBands.unshift(config);
+			});
+		}
+	},
+	
+	/**
+	 * The default options object
+	 */
+	defaultOptions: {
+		// background: {conditional},
+		center: ['50%', '50%'],
+		size: '85%',
+		startAngle: 0
+		//endAngle: startAngle + 360
+	},	
+	
+	/**
+	 * The default background options
+	 */
+	defaultBackgroundOptions: {
+		shape: 'circle',
+		borderWidth: 1,
+		borderColor: 'silver',
+		backgroundColor: {
+			linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
+			stops: [
+				[0, '#FFF'],
+				[1, '#DDD']
+			]
+		},
+		from: Number.MIN_VALUE, // corrected to axis min
+		innerRadius: 0,
+		to: Number.MAX_VALUE, // corrected to axis max
+		outerRadius: '105%'
+	}
+	
+});
+var axisProto = Axis.prototype,
+	tickProto = Tick.prototype;
+	
+/**
+ * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
+ */
+var hiddenAxisMixin = {
+	getOffset: noop,
+	redraw: function () {
+		this.isDirty = false; // prevent setting Y axis dirty
+	},
+	render: function () {
+		this.isDirty = false; // prevent setting Y axis dirty
+	},
+	setScale: noop,
+	setCategories: noop,
+	setTitle: noop
+};
+
+/**
+ * Augmented methods for the value axis
+ */
+/*jslint unparam: true*/
+var radialAxisMixin = {
+	isRadial: true,
+	
+	/**
+	 * The default options extend defaultYAxisOptions
+	 */
+	defaultRadialGaugeOptions: {
+		labels: {
+			align: 'center',
+			x: 0,
+			y: null // auto
+		},
+		minorGridLineWidth: 0,
+		minorTickInterval: 'auto',
+		minorTickLength: 10,
+		minorTickPosition: 'inside',
+		minorTickWidth: 1,
+		plotBands: [],
+		tickLength: 10,
+		tickPosition: 'inside',
+		tickWidth: 2,
+		title: {
+			rotation: 0
+		},
+		zIndex: 2 // behind dials, points in the series group
+	},
+	
+	// Circular axis around the perimeter of a polar chart
+	defaultRadialXOptions: {
+		gridLineWidth: 1, // spokes
+		labels: {
+			align: null, // auto
+			distance: 15,
+			x: 0,
+			y: null // auto
+		},
+		maxPadding: 0,
+		minPadding: 0,
+		plotBands: [],
+		showLastLabel: false, 
+		tickLength: 0
+	},
+	
+	// Radial axis, like a spoke in a polar chart
+	defaultRadialYOptions: {
+		gridLineInterpolation: 'circle',
+		labels: {
+			align: 'right',
+			x: -3,
+			y: -2
+		},
+		plotBands: [],
+		showLastLabel: false,
+		title: {
+			x: 4,
+			text: null,
+			rotation: 90
+		}
+	},
+	
+	/**
+	 * Merge and set options
+	 */
+	setOptions: function (userOptions) {
+		
+		this.options = merge(
+			this.defaultOptions,
+			this.defaultRadialOptions,
+			userOptions
+		);
+		
+	},
+	
+	/**
+	 * Wrap the getOffset method to return zero offset for title or labels in a radial 
+	 * axis
+	 */
+	getOffset: function () {
+		// Call the Axis prototype method (the method we're in now is on the instance)
+		axisProto.getOffset.call(this);
+		
+		// Title or label offsets are not counted
+		this.chart.axisOffset[this.side] = 0;
+	},
+
+
+	/**
+	 * Get the path for the axis line. This method is also referenced in the getPlotLinePath
+	 * method.
+	 */
+	getLinePath: function (lineWidth, radius) {
+		var center = this.center;
+		radius = pick(radius, center[2] / 2 - this.offset);
+		
+		return this.chart.renderer.symbols.arc(
+			this.left + center[0],
+			this.top + center[1],
+			radius,
+			radius, 
+			{
+				start: this.startAngleRad,
+				end: this.endAngleRad,
+				open: true,
+				innerR: 0
+			}
+		);
+	},
+
+	/**
+	 * Override setAxisTranslation by setting the translation to the difference
+	 * in rotation. This allows the translate method to return angle for 
+	 * any given value.
+	 */
+	setAxisTranslation: function () {
+		
+		// Call uber method		
+		axisProto.setAxisTranslation.call(this);
+			
+		// Set transA and minPixelPadding
+		if (this.center) { // it's not defined the first time
+			if (this.isCircular) {
+				
+				this.transA = (this.endAngleRad - this.startAngleRad) / 
+					((this.max - this.min) || 1);
+					
+				
+			} else { 
+				this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
+			}
+			
+			if (this.isXAxis) {
+				this.minPixelPadding = this.transA * this.minPointOffset +
+					(this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
+			}
+		}
+	},
+	
+	/**
+	 * In case of auto connect, add one closestPointRange to the max value right before
+	 * tickPositions are computed, so that ticks will extend passed the real max.
+	 */
+	beforeSetTickPositions: function () {
+		if (this.autoConnect) {
+			this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260
+		}
+	},
+	
+	/**
+	 * Override the setAxisSize method to use the arc's circumference as length. This
+	 * allows tickPixelInterval to apply to pixel lengths along the perimeter
+	 */
+	setAxisSize: function () {
+		
+		axisProto.setAxisSize.call(this);
+
+		if (this.isRadial) {
+
+			// Set the center array
+			this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);
+			
+			this.len = this.width = this.height = this.isCircular ?
+				this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
+				this.center[2] / 2;
+		}
+	},
+	
+	/**
+	 * Returns the x, y coordinate of a point given by a value and a pixel distance
+	 * from center
+	 */
+	getPosition: function (value, length) {
+		if (!this.isCircular) {
+			length = this.translate(value);
+			value = this.min;	
+		}
+		
+		return this.postTranslate(
+			this.translate(value),
+			pick(length, this.center[2] / 2) - this.offset
+		);		
+	},
+	
+	/**
+	 * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates. 
+	 */
+	postTranslate: function (angle, radius) {
+		
+		var chart = this.chart,
+			center = this.center;
+			
+		angle = this.startAngleRad + angle;
+		
+		return {
+			x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
+			y: chart.plotTop + center[1] + Math.sin(angle) * radius
+		}; 
+		
+	},
+	
+	/**
+	 * Find the path for plot bands along the radial axis
+	 */
+	getPlotBandPath: function (from, to, options) {
+		var center = this.center,
+			startAngleRad = this.startAngleRad,
+			fullRadius = center[2] / 2,
+			radii = [
+				pick(options.outerRadius, '100%'),
+				options.innerRadius,
+				pick(options.thickness, 10)
+			],
+			percentRegex = /%$/,
+			start,
+			end,
+			open,
+			isCircular = this.isCircular, // X axis in a polar chart
+			ret;
+			
+		// Polygonal plot bands
+		if (this.options.gridLineInterpolation === 'polygon') {
+			ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
+		
+		// Circular grid bands
+		} else {
+			
+			// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
+			if (!isCircular) {
+				radii[0] = this.translate(from);
+				radii[1] = this.translate(to);
+			}
+			
+			// Convert percentages to pixel values
+			radii = map(radii, function (radius) {
+				if (percentRegex.test(radius)) {
+					radius = (pInt(radius, 10) * fullRadius) / 100;
+				}
+				return radius;
+			});
+			
+			// Handle full circle
+			if (options.shape === 'circle' || !isCircular) {
+				start = -Math.PI / 2;
+				end = Math.PI * 1.5;
+				open = true;
+			} else {
+				start = startAngleRad + this.translate(from);
+				end = startAngleRad + this.translate(to);
+			}
+		
+		
+			ret = this.chart.renderer.symbols.arc(
+				this.left + center[0],
+				this.top + center[1],
+				radii[0],
+				radii[0],
+				{
+					start: start,
+					end: end,
+					innerR: pick(radii[1], radii[0] - radii[2]),
+					open: open
+				}
+			);
+		}
+		 
+		return ret;
+	},
+	
+	/**
+	 * Find the path for plot lines perpendicular to the radial axis.
+	 */
+	getPlotLinePath: function (value, reverse) {
+		var axis = this,
+			center = axis.center,
+			chart = axis.chart,
+			end = axis.getPosition(value),
+			xAxis,
+			xy,
+			tickPositions,
+			ret;
+		
+		// Spokes
+		if (axis.isCircular) {
+			ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
+		
+		// Concentric circles			
+		} else if (axis.options.gridLineInterpolation === 'circle') {
+			value = axis.translate(value);
+			if (value) { // a value of 0 is in the center
+				ret = axis.getLinePath(0, value);
+			}
+		// Concentric polygons 
+		} else {
+			xAxis = chart.xAxis[0];
+			ret = [];
+			value = axis.translate(value);
+			tickPositions = xAxis.tickPositions;
+			if (xAxis.autoConnect) {
+				tickPositions = tickPositions.concat([tickPositions[0]]);
+			}
+			// Reverse the positions for concatenation of polygonal plot bands
+			if (reverse) {
+				tickPositions = [].concat(tickPositions).reverse();
+			}
+				
+			each(tickPositions, function (pos, i) {
+				xy = xAxis.getPosition(pos, value);
+				ret.push(i ? 'L' : 'M', xy.x, xy.y);
+			});
+			
+		}
+		return ret;
+	},
+	
+	/**
+	 * Find the position for the axis title, by default inside the gauge
+	 */
+	getTitlePosition: function () {
+		var center = this.center,
+			chart = this.chart,
+			titleOptions = this.options.title;
+		
+		return { 
+			x: chart.plotLeft + center[0] + (titleOptions.x || 0), 
+			y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] * 
+				center[2]) + (titleOptions.y || 0)  
+		};
+	}
+	
+};
+/*jslint unparam: false*/
+
+/**
+ * Override axisProto.init to mix in special axis instance functions and function overrides
+ */
+wrap(axisProto, 'init', function (proceed, chart, userOptions) {
+	var axis = this,
+		angular = chart.angular,
+		polar = chart.polar,
+		isX = userOptions.isX,
+		isHidden = angular && isX,
+		isCircular,
+		startAngleRad,
+		endAngleRad,
+		options,
+		chartOptions = chart.options,
+		paneIndex = userOptions.pane || 0,
+		pane,
+		paneOptions;
+		
+	// Before prototype.init
+	if (angular) {
+		extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
+		isCircular =  !isX;
+		if (isCircular) {
+			this.defaultRadialOptions = this.defaultRadialGaugeOptions;
+		}
+		
+	} else if (polar) {
+		//extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);
+		extend(this, radialAxisMixin);
+		isCircular = isX;
+		this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
+		
+	}
+	
+	// Run prototype.init
+	proceed.call(this, chart, userOptions);
+	
+	if (!isHidden && (angular || polar)) {
+		options = this.options;
+		
+		// Create the pane and set the pane options.
+		if (!chart.panes) {
+			chart.panes = [];
+		}
+		this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
+			splat(chartOptions.pane)[paneIndex],
+			chart,
+			axis
+		);
+		paneOptions = pane.options;
+		
+			
+		// Disable certain features on angular and polar axes
+		chart.inverted = false;
+		chartOptions.chart.zoomType = null;
+		
+		// Start and end angle options are
+		// given in degrees relative to top, while internal computations are
+		// in radians relative to right (like SVG).
+		this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
+		this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360)  - 90) * Math.PI / 180;
+		this.offset = options.offset || 0;
+		
+		this.isCircular = isCircular;
+		
+		// Automatically connect grid lines?
+		if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {
+			this.autoConnect = true;
+		}
+	}
+	
+});
+
+/**
+ * Add special cases within the Tick class' methods for radial axes.
+ */	
+wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
+	var axis = this.axis;
+	
+	return axis.getPosition ? 
+		axis.getPosition(pos) :
+		proceed.call(this, horiz, pos, tickmarkOffset, old);	
+});
+
+/**
+ * Wrap the getLabelPosition function to find the center position of the label
+ * based on the distance option
+ */	
+wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
+	var axis = this.axis,
+		optionsY = labelOptions.y,
+		ret,
+		align = labelOptions.align,
+		angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
+	
+	if (axis.isRadial) {
+		ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
+		
+		// Automatically rotated
+		if (labelOptions.rotation === 'auto') {
+			label.attr({ 
+				rotation: angle
+			});
+		
+		// Vertically centered
+		} else if (optionsY === null) {
+			optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
+		
+		}
+		
+		// Automatic alignment
+		if (align === null) {
+			if (axis.isCircular) {
+				if (angle > 20 && angle < 160) {
+					align = 'left'; // right hemisphere
+				} else if (angle > 200 && angle < 340) {
+					align = 'right'; // left hemisphere
+				} else {
+					align = 'center'; // top or bottom
+				}
+			} else {
+				align = 'center';
+			}
+			label.attr({
+				align: align
+			});
+		}
+		
+		ret.x += labelOptions.x;
+		ret.y += optionsY;
+		
+	} else {
+		ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
+	}
+	return ret;
+});
+
+/**
+ * Wrap the getMarkPath function to return the path of the radial marker
+ */
+wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
+	var axis = this.axis,
+		endPoint,
+		ret;
+		
+	if (axis.isRadial) {
+		endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
+		ret = [
+			'M',
+			x,
+			y,
+			'L',
+			endPoint.x,
+			endPoint.y
+		];
+	} else {
+		ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
+	}
+	return ret;
+});/* 
+ * The AreaRangeSeries class
+ * 
+ */
+
+/**
+ * Extend the default options with map options
+ */
+defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
+	lineWidth: 1,
+	marker: null,
+	threshold: null,
+	tooltip: {
+		pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>' 
+	},
+	trackByArea: true,
+	dataLabels: {
+		verticalAlign: null,
+		xLow: 0,
+		xHigh: 0,
+		yLow: 0,
+		yHigh: 0	
+	}
+});
+
+/**
+ * Add the series type
+ */
+seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {
+	type: 'arearange',
+	pointArrayMap: ['low', 'high'],
+	toYData: function (point) {
+		return [point.low, point.high];
+	},
+	pointValKey: 'low',
+	
+	/**
+	 * Extend getSegments to force null points if the higher value is null. #1703.
+	 */
+	getSegments: function () {
+		var series = this;
+
+		each(series.points, function (point) {
+			if (!series.options.connectNulls && (point.low === null || point.high === null)) {
+				point.y = null;
+			} else if (point.low === null && point.high !== null) {
+				point.y = point.high;
+			}
+		});
+		Series.prototype.getSegments.call(this);
+	},
+	
+	/**
+	 * Translate data points from raw values x and y to plotX and plotY
+	 */
+	translate: function () {
+		var series = this,
+			yAxis = series.yAxis;
+
+		seriesTypes.area.prototype.translate.apply(series);
+
+		// Set plotLow and plotHigh
+		each(series.points, function (point) {
+
+			var low = point.low,
+				high = point.high,
+				plotY = point.plotY;
+
+			if (high === null && low === null) {
+				point.y = null;
+			} else if (low === null) {
+				point.plotLow = point.plotY = null;
+				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
+			} else if (high === null) {
+				point.plotLow = plotY;
+				point.plotHigh = null;
+			} else {
+				point.plotLow = plotY;
+				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
+			}
+		});
+	},
+	
+	/**
+	 * Extend the line series' getSegmentPath method by applying the segment
+	 * path to both lower and higher values of the range
+	 */
+	getSegmentPath: function (segment) {
+		
+		var lowSegment,
+			highSegment = [],
+			i = segment.length,
+			baseGetSegmentPath = Series.prototype.getSegmentPath,
+			point,
+			linePath,
+			lowerPath,
+			options = this.options,
+			step = options.step,
+			higherPath;
+			
+		// Remove nulls from low segment
+		lowSegment = HighchartsAdapter.grep(segment, function (point) {
+			return point.plotLow !== null;
+		});
+		
+		// Make a segment with plotX and plotY for the top values
+		while (i--) {
+			point = segment[i];
+			if (point.plotHigh !== null) {
+				highSegment.push({
+					plotX: point.plotX,
+					plotY: point.plotHigh
+				});
+			}
+		}
+		
+		// Get the paths
+		lowerPath = baseGetSegmentPath.call(this, lowSegment);
+		if (step) {
+			if (step === true) {
+				step = 'left';
+			}
+			options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath
+		}
+		higherPath = baseGetSegmentPath.call(this, highSegment);
+		options.step = step;
+		
+		// Create a line on both top and bottom of the range
+		linePath = [].concat(lowerPath, higherPath);
+		
+		// For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
+		higherPath[0] = 'L'; // this probably doesn't work for spline			
+		this.areaPath = this.areaPath.concat(lowerPath, higherPath);
+		
+		return linePath;
+	},
+	
+	/**
+	 * Extend the basic drawDataLabels method by running it for both lower and higher
+	 * values.
+	 */
+	drawDataLabels: function () {
+		
+		var data = this.data,
+			length = data.length,
+			i,
+			originalDataLabels = [],
+			seriesProto = Series.prototype,
+			dataLabelOptions = this.options.dataLabels,
+			point,
+			inverted = this.chart.inverted;
+			
+		if (dataLabelOptions.enabled || this._hasPointLabels) {
+			
+			// Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
+			i = length;
+			while (i--) {
+				point = data[i];
+				
+				// Set preliminary values
+				point.y = point.high;
+				point.plotY = point.plotHigh;
+				
+				// Store original data labels and set preliminary label objects to be picked up 
+				// in the uber method
+				originalDataLabels[i] = point.dataLabel;
+				point.dataLabel = point.dataLabelUpper;
+				
+				// Set the default offset
+				point.below = false;
+				if (inverted) {
+					dataLabelOptions.align = 'left';
+					dataLabelOptions.x = dataLabelOptions.xHigh;								
+				} else {
+					dataLabelOptions.y = dataLabelOptions.yHigh;
+				}
+			}
+			seriesProto.drawDataLabels.apply(this, arguments); // #1209
+			
+			// Step 2: reorganize and handle data labels for the lower values
+			i = length;
+			while (i--) {
+				point = data[i];
+				
+				// Move the generated labels from step 1, and reassign the original data labels
+				point.dataLabelUpper = point.dataLabel;
+				point.dataLabel = originalDataLabels[i];
+				
+				// Reset values
+				point.y = point.low;
+				point.plotY = point.plotLow;
+				
+				// Set the default offset
+				point.below = true;
+				if (inverted) {
+					dataLabelOptions.align = 'right';
+					dataLabelOptions.x = dataLabelOptions.xLow;
+				} else {
+					dataLabelOptions.y = dataLabelOptions.yLow;
+				}
+			}
+			seriesProto.drawDataLabels.apply(this, arguments);
+		}
+	
+	},
+	
+	alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
+	
+	getSymbol: seriesTypes.column.prototype.getSymbol,
+	
+	drawPoints: noop
+});/**
+ * The AreaSplineRangeSeries class
+ */
+
+defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);
+
+/**
+ * AreaSplineRangeSeries object
+ */
+seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
+	type: 'areasplinerange',
+	getPointSpline: seriesTypes.spline.prototype.getPointSpline
+});/**
+ * The ColumnRangeSeries class
+ */
+defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
+	lineWidth: 1,
+	pointRange: null
+});
+
+/**
+ * ColumnRangeSeries object
+ */
+seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
+	type: 'columnrange',
+	/**
+	 * Translate data points from raw values x and y to plotX and plotY
+	 */
+	translate: function () {
+		var series = this,
+			yAxis = series.yAxis,
+			plotHigh;
+
+		colProto.translate.apply(series);
+
+		// Set plotLow and plotHigh
+		each(series.points, function (point) {
+			var shapeArgs = point.shapeArgs,
+				minPointLength = series.options.minPointLength,
+				heightDifference,
+				height,
+				y;
+
+			point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
+			point.plotLow = point.plotY;
+
+			// adjust shape
+			y = plotHigh;
+			height = point.plotY - plotHigh;
+
+			if (height < minPointLength) {
+				heightDifference = (minPointLength - height);
+				height += heightDifference;
+				y -= heightDifference / 2;
+			}
+			shapeArgs.height = height;
+			shapeArgs.y = y;
+		});
+	},
+	trackerGroups: ['group', 'dataLabels'],
+	drawGraph: noop,
+	pointAttrToOptions: colProto.pointAttrToOptions,
+	drawPoints: colProto.drawPoints,
+	drawTracker: colProto.drawTracker,
+	animate: colProto.animate,
+	getColumnMetrics: colProto.getColumnMetrics
+});
+/* 
+ * The GaugeSeries class
+ */
+
+
+
+/**
+ * Extend the default options
+ */
+defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
+	dataLabels: {
+		enabled: true,
+		y: 15,
+		borderWidth: 1,
+		borderColor: 'silver',
+		borderRadius: 3,
+		style: {
+			fontWeight: 'bold'
+		},
+		verticalAlign: 'top',
+		zIndex: 2
+	},
+	dial: {
+		// radius: '80%',
+		// backgroundColor: 'black',
+		// borderColor: 'silver',
+		// borderWidth: 0,
+		// baseWidth: 3,
+		// topWidth: 1,
+		// baseLength: '70%' // of radius
+		// rearLength: '10%'
+	},
+	pivot: {
+		//radius: 5,
+		//borderWidth: 0
+		//borderColor: 'silver',
+		//backgroundColor: 'black'
+	},
+	tooltip: {
+		headerFormat: ''
+	},
+	showInLegend: false
+});
+
+/**
+ * Extend the point object
+ */
+var GaugePoint = Highcharts.extendClass(Highcharts.Point, {
+	/**
+	 * Don't do any hover colors or anything
+	 */
+	setState: function (state) {
+		this.state = state;
+	}
+});
+
+
+/**
+ * Add the series type
+ */
+var GaugeSeries = {
+	type: 'gauge',
+	pointClass: GaugePoint,
+	
+	// chart.angular will be set to true when a gauge series is present, and this will
+	// be used on the axes
+	angular: true, 
+	drawGraph: noop,
+	fixedBox: true,
+	trackerGroups: ['group', 'dataLabels'],
+	
+	/**
+	 * Calculate paths etc
+	 */
+	translate: function () {
+		
+		var series = this,
+			yAxis = series.yAxis,
+			options = series.options,
+			center = yAxis.center;
+			
+		series.generatePoints();
+		
+		each(series.points, function (point) {
+			
+			var dialOptions = merge(options.dial, point.dial),
+				radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
+				baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
+				rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
+				baseWidth = dialOptions.baseWidth || 3,
+				topWidth = dialOptions.topWidth || 1,
+				rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
+
+			// Handle the wrap option
+			if (options.wrap === false) {
+				rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
+			}
+			rotation = rotation * 180 / Math.PI;
+				
+			point.shapeType = 'path';
+			point.shapeArgs = {
+				d: dialOptions.path || [
+					'M', 
+					-rearLength, -baseWidth / 2, 
+					'L', 
+					baseLength, -baseWidth / 2,
+					radius, -topWidth / 2,
+					radius, topWidth / 2,
+					baseLength, baseWidth / 2,
+					-rearLength, baseWidth / 2,
+					'z'
+				],
+				translateX: center[0],
+				translateY: center[1],
+				rotation: rotation
+			};
+			
+			// Positions for data label
+			point.plotX = center[0];
+			point.plotY = center[1];
+		});
+	},
+	
+	/**
+	 * Draw the points where each point is one needle
+	 */
+	drawPoints: function () {
+		
+		var series = this,
+			center = series.yAxis.center,
+			pivot = series.pivot,
+			options = series.options,
+			pivotOptions = options.pivot,
+			renderer = series.chart.renderer;
+		
+		each(series.points, function (point) {
+			
+			var graphic = point.graphic,
+				shapeArgs = point.shapeArgs,
+				d = shapeArgs.d,
+				dialOptions = merge(options.dial, point.dial); // #1233
+			
+			if (graphic) {
+				graphic.animate(shapeArgs);
+				shapeArgs.d = d; // animate alters it
+			} else {
+				point.graphic = renderer[point.shapeType](shapeArgs)
+					.attr({
+						stroke: dialOptions.borderColor || 'none',
+						'stroke-width': dialOptions.borderWidth || 0,
+						fill: dialOptions.backgroundColor || 'black',
+						rotation: shapeArgs.rotation // required by VML when animation is false
+					})
+					.add(series.group);
+			}
+		});
+		
+		// Add or move the pivot
+		if (pivot) {
+			pivot.animate({ // #1235
+				translateX: center[0],
+				translateY: center[1]
+			});
+		} else {
+			series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
+				.attr({
+					'stroke-width': pivotOptions.borderWidth || 0,
+					stroke: pivotOptions.borderColor || 'silver',
+					fill: pivotOptions.backgroundColor || 'black'
+				})
+				.translate(center[0], center[1])
+				.add(series.group);
+		}
+	},
+	
+	/**
+	 * Animate the arrow up from startAngle
+	 */
+	animate: function (init) {
+		var series = this;
+
+		if (!init) {
+			each(series.points, function (point) {
+				var graphic = point.graphic;
+
+				if (graphic) {
+					// start value
+					graphic.attr({
+						rotation: series.yAxis.startAngleRad * 180 / Math.PI
+					});
+
+					// animate
+					graphic.animate({
+						rotation: point.shapeArgs.rotation
+					}, series.options.animation);
+				}
+			});
+
+			// delete this function to allow it only once
+			series.animate = null;
+		}
+	},
+	
+	render: function () {
+		this.group = this.plotGroup(
+			'group', 
+			'series', 
+			this.visible ? 'visible' : 'hidden', 
+			this.options.zIndex, 
+			this.chart.seriesGroup
+		);
+		seriesTypes.pie.prototype.render.call(this);
+		this.group.clip(this.chart.clipRect);
+	},
+	
+	setData: seriesTypes.pie.prototype.setData,
+	drawTracker: seriesTypes.column.prototype.drawTracker
+};
+seriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* ****************************************************************************
+ * Start Box plot series code											      *
+ *****************************************************************************/
+
+// Set default options
+defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
+	fillColor: '#FFFFFF',
+	lineWidth: 1,
+	//medianColor: null,
+	medianWidth: 2,
+	states: {
+		hover: {
+			brightness: -0.3
+		}
+	},
+	//stemColor: null,
+	//stemDashStyle: 'solid'
+	//stemWidth: null,
+	threshold: null,
+	tooltip: {
+		pointFormat: '<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>' +
+			'Maximum: {point.high}<br/>' +
+			'Upper quartile: {point.q3}<br/>' +
+			'Median: {point.median}<br/>' +
+			'Lower quartile: {point.q1}<br/>' +
+			'Minimum: {point.low}<br/>'
+			
+	},
+	//whiskerColor: null,
+	whiskerLength: '50%',
+	whiskerWidth: 2
+});
+
+// Create the series object
+seriesTypes.boxplot = extendClass(seriesTypes.column, {
+	type: 'boxplot',
+	pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
+	toYData: function (point) { // return a plain array for speedy calculation
+		return [point.low, point.q1, point.median, point.q3, point.high];
+	},
+	pointValKey: 'high', // defines the top of the tracker
+	
+	/**
+	 * One-to-one mapping from options to SVG attributes
+	 */
+	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
+		fill: 'fillColor',
+		stroke: 'color',
+		'stroke-width': 'lineWidth'
+	},
+	
+	/**
+	 * Disable data labels for box plot
+	 */
+	drawDataLabels: noop,
+
+	/**
+	 * Translate data points from raw values x and y to plotX and plotY
+	 */
+	translate: function () {
+		var series = this,
+			yAxis = series.yAxis,
+			pointArrayMap = series.pointArrayMap;
+
+		seriesTypes.column.prototype.translate.apply(series);
+
+		// do the translation on each point dimension
+		each(series.points, function (point) {
+			each(pointArrayMap, function (key) {
+				if (point[key] !== null) {
+					point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);
+				}
+			});
+		});
+	},
+
+	/**
+	 * Draw the data points
+	 */
+	drawPoints: function () {
+		var series = this,  //state = series.state,
+			points = series.points,
+			options = series.options,
+			chart = series.chart,
+			renderer = chart.renderer,
+			pointAttr,
+			q1Plot,
+			q3Plot,
+			highPlot,
+			lowPlot,
+			medianPlot,
+			crispCorr,
+			crispX,
+			graphic,
+			stemPath,
+			stemAttr,
+			boxPath,
+			whiskersPath,
+			whiskersAttr,
+			medianPath,
+			medianAttr,
+			width,
+			left,
+			right,
+			halfWidth,
+			shapeArgs,
+			color,
+			doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
+			whiskerLength = parseInt(series.options.whiskerLength, 10) / 100;
+
+
+		each(points, function (point) {
+
+			graphic = point.graphic;
+			shapeArgs = point.shapeArgs; // the box
+			stemAttr = {};
+			whiskersAttr = {};
+			medianAttr = {};
+			color = point.color || series.color;
+			
+			if (point.plotY !== UNDEFINED) {
+
+				pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
+
+				// crisp vector coordinates
+				width = shapeArgs.width;
+				left = mathFloor(shapeArgs.x);
+				right = left + width;
+				halfWidth = mathRound(width / 2);
+				//crispX = mathRound(left + halfWidth) + crispCorr;
+				q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;
+				q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;
+				highPlot = mathFloor(point.highPlot);// + crispCorr;
+				lowPlot = mathFloor(point.lowPlot);// + crispCorr;
+				
+				// Stem attributes
+				stemAttr.stroke = point.stemColor || options.stemColor || color;
+				stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
+				stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
+				
+				// Whiskers attributes
+				whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
+				whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
+				
+				// Median attributes
+				medianAttr.stroke = point.medianColor || options.medianColor || color;
+				medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
+				
+				
+				// The stem
+				crispCorr = (stemAttr['stroke-width'] % 2) / 2;
+				crispX = left + halfWidth + crispCorr;				
+				stemPath = [
+					// stem up
+					'M',
+					crispX, q3Plot,
+					'L',
+					crispX, highPlot,
+					
+					// stem down
+					'M',
+					crispX, q1Plot,
+					'L',
+					crispX, lowPlot,
+					'z'
+				];
+				
+				// The box
+				if (doQuartiles) {
+					crispCorr = (pointAttr['stroke-width'] % 2) / 2;
+					crispX = mathFloor(crispX) + crispCorr;
+					q1Plot = mathFloor(q1Plot) + crispCorr;
+					q3Plot = mathFloor(q3Plot) + crispCorr;
+					left += crispCorr;
+					right += crispCorr;
+					boxPath = [
+						'M',
+						left, q3Plot,
+						'L',
+						left, q1Plot,
+						'L',
+						right, q1Plot,
+						'L',
+						right, q3Plot,
+						'L',
+						left, q3Plot,
+						'z'
+					];
+				}
+				
+				// The whiskers
+				if (whiskerLength) {
+					crispCorr = (whiskersAttr['stroke-width'] % 2) / 2;
+					highPlot = highPlot + crispCorr;
+					lowPlot = lowPlot + crispCorr;
+					whiskersPath = [
+						// High whisker
+						'M',
+						crispX - halfWidth * whiskerLength, 
+						highPlot,
+						'L',
+						crispX + halfWidth * whiskerLength, 
+						highPlot,
+						
+						// Low whisker
+						'M',
+						crispX - halfWidth * whiskerLength, 
+						lowPlot,
+						'L',
+						crispX + halfWidth * whiskerLength, 
+						lowPlot
+					];
+				}
+				
+				// The median
+				crispCorr = (medianAttr['stroke-width'] % 2) / 2;				
+				medianPlot = mathRound(point.medianPlot) + crispCorr;
+				medianPath = [
+					'M',
+					left, 
+					medianPlot,
+					'L',
+					right, 
+					medianPlot,
+					'z'
+				];
+				
+				// Create or update the graphics
+				if (graphic) { // update
+					
+					point.stem.animate({ d: stemPath });
+					if (whiskerLength) {
+						point.whiskers.animate({ d: whiskersPath });
+					}
+					if (doQuartiles) {
+						point.box.animate({ d: boxPath });
+					}
+					point.medianShape.animate({ d: medianPath });
+					
+				} else { // create new
+					point.graphic = graphic = renderer.g()
+						.add(series.group);
+					
+					point.stem = renderer.path(stemPath)
+						.attr(stemAttr)
+						.add(graphic);
+						
+					if (whiskerLength) {
+						point.whiskers = renderer.path(whiskersPath) 
+							.attr(whiskersAttr)
+							.add(graphic);
+					}
+					if (doQuartiles) {
+						point.box = renderer.path(boxPath)
+							.attr(pointAttr)
+							.add(graphic);
+					}	
+					point.medianShape = renderer.path(medianPath)
+						.attr(medianAttr)
+						.add(graphic);
+				}
+			}
+		});
+
+	}
+
+
+});
+
+/* ****************************************************************************
+ * End Box plot series code												*
+ *****************************************************************************/
+/* ****************************************************************************
+ * Start error bar series code                                                *
+ *****************************************************************************/
+
+// 1 - set default options
+defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
+	color: '#000000',
+	grouping: false,
+	linkedTo: ':previous',
+	tooltip: {
+		pointFormat: defaultPlotOptions.arearange.tooltip.pointFormat
+	},
+	whiskerWidth: null
+});
+
+// 2 - Create the series object
+seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
+	type: 'errorbar',
+	pointArrayMap: ['low', 'high'], // array point configs are mapped to this
+	toYData: function (point) { // return a plain array for speedy calculation
+		return [point.low, point.high];
+	},
+	pointValKey: 'high', // defines the top of the tracker
+	doQuartiles: false,
+
+	/**
+	 * Get the width and X offset, either on top of the linked series column
+	 * or standalone
+	 */
+	getColumnMetrics: function () {
+		return (this.linkedParent && this.linkedParent.columnMetrics) || 
+			seriesTypes.column.prototype.getColumnMetrics.call(this);
+	}
+});
+
+/* ****************************************************************************
+ * End error bar series code                                                  *
+ *****************************************************************************/
+/* ****************************************************************************
+ * Start Waterfall series code                                                *
+ *****************************************************************************/
+
+// 1 - set default options
+defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {
+	lineWidth: 1,
+	lineColor: '#333',
+	dashStyle: 'dot',
+	borderColor: '#333'
+});
+
+
+// 2 - Create the series object
+seriesTypes.waterfall = extendClass(seriesTypes.column, {
+	type: 'waterfall',
+
+	upColorProp: 'fill',
+
+	pointArrayMap: ['low', 'y'],
+
+	pointValKey: 'y',
+
+	/**
+	 * Init waterfall series, force stacking
+	 */
+	init: function (chart, options) {
+		// force stacking
+		options.stacking = true;
+
+		seriesTypes.column.prototype.init.call(this, chart, options);
+	},
+
+
+	/**
+	 * Translate data points from raw values
+	 */
+	translate: function () {
+		var series = this,
+			options = series.options,
+			axis = series.yAxis,
+			len,
+			i,
+			points,
+			point,
+			shapeArgs,
+			stack,
+			y,
+			previousY,
+			stackPoint,
+			threshold = options.threshold,
+			crispCorr = (options.borderWidth % 2) / 2;
+
+		// run column series translate
+		seriesTypes.column.prototype.translate.apply(this);
+
+		previousY = threshold;
+		points = series.points;
+
+		for (i = 0, len = points.length; i < len; i++) {
+			// cache current point object
+			point = points[i];
+			shapeArgs = point.shapeArgs;
+
+			// get current stack
+			stack = series.getStack(i);
+			stackPoint = stack.points[series.index];
+
+			// override point value for sums
+			if (isNaN(point.y)) {
+				point.y = series.yData[i];
+			}
+
+			// up points
+			y = mathMax(previousY, previousY + point.y) + stackPoint[0];
+			shapeArgs.y = axis.translate(y, 0, 1);
+
+
+			// sum points
+			if (point.isSum || point.isIntermediateSum) {
+				shapeArgs.y = axis.translate(stackPoint[1], 0, 1);
+				shapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y;
+
+			// if it's not the sum point, update previous stack end position
+			} else {
+				previousY += stack.total;
+			}
+
+			// negative points
+			if (shapeArgs.height < 0) {
+				shapeArgs.y += shapeArgs.height;
+				shapeArgs.height *= -1;
+			}
+
+			point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;
+			shapeArgs.height = mathRound(shapeArgs.height);
+			point.yBottom = shapeArgs.y + shapeArgs.height;
+		}
+	},
+
+	/**
+	 * Call default processData then override yData to reflect waterfall's extremes on yAxis
+	 */
+	processData: function (force) {
+		var series = this,
+			options = series.options,
+			yData = series.yData,
+			points = series.points,
+			point,
+			dataLength = yData.length,
+			threshold = options.threshold || 0,
+			subSum,
+			sum,
+			dataMin,
+			dataMax,
+			y,
+			i;
+
+		sum = subSum = dataMin = dataMax = threshold;
+
+		for (i = 0; i < dataLength; i++) {
+			y = yData[i];
+			point = points && points[i] ? points[i] : {};
+
+			if (y === "sum" || point.isSum) {
+				yData[i] = sum;
+			} else if (y === "intermediateSum" || point.isIntermediateSum) {
+				yData[i] = subSum;
+				subSum = threshold;
+			} else {
+				sum += y;
+				subSum += y;
+			}
+			dataMin = Math.min(sum, dataMin);
+			dataMax = Math.max(sum, dataMax);
+		}
+
+		Series.prototype.processData.call(this, force);
+
+		// Record extremes
+		series.dataMin = dataMin;
+		series.dataMax = dataMax;
+	},
+
+	/**
+	 * Return y value or string if point is sum
+	 */
+	toYData: function (pt) {
+		if (pt.isSum) {
+			return "sum";
+		} else if (pt.isIntermediateSum) {
+			return "intermediateSum";
+		}
+
+		return pt.y;
+	},
+
+	/**
+	 * Postprocess mapping between options and SVG attributes
+	 */
+	getAttribs: function () {
+		seriesTypes.column.prototype.getAttribs.apply(this, arguments);
+
+		var series = this,
+			options = series.options,
+			stateOptions = options.states,
+			upColor = options.upColor || series.color,
+			hoverColor = Highcharts.Color(upColor).brighten(0.1).get(),
+			seriesDownPointAttr = merge(series.pointAttr),
+			upColorProp = series.upColorProp;
+
+		seriesDownPointAttr[''][upColorProp] = upColor;
+		seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;
+		seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;
+
+		each(series.points, function (point) {
+			if (point.y > 0 && !point.color) {
+				point.pointAttr = seriesDownPointAttr;
+				point.color = upColor;
+			}
+		});
+	},
+
+	/**
+	 * Draw columns' connector lines
+	 */
+	getGraphPath: function () {
+
+		var data = this.data,
+			length = data.length,
+			lineWidth = this.options.lineWidth + this.options.borderWidth,
+			normalizer = mathRound(lineWidth) % 2 / 2,
+			path = [],
+			M = 'M',
+			L = 'L',
+			prevArgs,
+			pointArgs,
+			i,
+			d;
+
+		for (i = 1; i < length; i++) {
+			pointArgs = data[i].shapeArgs;
+			prevArgs = data[i - 1].shapeArgs;
+
+			d = [
+				M,
+				prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
+				L,
+				pointArgs.x, prevArgs.y + normalizer
+			];
+
+			if (data[i - 1].y < 0) {
+				d[2] += prevArgs.height;
+				d[5] += prevArgs.height;
+			}
+
+			path = path.concat(d);
+		}
+
+		return path;
+	},
+
+	/**
+	 * Extremes are recorded in processData
+	 */
+	getExtremes: noop,
+
+	/**
+	 * Return stack for given index
+	 */
+	getStack: function (i) {
+		var axis = this.yAxis,
+			stacks = axis.stacks,
+			key = this.stackKey;
+
+		if (this.processedYData[i] < this.options.threshold) {
+			key = '-' + key;
+		}
+
+		return stacks[key][i];
+	},
+
+	drawGraph: Series.prototype.drawGraph
+});
+
+/* ****************************************************************************
+ * End Waterfall series code                                                  *
+ *****************************************************************************/
+/* ****************************************************************************
+ * Start Bubble series code											          *
+ *****************************************************************************/
+
+// 1 - set default options
+defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
+	dataLabels: {
+		inside: true,
+		style: {
+			color: 'white',
+			textShadow: '0px 0px 3px black'
+		},
+		verticalAlign: 'middle'
+	},
+	// displayNegative: true,
+	marker: {
+		// fillOpacity: 0.5,
+		lineColor: null, // inherit from series.color
+		lineWidth: 1
+	},
+	minSize: 8,
+	maxSize: '20%',
+	// negativeColor: null,
+	tooltip: {
+		pointFormat: '({point.x}, {point.y}), Size: {point.z}'
+	},
+	turboThreshold: 0,
+	zThreshold: 0
+});
+
+// 2 - Create the series object
+seriesTypes.bubble = extendClass(seriesTypes.scatter, {
+	type: 'bubble',
+	pointArrayMap: ['y', 'z'],
+	trackerGroups: ['group', 'dataLabelsGroup'],
+	
+	/**
+	 * Mapping between SVG attributes and the corresponding options
+	 */
+	pointAttrToOptions: { 
+		stroke: 'lineColor',
+		'stroke-width': 'lineWidth',
+		fill: 'fillColor'
+	},
+	
+	/**
+	 * Apply the fillOpacity to all fill positions
+	 */
+	applyOpacity: function (fill) {
+		var markerOptions = this.options.marker,
+			fillOpacity = pick(markerOptions.fillOpacity, 0.5);
+		
+		// When called from Legend.colorizeItem, the fill isn't predefined
+		fill = fill || markerOptions.fillColor || this.color; 
+		
+		if (fillOpacity !== 1) {
+			fill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba');
+		}
+		return fill;
+	},
+	
+	/**
+	 * Extend the convertAttribs method by applying opacity to the fill
+	 */
+	convertAttribs: function () {
+		var obj = Series.prototype.convertAttribs.apply(this, arguments);
+		
+		obj.fill = this.applyOpacity(obj.fill);
+		
+		return obj;
+	},
+
+	/**
+	 * Get the radius for each point based on the minSize, maxSize and each point's Z value. This
+	 * must be done prior to Series.translate because the axis needs to add padding in 
+	 * accordance with the point sizes.
+	 */
+	getRadii: function (zMin, zMax, minSize, maxSize) {
+		var len,
+			i,
+			pos,
+			zData = this.zData,
+			radii = [],
+			zRange;
+		
+		// Set the shape type and arguments to be picked up in drawPoints
+		for (i = 0, len = zData.length; i < len; i++) {
+			zRange = zMax - zMin;
+			pos = zRange > 0 ? // relative size, a number between 0 and 1
+				(zData[i] - zMin) / (zMax - zMin) : 
+				0.5;
+			radii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2);
+		}
+		this.radii = radii;
+	},
+	
+	/**
+	 * Perform animation on the bubbles
+	 */
+	animate: function (init) {
+		var animation = this.options.animation;
+		
+		if (!init) { // run the animation
+			each(this.points, function (point) {
+				var graphic = point.graphic,
+					shapeArgs = point.shapeArgs;
+
+				if (graphic && shapeArgs) {
+					// start values
+					graphic.attr('r', 1);
+
+					// animate
+					graphic.animate({
+						r: shapeArgs.r
+					}, animation);
+				}
+			});
+
+			// delete this function to allow it only once
+			this.animate = null;
+		}
+	},
+	
+	/**
+	 * Extend the base translate method to handle bubble size
+	 */
+	translate: function () {
+		
+		var i,
+			data = this.data,
+			point,
+			radius,
+			radii = this.radii;
+		
+		// Run the parent method
+		seriesTypes.scatter.prototype.translate.call(this);
+		
+		// Set the shape type and arguments to be picked up in drawPoints
+		i = data.length;
+		
+		while (i--) {
+			point = data[i];
+			radius = radii ? radii[i] : 0; // #1737
+
+			// Flag for negativeColor to be applied in Series.js
+			point.negative = point.z < (this.options.zThreshold || 0);
+			
+			if (radius >= this.minPxSize / 2) {
+				// Shape arguments
+				point.shapeType = 'circle';
+				point.shapeArgs = {
+					x: point.plotX,
+					y: point.plotY,
+					r: radius
+				};
+				
+				// Alignment box for the data label
+				point.dlBox = {
+					x: point.plotX - radius,
+					y: point.plotY - radius,
+					width: 2 * radius,
+					height: 2 * radius
+				};
+			} else { // below zThreshold
+				point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691
+			}
+		}
+	},
+	
+	/**
+	 * Get the series' symbol in the legend
+	 * 
+	 * @param {Object} legend The legend object
+	 * @param {Object} item The series (this) or point
+	 */
+	drawLegendSymbol: function (legend, item) {
+		var radius = pInt(legend.itemStyle.fontSize) / 2;
+		
+		item.legendSymbol = this.chart.renderer.circle(
+			radius,
+			legend.baseline - radius,
+			radius
+		).attr({
+			zIndex: 3
+		}).add(item.legendGroup);
+		item.legendSymbol.isMarker = true;	
+		
+	},
+	
+	drawPoints: seriesTypes.column.prototype.drawPoints,
+	alignDataLabel: seriesTypes.column.prototype.alignDataLabel
+});
+
+/**
+ * Add logic to pad each axis with the amount of pixels
+ * necessary to avoid the bubbles to overflow.
+ */
+Axis.prototype.beforePadding = function () {
+	var axis = this,
+		axisLength = this.len,
+		chart = this.chart,
+		pxMin = 0, 
+		pxMax = axisLength,
+		isXAxis = this.isXAxis,
+		dataKey = isXAxis ? 'xData' : 'yData',
+		min = this.min,
+		extremes = {},
+		smallestSize = math.min(chart.plotWidth, chart.plotHeight),
+		zMin = Number.MAX_VALUE,
+		zMax = -Number.MAX_VALUE,
+		range = this.max - min,
+		transA = axisLength / range,
+		activeSeries = [];
+
+	// Handle padding on the second pass, or on redraw
+	if (this.tickPositions) {
+		each(this.series, function (series) {
+
+			var seriesOptions = series.options,
+				zData;
+
+			if (series.type === 'bubble' && series.visible) {
+
+				// Correction for #1673
+				axis.allowZoomOutside = true;
+
+				// Cache it
+				activeSeries.push(series);
+
+				if (isXAxis) { // because X axis is evaluated first
+				
+					// For each series, translate the size extremes to pixel values
+					each(['minSize', 'maxSize'], function (prop) {
+						var length = seriesOptions[prop],
+							isPercent = /%$/.test(length);
+						
+						length = pInt(length);
+						extremes[prop] = isPercent ?
+							smallestSize * length / 100 :
+							length;
+						
+					});
+					series.minPxSize = extremes.minSize;
+					
+					// Find the min and max Z
+					zData = series.zData;
+					if (zData.length) { // #1735
+						zMin = math.min(
+							zMin,
+							math.max(
+								arrayMin(zData), 
+								seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE
+							)
+						);
+						zMax = math.max(zMax, arrayMax(zData));
+					}
+				}
+			}
+		});
+
+		each(activeSeries, function (series) {
+
+			var data = series[dataKey],
+				i = data.length,
+				radius;
+
+			if (isXAxis) {
+				series.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize);
+			}
+			
+			if (range > 0) {
+				while (i--) {
+					radius = series.radii[i];
+					pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
+					pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
+				}
+			}
+		});
+		
+		if (activeSeries.length && range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) {
+			pxMax -= axisLength;
+			transA *= (axisLength + pxMin - pxMax) / axisLength;
+			this.min += pxMin / transA;
+			this.max += pxMax / transA;
+		}
+	}
+};
+
+/* ****************************************************************************
+ * End Bubble series code                                                     *
+ *****************************************************************************/
+/**
+ * Extensions for polar charts. Additionally, much of the geometry required for polar charts is
+ * gathered in RadialAxes.js.
+ * 
+ */
+
+var seriesProto = Series.prototype,
+	pointerProto = Highcharts.Pointer.prototype;
+
+
+
+/**
+ * Translate a point's plotX and plotY from the internal angle and radius measures to 
+ * true plotX, plotY coordinates
+ */
+seriesProto.toXY = function (point) {
+	var xy,
+		chart = this.chart,
+		plotX = point.plotX,
+		plotY = point.plotY;
+	
+	// Save rectangular plotX, plotY for later computation
+	point.rectPlotX = plotX;
+	point.rectPlotY = plotY;
+	
+	// Record the angle in degrees for use in tooltip
+	point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
+	
+	// Find the polar plotX and plotY
+	xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
+	point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
+	point.plotY = point.polarPlotY = xy.y - chart.plotTop;
+};
+
+/** 
+ * Order the tooltip points to get the mouse capture ranges correct. #1915. 
+ */
+seriesProto.orderTooltipPoints = function (points) {
+	if (this.chart.polar) {
+		points.sort(function (a, b) {
+			return a.clientX - b.clientX;
+		});
+
+		// Wrap mouse tracking around to capture movement on the segment to the left
+		// of the north point (#1469, #2093).
+		if (points[0]) {
+			points[0].wrappedClientX = points[0].clientX + 360;
+			points.push(points[0]);
+		}
+	}
+};
+
+
+/**
+ * Add some special init logic to areas and areasplines
+ */
+function initArea(proceed, chart, options) {
+	proceed.call(this, chart, options);
+	if (this.chart.polar) {
+		
+		/**
+		 * Overridden method to close a segment path. While in a cartesian plane the area 
+		 * goes down to the threshold, in the polar chart it goes to the center.
+		 */
+		this.closeSegment = function (path) {
+			var center = this.xAxis.center;
+			path.push(
+				'L',
+				center[0],
+				center[1]
+			);			
+		};
+		
+		// Instead of complicated logic to draw an area around the inner area in a stack,
+		// just draw it behind
+		this.closedStacks = true;
+	}
+}
+wrap(seriesTypes.area.prototype, 'init', initArea);
+wrap(seriesTypes.areaspline.prototype, 'init', initArea);
+		
+
+/**
+ * Overridden method for calculating a spline from one point to the next
+ */
+wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) {
+	
+	var ret,
+		smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;
+		denom = smoothing + 1,
+		plotX, 
+		plotY,
+		lastPoint,
+		nextPoint,
+		lastX,
+		lastY,
+		nextX,
+		nextY,
+		leftContX,
+		leftContY,
+		rightContX,
+		rightContY,
+		distanceLeftControlPoint,
+		distanceRightControlPoint,
+		leftContAngle,
+		rightContAngle,
+		jointAngle;
+		
+		
+	if (this.chart.polar) {
+		
+		plotX = point.plotX;
+		plotY = point.plotY;
+		lastPoint = segment[i - 1];
+		nextPoint = segment[i + 1];
+			
+		// Connect ends
+		if (this.connectEnds) {
+			if (!lastPoint) {
+				lastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected
+			}
+			if (!nextPoint) {
+				nextPoint = segment[1];
+			}	
+		}
+
+		// find control points
+		if (lastPoint && nextPoint) {
+		
+			lastX = lastPoint.plotX;
+			lastY = lastPoint.plotY;
+			nextX = nextPoint.plotX;
+			nextY = nextPoint.plotY;
+			leftContX = (smoothing * plotX + lastX) / denom;
+			leftContY = (smoothing * plotY + lastY) / denom;
+			rightContX = (smoothing * plotX + nextX) / denom;
+			rightContY = (smoothing * plotY + nextY) / denom;
+			distanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2));
+			distanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2));
+			leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
+			rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
+			jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
+				
+				
+			// Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle
+			if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
+				jointAngle -= Math.PI;
+			}
+			
+			// Find the corrected control points for a spline straight through the point
+			leftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint;
+			leftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint;
+			rightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint;
+			rightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint;
+			
+			// Record for drawing in next point
+			point.rightContX = rightContX;
+			point.rightContY = rightContY;
+
+		}
+		
+		
+		// moveTo or lineTo
+		if (!i) {
+			ret = ['M', plotX, plotY];
+		} else { // curve from last point to this
+			ret = [
+				'C',
+				lastPoint.rightContX || lastPoint.plotX,
+				lastPoint.rightContY || lastPoint.plotY,
+				leftContX || plotX,
+				leftContY || plotY,
+				plotX,
+				plotY
+			];
+			lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later
+		}
+		
+		
+	} else {
+		ret = proceed.call(this, segment, point, i);
+	}
+	return ret;
+});
+
+/**
+ * Extend translate. The plotX and plotY values are computed as if the polar chart were a
+ * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from
+ * center. 
+ */
+wrap(seriesProto, 'translate', function (proceed) {
+		
+	// Run uber method
+	proceed.call(this);
+	
+	// Postprocess plot coordinates
+	if (this.chart.polar && !this.preventPostTranslate) {
+		var points = this.points,
+			i = points.length;
+		while (i--) {
+			// Translate plotX, plotY from angle and radius to true plot coordinates
+			this.toXY(points[i]);
+		}
+	}
+});
+
+/** 
+ * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in 
+ * line-like series.
+ */
+wrap(seriesProto, 'getSegmentPath', function (proceed, segment) {
+		
+	var points = this.points;
+	
+	// Connect the path
+	if (this.chart.polar && this.options.connectEnds !== false && 
+			segment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) {
+		this.connectEnds = true; // re-used in splines
+		segment = [].concat(segment, [points[0]]);
+	}
+	
+	// Run uber method
+	return proceed.call(this, segment);
+	
+});
+
+
+function polarAnimate(proceed, init) {
+	var chart = this.chart,
+		animation = this.options.animation,
+		group = this.group,
+		markerGroup = this.markerGroup,
+		center = this.xAxis.center,
+		plotLeft = chart.plotLeft,
+		plotTop = chart.plotTop,
+		attribs;
+
+	// Specific animation for polar charts
+	if (chart.polar) {
+		
+		// Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation
+		// would be so slow it would't matter.
+		if (chart.renderer.isSVG) {
+
+			if (animation === true) {
+				animation = {};
+			}
+	
+			// Initialize the animation
+			if (init) {
+				
+				// Scale down the group and place it in the center
+				attribs = {
+					translateX: center[0] + plotLeft,
+					translateY: center[1] + plotTop,
+					scaleX: 0.001, // #1499
+					scaleY: 0.001
+				};
+					
+				group.attr(attribs);
+				if (markerGroup) {
+					markerGroup.attrSetters = group.attrSetters;
+					markerGroup.attr(attribs);
+				}
+				
+			// Run the animation
+			} else {
+				attribs = {
+					translateX: plotLeft,
+					translateY: plotTop,
+					scaleX: 1,
+					scaleY: 1
+				};
+				group.animate(attribs, animation);
+				if (markerGroup) {
+					markerGroup.animate(attribs, animation);
+				}
+				
+				// Delete this function to allow it only once
+				this.animate = null;
+			}
+		}
+	
+	// For non-polar charts, revert to the basic animation
+	} else {
+		proceed.call(this, init);
+	} 
+}
+
+// Define the animate method for both regular series and column series and their derivatives
+wrap(seriesProto, 'animate', polarAnimate);
+wrap(colProto, 'animate', polarAnimate);
+
+
+/**
+ * Throw in a couple of properties to let setTooltipPoints know we're indexing the points
+ * in degrees (0-360), not plot pixel width.
+ */
+wrap(seriesProto, 'setTooltipPoints', function (proceed, renew) {
+		
+	if (this.chart.polar) {
+		extend(this.xAxis, {
+			tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array
+		});	
+	}
+	
+	// Run uber method
+	return proceed.call(this, renew);
+});
+
+
+/**
+ * Extend the column prototype's translate method
+ */
+wrap(colProto, 'translate', function (proceed) {
+		
+	var xAxis = this.xAxis,
+		len = this.yAxis.len,
+		center = xAxis.center,
+		startAngleRad = xAxis.startAngleRad,
+		renderer = this.chart.renderer,
+		start,
+		points,
+		point,
+		i;
+	
+	this.preventPostTranslate = true;
+	
+	// Run uber method
+	proceed.call(this);
+	
+	// Postprocess plot coordinates
+	if (xAxis.isRadial) {
+		points = this.points;
+		i = points.length;
+		while (i--) {
+			point = points[i];
+			start = point.barX + startAngleRad;
+			point.shapeType = 'path';
+			point.shapeArgs = {
+				d: renderer.symbols.arc(
+					center[0],
+					center[1],
+					len - point.plotY,
+					null, 
+					{
+						start: start,
+						end: start + point.pointWidth,
+						innerR: len - pick(point.yBottom, len)
+					}
+				)
+			};
+			this.toXY(point); // provide correct plotX, plotY for tooltip
+		}
+	}
+});
+
+
+/**
+ * Align column data labels outside the columns. #1199.
+ */
+wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) {
+	
+	if (this.chart.polar) {
+		var angle = point.rectPlotX / Math.PI * 180,
+			align,
+			verticalAlign;
+		
+		// Align nicely outside the perimeter of the columns
+		if (options.align === null) {
+			if (angle > 20 && angle < 160) {
+				align = 'left'; // right hemisphere
+			} else if (angle > 200 && angle < 340) {
+				align = 'right'; // left hemisphere
+			} else {
+				align = 'center'; // top or bottom
+			}
+			options.align = align;
+		}
+		if (options.verticalAlign === null) {
+			if (angle < 45 || angle > 315) {
+				verticalAlign = 'bottom'; // top part
+			} else if (angle > 135 && angle < 225) {
+				verticalAlign = 'top'; // bottom part
+			} else {
+				verticalAlign = 'middle'; // left or right
+			}
+			options.verticalAlign = verticalAlign;
+		}
+		
+		seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
+	} else {
+		proceed.call(this, point, dataLabel, options, alignTo, isNew);
+	}
+	
+});
+
+/**
+ * Extend the mouse tracker to return the tooltip position index in terms of
+ * degrees rather than pixels
+ */
+wrap(pointerProto, 'getIndex', function (proceed, e) {
+	var ret,
+		chart = this.chart,
+		center,
+		x,
+		y;
+	
+	if (chart.polar) {
+		center = chart.xAxis[0].center;
+		x = e.chartX - center[0] - chart.plotLeft;
+		y = e.chartY - center[1] - chart.plotTop;
+		
+		ret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180);
+	
+	} else {
+	
+		// Run uber method
+		ret = proceed.call(this, e);
+	}
+	return ret;
+});
+
+/**
+ * Extend getCoordinates to prepare for polar axis values
+ */
+wrap(pointerProto, 'getCoordinates', function (proceed, e) {
+	var chart = this.chart,
+		ret = {
+			xAxis: [],
+			yAxis: []
+		};
+	
+	if (chart.polar) {	
+
+		each(chart.axes, function (axis) {
+			var isXAxis = axis.isXAxis,
+				center = axis.center,
+				x = e.chartX - center[0] - chart.plotLeft,
+				y = e.chartY - center[1] - chart.plotTop;
+			
+			ret[isXAxis ? 'xAxis' : 'yAxis'].push({
+				axis: axis,
+				value: axis.translate(
+					isXAxis ?
+						Math.PI - Math.atan2(x, y) : // angle 
+						Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center
+					true
+				)
+			});
+		});
+		
+	} else {
+		ret = proceed.call(this, e);
+	}
+	
+	return ret;
+});
+}(Highcharts));

--
Gitblit v1.8.0