← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands-website/update_jvascript into lp:widelands-website

 

kaputtnik has proposed merging lp:~widelands-dev/widelands-website/update_jvascript into lp:widelands-website.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands-website/update_jvascript/+merge/331244

Update jquery from version 1.6.2 to 3.2.1

This needs adjustments to some other javascript files. To find incompatible/deprecated commands  jquery-migrate is loaded: It shows warnings in the browsers console. It has to be removed in production.

Because Highcharts (used for polls) didn't work with the new jquery library, it is now updated to version 5, adjusted and i did some small beautification (e.g. labels are not in one row anymore like here for the left label: https://wl.widelands.org/poll/12/).
Highcharts throws an error shown in browsers console, but it works. The description of the error: https://www.highcharts.com/errors/16 Don't know how to fix this...

Deleted some js files which i believe were forgotten to remove in the past.

I am busy today and tomorrow, but next week i have a lot of time.
-- 
The attached diff has been truncated due to its size.
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/update_jvascript into lp:widelands-website.
=== modified file 'media/js/disableOnSubmit.js'
--- media/js/disableOnSubmit.js	2011-07-06 23:31:10 +0000
+++ media/js/disableOnSubmit.js	2017-09-23 09:21:04 +0000
@@ -6,11 +6,11 @@
  */
 $.fn.disableOnSubmit = function(disableList){
 	
-	if(disableList == null){var $list = 'input[type=submit],input[type=button],input[type=reset],button';}
+	if(disableList === null){var $list = 'input[type=submit],input[type=button],input[type=reset],button';}
 	else{var $list = disableList;}
 	
 	// Makes sure button is enabled at start
-	$(this).find($list).removeAttr('disabled');
+	$(this).find($list).prop("disabled", true);
 	
 	$(this).submit(function(){$(this).find($list).attr('disabled','disabled');});
 	return this;

=== modified file 'media/js/encyclopedia.js'
--- media/js/encyclopedia.js	2017-03-15 20:59:33 +0000
+++ media/js/encyclopedia.js	2017-09-23 09:21:04 +0000
@@ -1,6 +1,5 @@
 $(document).ready(function() {
-    var elem = document.getElementById('apply_filter');
-    elem.addEventListener('click', set_display);
+    $('#apply_filter').on('click', set_display);
     // Find names of checkboxes:
     checkb_names = get_input_names(); 
     // Initialize after reload, e.g. pressing F5:
@@ -8,7 +7,7 @@
 
     // Smooth scrolling, taken from:
     // http://stackoverflow.com/a/18795112
-    $('a[href*=#]').click(function(event){
+    $("a[href*='#']").click(function(event){
         $('html, body').animate({
             scrollTop: $( $.attr(this, 'href') ).offset().top
         }, 500);

=== removed directory 'media/js/highcharts_219'
=== removed directory 'media/js/highcharts_219/adapters'
=== removed file 'media/js/highcharts_219/adapters/mootools-adapter.js'
--- media/js/highcharts_219/adapters/mootools-adapter.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/adapters/mootools-adapter.js	1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-/*
- Highcharts JS v2.1.9 (2011-11-11)
- MooTools adapter
-
- (c) 2010-2011 Torstein H?nsi
-
- License: www.highcharts.com/license
-*/
-(function(){var e=window,h=e.MooTools.version.substring(0,3),i=h==="1.2"||h==="1.1",m=i||h==="1.3",j=e.$extend||function(){return Object.append.apply(Object,arguments)};e.HighchartsAdapter={init:function(a){var b=Fx.prototype,c=b.start,d=Fx.Morph.prototype,g=d.compute;b.start=function(f){var k=this.element;if(f.d)this.paths=a.init(k,k.d,this.toD);c.apply(this,arguments);return this};d.compute=function(f,k,n){var l=this.paths;if(l)this.element.attr("d",a.step(l[0],l[1],n,this.toD));else return g.apply(this,
-arguments)}},animate:function(a,b,c){var d=a.attr,g=c&&c.complete;if(d&&!a.setStyle){a.getStyle=a.attr;a.setStyle=function(){var f=arguments;a.attr.call(a,f[0],f[1][0])};a.$family=a.uid=true}e.HighchartsAdapter.stop(a);c=new Fx.Morph(d?a:$(a),j({transition:Fx.Transitions.Quad.easeInOut},c));if(b.d)c.toD=b.d;g&&c.addEvent("complete",g);c.start(b);a.fx=c},each:function(a,b){return i?$each(a,b):a.each(b)},map:function(a,b){return a.map(b)},grep:function(a,b){return a.filter(b)},merge:function(){var a=
-arguments,b=[{}],c=a.length;if(i)a=$merge.apply(null,a);else{for(;c--;)if(typeof a[c]!=="boolean")b[c+1]=a[c];a=Object.merge.apply(Object,b)}return a},extendWithEvents:function(a){a.addEvent||(a.nodeName?$(a):j(a,new Events))},addEvent:function(a,b,c){if(typeof b==="string"){if(b==="unload")b="beforeunload";e.HighchartsAdapter.extendWithEvents(a);a.addEvent(b,c)}},removeEvent:function(a,b,c){if(typeof a!=="string"){e.HighchartsAdapter.extendWithEvents(a);if(b){if(b==="unload")b="beforeunload";c?a.removeEvent(b,
-c):a.removeEvents(b)}else a.removeEvents()}},fireEvent:function(a,b,c,d){b={type:b,target:a};b=m?new Event(b):new DOMEvent(b);b=j(b,c);b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)},stop:function(a){a.fx&&a.fx.cancel()}}})();

=== removed file 'media/js/highcharts_219/adapters/mootools-adapter.src.js'
--- media/js/highcharts_219/adapters/mootools-adapter.src.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/adapters/mootools-adapter.src.js	1970-01-01 00:00:00 +0000
@@ -1,264 +0,0 @@
-/**
- * @license Highcharts JS v2.1.9 (2011-11-11)
- * MooTools adapter
- *
- * (c) 2010-2011 Torstein Hønsi
- *
- * License: www.highcharts.com/license
- */
-
-// JSLint options:
-/*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */
-
-(function () {
-
-var win = window,
-	mooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number
-	legacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not.
-	legacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent.
-	$extend = win.$extend || function () {
-		return Object.append.apply(Object, arguments);
-	};
-
-win.HighchartsAdapter = {
-	/**
-	 * Initialize the adapter. This is run once as Highcharts is first run.
-	 * @param {Object} pathAnim The helper object to do animations across adapters.
-	 */
-	init: function (pathAnim) {
-		var fxProto = Fx.prototype,
-			fxStart = fxProto.start,
-			morphProto = Fx.Morph.prototype,
-			morphCompute = morphProto.compute;
-
-		// override Fx.start to allow animation of SVG element wrappers
-		/*jslint unparam: true*//* allow unused parameters in fx functions */
-		fxProto.start = function (from, to) {
-			var fx = this,
-				elem = fx.element;
-
-			// special for animating paths
-			if (from.d) {
-				//this.fromD = this.element.d.split(' ');
-				fx.paths = pathAnim.init(
-					elem,
-					elem.d,
-					fx.toD
-				);
-			}
-			fxStart.apply(fx, arguments);
-
-			return this; // chainable
-		};
-
-		// override Fx.step to allow animation of SVG element wrappers
-		morphProto.compute = function (from, to, delta) {
-			var fx = this,
-				paths = fx.paths;
-
-			if (paths) {
-				fx.element.attr(
-					'd',
-					pathAnim.step(paths[0], paths[1], delta, fx.toD)
-				);
-			} else {
-				return morphCompute.apply(fx, arguments);
-			}
-		};
-		/*jslint unparam: false*/
-	},
-
-	/**
-	 * Animate a HTML element or SVG element wrapper
-	 * @param {Object} el
-	 * @param {Object} params
-	 * @param {Object} options jQuery-like animation options: duration, easing, callback
-	 */
-	animate: function (el, params, options) {
-		var isSVGElement = el.attr,
-			effect,
-			complete = options && options.complete;
-
-		if (isSVGElement && !el.setStyle) {
-			// add setStyle and getStyle methods for internal use in Moo
-			el.getStyle = el.attr;
-			el.setStyle = function () { // property value is given as array in Moo - break it down
-				var args = arguments;
-				el.attr.call(el, args[0], args[1][0]);
-			};
-			// dirty hack to trick Moo into handling el as an element wrapper
-			el.$family = el.uid = true;
-		}
-
-		// stop running animations
-		win.HighchartsAdapter.stop(el);
-
-		// define and run the effect
-		effect = new Fx.Morph(
-			isSVGElement ? el : $(el),
-			$extend({
-				transition: Fx.Transitions.Quad.easeInOut
-			}, options)
-		);
-
-		// special treatment for paths
-		if (params.d) {
-			effect.toD = params.d;
-		}
-
-		// jQuery-like events
-		if (complete) {
-			effect.addEvent('complete', complete);
-		}
-
-		// run
-		effect.start(params);
-
-		// record for use in stop method
-		el.fx = effect;
-	},
-
-	/**
-	 * MooTool's each function
-	 *
-	 */
-	each: function (arr, fn) {
-		return legacy ?
-			$each(arr, fn) :
-			arr.each(fn);
-	},
-
-	/**
-	 * Map an array
-	 * @param {Array} arr
-	 * @param {Function} fn
-	 */
-	map: function (arr, fn) {
-		return arr.map(fn);
-	},
-
-	/**
-	 * Grep or filter an array
-	 * @param {Array} arr
-	 * @param {Function} fn
-	 */
-	grep: function (arr, fn) {
-		return arr.filter(fn);
-	},
-
-	/**
-	 * Deep merge two objects and return a third
-	 */
-	merge: function () {
-		var args = arguments,
-			args13 = [{}], // MooTools 1.3+
-			i = args.length,
-			ret;
-
-		if (legacy) {
-			ret = $merge.apply(null, args);
-		} else {
-			while (i--) {
-				// Boolean argumens should not be merged.
-				// JQuery explicitly skips this, so we do it here as well.
-				if (typeof args[i] !== 'boolean') {
-					args13[i + 1] = args[i];
-				}
-			}
-			ret = Object.merge.apply(Object, args13);
-		}
-
-		return ret;
-	},
-
-	/**
-	 * Extends an object with Events, if its not done
-	 */
-	extendWithEvents: function (el) {
-		// if the addEvent method is not defined, el is a custom Highcharts object
-		// like series or point
-		if (!el.addEvent) {
-			if (el.nodeName) {
-				el = $(el); // a dynamically generated node
-			} else {
-				$extend(el, new Events()); // a custom object
-			}
-		}
-	},
-
-	/**
-	 * Add an event listener
-	 * @param {Object} el HTML element or custom object
-	 * @param {String} type Event type
-	 * @param {Function} fn Event handler
-	 */
-	addEvent: function (el, type, fn) {
-		if (typeof type === 'string') { // chart broke due to el being string, type function
-
-			if (type === 'unload') { // Moo self destructs before custom unload events
-				type = 'beforeunload';
-			}
-
-			win.HighchartsAdapter.extendWithEvents(el);
-
-			el.addEvent(type, fn);
-		}
-	},
-
-	removeEvent: function (el, type, fn) {
-		if (typeof el === 'string') {
-			// el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out.
-			return;
-		}
-		win.HighchartsAdapter.extendWithEvents(el);
-		if (type) {
-			if (type === 'unload') { // Moo self destructs before custom unload events
-				type = 'beforeunload';
-			}
-
-			if (fn) {
-				el.removeEvent(type, fn);
-			} else {
-				el.removeEvents(type);
-			}
-		} else {
-			el.removeEvents();
-		}
-	},
-
-	fireEvent: function (el, event, eventArguments, defaultFunction) {
-		var eventArgs = {
-			type: event,
-			target: el
-		};
-		// create an event object that keeps all functions
-		event = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs);
-		event = $extend(event, eventArguments);
-		// override the preventDefault function to be able to use
-		// this for custom events
-		event.preventDefault = function () {
-			defaultFunction = null;
-		};
-		// if fireEvent is not available on the object, there hasn't been added
-		// any events to it above
-		if (el.fireEvent) {
-			el.fireEvent(event.type, event);
-		}
-
-		// fire the default if it is passed and it is not prevented above
-		if (defaultFunction) {
-			defaultFunction(event);
-		}
-	},
-
-	/**
-	 * Stop running animations on the object
-	 */
-	stop: function (el) {
-		if (el.fx) {
-			el.fx.cancel();
-		}
-	}
-};
-
-}());

=== removed file 'media/js/highcharts_219/adapters/prototype-adapter.js'
--- media/js/highcharts_219/adapters/prototype-adapter.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/adapters/prototype-adapter.js	1970-01-01 00:00:00 +0000
@@ -1,15 +0,0 @@
-/*
- Highcharts JS v2.1.9 (2011-11-11)
- Prototype adapter
-
- @author Michael Nelson, Torstein H?nsi.
-
- Feel free to use and modify this script.
- Highcharts license: www.highcharts.com/license.
-*/
-var HighchartsAdapter=function(){var g=typeof Effect!=="undefined";return{init:function(c){if(g)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(a,b,d,e){var f;this.element=a;this.key=b;f=a.attr(b);if(b==="d"){this.paths=c.init(a,a.d,d);this.toD=d;f=0;d=1}this.start(Object.extend(e||{},{from:f,to:d,attribute:b}))},setup:function(){HighchartsAdapter._extend(this.element);if(!this.element._highchart_animation)this.element._highchart_animation={};this.element._highchart_animation[this.key]=
-this},update:function(a){var b=this.paths;if(b)a=c.step(b[0],b[1],a,this.toD);this.element.attr(this.options.attribute,a)},finish:function(){delete this.element._highchart_animation[this.key]}})},addNS:function(c){var a=/^(?:click|mouse(?:down|up|over|move|out))$/;return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(c)||a.test(c)?c:"h:"+c},addEvent:function(c,a,b){if(c.addEventListener||c.attachEvent)Event.observe($(c),HighchartsAdapter.addNS(a),b);else{HighchartsAdapter._extend(c);
-c._highcharts_observe(a,b)}},animate:function(c,a,b){var d;b=b||{};b.delay=0;b.duration=(b.duration||500)/1E3;if(g)for(d in a)new Effect.HighchartsTransition($(c),d,a[d],b);else for(d in a)c.attr(d,a[d]);if(!c.attr)throw"Todo: implement animate DOM objects";},stop:function(c){var a;if(c._highcharts_extended&&c._highchart_animation)for(a in c._highchart_animation)c._highchart_animation[a].cancel()},each:function(c,a){$A(c).each(a)},fireEvent:function(c,a,b,d){if(c.fire)c.fire(HighchartsAdapter.addNS(a),
-b);else if(c._highcharts_extended){b=b||{};c._highcharts_fire(a,b)}if(b&&b.defaultPrevented)d=null;d&&d(b)},removeEvent:function(c,a,b){if($(c).stopObserving){if(a)a=HighchartsAdapter.addNS(a);$(c).stopObserving(a,b)}if(window===c)Event.stopObserving(c,a,b);else{HighchartsAdapter._extend(c);c._highcharts_stop_observing(a,b)}},grep:function(c,a){return c.findAll(a)},map:function(c,a){return c.map(a)},merge:function(){function c(a,b){var d,e;for(e in b){d=b[e];a[e]=d&&typeof d==="object"&&d.constructor!==
-Array&&typeof d.nodeType!=="number"?c(a[e]||{},d):b[e]}return a}return function(){var a=arguments,b,d={};for(b=0;b<a.length;b++)d=c(d,a[b]);return d}.apply(this,arguments)},_extend:function(c){c._highcharts_extended||Object.extend(c,{_highchart_events:{},_highchart_animation:null,_highcharts_extended:true,_highcharts_observe:function(a,b){this._highchart_events[a]=[this._highchart_events[a],b].compact().flatten()},_highcharts_stop_observing:function(a,b){if(a)if(b)this._highchart_events[a]=[this._highchart_events[a]].compact().flatten().without(b);
-else delete this._highchart_events[a];else this._highchart_events={}},_highcharts_fire:function(a,b){(this._highchart_events[a]||[]).each(function(d){if(!b.stopped){b.preventDefault=function(){b.defaultPrevented=true};d.bind(this)(b)===false&&b.preventDefault()}}.bind(this))}})}}}();

=== removed file 'media/js/highcharts_219/adapters/prototype-adapter.src.js'
--- media/js/highcharts_219/adapters/prototype-adapter.src.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/adapters/prototype-adapter.src.js	1970-01-01 00:00:00 +0000
@@ -1,331 +0,0 @@
-/**
- * @license Highcharts JS v2.1.9 (2011-11-11)
- * Prototype adapter
- *
- * @author Michael Nelson, Torstein Hønsi.
- *
- * Feel free to use and modify this script.
- * Highcharts license: www.highcharts.com/license.
- */
-
-/*
- * Known issues:
- *    - Some grid lines land in wrong position - http://jsfiddle.net/highcharts/jaRhY/28
- */
-
-// JSLint options:
-/*global Effect, Class, Event, $, $A */
-
-// Adapter interface between prototype and the Highcharts charting library
-var HighchartsAdapter = (function () {
-
-var hasEffect = typeof Effect !== 'undefined';
-
-return {
-
-	/**
-	 * Initialize the adapter. This is run once as Highcharts is first run.
-	 * @param {Object} pathAnim The helper object to do animations across adapters.
-	 */
-	init: function (pathAnim) {
-		if (hasEffect) {
-			/**
-			 * Animation for Highcharts SVG element wrappers only
-			 * @param {Object} element
-			 * @param {Object} attribute
-			 * @param {Object} to
-			 * @param {Object} options
-			 */
-			Effect.HighchartsTransition = Class.create(Effect.Base, {
-				initialize: function (element, attr, to, options) {
-					var from,
-						opts;
-
-					this.element = element;
-					this.key = attr;
-					from = element.attr(attr);
-
-					// special treatment for paths
-					if (attr === 'd') {
-						this.paths = pathAnim.init(
-							element,
-							element.d,
-							to
-						);
-						this.toD = to;
-
-
-						// fake values in order to read relative position as a float in update
-						from = 0;
-						to = 1;
-					}
-
-					opts = Object.extend((options || {}), {
-						from: from,
-						to: to,
-						attribute: attr
-					});
-					this.start(opts);
-				},
-				setup: function () {
-					HighchartsAdapter._extend(this.element);
-					// If this is the first animation on this object, create the _highcharts_animation helper that
-					// contain pointers to the animation objects.
-					if (!this.element._highchart_animation) {
-						this.element._highchart_animation = {};
-					}
-
-					// Store a reference to this animation instance.
-					this.element._highchart_animation[this.key] = this;
-				},
-				update: function (position) {
-					var paths = this.paths;
-
-					if (paths) {
-						position = pathAnim.step(paths[0], paths[1], position, this.toD);
-					}
-
-					this.element.attr(this.options.attribute, position);
-				},
-				finish: function () {
-					// Delete the property that holds this animation now that it is finished.
-					// Both canceled animations and complete ones gets a 'finish' call.
-					delete this.element._highchart_animation[this.key];
-				}
-			});
-		}
-	},
-
-	/**
-	 * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of
-	 * events that are not recognized as native.
-	 */
-	addNS: function (eventName) {
-		var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
-			MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/;
-		return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ?
-			eventName :
-			'h:' + eventName;
-	},
-
-	// el needs an event to be attached. el is not necessarily a dom element
-	addEvent: function (el, event, fn) {
-		if (el.addEventListener || el.attachEvent) {
-			Event.observe($(el), HighchartsAdapter.addNS(event), fn);
-
-		} else {
-			HighchartsAdapter._extend(el);
-			el._highcharts_observe(event, fn);
-		}
-	},
-
-	// motion makes things pretty. use it if effects is loaded, if not... still get to the end result.
-	animate: function (el, params, options) {
-		var key,
-			fx;
-
-		// default options
-		options = options || {};
-		options.delay = 0;
-		options.duration = (options.duration || 500) / 1000;
-
-		// animate wrappers and DOM elements
-		if (hasEffect) {
-			for (key in params) {
-				// The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object
-				// on the element itself so its not really lost.
-				fx = new Effect.HighchartsTransition($(el), key, params[key], options);
-			}
-		} else {
-			for (key in params) {
-				el.attr(key, params[key]);
-			}
-		}
-
-		if (!el.attr) {
-			throw 'Todo: implement animate DOM objects';
-		}
-	},
-
-	// this only occurs in higcharts 2.0+
-	stop: function (el) {
-		var key;
-		if (el._highcharts_extended && el._highchart_animation) {
-			for (key in el._highchart_animation) {
-				// Cancel the animation
-				// The 'finish' function in the Effect object will remove the reference
-				el._highchart_animation[key].cancel();
-			}
-		}
-	},
-
-	// um.. each
-	each: function (arr, fn) {
-		$A(arr).each(fn);
-	},
-
-	// fire an event based on an event name (event) and an object (el).
-	// again, el may not be a dom element
-	fireEvent: function (el, event, eventArguments, defaultFunction) {
-		if (el.fire) {
-			el.fire(HighchartsAdapter.addNS(event), eventArguments);
-		} else if (el._highcharts_extended) {
-			eventArguments = eventArguments || {};
-			el._highcharts_fire(event, eventArguments);
-		}
-
-		if (eventArguments && eventArguments.defaultPrevented) {
-			defaultFunction = null;
-		}
-
-		if (defaultFunction) {
-			defaultFunction(eventArguments);
-		}
-	},
-
-	removeEvent: function (el, event, handler) {
-		if ($(el).stopObserving) {
-			if (event) {
-				event = HighchartsAdapter.addNS(event);
-			}
-			$(el).stopObserving(event, handler);
-		} if (window === el) {
-			Event.stopObserving(el, event, handler);
-		} else {
-			HighchartsAdapter._extend(el);
-			el._highcharts_stop_observing(event, handler);
-		}
-	},
-
-	// um, grep
-	grep: function (arr, fn) {
-		return arr.findAll(fn);
-	},
-
-	// um, map
-	map: function (arr, fn) {
-		return arr.map(fn);
-	},
-
-	// deep merge. merge({a : 'a', b : {b1 : 'b1', b2 : 'b2'}}, {b : {b2 : 'b2_prime'}, c : 'c'}) => {a : 'a', b : {b1 : 'b1', b2 : 'b2_prime'}, c : 'c'}
-	/*merge: function(){
-		function doCopy(copy, original) {
-			var value,
-				key,
-				undef,
-				nil,
-				same,
-				obj,
-				arr,
-				node;
-
-			for (key in original) {
-				value = original[key];
-				undef = typeof(value) === 'undefined';
-				nil = value === null;
-				same = original === copy[key];
-
-				if (undef || nil || same) {
-					continue;
-				}
-
-				obj = typeof(value) === 'object';
-				arr = value && obj && value.constructor == Array;
-				node = !!value.nodeType;
-
-				if (obj && !arr && !node) {
-					copy[key] = doCopy(typeof copy[key] == 'object' ? copy[key] : {}, value);
-				}
-				else {
-					copy[key] = original[key];
-				}
-			}
-			return copy;
-		}
-
-		var args = arguments, retVal = {};
-
-		for (var i = 0; i < args.length; i++) {
-			retVal = doCopy(retVal, args[i]);
-		}
-
-		return retVal;
-	},*/
-	merge: function () { // the built-in prototype merge function doesn't do deep copy
-		function doCopy(copy, original) {
-			var value, key;
-
-			for (key in original) {
-				value = original[key];
-				if (value && typeof value === 'object' && value.constructor !== Array &&
-						typeof value.nodeType !== 'number') {
-					copy[key] = doCopy(copy[key] || {}, value); // copy
-
-				} else {
-					copy[key] = original[key];
-				}
-			}
-			return copy;
-		}
-
-		function merge() {
-			var args = arguments,
-				i,
-				retVal = {};
-
-			for (i = 0; i < args.length; i++) {
-				retVal = doCopy(retVal, args[i]);
-
-			}
-			return retVal;
-		}
-
-		return merge.apply(this, arguments);
-	},
-
-	// extend an object to handle highchart events (highchart objects, not svg elements).
-	// this is a very simple way of handling events but whatever, it works (i think)
-	_extend: function (object) {
-		if (!object._highcharts_extended) {
-			Object.extend(object, {
-				_highchart_events: {},
-				_highchart_animation: null,
-				_highcharts_extended: true,
-				_highcharts_observe: function (name, fn) {
-					this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();
-				},
-				_highcharts_stop_observing: function (name, fn) {
-					if (name) {
-						if (fn) {
-							this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);
-						} else {
-							delete this._highchart_events[name];
-						}
-					} else {
-						this._highchart_events = {};
-					}
-				},
-				_highcharts_fire: function (name, args) {
-					(this._highchart_events[name] || []).each(function (fn) {
-						// args is never null here
-						if (args.stopped) {
-							return; // "throw $break" wasn't working. i think because of the scope of 'this'.
-						}
-
-						// Attach a simple preventDefault function to skip default handler if called
-						args.preventDefault = function () {
-							args.defaultPrevented = true;
-						};
-
-						// If the event handler return false, prevent the default handler from executing
-						if (fn.bind(this)(args) === false) {
-							args.preventDefault();
-						}
-					}
-.bind(this));
-				}
-			});
-		}
-	}
-};
-}());

=== removed file 'media/js/highcharts_219/highcharts.js'
--- media/js/highcharts_219/highcharts.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/highcharts.js	1970-01-01 00:00:00 +0000
@@ -1,176 +0,0 @@
-/*
- Highcharts JS v2.1.9 (2011-11-11)
-
- (c) 2009-2011 Torstein H?nsi
-
- License: www.highcharts.com/license
-*/
-(function(){function sa(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function ja(a,b){return parseInt(a,b||10)}function Sb(a){return typeof a==="string"}function Nb(a){return typeof a==="object"}function lc(a){return typeof a==="number"}function mc(a){return Fa.log(a)/Fa.LN10}function nc(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function K(a){return a!==Wa&&a!==null}function Ga(a,b,c){var d,e;if(Sb(b))if(K(c))a.setAttribute(b,c);else{if(a&&a.getAttribute)e=a.getAttribute(b)}else if(K(b)&&
-Nb(b))for(d in b)a.setAttribute(d,b[d]);return e}function zc(a){return Object.prototype.toString.call(a)==="[object Array]"?a:[a]}function A(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++){c=a[b];if(typeof c!=="undefined"&&c!==null)return c}}function Ja(a,b){if(Pc)if(b&&b.opacity!==Wa)b.filter="alpha(opacity="+b.opacity*100+")";sa(a.style,b)}function hb(a,b,c,d,e){a=ua.createElement(a);b&&sa(a,b);e&&Ja(a,{padding:0,border:jb,margin:0});c&&Ja(a,c);d&&d.appendChild(a);return a}function yb(a,b){var c=
-function(){};c.prototype=new a;sa(c.prototype,b);return c}function Ed(a,b,c,d){var e=Xa.lang;a=a;var f=isNaN(b=bb(b))?2:b;b=c===undefined?e.decimalPoint:c;d=d===undefined?e.thousandsSep:d;e=a<0?"-":"";c=String(ja(a=bb(+a||0).toFixed(f)));var g=c.length>3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+bb(a-c).toFixed(f).slice(2):"")}function Fd(a){var b={left:a.offsetLeft,top:a.offsetTop};for(a=a.offsetParent;a;){b.left+=a.offsetLeft;b.top+=a.offsetTop;
-if(a!==ua.body&&a!==ua.documentElement){b.left-=a.scrollLeft;b.top-=a.scrollTop}a=a.offsetParent}return b}function Gd(){this.symbol=this.color=0}function fe(a,b,c,d,e,f,g){var h=g.x;g=g.y;var i=h-a+c-25,j=g-b+d+10,m;if(i<7)i=c+h+15;if(i+a>c+e){i-=i+a-(c+e);j-=b;m=true}if(j<5){j=5;if(m&&g>=j&&g<=j+b)j=g+b-5}else if(j+b>d+f)j=d+f-b-5;return{x:i,y:j}}function Hd(a,b){var c=a.length,d;for(d=0;d<c;d++)a[d].ss_i=d;a.sort(function(e,f){var g=b(e,f);return g===0?e.ss_i-f.ss_i:g});for(d=0;d<c;d++)delete a[d].ss_i}
-function Ac(a){for(var b in a){a[b]&&a[b].destroy&&a[b].destroy();delete a[b]}}function oc(a,b){Bc=A(a,b.animation)}function Id(){var a=Xa.global.useUTC;Qc=a?Date.UTC:function(b,c,d,e,f,g){return(new Date(b,c,A(d,1),A(e,0),A(f,0),A(g,0))).getTime()};id=a?"getUTCMinutes":"getMinutes";jd=a?"getUTCHours":"getHours";kd=a?"getUTCDay":"getDay";Cc=a?"getUTCDate":"getDate";Rc=a?"getUTCMonth":"getMonth";Sc=a?"getUTCFullYear":"getFullYear";Jd=a?"setUTCMinutes":"setMinutes";Kd=a?"setUTCHours":"setHours";ld=
-a?"setUTCDate":"setDate";Ld=a?"setUTCMonth":"setMonth";Md=a?"setUTCFullYear":"setFullYear"}function pc(a){Tc||(Tc=hb(Tb));a&&Tc.appendChild(a);Tc.innerHTML=""}function Uc(){}function Nd(a,b){function c(p){function q(k,n){this.pos=k;this.minor=n;this.isNew=true;n||this.addLabel()}function w(k){if(k){this.options=k;this.id=k.id}return this}function x(k,n,t,r){this.isNegative=n;this.options=k;this.x=t;this.stack=r;this.alignOptions={align:k.align||(va?n?"left":"right":"center"),verticalAlign:k.verticalAlign||
-(va?"middle":n?"bottom":"top"),y:A(k.y,va?4:n?14:-6),x:A(k.x,va?n?-6:6:0)};this.textAlign=k.textAlign||(va?n?"right":"left":"center")}function V(){var k=[],n=[],t;pa=wa=null;zb=[];u(Ha,function(r){t=false;u(["xAxis","yAxis"],function(F){if(r.isCartesian&&(F==="xAxis"&&xa||F==="yAxis"&&!xa)&&(r.options[F]===o.index||r.options[F]===Wa&&o.index===0)){r[F]=I;zb.push(r);t=true}});if(!r.visible&&z.ignoreHiddenSeries)t=false;if(t){var J,E,Q,fa,ka,$;if(!xa){J=r.options.stacking;Vc=J==="percent";if(J){ka=
-r.options.stack;fa=r.type+A(ka,"");$="-"+fa;r.stackKey=fa;E=k[fa]||[];k[fa]=E;Q=n[$]||[];n[$]=Q}if(Vc){pa=0;wa=99}}if(r.isCartesian){u(r.data,function(F){var O=F.x,S=F.y,aa=S<0,Eb=aa?Q:E,kb=aa?$:fa;if(pa===null)pa=wa=F[qa];if(xa)if(O>wa)wa=O;else{if(O<pa)pa=O}else if(K(S)){if(J)Eb[O]=K(Eb[O])?Eb[O]+S:S;S=Eb?Eb[O]:S;F=A(F.low,S);if(!Vc)if(S>wa)wa=S;else if(F<pa)pa=F;if(J){s[kb]||(s[kb]={});s[kb][O]||(s[kb][O]=new x(o.stackLabels,aa,O,ka));s[kb][O].setTotal(S)}}});if(/(area|column|bar)/.test(r.type)&&
-!xa)if(pa>=0){pa=0;Od=true}else if(wa<0){wa=0;Pd=true}}}})}function N(k,n){var t,r;Fb=n?1:Fa.pow(10,lb(Fa.log(k)/Fa.LN10));t=k/Fb;if(!n){n=[1,2,2.5,5,10];if(o.allowDecimals===false||ca)if(Fb===1)n=[1,2,5,10];else if(Fb<=0.1)n=[1/Fb]}for(r=0;r<n.length;r++){k=n[r];if(t<=(n[r]+(n[r+1]||n[r]))/2)break}k*=Fb;return k}function ta(k){var n;n=k;Fb=A(Fb,Fa.pow(10,lb(Fa.log(Ta)/Fa.LN10)));if(Fb<1){n=W(1/Fb)*10;n=W(k*n)/n}return n}function da(){var k,n,t,r,J=o.tickInterval,E=o.tickPixelInterval;k=o.maxZoom||
-(xa&&!K(o.min)&&!K(o.max)?tb(l.smallestInterval*5,wa-pa):null);ya=R?Da:Aa;if(Ub){t=l[xa?"xAxis":"yAxis"][o.linkedTo];r=t.getExtremes();ia=A(r.min,r.dataMin);ra=A(r.max,r.dataMax)}else{ia=A(Vb,o.min,pa);ra=A(Gb,o.max,wa)}if(ca){ia=mc(ia);ra=mc(ra)}if(ra-ia<k){r=(k-ra+ia)/2;ia=Ia(ia-r,A(o.min,ia-r),pa);ra=tb(ia+k,A(o.max,ia+k),wa)}if(!Ya&&!Vc&&!Ub&&K(ia)&&K(ra)){k=ra-ia||1;if(!K(o.min)&&!K(Vb)&&Qd&&(pa<0||!Od))ia-=k*Qd;if(!K(o.max)&&!K(Gb)&&Rd&&(wa>0||!Pd))ra+=k*Rd}Ta=ia===ra?1:Ub&&!J&&E===t.options.tickPixelInterval?
-t.tickInterval:A(J,Ya?1:(ra-ia)*E/ya);if(!D&&!K(o.tickInterval))Ta=N(Ta);I.tickInterval=Ta;Wc=o.minorTickInterval==="auto"&&Ta?Ta/5:o.minorTickInterval;if(D){Ba=[];J=Xa.global.useUTC;var Q=1E3/ub,fa=6E4/ub,ka=36E5/ub;E=864E5/ub;k=6048E5/ub;r=2592E6/ub;var $=31556952E3/ub,F=[["second",Q,[1,2,5,10,15,30]],["minute",fa,[1,2,5,10,15,30]],["hour",ka,[1,2,3,4,6,8,12]],["day",E,[1,2]],["week",k,[1,2]],["month",r,[1,2,3,4,6]],["year",$,null]],O=F[6],S=O[1],aa=O[2];for(t=0;t<F.length;t++){O=F[t];S=O[1];aa=
-O[2];if(F[t+1])if(Ta<=(S*aa[aa.length-1]+F[t+1][1])/2)break}if(S===$&&Ta<5*S)aa=[1,2,5];F=N(Ta/S,aa);aa=new Date(ia*ub);aa.setMilliseconds(0);if(S>=Q)aa.setSeconds(S>=fa?0:F*lb(aa.getSeconds()/F));if(S>=fa)aa[Jd](S>=ka?0:F*lb(aa[id]()/F));if(S>=ka)aa[Kd](S>=E?0:F*lb(aa[jd]()/F));if(S>=E)aa[ld](S>=r?1:F*lb(aa[Cc]()/F));if(S>=r){aa[Ld](S>=$?0:F*lb(aa[Rc]()/F));n=aa[Sc]()}if(S>=$){n-=n%F;aa[Md](n)}S===k&&aa[ld](aa[Cc]()-aa[kd]()+o.startOfWeek);t=1;n=aa[Sc]();Q=aa.getTime()/ub;fa=aa[Rc]();for(ka=aa[Cc]();Q<
-ra&&t<Da;){Ba.push(Q);if(S===$)Q=Qc(n+t*F,0)/ub;else if(S===r)Q=Qc(n,fa+t*F)/ub;else if(!J&&(S===E||S===k))Q=Qc(n,fa,ka+t*F*(S===E?1:7));else Q+=S*F;t++}Ba.push(Q);Xc=o.dateTimeLabelFormats[O[0]]}else{t=ta(lb(ia/Ta)*Ta);n=ta(md(ra/Ta)*Ta);Ba=[];for(t=ta(t);t<=n;){Ba.push(t);t=ta(t+Ta)}}if(!Ub){if(Ya||xa&&l.hasColumn){n=(Ya?1:Ta)*0.5;if(Ya||!K(A(o.min,Vb)))ia-=n;if(Ya||!K(A(o.max,Gb)))ra+=n}n=Ba[0];t=Ba[Ba.length-1];if(o.startOnTick)ia=n;else ia>n&&Ba.shift();if(o.endOnTick)ra=t;else ra<t&&Ba.pop();
-Ob||(Ob={x:0,y:0});if(!D&&Ba.length>Ob[qa])Ob[qa]=Ba.length}}function Ma(){var k,n;Dc=ia;Sd=ra;V();da();Hb=fb;fb=ya/(ra-ia||1);if(!xa)for(k in s)for(n in s[k])s[k][n].cum=s[k][n].total;if(!I.isDirty)I.isDirty=ia!==Dc||ra!==Sd}function za(k){k=(new w(k)).render();Pb.push(k);return k}function eb(){var k=o.title,n=o.stackLabels,t=o.alternateGridColor,r=o.lineWidth,J,E,Q=(J=l.hasRendered)&&K(Dc)&&!isNaN(Dc);E=zb.length&&K(ia)&&K(ra);ya=R?Da:Aa;fb=ya/(ra-ia||1);cc=R?X:vb;if(E||Ub){if(Wc&&!Ya)for(E=ia+
-(Ba[0]-ia)%Wc;E<=ra;E+=Wc){Wb[E]||(Wb[E]=new q(E,true));Q&&Wb[E].isNew&&Wb[E].render(null,true);Wb[E].isActive=true;Wb[E].render()}u(Ba,function($,F){if(!Ub||$>=ia&&$<=ra){Q&&mb[$].isNew&&mb[$].render(F,true);mb[$].isActive=true;mb[$].render(F)}});t&&u(Ba,function($,F){if(F%2===0&&$<ra){dc[$]||(dc[$]=new w);dc[$].options={from:$,to:Ba[F+1]!==Wa?Ba[F+1]:ra,color:t};dc[$].render();dc[$].isActive=true}});J||u((o.plotLines||[]).concat(o.plotBands||[]),function($){Pb.push((new w($)).render())})}u([mb,
-Wb,dc],function($){for(var F in $)if($[F].isActive)$[F].isActive=false;else{$[F].destroy();delete $[F]}});if(r){J=X+(Oa?Da:0)+la;E=cb-vb-(Oa?Aa:0)+la;J=ga.crispLine([Za,R?X:J,R?E:ea,Ka,R?$a-Ib:J,R?E:cb-vb],r);if(La)La.animate({d:J});else La=ga.path(J).attr({stroke:o.lineColor,"stroke-width":r,zIndex:7}).add()}if(ba){J=R?X:ea;r=ja(k.style.fontSize||12);J={low:J+(R?0:ya),middle:J+ya/2,high:J+(R?ya:0)}[k.align];r=(R?ea+Aa:X)+(R?1:-1)*(Oa?-1:1)*nd+(L===2?r:0);ba[ba.isNew?"attr":"animate"]({x:R?J:r+(Oa?
-Da:0)+la+(k.x||0),y:R?r-(Oa?Aa:0)+la:J+(k.y||0)});ba.isNew=false}if(n&&n.enabled){var fa,ka;n=I.stackTotalGroup;if(!n)I.stackTotalGroup=n=ga.g("stack-labels").attr({visibility:Ab,zIndex:6}).translate(X,ea).add();for(fa in s){k=s[fa];for(ka in k)k[ka].render(n)}}I.isDirty=false}function ab(k){for(var n=Pb.length;n--;)Pb[n].id===k&&Pb[n].destroy()}var xa=p.isX,Oa=p.opposite,R=va?!xa:xa,L=R?Oa?0:2:Oa?1:3,s={},o=Ca(xa?Yc:od,[ge,he,Td,ie][L],p),I=this,ba,B=o.type,D=B==="datetime",ca=B==="logarithmic",
-la=o.offset||0,qa=xa?"x":"y",ya,fb,Hb,cc=R?X:vb,G,ha,na,Ra,La,pa,wa,zb,Vb,Gb,ra=null,ia=null,Dc,Sd,Qd=o.minPadding,Rd=o.maxPadding,Ub=K(o.linkedTo),Od,Pd,Vc;B=o.events;var pd,Pb=[],Ta,Wc,Fb,Ba,mb={},Wb={},dc={},qc,rc,nd,Xc,Ya=o.categories,je=o.labels.formatter||function(){var k=this.value;return Xc?Zc(Xc,k):Ta%1E6===0?k/1E6+"M":Ta%1E3===0?k/1E3+"k":!Ya&&k>=1E3?Ed(k,0):k},$c=R&&o.labels.staggerLines,ec=o.reversed,fc=Ya&&o.tickmarkPlacement==="between"?0.5:0;q.prototype={addLabel:function(){var k=this.pos,
-n=o.labels,t=!(k===ia&&!A(o.showFirstLabel,1)||k===ra&&!A(o.showLastLabel,0)),r=Ya&&R&&Ya.length&&!n.step&&!n.staggerLines&&!n.rotation&&Da/Ya.length||!R&&Da/2,J=Ya&&K(Ya[k])?Ya[k]:k,E=this.label;k=je.call({isFirst:k===Ba[0],isLast:k===Ba[Ba.length-1],dateTimeLabelFormat:Xc,value:ca?Fa.pow(10,J):J});r=r&&{width:Ia(1,W(r-2*(n.padding||10)))+Ua};r=sa(r,n.style);if(E===Wa)this.label=K(k)&&t&&n.enabled?ga.text(k,0,0,n.useHTML).attr({align:n.align,rotation:n.rotation}).css(r).add(na):null;else E&&E.attr({text:k}).css(r)},
-getLabelSize:function(){var k=this.label;return k?(this.labelBBox=k.getBBox())[R?"height":"width"]:0},render:function(k,n){var t=!this.minor,r=this.label,J=this.pos,E=o.labels,Q=this.gridLine,fa=t?o.gridLineWidth:o.minorGridLineWidth,ka=t?o.gridLineColor:o.minorGridLineColor,$=t?o.gridLineDashStyle:o.minorGridLineDashStyle,F=this.mark,O=t?o.tickLength:o.minorTickLength,S=t?o.tickWidth:o.minorTickWidth||0,aa=t?o.tickColor:o.minorTickColor,Eb=t?o.tickPosition:o.minorTickPosition,kb=E.step,nb=n&&ad||
-cb,Qb;Qb=R?G(J+fc,null,null,n)+cc:X+la+(Oa?(n&&qd||$a)-Ib-X:0);nb=R?nb-vb+la-(Oa?Aa:0):nb-G(J+fc,null,null,n)-cc;if(fa){J=ha(J+fc,fa,n);if(Q===Wa){Q={stroke:ka,"stroke-width":fa};if($)Q.dashstyle=$;if(t)Q.zIndex=1;this.gridLine=Q=fa?ga.path(J).attr(Q).add(Ra):null}!n&&Q&&J&&Q.animate({d:J})}if(S){if(Eb==="inside")O=-O;if(Oa)O=-O;t=ga.crispLine([Za,Qb,nb,Ka,Qb+(R?0:-O),nb+(R?O:0)],S);if(F)F.animate({d:t});else this.mark=ga.path(t).attr({stroke:aa,"stroke-width":S}).add(na)}if(r&&!isNaN(Qb)){Qb=Qb+
-E.x-(fc&&R?fc*fb*(ec?-1:1):0);nb=nb+E.y-(fc&&!R?fc*fb*(ec?1:-1):0);K(E.y)||(nb+=ja(r.styles.lineHeight)*0.9-r.getBBox().height/2);if($c)nb+=k/(kb||1)%$c*16;if(kb)r[k%kb?"hide":"show"]();r[this.isNew?"attr":"animate"]({x:Qb,y:nb})}this.isNew=false},destroy:function(){Ac(this)}};w.prototype={render:function(){var k=this,n=k.options,t=n.label,r=k.label,J=n.width,E=n.to,Q=n.from,fa=n.value,ka,$=n.dashStyle,F=k.svgElem,O=[],S,aa,Eb=n.color;aa=n.zIndex;var kb=n.events;if(ca){Q=mc(Q);E=mc(E);fa=mc(fa)}if(J){O=
-ha(fa,J);n={stroke:Eb,"stroke-width":J};if($)n.dashstyle=$}else if(K(Q)&&K(E)){Q=Ia(Q,ia);E=tb(E,ra);ka=ha(E);if((O=ha(Q))&&ka)O.push(ka[4],ka[5],ka[1],ka[2]);else O=null;n={fill:Eb}}else return;if(K(aa))n.zIndex=aa;if(F)if(O)F.animate({d:O},null,F.onGetPath);else{F.hide();F.onGetPath=function(){F.show()}}else if(O&&O.length){k.svgElem=F=ga.path(O).attr(n).add();if(kb){$=function(nb){F.on(nb,function(Qb){kb[nb].apply(k,[Qb])})};for(S in kb)$(S)}}if(t&&K(t.text)&&O&&O.length&&Da>0&&Aa>0){t=Ca({align:R&&
-ka&&"center",x:R?!ka&&4:10,verticalAlign:!R&&ka&&"middle",y:R?ka?16:10:ka?6:-4,rotation:R&&!ka&&90},t);if(!r)k.label=r=ga.text(t.text,0,0).attr({align:t.textAlign||t.align,rotation:t.rotation,zIndex:aa}).css(t.style).add();ka=[O[1],O[4],A(O[6],O[1])];O=[O[2],O[5],A(O[7],O[2])];S=tb.apply(Fa,ka);aa=tb.apply(Fa,O);r.align(t,false,{x:S,y:aa,width:Ia.apply(Fa,ka)-S,height:Ia.apply(Fa,O)-aa});r.show()}else r&&r.hide();return k},destroy:function(){Ac(this);nc(Pb,this)}};x.prototype={destroy:function(){Ac(this)},
-setTotal:function(k){this.cum=this.total=k},render:function(k){var n=this.options.formatter.call(this);if(this.label)this.label.attr({text:n,visibility:ob});else this.label=l.renderer.text(n,0,0).css(this.options.style).attr({align:this.textAlign,rotation:this.options.rotation,visibility:ob}).add(k)},setOffset:function(k,n){var t=this.isNegative,r=I.translate(this.total),J=I.translate(0);J=bb(r-J);var E=l.xAxis[0].translate(this.x)+k,Q=l.plotHeight;t={x:va?t?r:r-J:E,y:va?Q-E-n:t?Q-r-J:Q-r,width:va?
-J:n,height:va?n:J};this.label&&this.label.align(this.alignOptions,null,t).attr({visibility:Ab})}};G=function(k,n,t,r,J){var E=1,Q=0,fa=r?Hb:fb;r=r?Dc:ia;fa||(fa=fb);if(t){E*=-1;Q=ya}if(ec){E*=-1;Q-=E*ya}if(n){if(ec)k=ya-k;k=k/fa+r;if(ca&&J)k=Fa.pow(10,k)}else{if(ca&&J)k=mc(k);k=E*(k-r)*fa+Q}return k};ha=function(k,n,t){var r,J,E;k=G(k,null,null,t);var Q=t&&ad||cb,fa=t&&qd||$a,ka;t=J=W(k+cc);r=E=W(Q-k-cc);if(isNaN(k))ka=true;else if(R){r=ea;E=Q-vb;if(t<X||t>X+Da)ka=true}else{t=X;J=fa-Ib;if(r<ea||r>
-ea+Aa)ka=true}return ka?null:ga.crispLine([Za,t,r,Ka,J,E],n||0)};if(va&&xa&&ec===Wa)ec=true;sa(I,{addPlotBand:za,addPlotLine:za,adjustTickAmount:function(){if(Ob&&!D&&!Ya&&!Ub){var k=qc,n=Ba.length;qc=Ob[qa];if(n<qc){for(;Ba.length<qc;)Ba.push(ta(Ba[Ba.length-1]+Ta));fb*=(n-1)/(qc-1);ra=Ba[Ba.length-1]}if(K(k)&&qc!==k)I.isDirty=true}},categories:Ya,getExtremes:function(){return{min:ia,max:ra,dataMin:pa,dataMax:wa,userMin:Vb,userMax:Gb}},getPlotLinePath:ha,getThreshold:function(k){if(ia>k)k=ia;else if(ra<
-k)k=ra;return G(k,0,1)},isXAxis:xa,options:o,plotLinesAndBands:Pb,getOffset:function(){var k=zb.length&&K(ia)&&K(ra),n=0,t=0,r=o.title,J=o.labels,E=[-1,1,1,-1][L],Q;if(!na){na=ga.g("axis").attr({zIndex:7}).add();Ra=ga.g("grid").attr({zIndex:1}).add()}rc=0;if(k||Ub){u(Ba,function(fa){if(mb[fa])mb[fa].addLabel();else mb[fa]=new q(fa);if(L===0||L===2||{1:"left",3:"right"}[L]===J.align)rc=Ia(mb[fa].getLabelSize(),rc)});if($c)rc+=($c-1)*16}else for(Q in mb){mb[Q].destroy();delete mb[Q]}if(r&&r.text){if(!ba){ba=
-I.axisTitle=ga.text(r.text,0,0,r.useHTML).attr({zIndex:7,rotation:r.rotation||0,align:r.textAlign||{low:"left",middle:"center",high:"right"}[r.align]}).css(r.style).add();ba.isNew=true}n=ba.getBBox()[R?"height":"width"];t=A(r.margin,R?5:10)}la=E*(o.offset||Xb[L]);nd=rc+(L!==2&&rc&&E*o.labels[R?"y":"x"])+t;Xb[L]=Ia(Xb[L],nd+n+E*la)},render:eb,setCategories:function(k,n){I.categories=p.categories=Ya=k;u(zb,function(t){t.translate();t.setTooltipPoints(true)});I.isDirty=true;A(n,true)&&l.redraw()},setExtremes:function(k,
-n,t,r){t=A(t,true);Pa(I,"setExtremes",{min:k,max:n},function(){Vb=k;Gb=n;t&&l.redraw(r)})},setScale:Ma,setTickPositions:da,translate:G,redraw:function(){Yb.resetTracker&&Yb.resetTracker();eb();u(Pb,function(k){k.render()});u(zb,function(k){k.isDirty=true})},removePlotBand:ab,removePlotLine:ab,reversed:ec,stacks:s,destroy:function(){var k;pb(I);for(k in s){Ac(s[k]);s[k]=null}if(I.stackTotalGroup)I.stackTotalGroup=I.stackTotalGroup.destroy();u([mb,Wb,dc,Pb],function(n){Ac(n)});u([La,na,Ra,ba],function(n){n&&
-n.destroy()});La=na=Ra=ba=null}});for(pd in B)Qa(I,pd,B[pd]);Ma()}function d(){var p={};return{add:function(q,w,x,V){if(!p[q]){w=ga.text(w,0,0).css(a.toolbar.itemStyle).align({align:"right",x:-Ib-20,y:ea+30}).on("click",V).attr({align:"right",zIndex:20}).add();p[q]=w}},remove:function(q){pc(p[q].element);p[q]=null}}}function e(p){function q(){var B=this.points||zc(this),D=B[0].series.xAxis,ca=this.x;D=D&&D.options.type==="datetime";var la=Sb(ca)||D,qa;qa=la?['<span style="font-size: 10px">'+(D?Zc("%A, %b %e, %Y",
-ca):ca)+"</span>"]:[];u(B,function(ya){qa.push(ya.point.tooltipFormatter(la))});return qa.join("<br/>")}function w(B,D){L=xa?B:(2*L+B)/3;s=xa?D:(s+D)/2;o.translate(L,s);rd=bb(B-L)>1||bb(D-s)>1?function(){w(B,D)}:null}function x(){if(!xa){var B=l.hoverPoints;o.hide();u(da,function(D){D&&D.hide()});B&&u(B,function(D){D.setState()});l.hoverPoints=null;xa=true}}var V,N=p.borderWidth,ta=p.crosshairs,da=[],Ma=p.style,za=p.shared,eb=ja(Ma.padding),ab=N+eb,xa=true,Oa,R,L=0,s=0;Ma.padding=0;var o=ga.g("tooltip").attr({zIndex:8}).add(),
-I=ga.rect(ab,ab,0,0,p.borderRadius,N).attr({fill:p.backgroundColor,"stroke-width":N}).add(o).shadow(p.shadow),ba=ga.text("",eb+ab,ja(Ma.fontSize)+eb+ab,p.useHTML).attr({zIndex:1}).css(Ma).add(o);o.hide();return{shared:za,refresh:function(B){var D,ca,la,qa=0,ya={},fb=[];la=B.tooltipPos;D=p.formatter||q;ya=l.hoverPoints;if(za){ya&&u(ya,function(Hb){Hb.setState()});l.hoverPoints=B;u(B,function(Hb){Hb.setState(Bb);qa+=Hb.plotY;fb.push(Hb.getLabelConfig())});ca=B[0].plotX;qa=W(qa)/B.length;ya={x:B[0].category};
-ya.points=fb;B=B[0]}else ya=B.getLabelConfig();ya=D.call(ya);V=B.series;ca=za?ca:B.plotX;qa=za?qa:B.plotY;D=W(la?la[0]:va?Da-qa:ca);ca=W(la?la[1]:va?Aa-ca:qa);la=za||!B.series.isCartesian||gc(D,ca);if(ya===false||!la)x();else{if(xa){o.show();xa=false}ba.attr({text:ya});la=ba.getBBox();Oa=la.width+2*eb;R=la.height+2*eb;I.attr({width:Oa,height:R,stroke:p.borderColor||B.color||V.color||"#606060"});D=fe(Oa,R,X,ea,Da,Aa,{x:D,y:ca});w(W(D.x-ab),W(D.y-ab))}if(ta){ta=zc(ta);for(D=ta.length;D--;){ca=B.series[D?
-"yAxis":"xAxis"];if(ta[D]&&ca){ca=ca.getPlotLinePath(B[D?"y":"x"],1);if(da[D])da[D].attr({d:ca,visibility:Ab});else{la={"stroke-width":ta[D].width||1,stroke:ta[D].color||"#C0C0C0",zIndex:2};if(ta[D].dashStyle)la.dashstyle=ta[D].dashStyle;da[D]=ga.path(ca).attr(la).add()}}}}},hide:x,destroy:function(){u(da,function(B){B&&B.destroy()});u([I,ba,o],function(B){B&&B.destroy()});I=ba=o=null}}}function f(p){function q(L){var s,o=Ud&&ua.width/ua.body.scrollWidth-1,I,ba,B;L=L||db.event;if(!L.target)L.target=
-L.srcElement;s=L.touches?L.touches.item(0):L;if(L.type!=="mousemove"||db.opera||o){Jb=Fd(oa);I=Jb.left;ba=Jb.top}if(Pc){B=L.x;s=L.y}else if(s.layerX===Wa){B=s.pageX-I;s=s.pageY-ba}else{B=L.layerX;s=L.layerY}if(o){B+=W((o+1)*I-I);s+=W((o+1)*ba-ba)}return sa(L,{chartX:B,chartY:s})}function w(L){var s={xAxis:[],yAxis:[]};u(Va,function(o){var I=o.translate,ba=o.isXAxis;s[ba?"xAxis":"yAxis"].push({axis:o,value:I((va?!ba:ba)?L.chartX-X:Aa-L.chartY+ea,true)})});return s}function x(){var L=l.hoverSeries,
-s=l.hoverPoint;s&&s.onMouseOut();L&&L.onMouseOut();hc&&hc.hide();sd=null}function V(){if(za){var L={xAxis:[],yAxis:[]},s=za.getBBox(),o=s.x-X,I=s.y-ea;if(Ma){u(Va,function(ba){var B=ba.translate,D=ba.isXAxis,ca=va?!D:D,la=B(ca?o:Aa-I-s.height,true,0,0,1);B=B(ca?o+s.width:Aa-I,true,0,0,1);L[D?"xAxis":"yAxis"].push({axis:ba,min:tb(la,B),max:Ia(la,B)})});Pa(l,"selection",L,td)}za=za.destroy()}l.mouseIsDown=ud=Ma=false;pb(ua,Kb?"touchend":"mouseup",V)}function N(L){var s=K(L.pageX)?L.pageX:L.page.x;L=
-K(L.pageX)?L.pageY:L.page.y;Jb&&!gc(s-Jb.left-X,L-Jb.top-ea)&&x()}var ta,da,Ma,za,eb=z.zoomType,ab=/x/.test(eb),xa=/y/.test(eb),Oa=ab&&!va||xa&&va,R=xa&&!va||ab&&va;bd=function(){if(Ec){Ec.translate(X,ea);va&&Ec.attr({width:l.plotWidth,height:l.plotHeight}).invert()}else l.trackerGroup=Ec=ga.g("tracker").attr({zIndex:9}).add()};bd();if(p.enabled)l.tooltip=hc=e(p);(function(){oa.onmousedown=function(s){s=q(s);!Kb&&s.preventDefault&&s.preventDefault();l.mouseIsDown=ud=true;ta=s.chartX;da=s.chartY;Qa(ua,
-Kb?"touchend":"mouseup",V)};var L=function(s){if(!(s&&s.touches&&s.touches.length>1)){s=q(s);if(!Kb)s.returnValue=false;var o=s.chartX,I=s.chartY,ba=!gc(o-X,I-ea);Jb||(Jb=Fd(oa));if(Kb&&s.type==="touchstart")if(Ga(s.target,"isTracker"))l.runTrackerClick||s.preventDefault();else!ke&&!ba&&s.preventDefault();if(ba){if(o<X)o=X;else if(o>X+Da)o=X+Da;if(I<ea)I=ea;else if(I>ea+Aa)I=ea+Aa}if(ud&&s.type!=="touchstart"){Ma=Math.sqrt(Math.pow(ta-o,2)+Math.pow(da-I,2));if(Ma>10){if(sc&&(ab||xa)&&gc(ta-X,da-ea))za||
-(za=ga.rect(X,ea,Oa?1:Da,R?1:Aa,0).attr({fill:z.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add());if(za&&Oa){o=o-ta;za.attr({width:bb(o),x:(o>0?0:o)+ta})}if(za&&R){I=I-da;za.attr({height:bb(I),y:(I>0?0:I)+da})}}}else if(!ba){var B;I=l.hoverPoint;o=l.hoverSeries;var D,ca,la=$a,qa=va?s.chartY:s.chartX-X;if(hc&&p.shared){B=[];D=Ha.length;for(ca=0;ca<D;ca++)if(Ha[ca].visible&&Ha[ca].tooltipPoints.length){s=Ha[ca].tooltipPoints[qa];s._dist=bb(qa-s.plotX);la=tb(la,s._dist);B.push(s)}for(D=
-B.length;D--;)B[D]._dist>la&&B.splice(D,1);if(B.length&&B[0].plotX!==sd){hc.refresh(B);sd=B[0].plotX}}if(o&&o.tracker)(s=o.tooltipPoints[qa])&&s!==I&&s.onMouseOver()}return ba||!sc}};oa.onmousemove=L;Qa(oa,"mouseleave",x);Qa(ua,"mousemove",N);oa.ontouchstart=function(s){if(ab||xa)oa.onmousedown(s);L(s)};oa.ontouchmove=L;oa.ontouchend=function(){Ma&&x()};oa.onclick=function(s){var o=l.hoverPoint;s=q(s);s.cancelBubble=true;if(!Ma)if(o&&Ga(s.target,"isTracker")){var I=o.plotX,ba=o.plotY;sa(o,{pageX:Jb.left+
-X+(va?Da-ba:I),pageY:Jb.top+ea+(va?Aa-I:ba)});Pa(o.series,"click",sa(s,{point:o}));o.firePointEvent("click",s)}else{sa(s,w(s));gc(s.chartX-X,s.chartY-ea)&&Pa(l,"click",s)}Ma=false}})();Vd=setInterval(function(){rd&&rd()},32);sa(this,{zoomX:ab,zoomY:xa,resetTracker:x,destroy:function(){if(l.trackerGroup)l.trackerGroup=Ec=l.trackerGroup.destroy();pb(ua,"mousemove",N);oa.onclick=oa.onmousedown=oa.onmousemove=oa.ontouchstart=oa.ontouchend=oa.ontouchmove=null}})}function g(p){var q=p.type||z.type||z.defaultSeriesType,
-w=wb[q],x=l.hasRendered;if(x)if(va&&q==="column")w=wb.bar;else if(!va&&q==="bar")w=wb.column;q=new w;q.init(l,p);if(!x&&q.inverted)va=true;if(q.isCartesian)sc=q.isCartesian;Ha.push(q);return q}function h(){z.alignTicks!==false&&u(Va,function(p){p.adjustTickAmount()});Ob=null}function i(p){var q=l.isDirtyLegend,w,x=l.isDirtyBox,V=Ha.length,N=V,ta=l.clipRect;for(oc(p,l);N--;){p=Ha[N];if(p.isDirty&&p.options.stacking){w=true;break}}if(w)for(N=V;N--;){p=Ha[N];if(p.options.stacking)p.isDirty=true}u(Ha,
-function(da){if(da.isDirty){da.cleanData();da.getSegments();if(da.options.legendType==="point")q=true}});if(q&&Fc.renderLegend){Fc.renderLegend();l.isDirtyLegend=false}if(sc){if(!cd){Ob=null;u(Va,function(da){da.setScale()})}h();Gc();u(Va,function(da){if(da.isDirty||x){da.redraw();x=true}})}if(x){vd();bd();if(ta){Hc(ta);ta.animate({width:l.plotSizeX,height:l.plotSizeY})}}u(Ha,function(da){if(da.isDirty&&da.visible&&(!da.isCartesian||da.xAxis))da.redraw()});Yb&&Yb.resetTracker&&Yb.resetTracker();Pa(l,
-"redraw")}function j(){var p=a.xAxis||{},q=a.yAxis||{},w;p=zc(p);u(p,function(x,V){x.index=V;x.isX=true});q=zc(q);u(q,function(x,V){x.index=V});Va=p.concat(q);l.xAxis=[];l.yAxis=[];Va=tc(Va,function(x){w=new c(x);l[w.isXAxis?"xAxis":"yAxis"].push(w);return w});h()}function m(p,q){uc=Ca(a.title,p);Ic=Ca(a.subtitle,q);u([["title",p,uc],["subtitle",q,Ic]],function(w){var x=w[0],V=l[x],N=w[1];w=w[2];if(V&&N)V=V.destroy();if(w&&w.text&&!V)l[x]=ga.text(w.text,0,0,w.useHTML).attr({align:w.align,"class":"highcharts-"+
-x,zIndex:1}).css(w.style).add().align(w,false,Rb)})}function v(){qb=z.renderTo;Wd=vc+wd++;if(Sb(qb))qb=ua.getElementById(qb);qb.innerHTML="";if(!qb.offsetWidth){Zb=qb.cloneNode(0);Ja(Zb,{position:ic,top:"-9999px",display:""});ua.body.appendChild(Zb)}dd=(Zb||qb).offsetWidth;Jc=(Zb||qb).offsetHeight;l.chartWidth=$a=z.width||dd||600;l.chartHeight=cb=z.height||(Jc>19?Jc:400);l.container=oa=hb(Tb,{className:"highcharts-container"+(z.className?" "+z.className:""),id:Wd},sa({position:Xd,overflow:ob,width:$a+
-Ua,height:cb+Ua,textAlign:"left"},z.style),Zb||qb);l.renderer=ga=z.forExport?new ed(oa,$a,cb,true):new fd(oa,$a,cb);var p,q;if(Yd&&oa.getBoundingClientRect){p=function(){Ja(oa,{left:0,top:0});q=oa.getBoundingClientRect();Ja(oa,{left:-(q.left-ja(q.left))+Ua,top:-(q.top-ja(q.top))+Ua})};p();Qa(db,"resize",p);Qa(l,"destroy",function(){pb(db,"resize",p)})}}function P(){function p(){var w=z.width||qb.offsetWidth,x=z.height||qb.offsetHeight;if(w&&x){if(w!==dd||x!==Jc){clearTimeout(q);q=setTimeout(function(){xd(w,
-x,false)},100)}dd=w;Jc=x}}var q;Qa(db,"resize",p);Qa(l,"destroy",function(){pb(db,"resize",p)})}function T(){Pa(l,"endResize",null,function(){cd-=1})}function Y(){var p=a.labels,q=a.credits,w;m();Fc=l.legend=new le;Gc();u(Va,function(x){x.setTickPositions(true)});h();Gc();vd();sc&&u(Va,function(x){x.render()});if(!l.seriesGroup)l.seriesGroup=ga.g("series-group").attr({zIndex:3}).add();u(Ha,function(x){x.translate();x.setTooltipPoints();x.render()});p.items&&u(p.items,function(){var x=sa(p.style,this.style),
-V=ja(x.left)+X,N=ja(x.top)+ea+12;delete x.left;delete x.top;ga.text(this.html,V,N).attr({zIndex:2}).css(x).add()});if(!l.toolbar)l.toolbar=d();if(q.enabled&&!l.credits){w=q.href;l.credits=ga.text(q.text,0,0).on("click",function(){if(w)location.href=w}).attr({align:q.position.align,zIndex:8}).css(q.style).add().align(q.position)}bd();l.hasRendered=true;if(Zb){qb.appendChild(oa);pc(Zb)}}function H(){var p,q=oa&&oa.parentNode;if(l!==null){Pa(l,"destroy");pb(db,"unload",H);pb(l);for(p=Va.length;p--;)Va[p]=
-Va[p].destroy();for(p=Ha.length;p--;)Ha[p]=Ha[p].destroy();u(["title","subtitle","seriesGroup","clipRect","credits","tracker"],function(w){var x=l[w];if(x)l[w]=x.destroy()});u([wc,xc,Kc,Fc,hc,ga,Yb],function(w){w&&w.destroy&&w.destroy()});wc=xc=Kc=Fc=hc=ga=Yb=null;if(oa){oa.innerHTML="";pb(oa);q&&pc(oa);oa=null}clearInterval(Vd);for(p in l)delete l[p];l=null}}function U(){if(!Lc&&db==db.top&&ua.readyState!=="complete")ua.attachEvent("onreadystatechange",function(){ua.detachEvent("onreadystatechange",
-U);ua.readyState==="complete"&&U()});else{v();yd();zd();u(a.series||[],function(p){g(p)});l.inverted=va=A(va,a.chart.inverted);j();l.render=Y;l.tracker=Yb=new f(a.tooltip);Y();Pa(l,"load");b&&b.apply(l,[l]);u(l.callbacks,function(p){p.apply(l,[l])})}}Yc=Ca(Yc,Xa.xAxis);od=Ca(od,Xa.yAxis);Xa.xAxis=Xa.yAxis=null;a=Ca(Xa,a);var z=a.chart,M=z.margin;M=Nb(M)?M:[M,M,M,M];var y=A(z.marginTop,M[0]),C=A(z.marginRight,M[1]),Z=A(z.marginBottom,M[2]),Sa=A(z.marginLeft,M[3]),Na=z.spacingTop,Ea=z.spacingRight,
-gb=z.spacingBottom,Lb=z.spacingLeft,Rb,uc,Ic,ea,Ib,vb,X,Xb,qb,Zb,oa,Wd,dd,Jc,$a,cb,qd,ad,wc,Kc,Ad,xc,l=this,ke=(M=z.events)&&!!M.click,Bd,gc,hc,ud,jc,Zd,Cd,Aa,Da,Yb,Ec,bd,Fc,$b,ac,Jb,sc=z.showAxes,cd=0,Va=[],Ob,Ha=[],va,ga,rd,Vd,sd,vd,Gc,yd,zd,xd,td,$d,le=function(){function p(G,ha){var na=G.legendItem,Ra=G.legendLine,La=G.legendSymbol,pa=Oa.color,wa=ha?N.itemStyle.color:pa,zb=ha?G.color:pa;pa=ha?G.pointAttr[ib]:{stroke:pa,fill:pa};na&&na.css({fill:wa});Ra&&Ra.attr({stroke:zb});La&&La.attr(pa)}function q(G,
-ha,na){var Ra=G.legendItem,La=G.legendLine,pa=G.legendSymbol;G=G.checkbox;Ra&&Ra.attr({x:ha,y:na});La&&La.translate(ha,na-4);pa&&pa.attr({x:ha+pa.xOff,y:na+pa.yOff});if(G){G.x=ha;G.y=na}}function w(){u(za,function(G){var ha=G.checkbox,na=qa.alignAttr;ha&&Ja(ha,{left:na.translateX+G.legendItemWidth+ha.x-40+Ua,top:na.translateY+ha.y-11+Ua})})}function x(G){var ha,na,Ra,La,pa=G.legendItem;La=G.series||G;var wa=La.options,zb=wa&&wa.borderWidth||0;if(!pa){La=/^(bar|pie|area|column)$/.test(La.type);G.legendItem=
-pa=ga.text(N.labelFormatter.call(G),0,0).css(G.visible?ab:Oa).on("mouseover",function(){G.setState(Bb);pa.css(xa)}).on("mouseout",function(){pa.css(G.visible?ab:Oa);G.setState()}).on("click",function(){var Gb=function(){G.setVisible()};G.firePointEvent?G.firePointEvent("legendItemClick",null,Gb):Pa(G,"legendItemClick",null,Gb)}).attr({zIndex:2}).add(qa);if(!La&&wa&&wa.lineWidth){var Vb={"stroke-width":wa.lineWidth,zIndex:2};if(wa.dashStyle)Vb.dashstyle=wa.dashStyle;G.legendLine=ga.path([Za,-da-Ma,
-0,Ka,-Ma,0]).attr(Vb).add(qa)}if(La)ha=ga.rect(na=-da-Ma,Ra=-11,da,12,2).attr({zIndex:3}).add(qa);else if(wa&&wa.marker&&wa.marker.enabled)ha=ga.symbol(G.symbol,na=-da/2-Ma,Ra=-4,wa.marker.radius).attr({zIndex:3}).add(qa);if(ha){ha.xOff=na+zb%2/2;ha.yOff=Ra+zb%2/2}G.legendSymbol=ha;p(G,G.visible);if(wa&&wa.showCheckbox){G.checkbox=hb("input",{type:"checkbox",checked:G.selected,defaultChecked:G.selected},N.itemCheckboxStyle,oa);Qa(G.checkbox,"click",function(Gb){Pa(G,"checkboxClick",{checked:Gb.target.checked},
-function(){G.select()})})}}ha=pa.getBBox();na=G.legendItemWidth=N.itemWidth||da+Ma+ha.width+R;B=ha.height;if(ta&&o-s+na>(fb||$a-2*R-s)){o=s;I+=B}ba=I;q(G,o,I);if(ta)o+=na;else I+=B;ya=fb||Ia(ta?o-s:na,ya)}function V(){o=s;I=L;ba=ya=0;qa||(qa=ga.g("legend").attr({zIndex:7}).add());za=[];u(Hb,function(Ra){var La=Ra.options;if(La.showInLegend)za=za.concat(La.legendType==="point"?Ra.data:Ra)});Hd(za,function(Ra,La){return(Ra.options.legendIndex||0)-(La.options.legendIndex||0)});cc&&za.reverse();u(za,
-x);$b=fb||ya;ac=ba-L+B;if(ca||la){$b+=2*R;ac+=2*R;if(D){if($b>0&&ac>0){D[D.isNew?"attr":"animate"](D.crisp(null,null,null,$b,ac));D.isNew=false}}else{D=ga.rect(0,0,$b,ac,N.borderRadius,ca||0).attr({stroke:N.borderColor,"stroke-width":ca||0,fill:la||jb}).add(qa).shadow(N.shadow);D.isNew=true}D[za.length?"show":"hide"]()}for(var G=["left","right","top","bottom"],ha,na=4;na--;){ha=G[na];if(eb[ha]&&eb[ha]!=="auto"){N[na<2?"align":"verticalAlign"]=ha;N[na<2?"x":"y"]=ja(eb[ha])*(na%2?-1:1)}}za.length&&
-qa.align(sa(N,{width:$b,height:ac}),true,Rb);cd||w()}var N=l.options.legend;if(N.enabled){var ta=N.layout==="horizontal",da=N.symbolWidth,Ma=N.symbolPadding,za,eb=N.style,ab=N.itemStyle,xa=N.itemHoverStyle,Oa=N.itemHiddenStyle,R=ja(eb.padding),L=18,s=4+R+da+Ma,o,I,ba,B=0,D,ca=N.borderWidth,la=N.backgroundColor,qa,ya,fb=N.width,Hb=l.series,cc=N.reversed;V();Qa(l,"endResize",w);return{colorizeItem:p,destroyItem:function(G){var ha=G.checkbox;u(["legendItem","legendLine","legendSymbol"],function(na){G[na]&&
-G[na].destroy()});ha&&pc(G.checkbox)},renderLegend:V,destroy:function(){if(D)D=D.destroy();if(qa)qa=qa.destroy()}}}};gc=function(p,q){return p>=0&&p<=Da&&q>=0&&q<=Aa};$d=function(){Pa(l,"selection",{resetSelection:true},td);l.toolbar.remove("zoom")};td=function(p){var q=Xa.lang,w=l.pointCount<100;l.toolbar.add("zoom",q.resetZoom,q.resetZoomTitle,$d);!p||p.resetSelection?u(Va,function(x){x.setExtremes(null,null,false,w)}):u(p.xAxis.concat(p.yAxis),function(x){var V=x.axis;if(l.tracker[V.isXAxis?"zoomX":
-"zoomY"])V.setExtremes(x.min,x.max,false,w)});i()};Gc=function(){var p=a.legend,q=A(p.margin,10),w=p.x,x=p.y,V=p.align,N=p.verticalAlign,ta;yd();if((l.title||l.subtitle)&&!K(y))if(ta=Ia(l.title&&!uc.floating&&!uc.verticalAlign&&uc.y||0,l.subtitle&&!Ic.floating&&!Ic.verticalAlign&&Ic.y||0))ea=Ia(ea,ta+A(uc.margin,15)+Na);if(p.enabled&&!p.floating)if(V==="right")K(C)||(Ib=Ia(Ib,$b-w+q+Ea));else if(V==="left")K(Sa)||(X=Ia(X,$b+w+q+Lb));else if(N==="top")K(y)||(ea=Ia(ea,ac+x+q+Na));else if(N==="bottom")K(Z)||
-(vb=Ia(vb,ac-x+q+gb));sc&&u(Va,function(da){da.getOffset()});K(Sa)||(X+=Xb[3]);K(y)||(ea+=Xb[0]);K(Z)||(vb+=Xb[2]);K(C)||(Ib+=Xb[1]);zd()};xd=function(p,q,w){var x=l.title,V=l.subtitle;cd+=1;oc(w,l);ad=cb;qd=$a;l.chartWidth=$a=W(p);l.chartHeight=cb=W(q);Ja(oa,{width:$a+Ua,height:cb+Ua});ga.setSize($a,cb,w);Da=$a-X-Ib;Aa=cb-ea-vb;Ob=null;u(Va,function(N){N.isDirty=true;N.setScale()});u(Ha,function(N){N.isDirty=true});l.isDirtyLegend=true;l.isDirtyBox=true;Gc();x&&x.align(null,null,Rb);V&&V.align(null,
-null,Rb);i(w);ad=null;Pa(l,"resize");Bc===false?T():setTimeout(T,Bc&&Bc.duration||500)};zd=function(){l.plotLeft=X=W(X);l.plotTop=ea=W(ea);l.plotWidth=Da=W($a-X-Ib);l.plotHeight=Aa=W(cb-ea-vb);l.plotSizeX=va?Aa:Da;l.plotSizeY=va?Da:Aa;Rb={x:Lb,y:Na,width:$a-Lb-Ea,height:cb-Na-gb}};yd=function(){ea=A(y,Na);Ib=A(C,Ea);vb=A(Z,gb);X=A(Sa,Lb);Xb=[0,0,0,0]};vd=function(){var p=z.borderWidth||0,q=z.backgroundColor,w=z.plotBackgroundColor,x=z.plotBackgroundImage,V,N={x:X,y:ea,width:Da,height:Aa};V=p+(z.shadow?
-8:0);if(p||q)if(wc)wc.animate(wc.crisp(null,null,null,$a-V,cb-V));else wc=ga.rect(V/2,V/2,$a-V,cb-V,z.borderRadius,p).attr({stroke:z.borderColor,"stroke-width":p,fill:q||jb}).add().shadow(z.shadow);if(w)if(Kc)Kc.animate(N);else Kc=ga.rect(X,ea,Da,Aa,0).attr({fill:w}).add().shadow(z.plotShadow);if(x)if(Ad)Ad.animate(N);else Ad=ga.image(x,X,ea,Da,Aa).add();if(z.plotBorderWidth)if(xc)xc.animate(xc.crisp(null,X,ea,Da,Aa));else xc=ga.rect(X,ea,Da,Aa,0,z.plotBorderWidth).attr({stroke:z.plotBorderColor,
-"stroke-width":z.plotBorderWidth,zIndex:4}).add();l.isDirtyBox=false};Qa(db,"unload",H);z.reflow!==false&&Qa(l,"load",P);if(M)for(Bd in M)Qa(l,Bd,M[Bd]);l.options=a;l.series=Ha;l.addSeries=function(p,q,w){var x;if(p){oc(w,l);q=A(q,true);Pa(l,"addSeries",{options:p},function(){x=g(p);x.isDirty=true;l.isDirtyLegend=true;q&&l.redraw()})}return x};l.animation=A(z.animation,true);l.destroy=H;l.get=function(p){var q,w,x;for(q=0;q<Va.length;q++)if(Va[q].options.id===p)return Va[q];for(q=0;q<Ha.length;q++)if(Ha[q].options.id===
-p)return Ha[q];for(q=0;q<Ha.length;q++){x=Ha[q].data;for(w=0;w<x.length;w++)if(x[w].id===p)return x[w]}return null};l.getSelectedPoints=function(){var p=[];u(Ha,function(q){p=p.concat(Dd(q.data,function(w){return w.selected}))});return p};l.getSelectedSeries=function(){return Dd(Ha,function(p){return p.selected})};l.hideLoading=function(){gd(jc,{opacity:0},{duration:a.loading.hideDuration,complete:function(){Ja(jc,{display:jb})}});Cd=false};l.isInsidePlot=gc;l.redraw=i;l.setSize=xd;l.setTitle=m;l.showLoading=
-function(p){var q=a.loading;if(!jc){jc=hb(Tb,{className:"highcharts-loading"},sa(q.style,{left:X+Ua,top:ea+Ua,width:Da+Ua,height:Aa+Ua,zIndex:10,display:jb}),oa);Zd=hb("span",null,q.labelStyle,jc)}Zd.innerHTML=p||a.lang.loading;if(!Cd){Ja(jc,{opacity:0,display:""});gd(jc,{opacity:q.style.opacity},{duration:q.showDuration});Cd=true}};l.pointCount=0;l.counters=new Gd;U()}var ua=document,db=window,Fa=Math,W=Fa.round,lb=Fa.floor,md=Fa.ceil,Ia=Fa.max,tb=Fa.min,bb=Fa.abs,rb=Fa.cos,Cb=Fa.sin,kc=Fa.PI,ae=
-kc*2/360,yc=navigator.userAgent,Pc=/msie/i.test(yc)&&!db.opera,Mc=ua.documentMode===8,Ud=/AppleWebKit/.test(yc),Yd=/Firefox/.test(yc),Lc=!!ua.createElementNS&&!!ua.createElementNS("http://www.w3.org/2000/svg","svg";).createSVGRect,me=Yd&&parseInt(yc.split("Firefox/")[1],10)<4,fd,Kb=ua.documentElement.ontouchstart!==undefined,be={},wd=0,ub=1,Tc,Xa,Zc,Bc,Nc,Wa,Tb="div",ic="absolute",Xd="relative",ob="hidden",vc="highcharts-",Ab="visible",Ua="px",jb="none",Za="M",Ka="L",ce="rgba(192,192,192,"+(Lc?1.0E-6:
-0.0020)+")",ib="",Bb="hover",Qc,id,jd,kd,Cc,Rc,Sc,Jd,Kd,ld,Ld,Md,ma=db.HighchartsAdapter,Db=ma||{},u=Db.each,Dd=Db.grep,tc=Db.map,Ca=Db.merge,Qa=Db.addEvent,pb=Db.removeEvent,Pa=Db.fireEvent,gd=Db.animate,Hc=Db.stop,wb={};Zc=function(a,b,c){function d(P){return P.toString().replace(/^([0-9])$/,"0$1")}if(!K(b)||isNaN(b))return"Invalid date";a=A(a,"%Y-%m-%d %H:%M:%S");b=new Date(b*ub);var e,f=b[jd](),g=b[kd](),h=b[Cc](),i=b[Rc](),j=b[Sc](),m=Xa.lang,v=m.weekdays;b={a:v[g].substr(0,3),A:v[g],d:d(h),
-e:h,b:m.shortMonths[i],B:m.months[i],m:d(i+1),y:j.toString().substr(2,2),Y:j,H:d(f),I:d(f%12||12),l:f%12||12,M:d(b[id]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:d(b.getSeconds())};for(e in b)a=a.replace("%"+e,b[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};Gd.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};Nc={init:function(a,b,c){b=b||"";var d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g;b=b.split(" ");c=[].concat(c);var h,
-i,j=function(m){for(g=m.length;g--;)m[g]===Za&&m.splice(g+1,0,m[g+1],m[g+2],m[g+1],m[g+2])};if(e){j(b);j(c)}if(a.isArea){h=b.splice(b.length-6,6);i=c.splice(c.length-6,6)}if(d){c=[].concat(c).splice(0,f).concat(c);a.shift=false}if(b.length)for(a=c.length;b.length<a;){d=[].concat(b).splice(b.length-f,f);if(e){d[f-6]=d[f-2];d[f-5]=d[f-1]}b=b.concat(d)}if(h){b=b.concat(h);c=c.concat(i)}return[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;){d=parseFloat(a[f]);
-e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d}else e=b;return e}};ma&&ma.init&&ma.init(Nc);if(!ma&&db.jQuery){var Mb=jQuery;u=function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===false)return c};Dd=Mb.grep;tc=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=b.call(a[d],a[d],d,a);return c};Ca=function(){var a=arguments;return Mb.extend(true,null,a[0],a[1],a[2],a[3])};Qa=function(a,b,c){Mb(a).bind(b,c)};pb=function(a,b,c){var d=ua.removeEventListener?"removeEventListener":"detachEvent";
-if(ua[d]&&!a[d])a[d]=function(){};Mb(a).unbind(b,c)};Pa=function(a,b,c,d){var e=Mb.Event(b),f="detached"+b;sa(e,c);if(a[b]){a[f]=a[b];a[b]=null}Mb(a).trigger(e);if(a[f]){a[b]=a[f];a[f]=null}d&&!e.isDefaultPrevented()&&d(e)};gd=function(a,b,c){var d=Mb(a);if(b.d){a.toD=b.d;b.d=1}d.stop();d.animate(b,c)};Hc=function(a){Mb(a).stop()};Mb.extend(Mb.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});var de=jQuery.fx,ee=de.step;u(["cur","_default","width","height"],function(a,b){var c=b?
-ee:de.prototype,d=c[a],e;if(d)c[a]=function(f){f=b?f:this;e=f.elem;return e.attr?e.attr(f.prop,f.now):d.apply(this,arguments)}});ee.d=function(a){var b=a.elem;if(!a.started){var c=Nc.init(b,b.d,b.toD);a.start=c[0];a.end=c[1];a.started=true}b.attr("d",Nc.step(a.start,a.end,a.pos,b.toD))}}ma={enabled:true,align:"center",x:0,y:15,style:{color:"#666",fontSize:"11px",lineHeight:"14px"}};Xa={colors:["#4572A7","#AA4643","#89A54E","#80699B","#3D96AE","#DB843D","#92A8CD","#A47D7C","#B5CA92"],symbols:["circle",
-"diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","June","Jul","Aug","Sep","Oct","Nov","Dec"],weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],decimalPoint:".",resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:true},chart:{borderColor:"#4572A7",
-borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:true,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0"},title:{text:"Chart title",align:"center",y:15,style:{color:"#3E576F",fontSize:"16px"}},subtitle:{text:"",align:"center",y:30,style:{color:"#6D869F"}},plotOptions:{line:{allowPointSelect:false,showCheckbox:false,
-animation:{duration:1E3},events:{},lineWidth:2,shadow:true,marker:{enabled:true,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:Ca(ma,{enabled:false,y:-6,formatter:function(){return this.y}}),showInLegend:true,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:true}},labels:{style:{position:ic,color:"#3E576F"}},legend:{enabled:true,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},
-borderWidth:1,borderColor:"#909090",borderRadius:5,shadow:false,style:{padding:"5px"},itemStyle:{cursor:"pointer",color:"#3E576F"},itemHoverStyle:{cursor:"pointer",color:"#000000"},itemHiddenStyle:{color:"#C0C0C0"},itemCheckboxStyle:{position:ic,width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0},loading:{hideDuration:100,labelStyle:{fontWeight:"bold",position:Xd,top:"1em"},showDuration:100,style:{position:ic,backgroundColor:"white",opacity:0.5,textAlign:"center"}},
-tooltip:{enabled:true,backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,shadow:true,snap:Kb?25:10,style:{color:"#333333",fontSize:"12px",padding:"5px",whiteSpace:"nowrap"}},toolbar:{itemStyle:{color:"#4572A7",cursor:"pointer"}},credits:{enabled:true,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"10px"}}};var Yc={dateTimeLabelFormats:{second:"%H:%M:%S",minute:"%H:%M",
-hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:false,gridLineColor:"#C0C0C0",labels:ma,lineColor:"#C0D0E0",lineWidth:1,max:null,min:null,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:false,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#6D869F",
-fontWeight:"bold"}},type:"linear"},od=Ca(Yc,{endOnTick:true,gridLineWidth:1,tickPixelInterval:72,showLastLabel:true,labels:{align:"right",x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:true,tickWidth:0,title:{rotation:270,text:"Y-values"},stackLabels:{enabled:false,formatter:function(){return this.total},style:ma.style}}),ie={labels:{align:"right",x:-8,y:null},title:{rotation:270}},he={labels:{align:"left",x:8,y:null},title:{rotation:90}},Td={labels:{align:"center",x:0,y:14},title:{rotation:0}},
-ge=Ca(Td,{labels:{y:-5}}),xb=Xa.plotOptions;ma=xb.line;xb.spline=Ca(ma);xb.scatter=Ca(ma,{lineWidth:0,states:{hover:{lineWidth:0}}});xb.area=Ca(ma,{});xb.areaspline=Ca(xb.area);xb.column=Ca(ma,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,states:{hover:{brightness:0.1,shadow:false},select:{color:"#C0C0C0",borderColor:"#000000",shadow:false}},dataLabels:{y:null,verticalAlign:null}});xb.bar=Ca(xb.column,{dataLabels:{align:"left",x:5,
-y:0}});xb.pie=Ca(ma,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],colorByPoint:true,dataLabels:{distance:30,enabled:true,formatter:function(){return this.point.name},y:5},legendType:"point",marker:null,size:"75%",showInLegend:false,slicedOffset:10,states:{hover:{brightness:0.1,shadow:false}}});Id();var bc=function(a){var b=[],c;(function(d){if(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(d))b=[ja(c[1]),ja(c[2]),ja(c[3]),parseFloat(c[4],
-10)];else if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(d))b=[ja(c[1],16),ja(c[2],16),ja(c[3],16),1]})(a);return{get:function(d){return b&&!isNaN(b[0])?d==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":d==="a"?b[3]:"rgba("+b.join(",")+")":a},brighten:function(d){if(lc(d)&&d!==0){var e;for(e=0;e<3;e++){b[e]+=ja(d*255);if(b[e]<0)b[e]=0;if(b[e]>255)b[e]=255}}return this},setOpacity:function(d){b[3]=d;return this}}};Uc.prototype={init:function(a,b){this.element=ua.createElementNS("http://www.w3.org/2000/svg";,
-b);this.renderer=a},animate:function(a,b,c){if(b=A(b,Bc,true)){b=Ca(b);if(c)b.complete=c;gd(this,a,b)}else{this.attr(a);c&&c()}},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName,i=this.renderer,j,m=this.shadows,v=this.htmlNode,P,T=this;if(Sb(a)&&K(b)){c=a;a={};a[c]=b}if(Sb(a)){c=a;if(h==="circle")c={x:"cx",y:"cy"}[c]||c;else if(c==="strokeWidth")c="stroke-width";T=Ga(g,c)||this[c]||0;if(c!=="d"&&c!=="visibility")T=parseFloat(T)}else for(c in a){j=false;d=a[c];if(c==="d"){if(d&&d.join)d=
-d.join(" ");if(/(NaN| {2}|^$)/.test(d))d="M 0 0";this.d=d}else if(c==="x"&&h==="text"){for(e=0;e<g.childNodes.length;e++){f=g.childNodes[e];Ga(f,"x")===Ga(g,"x")&&Ga(f,"x",d)}if(this.rotation)Ga(g,"transform","rotate("+this.rotation+" "+d+" "+ja(a.y||Ga(g,"y"))+")")}else if(c==="fill")d=i.color(d,g,c);else if(h==="circle"&&(c==="x"||c==="y"))c={x:"cx",y:"cy"}[c]||c;else if(c==="translateX"||c==="translateY"||c==="rotation"||c==="verticalAlign"){this[c]=d;this.updateTransform();j=true}else if(c===
-"stroke")d=i.color(d,g,c);else if(c==="dashstyle"){c="stroke-dasharray";d=d&&d.toLowerCase();if(d==="solid")d=jb;else if(d){d=d.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(e=d.length;e--;)d[e]=ja(d[e])*a["stroke-width"];d=d.join(",")}}else if(c==="isTracker")this[c]=d;else if(c==="width")d=ja(d);else if(c===
-"align"){c="text-anchor";d={left:"start",center:"middle",right:"end"}[d]}else if(c==="title"){e=ua.createElementNS("http://www.w3.org/2000/svg","title";);e.appendChild(ua.createTextNode(d));g.appendChild(e)}if(c==="strokeWidth")c="stroke-width";if(Ud&&c==="stroke-width"&&d===0)d=1.0E-6;if(this.symbolName&&/^(x|y|r|start|end|innerR)/.test(c)){if(!P){this.symbolAttr(a);P=true}j=true}if(m&&/^(width|height|visibility|x|y|d)$/.test(c))for(e=m.length;e--;)Ga(m[e],c,d);if((c==="width"||c==="height")&&h===
-"rect"&&d<0)d=0;if(c==="text"){this.textStr=d;this.added&&i.buildText(this)}else j||Ga(g,c,d);if(v&&(c==="x"||c==="y"||c==="translateX"||c==="translateY"||c==="visibility")){e=v.length?v:[this];f=e.length;var Y;for(Y=0;Y<f;Y++){v=e[Y];j=v.getBBox();v=v.htmlNode;Ja(v,sa(this.styles,{left:j.x+(this.translateX||0)+Ua,top:j.y+(this.translateY||0)+Ua}));c==="visibility"&&Ja(v,{visibility:d})}}}return T},symbolAttr:function(a){var b=this;u(["x","y","r","start","end","width","height","innerR"],function(c){b[c]=
-A(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](W(b.x*2)/2,W(b.y*2)/2,b.r,{start:b.start,end:b.end,width:b.width,height:b.height,innerR:b.innerR})})},clip:function(a){return this.attr("clip-path","url("+this.renderer.url+"#"+a.id+")")},crisp:function(a,b,c,d,e){var f,g={},h={},i;a=a||this.strokeWidth||0;i=a%2/2;h.x=lb(b||this.x||0)+i;h.y=lb(c||this.y||0)+i;h.width=lb((d||this.width||0)-2*i);h.height=lb((e||this.height||0)-2*i);h.strokeWidth=a;for(f in h)if(this[f]!==h[f])this[f]=g[f]=h[f];
-return g},css:function(a){var b=this.element;b=a&&a.width&&b.nodeName==="text";var c,d="",e=function(f,g){return"-"+g.toLowerCase()};if(a&&a.color)a.fill=a.color;this.styles=a=sa(this.styles,a);if(Pc&&!Lc){b&&delete a.width;Ja(this.element,a)}else{for(c in a)d+=c.replace(/([A-Z])/g,e)+":"+a[c]+";";this.attr({style:d})}b&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=b;if(Kb&&a==="click"){a="touchstart";c=function(d){d.preventDefault();b()}}this.element["on"+a]=c;return this},
-translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=true;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.inverted,d=this.rotation,e=[];if(c){a+=this.attr("width");b+=this.attr("height")}if(a||b)e.push("translate("+a+","+b+")");if(c)e.push("rotate(90) scale(-1,1)");else d&&e.push("rotate("+d+" "+this.x+" "+this.y+")");e.length&&Ga(this.element,"transform",e.join(" "))},toFront:function(){var a=
-this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){if(a){this.alignOptions=a;this.alignByTranslate=b;c||this.renderer.alignedObjects.push(this)}else{a=this.alignOptions;b=this.alignByTranslate}c=A(c,this.renderer);var d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),h={};if(/^(right|center)$/.test(d))f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=W(f);if(/^(bottom|middle)$/.test(e))g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||
-1);h[b?"translateY":"y"]=W(g);this[this.placed?"animate":"attr"](h);this.placed=true;this.alignAttr=h;return this},getBBox:function(){var a,b,c,d=this.rotation,e=d*ae;try{a=sa({},this.element.getBBox())}catch(f){a={width:0,height:0}}b=a.width;c=a.height;if(d){a.width=bb(c*Cb(e))+bb(b*rb(e));a.height=bb(c*rb(e))+bb(b*Cb(e))}return a},show:function(){return this.attr({visibility:Ab})},hide:function(){return this.attr({visibility:ob})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=
-d.childNodes,f=this.element,g=Ga(f,"zIndex");this.parentInverted=a&&a.inverted;this.textStr!==undefined&&b.buildText(this);if(a&&this.htmlNode){if(!a.htmlNode)a.htmlNode=[];a.htmlNode.push(this)}if(g){c.handleZ=true;g=ja(g)}if(c.handleZ)for(c=0;c<e.length;c++){a=e[c];b=Ga(a,"zIndex");if(a!==f&&(ja(b)>g||!K(g)&&K(b))){d.insertBefore(f,a);return this}}d.appendChild(f);this.added=true;return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||
-{},c=a.shadows,d,e;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=null;Hc(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(e=0;e<a.stops.length;e++)a.stops[e]=a.stops[e].destroy();a.stops=null}a.safeRemoveChild(b);c&&u(c,function(f){a.safeRemoveChild(f)});nc(a.renderer.alignedObjects,a);for(d in a)delete a[d];return null},empty:function(){for(var a=this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a,b){var c=[],d,e,f=this.element,g=this.parentInverted?
-"(-1,-1)":"(1,1)";if(a){for(d=1;d<=3;d++){e=f.cloneNode(0);Ga(e,{isShadow:"true",stroke:"rgb(0, 0, 0)","stroke-opacity":0.05*d,"stroke-width":7-2*d,transform:"translate"+g,fill:jb});b?b.element.appendChild(e):f.parentNode.insertBefore(e,f);c.push(e)}this.shadows=c}return this}};var ed=function(){this.init.apply(this,arguments)};ed.prototype={Element:Uc,init:function(a,b,c,d){var e=location,f;f=this.createElement("svg").attr({xmlns:"http://www.w3.org/2000/svg",version:"1.1"});a.appendChild(f.element);
-this.box=f.element;this.boxWrapper=f;this.alignedObjects=[];this.url=Pc?"":e.href.replace(/#.*?$/,"");this.defs=this.createElement("defs").add();this.forExport=d;this.gradients=[];this.setSize(b,c,false)},destroy:function(){var a,b=this.gradients,c=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();if(b){for(a=0;a<b.length;a++)this.gradients[a]=b[a].destroy();this.gradients=null}if(c)this.defs=c.destroy();return this.alignedObjects=null},createElement:function(a){var b=new this.Element;
-b.init(this,a);return b},buildText:function(a){for(var b=a.element,c=A(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=Ga(b,"x"),h=a.styles,i=h&&a.useHTML&&!this.forExport,j=a.htmlNode,m=h&&ja(h.width),v=h&&h.lineHeight,P,T=d.length;T--;)b.removeChild(d[T]);m&&!a.added&&
-this.box.appendChild(b);u(c,function(Y,H){var U,z=0,M;Y=Y.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");U=Y.split("|||");u(U,function(y){if(y!==""||U.length===1){var C={},Z=ua.createElementNS("http://www.w3.org/2000/svg","tspan";);e.test(y)&&Ga(Z,"style",y.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"));if(f.test(y)){Ga(Z,"onclick",'location.href="'+y.match(f)[1]+'"');Ja(Z,{cursor:"pointer"})}y=(y.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">");Z.appendChild(ua.createTextNode(y));
-if(z)C.dx=3;else C.x=g;if(!z){if(H){!Lc&&a.renderer.forExport&&Ja(Z,{display:"block"});M=db.getComputedStyle&&ja(db.getComputedStyle(P,null).getPropertyValue("line-height"));if(!M||isNaN(M))M=v||P.offsetHeight||18;Ga(Z,"dy",M)}P=Z}Ga(Z,C);b.appendChild(Z);z++;if(m){y=y.replace(/-/g,"- ").split(" ");for(var Sa,Na=[];y.length||Na.length;){Sa=b.getBBox().width;C=Sa>m;if(!C||y.length===1){y=Na;Na=[];if(y.length){Z=ua.createElementNS("http://www.w3.org/2000/svg","tspan";);Ga(Z,{dy:v||16,x:g});b.appendChild(Z);
-if(Sa>m)m=Sa}}else{Z.removeChild(Z.firstChild);Na.unshift(y.pop())}y.length&&Z.appendChild(ua.createTextNode(y.join(" ").replace(/- /g,"-")))}}}})});if(i){if(!j)j=a.htmlNode=hb("span",null,sa(h,{position:ic,top:0,left:0}),this.box.parentNode);j.innerHTML=a.textStr;for(T=d.length;T--;)d[T].style.visibility=ob}},crispLine:function(a,b){if(a[1]===a[4])a[1]=a[4]=W(a[1])+b%2/2;if(a[2]===a[5])a[2]=a[5]=W(a[2])+b%2/2;return a},path:function(a){return this.createElement("path").attr({d:a,fill:jb})},circle:function(a,
-b,c){a=Nb(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(Nb(a)){b=a.y;c=a.r;d=a.innerR;e=a.start;f=a.end;a=a.x}return this.symbol("arc",a||0,b||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){if(Nb(a)){b=a.y;c=a.width;d=a.height;e=a.r;f=a.strokeWidth;a=a.x}e=this.createElement("rect").attr({rx:e,ry:e,fill:jb});return e.attr(e.crisp(f,a,b,Ia(c,0),Ia(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;
-this.height=b;for(this.boxWrapper[A(c,true)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return K(a)?b.attr({"class":vc+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:jb};arguments.length>1&&sa(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e){var f,
-g=this.symbols[a];g=g&&g(W(b),W(c),d,e);var h=/^url\((.*?)\)$/,i;if(g){f=this.path(g);sa(f,{symbolName:a,x:b,y:c,r:d});e&&sa(f,e)}else if(h.test(a)){var j=function(m,v){m.attr({width:v[0],height:v[1]}).translate(-W(v[0]/2),-W(v[1]/2))};i=a.match(h)[1];a=be[i];f=this.image(i).attr({x:b,y:c});if(a)j(f,a);else{f.attr({width:0,height:0});hb("img",{onload:function(){j(f,be[i]=[this.width,this.height])},src:i})}}else f=this.circle(b,c,d);return f},symbols:{square:function(a,b,c){c=0.707*c;return[Za,a-c,
-b-c,Ka,a+c,b-c,a+c,b+c,a-c,b+c,"Z"]},triangle:function(a,b,c){return[Za,a,b-1.33*c,Ka,a+c,b+0.67*c,a-c,b+0.67*c,"Z"]},"triangle-down":function(a,b,c){return[Za,a,b+1.33*c,Ka,a-c,b-0.67*c,a+c,b-0.67*c,"Z"]},diamond:function(a,b,c){return[Za,a,b-c,Ka,a+c,b,a,b+c,a-c,b,"Z"]},arc:function(a,b,c,d){var e=d.start,f=d.end-1.0E-6,g=d.innerR,h=rb(e),i=Cb(e),j=rb(f);f=Cb(f);d=d.end-e<kc?0:1;return[Za,a+c*h,b+c*i,"A",c,c,0,d,1,a+c*j,b+c*f,Ka,a+g*j,b+g*f,"A",g,g,0,d,0,a+g*h,b+g*i,"Z"]}},clipRect:function(a,b,
-c,d){var e=vc+wd++,f=this.createElement("clipPath").attr({id:e}).add(this.defs);a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;return a},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f=this;b=a.linearGradient;c=vc+wd++;var g,h,i;g=f.createElement("linearGradient").attr({id:c,gradientUnits:"userSpaceOnUse",x1:b[0],y1:b[1],x2:b[2],y2:b[3]}).add(f.defs);f.gradients.push(g);g.stops=[];u(a.stops,function(j){if(e.test(j[1])){d=bc(j[1]);h=d.get("rgb");i=d.get("a")}else{h=j[1];i=1}j=
-f.createElement("stop").attr({offset:j[0],"stop-color":h,"stop-opacity":i}).add(g);g.stops.push(j)});return"url("+this.url+"#"+c+")"}else if(e.test(a)){d=bc(a);Ga(b,c+"-opacity",d.get("a"));return d.get("rgb")}else{b.removeAttribute(c+"-opacity");return a}},text:function(a,b,c,d){var e=Xa.chart.style;b=W(A(b,0));c=W(A(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({fontFamily:e.fontFamily,fontSize:e.fontSize});a.x=b;a.y=c;a.useHTML=d;return a}};fd=ed;if(!Lc){Db=yb(Uc,{init:function(a,
-b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ",ic,";"];if(b==="shape"||b===Tb)d.push("left:0;top:0;width:10px;height:10px;");if(Mc)d.push("visibility: ",b===Tb?ob:Ab);c.push(' style="',d.join(""),'"/>');if(b){c=b===Tb||b==="span"||b==="img"?c.join(""):a.prepVML(c);this.element=hb(c)}this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box;d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);Mc&&d.gVis===ob&&Ja(c,{visibility:ob});d.appendChild(c);this.added=true;this.alignOnAdd&&
-this.updateTransform();return this},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,m,v,P=this.shadows,T=this;if(Sb(a)&&K(b)){c=a;a={};a[c]=b}if(Sb(a)){c=a;T=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c]}else for(c in a){d=a[c];m=false;if(j&&/^(x|y|r|start|end|width|height|innerR)/.test(c)){if(!v){this.symbolAttr(a);v=true}m=true}else if(c==="d"){d=d||[];this.d=d.join(" ");e=d.length;for(m=[];e--;)m[e]=lc(d[e])?W(d[e]*10)-
-5:d[e]==="Z"?"x":d[e];d=m.join(" ")||"x";f.path=d;if(P)for(e=P.length;e--;)P[e].path=d;m=true}else if(c==="zIndex"||c==="visibility"){if(Mc&&c==="visibility"&&h==="DIV"){f.gVis=d;m=f.childNodes;for(e=m.length;e--;)Ja(m[e],{visibility:d});if(d===Ab)d=null}if(d)g[c]=d;m=true}else if(/^(width|height)$/.test(c)){this[c]=d;if(this.updateClipping){this[c]=d;this.updateClipping()}else g[c]=d;m=true}else if(/^(x|y)$/.test(c)){this[c]=d;if(f.tagName==="SPAN")this.updateTransform();else g[{x:"left",y:"top"}[c]]=
-d}else if(c==="class")f.className=d;else if(c==="stroke"){d=i.color(d,f,c);c="strokecolor"}else if(c==="stroke-width"||c==="strokeWidth"){f.stroked=d?true:false;c="strokeweight";this[c]=d;if(lc(d))d+=Ua}else if(c==="dashstyle"){(f.getElementsByTagName("stroke")[0]||hb(i.prepVML(["<stroke/>"]),null,null,f))[c]=d||"solid";this.dashstyle=d;m=true}else if(c==="fill")if(h==="SPAN")g.color=d;else{f.filled=d!==jb?true:false;d=i.color(d,f,c);c="fillcolor"}else if(c==="translateX"||c==="translateY"||c==="rotation"||
-c==="align"){if(c==="align")c="textAlign";this[c]=d;this.updateTransform();m=true}else if(c==="text"){this.bBox=null;f.innerHTML=d;m=true}if(P&&c==="visibility")for(e=P.length;e--;)P[e].style[c]=d;if(!m)if(Mc)f[c]=d;else Ga(f,c,d)}return T},clip:function(a){var b=this,c=a.members;c.push(b);b.destroyClip=function(){nc(c,b)};return b.css(a.getCSS(b.inverted))},css:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width){delete a.width;this.textWidth=b;this.updateTransform()}this.styles=sa(this.styles,
-a);Ja(this.element,a);return this},safeRemoveChild:function(a){a.parentNode&&pc(a)},destroy:function(){this.destroyClip&&this.destroyClip();return Uc.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;){c=a[b];c.parentNode.removeChild(c)}},getBBox:function(){var a=this.element,b=this.bBox;if(!b){if(a.nodeName==="text")a.style.position=ic;b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},on:function(a,b){this.element["on"+
-a]=function(){var c=db.event;c.target=c.srcElement;b(c)};return this},updateTransform:function(){if(this.added){var a=this,b=a.element,c=a.translateX||0,d=a.translateY||0,e=a.x||0,f=a.y||0,g=a.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=g&&g!=="left";if(c||d)a.css({marginLeft:c,marginTop:d});a.inverted&&u(b.childNodes,function(z){a.renderer.invertChild(z,b)});if(b.tagName==="SPAN"){var j,m;c=a.rotation;var v;j=0;d=1;var P=0,T;v=ja(a.textWidth);var Y=a.xCorr||0,H=a.yCorr||0,U=[c,g,b.innerHTML,
-a.textWidth].join(",");if(U!==a.cTT){if(K(c)){j=c*ae;d=rb(j);P=Cb(j);Ja(b,{filter:c?["progid:DXImageTransform.Microsoft.Matrix(M11=",d,", M12=",-P,", M21=",P,", M22=",d,", sizingMethod='auto expand')"].join(""):jb})}j=b.offsetWidth;m=b.offsetHeight;if(j>v){Ja(b,{width:v+Ua,display:"block",whiteSpace:"normal"});j=v}v=W((ja(b.style.fontSize)||12)*1.2);Y=d<0&&-j;H=P<0&&-m;T=d*P<0;Y+=P*v*(T?1-h:h);H-=d*v*(c?T?h:1-h:1);if(i){Y-=j*h*(d<0?-1:1);if(c)H-=m*h*(P<0?-1:1);Ja(b,{textAlign:g})}a.xCorr=Y;a.yCorr=
-H}Ja(b,{left:e+Y,top:f+H});a.cTT=U}}else this.alignOnAdd=true},shadow:function(a,b){var c=[],d,e=this.element,f=this.renderer,g,h=e.style,i,j=e.path;if(j&&typeof j.value!=="string")j="x";if(a){for(d=1;d<=3;d++){i=['<shape isShadow="true" strokeweight="',7-2*d,'" filled="false" path="',j,'" coordsize="100,100" style="',e.style.cssText,'" />'];g=hb(f.prepVML(i),null,{left:ja(h.left)+1,top:ja(h.top)+1});i=['<stroke color="black" opacity="',0.05*d,'"/>'];hb(f.prepVML(i),null,null,g);b?b.element.appendChild(g):
-e.parentNode.insertBefore(g,e);c.push(g)}this.shadows=c}return this}});ma=function(){this.init.apply(this,arguments)};ma.prototype=Ca(ed.prototype,{Element:Db,isIE8:yc.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d;this.alignedObjects=[];d=this.createElement(Tb);a.appendChild(d.element);this.box=d.element;this.boxWrapper=d;this.setSize(b,c,false);if(!ua.namespaces.hcv){ua.namespaces.add("hcv","urn:schemas-microsoft-com:vml");ua.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}},
-clipRect:function(a,b,c,d){var e=this.createElement();return sa(e,{members:[],left:a,top:b,width:c,height:d,getCSS:function(f){var g=this.top,h=this.left,i=h+this.width,j=g+this.height;g={clip:"rect("+W(f?h:g)+"px,"+W(f?j:i)+"px,"+W(f?i:j)+"px,"+W(f?g:h)+"px)"};!f&&Mc&&sa(g,{width:i+Ua,height:j+Ua});return g},updateClipping:function(){u(e.members,function(f){f.css(e.getCSS(f.inverted))})}})},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f,g,h=a.linearGradient,i,j,m,v;u(a.stops,
-function(P,T){if(e.test(P[1])){d=bc(P[1]);f=d.get("rgb");g=d.get("a")}else{f=P[1];g=1}if(T){m=f;v=g}else{i=f;j=g}});a=90-Fa.atan((h[3]-h[1])/(h[2]-h[0]))*180/kc;a=["<",c,' colors="0% ',i,",100% ",m,'" angle="',a,'" opacity="',v,'" o:opacity2="',j,'" type="gradient" focus="100%" />'];hb(this.prepVML(a),null,null,b)}else if(e.test(a)&&b.tagName!=="IMG"){d=bc(a);a=["<",c,' opacity="',d.get("a"),'"/>'];hb(this.prepVML(a),null,null,b);return d.get("rgb")}else{b=b.getElementsByTagName(c);if(b.length)b[0].opacity=
-1;return a}},prepVML:function(a){var b=this.isIE8;a=a.join("");if(b){a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />');a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')}else a=a.replace("<","<hcv:");return a},text:function(a,b,c){var d=Xa.chart.style;return this.createElement("span").attr({text:a,x:W(b),y:W(c)}).css({whiteSpace:"nowrap",fontFamily:d.fontFamily,
-fontSize:d.fontSize})},path:function(a){return this.createElement("shape").attr({coordsize:"100 100",d:a})},circle:function(a,b,c){return this.symbol("circle").attr({x:a,y:b,r:c})},g:function(a){var b;if(a)b={className:vc+a,"class":vc+a};return this.createElement(Tb).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.css({left:b,top:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(Nb(a)){b=a.y;c=a.width;d=a.height;e=a.r;f=a.strokeWidth;
-a=a.x}var g=this.symbol("rect");g.r=e;return g.attr(g.crisp(f,a,b,Ia(c,0),Ia(d,0)))},invertChild:function(a,b){var c=b.style;Ja(a,{flip:"x",left:ja(c.width)-10,top:ja(c.height)-10,rotation:-90})},symbols:{arc:function(a,b,c,d){var e=d.start,f=d.end,g=rb(e),h=Cb(e),i=rb(f),j=Cb(f);d=d.innerR;var m=0.07/c,v=d&&0.1/d||0;if(f-e===0)return["x"];else if(2*kc-f+e<m)i=-m;else if(f-e<v)i=rb(e+v);return["wa",a-c,b-c,a+c,b+c,a+c*g,b+c*h,a+c*i,b+c*j,"at",a-d,b-d,a+d,b+d,a+d*i,b+d*j,a+d*g,b+d*h,"x","e"]},circle:function(a,
-b,c){return["wa",a-c,b-c,a+c,b+c,a+c,b,a+c,b,"e"]},rect:function(a,b,c,d){if(!K(d))return[];var e=d.width;d=d.height;var f=a+e,g=b+d;c=tb(c,e,d);return[Za,a+c,b,Ka,f-c,b,"wa",f-2*c,b,f,b+2*c,f-c,b,f,b+c,Ka,f,g-c,"wa",f-2*c,g-2*c,f,g,f,g-c,f-c,g,Ka,a+c,g,"wa",a,g-2*c,a+2*c,g,a+c,g,a,g-c,Ka,a,b+c,"wa",a,b,a+2*c,b+2*c,a,b+c,a+c,b,"x","e"]}}});fd=ma}Nd.prototype.callbacks=[];var Oc=function(){};Oc.prototype={init:function(a,b){var c=a.chart.counters,d;this.series=a;this.applyOptions(b);this.pointAttr=
-{};if(a.options.colorByPoint){d=a.chart.options.colors;if(!this.options)this.options={};this.color=this.options.color=this.color||d[c.color++];c.wrapColor(d.length)}a.chart.pointCount++;return this},applyOptions:function(a){var b=this.series;this.config=a;if(lc(a)||a===null)this.y=a;else if(Nb(a)&&!lc(a.length)){sa(this,a);this.options=a}else if(Sb(a[0])){this.name=a[0];this.y=a[1]}else if(lc(a[0])){this.x=a[0];this.y=a[1]}if(this.x===Wa)this.x=b.autoIncrement()},destroy:function(){var a=this,b=a.series,
-c=b.chart.hoverPoints,d;b.chart.pointCount--;if(c){a.setState();nc(c,a)}a===b.chart.hoverPoint&&a.onMouseOut();pb(a);u(["graphic","tracker","group","dataLabel","connector","shadowGroup"],function(e){a[e]&&a[e].destroy()});a.legendItem&&a.series.chart.legend.destroyItem(a);for(d in a)a[d]=null},getLabelConfig:function(){return{x:this.category,y:this.y,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},select:function(a,b){var c=this,d=c.series.chart;a=A(a,
-!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=a;c.setState(a&&"select");b||u(d.getSelectedPoints(),function(e){if(e.selected&&e!==c){e.selected=false;e.setState(ib);e.firePointEvent("unselect")}})})},onMouseOver:function(){var a=this.series.chart,b=a.tooltip,c=a.hoverPoint;c&&c!==this&&c.onMouseOut();this.firePointEvent("mouseOver");b&&!b.shared&&b.refresh(this);this.setState(Bb);a.hoverPoint=this},onMouseOut:function(){this.firePointEvent("mouseOut");this.setState();
-this.series.chart.hoverPoint=null},tooltipFormatter:function(a){var b=this.series;return['<span style="color:'+b.color+'">',this.name||b.name,"</span>: ",!a?"<b>x = "+(this.name||this.x)+",</b> ":"","<b>",!a?"y = ":"",this.y,"</b>"].join("")},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g=e.chart;b=A(b,true);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);if(Nb(a)){e.getAttribs();f&&f.attr(d.pointAttr[e.state])}e.isDirty=true;b&&g.redraw(c)})},remove:function(a,b){var c=
-this,d=c.series,e=d.chart,f=d.data;oc(b,e);a=A(a,true);c.firePointEvent("remove",null,function(){nc(f,c);c.destroy();d.isDirty=true;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;if(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])this.importEvents();if(a==="click"&&e.allowPointSelect)c=function(f){d.select(null,f.ctrlKey||f.metaKey||f.shiftKey)};Pa(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=Ca(this.series.options.point,
-this.options).events,b;this.events=a;for(b in a)Qa(this,b,a[b]);this.hasImportedEvents=true}},setState:function(a){var b=this.series,c=b.options.states,d=xb[b.type].marker&&b.options.marker,e=d&&!d.enabled,f=(d=d&&d.states[a])&&d.enabled===false,g=b.stateMarkerGraphic,h=b.chart,i=this.pointAttr;a=a||ib;if(!(a===this.state||this.selected&&a!=="select"||c[a]&&c[a].enabled===false||a&&(f||e&&!d.enabled))){if(this.graphic)this.graphic.attr(i[a]);else{if(a){if(!g)b.stateMarkerGraphic=g=h.renderer.circle(0,
-0,i[a].r).attr(i[a]).add(b.group);g.translate(this.plotX,this.plotY)}if(g)g[a?"show":"hide"]()}this.state=a}}};var sb=function(){};sb.prototype={isCartesian:true,type:"line",pointClass:Oc,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;d=a.series.length;this.chart=a;b=this.setOptions(b);sa(this,{index:d,options:b,name:b.name||"Series "+(d+1),state:ib,pointAttr:{},visible:b.visible!==false,selected:b.selected===true});d=b.events;
-for(c in d)Qa(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=true;this.getColor();this.getSymbol();this.setData(b.data,false)},autoIncrement:function(){var a=this.options,b=this.xIncrement;b=A(b,a.pointStart,0);this.pointInterval=A(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},cleanData:function(){var a=this.chart,b=this.data,c,d,e=a.smallestInterval,f,g;Hd(b,function(h,i){return h.x-i.x});if(this.options.connectNulls)for(g=
-b.length-1;g>=0;g--)b[g].y===null&&b[g-1]&&b[g+1]&&b.splice(g,1);for(g=b.length-1;g>=0;g--)if(b[g-1]){f=b[g].x-b[g-1].x;if(f>0&&(d===Wa||f<d)){d=f;c=g}}if(e===Wa||d<e)a.smallestInterval=d;this.closestPoints=c},getSegments:function(){var a=-1,b=[],c=this.data;u(c,function(d,e){if(d.y===null){e>a+1&&b.push(c.slice(a+1,e));a=e}else e===c.length-1&&b.push(c.slice(a+1,e+1))});this.segments=b},setOptions:function(a){var b=this.chart.options.plotOptions;return Ca(b[this.type],b.series,a)},getColor:function(){var a=
-this.chart.options.colors,b=this.chart.counters;this.color=this.options.color||a[b.color++]||"#0000ff";b.wrapColor(a.length)},getSymbol:function(){var a=this.chart.options.symbols,b=this.chart.counters;this.symbol=this.options.marker.symbol||a[b.symbol++];b.wrapSymbol(a.length)},addPoint:function(a,b,c,d){var e=this.data,f=this.graph,g=this.area,h=this.chart;a=(new this.pointClass).init(this,a);oc(d,h);if(f&&c)f.shift=c;if(g){g.shift=c;g.isArea=true}b=A(b,true);e.push(a);c&&e[0].remove(false);this.getAttribs();
-this.isDirty=true;b&&h.redraw()},setData:function(a,b){var c=this,d=c.data,e=c.initialColor,f=c.chart,g=d&&d.length||0;c.xIncrement=null;if(K(e))f.counters.color=e;for(a=tc(zc(a||[]),function(h){return(new c.pointClass).init(c,h)});g--;)d[g].destroy();c.data=a;c.cleanData();c.getSegments();c.getAttribs();c.isDirty=true;f.isDirtyBox=true;A(b,true)&&f.redraw(false)},remove:function(a,b){var c=this,d=c.chart;a=A(a,true);if(!c.isRemoving){c.isRemoving=true;Pa(c,"remove",null,function(){c.destroy();d.isDirtyLegend=
-d.isDirtyBox=true;a&&d.redraw(b)})}c.isRemoving=false},translate:function(){for(var a=this.chart,b=this.options.stacking,c=this.xAxis.categories,d=this.yAxis,e=this.data,f=e.length;f--;){var g=e[f],h=g.x,i=g.y,j=g.low,m=d.stacks[(i<0?"-":"")+this.stackKey];g.plotX=this.xAxis.translate(h);if(b&&this.visible&&m&&m[h]){j=m[h];h=j.total;j.cum=j=j.cum-i;i=j+i;if(b==="percent"){j=h?j*100/h:0;i=h?i*100/h:0}g.percentage=h?g.y*100/h:0;g.stackTotal=h}if(K(j))g.yBottom=d.translate(j,0,1,0,1);if(i!==null)g.plotY=
-d.translate(i,0,1,0,1);g.clientX=a.inverted?a.plotHeight-g.plotX:g.plotX;g.category=c&&c[g.x]!==Wa?c[g.x]:g.x}},setTooltipPoints:function(a){var b=this.chart,c=b.inverted,d=[],e=W((c?b.plotTop:b.plotLeft)+b.plotSizeX),f,g,h=[];if(a)this.tooltipPoints=null;u(this.segments,function(i){d=d.concat(i)});if(this.xAxis&&this.xAxis.reversed)d=d.reverse();u(d,function(i,j){f=d[j-1]?d[j-1]._high+1:0;for(g=i._high=d[j+1]?lb((i.plotX+(d[j+1]?d[j+1].plotX:e))/2):e;f<=g;)h[c?e-f++:f++]=i});this.tooltipPoints=h},
-onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(!(!Kb&&a.mouseIsDown)){b&&b!==this&&b.onMouseOut();this.options.events.mouseOver&&Pa(this,"mouseOver");this.tracker&&this.tracker.toFront();this.setState(Bb);a.hoverSeries=this}},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut();this&&a.events.mouseOut&&Pa(this,"mouseOut");c&&!a.stickyTracking&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this.chart,c=this.clipRect,
-d=this.options.animation;if(d&&!Nb(d))d={};if(a){if(!c.isAnimating){c.attr("width",0);c.isAnimating=true}}else{c.animate({width:b.plotSizeX},d);this.animate=null}},drawPoints:function(){var a,b=this.data,c=this.chart,d,e,f,g,h,i;if(this.options.marker.enabled)for(f=b.length;f--;){g=b[f];d=g.plotX;e=g.plotY;i=g.graphic;if(e!==Wa&&!isNaN(e)){a=g.pointAttr[g.selected?"select":ib];h=a.r;if(i)i.animate({x:d,y:e,r:h});else g.graphic=c.renderer.symbol(A(g.marker&&g.marker.symbol,this.symbol),d,e,h).attr(a).add(this.group)}}},
-convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={};a=a||{};b=b||{};c=c||{};d=d||{};for(f in e){g=e[f];h[f]=A(a[g],b[f],c[f],d[f])}return h},getAttribs:function(){var a=this,b=xb[a.type].marker?a.options.marker:a.options,c=b.states,d=c[Bb],e,f=a.color,g={stroke:f,fill:f},h=a.data,i=[],j,m=a.pointAttrToOptions,v;if(a.options.marker){d.radius=d.radius||b.radius+2;d.lineWidth=d.lineWidth||b.lineWidth+1}else d.color=d.color||bc(d.color||f).brighten(d.brightness).get();i[ib]=a.convertAttribs(b,
-g);u([Bb,"select"],function(P){i[P]=a.convertAttribs(c[P],i[ib])});a.pointAttr=i;for(f=h.length;f--;){g=h[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===false)b.radius=0;e=false;if(g.options)for(v in m)if(K(b[m[v]]))e=true;if(e){j=[];c=b.states||{};e=c[Bb]=c[Bb]||{};if(!a.options.marker)e.color=bc(e.color||g.options.color).brighten(e.brightness||d.brightness).get();j[ib]=a.convertAttribs(b,i[ib]);j[Bb]=a.convertAttribs(c[Bb],i[Bb],j[ib]);j.select=a.convertAttribs(c.select,i.select,
-j[ib])}else j=i;g.pointAttr=j}},destroy:function(){var a=this,b=a.chart,c=a.clipRect,d=/\/5[0-9\.]+ (Safari|Mobile)\//.test(yc),e,f;Pa(a,"destroy");pb(a);a.legendItem&&a.chart.legend.destroyItem(a);u(a.data,function(g){g.destroy()});if(c&&c!==b.clipRect)a.clipRect=c.destroy();u(["area","graph","dataLabelsGroup","group","tracker"],function(g){if(a[g]){e=d&&g==="group"?"hide":"destroy";a[g][e]()}});if(b.hoverSeries===a)b.hoverSeries=null;nc(b.series,a);for(f in a)delete a[f]},drawDataLabels:function(){if(this.options.dataLabels.enabled){var a,
-b,c=this.data,d=this.options,e=d.dataLabels,f,g=this.dataLabelsGroup,h=this.chart,i=h.renderer,j=h.inverted,m=this.type,v;v=d.stacking;var P=m==="column"||m==="bar",T=e.verticalAlign===null,Y=e.y===null;if(P)if(v){if(T)e=Ca(e,{verticalAlign:"middle"});if(Y)e=Ca(e,{y:{top:14,middle:4,bottom:-6}[e.verticalAlign]})}else if(T)e=Ca(e,{verticalAlign:"top"});if(g)g.translate(h.plotLeft,h.plotTop);else g=this.dataLabelsGroup=i.g("data-labels").attr({visibility:this.visible?Ab:ob,zIndex:6}).translate(h.plotLeft,
-h.plotTop).add();v=e.color;if(v==="auto")v=null;e.style.color=A(v,this.color,"black");u(c,function(H){var U=H.barX,z=U&&U+H.barW/2||H.plotX||-999,M=A(H.plotY,-999),y=H.dataLabel,C=e.align,Z=Y?H.y>=0?-6:12:e.y;f=e.formatter.call(H.getLabelConfig());a=(j?h.plotWidth-M:z)+e.x;b=(j?h.plotHeight-z:M)+Z;if(m==="column")a+={left:-1,right:1}[C]*H.barW/2||0;if(j&&H.y<0){C="right";a-=10}if(y){if(j&&!e.y)b=b+ja(y.styles.lineHeight)*0.9-y.getBBox().height/2;y.attr({text:f}).animate({x:a,y:b})}else if(K(f)){y=
-H.dataLabel=i.text(f,a,b).attr({align:C,rotation:e.rotation,zIndex:1}).css(e.style).add(g);j&&!e.y&&y.attr({y:b+ja(y.styles.lineHeight)*0.9-y.getBBox().height/2})}if(P&&d.stacking&&y){z=H.barY;M=H.barW;H=H.barH;y.align(e,null,{x:j?h.plotWidth-z-H:U,y:j?h.plotHeight-U-M:z,width:j?H:M,height:j?M:H})}})}},drawGraph:function(){var a=this,b=a.options,c=a.graph,d=[],e,f=a.area,g=a.group,h=b.lineColor||a.color,i=b.lineWidth,j=b.dashStyle,m,v=a.chart.renderer,P=a.yAxis.getThreshold(b.threshold||0),T=/^area/.test(a.type),
-Y=[],H=[];u(a.segments,function(U){m=[];u(U,function(C,Z){if(a.getPointSpline)m.push.apply(m,a.getPointSpline(U,C,Z));else{m.push(Z?Ka:Za);Z&&b.step&&m.push(C.plotX,U[Z-1].plotY);m.push(C.plotX,C.plotY)}});if(U.length>1)d=d.concat(m);else Y.push(U[0]);if(T){var z=[],M,y=m.length;for(M=0;M<y;M++)z.push(m[M]);y===3&&z.push(Ka,m[1],m[2]);if(b.stacking&&a.type!=="areaspline")for(M=U.length-1;M>=0;M--)z.push(U[M].plotX,U[M].yBottom);else z.push(Ka,U[U.length-1].plotX,P,Ka,U[0].plotX,P);H=H.concat(z)}});
-a.graphPath=d;a.singlePoints=Y;if(T){e=A(b.fillColor,bc(a.color).setOpacity(b.fillOpacity||0.75).get());if(f)f.animate({d:H});else a.area=a.chart.renderer.path(H).attr({fill:e}).add(g)}if(c){Hc(c);c.animate({d:d})}else if(i){c={stroke:h,"stroke-width":i};if(j)c.dashstyle=j;a.graph=v.path(d).attr(c).add(g).shadow(b.shadow)}},render:function(){var a=this,b=a.chart,c,d,e=a.options,f=e.animation,g=f&&a.animate;f=g?f&&f.duration||500:0;var h=a.clipRect,i=b.renderer;if(!h){h=a.clipRect=!b.hasRendered&&
-b.clipRect?b.clipRect:i.clipRect(0,0,b.plotSizeX,b.plotSizeY);if(!b.clipRect)b.clipRect=h}if(!a.group){c=a.group=i.g("series");if(b.inverted){d=function(){c.attr({width:b.plotWidth,height:b.plotHeight}).invert()};d();Qa(b,"resize",d);Qa(a,"destroy",function(){pb(b,"resize",d)})}c.clip(a.clipRect).attr({visibility:a.visible?Ab:ob,zIndex:e.zIndex}).translate(b.plotLeft,b.plotTop).add(b.seriesGroup)}a.drawDataLabels();g&&a.animate(true);a.drawGraph&&a.drawGraph();a.drawPoints();a.options.enableMouseTracking!==
-false&&a.drawTracker();g&&a.animate();setTimeout(function(){h.isAnimating=false;if((c=a.group)&&h!==b.clipRect&&h.renderer){c.clip(a.clipRect=b.clipRect);h.destroy()}},f);a.isDirty=false},redraw:function(){var a=this.chart,b=this.group;if(b){a.inverted&&b.attr({width:a.plotWidth,height:a.plotHeight});b.animate({translateX:a.plotLeft,translateY:a.plotTop})}this.translate();this.setTooltipPoints(true);this.render()},setState:function(a){var b=this.options,c=this.graph,d=b.states;b=b.lineWidth;a=a||
-ib;if(this.state!==a){this.state=a;if(!(d[a]&&d[a].enabled===false)){if(a)b=d[a].lineWidth||b+1;if(c&&!c.dashstyle)c.attr({"stroke-width":b},a?0:500)}}},setVisible:function(a,b){var c=this.chart,d=this.legendItem,e=this.group,f=this.tracker,g=this.dataLabelsGroup,h,i=this.data,j=c.options.chart.ignoreHiddenSeries;h=this.visible;h=(this.visible=a=a===Wa?!h:a)?"show":"hide";e&&e[h]();if(f)f[h]();else for(e=i.length;e--;){f=i[e];f.tracker&&f.tracker[h]()}g&&g[h]();d&&c.legend.colorizeItem(this,a);this.isDirty=
-true;this.options.stacking&&u(c.series,function(m){if(m.options.stacking&&m.visible)m.isDirty=true});if(j)c.isDirtyBox=true;b!==false&&c.redraw();Pa(this,h)},show:function(){this.setVisible(true)},hide:function(){this.setVisible(false)},select:function(a){this.selected=a=a===Wa?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;Pa(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=[].concat(a.graphPath),d=c.length,e=a.chart,f=e.options.tooltip.snap,g=a.tracker,h=b.cursor;
-h=h&&{cursor:h};var i=a.singlePoints,j;if(d)for(j=d+1;j--;){c[j]===Za&&c.splice(j+1,0,c[j+1]-f,c[j+2],Ka);if(j&&c[j]===Za||j===d)c.splice(j,0,Ka,c[j-2]+f,c[j-1])}for(j=0;j<i.length;j++){d=i[j];c.push(Za,d.plotX-f,d.plotY,Ka,d.plotX+f,d.plotY)}if(g)g.attr({d:c});else a.tracker=e.renderer.path(c).attr({isTracker:true,stroke:ce,fill:jb,"stroke-width":b.lineWidth+2*f,visibility:a.visible?Ab:ob,zIndex:b.zIndex||1}).on(Kb?"touchstart":"mouseover",function(){e.hoverSeries!==a&&a.onMouseOver()}).on("mouseout",
-function(){b.stickyTracking||a.onMouseOut()}).css(h).add(e.trackerGroup)}};ma=yb(sb);wb.line=ma;ma=yb(sb,{type:"area"});wb.area=ma;ma=yb(sb,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,i,j,m;if(c&&c<a.length-1){a=f.plotY;j=g.plotX;g=g.plotY;var v;h=(1.5*d+f.plotX)/2.5;i=(1.5*e+a)/2.5;j=(1.5*d+j)/2.5;m=(1.5*e+g)/2.5;v=(m-i)*(j-d)/(j-h)+e-m;i+=v;m+=v;if(i>a&&i>e){i=Ia(a,e);m=2*e-i}else if(i<a&&i<e){i=tb(a,e);m=2*e-i}if(m>g&&m>e){m=Ia(g,e);i=2*e-m}else if(m<
-g&&m<e){m=tb(g,e);i=2*e-m}b.rightContX=j;b.rightContY=m}if(c){b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e];f.rightContX=f.rightContY=null}else b=[Za,d,e];return b}});wb.spline=ma;ma=yb(ma,{type:"areaspline"});wb.areaspline=ma;var hd=yb(sb,{type:"column",pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},init:function(){sb.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasColumn=true;b.hasRendered&&u(b.series,function(c){if(c.type===
-a.type)c.isDirty=true})},translate:function(){var a=this,b=a.chart,c=a.options,d=c.stacking,e=c.borderWidth,f=0,g=a.xAxis.reversed,h=a.xAxis.categories,i={},j,m;sb.prototype.translate.apply(a);u(b.series,function(C){if(C.type===a.type&&C.visible){if(C.options.stacking){j=C.stackKey;if(i[j]===Wa)i[j]=f++;m=i[j]}else m=f++;C.columnIndex=m}});var v=a.data,P=a.closestPoints;h=bb(v[1]?v[P].plotX-v[P-1].plotX:b.plotSizeX/(h&&h.length||1));P=h*c.groupPadding;var T=(h-2*P)/f,Y=c.pointWidth,H=K(Y)?(T-Y)/2:
-T*c.pointPadding,U=Ia(A(Y,T-2*H),1),z=H+(P+((g?f-a.columnIndex:a.columnIndex)||0)*T-h/2)*(g?-1:1),M=a.yAxis.getThreshold(c.threshold||0),y=A(c.minPointLength,5);u(v,function(C){var Z=C.plotY,Sa=C.yBottom||M,Na=C.plotX+z,Ea=md(tb(Z,Sa)),gb=md(Ia(Z,Sa)-Ea),Lb=a.yAxis.stacks[(C.y<0?"-":"")+a.stackKey],Rb;d&&a.visible&&Lb&&Lb[C.x]&&Lb[C.x].setOffset(z,U);if(bb(gb)<y){if(y){gb=y;Ea=bb(Ea-M)>y?Sa-y:M-(Z<=M?y:0)}Rb=Ea-3}sa(C,{barX:Na,barY:Ea,barW:U,barH:gb});C.shapeType="rect";Z=sa(b.renderer.Element.prototype.crisp.apply({},
-[e,Na,Ea,U,gb]),{r:c.borderRadius});if(e%2){Z.y-=1;Z.height+=1}C.shapeArgs=Z;C.trackerArgs=K(Rb)&&Ca(C.shapeArgs,{height:Ia(6,gb+3),y:Rb})})},getSymbol:function(){},drawGraph:function(){},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,e;u(a.data,function(f){var g=f.plotY;if(g!==Wa&&!isNaN(g)&&f.y!==null){d=f.graphic;e=f.shapeArgs;if(d){Hc(d);d.animate(e)}else f.graphic=c[f.shapeType](e).attr(f.pointAttr[f.selected?"select":ib]).add(a.group).shadow(b.shadow)}})},drawTracker:function(){var a=
-this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options,h=g.cursor,i=h&&{cursor:h},j;u(a.data,function(m){e=m.tracker;d=m.trackerArgs||m.shapeArgs;delete d.strokeWidth;if(m.y!==null)if(e)e.attr(d);else m.tracker=c[m.shapeType](d).attr({isTracker:f,fill:ce,visibility:a.visible?Ab:ob,zIndex:g.zIndex||1}).on(Kb?"touchstart":"mouseover",function(v){j=v.relatedTarget||v.fromElement;b.hoverSeries!==a&&Ga(j,"isTracker")!==f&&a.onMouseOver();m.onMouseOver()}).on("mouseout",function(v){if(!g.stickyTracking){j=
-v.relatedTarget||v.toElement;Ga(j,"isTracker")!==f&&a.onMouseOut()}}).css(i).add(m.group||b.trackerGroup)})},animate:function(a){var b=this,c=b.data;if(!a){u(c,function(d){var e=d.graphic;d=d.shapeArgs;if(e){e.attr({height:0,y:b.yAxis.translate(0,0,1)});e.animate({height:d.height,y:d.y},b.options.animation)}});b.animate=null}},remove:function(){var a=this,b=a.chart;b.hasRendered&&u(b.series,function(c){if(c.type===a.type)c.isDirty=true});sb.prototype.remove.apply(a,arguments)}});wb.column=hd;ma=yb(hd,
-{type:"bar",init:function(a){a.inverted=this.inverted=true;hd.prototype.init.apply(this,arguments)}});wb.bar=ma;ma=yb(sb,{type:"scatter",translate:function(){var a=this;sb.prototype.translate.apply(a);u(a.data,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){var a=this,b=a.options.cursor,c=b&&{cursor:b},d;u(a.data,function(e){(d=e.graphic)&&d.attr({isTracker:true}).on("mouseover",function(){a.onMouseOver();e.onMouseOver()}).on("mouseout",
-function(){a.options.stickyTracking||a.onMouseOut()}).css(c)})},cleanData:function(){}});wb.scatter=ma;ma=yb(Oc,{init:function(){Oc.prototype.init.apply(this,arguments);var a=this,b;sa(a,{visible:a.visible!==false,name:A(a.name,"Slice")});b=function(){a.slice()};Qa(a,"select",b);Qa(a,"unselect",b);return a},setVisible:function(a){var b=this.series.chart,c=this.tracker,d=this.dataLabel,e=this.connector,f=this.shadowGroup,g;g=(this.visible=a=a===Wa?!this.visible:a)?"show":"hide";this.group[g]();c&&
-c[g]();d&&d[g]();e&&e[g]();f&&f[g]();this.legendItem&&b.legend.colorizeItem(this,a)},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;oc(c,d);A(b,true);a=this.sliced=K(a)?a:!this.sliced;a={translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop};this.group.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}});ma=yb(sb,{type:"pie",isCartesian:false,pointClass:ma,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:function(){this.initialColor=
-this.chart.counters.color},animate:function(){var a=this;u(a.data,function(b){var c=b.graphic;b=b.shapeArgs;var d=-kc/2;if(c){c.attr({r:0,start:d,end:d});c.animate({r:b.r,start:b.start,end:b.end},a.options.animation)}});a.animate=null},translate:function(){var a=0,b=-0.25,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f=c.center.concat([c.size,c.innerSize||0]),g=this.chart,h=g.plotWidth,i=g.plotHeight,j,m,v,P=this.data,T=2*kc,Y,H=tb(h,i),U,z,M,y=c.dataLabels.distance;f=tc(f,function(C,Z){return(U=
-/%$/.test(C))?[h,i,H,H][Z]*ja(C)/100:C});this.getX=function(C,Z){v=Fa.asin((C-f[1])/(f[2]/2+y));return f[0]+(Z?-1:1)*rb(v)*(f[2]/2+y)};this.center=f;u(P,function(C){a+=C.y});u(P,function(C){Y=a?C.y/a:0;j=W(b*T*1E3)/1E3;b+=Y;m=W(b*T*1E3)/1E3;C.shapeType="arc";C.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:j,end:m};v=(m+j)/2;C.slicedTranslation=tc([rb(v)*d+g.plotLeft,Cb(v)*d+g.plotTop],W);z=rb(v)*f[2]/2;M=Cb(v)*f[2]/2;C.tooltipPos=[f[0]+z*0.7,f[1]+M*0.7];C.labelPos=[f[0]+z+rb(v)*y,f[1]+M+Cb(v)*
-y,f[0]+z+rb(v)*e,f[1]+M+Cb(v)*e,f[0]+z,f[1]+M,y<0?"center":v<T/4?"left":"right",v];C.percentage=Y*100;C.total=a});this.setTooltipPoints()},render:function(){this.drawPoints();this.options.enableMouseTracking!==false&&this.drawTracker();this.drawDataLabels();this.options.animation&&this.animate&&this.animate();this.isDirty=false},drawPoints:function(){var a=this.chart,b=a.renderer,c,d,e,f=this.options.shadow,g,h;u(this.data,function(i){d=i.graphic;h=i.shapeArgs;e=i.group;g=i.shadowGroup;if(f&&!g)g=
-i.shadowGroup=b.g("shadow").attr({zIndex:4}).add();if(!e)e=i.group=b.g("point").attr({zIndex:5}).add();c=i.sliced?i.slicedTranslation:[a.plotLeft,a.plotTop];e.translate(c[0],c[1]);g&&g.translate(c[0],c[1]);if(d)d.animate(h);else i.graphic=b.arc(h).attr(sa(i.pointAttr[ib],{"stroke-linejoin":"round"})).add(i.group).shadow(f,g);i.visible===false&&i.setVisible(false)})},drawDataLabels:function(){var a=this.data,b,c=this.chart,d=this.options.dataLabels,e=A(d.connectorPadding,10),f=A(d.connectorWidth,1),
-g,h,i=A(d.softConnector,true),j=d.distance,m=this.center,v=m[2]/2;m=m[1];var P=j>0,T=[[],[]],Y,H,U,z,M=2,y;if(d.enabled){sb.prototype.drawDataLabels.apply(this);u(a,function(gb){if(gb.dataLabel)T[gb.labelPos[7]<kc/2?0:1].push(gb)});T[1].reverse();z=function(gb,Lb){return Lb.y-gb.y};for(a=T[0][0]&&T[0][0].dataLabel&&ja(T[0][0].dataLabel.styles.lineHeight);M--;){var C=[],Z=[],Sa=T[M],Na=Sa.length,Ea;for(y=m-v-j;y<=m+v+j;y+=a)C.push(y);U=C.length;if(Na>U){h=[].concat(Sa);h.sort(z);for(y=Na;y--;)h[y].rank=
-y;for(y=Na;y--;)Sa[y].rank>=U&&Sa.splice(y,1);Na=Sa.length}for(y=0;y<Na;y++){b=Sa[y];h=b.labelPos;b=9999;for(H=0;H<U;H++){g=bb(C[H]-h[1]);if(g<b){b=g;Ea=H}}if(Ea<y&&C[y]!==null)Ea=y;else{if(U<Na-y+Ea&&C[y]!==null)Ea=U-Na+y;for(;C[Ea]===null;)Ea++}Z.push({i:Ea,y:C[Ea]});C[Ea]=null}Z.sort(z);for(y=0;y<Na;y++){b=Sa[y];h=b.labelPos;g=b.dataLabel;H=Z.pop();Y=h[1];U=b.visible===false?ob:Ab;Ea=H.i;H=H.y;if(Y>H&&C[Ea+1]!==null||Y<H&&C[Ea-1]!==null)H=Y;Y=this.getX(Ea===0||Ea===C.length-1?Y:H,M);g.attr({visibility:U,
-align:h[6]})[g.moved?"animate":"attr"]({x:Y+d.x+({left:e,right:-e}[h[6]]||0),y:H+d.y});g.moved=true;if(P&&f){g=b.connector;h=i?[Za,Y+(h[6]==="left"?5:-5),H,"C",Y,H,2*h[2]-h[4],2*h[3]-h[5],h[2],h[3],Ka,h[4],h[5]]:[Za,Y+(h[6]==="left"?5:-5),H,Ka,h[2],h[3],Ka,h[4],h[5]];if(g){g.animate({d:h});g.attr("visibility",U)}else b.connector=g=this.chart.renderer.path(h).attr({"stroke-width":f,stroke:d.connectorColor||b.color||"#606060",visibility:U,zIndex:3}).translate(c.plotLeft,c.plotTop).add()}}}}},drawTracker:hd.prototype.drawTracker,
-getSymbol:function(){}});wb.pie=ma;db.Highcharts={Chart:Nd,dateFormat:Zc,pathAnim:Nc,getOptions:function(){return Xa},hasRtlBug:me,numberFormat:Ed,Point:Oc,Color:bc,Renderer:fd,seriesTypes:wb,setOptions:function(a){Xa=Ca(Xa,a);Id();return Xa},Series:sb,addEvent:Qa,removeEvent:pb,createElement:hb,discardElement:pc,css:Ja,each:u,extend:sa,map:tc,merge:Ca,pick:A,extendClass:yb,product:"Highcharts",version:"2.1.9"}})();

=== removed file 'media/js/highcharts_219/highcharts.src.js'
--- media/js/highcharts_219/highcharts.src.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/highcharts.src.js	1970-01-01 00:00:00 +0000
@@ -1,11454 +0,0 @@
-// ==ClosureCompiler==
-// @compilation_level SIMPLE_OPTIMIZATIONS
-
-/**
- * @license Highcharts JS v2.1.9 (2011-11-11)
- *
- * (c) 2009-2011 Torstein Hønsi
- *
- * License: www.highcharts.com/license
- */
-
-// JSLint options:
-/*global document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $ */
-
-(function () {
-// encapsulated variables
-var doc = document,
-	win = window,
-	math = Math,
-	mathRound = math.round,
-	mathFloor = math.floor,
-	mathCeil = math.ceil,
-	mathMax = math.max,
-	mathMin = math.min,
-	mathAbs = math.abs,
-	mathCos = math.cos,
-	mathSin = math.sin,
-	mathPI = math.PI,
-	deg2rad = mathPI * 2 / 360,
-
-
-	// some variables
-	userAgent = navigator.userAgent,
-	isIE = /msie/i.test(userAgent) && !win.opera,
-	docMode8 = doc.documentMode === 8,
-	isWebKit = /AppleWebKit/.test(userAgent),
-	isFirefox = /Firefox/.test(userAgent),
-	SVG_NS = 'http://www.w3.org/2000/svg',
-	hasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg').createSVGRect,
-	hasRtlBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4, // issue #38
-	Renderer,
-	hasTouch = doc.documentElement.ontouchstart !== undefined,
-	symbolSizes = {},
-	idCounter = 0,
-	timeFactor = 1, // 1 = JavaScript time, 1000 = Unix time
-	garbageBin,
-	defaultOptions,
-	dateFormat, // function
-	globalAnimation,
-	pathAnim,
-
-
-	// some constants for frequently used strings
-	UNDEFINED,
-	DIV = 'div',
-	ABSOLUTE = 'absolute',
-	RELATIVE = 'relative',
-	HIDDEN = 'hidden',
-	PREFIX = 'highcharts-',
-	VISIBLE = 'visible',
-	PX = 'px',
-	NONE = 'none',
-	M = 'M',
-	L = 'L',
-	/*
-	 * Empirical lowest possible opacities for TRACKER_FILL
-	 * IE6: 0.002
-	 * IE7: 0.002
-	 * IE8: 0.002
-	 * IE9: 0.00000000001 (unlimited)
-	 * FF: 0.00000000001 (unlimited)
-	 * Chrome: 0.000001
-	 * Safari: 0.000001
-	 * Opera: 0.00000000001 (unlimited)
-	 */
-	TRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.000001 : 0.002) + ')', // invisible but clickable
-	NORMAL_STATE = '',
-	HOVER_STATE = 'hover',
-	SELECT_STATE = 'select',
-
-	// time methods, changed based on whether or not UTC is used
-	makeTime,
-	getMinutes,
-	getHours,
-	getDay,
-	getDate,
-	getMonth,
-	getFullYear,
-	setMinutes,
-	setHours,
-	setDate,
-	setMonth,
-	setFullYear,
-
-	// check for a custom HighchartsAdapter defined prior to this file
-	globalAdapter = win.HighchartsAdapter,
-	adapter = globalAdapter || {},
-
-	// Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object
-	// and all the utility functions will be null. In that case they are populated by the
-	// default adapters below.
-	each = adapter.each,
-	grep = adapter.grep,
-	map = adapter.map,
-	merge = adapter.merge,
-	addEvent = adapter.addEvent,
-	removeEvent = adapter.removeEvent,
-	fireEvent = adapter.fireEvent,
-	animate = adapter.animate,
-	stop = adapter.stop,
-
-	// lookup over the types and the associated classes
-	seriesTypes = {};
-
-/**
- * Extend an object with the members of another
- * @param {Object} a The object to be extended
- * @param {Object} b The object to add to the first one
- */
-function extend(a, b) {
-	var n;
-	if (!a) {
-		a = {};
-	}
-	for (n in b) {
-		a[n] = b[n];
-	}
-	return a;
-}
-
-/**
- * Shortcut for parseInt
- * @param {Object} s
- */
-function pInt(s, mag) {
-	return parseInt(s, mag || 10);
-}
-
-/**
- * Check for string
- * @param {Object} s
- */
-function isString(s) {
-	return typeof s === 'string';
-}
-
-/**
- * Check for object
- * @param {Object} obj
- */
-function isObject(obj) {
-	return typeof obj === 'object';
-}
-
-/**
- * Check for array
- * @param {Object} obj
- */
-function isArray(obj) {
-	return Object.prototype.toString.call(obj) === '[object Array]';
-}
-
-/**
- * Check for number
- * @param {Object} n
- */
-function isNumber(n) {
-	return typeof n === 'number';
-}
-
-function log2lin(num) {
-	return math.log(num) / math.LN10;
-}
-function lin2log(num) {
-	return math.pow(10, num);
-}
-
-/**
- * Remove last occurence of an item from an array
- * @param {Array} arr
- * @param {Mixed} item
- */
-function erase(arr, item) {
-	var i = arr.length;
-	while (i--) {
-		if (arr[i] === item) {
-			arr.splice(i, 1);
-			break;
-		}
-	}
-	//return arr;
-}
-
-/**
- * Returns true if the object is not null or undefined. Like MooTools' $.defined.
- * @param {Object} obj
- */
-function defined(obj) {
-	return obj !== UNDEFINED && obj !== null;
-}
-
-/**
- * Set or get an attribute or an object of attributes. Can't use jQuery attr because
- * it attempts to set expando properties on the SVG element, which is not allowed.
- *
- * @param {Object} elem The DOM element to receive the attribute(s)
- * @param {String|Object} prop The property or an abject of key-value pairs
- * @param {String} value The value if a single property is set
- */
-function attr(elem, prop, value) {
-	var key,
-		setAttribute = 'setAttribute',
-		ret;
-
-	// if the prop is a string
-	if (isString(prop)) {
-		// set the value
-		if (defined(value)) {
-
-			elem[setAttribute](prop, value);
-
-		// get the value
-		} else if (elem && elem.getAttribute) { // elem not defined when printing pie demo...
-			ret = elem.getAttribute(prop);
-		}
-
-	// else if prop is defined, it is a hash of key/value pairs
-	} else if (defined(prop) && isObject(prop)) {
-		for (key in prop) {
-			elem[setAttribute](key, prop[key]);
-		}
-	}
-	return ret;
-}
-/**
- * Check if an element is an array, and if not, make it into an array. Like
- * MooTools' $.splat.
- */
-function splat(obj) {
-	return isArray(obj) ? obj : [obj];
-}
-
-
-/**
- * Return the first value that is defined. Like MooTools' $.pick.
- */
-function pick() {
-	var args = arguments,
-		i,
-		arg,
-		length = args.length;
-	for (i = 0; i < length; i++) {
-		arg = args[i];
-		if (typeof arg !== 'undefined' && arg !== null) {
-			return arg;
-		}
-	}
-}
-
-/**
- * Set CSS on a given element
- * @param {Object} el
- * @param {Object} styles Style object with camel case property names
- */
-function css(el, styles) {
-	if (isIE) {
-		if (styles && styles.opacity !== UNDEFINED) {
-			styles.filter = 'alpha(opacity=' + (styles.opacity * 100) + ')';
-		}
-	}
-	extend(el.style, styles);
-}
-
-/**
- * Utility function to create element with attributes and styles
- * @param {Object} tag
- * @param {Object} attribs
- * @param {Object} styles
- * @param {Object} parent
- * @param {Object} nopad
- */
-function createElement(tag, attribs, styles, parent, nopad) {
-	var el = doc.createElement(tag);
-	if (attribs) {
-		extend(el, attribs);
-	}
-	if (nopad) {
-		css(el, {padding: 0, border: NONE, margin: 0});
-	}
-	if (styles) {
-		css(el, styles);
-	}
-	if (parent) {
-		parent.appendChild(el);
-	}
-	return el;
-}
-
-/**
- * Extend a prototyped class by new members
- * @param {Object} parent
- * @param {Object} members
- */
-function extendClass(parent, members) {
-	var object = function () {};
-	object.prototype = new parent();
-	extend(object.prototype, members);
-	return object;
-}
-
-/**
- * Format a number and return a string based on input settings
- * @param {Number} number The input number to format
- * @param {Number} decimals The amount of decimals
- * @param {String} decPoint The decimal point, defaults to the one given in the lang options
- * @param {String} thousandsSep The thousands separator, defaults to the one given in the lang options
- */
-function numberFormat(number, decimals, decPoint, thousandsSep) {
-	var lang = defaultOptions.lang,
-		// http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/
-		n = number,
-		c = isNaN(decimals = mathAbs(decimals)) ? 2 : decimals,
-		d = decPoint === undefined ? lang.decimalPoint : decPoint,
-		t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep,
-		s = n < 0 ? "-" : "",
-		i = String(pInt(n = mathAbs(+n || 0).toFixed(c))),
-		j = i.length > 3 ? i.length % 3 : 0;
-
-	return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) +
-		(c ? d + mathAbs(n - i).toFixed(c).slice(2) : "");
-}
-
-/**
- * Based on http://www.php.net/manual/en/function.strftime.php
- * @param {String} format
- * @param {Number} timestamp
- * @param {Boolean} capitalize
- */
-dateFormat = function (format, timestamp, capitalize) {
-	function pad(number) {
-		return number.toString().replace(/^([0-9])$/, '0$1');
-	}
-
-	if (!defined(timestamp) || isNaN(timestamp)) {
-		return 'Invalid date';
-	}
-	format = pick(format, '%Y-%m-%d %H:%M:%S');
-
-	var date = new Date(timestamp * timeFactor),
-		key, // used in for constuct below
-		// get the basic time values
-		hours = date[getHours](),
-		day = date[getDay](),
-		dayOfMonth = date[getDate](),
-		month = date[getMonth](),
-		fullYear = date[getFullYear](),
-		lang = defaultOptions.lang,
-		langWeekdays = lang.weekdays,
-		/* // uncomment this and the 'W' format key below to enable week numbers
-		weekNumber = function() {
-			var clone = new Date(date.valueOf()),
-				day = clone[getDay]() == 0 ? 7 : clone[getDay](),
-				dayNumber;
-			clone.setDate(clone[getDate]() + 4 - day);
-			dayNumber = mathFloor((clone.getTime() - new Date(clone[getFullYear](), 0, 1, -6)) / 86400000);
-			return 1 + mathFloor(dayNumber / 7);
-		},
-		*/
-
-		// list all format keys
-		replacements = {
-
-			// Day
-			'a': langWeekdays[day].substr(0, 3), // Short weekday, like 'Mon'
-			'A': langWeekdays[day], // Long weekday, like 'Monday'
-			'd': pad(dayOfMonth), // Two digit day of the month, 01 to 31
-			'e': dayOfMonth, // Day of the month, 1 through 31
-
-			// Week (none implemented)
-			//'W': weekNumber(),
-
-			// Month
-			'b': lang.shortMonths[month], // Short month, like 'Jan'
-			'B': lang.months[month], // Long month, like 'January'
-			'm': pad(month + 1), // Two digit month number, 01 through 12
-
-			// Year
-			'y': fullYear.toString().substr(2, 2), // Two digits year, like 09 for 2009
-			'Y': fullYear, // Four digits year, like 2009
-
-			// Time
-			'H': pad(hours), // Two digits hours in 24h format, 00 through 23
-			'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11
-			'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12
-			'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59
-			'p': hours < 12 ? 'AM' : 'PM', // Upper case AM or PM
-			'P': hours < 12 ? 'am' : 'pm', // Lower case AM or PM
-			'S': pad(date.getSeconds()) // Two digits seconds, 00 through  59
-
-		};
-
-
-	// do the replaces
-	for (key in replacements) {
-		format = format.replace('%' + key, replacements[key]);
-	}
-
-	// Optionally capitalize the string and return
-	return capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format;
-};
-
-/**
- * Loop up the node tree and add offsetWidth and offsetHeight to get the
- * total page offset for a given element. Used by Opera and iOS on hover and
- * all browsers on point click.
- *
- * @param {Object} el
- *
- */
-function getPosition(el) {
-	var p = { left: el.offsetLeft, top: el.offsetTop };
-	el = el.offsetParent;
-	while (el) {
-		p.left += el.offsetLeft;
-		p.top += el.offsetTop;
-		if (el !== doc.body && el !== doc.documentElement) {
-			p.left -= el.scrollLeft;
-			p.top -= el.scrollTop;
-		}
-		el = el.offsetParent;
-	}
-	return p;
-}
-
-/**
- * Helper class that contains variuos counters that are local to the chart.
- */
-function ChartCounters() {
-	this.color = 0;
-	this.symbol = 0;
-}
-
-ChartCounters.prototype = {
-	/**
-	 * Wraps the color counter if it reaches the specified length.
-	 */
-	wrapColor: function (length) {
-		if (this.color >= length) {
-			this.color = 0;
-		}
-	},
-
-	/**
-	 * Wraps the symbol counter if it reaches the specified length.
-	 */
-	wrapSymbol: function (length) {
-		if (this.symbol >= length) {
-			this.symbol = 0;
-		}
-	}
-};
-
-/**
- * Utility method extracted from Tooltip code that places a tooltip in a chart without spilling over
- * and not covering the point it self.
- */
-function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point) {
-	// keep the box within the chart area
-	var pointX = point.x,
-		pointY = point.y,
-		x = pointX - boxWidth + outerLeft - 25,
-		y = pointY - boxHeight + outerTop + 10,
-		alignedRight;
-
-	// it is too far to the left, adjust it
-	if (x < 7) {
-		x = outerLeft + pointX + 15;
-	}
-
-	// Test to see if the tooltip is to far to the right,
-	// if it is, move it back to be inside and then up to not cover the point.
-	if ((x + boxWidth) > (outerLeft + outerWidth)) {
-		x -= (x + boxWidth) - (outerLeft + outerWidth);
-		y -= boxHeight;
-		alignedRight = true;
-	}
-
-	if (y < 5) {
-		y = 5; // above
-
-		// If the tooltip is still covering the point, move it below instead
-		if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) {
-			y = pointY + boxHeight - 5; // below
-		}
-	} else if (y + boxHeight > outerTop + outerHeight) {
-		y = outerTop + outerHeight - boxHeight - 5; // below
-	}
-
-	return {x: x, y: y};
-}
-
-/**
- * Utility method that sorts an object array and keeping the order of equal items.
- * ECMA script standard does not specify the behaviour when items are equal.
- */
-function stableSort(arr, sortFunction) {
-	var length = arr.length,
-		i;
-
-	// Add index to each item
-	for (i = 0; i < length; i++) {
-		arr[i].ss_i = i; // stable sort index
-	}
-
-	arr.sort(function (a, b) {
-		var sortValue = sortFunction(a, b);
-		return sortValue === 0 ? a.ss_i - b.ss_i : sortValue;
-	});
-
-	// Remove index from items
-	for (i = 0; i < length; i++) {
-		delete arr[i].ss_i; // stable sort index
-	}
-}
-
-/**
- * Utility method that destroys any SVGElement or VMLElement that are properties on the given object.
- * It loops all properties and invokes destroy if there is a destroy method. The property is
- * then delete'ed.
- */
-function destroyObjectProperties(obj) {
-	var n;
-	for (n in obj) {
-		// If the object is non-null and destroy is defined
-		if (obj[n] && obj[n].destroy) {
-			// Invoke the destroy
-			obj[n].destroy();
-		}
-
-		// Delete the property from the object.
-		delete obj[n];
-	}
-}
-
-/**
- * Path interpolation algorithm used across adapters
- */
-pathAnim = {
-	/**
-	 * Prepare start and end values so that the path can be animated one to one
-	 */
-	init: function (elem, fromD, toD) {
-		fromD = fromD || '';
-		var shift = elem.shift,
-			bezier = fromD.indexOf('C') > -1,
-			numParams = bezier ? 7 : 3,
-			endLength,
-			slice,
-			i,
-			start = fromD.split(' '),
-			end = [].concat(toD), // copy
-			startBaseLine,
-			endBaseLine,
-			sixify = function (arr) { // in splines make move points have six parameters like bezier curves
-				i = arr.length;
-				while (i--) {
-					if (arr[i] === M) {
-						arr.splice(i + 1, 0, arr[i + 1], arr[i + 2], arr[i + 1], arr[i + 2]);
-					}
-				}
-			};
-
-		if (bezier) {
-			sixify(start);
-			sixify(end);
-		}
-
-		// pull out the base lines before padding
-		if (elem.isArea) {
-			startBaseLine = start.splice(start.length - 6, 6);
-			endBaseLine = end.splice(end.length - 6, 6);
-		}
-
-		// if shifting points, prepend a dummy point to the end path
-		if (shift) {
-
-			end = [].concat(end).splice(0, numParams).concat(end);
-			elem.shift = false; // reset for following animations
-		}
-
-		// copy and append last point until the length matches the end length
-		if (start.length) {
-			endLength = end.length;
-			while (start.length < endLength) {
-
-				//bezier && sixify(start);
-				slice = [].concat(start).splice(start.length - numParams, numParams);
-				if (bezier) { // disable first control point
-					slice[numParams - 6] = slice[numParams - 2];
-					slice[numParams - 5] = slice[numParams - 1];
-				}
-				start = start.concat(slice);
-			}
-		}
-
-		if (startBaseLine) { // append the base lines for areas
-			start = start.concat(startBaseLine);
-			end = end.concat(endBaseLine);
-		}
-		return [start, end];
-	},
-
-	/**
-	 * Interpolate each value of the path and return the array
-	 */
-	step: function (start, end, pos, complete) {
-		var ret = [],
-			i = start.length,
-			startVal;
-
-		if (pos === 1) { // land on the final path without adjustment points appended in the ends
-			ret = complete;
-
-		} else if (i === end.length && pos < 1) {
-			while (i--) {
-				startVal = parseFloat(start[i]);
-				ret[i] =
-					isNaN(startVal) ? // a letter instruction like M or L
-						start[i] :
-						pos * (parseFloat(end[i] - startVal)) + startVal;
-
-			}
-		} else { // if animation is finished or length not matching, land on right value
-			ret = end;
-		}
-		return ret;
-	}
-};
-
-
-/**
- * Set the global animation to either a given value, or fall back to the
- * given chart's animation option
- * @param {Object} animation
- * @param {Object} chart
- */
-function setAnimation(animation, chart) {
-	globalAnimation = pick(animation, chart.animation);
-}
-
-/*
- * Define the adapter for frameworks. If an external adapter is not defined,
- * Highcharts reverts to the built-in jQuery adapter.
- */
-if (globalAdapter && globalAdapter.init) {
-	// Initialize the adapter with the pathAnim object that takes care
-	// of path animations.
-	globalAdapter.init(pathAnim);
-}
-if (!globalAdapter && win.jQuery) {
-	var jQ = jQuery;
-
-	/**
-	 * Utility for iterating over an array. Parameters are reversed compared to jQuery.
-	 * @param {Array} arr
-	 * @param {Function} fn
-	 */
-	each = function (arr, fn) {
-		var i = 0,
-			len = arr.length;
-		for (; i < len; i++) {
-			if (fn.call(arr[i], arr[i], i, arr) === false) {
-				return i;
-			}
-		}
-	};
-
-	/**
-	 * Filter an array
-	 */
-	grep = jQ.grep;
-
-	/**
-	 * Map an array
-	 * @param {Array} arr
-	 * @param {Function} fn
-	 */
-	map = function (arr, fn) {
-		//return jQuery.map(arr, fn);
-		var results = [],
-			i = 0,
-			len = arr.length;
-		for (; i < len; i++) {
-			results[i] = fn.call(arr[i], arr[i], i, arr);
-		}
-		return results;
-
-	};
-
-	/**
-	 * Deep merge two objects and return a third object
-	 */
-	merge = function () {
-		var args = arguments;
-		return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
-	};
-
-	/**
-	 * Add an event listener
-	 * @param {Object} el A HTML element or custom object
-	 * @param {String} event The event type
-	 * @param {Function} fn The event handler
-	 */
-	addEvent = function (el, event, fn) {
-		jQ(el).bind(event, fn);
-	};
-
-	/**
-	 * Remove event added with addEvent
-	 * @param {Object} el The object
-	 * @param {String} eventType The event type. Leave blank to remove all events.
-	 * @param {Function} handler The function to remove
-	 */
-	removeEvent = function (el, eventType, handler) {
-		// workaround for jQuery issue with unbinding custom events:
-		// http://forum.jquery.com/topic/javascript-error-when-unbinding-a-custom-event-using-jquery-1-4-2
-		var func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent';
-		if (doc[func] && !el[func]) {
-			el[func] = function () {};
-		}
-
-		jQ(el).unbind(eventType, handler);
-	};
-
-	/**
-	 * Fire an event on a custom object
-	 * @param {Object} el
-	 * @param {String} type
-	 * @param {Object} eventArguments
-	 * @param {Function} defaultFunction
-	 */
-	fireEvent = function (el, type, eventArguments, defaultFunction) {
-		var event = jQ.Event(type),
-			detachedType = 'detached' + type;
-		extend(event, eventArguments);
-
-		// Prevent jQuery from triggering the object method that is named the
-		// same as the event. For example, if the event is 'select', jQuery
-		// attempts calling el.select and it goes into a loop.
-		if (el[type]) {
-			el[detachedType] = el[type];
-			el[type] = null;
-		}
-
-		// trigger it
-		jQ(el).trigger(event);
-
-		// attach the method
-		if (el[detachedType]) {
-			el[type] = el[detachedType];
-			el[detachedType] = null;
-		}
-
-		if (defaultFunction && !event.isDefaultPrevented()) {
-			defaultFunction(event);
-		}
-	};
-
-	/**
-	 * Animate a HTML element or SVG element wrapper
-	 * @param {Object} el
-	 * @param {Object} params
-	 * @param {Object} options jQuery-like animation options: duration, easing, callback
-	 */
-	animate = function (el, params, options) {
-		var $el = jQ(el);
-		if (params.d) {
-			el.toD = params.d; // keep the array form for paths, used in jQ.fx.step.d
-			params.d = 1; // because in jQuery, animating to an array has a different meaning
-		}
-
-		$el.stop();
-		$el.animate(params, options);
-
-	};
-	/**
-	 * Stop running animation
-	 */
-	stop = function (el) {
-		jQ(el).stop();
-	};
-
-
-	//=== Extend jQuery on init
-	
-	/*jslint unparam: true*//* allow unused param x in this function */
-	jQ.extend(jQ.easing, {
-		easeOutQuad: function (x, t, b, c, d) {
-			return -c * (t /= d) * (t - 2) + b;
-		}
-	});
-	/*jslint unparam: false*/
-
-	// extend the animate function to allow SVG animations
-	var jFx = jQuery.fx,
-		jStep = jFx.step;
-		
-	// extend some methods to check for elem.attr, which means it is a Highcharts SVG object
-	each(['cur', '_default', 'width', 'height'], function (fn, i) {
-		var obj = i ? jStep : jFx.prototype, // 'cur', the getter' relates to jFx.prototype
-			base = obj[fn],
-			elem;
-		
-		if (base) { // step.width and step.height don't exist in jQuery < 1.7
-		
-			// create the extended function replacement
-			obj[fn] = function (fx) {
-				
-				// jFx.prototype.cur does not use fx argument
-				fx = i ? fx : this;
-				
-				// shortcut
-				elem = fx.elem;
-				
-				// jFX.prototype.cur returns the current value. The other ones are setters 
-				// and returning a value has no effect.
-				return elem.attr ? // is SVG element wrapper
-					elem.attr(fx.prop, fx.now) : // apply the SVG wrapper's method
-					base.apply(this, arguments); // use jQuery's built-in method
-			};
-		}
-	});
-	
-	// animate paths
-	jStep.d = function (fx) {
-		var elem = fx.elem;
-
-
-		// Normally start and end should be set in state == 0, but sometimes,
-		// for reasons unknown, this doesn't happen. Perhaps state == 0 is skipped
-		// in these cases
-		if (!fx.started) {
-			var ends = pathAnim.init(elem, elem.d, elem.toD);
-			fx.start = ends[0];
-			fx.end = ends[1];
-			fx.started = true;
-		}
-
-
-		// interpolate each value of the path
-		elem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD));
-
-	};
-}
-
-
-/**
- * Add a global listener for mousemove events
- */
-/*addEvent(doc, 'mousemove', function(e) {
-	if (globalMouseMove) {
-		globalMouseMove(e);
-	}
-});*/
-/**
- * Set the time methods globally based on the useUTC option. Time method can be either
- * local time or UTC (default).
- */
-function setTimeMethods() {
-	var useUTC = defaultOptions.global.useUTC;
-
-	makeTime = useUTC ? Date.UTC : function (year, month, date, hours, minutes, seconds) {
-		return new Date(
-			year,
-			month,
-			pick(date, 1),
-			pick(hours, 0),
-			pick(minutes, 0),
-			pick(seconds, 0)
-		).getTime();
-	};
-	getMinutes = useUTC ? 'getUTCMinutes' : 'getMinutes';
-	getHours = useUTC ? 'getUTCHours' : 'getHours';
-	getDay = useUTC ? 'getUTCDay' : 'getDay';
-	getDate = useUTC ? 'getUTCDate' : 'getDate';
-	getMonth = useUTC ? 'getUTCMonth' : 'getMonth';
-	getFullYear = useUTC ? 'getUTCFullYear' : 'getFullYear';
-	setMinutes = useUTC ? 'setUTCMinutes' : 'setMinutes';
-	setHours = useUTC ? 'setUTCHours' : 'setHours';
-	setDate = useUTC ? 'setUTCDate' : 'setDate';
-	setMonth = useUTC ? 'setUTCMonth' : 'setMonth';
-	setFullYear = useUTC ? 'setUTCFullYear' : 'setFullYear';
-
-}
-
-/**
- * Merge the default options with custom options and return the new options structure
- * @param {Object} options The new custom options
- */
-function setOptions(options) {
-	defaultOptions = merge(defaultOptions, options);
-
-	// apply UTC
-	setTimeMethods();
-
-	return defaultOptions;
-}
-
-/**
- * Get the updated default options. Merely exposing defaultOptions for outside modules
- * isn't enough because the setOptions method creates a new object.
- */
-function getOptions() {
-	return defaultOptions;
-}
-
-/**
- * Discard an element by moving it to the bin and delete
- * @param {Object} The HTML node to discard
- */
-function discardElement(element) {
-	// create a garbage bin element, not part of the DOM
-	if (!garbageBin) {
-		garbageBin = createElement(DIV);
-	}
-
-	// move the node and empty bin
-	if (element) {
-		garbageBin.appendChild(element);
-	}
-	garbageBin.innerHTML = '';
-}
-
-/* ****************************************************************************
- * Handle the options                                                         *
- *****************************************************************************/
-var
-
-defaultLabelOptions = {
-	enabled: true,
-	// rotation: 0,
-	align: 'center',
-	x: 0,
-	y: 15,
-	/*formatter: function() {
-		return this.value;
-	},*/
-	style: {
-		color: '#666',
-		fontSize: '11px',
-		lineHeight: '14px'
-	}
-};
-
-defaultOptions = {
-	colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE',
-		'#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'],
-	symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
-	lang: {
-		loading: 'Loading...',
-		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
-				'August', 'September', 'October', 'November', 'December'],
-		shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
-		weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
-		decimalPoint: '.',
-		resetZoom: 'Reset zoom',
-		resetZoomTitle: 'Reset zoom level 1:1',
-		thousandsSep: ','
-	},
-	global: {
-		useUTC: true
-	},
-	chart: {
-		//animation: true,
-		//alignTicks: false,
-		//reflow: true,
-		//className: null,
-		//events: { load, selection },
-		//margin: [null],
-		//marginTop: null,
-		//marginRight: null,
-		//marginBottom: null,
-		//marginLeft: null,
-		borderColor: '#4572A7',
-		//borderWidth: 0,
-		borderRadius: 5,
-		defaultSeriesType: 'line',
-		ignoreHiddenSeries: true,
-		//inverted: false,
-		//shadow: false,
-		spacingTop: 10,
-		spacingRight: 10,
-		spacingBottom: 15,
-		spacingLeft: 10,
-		style: {
-			fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
-			fontSize: '12px'
-		},
-		backgroundColor: '#FFFFFF',
-		//plotBackgroundColor: null,
-		plotBorderColor: '#C0C0C0'
-		//plotBorderWidth: 0,
-		//plotShadow: false,
-		//zoomType: ''
-	},
-	title: {
-		text: 'Chart title',
-		align: 'center',
-		// floating: false,
-		// margin: 15,
-		// x: 0,
-		// verticalAlign: 'top',
-		y: 15,
-		style: {
-			color: '#3E576F',
-			fontSize: '16px'
-		}
-
-	},
-	subtitle: {
-		text: '',
-		align: 'center',
-		// floating: false
-		// x: 0,
-		// verticalAlign: 'top',
-		y: 30,
-		style: {
-			color: '#6D869F'
-		}
-	},
-
-	plotOptions: {
-		line: { // base series options
-			allowPointSelect: false,
-			showCheckbox: false,
-			animation: {
-				duration: 1000
-			},
-			//connectNulls: false,
-			//cursor: 'default',
-			//dashStyle: null,
-			//enableMouseTracking: true,
-			events: {},
-			//legendIndex: 0,
-			lineWidth: 2,
-			shadow: true,
-			// stacking: null,
-			marker: {
-				enabled: true,
-				//symbol: null,
-				lineWidth: 0,
-				radius: 4,
-				lineColor: '#FFFFFF',
-				//fillColor: null,
-				states: { // states for a single point
-					hover: {
-						//radius: base + 2
-					},
-					select: {
-						fillColor: '#FFFFFF',
-						lineColor: '#000000',
-						lineWidth: 2
-					}
-				}
-			},
-			point: {
-				events: {}
-			},
-			dataLabels: merge(defaultLabelOptions, {
-				enabled: false,
-				y: -6,
-				formatter: function () {
-					return this.y;
-				}
-			}),
-
-			//pointStart: 0,
-			//pointInterval: 1,
-			showInLegend: true,
-			states: { // states for the entire series
-				hover: {
-					//enabled: false,
-					//lineWidth: base + 1,
-					marker: {
-						// lineWidth: base + 1,
-						// radius: base + 1
-					}
-				},
-				select: {
-					marker: {}
-				}
-			},
-			stickyTracking: true
-			//zIndex: null
-		}
-	},
-	labels: {
-		//items: [],
-		style: {
-			//font: defaultFont,
-			position: ABSOLUTE,
-			color: '#3E576F'
-		}
-	},
-	legend: {
-		enabled: true,
-		align: 'center',
-		//floating: false,
-		layout: 'horizontal',
-		labelFormatter: function () {
-			return this.name;
-		},
-		borderWidth: 1,
-		borderColor: '#909090',
-		borderRadius: 5,
-		// margin: 10,
-		// reversed: false,
-		shadow: false,
-		// backgroundColor: null,
-		style: {
-			padding: '5px'
-		},
-		itemStyle: {
-			cursor: 'pointer',
-			color: '#3E576F'
-		},
-		itemHoverStyle: {
-			cursor: 'pointer',
-			color: '#000000'
-		},
-		itemHiddenStyle: {
-			color: '#C0C0C0'
-		},
-		itemCheckboxStyle: {
-			position: ABSOLUTE,
-			width: '13px', // for IE precision
-			height: '13px'
-		},
-		// itemWidth: undefined,
-		symbolWidth: 16,
-		symbolPadding: 5,
-		verticalAlign: 'bottom',
-		// width: undefined,
-		x: 0,
-		y: 0
-	},
-
-	loading: {
-		hideDuration: 100,
-		labelStyle: {
-			fontWeight: 'bold',
-			position: RELATIVE,
-			top: '1em'
-		},
-		showDuration: 100,
-		style: {
-			position: ABSOLUTE,
-			backgroundColor: 'white',
-			opacity: 0.5,
-			textAlign: 'center'
-		}
-	},
-
-	tooltip: {
-		enabled: true,
-		//crosshairs: null,
-		backgroundColor: 'rgba(255, 255, 255, .85)',
-		borderWidth: 2,
-		borderRadius: 5,
-		//formatter: defaultFormatter,
-		shadow: true,
-		//shared: false,
-		snap: hasTouch ? 25 : 10,
-		style: {
-			color: '#333333',
-			fontSize: '12px',
-			padding: '5px',
-			whiteSpace: 'nowrap'
-		}
-	},
-
-	toolbar: {
-		itemStyle: {
-			color: '#4572A7',
-			cursor: 'pointer'
-		}
-	},
-
-	credits: {
-		enabled: true,
-		text: 'Highcharts.com',
-		href: 'http://www.highcharts.com',
-		position: {
-			align: 'right',
-			x: -10,
-			verticalAlign: 'bottom',
-			y: -5
-		},
-		style: {
-			cursor: 'pointer',
-			color: '#909090',
-			fontSize: '10px'
-		}
-	}
-};
-
-// Axis defaults
-var defaultXAxisOptions =  {
-	// allowDecimals: null,
-	// alternateGridColor: null,
-	// categories: [],
-	dateTimeLabelFormats: {
-		second: '%H:%M:%S',
-		minute: '%H:%M',
-		hour: '%H:%M',
-		day: '%e. %b',
-		week: '%e. %b',
-		month: '%b \'%y',
-		year: '%Y'
-	},
-	endOnTick: false,
-	gridLineColor: '#C0C0C0',
-	// gridLineDashStyle: 'solid', // docs
-	// gridLineWidth: 0,
-	// reversed: false,
-
-	labels: defaultLabelOptions,
-		// { step: null },
-	lineColor: '#C0D0E0',
-	lineWidth: 1,
-	//linkedTo: null,
-	max: null,
-	min: null,
-	minPadding: 0.01,
-	maxPadding: 0.01,
-	//maxZoom: null,
-	minorGridLineColor: '#E0E0E0',
-	// minorGridLineDashStyle: null,
-	minorGridLineWidth: 1,
-	minorTickColor: '#A0A0A0',
-	//minorTickInterval: null,
-	minorTickLength: 2,
-	minorTickPosition: 'outside', // inside or outside
-	//minorTickWidth: 0,
-	//opposite: false,
-	//offset: 0,
-	//plotBands: [{
-	//	events: {},
-	//	zIndex: 1,
-	//	labels: { align, x, verticalAlign, y, style, rotation, textAlign }
-	//}],
-	//plotLines: [{
-	//	events: {}
-	//  dashStyle: {}
-	//	zIndex:
-	//	labels: { align, x, verticalAlign, y, style, rotation, textAlign }
-	//}],
-	//reversed: false,
-	// showFirstLabel: true,
-	// showLastLabel: false,
-	startOfWeek: 1,
-	startOnTick: false,
-	tickColor: '#C0D0E0',
-	//tickInterval: null,
-	tickLength: 5,
-	tickmarkPlacement: 'between', // on or between
-	tickPixelInterval: 100,
-	tickPosition: 'outside',
-	tickWidth: 1,
-	title: {
-		//text: null,
-		align: 'middle', // low, middle or high
-		//margin: 0 for horizontal, 10 for vertical axes,
-		//rotation: 0,
-		//side: 'outside',
-		style: {
-			color: '#6D869F',
-			//font: defaultFont.replace('normal', 'bold')
-			fontWeight: 'bold'
-		}
-		//x: 0,
-		//y: 0
-	},
-	type: 'linear' // linear, logarithmic or datetime
-},
-
-defaultYAxisOptions = merge(defaultXAxisOptions, {
-	endOnTick: true,
-	gridLineWidth: 1,
-	tickPixelInterval: 72,
-	showLastLabel: true,
-	labels: {
-		align: 'right',
-		x: -8,
-		y: 3
-	},
-	lineWidth: 0,
-	maxPadding: 0.05,
-	minPadding: 0.05,
-	startOnTick: true,
-	tickWidth: 0,
-	title: {
-		rotation: 270,
-		text: 'Y-values'
-	},
-	stackLabels: {
-		enabled: false,
-		//align: dynamic,
-		//y: dynamic,
-		//x: dynamic,
-		//verticalAlign: dynamic,
-		//textAlign: dynamic,
-		//rotation: 0,
-		formatter: function () {
-			return this.total;
-		},
-		style: defaultLabelOptions.style
-	}
-}),
-
-defaultLeftAxisOptions = {
-	labels: {
-		align: 'right',
-		x: -8,
-		y: null
-	},
-	title: {
-		rotation: 270
-	}
-},
-defaultRightAxisOptions = {
-	labels: {
-		align: 'left',
-		x: 8,
-		y: null
-	},
-	title: {
-		rotation: 90
-	}
-},
-defaultBottomAxisOptions = { // horizontal axis
-	labels: {
-		align: 'center',
-		x: 0,
-		y: 14
-		// staggerLines: null
-	},
-	title: {
-		rotation: 0
-	}
-},
-defaultTopAxisOptions = merge(defaultBottomAxisOptions, {
-	labels: {
-		y: -5
-		// staggerLines: null
-	}
-});
-
-
-
-
-// Series defaults
-var defaultPlotOptions = defaultOptions.plotOptions,
-	defaultSeriesOptions = defaultPlotOptions.line;
-//defaultPlotOptions.line = merge(defaultSeriesOptions);
-defaultPlotOptions.spline = merge(defaultSeriesOptions);
-defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
-	lineWidth: 0,
-	states: {
-		hover: {
-			lineWidth: 0
-		}
-	}
-});
-defaultPlotOptions.area = merge(defaultSeriesOptions, {
-	// threshold: 0,
-	// lineColor: null, // overrides color, but lets fillColor be unaltered
-	// fillOpacity: 0.75,
-	// fillColor: null
-
-});
-defaultPlotOptions.areaspline = merge(defaultPlotOptions.area);
-defaultPlotOptions.column = merge(defaultSeriesOptions, {
-	borderColor: '#FFFFFF',
-	borderWidth: 1,
-	borderRadius: 0,
-	//colorByPoint: undefined,
-	groupPadding: 0.2,
-	marker: null, // point options are specified in the base options
-	pointPadding: 0.1,
-	//pointWidth: null,
-	minPointLength: 0,
-	states: {
-		hover: {
-			brightness: 0.1,
-			shadow: false
-		},
-		select: {
-			color: '#C0C0C0',
-			borderColor: '#000000',
-			shadow: false
-		}
-	},
-	dataLabels: {
-		y: null,
-		verticalAlign: null
-	}
-});
-defaultPlotOptions.bar = merge(defaultPlotOptions.column, {
-	dataLabels: {
-		align: 'left',
-		x: 5,
-		y: 0
-	}
-});
-defaultPlotOptions.pie = merge(defaultSeriesOptions, {
-	//dragType: '', // n/a
-	borderColor: '#FFFFFF',
-	borderWidth: 1,
-	center: ['50%', '50%'],
-	colorByPoint: true, // always true for pies
-	dataLabels: {
-		// align: null,
-		// connectorWidth: 1,
-		// connectorColor: point.color,
-		// connectorPadding: 5,
-		distance: 30,
-		enabled: true,
-		formatter: function () {
-			return this.point.name;
-		},
-		// softConnector: true,
-		y: 5
-	},
-	//innerSize: 0,
-	legendType: 'point',
-	marker: null, // point options are specified in the base options
-	size: '75%',
-	showInLegend: false,
-	slicedOffset: 10,
-	states: {
-		hover: {
-			brightness: 0.1,
-			shadow: false
-		}
-	}
-
-});
-
-// set the default time methods
-setTimeMethods();
-
-
-/**
- * Handle color operations. The object methods are chainable.
- * @param {String} input The input color in either rbga or hex format
- */
-var Color = function (input) {
-	// declare variables
-	var rgba = [], result;
-
-	/**
-	 * Parse the input color to rgba array
-	 * @param {String} input
-	 */
-	function init(input) {
-
-		// rgba
-		result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input);
-		if (result) {
-			rgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)];
-		} else { // hex
-			result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input);
-			if (result) {
-				rgba = [pInt(result[1], 16), pInt(result[2], 16), pInt(result[3], 16), 1];
-			}
-		}
-
-	}
-	/**
-	 * Return the color a specified format
-	 * @param {String} format
-	 */
-	function get(format) {
-		var ret;
-
-		// it's NaN if gradient colors on a column chart
-		if (rgba && !isNaN(rgba[0])) {
-			if (format === 'rgb') {
-				ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')';
-			} else if (format === 'a') {
-				ret = rgba[3];
-			} else {
-				ret = 'rgba(' + rgba.join(',') + ')';
-			}
-		} else {
-			ret = input;
-		}
-		return ret;
-	}
-
-	/**
-	 * Brighten the color
-	 * @param {Number} alpha
-	 */
-	function brighten(alpha) {
-		if (isNumber(alpha) && alpha !== 0) {
-			var i;
-			for (i = 0; i < 3; i++) {
-				rgba[i] += pInt(alpha * 255);
-
-				if (rgba[i] < 0) {
-					rgba[i] = 0;
-				}
-				if (rgba[i] > 255) {
-					rgba[i] = 255;
-				}
-			}
-		}
-		return this;
-	}
-	/**
-	 * Set the color's opacity to a given alpha value
-	 * @param {Number} alpha
-	 */
-	function setOpacity(alpha) {
-		rgba[3] = alpha;
-		return this;
-	}
-
-	// initialize: parse the input
-	init(input);
-
-	// public methods
-	return {
-		get: get,
-		brighten: brighten,
-		setOpacity: setOpacity
-	};
-};
-
-/**
- * A wrapper object for SVG elements
- */
-function SVGElement() {}
-
-SVGElement.prototype = {
-	/**
-	 * Initialize the SVG renderer
-	 * @param {Object} renderer
-	 * @param {String} nodeName
-	 */
-	init: function (renderer, nodeName) {
-		this.element = doc.createElementNS(SVG_NS, nodeName);
-		this.renderer = renderer;
-	},
-	/**
-	 * Animate a given attribute
-	 * @param {Object} params
-	 * @param {Number} options The same options as in jQuery animation
-	 * @param {Function} complete Function to perform at the end of animation
-	 */
-	animate: function (params, options, complete) {
-		var animOptions = pick(options, globalAnimation, true);
-		if (animOptions) {
-			animOptions = merge(animOptions);
-			if (complete) { // allows using a callback with the global animation without overwriting it
-				animOptions.complete = complete;
-			}
-			animate(this, params, animOptions);
-		} else {
-			this.attr(params);
-			if (complete) {
-				complete();
-			}
-		}
-	},
-	/**
-	 * Set or get a given attribute
-	 * @param {Object|String} hash
-	 * @param {Mixed|Undefined} val
-	 */
-	attr: function (hash, val) {
-		var key,
-			value,
-			i,
-			child,
-			element = this.element,
-			nodeName = element.nodeName,
-			renderer = this.renderer,
-			skipAttr,
-			shadows = this.shadows,
-			htmlNode = this.htmlNode,
-			hasSetSymbolSize,
-			ret = this;
-
-		// single key-value pair
-		if (isString(hash) && defined(val)) {
-			key = hash;
-			hash = {};
-			hash[key] = val;
-		}
-
-		// used as a getter: first argument is a string, second is undefined
-		if (isString(hash)) {
-			key = hash;
-			if (nodeName === 'circle') {
-				key = { x: 'cx', y: 'cy' }[key] || key;
-			} else if (key === 'strokeWidth') {
-				key = 'stroke-width';
-			}
-			ret = attr(element, key) || this[key] || 0;
-
-			if (key !== 'd' && key !== 'visibility') { // 'd' is string in animation step
-				ret = parseFloat(ret);
-			}
-
-		// setter
-		} else {
-
-			for (key in hash) {
-				skipAttr = false; // reset
-				value = hash[key];
-
-				// paths
-				if (key === 'd') {
-					if (value && value.join) { // join path
-						value = value.join(' ');
-					}
-					if (/(NaN| {2}|^$)/.test(value)) {
-						value = 'M 0 0';
-					}
-					this.d = value; // shortcut for animations
-
-				// update child tspans x values
-				} else if (key === 'x' && nodeName === 'text') {
-					for (i = 0; i < element.childNodes.length; i++) {
-						child = element.childNodes[i];
-						// if the x values are equal, the tspan represents a linebreak
-						if (attr(child, 'x') === attr(element, 'x')) {
-							//child.setAttribute('x', value);
-							attr(child, 'x', value);
-						}
-					}
-
-					if (this.rotation) {
-						attr(element, 'transform', 'rotate(' + this.rotation + ' ' + value + ' ' +
-							pInt(hash.y || attr(element, 'y')) + ')');
-					}
-
-				// apply gradients
-				} else if (key === 'fill') {
-					value = renderer.color(value, element, key);
-
-				// circle x and y
-				} else if (nodeName === 'circle' && (key === 'x' || key === 'y')) {
-					key = { x: 'cx', y: 'cy' }[key] || key;
-
-				// translation and text rotation
-				} else if (key === 'translateX' || key === 'translateY' || key === 'rotation' || key === 'verticalAlign') {
-					this[key] = value;
-					this.updateTransform();
-					skipAttr = true;
-
-				// apply opacity as subnode (required by legacy WebKit and Batik)
-				} else if (key === 'stroke') {
-					value = renderer.color(value, element, key);
-
-				// emulate VML's dashstyle implementation
-				} else if (key === 'dashstyle') {
-					key = 'stroke-dasharray';
-					value = value && value.toLowerCase();
-					if (value === 'solid') {
-						value = NONE;
-					} else if (value) {
-						value = value
-							.replace('shortdashdotdot', '3,1,1,1,1,1,')
-							.replace('shortdashdot', '3,1,1,1')
-							.replace('shortdot', '1,1,')
-							.replace('shortdash', '3,1,')
-							.replace('longdash', '8,3,')
-							.replace(/dot/g, '1,3,')
-							.replace('dash', '4,3,')
-							.replace(/,$/, '')
-							.split(','); // ending comma
-
-						i = value.length;
-						while (i--) {
-							value[i] = pInt(value[i]) * hash['stroke-width'];
-						}
-
-						value = value.join(',');
-					}
-
-				// special
-				} else if (key === 'isTracker') {
-					this[key] = value;
-
-				// IE9/MooTools combo: MooTools returns objects instead of numbers and IE9 Beta 2
-				// is unable to cast them. Test again with final IE9.
-				} else if (key === 'width') {
-					value = pInt(value);
-
-				// Text alignment
-				} else if (key === 'align') {
-					key = 'text-anchor';
-					value = { left: 'start', center: 'middle', right: 'end' }[value];
-
-
-				// Title requires a subnode, #431
-				} else if (key === 'title') {
-					var title = doc.createElementNS(SVG_NS, 'title');
-					title.appendChild(doc.createTextNode(value));
-					element.appendChild(title);
-				}
-
-
-
-				// jQuery animate changes case
-				if (key === 'strokeWidth') {
-					key = 'stroke-width';
-				}
-
-				// Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461)
-				if (isWebKit && key === 'stroke-width' && value === 0) {
-					value = 0.000001;
-				}
-
-				// symbols
-				if (this.symbolName && /^(x|y|r|start|end|innerR)/.test(key)) {
-
-
-					if (!hasSetSymbolSize) {
-						this.symbolAttr(hash);
-						hasSetSymbolSize = true;
-					}
-					skipAttr = true;
-				}
-
-				// let the shadow follow the main element
-				if (shadows && /^(width|height|visibility|x|y|d)$/.test(key)) {
-					i = shadows.length;
-					while (i--) {
-						attr(shadows[i], key, value);
-					}
-				}
-
-				// validate heights
-				if ((key === 'width' || key === 'height') && nodeName === 'rect' && value < 0) {
-					value = 0;
-				}
-
-				if (key === 'text') {
-					// only one node allowed
-					this.textStr = value;
-					if (this.added) {
-						renderer.buildText(this);
-					}
-				} else if (!skipAttr) {
-					//element.setAttribute(key, value);
-					attr(element, key, value);
-				}
-
-				// Issue #38
-				if (htmlNode && (key === 'x' || key === 'y' ||
-						key === 'translateX' || key === 'translateY' || key === 'visibility')) {
-					var wrapper = this,
-						bBox,
-						arr = htmlNode.length ? htmlNode : [this],
-						length = arr.length,
-						itemWrapper,
-						j;
-
-					for (j = 0; j < length; j++) {
-						itemWrapper = arr[j];
-						bBox = itemWrapper.getBBox();
-						htmlNode = itemWrapper.htmlNode; // reassign to child item
-						css(htmlNode, extend(wrapper.styles, {
-							left: (bBox.x + (wrapper.translateX || 0)) + PX,
-							top: (bBox.y + (wrapper.translateY || 0)) + PX
-						}));
-
-						if (key === 'visibility') {
-							css(htmlNode, {
-								visibility: value
-							});
-						}
-					}
-				}
-
-			}
-
-		}
-		return ret;
-	},
-
-	/**
-	 * If one of the symbol size affecting parameters are changed,
-	 * check all the others only once for each call to an element's
-	 * .attr() method
-	 * @param {Object} hash
-	 */
-	symbolAttr: function (hash) {
-		var wrapper = this;
-
-		each(['x', 'y', 'r', 'start', 'end', 'width', 'height', 'innerR'], function (key) {
-			wrapper[key] = pick(hash[key], wrapper[key]);
-		});
-
-		wrapper.attr({
-			d: wrapper.renderer.symbols[wrapper.symbolName](
-					mathRound(wrapper.x * 2) / 2, // Round to halves. Issue #274.
-					mathRound(wrapper.y * 2) / 2,
-					wrapper.r,
-					{
-						start: wrapper.start,
-						end: wrapper.end,
-						width: wrapper.width,
-						height: wrapper.height,
-						innerR: wrapper.innerR
-					}
-			)
-		});
-	},
-
-	/**
-	 * Apply a clipping path to this object
-	 * @param {String} id
-	 */
-	clip: function (clipRect) {
-		return this.attr('clip-path', 'url(' + this.renderer.url + '#' + clipRect.id + ')');
-	},
-
-	/**
-	 * Calculate the coordinates needed for drawing a rectangle crisply and return the
-	 * calculated attributes
-	 * @param {Number} strokeWidth
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	crisp: function (strokeWidth, x, y, width, height) {
-
-		var wrapper = this,
-			key,
-			attr = {},
-			values = {},
-			normalizer;
-
-		strokeWidth = strokeWidth || wrapper.strokeWidth || 0;
-		normalizer = strokeWidth % 2 / 2;
-
-		// normalize for crisp edges
-		values.x = mathFloor(x || wrapper.x || 0) + normalizer;
-		values.y = mathFloor(y || wrapper.y || 0) + normalizer;
-		values.width = mathFloor((width || wrapper.width || 0) - 2 * normalizer);
-		values.height = mathFloor((height || wrapper.height || 0) - 2 * normalizer);
-		values.strokeWidth = strokeWidth;
-
-		for (key in values) {
-			if (wrapper[key] !== values[key]) { // only set attribute if changed
-				wrapper[key] = attr[key] = values[key];
-			}
-		}
-
-		return attr;
-	},
-
-	/**
-	 * Set styles for the element
-	 * @param {Object} styles
-	 */
-	css: function (styles) {
-		/*jslint unparam: true*//* allow unused param a in the regexp function below */
-		var elemWrapper = this,
-			elem = elemWrapper.element,
-			textWidth = styles && styles.width && elem.nodeName === 'text',
-			n,
-			serializedCss = '',
-			hyphenate = function (a, b) { return '-' + b.toLowerCase(); };
-		/*jslint unparam: false*/
-
-		// convert legacy
-		if (styles && styles.color) {
-			styles.fill = styles.color;
-		}
-
-		// Merge the new styles with the old ones
-		styles = extend(
-			elemWrapper.styles,
-			styles
-		);
-
-
-		// store object
-		elemWrapper.styles = styles;
-
-
-		// serialize and set style attribute
-		if (isIE && !hasSVG) { // legacy IE doesn't support setting style attribute
-			if (textWidth) {
-				delete styles.width;
-			}
-			css(elemWrapper.element, styles);
-		} else {
-			for (n in styles) {
-				serializedCss += n.replace(/([A-Z])/g, hyphenate) + ':' + styles[n] + ';';
-			}
-			elemWrapper.attr({
-				style: serializedCss
-			});
-		}
-
-
-		// re-build text
-		if (textWidth && elemWrapper.added) {
-			elemWrapper.renderer.buildText(elemWrapper);
-		}
-
-		return elemWrapper;
-	},
-
-	/**
-	 * Add an event listener
-	 * @param {String} eventType
-	 * @param {Function} handler
-	 */
-	on: function (eventType, handler) {
-		var fn = handler;
-		// touch
-		if (hasTouch && eventType === 'click') {
-			eventType = 'touchstart';
-			fn = function (e) {
-				e.preventDefault();
-				handler();
-			};
-		}
-		// simplest possible event model for internal use
-		this.element['on' + eventType] = fn;
-		return this;
-	},
-
-
-	/**
-	 * Move an object and its children by x and y values
-	 * @param {Number} x
-	 * @param {Number} y
-	 */
-	translate: function (x, y) {
-		return this.attr({
-			translateX: x,
-			translateY: y
-		});
-	},
-
-	/**
-	 * Invert a group, rotate and flip
-	 */
-	invert: function () {
-		var wrapper = this;
-		wrapper.inverted = true;
-		wrapper.updateTransform();
-		return wrapper;
-	},
-
-	/**
-	 * Private method to update the transform attribute based on internal
-	 * properties
-	 */
-	updateTransform: function () {
-		var wrapper = this,
-			translateX = wrapper.translateX || 0,
-			translateY = wrapper.translateY || 0,
-			inverted = wrapper.inverted,
-			rotation = wrapper.rotation,
-			transform = [];
-
-		// flipping affects translate as adjustment for flipping around the group's axis
-		if (inverted) {
-			translateX += wrapper.attr('width');
-			translateY += wrapper.attr('height');
-		}
-
-		// apply translate
-		if (translateX || translateY) {
-			transform.push('translate(' + translateX + ',' + translateY + ')');
-		}
-
-		// apply rotation
-		if (inverted) {
-			transform.push('rotate(90) scale(-1,1)');
-		} else if (rotation) { // text rotation
-			transform.push('rotate(' + rotation + ' ' + wrapper.x + ' ' + wrapper.y + ')');
-		}
-
-		if (transform.length) {
-			attr(wrapper.element, 'transform', transform.join(' '));
-		}
-	},
-	/**
-	 * Bring the element to the front
-	 */
-	toFront: function () {
-		var element = this.element;
-		element.parentNode.appendChild(element);
-		return this;
-	},
-
-
-	/**
-	 * Break down alignment options like align, verticalAlign, x and y
-	 * to x and y relative to the chart.
-	 *
-	 * @param {Object} alignOptions
-	 * @param {Boolean} alignByTranslate
-	 * @param {Object} box The box to align to, needs a width and height
-	 *
-	 */
-	align: function (alignOptions, alignByTranslate, box) {
-		var elemWrapper = this;
-
-		if (!alignOptions) { // called on resize
-			alignOptions = elemWrapper.alignOptions;
-			alignByTranslate = elemWrapper.alignByTranslate;
-		} else { // first call on instanciate
-			elemWrapper.alignOptions = alignOptions;
-			elemWrapper.alignByTranslate = alignByTranslate;
-			if (!box) { // boxes other than renderer handle this internally
-				elemWrapper.renderer.alignedObjects.push(elemWrapper);
-			}
-		}
-
-		box = pick(box, elemWrapper.renderer);
-
-		var align = alignOptions.align,
-			vAlign = alignOptions.verticalAlign,
-			x = (box.x || 0) + (alignOptions.x || 0), // default: left align
-			y = (box.y || 0) + (alignOptions.y || 0), // default: top align
-			attribs = {};
-
-
-		// align
-		if (/^(right|center)$/.test(align)) {
-			x += (box.width - (alignOptions.width || 0)) /
-					{ right: 1, center: 2 }[align];
-		}
-		attribs[alignByTranslate ? 'translateX' : 'x'] = mathRound(x);
-
-
-		// vertical align
-		if (/^(bottom|middle)$/.test(vAlign)) {
-			y += (box.height - (alignOptions.height || 0)) /
-					({ bottom: 1, middle: 2 }[vAlign] || 1);
-
-		}
-		attribs[alignByTranslate ? 'translateY' : 'y'] = mathRound(y);
-
-		// animate only if already placed
-		elemWrapper[elemWrapper.placed ? 'animate' : 'attr'](attribs);
-		elemWrapper.placed = true;
-		elemWrapper.alignAttr = attribs;
-
-		return elemWrapper;
-	},
-
-	/**
-	 * Get the bounding box (width, height, x and y) for the element
-	 */
-	getBBox: function () {
-		var bBox,
-			width,
-			height,
-			rotation = this.rotation,
-			rad = rotation * deg2rad;
-
-		try { // fails in Firefox if the container has display: none
-			// use extend because IE9 is not allowed to change width and height in case
-			// of rotation (below)
-			bBox = extend({}, this.element.getBBox());
-		} catch (e) {
-			bBox = { width: 0, height: 0 };
-		}
-		width = bBox.width;
-		height = bBox.height;
-
-		// adjust for rotated text
-		if (rotation) {
-			bBox.width = mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad));
-			bBox.height = mathAbs(height * mathCos(rad)) + mathAbs(width * mathSin(rad));
-		}
-
-		return bBox;
-	},
-
-	/* *
-	 * Manually compute width and height of rotated text from non-rotated. Shared by SVG and VML
-	 * @param {Object} bBox
-	 * @param {number} rotation
-	 * /
-	rotateBBox: function(bBox, rotation) {
-		var rad = rotation * math.PI * 2 / 360, // radians
-			width = bBox.width,
-			height = bBox.height;
-
-
-	},*/
-
-	/**
-	 * Show the element
-	 */
-	show: function () {
-		return this.attr({ visibility: VISIBLE });
-	},
-
-	/**
-	 * Hide the element
-	 */
-	hide: function () {
-		return this.attr({ visibility: HIDDEN });
-	},
-
-	/**
-	 * Add the element
-	 * @param {Object|Undefined} parent Can be an element, an element wrapper or undefined
-	 *    to append the element to the renderer.box.
-	 */
-	add: function (parent) {
-
-		var renderer = this.renderer,
-			parentWrapper = parent || renderer,
-			parentNode = parentWrapper.element || renderer.box,
-			childNodes = parentNode.childNodes,
-			element = this.element,
-			zIndex = attr(element, 'zIndex'),
-			otherElement,
-			otherZIndex,
-			i;
-
-		// mark as inverted
-		this.parentInverted = parent && parent.inverted;
-
-		// build formatted text
-		if (this.textStr !== undefined) {
-			renderer.buildText(this);
-		}
-
-		// register html spans in groups
-		if (parent && this.htmlNode) {
-			if (!parent.htmlNode) {
-				parent.htmlNode = [];
-			}
-			parent.htmlNode.push(this);
-		}
-
-		// mark the container as having z indexed children
-		if (zIndex) {
-			parentWrapper.handleZ = true;
-			zIndex = pInt(zIndex);
-		}
-
-		// insert according to this and other elements' zIndex
-		if (parentWrapper.handleZ) { // this element or any of its siblings has a z index
-			for (i = 0; i < childNodes.length; i++) {
-				otherElement = childNodes[i];
-				otherZIndex = attr(otherElement, 'zIndex');
-				if (otherElement !== element && (
-						// insert before the first element with a higher zIndex
-						pInt(otherZIndex) > zIndex ||
-						// if no zIndex given, insert before the first element with a zIndex
-						(!defined(zIndex) && defined(otherZIndex))
-
-						)) {
-					parentNode.insertBefore(element, otherElement);
-					return this;
-				}
-			}
-		}
-
-		// default: append at the end
-		parentNode.appendChild(element);
-
-		this.added = true;
-
-		return this;
-	},
-
-	/**
-	 * Removes a child either by removeChild or move to garbageBin.
-	 * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not.
-	 */
-	safeRemoveChild: function (element) {
-		var parentNode = element.parentNode;
-		if (parentNode) {
-			parentNode.removeChild(element);
-		}
-	},
-
-	/**
-	 * Destroy the element and element wrapper
-	 */
-	destroy: function () {
-		var wrapper = this,
-			element = wrapper.element || {},
-			shadows = wrapper.shadows,
-			key,
-			i;
-
-		// remove events
-		element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = null;
-		stop(wrapper); // stop running animations
-
-		if (wrapper.clipPath) {
-			wrapper.clipPath = wrapper.clipPath.destroy();
-		}
-
-		// Destroy stops in case this is a gradient object
-		if (wrapper.stops) {
-			for (i = 0; i < wrapper.stops.length; i++) {
-				wrapper.stops[i] = wrapper.stops[i].destroy();
-			}
-			wrapper.stops = null;
-		}
-
-		// remove element
-		wrapper.safeRemoveChild(element);
-
-		// destroy shadows
-		if (shadows) {
-			each(shadows, function (shadow) {
-				wrapper.safeRemoveChild(shadow);
-			});
-		}
-
-		// remove from alignObjects
-		erase(wrapper.renderer.alignedObjects, wrapper);
-
-		for (key in wrapper) {
-			delete wrapper[key];
-		}
-
-		return null;
-	},
-
-	/**
-	 * Empty a group element
-	 */
-	empty: function () {
-		var element = this.element,
-			childNodes = element.childNodes,
-			i = childNodes.length;
-
-		while (i--) {
-			element.removeChild(childNodes[i]);
-		}
-	},
-
-	/**
-	 * Add a shadow to the element. Must be done after the element is added to the DOM
-	 * @param {Boolean} apply
-	 */
-	shadow: function (apply, group) {
-		var shadows = [],
-			i,
-			shadow,
-			element = this.element,
-
-			// compensate for inverted plot area
-			transform = this.parentInverted ? '(-1,-1)' : '(1,1)';
-
-
-		if (apply) {
-			for (i = 1; i <= 3; i++) {
-				shadow = element.cloneNode(0);
-				attr(shadow, {
-					'isShadow': 'true',
-					'stroke': 'rgb(0, 0, 0)',
-					'stroke-opacity': 0.05 * i,
-					'stroke-width': 7 - 2 * i,
-					'transform': 'translate' + transform,
-					'fill': NONE
-				});
-
-				if (group) {
-					group.element.appendChild(shadow);
-				} else {
-					element.parentNode.insertBefore(shadow, element);
-				}
-
-				shadows.push(shadow);
-			}
-
-			this.shadows = shadows;
-		}
-		return this;
-
-	}
-};
-
-/**
- * The default SVG renderer
- */
-var SVGRenderer = function () {
-	this.init.apply(this, arguments);
-};
-SVGRenderer.prototype = {
-
-	Element: SVGElement,
-
-	/**
-	 * Initialize the SVGRenderer
-	 * @param {Object} container
-	 * @param {Number} width
-	 * @param {Number} height
-	 * @param {Boolean} forExport
-	 */
-	init: function (container, width, height, forExport) {
-		var renderer = this,
-			loc = location,
-			boxWrapper;
-
-		boxWrapper = renderer.createElement('svg')
-			.attr({
-				xmlns: SVG_NS,
-				version: '1.1'
-			});
-		container.appendChild(boxWrapper.element);
-
-		// object properties
-		renderer.box = boxWrapper.element;
-		renderer.boxWrapper = boxWrapper;
-		renderer.alignedObjects = [];
-		renderer.url = isIE ? '' : loc.href.replace(/#.*?$/, ''); // page url used for internal references
-		renderer.defs = this.createElement('defs').add();
-		renderer.forExport = forExport;
-		renderer.gradients = []; // Array where gradient SvgElements are stored
-
-		renderer.setSize(width, height, false);
-
-	},
-
-	/**
-	 * Destroys the renderer and its allocated members.
-	 */
-	destroy: function () {
-		var renderer = this,
-			i,
-			rendererGradients = renderer.gradients,
-			rendererDefs = renderer.defs;
-		renderer.box = null;
-		renderer.boxWrapper = renderer.boxWrapper.destroy();
-
-		// Call destroy on all gradient elements
-		if (rendererGradients) { // gradients are null in VMLRenderer
-			for (i = 0; i < rendererGradients.length; i++) {
-				renderer.gradients[i] = rendererGradients[i].destroy();
-			}
-			renderer.gradients = null;
-		}
-
-		// Defs are null in VMLRenderer
-		// Otherwise, destroy them here.
-		if (rendererDefs) {
-			renderer.defs = rendererDefs.destroy();
-		}
-
-		renderer.alignedObjects = null;
-
-		return null;
-	},
-
-	/**
-	 * Create a wrapper for an SVG element
-	 * @param {Object} nodeName
-	 */
-	createElement: function (nodeName) {
-		var wrapper = new this.Element();
-		wrapper.init(this, nodeName);
-		return wrapper;
-	},
-
-
-	/**
-	 * Parse a simple HTML string into SVG tspans
-	 *
-	 * @param {Object} textNode The parent text SVG node
-	 */
-	buildText: function (wrapper) {
-		var textNode = wrapper.element,
-			lines = pick(wrapper.textStr, '').toString()
-				.replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
-				.replace(/<(i|em)>/g, '<span style="font-style:italic">')
-				.replace(/<a/g, '<span')
-				.replace(/<\/(b|strong|i|em|a)>/g, '</span>')
-				.split(/<br.*?>/g),
-			childNodes = textNode.childNodes,
-			styleRegex = /style="([^"]+)"/,
-			hrefRegex = /href="([^"]+)"/,
-			parentX = attr(textNode, 'x'),
-			textStyles = wrapper.styles,
-			renderAsHtml = textStyles && wrapper.useHTML && !this.forExport,
-			htmlNode = wrapper.htmlNode,
-			//arr, issue #38 workaround
-			width = textStyles && pInt(textStyles.width),
-			textLineHeight = textStyles && textStyles.lineHeight,
-			lastLine,
-			GET_COMPUTED_STYLE = 'getComputedStyle',
-			i = childNodes.length;
-
-		// remove old text
-		while (i--) {
-			textNode.removeChild(childNodes[i]);
-		}
-
-		if (width && !wrapper.added) {
-			this.box.appendChild(textNode); // attach it to the DOM to read offset width
-		}
-
-		each(lines, function (line, lineNo) {
-			var spans, spanNo = 0, lineHeight;
-
-			line = line.replace(/<span/g, '|||<span').replace(/<\/span>/g, '</span>|||');
-			spans = line.split('|||');
-
-			each(spans, function (span) {
-				if (span !== '' || spans.length === 1) {
-					var attributes = {},
-						tspan = doc.createElementNS(SVG_NS, 'tspan');
-					if (styleRegex.test(span)) {
-						attr(
-							tspan,
-							'style',
-							span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2')
-						);
-					}
-					if (hrefRegex.test(span)) {
-						attr(tspan, 'onclick', 'location.href=\"' + span.match(hrefRegex)[1] + '\"');
-						css(tspan, { cursor: 'pointer' });
-					}
-
-					span = (span.replace(/<(.|\n)*?>/g, '') || ' ')
-						.replace(/&lt;/g, '<')
-						.replace(/&gt;/g, '>');
-
-					// issue #38 workaround.
-					/*if (reverse) {
-						arr = [];
-						i = span.length;
-						while (i--) {
-							arr.push(span.charAt(i));
-						}
-						span = arr.join('');
-					}*/
-
-					// add the text node
-					tspan.appendChild(doc.createTextNode(span));
-
-					if (!spanNo) { // first span in a line, align it to the left
-						attributes.x = parentX;
-					} else {
-						// Firefox ignores spaces at the front or end of the tspan
-						attributes.dx = 3; // space
-					}
-
-					// first span on subsequent line, add the line height
-					if (!spanNo) {
-						if (lineNo) {
-
-							// allow getting the right offset height in exporting in IE
-							if (!hasSVG && wrapper.renderer.forExport) {
-								css(tspan, { display: 'block' });
-							}
-
-							// Webkit and opera sometimes return 'normal' as the line height. In that
-							// case, webkit uses offsetHeight, while Opera falls back to 18
-							lineHeight = win[GET_COMPUTED_STYLE] &&
-								pInt(win[GET_COMPUTED_STYLE](lastLine, null).getPropertyValue('line-height'));
-
-							if (!lineHeight || isNaN(lineHeight)) {
-								lineHeight = textLineHeight || lastLine.offsetHeight || 18;
-							}
-							attr(tspan, 'dy', lineHeight);
-						}
-						lastLine = tspan; // record for use in next line
-					}
-
-					// add attributes
-					attr(tspan, attributes);
-
-					// append it
-					textNode.appendChild(tspan);
-
-					spanNo++;
-
-					// check width and apply soft breaks
-					if (width) {
-						var words = span.replace(/-/g, '- ').split(' '),
-							tooLong,
-							actualWidth,
-							rest = [];
-
-						while (words.length || rest.length) {
-							actualWidth = textNode.getBBox().width;
-							tooLong = actualWidth > width;
-							if (!tooLong || words.length === 1) { // new line needed
-								words = rest;
-								rest = [];
-								if (words.length) {
-									tspan = doc.createElementNS(SVG_NS, 'tspan');
-									attr(tspan, {
-										dy: textLineHeight || 16,
-										x: parentX
-									});
-									textNode.appendChild(tspan);
-
-									if (actualWidth > width) { // a single word is pressing it out
-										width = actualWidth;
-									}
-								}
-							} else { // append to existing line tspan
-								tspan.removeChild(tspan.firstChild);
-								rest.unshift(words.pop());
-							}
-							if (words.length) {
-								tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
-							}
-						}
-					}
-				}
-			});
-		});
-
-		// Fix issue #38 and allow HTML in tooltips and other labels
-		if (renderAsHtml) {
-			if (!htmlNode) {
-				htmlNode = wrapper.htmlNode = createElement('span', null, extend(textStyles, {
-					position: ABSOLUTE,
-					top: 0,
-					left: 0
-				}), this.box.parentNode);
-			}
-			htmlNode.innerHTML = wrapper.textStr;
-
-			i = childNodes.length;
-			while (i--) {
-				childNodes[i].style.visibility = HIDDEN;
-			}
-		}
-	},
-
-	/**
-	 * Make a straight line crisper by not spilling out to neighbour pixels
-	 * @param {Array} points
-	 * @param {Number} width
-	 */
-	crispLine: function (points, width) {
-		// points format: [M, 0, 0, L, 100, 0]
-		// normalize to a crisp line
-		if (points[1] === points[4]) {
-			points[1] = points[4] = mathRound(points[1]) + (width % 2 / 2);
-		}
-		if (points[2] === points[5]) {
-			points[2] = points[5] = mathRound(points[2]) + (width % 2 / 2);
-		}
-		return points;
-	},
-
-
-	/**
-	 * Draw a path
-	 * @param {Array} path An SVG path in array form
-	 */
-	path: function (path) {
-		return this.createElement('path').attr({
-			d: path,
-			fill: NONE
-		});
-	},
-
-	/**
-	 * Draw and return an SVG circle
-	 * @param {Number} x The x position
-	 * @param {Number} y The y position
-	 * @param {Number} r The radius
-	 */
-	circle: function (x, y, r) {
-		var attr = isObject(x) ?
-			x :
-			{
-				x: x,
-				y: y,
-				r: r
-			};
-
-		return this.createElement('circle').attr(attr);
-	},
-
-	/**
-	 * Draw and return an arc
-	 * @param {Number} x X position
-	 * @param {Number} y Y position
-	 * @param {Number} r Radius
-	 * @param {Number} innerR Inner radius like used in donut charts
-	 * @param {Number} start Starting angle
-	 * @param {Number} end Ending angle
-	 */
-	arc: function (x, y, r, innerR, start, end) {
-		// arcs are defined as symbols for the ability to set
-		// attributes in attr and animate
-
-		if (isObject(x)) {
-			y = x.y;
-			r = x.r;
-			innerR = x.innerR;
-			start = x.start;
-			end = x.end;
-			x = x.x;
-		}
-
-		return this.symbol('arc', x || 0, y || 0, r || 0, {
-			innerR: innerR || 0,
-			start: start || 0,
-			end: end || 0
-		});
-	},
-
-	/**
-	 * Draw and return a rectangle
-	 * @param {Number} x Left position
-	 * @param {Number} y Top position
-	 * @param {Number} width
-	 * @param {Number} height
-	 * @param {Number} r Border corner radius
-	 * @param {Number} strokeWidth A stroke width can be supplied to allow crisp drawing
-	 */
-	rect: function (x, y, width, height, r, strokeWidth) {
-		if (isObject(x)) {
-			y = x.y;
-			width = x.width;
-			height = x.height;
-			r = x.r;
-			strokeWidth = x.strokeWidth;
-			x = x.x;
-		}
-		var wrapper = this.createElement('rect').attr({
-			rx: r,
-			ry: r,
-			fill: NONE
-		});
-
-		return wrapper.attr(wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)));
-	},
-
-	/**
-	 * Resize the box and re-align all aligned elements
-	 * @param {Object} width
-	 * @param {Object} height
-	 * @param {Boolean} animate
-	 *
-	 */
-	setSize: function (width, height, animate) {
-		var renderer = this,
-			alignedObjects = renderer.alignedObjects,
-			i = alignedObjects.length;
-
-		renderer.width = width;
-		renderer.height = height;
-
-		renderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({
-			width: width,
-			height: height
-		});
-
-		while (i--) {
-			alignedObjects[i].align();
-		}
-	},
-
-	/**
-	 * Create a group
-	 * @param {String} name The group will be given a class name of 'highcharts-{name}'.
-	 *     This can be used for styling and scripting.
-	 */
-	g: function (name) {
-		var elem = this.createElement('g');
-		return defined(name) ? elem.attr({ 'class': PREFIX + name }) : elem;
-	},
-
-	/**
-	 * Display an image
-	 * @param {String} src
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	image: function (src, x, y, width, height) {
-		var attribs = {
-				preserveAspectRatio: NONE
-			},
-			elemWrapper;
-
-		// optional properties
-		if (arguments.length > 1) {
-			extend(attribs, {
-				x: x,
-				y: y,
-				width: width,
-				height: height
-			});
-		}
-
-		elemWrapper = this.createElement('image').attr(attribs);
-
-		// set the href in the xlink namespace
-		if (elemWrapper.element.setAttributeNS) {
-			elemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink',
-				'href', src);
-		} else {
-			// could be exporting in IE
-			// using href throws "not supported" in ie7 and under, requries regex shim to fix later
-			elemWrapper.element.setAttribute('hc-svg-href', src);
-		}
-
-		return elemWrapper;
-	},
-
-	/**
-	 * Draw a symbol out of pre-defined shape paths from the namespace 'symbol' object.
-	 *
-	 * @param {Object} symbol
-	 * @param {Object} x
-	 * @param {Object} y
-	 * @param {Object} radius
-	 * @param {Object} options
-	 */
-	symbol: function (symbol, x, y, radius, options) {
-
-		var obj,
-
-			// get the symbol definition function
-			symbolFn = this.symbols[symbol],
-
-			// check if there's a path defined for this symbol
-			path = symbolFn && symbolFn(
-				mathRound(x),
-				mathRound(y),
-				radius,
-				options
-			),
-
-			imageRegex = /^url\((.*?)\)$/,
-			imageSrc,
-			imageSize;
-
-		if (path) {
-
-			obj = this.path(path);
-			// expando properties for use in animate and attr
-			extend(obj, {
-				symbolName: symbol,
-				x: x,
-				y: y,
-				r: radius
-			});
-			if (options) {
-				extend(obj, options);
-			}
-
-
-		// image symbols
-		} else if (imageRegex.test(symbol)) {
-
-			var centerImage = function (img, size) {
-				img.attr({
-					width: size[0],
-					height: size[1]
-				}).translate(
-					-mathRound(size[0] / 2),
-					-mathRound(size[1] / 2)
-				);
-			};
-
-			imageSrc = symbol.match(imageRegex)[1];
-			imageSize = symbolSizes[imageSrc];
-
-			// create the image synchronously, add attribs async
-			obj = this.image(imageSrc)
-				.attr({
-					x: x,
-					y: y
-				});
-
-			if (imageSize) {
-				centerImage(obj, imageSize);
-			} else {
-				// initialize image to be 0 size so export will still function if there's no cached sizes
-				obj.attr({ width: 0, height: 0 });
-
-				// create a dummy JavaScript image to get the width and height
-				createElement('img', {
-					onload: function () {
-						var img = this;
-						centerImage(obj, symbolSizes[imageSrc] = [img.width, img.height]);
-					},
-					src: imageSrc
-				});
-			}
-
-		// default circles
-		} else {
-			obj = this.circle(x, y, radius);
-		}
-
-		return obj;
-	},
-
-	/**
-	 * An extendable collection of functions for defining symbol paths.
-	 */
-	symbols: {
-		'square': function (x, y, radius) {
-			var len = 0.707 * radius;
-			return [
-				M, x - len, y - len,
-				L, x + len, y - len,
-				x + len, y + len,
-				x - len, y + len,
-				'Z'
-			];
-		},
-
-		'triangle': function (x, y, radius) {
-			return [
-				M, x, y - 1.33 * radius,
-				L, x + radius, y + 0.67 * radius,
-				x - radius, y + 0.67 * radius,
-				'Z'
-			];
-		},
-
-		'triangle-down': function (x, y, radius) {
-			return [
-				M, x, y + 1.33 * radius,
-				L, x - radius, y - 0.67 * radius,
-				x + radius, y - 0.67 * radius,
-				'Z'
-			];
-		},
-		'diamond': function (x, y, radius) {
-			return [
-				M, x, y - radius,
-				L, x + radius, y,
-				x, y + radius,
-				x - radius, y,
-				'Z'
-			];
-		},
-		'arc': function (x, y, radius, options) {
-			var start = options.start,
-				end = options.end - 0.000001, // to prevent cos and sin of start and end from becoming equal on 360 arcs
-				innerRadius = options.innerR,
-				cosStart = mathCos(start),
-				sinStart = mathSin(start),
-				cosEnd = mathCos(end),
-				sinEnd = mathSin(end),
-				longArc = options.end - start < mathPI ? 0 : 1;
-
-			return [
-				M,
-				x + radius * cosStart,
-				y + radius * sinStart,
-				'A', // arcTo
-				radius, // x radius
-				radius, // y radius
-				0, // slanting
-				longArc, // long or short arc
-				1, // clockwise
-				x + radius * cosEnd,
-				y + radius * sinEnd,
-				L,
-				x + innerRadius * cosEnd,
-				y + innerRadius * sinEnd,
-				'A', // arcTo
-				innerRadius, // x radius
-				innerRadius, // y radius
-				0, // slanting
-				longArc, // long or short arc
-				0, // clockwise
-				x + innerRadius * cosStart,
-				y + innerRadius * sinStart,
-
-				'Z' // close
-			];
-		}
-	},
-
-	/**
-	 * Define a clipping rectangle
-	 * @param {String} id
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	clipRect: function (x, y, width, height) {
-		var wrapper,
-			id = PREFIX + idCounter++,
-
-			clipPath = this.createElement('clipPath').attr({
-				id: id
-			}).add(this.defs);
-
-		wrapper = this.rect(x, y, width, height, 0).add(clipPath);
-		wrapper.id = id;
-		wrapper.clipPath = clipPath;
-
-		return wrapper;
-	},
-
-
-	/**
-	 * Take a color and return it if it's a string, make it a gradient if it's a
-	 * gradient configuration object
-	 *
-	 * @param {Object} color The color or config object
-	 */
-	color: function (color, elem, prop) {
-		var colorObject,
-			regexRgba = /^rgba/;
-		if (color && color.linearGradient) {
-			var renderer = this,
-				strLinearGradient = 'linearGradient',
-				linearGradient = color[strLinearGradient],
-				id = PREFIX + idCounter++,
-				gradientObject,
-				stopColor,
-				stopOpacity;
-			gradientObject = renderer.createElement(strLinearGradient).attr({
-				id: id,
-				gradientUnits: 'userSpaceOnUse',
-				x1: linearGradient[0],
-				y1: linearGradient[1],
-				x2: linearGradient[2],
-				y2: linearGradient[3]
-			}).add(renderer.defs);
-
-			// Keep a reference to the gradient object so it is possible to destroy it later
-			renderer.gradients.push(gradientObject);
-
-			// The gradient needs to keep a list of stops to be able to destroy them
-			gradientObject.stops = [];
-			each(color.stops, function (stop) {
-				var stopObject;
-				if (regexRgba.test(stop[1])) {
-					colorObject = Color(stop[1]);
-					stopColor = colorObject.get('rgb');
-					stopOpacity = colorObject.get('a');
-				} else {
-					stopColor = stop[1];
-					stopOpacity = 1;
-				}
-				stopObject = renderer.createElement('stop').attr({
-					offset: stop[0],
-					'stop-color': stopColor,
-					'stop-opacity': stopOpacity
-				}).add(gradientObject);
-
-				// Add the stop element to the gradient
-				gradientObject.stops.push(stopObject);
-			});
-
-			return 'url(' + this.url + '#' + id + ')';
-
-		// Webkit and Batik can't show rgba.
-		} else if (regexRgba.test(color)) {
-			colorObject = Color(color);
-			attr(elem, prop + '-opacity', colorObject.get('a'));
-
-			return colorObject.get('rgb');
-
-
-		} else {
-			// Remove the opacity attribute added above. Does not throw if the attribute is not there.
-			elem.removeAttribute(prop + '-opacity');
-
-			return color;
-		}
-
-	},
-
-
-	/**
-	 * Add text to the SVG object
-	 * @param {String} str
-	 * @param {Number} x Left position
-	 * @param {Number} y Top position
-	 * @param {Boolean} useHTML Use HTML to render the text
-	 */
-	text: function (str, x, y, useHTML) {
-
-		// declare variables
-		var defaultChartStyle = defaultOptions.chart.style,
-			wrapper;
-
-		x = mathRound(pick(x, 0));
-		y = mathRound(pick(y, 0));
-
-		wrapper = this.createElement('text')
-			.attr({
-				x: x,
-				y: y,
-				text: str
-			})
-			.css({
-				fontFamily: defaultChartStyle.fontFamily,
-				fontSize: defaultChartStyle.fontSize
-			});
-
-		wrapper.x = x;
-		wrapper.y = y;
-		wrapper.useHTML = useHTML;
-		return wrapper;
-	}
-}; // end SVGRenderer
-
-// general renderer
-Renderer = SVGRenderer;
-
-
-
-/* ****************************************************************************
- *                                                                            *
- * START OF INTERNET EXPLORER <= 8 SPECIFIC CODE                              *
- *                                                                            *
- * For applications and websites that don't need IE support, like platform    *
- * targeted mobile apps and web apps, this code can be removed.               *
- *                                                                            *
- *****************************************************************************/
-var VMLRenderer;
-if (!hasSVG) {
-
-/**
- * The VML element wrapper.
- */
-var VMLElement = extendClass(SVGElement, {
-
-	/**
-	 * Initialize a new VML element wrapper. It builds the markup as a string
-	 * to minimize DOM traffic.
-	 * @param {Object} renderer
-	 * @param {Object} nodeName
-	 */
-	init: function (renderer, nodeName) {
-		var markup =  ['<', nodeName, ' filled="f" stroked="f"'],
-			style = ['position: ', ABSOLUTE, ';'];
-
-		// divs and shapes need size
-		if (nodeName === 'shape' || nodeName === DIV) {
-			style.push('left:0;top:0;width:10px;height:10px;');
-		}
-		if (docMode8) {
-			style.push('visibility: ', nodeName === DIV ? HIDDEN : VISIBLE);
-		}
-
-		markup.push(' style="', style.join(''), '"/>');
-
-		// create element with default attributes and style
-		if (nodeName) {
-			markup = nodeName === DIV || nodeName === 'span' || nodeName === 'img' ?
-				markup.join('')
-				: renderer.prepVML(markup);
-			this.element = createElement(markup);
-		}
-
-		this.renderer = renderer;
-	},
-
-	/**
-	 * Add the node to the given parent
-	 * @param {Object} parent
-	 */
-	add: function (parent) {
-		var wrapper = this,
-			renderer = wrapper.renderer,
-			element = wrapper.element,
-			box = renderer.box,
-			inverted = parent && parent.inverted,
-
-			// get the parent node
-			parentNode = parent ?
-				parent.element || parent :
-				box;
-
-
-		// if the parent group is inverted, apply inversion on all children
-		if (inverted) { // only on groups
-			renderer.invertChild(element, parentNode);
-		}
-
-		// issue #140 workaround - related to #61 and #74
-		if (docMode8 && parentNode.gVis === HIDDEN) {
-			css(element, { visibility: HIDDEN });
-		}
-
-		// append it
-		parentNode.appendChild(element);
-
-		// align text after adding to be able to read offset
-		wrapper.added = true;
-		if (wrapper.alignOnAdd) {
-			wrapper.updateTransform();
-		}
-
-		return wrapper;
-	},
-
-	/**
-	 * Get or set attributes
-	 */
-	attr: function (hash, val) {
-		var key,
-			value,
-			i,
-			element = this.element || {},
-			elemStyle = element.style,
-			nodeName = element.nodeName,
-			renderer = this.renderer,
-			symbolName = this.symbolName,
-			childNodes,
-			hasSetSymbolSize,
-			shadows = this.shadows,
-			skipAttr,
-			ret = this;
-
-		// single key-value pair
-		if (isString(hash) && defined(val)) {
-			key = hash;
-			hash = {};
-			hash[key] = val;
-		}
-
-		// used as a getter, val is undefined
-		if (isString(hash)) {
-			key = hash;
-			if (key === 'strokeWidth' || key === 'stroke-width') {
-				ret = this.strokeweight;
-			} else {
-				ret = this[key];
-			}
-
-		// setter
-		} else {
-			for (key in hash) {
-				value = hash[key];
-				skipAttr = false;
-
-				// prepare paths
-				// symbols
-				if (symbolName && /^(x|y|r|start|end|width|height|innerR)/.test(key)) {
-					// if one of the symbol size affecting parameters are changed,
-					// check all the others only once for each call to an element's
-					// .attr() method
-					if (!hasSetSymbolSize) {
-						this.symbolAttr(hash);
-
-						hasSetSymbolSize = true;
-					}
-
-					skipAttr = true;
-
-				} else if (key === 'd') {
-					value = value || [];
-					this.d = value.join(' '); // used in getter for animation
-
-					// convert paths
-					i = value.length;
-					var convertedPath = [];
-					while (i--) {
-
-						// Multiply by 10 to allow subpixel precision.
-						// Substracting half a pixel seems to make the coordinates
-						// align with SVG, but this hasn't been tested thoroughly
-						if (isNumber(value[i])) {
-							convertedPath[i] = mathRound(value[i] * 10) - 5;
-						} else if (value[i] === 'Z') { // close the path
-							convertedPath[i] = 'x';
-						} else {
-							convertedPath[i] = value[i];
-						}
-
-					}
-					value = convertedPath.join(' ') || 'x';
-					element.path = value;
-
-					// update shadows
-					if (shadows) {
-						i = shadows.length;
-						while (i--) {
-							shadows[i].path = value;
-						}
-					}
-					skipAttr = true;
-
-				// directly mapped to css
-				} else if (key === 'zIndex' || key === 'visibility') {
-
-					// issue 61 workaround
-					if (docMode8 && key === 'visibility' && nodeName === 'DIV') {
-						element.gVis = value;
-						childNodes = element.childNodes;
-						i = childNodes.length;
-						while (i--) {
-							css(childNodes[i], { visibility: value });
-						}
-						if (value === VISIBLE) { // issue 74
-							value = null;
-						}
-					}
-
-					if (value) {
-						elemStyle[key] = value;
-					}
-
-
-
-					skipAttr = true;
-
-				// width and height
-				} else if (/^(width|height)$/.test(key)) {
-
-					this[key] = value; // used in getter
-
-					// clipping rectangle special
-					if (this.updateClipping) {
-						this[key] = value;
-						this.updateClipping();
-
-					} else {
-						// normal
-						elemStyle[key] = value;
-					}
-
-					skipAttr = true;
-
-				// x and y
-				} else if (/^(x|y)$/.test(key)) {
-
-					this[key] = value; // used in getter
-
-					if (element.tagName === 'SPAN') {
-						this.updateTransform();
-
-					} else {
-						elemStyle[{ x: 'left', y: 'top' }[key]] = value;
-					}
-
-				// class name
-				} else if (key === 'class') {
-					// IE8 Standards mode has problems retrieving the className
-					element.className = value;
-
-				// stroke
-				} else if (key === 'stroke') {
-
-					value = renderer.color(value, element, key);
-
-					key = 'strokecolor';
-
-				// stroke width
-				} else if (key === 'stroke-width' || key === 'strokeWidth') {
-					element.stroked = value ? true : false;
-					key = 'strokeweight';
-					this[key] = value; // used in getter, issue #113
-					if (isNumber(value)) {
-						value += PX;
-					}
-
-				// dashStyle
-				} else if (key === 'dashstyle') {
-					var strokeElem = element.getElementsByTagName('stroke')[0] ||
-						createElement(renderer.prepVML(['<stroke/>']), null, null, element);
-					strokeElem[key] = value || 'solid';
-					this.dashstyle = value; /* because changing stroke-width will change the dash length
-						and cause an epileptic effect */
-					skipAttr = true;
-
-				// fill
-				} else if (key === 'fill') {
-
-					if (nodeName === 'SPAN') { // text color
-						elemStyle.color = value;
-					} else {
-						element.filled = value !== NONE ? true : false;
-
-						value = renderer.color(value, element, key);
-
-						key = 'fillcolor';
-					}
-
-				// translation for animation
-				} else if (key === 'translateX' || key === 'translateY' || key === 'rotation' || key === 'align') {
-					if (key === 'align') {
-						key = 'textAlign';
-					}
-					this[key] = value;
-					this.updateTransform();
-
-					skipAttr = true;
-				} else if (key === 'text') { // text for rotated and non-rotated elements
-					this.bBox = null;
-					element.innerHTML = value;
-					skipAttr = true;
-				}
-
-
-				// let the shadow follow the main element
-				if (shadows && key === 'visibility') {
-					i = shadows.length;
-					while (i--) {
-						shadows[i].style[key] = value;
-					}
-				}
-
-
-
-				if (!skipAttr) {
-					if (docMode8) { // IE8 setAttribute bug
-						element[key] = value;
-					} else {
-						attr(element, key, value);
-					}
-				}
-			}
-		}
-		return ret;
-	},
-
-	/**
-	 * Set the element's clipping to a predefined rectangle
-	 *
-	 * @param {String} id The id of the clip rectangle
-	 */
-	clip: function (clipRect) {
-		var wrapper = this,
-			clipMembers = clipRect.members;
-
-		clipMembers.push(wrapper);
-		wrapper.destroyClip = function () {
-			erase(clipMembers, wrapper);
-		};
-		return wrapper.css(clipRect.getCSS(wrapper.inverted));
-	},
-
-	/**
-	 * Set styles for the element
-	 * @param {Object} styles
-	 */
-	css: function (styles) {
-		var wrapper = this,
-			element = wrapper.element,
-			textWidth = styles && element.tagName === 'SPAN' && styles.width;
-
-		/*if (textWidth) {
-			extend(styles, {
-				display: 'block',
-				whiteSpace: 'normal'
-			});
-		}*/
-		if (textWidth) {
-			delete styles.width;
-			wrapper.textWidth = textWidth;
-			wrapper.updateTransform();
-		}
-
-		wrapper.styles = extend(wrapper.styles, styles);
-		css(wrapper.element, styles);
-
-		return wrapper;
-	},
-
-	/**
-	 * Removes a child either by removeChild or move to garbageBin.
-	 * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not.
-	 */
-	safeRemoveChild: function (element) {
-		// discardElement will detach the node from its parent before attaching it
-		// to the garbage bin. Therefore it is important that the node is attached and have parent.
-		var parentNode = element.parentNode;
-		if (parentNode) {
-			discardElement(element);
-		}
-	},
-
-	/**
-	 * Extend element.destroy by removing it from the clip members array
-	 */
-	destroy: function () {
-		var wrapper = this;
-
-		if (wrapper.destroyClip) {
-			wrapper.destroyClip();
-		}
-
-		return SVGElement.prototype.destroy.apply(wrapper);
-	},
-
-	/**
-	 * Remove all child nodes of a group, except the v:group element
-	 */
-	empty: function () {
-		var element = this.element,
-			childNodes = element.childNodes,
-			i = childNodes.length,
-			node;
-
-		while (i--) {
-			node = childNodes[i];
-			node.parentNode.removeChild(node);
-		}
-	},
-
-	/**
-	 * VML override for calculating the bounding box based on offsets
-	 *
-	 * @return {Object} A hash containing values for x, y, width and height
-	 */
-
-	getBBox: function () {
-		var wrapper = this,
-			element = wrapper.element,
-			bBox = wrapper.bBox;
-
-		if (!bBox) {
-			// faking getBBox in exported SVG in legacy IE
-			if (element.nodeName === 'text') {
-				element.style.position = ABSOLUTE;
-			}
-
-			bBox = wrapper.bBox = {
-				x: element.offsetLeft,
-				y: element.offsetTop,
-				width: element.offsetWidth,
-				height: element.offsetHeight
-			};
-		}
-		return bBox;
-
-	},
-
-	/**
-	 * Add an event listener. VML override for normalizing event parameters.
-	 * @param {String} eventType
-	 * @param {Function} handler
-	 */
-	on: function (eventType, handler) {
-		// simplest possible event model for internal use
-		this.element['on' + eventType] = function () {
-			var evt = win.event;
-			evt.target = evt.srcElement;
-			handler(evt);
-		};
-		return this;
-	},
-
-
-	/**
-	 * VML override private method to update elements based on internal
-	 * properties based on SVG transform
-	 */
-	updateTransform: function () {
-		// aligning non added elements is expensive
-		if (!this.added) {
-			this.alignOnAdd = true;
-			return;
-		}
-
-		var wrapper = this,
-			elem = wrapper.element,
-			translateX = wrapper.translateX || 0,
-			translateY = wrapper.translateY || 0,
-			x = wrapper.x || 0,
-			y = wrapper.y || 0,
-			align = wrapper.textAlign || 'left',
-			alignCorrection = { left: 0, center: 0.5, right: 1 }[align],
-			nonLeft = align && align !== 'left';
-
-		// apply translate
-		if (translateX || translateY) {
-			wrapper.css({
-				marginLeft: translateX,
-				marginTop: translateY
-			});
-		}
-
-		// apply inversion
-		if (wrapper.inverted) { // wrapper is a group
-			each(elem.childNodes, function (child) {
-				wrapper.renderer.invertChild(child, elem);
-			});
-		}
-
-		if (elem.tagName === 'SPAN') {
-
-			var width, height,
-				rotation = wrapper.rotation,
-				lineHeight,
-				radians = 0,
-				costheta = 1,
-				sintheta = 0,
-				quad,
-				textWidth = pInt(wrapper.textWidth),
-				xCorr = wrapper.xCorr || 0,
-				yCorr = wrapper.yCorr || 0,
-				currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(',');
-
-			if (currentTextTransform !== wrapper.cTT) { // do the calculations and DOM access only if properties changed
-
-				if (defined(rotation)) {
-					radians = rotation * deg2rad; // deg to rad
-					costheta = mathCos(radians);
-					sintheta = mathSin(radians);
-
-					// Adjust for alignment and rotation.
-					// Test case: http://highcharts.com/tests/?file=text-rotation
-					css(elem, {
-						filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta,
-							', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta,
-							', sizingMethod=\'auto expand\')'].join('') : NONE
-					});
-				}
-
-				width = elem.offsetWidth;
-				height = elem.offsetHeight;
-
-				// update textWidth
-				if (width > textWidth) {
-					css(elem, {
-						width: textWidth + PX,
-						display: 'block',
-						whiteSpace: 'normal'
-					});
-					width = textWidth;
-				}
-
-				// correct x and y
-				lineHeight = mathRound((pInt(elem.style.fontSize) || 12) * 1.2);
-				xCorr = costheta < 0 && -width;
-				yCorr = sintheta < 0 && -height;
-
-				// correct for lineHeight and corners spilling out after rotation
-				quad = costheta * sintheta < 0;
-				xCorr += sintheta * lineHeight * (quad ? 1 - alignCorrection : alignCorrection);
-				yCorr -= costheta * lineHeight * (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1);
-
-				// correct for the length/height of the text
-				if (nonLeft) {
-					xCorr -= width * alignCorrection * (costheta < 0 ? -1 : 1);
-					if (rotation) {
-						yCorr -= height * alignCorrection * (sintheta < 0 ? -1 : 1);
-					}
-					css(elem, {
-						textAlign: align
-					});
-				}
-
-				// record correction
-				wrapper.xCorr = xCorr;
-				wrapper.yCorr = yCorr;
-			}
-
-			// apply position with correction
-			css(elem, {
-				left: x + xCorr,
-				top: y + yCorr
-			});
-
-			// record current text transform
-			wrapper.cTT = currentTextTransform;
-		}
-	},
-
-	/**
-	 * Apply a drop shadow by copying elements and giving them different strokes
-	 * @param {Boolean} apply
-	 */
-	shadow: function (apply, group) {
-		var shadows = [],
-			i,
-			element = this.element,
-			renderer = this.renderer,
-			shadow,
-			elemStyle = element.style,
-			markup,
-			path = element.path;
-
-		// some times empty paths are not strings
-		if (path && typeof path.value !== 'string') {
-			path = 'x';
-		}
-
-		if (apply) {
-			for (i = 1; i <= 3; i++) {
-				markup = ['<shape isShadow="true" strokeweight="', (7 - 2 * i),
-					'" filled="false" path="', path,
-					'" coordsize="100,100" style="', element.style.cssText, '" />'];
-				shadow = createElement(renderer.prepVML(markup),
-					null, {
-						left: pInt(elemStyle.left) + 1,
-						top: pInt(elemStyle.top) + 1
-					}
-				);
-
-				// apply the opacity
-				markup = ['<stroke color="black" opacity="', (0.05 * i), '"/>'];
-				createElement(renderer.prepVML(markup), null, null, shadow);
-
-
-				// insert it
-				if (group) {
-					group.element.appendChild(shadow);
-				} else {
-					element.parentNode.insertBefore(shadow, element);
-				}
-
-				// record it
-				shadows.push(shadow);
-
-			}
-
-			this.shadows = shadows;
-		}
-		return this;
-
-	}
-});
-
-/**
- * The VML renderer
- */
-VMLRenderer = function () {
-	this.init.apply(this, arguments);
-};
-VMLRenderer.prototype = merge(SVGRenderer.prototype, { // inherit SVGRenderer
-
-	Element: VMLElement,
-	isIE8: userAgent.indexOf('MSIE 8.0') > -1,
-
-
-	/**
-	 * Initialize the VMLRenderer
-	 * @param {Object} container
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	init: function (container, width, height) {
-		var renderer = this,
-			boxWrapper;
-
-		renderer.alignedObjects = [];
-
-		boxWrapper = renderer.createElement(DIV);
-		container.appendChild(boxWrapper.element);
-
-
-		// generate the containing box
-		renderer.box = boxWrapper.element;
-		renderer.boxWrapper = boxWrapper;
-
-
-		renderer.setSize(width, height, false);
-
-		// The only way to make IE6 and IE7 print is to use a global namespace. However,
-		// with IE8 the only way to make the dynamic shapes visible in screen and print mode
-		// seems to be to add the xmlns attribute and the behaviour style inline.
-		if (!doc.namespaces.hcv) {
-
-			doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml');
-
-			// setup default css
-			doc.createStyleSheet().cssText =
-				'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' +
-				'{ behavior:url(#default#VML); display: inline-block; } ';
-
-		}
-	},
-
-	/**
-	 * Define a clipping rectangle. In VML it is accomplished by storing the values
-	 * for setting the CSS style to all associated members.
-	 *
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	clipRect: function (x, y, width, height) {
-
-		// create a dummy element
-		var clipRect = this.createElement();
-
-		// mimic a rectangle with its style object for automatic updating in attr
-		return extend(clipRect, {
-			members: [],
-			left: x,
-			top: y,
-			width: width,
-			height: height,
-			getCSS: function (inverted) {
-				var rect = this,//clipRect.element.style,
-					top = rect.top,
-					left = rect.left,
-					right = left + rect.width,
-					bottom = top + rect.height,
-					ret = {
-						clip: 'rect(' +
-							mathRound(inverted ? left : top) + 'px,' +
-							mathRound(inverted ? bottom : right) + 'px,' +
-							mathRound(inverted ? right : bottom) + 'px,' +
-							mathRound(inverted ? top : left) + 'px)'
-					};
-
-				// issue 74 workaround
-				if (!inverted && docMode8) {
-					extend(ret, {
-						width: right + PX,
-						height: bottom + PX
-					});
-				}
-				return ret;
-			},
-
-			// used in attr and animation to update the clipping of all members
-			updateClipping: function () {
-				each(clipRect.members, function (member) {
-					member.css(clipRect.getCSS(member.inverted));
-				});
-			}
-		});
-
-	},
-
-
-	/**
-	 * Take a color and return it if it's a string, make it a gradient if it's a
-	 * gradient configuration object, and apply opacity.
-	 *
-	 * @param {Object} color The color or config object
-	 */
-	color: function (color, elem, prop) {
-		var colorObject,
-			regexRgba = /^rgba/,
-			markup;
-
-		if (color && color.linearGradient) {
-
-			var stopColor,
-				stopOpacity,
-				linearGradient = color.linearGradient,
-				angle,
-				color1,
-				opacity1,
-				color2,
-				opacity2;
-
-			each(color.stops, function (stop, i) {
-				if (regexRgba.test(stop[1])) {
-					colorObject = Color(stop[1]);
-					stopColor = colorObject.get('rgb');
-					stopOpacity = colorObject.get('a');
-				} else {
-					stopColor = stop[1];
-					stopOpacity = 1;
-				}
-
-				if (!i) { // first
-					color1 = stopColor;
-					opacity1 = stopOpacity;
-				} else {
-					color2 = stopColor;
-					opacity2 = stopOpacity;
-				}
-			});
-
-
-
-			// calculate the angle based on the linear vector
-			angle = 90  - math.atan(
-				(linearGradient[3] - linearGradient[1]) / // y vector
-				(linearGradient[2] - linearGradient[0]) // x vector
-				) * 180 / mathPI;
-
-			// when colors attribute is used, the meanings of opacity and o:opacity2
-			// are reversed.
-			markup = ['<', prop, ' colors="0% ', color1, ',100% ', color2, '" angle="', angle,
-				'" opacity="', opacity2, '" o:opacity2="', opacity1,
-				'" type="gradient" focus="100%" />'];
-			createElement(this.prepVML(markup), null, null, elem);
-
-
-
-		// if the color is an rgba color, split it and add a fill node
-		// to hold the opacity component
-		} else if (regexRgba.test(color) && elem.tagName !== 'IMG') {
-
-			colorObject = Color(color);
-
-			markup = ['<', prop, ' opacity="', colorObject.get('a'), '"/>'];
-			createElement(this.prepVML(markup), null, null, elem);
-
-			return colorObject.get('rgb');
-
-
-		} else {
-			var strokeNodes = elem.getElementsByTagName(prop);
-			if (strokeNodes.length) {
-				strokeNodes[0].opacity = 1;
-			}
-			return color;
-		}
-
-	},
-
-	/**
-	 * Take a VML string and prepare it for either IE8 or IE6/IE7.
-	 * @param {Array} markup A string array of the VML markup to prepare
-	 */
-	prepVML: function (markup) {
-		var vmlStyle = 'display:inline-block;behavior:url(#default#VML);',
-			isIE8 = this.isIE8;
-
-		markup = markup.join('');
-
-		if (isIE8) { // add xmlns and style inline
-			markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />');
-			if (markup.indexOf('style="') === -1) {
-				markup = markup.replace('/>', ' style="' + vmlStyle + '" />');
-			} else {
-				markup = markup.replace('style="', 'style="' + vmlStyle);
-			}
-
-		} else { // add namespace
-			markup = markup.replace('<', '<hcv:');
-		}
-
-		return markup;
-	},
-
-	/**
-	 * Create rotated and aligned text
-	 * @param {String} str
-	 * @param {Number} x
-	 * @param {Number} y
-	 */
-	text: function (str, x, y) {
-
-		var defaultChartStyle = defaultOptions.chart.style;
-
-		return this.createElement('span')
-			.attr({
-				text: str,
-				x: mathRound(x),
-				y: mathRound(y)
-			})
-			.css({
-				whiteSpace: 'nowrap',
-				fontFamily: defaultChartStyle.fontFamily,
-				fontSize: defaultChartStyle.fontSize
-			});
-	},
-
-	/**
-	 * Create and return a path element
-	 * @param {Array} path
-	 */
-	path: function (path) {
-		// create the shape
-		return this.createElement('shape').attr({
-			// subpixel precision down to 0.1 (width and height = 10px)
-			coordsize: '100 100',
-			d: path
-		});
-	},
-
-	/**
-	 * Create and return a circle element. In VML circles are implemented as
-	 * shapes, which is faster than v:oval
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} r
-	 */
-	circle: function (x, y, r) {
-		return this.symbol('circle').attr({ x: x, y: y, r: r});
-	},
-
-	/**
-	 * Create a group using an outer div and an inner v:group to allow rotating
-	 * and flipping. A simple v:group would have problems with positioning
-	 * child HTML elements and CSS clip.
-	 *
-	 * @param {String} name The name of the group
-	 */
-	g: function (name) {
-		var wrapper,
-			attribs;
-
-		// set the class name
-		if (name) {
-			attribs = { 'className': PREFIX + name, 'class': PREFIX + name };
-		}
-
-		// the div to hold HTML and clipping
-		wrapper = this.createElement(DIV).attr(attribs);
-
-		return wrapper;
-	},
-
-	/**
-	 * VML override to create a regular HTML image
-	 * @param {String} src
-	 * @param {Number} x
-	 * @param {Number} y
-	 * @param {Number} width
-	 * @param {Number} height
-	 */
-	image: function (src, x, y, width, height) {
-		var obj = this.createElement('img')
-			.attr({ src: src });
-
-		if (arguments.length > 1) {
-			obj.css({
-				left: x,
-				top: y,
-				width: width,
-				height: height
-			});
-		}
-		return obj;
-	},
-
-	/**
-	 * VML uses a shape for rect to overcome bugs and rotation problems
-	 */
-	rect: function (x, y, width, height, r, strokeWidth) {
-
-		if (isObject(x)) {
-			y = x.y;
-			width = x.width;
-			height = x.height;
-			r = x.r;
-			strokeWidth = x.strokeWidth;
-			x = x.x;
-		}
-		var wrapper = this.symbol('rect');
-		wrapper.r = r;
-
-		return wrapper.attr(wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)));
-	},
-
-	/**
-	 * In the VML renderer, each child of an inverted div (group) is inverted
-	 * @param {Object} element
-	 * @param {Object} parentNode
-	 */
-	invertChild: function (element, parentNode) {
-		var parentStyle = parentNode.style;
-
-		css(element, {
-			flip: 'x',
-			left: pInt(parentStyle.width) - 10,
-			top: pInt(parentStyle.height) - 10,
-			rotation: -90
-		});
-	},
-
-	/**
-	 * Symbol definitions that override the parent SVG renderer's symbols
-	 *
-	 */
-	symbols: {
-		// VML specific arc function
-		arc: function (x, y, radius, options) {
-			var start = options.start,
-				end = options.end,
-				cosStart = mathCos(start),
-				sinStart = mathSin(start),
-				cosEnd = mathCos(end),
-				sinEnd = mathSin(end),
-				innerRadius = options.innerR,
-				circleCorrection = 0.07 / radius,
-				innerCorrection = (innerRadius && 0.1 / innerRadius) || 0;
-
-			if (end - start === 0) { // no angle, don't show it.
-				return ['x'];
-
-			//} else if (end - start == 2 * mathPI) { // full circle
-			} else if (2 * mathPI - end + start < circleCorrection) { // full circle
-				// empirical correction found by trying out the limits for different radii
-				cosEnd = -circleCorrection;
-			} else if (end - start < innerCorrection) { // issue #186, another mysterious VML arc problem
-				cosEnd = mathCos(start + innerCorrection);
-			}
-
-			return [
-				'wa', // clockwise arc to
-				x - radius, // left
-				y - radius, // top
-				x + radius, // right
-				y + radius, // bottom
-				x + radius * cosStart, // start x
-				y + radius * sinStart, // start y
-				x + radius * cosEnd, // end x
-				y + radius * sinEnd, // end y
-
-
-				'at', // anti clockwise arc to
-				x - innerRadius, // left
-				y - innerRadius, // top
-				x + innerRadius, // right
-				y + innerRadius, // bottom
-				x + innerRadius * cosEnd, // start x
-				y + innerRadius * sinEnd, // start y
-				x + innerRadius * cosStart, // end x
-				y + innerRadius * sinStart, // end y
-
-				'x', // finish path
-				'e' // close
-			];
-
-		},
-		// Add circle symbol path. This performs significantly faster than v:oval.
-		circle: function (x, y, r) {
-			return [
-				'wa', // clockwisearcto
-				x - r, // left
-				y - r, // top
-				x + r, // right
-				y + r, // bottom
-				x + r, // start x
-				y,     // start y
-				x + r, // end x
-				y,     // end y
-				//'x', // finish path
-				'e' // close
-			];
-		},
-		/**
-		 * Add rectangle symbol path which eases rotation and omits arcsize problems
-		 * compared to the built-in VML roundrect shape
-		 *
-		 * @param {Number} left Left position
-		 * @param {Number} top Top position
-		 * @param {Number} r Border radius
-		 * @param {Object} options Width and height
-		 */
-
-		rect: function (left, top, r, options) {
-			if (!defined(options)) {
-				return [];
-			}
-			var width = options.width,
-				height = options.height,
-				right = left + width,
-				bottom = top + height;
-
-			r = mathMin(r, width, height);
-
-			return [
-				M,
-				left + r, top,
-
-				L,
-				right - r, top,
-				'wa',
-				right - 2 * r, top,
-				right, top + 2 * r,
-				right - r, top,
-				right, top + r,
-
-				L,
-				right, bottom - r,
-				'wa',
-				right - 2 * r, bottom - 2 * r,
-				right, bottom,
-				right, bottom - r,
-				right - r, bottom,
-
-				L,
-				left + r, bottom,
-				'wa',
-				left, bottom - 2 * r,
-				left + 2 * r, bottom,
-				left + r, bottom,
-				left, bottom - r,
-
-				L,
-				left, top + r,
-				'wa',
-				left, top,
-				left + 2 * r, top + 2 * r,
-				left, top + r,
-				left + r, top,
-
-
-				'x',
-				'e'
-			];
-
-		}
-	}
-});
-
-// general renderer
-Renderer = VMLRenderer;
-}
-/* ****************************************************************************
- *                                                                            *
- * END OF INTERNET EXPLORER <= 8 SPECIFIC CODE                                *
- *                                                                            *
- *****************************************************************************/
-
-
-/**
- * The chart class
- * @param {Object} options
- * @param {Function} callback Function to run when the chart has loaded
- */
-function Chart(options, callback) {
-
-	defaultXAxisOptions = merge(defaultXAxisOptions, defaultOptions.xAxis);
-	defaultYAxisOptions = merge(defaultYAxisOptions, defaultOptions.yAxis);
-	defaultOptions.xAxis = defaultOptions.yAxis = null;
-
-	// Handle regular options
-	options = merge(defaultOptions, options);
-
-	// Define chart variables
-	var optionsChart = options.chart,
-		optionsMargin = optionsChart.margin,
-		margin = isObject(optionsMargin) ?
-			optionsMargin :
-			[optionsMargin, optionsMargin, optionsMargin, optionsMargin],
-		optionsMarginTop = pick(optionsChart.marginTop, margin[0]),
-		optionsMarginRight = pick(optionsChart.marginRight, margin[1]),
-		optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]),
-		optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]),
-		spacingTop = optionsChart.spacingTop,
-		spacingRight = optionsChart.spacingRight,
-		spacingBottom = optionsChart.spacingBottom,
-		spacingLeft = optionsChart.spacingLeft,
-		spacingBox,
-		chartTitleOptions,
-		chartSubtitleOptions,
-		plotTop,
-		marginRight,
-		marginBottom,
-		plotLeft,
-		axisOffset,
-		renderTo,
-		renderToClone,
-		container,
-		containerId,
-		containerWidth,
-		containerHeight,
-		chartWidth,
-		chartHeight,
-		oldChartWidth,
-		oldChartHeight,
-		chartBackground,
-		plotBackground,
-		plotBGImage,
-		plotBorder,
-		chart = this,
-		chartEvents = optionsChart.events,
-		runChartClick = chartEvents && !!chartEvents.click,
-		eventType,
-		isInsidePlot, // function
-		tooltip,
-		mouseIsDown,
-		loadingDiv,
-		loadingSpan,
-		loadingShown,
-		plotHeight,
-		plotWidth,
-		tracker,
-		trackerGroup,
-		placeTrackerGroup,
-		legend,
-		legendWidth,
-		legendHeight,
-		chartPosition,// = getPosition(container),
-		hasCartesianSeries = optionsChart.showAxes,
-		isResizing = 0,
-		axes = [],
-		maxTicks, // handle the greatest amount of ticks on grouped axes
-		series = [],
-		inverted,
-		renderer,
-		tooltipTick,
-		tooltipInterval,
-		hoverX,
-		drawChartBox, // function
-		getMargins, // function
-		resetMargins, // function
-		setChartSize, // function
-		resize,
-		zoom, // function
-		zoomOut; // function
-
-
-	/**
-	 * Create a new axis object
-	 * @param {Object} options
-	 */
-	function Axis(userOptions) {
-
-		// Define variables
-		var isXAxis = userOptions.isX,
-			opposite = userOptions.opposite, // needed in setOptions
-			horiz = inverted ? !isXAxis : isXAxis,
-			side = horiz ?
-				(opposite ? 0 : 2) : // top : bottom
-				(opposite ? 1 : 3),  // right : left
-			stacks = {},
-
-			options = merge(
-				isXAxis ? defaultXAxisOptions : defaultYAxisOptions,
-				[defaultTopAxisOptions, defaultRightAxisOptions,
-					defaultBottomAxisOptions, defaultLeftAxisOptions][side],
-				userOptions
-			),
-
-			axis = this,
-			axisTitle,
-			type = options.type,
-			isDatetimeAxis = type === 'datetime',
-			isLog = type === 'logarithmic',
-			offset = options.offset || 0,
-			xOrY = isXAxis ? 'x' : 'y',
-			axisLength,
-			transA, // translation factor
-			oldTransA, // used for prerendering
-			transB = horiz ? plotLeft : marginBottom, // translation addend
-			translate, // fn
-			getPlotLinePath, // fn
-			axisGroup,
-			gridGroup,
-			axisLine,
-			dataMin,
-			dataMax,
-			associatedSeries,
-			userMin,
-			userMax,
-			max = null,
-			min = null,
-			oldMin,
-			oldMax,
-			minPadding = options.minPadding,
-			maxPadding = options.maxPadding,
-			isLinked = defined(options.linkedTo),
-			ignoreMinPadding, // can be set to true by a column or bar series
-			ignoreMaxPadding,
-			usePercentage,
-			events = options.events,
-			eventType,
-			plotLinesAndBands = [],
-			tickInterval,
-			minorTickInterval,
-			magnitude,
-			tickPositions, // array containing predefined positions
-			ticks = {},
-			minorTicks = {},
-			alternateBands = {},
-			tickAmount,
-			labelOffset,
-			axisTitleMargin,// = options.title.margin,
-			dateTimeLabelFormat,
-			categories = options.categories,
-			labelFormatter = options.labels.formatter ||  // can be overwritten by dynamic format
-				function () {
-					var value = this.value,
-						ret;
-
-					if (dateTimeLabelFormat) { // datetime axis
-						ret = dateFormat(dateTimeLabelFormat, value);
-
-					} else if (tickInterval % 1000000 === 0) { // use M abbreviation
-						ret = (value / 1000000) + 'M';
-
-					} else if (tickInterval % 1000 === 0) { // use k abbreviation
-						ret = (value / 1000) + 'k';
-
-					} else if (!categories && value >= 1000) { // add thousands separators
-						ret = numberFormat(value, 0);
-
-					} else { // strings (categories) and small numbers
-						ret = value;
-					}
-					return ret;
-				},
-
-			staggerLines = horiz && options.labels.staggerLines,
-			reversed = options.reversed,
-			tickmarkOffset = (categories && options.tickmarkPlacement === 'between') ? 0.5 : 0;
-
-		/**
-		 * The Tick class
-		 */
-		function Tick(pos, minor) {
-			var tick = this;
-			tick.pos = pos;
-			tick.minor = minor;
-			tick.isNew = true;
-
-			if (!minor) {
-				tick.addLabel();
-			}
-		}
-		Tick.prototype = {
-			/**
-			 * Write the tick label
-			 */
-			addLabel: function () {
-				var pos = this.pos,
-					labelOptions = options.labels,
-					str,
-					withLabel = !((pos === min && !pick(options.showFirstLabel, 1)) ||
-						(pos === max && !pick(options.showLastLabel, 0))),
-					width = (categories && horiz && categories.length &&
-						!labelOptions.step && !labelOptions.staggerLines &&
-						!labelOptions.rotation &&
-						plotWidth / categories.length) ||
-						(!horiz && plotWidth / 2),
-					css,
-					value = categories && defined(categories[pos]) ? categories[pos] : pos,
-					label = this.label;
-
-
-				// get the string
-				str = labelFormatter.call({
-						isFirst: pos === tickPositions[0],
-						isLast: pos === tickPositions[tickPositions.length - 1],
-						dateTimeLabelFormat: dateTimeLabelFormat,
-						value: isLog ? lin2log(value) : value
-					});
-
-
-				// prepare CSS
-				css = width && { width: mathMax(1, mathRound(width - 2 * (labelOptions.padding || 10))) + PX };
-				css = extend(css, labelOptions.style);
-
-				// first call
-				if (label === UNDEFINED) {
-					this.label =
-						defined(str) && withLabel && labelOptions.enabled ?
-							renderer.text(
-									str,
-									0,
-									0,
-									labelOptions.useHTML
-								)
-								.attr({
-									align: labelOptions.align,
-									rotation: labelOptions.rotation
-								})
-								// without position absolute, IE export sometimes is wrong
-								.css(css)
-								.add(axisGroup) :
-							null;
-
-				// update
-				} else if (label) {
-					label.attr({ text: str })
-						.css(css);
-				}
-			},
-			/**
-			 * Get the offset height or width of the label
-			 */
-			getLabelSize: function () {
-				var label = this.label;
-				return label ?
-					((this.labelBBox = label.getBBox()))[horiz ? 'height' : 'width'] :
-					0;
-				},
-			/**
-			 * Put everything in place
-			 *
-			 * @param index {Number}
-			 * @param old {Boolean} Use old coordinates to prepare an animation into new position
-			 */
-			render: function (index, old) {
-				var tick = this,
-					major = !tick.minor,
-					label = tick.label,
-					pos = tick.pos,
-					labelOptions = options.labels,
-					gridLine = tick.gridLine,
-					gridLineWidth = major ? options.gridLineWidth : options.minorGridLineWidth,
-					gridLineColor = major ? options.gridLineColor : options.minorGridLineColor,
-					dashStyle = major ?
-						options.gridLineDashStyle :
-						options.minorGridLineDashStyle,
-					gridLinePath,
-					mark = tick.mark,
-					markPath,
-					tickLength = major ? options.tickLength : options.minorTickLength,
-					tickWidth = major ? options.tickWidth : (options.minorTickWidth || 0),
-					tickColor = major ? options.tickColor : options.minorTickColor,
-					tickPosition = major ? options.tickPosition : options.minorTickPosition,
-					step = labelOptions.step,
-					cHeight = (old && oldChartHeight) || chartHeight,
-					attribs,
-					x,
-					y;
-
-				// get x and y position for ticks and labels
-				x = horiz ?
-					translate(pos + tickmarkOffset, null, null, old) + transB :
-					plotLeft + offset + (opposite ? ((old && oldChartWidth) || chartWidth) - marginRight - plotLeft : 0);
-
-				y = horiz ?
-					cHeight - marginBottom + offset - (opposite ? plotHeight : 0) :
-					cHeight - translate(pos + tickmarkOffset, null, null, old) - transB;
-
-				// create the grid line
-				if (gridLineWidth) {
-					gridLinePath = getPlotLinePath(pos + tickmarkOffset, gridLineWidth, old);
-
-					if (gridLine === UNDEFINED) {
-						attribs = {
-							stroke: gridLineColor,
-							'stroke-width': gridLineWidth
-						};
-						if (dashStyle) {
-							attribs.dashstyle = dashStyle;
-						}
-						if (major) {
-							attribs.zIndex = 1;
-						}
-						tick.gridLine = gridLine =
-							gridLineWidth ?
-								renderer.path(gridLinePath)
-									.attr(attribs).add(gridGroup) :
-								null;
-					}
-
-					// If the parameter 'old' is set, the current call will be followed
-					// by another call, therefore do not do any animations this time
-					if (!old && gridLine && gridLinePath) {
-						gridLine.animate({
-							d: gridLinePath
-						});
-					}
-				}
-
-				// create the tick mark
-				if (tickWidth) {
-
-					// negate the length
-					if (tickPosition === 'inside') {
-						tickLength = -tickLength;
-					}
-					if (opposite) {
-						tickLength = -tickLength;
-					}
-
-					markPath = renderer.crispLine([
-						M,
-						x,
-						y,
-						L,
-						x + (horiz ? 0 : -tickLength),
-						y + (horiz ? tickLength : 0)
-					], tickWidth);
-
-					if (mark) { // updating
-						mark.animate({
-							d: markPath
-						});
-					} else { // first time
-						tick.mark = renderer.path(
-							markPath
-						).attr({
-							stroke: tickColor,
-							'stroke-width': tickWidth
-						}).add(axisGroup);
-					}
-				}
-
-				// the label is created on init - now move it into place
-				if (label && !isNaN(x)) {
-					x = x + labelOptions.x - (tickmarkOffset && horiz ?
-						tickmarkOffset * transA * (reversed ? -1 : 1) : 0);
-					y = y + labelOptions.y - (tickmarkOffset && !horiz ?
-						tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
-
-					// vertically centered
-					if (!defined(labelOptions.y)) {
-						y += pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
-					}
-
-
-					// correct for staggered labels
-					if (staggerLines) {
-						y += (index / (step || 1) % staggerLines) * 16;
-					}
-					// apply step
-					if (step) {
-						// show those indices dividable by step
-						label[index % step ? 'hide' : 'show']();
-					}
-
-					label[tick.isNew ? 'attr' : 'animate']({
-						x: x,
-						y: y
-					});
-				}
-
-				tick.isNew = false;
-			},
-			/**
-			 * Destructor for the tick prototype
-			 */
-			destroy: function () {
-				destroyObjectProperties(this);
-			}
-		};
-
-		/**
-		 * The object wrapper for plot lines and plot bands
-		 * @param {Object} options
-		 */
-		function PlotLineOrBand(options) {
-			var plotLine = this;
-			if (options) {
-				plotLine.options = options;
-				plotLine.id = options.id;
-			}
-
-			//plotLine.render()
-			return plotLine;
-		}
-
-		PlotLineOrBand.prototype = {
-
-		/**
-		 * Render the plot line or plot band. If it is already existing,
-		 * move it.
-		 */
-		render: function () {
-			var plotLine = this,
-				options = plotLine.options,
-				optionsLabel = options.label,
-				label = plotLine.label,
-				width = options.width,
-				to = options.to,
-				from = options.from,
-				value = options.value,
-				toPath, // bands only
-				dashStyle = options.dashStyle,
-				svgElem = plotLine.svgElem,
-				path = [],
-				addEvent,
-				eventType,
-				xs,
-				ys,
-				x,
-				y,
-				color = options.color,
-				zIndex = options.zIndex,
-				events = options.events,
-				attribs;
-
-			// logarithmic conversion
-			if (isLog) {
-				from = log2lin(from);
-				to = log2lin(to);
-				value = log2lin(value);
-			}
-
-			// plot line
-			if (width) {
-				path = getPlotLinePath(value, width);
-				attribs = {
-					stroke: color,
-					'stroke-width': width
-				};
-				if (dashStyle) {
-					attribs.dashstyle = dashStyle;
-				}
-			} else if (defined(from) && defined(to)) { // plot band
-				// keep within plot area
-				from = mathMax(from, min);
-				to = mathMin(to, max);
-
-				toPath = getPlotLinePath(to);
-				path = getPlotLinePath(from);
-				if (path && toPath) {
-					path.push(
-						toPath[4],
-						toPath[5],
-						toPath[1],
-						toPath[2]
-					);
-				} else { // outside the axis area
-					path = null;
-				}
-				attribs = {
-					fill: color
-				};
-			} else {
-				return;
-			}
-			// zIndex
-			if (defined(zIndex)) {
-				attribs.zIndex = zIndex;
-			}
-
-			// common for lines and bands
-			if (svgElem) {
-				if (path) {
-					svgElem.animate({
-						d: path
-					}, null, svgElem.onGetPath);
-				} else {
-					svgElem.hide();
-					svgElem.onGetPath = function () {
-						svgElem.show();
-					};
-				}
-			} else if (path && path.length) {
-				plotLine.svgElem = svgElem = renderer.path(path)
-					.attr(attribs).add();
-
-				// events
-				if (events) {
-					addEvent = function (eventType) {
-						svgElem.on(eventType, function (e) {
-							events[eventType].apply(plotLine, [e]);
-						});
-					};
-					for (eventType in events) {
-						addEvent(eventType);
-					}
-				}
-			}
-
-			// the plot band/line label
-			if (optionsLabel && defined(optionsLabel.text) && path && path.length && plotWidth > 0 && plotHeight > 0) {
-				// apply defaults
-				optionsLabel = merge({
-					align: horiz && toPath && 'center',
-					x: horiz ? !toPath && 4 : 10,
-					verticalAlign : !horiz && toPath && 'middle',
-					y: horiz ? toPath ? 16 : 10 : toPath ? 6 : -4,
-					rotation: horiz && !toPath && 90
-				}, optionsLabel);
-
-				// add the SVG element
-				if (!label) {
-					plotLine.label = label = renderer.text(
-							optionsLabel.text,
-							0,
-							0
-						)
-						.attr({
-							align: optionsLabel.textAlign || optionsLabel.align,
-							rotation: optionsLabel.rotation,
-							zIndex: zIndex
-						})
-						.css(optionsLabel.style)
-						.add();
-				}
-
-				// get the bounding box and align the label
-				xs = [path[1], path[4], pick(path[6], path[1])];
-				ys = [path[2], path[5], pick(path[7], path[2])];
-				x = mathMin.apply(math, xs);
-				y = mathMin.apply(math, ys);
-
-				label.align(optionsLabel, false, {
-					x: x,
-					y: y,
-					width: mathMax.apply(math, xs) - x,
-					height: mathMax.apply(math, ys) - y
-				});
-				label.show();
-
-			} else if (label) { // move out of sight
-				label.hide();
-			}
-
-			// chainable
-			return plotLine;
-		},
-
-		/**
-		 * Remove the plot line or band
-		 */
-		destroy: function () {
-			var obj = this;
-
-			destroyObjectProperties(obj);
-
-			// remove it from the lookup
-			erase(plotLinesAndBands, obj);
-		}
-		};
-
-		/**
-		 * The class for stack items
-		 */
-		function StackItem(options, isNegative, x, stackOption) {
-			var stackItem = this;
-
-			// Tells if the stack is negative
-			stackItem.isNegative = isNegative;
-
-			// Save the options to be able to style the label
-			stackItem.options = options;
-
-			// Save the x value to be able to position the label later
-			stackItem.x = x;
-
-			// Save the stack option on the series configuration object
-			stackItem.stack = stackOption;
-
-			// The align options and text align varies on whether the stack is negative and
-			// if the chart is inverted or not.
-			// First test the user supplied value, then use the dynamic.
-			stackItem.alignOptions = {
-				align: options.align || (inverted ? (isNegative ? 'left' : 'right') : 'center'),
-				verticalAlign: options.verticalAlign || (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')),
-				y: pick(options.y, inverted ? 4 : (isNegative ? 14 : -6)),
-				x: pick(options.x, inverted ? (isNegative ? -6 : 6) : 0)
-			};
-
-			stackItem.textAlign = options.textAlign || (inverted ? (isNegative ? 'right' : 'left') : 'center');
-		}
-
-		StackItem.prototype = {
-			destroy: function () {
-				destroyObjectProperties(this);
-			},
-
-			/**
-			 * Sets the total of this stack. Should be called when a serie is hidden or shown
-			 * since that will affect the total of other stacks.
-			 */
-			setTotal: function (total) {
-				this.total = total;
-				this.cum = total;
-			},
-
-			/**
-			 * Renders the stack total label and adds it to the stack label group.
-			 */
-			render: function (group) {
-				var stackItem = this,									// aliased this
-					str = stackItem.options.formatter.call(stackItem);	// format the text in the label
-
-				// Change the text to reflect the new total and set visibility to hidden in case the serie is hidden
-				if (stackItem.label) {
-					stackItem.label.attr({text: str, visibility: HIDDEN});
-				// Create new label
-				} else {
-					stackItem.label =
-						chart.renderer.text(str, 0, 0)				// dummy positions, actual position updated with setOffset method in columnseries
-							.css(stackItem.options.style)			// apply style
-							.attr({align: stackItem.textAlign,			// fix the text-anchor
-								rotation: stackItem.options.rotation,	// rotation
-								visibility: HIDDEN })					// hidden until setOffset is called
-							.add(group);							// add to the labels-group
-				}
-			},
-
-			/**
-			 * Sets the offset that the stack has from the x value and repositions the label.
-			 */
-			setOffset: function (xOffset, xWidth) {
-				var stackItem = this,										// aliased this
-					neg = stackItem.isNegative,								// special treatment is needed for negative stacks
-					y = axis.translate(stackItem.total),					// stack value translated mapped to chart coordinates
-					yZero = axis.translate(0),								// stack origin
-					h = mathAbs(y - yZero),									// stack height
-					x = chart.xAxis[0].translate(stackItem.x) + xOffset,	// stack x position
-					plotHeight = chart.plotHeight,
-					stackBox = {	// this is the box for the complete stack
-							x: inverted ? (neg ? y : y - h) : x,
-							y: inverted ? plotHeight - x - xWidth : (neg ? (plotHeight - y - h) : plotHeight - y),
-							width: inverted ? h : xWidth,
-							height: inverted ? xWidth : h
-					};
-
-				if (stackItem.label) {
-					stackItem.label
-						.align(stackItem.alignOptions, null, stackBox)	// align the label to the box
-						.attr({visibility: VISIBLE});					// set visibility
-				}
-			}
-		};
-
-		/**
-		 * Get the minimum and maximum for the series of each axis
-		 */
-		function getSeriesExtremes() {
-			var posStack = [],
-				negStack = [],
-				run;
-
-			// reset dataMin and dataMax in case we're redrawing
-			dataMin = dataMax = null;
-
-			// get an overview of what series are associated with this axis
-			associatedSeries = [];
-
-			each(series, function (serie) {
-				run = false;
-
-
-				// match this axis against the series' given or implicated axis
-				each(['xAxis', 'yAxis'], function (strAxis) {
-					if (
-						// the series is a cartesian type, and...
-						serie.isCartesian &&
-						// we're in the right x or y dimension, and...
-						((strAxis === 'xAxis' && isXAxis) || (strAxis === 'yAxis' && !isXAxis)) && (
-							// the axis number is given in the options and matches this axis index, or
-							(serie.options[strAxis] === options.index) ||
-							// the axis index is not given
-							(serie.options[strAxis] === UNDEFINED && options.index === 0)
-						)
-					) {
-						serie[strAxis] = axis;
-						associatedSeries.push(serie);
-
-						// the series is visible, run the min/max detection
-						run = true;
-					}
-				});
-				// ignore hidden series if opted
-				if (!serie.visible && optionsChart.ignoreHiddenSeries) {
-					run = false;
-				}
-
-				if (run) {
-
-					var stacking,
-						posPointStack,
-						negPointStack,
-						stackKey,
-						stackOption,
-						negKey;
-
-					if (!isXAxis) {
-						stacking = serie.options.stacking;
-						usePercentage = stacking === 'percent';
-
-						// create a stack for this particular series type
-						if (stacking) {
-							stackOption = serie.options.stack;
-							stackKey = serie.type + pick(stackOption, '');
-							negKey = '-' + stackKey;
-							serie.stackKey = stackKey; // used in translate
-
-							posPointStack = posStack[stackKey] || []; // contains the total values for each x
-							posStack[stackKey] = posPointStack;
-
-							negPointStack = negStack[negKey] || [];
-							negStack[negKey] = negPointStack;
-						}
-						if (usePercentage) {
-							dataMin = 0;
-							dataMax = 99;
-						}
-					}
-					if (serie.isCartesian) { // line, column etc. need axes, pie doesn't
-						each(serie.data, function (point) {
-							var pointX = point.x,
-								pointY = point.y,
-								isNegative = pointY < 0,
-								pointStack = isNegative ? negPointStack : posPointStack,
-								key = isNegative ? negKey : stackKey,
-								totalPos,
-								pointLow;
-
-							// initial values
-							if (dataMin === null) {
-
-								// start out with the first point
-								dataMin = dataMax = point[xOrY];
-							}
-
-							// x axis
-							if (isXAxis) {
-								if (pointX > dataMax) {
-									dataMax = pointX;
-								} else if (pointX < dataMin) {
-									dataMin = pointX;
-								}
-							} else if (defined(pointY)) { // y axis
-								if (stacking) {
-									pointStack[pointX] =
-										defined(pointStack[pointX]) ?
-										pointStack[pointX] + pointY : pointY;
-								}
-								totalPos = pointStack ? pointStack[pointX] : pointY;
-								pointLow = pick(point.low, totalPos);
-								if (!usePercentage) {
-									if (totalPos > dataMax) {
-										dataMax = totalPos;
-									} else if (pointLow < dataMin) {
-										dataMin = pointLow;
-									}
-								}
-								if (stacking) {
-									// add the series
-									if (!stacks[key]) {
-										stacks[key] = {};
-									}
-
-									// If the StackItem is there, just update the values,
-									// if not, create one first
-									if (!stacks[key][pointX]) {
-										stacks[key][pointX] = new StackItem(options.stackLabels, isNegative, pointX, stackOption);
-									}
-									stacks[key][pointX].setTotal(totalPos);
-								}
-							}
-						});
-
-
-						// For column, areas and bars, set the minimum automatically to zero
-						// and prevent that minPadding is added in setScale
-						if (/(area|column|bar)/.test(serie.type) && !isXAxis) {
-							var threshold = 0; // use series.options.threshold?
-							if (dataMin >= threshold) {
-								dataMin = threshold;
-								ignoreMinPadding = true;
-							} else if (dataMax < threshold) {
-								dataMax = threshold;
-								ignoreMaxPadding = true;
-							}
-						}
-					}
-				}
-			});
-
-		}
-
-		/**
-		 * Translate from axis value to pixel position on the chart, or back
-		 *
-		 */
-		translate = function (val, backwards, cvsCoord, old, handleLog) {
-			var sign = 1,
-				cvsOffset = 0,
-				localA = old ? oldTransA : transA,
-				localMin = old ? oldMin : min,
-				returnValue;
-
-			if (!localA) {
-				localA = transA;
-			}
-
-			if (cvsCoord) {
-				sign *= -1; // canvas coordinates inverts the value
-				cvsOffset = axisLength;
-			}
-			if (reversed) { // reversed axis
-				sign *= -1;
-				cvsOffset -= sign * axisLength;
-			}
-
-			if (backwards) { // reverse translation
-				if (reversed) {
-					val = axisLength - val;
-				}
-				returnValue = val / localA + localMin; // from chart pixel to value
-				if (isLog && handleLog) {
-					returnValue = lin2log(returnValue);
-				}
-
-			} else { // normal translation
-				if (isLog && handleLog) {
-					val = log2lin(val);
-				}
-				returnValue = sign * (val - localMin) * localA + cvsOffset; // from value to chart pixel
-			}
-
-			return returnValue;
-		};
-
-		/**
-		 * Create the path for a plot line that goes from the given value on
-		 * this axis, across the plot to the opposite side
-		 * @param {Number} value
-		 * @param {Number} lineWidth Used for calculation crisp line
-		 * @param {Number] old Use old coordinates (for resizing and rescaling)
-		 */
-		getPlotLinePath = function (value, lineWidth, old) {
-			var x1,
-				y1,
-				x2,
-				y2,
-				translatedValue = translate(value, null, null, old),
-				cHeight = (old && oldChartHeight) || chartHeight,
-				cWidth = (old && oldChartWidth) || chartWidth,
-				skip;
-
-			x1 = x2 = mathRound(translatedValue + transB);
-			y1 = y2 = mathRound(cHeight - translatedValue - transB);
-
-			if (isNaN(translatedValue)) { // no min or max
-				skip = true;
-
-			} else if (horiz) {
-				y1 = plotTop;
-				y2 = cHeight - marginBottom;
-				if (x1 < plotLeft || x1 > plotLeft + plotWidth) {
-					skip = true;
-				}
-			} else {
-				x1 = plotLeft;
-				x2 = cWidth - marginRight;
-				if (y1 < plotTop || y1 > plotTop + plotHeight) {
-					skip = true;
-				}
-			}
-			return skip ?
-				null :
-				renderer.crispLine([M, x1, y1, L, x2, y2], lineWidth || 0);
-		};
-
-
-		/**
-		 * Take an interval and normalize it to multiples of 1, 2, 2.5 and 5
-		 * @param {Number} interval
-		 */
-		function normalizeTickInterval(interval, multiples) {
-			var normalized, i;
-
-			// round to a tenfold of 1, 2, 2.5 or 5
-			magnitude = multiples ? 1 : math.pow(10, mathFloor(math.log(interval) / math.LN10));
-			normalized = interval / magnitude;
-
-			// multiples for a linear scale
-			if (!multiples) {
-				multiples = [1, 2, 2.5, 5, 10];
-				//multiples = [1, 2, 2.5, 4, 5, 7.5, 10];
-
-				// the allowDecimals option
-				if (options.allowDecimals === false || isLog) {
-					if (magnitude === 1) {
-						multiples = [1, 2, 5, 10];
-					} else if (magnitude <= 0.1) {
-						multiples = [1 / magnitude];
-					}
-				}
-			}
-
-			// normalize the interval to the nearest multiple
-			for (i = 0; i < multiples.length; i++) {
-				interval = multiples[i];
-				if (normalized <= (multiples[i] + (multiples[i + 1] || multiples[i])) / 2) {
-					break;
-				}
-			}
-
-			// multiply back to the correct magnitude
-			interval *= magnitude;
-
-			return interval;
-		}
-
-		/**
-		 * Set the tick positions to a time unit that makes sense, for example
-		 * on the first of each month or on every Monday.
-		 */
-		function setDateTimeTickPositions() {
-			tickPositions = [];
-			var i,
-				useUTC = defaultOptions.global.useUTC,
-				oneSecond = 1000 / timeFactor,
-				oneMinute = 60000 / timeFactor,
-				oneHour = 3600000 / timeFactor,
-				oneDay = 24 * 3600000 / timeFactor,
-				oneWeek = 7 * 24 * 3600000 / timeFactor,
-				oneMonth = 30 * 24 * 3600000 / timeFactor,
-				oneYear = 31556952000 / timeFactor,
-
-				units = [[
-					'second',						// unit name
-					oneSecond,						// fixed incremental unit
-					[1, 2, 5, 10, 15, 30]			// allowed multiples
-				], [
-					'minute',						// unit name
-					oneMinute,						// fixed incremental unit
-					[1, 2, 5, 10, 15, 30]			// allowed multiples
-				], [
-					'hour',							// unit name
-					oneHour,						// fixed incremental unit
-					[1, 2, 3, 4, 6, 8, 12]			// allowed multiples
-				], [
-					'day',							// unit name
-					oneDay,							// fixed incremental unit
-					[1, 2]							// allowed multiples
-				], [
-					'week',							// unit name
-					oneWeek,						// fixed incremental unit
-					[1, 2]							// allowed multiples
-				], [
-					'month',
-					oneMonth,
-					[1, 2, 3, 4, 6]
-				], [
-					'year',
-					oneYear,
-					null
-				]],
-
-				unit = units[6], // default unit is years
-				interval = unit[1],
-				multiples = unit[2];
-
-			// loop through the units to find the one that best fits the tickInterval
-			for (i = 0; i < units.length; i++) {
-				unit = units[i];
-				interval = unit[1];
-				multiples = unit[2];
-
-
-				if (units[i + 1]) {
-					// lessThan is in the middle between the highest multiple and the next unit.
-					var lessThan = (interval * multiples[multiples.length - 1] +
-								units[i + 1][1]) / 2;
-
-					// break and keep the current unit
-					if (tickInterval <= lessThan) {
-						break;
-					}
-				}
-			}
-
-			// prevent 2.5 years intervals, though 25, 250 etc. are allowed
-			if (interval === oneYear && tickInterval < 5 * interval) {
-				multiples = [1, 2, 5];
-			}
-
-			// get the minimum value by flooring the date
-			var multitude = normalizeTickInterval(tickInterval / interval, multiples),
-				minYear, // used in months and years as a basis for Date.UTC()
-				minDate = new Date(min * timeFactor);
-
-			minDate.setMilliseconds(0);
-
-			if (interval >= oneSecond) { // second
-				minDate.setSeconds(interval >= oneMinute ? 0 :
-					multitude * mathFloor(minDate.getSeconds() / multitude));
-			}
-
-			if (interval >= oneMinute) { // minute
-				minDate[setMinutes](interval >= oneHour ? 0 :
-					multitude * mathFloor(minDate[getMinutes]() / multitude));
-			}
-
-			if (interval >= oneHour) { // hour
-				minDate[setHours](interval >= oneDay ? 0 :
-					multitude * mathFloor(minDate[getHours]() / multitude));
-			}
-
-			if (interval >= oneDay) { // day
-				minDate[setDate](interval >= oneMonth ? 1 :
-					multitude * mathFloor(minDate[getDate]() / multitude));
-			}
-
-			if (interval >= oneMonth) { // month
-				minDate[setMonth](interval >= oneYear ? 0 :
-					multitude * mathFloor(minDate[getMonth]() / multitude));
-				minYear = minDate[getFullYear]();
-			}
-
-			if (interval >= oneYear) { // year
-				minYear -= minYear % multitude;
-				minDate[setFullYear](minYear);
-			}
-
-			// week is a special case that runs outside the hierarchy
-			if (interval === oneWeek) {
-				// get start of current week, independent of multitude
-				minDate[setDate](minDate[getDate]() - minDate[getDay]() +
-					options.startOfWeek);
-			}
-
-
-			// get tick positions
-			i = 1; // prevent crash just in case
-			minYear = minDate[getFullYear]();
-			var time = minDate.getTime() / timeFactor,
-				minMonth = minDate[getMonth](),
-				minDateDate = minDate[getDate]();
-
-			// iterate and add tick positions at appropriate values
-			while (time < max && i < plotWidth) {
-				tickPositions.push(time);
-
-				// if the interval is years, use Date.UTC to increase years
-				if (interval === oneYear) {
-					time = makeTime(minYear + i * multitude, 0) / timeFactor;
-
-				// if the interval is months, use Date.UTC to increase months
-				} else if (interval === oneMonth) {
-					time = makeTime(minYear, minMonth + i * multitude) / timeFactor;
-
-				// if we're using global time, the interval is not fixed as it jumps
-				// one hour at the DST crossover
-				} else if (!useUTC && (interval === oneDay || interval === oneWeek)) {
-					time = makeTime(minYear, minMonth, minDateDate +
-						i * multitude * (interval === oneDay ? 1 : 7));
-
-				// else, the interval is fixed and we use simple addition
-				} else {
-					time += interval * multitude;
-				}
-
-				i++;
-			}
-			// push the last time
-			tickPositions.push(time);
-
-
-			// dynamic label formatter
-			dateTimeLabelFormat = options.dateTimeLabelFormats[unit[0]];
-		}
-
-		/**
-		 * Fix JS round off float errors
-		 * @param {Number} num
-		 */
-		function correctFloat(num) {
-			var invMag, ret = num;
-			magnitude = pick(magnitude, math.pow(10, mathFloor(math.log(tickInterval) / math.LN10)));
-
-			if (magnitude < 1) {
-				invMag = mathRound(1 / magnitude)  * 10;
-				ret = mathRound(num * invMag) / invMag;
-			}
-			return ret;
-		}
-
-		/**
-		 * Set the tick positions of a linear axis to round values like whole tens or every five.
-		 */
-		function setLinearTickPositions() {
-
-			var i,
-				roundedMin = correctFloat(mathFloor(min / tickInterval) * tickInterval),
-				roundedMax = correctFloat(mathCeil(max / tickInterval) * tickInterval);
-
-			tickPositions = [];
-
-			// populate the intermediate values
-			i = correctFloat(roundedMin);
-			while (i <= roundedMax) {
-				tickPositions.push(i);
-				i = correctFloat(i + tickInterval);
-			}
-
-		}
-
-		/**
-		 * Set the tick positions to round values and optionally extend the extremes
-		 * to the nearest tick
-		 */
-		function setTickPositions() {
-			var length,
-				catPad,
-				linkedParent,
-				linkedParentExtremes,
-				tickIntervalOption = options.tickInterval,
-				tickPixelIntervalOption = options.tickPixelInterval,
-				maxZoom = options.maxZoom || (
-					isXAxis && !defined(options.min) && !defined(options.max) ?
-						mathMin(chart.smallestInterval * 5, dataMax - dataMin) :
-						null
-				),
-				zoomOffset;
-
-
-			axisLength = horiz ? plotWidth : plotHeight;
-
-			// linked axis gets the extremes from the parent axis
-			if (isLinked) {
-				linkedParent = chart[isXAxis ? 'xAxis' : 'yAxis'][options.linkedTo];
-				linkedParentExtremes = linkedParent.getExtremes();
-				min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);
-				max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);
-			} else { // initial min and max from the extreme data values
-				min = pick(userMin, options.min, dataMin);
-				max = pick(userMax, options.max, dataMax);
-			}
-
-			if (isLog) {
-				min = log2lin(min);
-				max = log2lin(max);
-			}
-
-			// maxZoom exceeded, just center the selection
-			if (max - min < maxZoom) {
-				zoomOffset = (maxZoom - max + min) / 2;
-				// if min and max options have been set, don't go beyond it
-				min = mathMax(min - zoomOffset, pick(options.min, min - zoomOffset), dataMin);
-				max = mathMin(min + maxZoom, pick(options.max, min + maxZoom), dataMax);
-			}
-
-			// pad the values to get clear of the chart's edges
-			if (!categories && !usePercentage && !isLinked && defined(min) && defined(max)) {
-				length = (max - min) || 1;
-				if (!defined(options.min) && !defined(userMin) && minPadding && (dataMin < 0 || !ignoreMinPadding)) {
-					min -= length * minPadding;
-				}
-				if (!defined(options.max) && !defined(userMax)  && maxPadding && (dataMax > 0 || !ignoreMaxPadding)) {
-					max += length * maxPadding;
-				}
-			}
-
-			// get tickInterval
-			if (min === max) {
-				tickInterval = 1;
-			} else if (isLinked && !tickIntervalOption &&
-					tickPixelIntervalOption === linkedParent.options.tickPixelInterval) {
-				tickInterval = linkedParent.tickInterval;
-			} else {
-				tickInterval = pick(
-					tickIntervalOption,
-					categories ? // for categoried axis, 1 is default, for linear axis use tickPix
-						1 :
-						(max - min) * tickPixelIntervalOption / axisLength
-				);
-			}
-
-			if (!isDatetimeAxis && !defined(options.tickInterval)) { // linear
-				tickInterval = normalizeTickInterval(tickInterval);
-			}
-			axis.tickInterval = tickInterval; // record for linked axis
-
-			// get minorTickInterval
-			minorTickInterval = options.minorTickInterval === 'auto' && tickInterval ?
-					tickInterval / 5 : options.minorTickInterval;
-
-			// find the tick positions
-			if (isDatetimeAxis) {
-				setDateTimeTickPositions();
-			} else {
-				setLinearTickPositions();
-			}
-
-			if (!isLinked) {
-				// pad categorised axis to nearest half unit
-				if (categories || (isXAxis && chart.hasColumn)) {
-					catPad = (categories ? 1 : tickInterval) * 0.5;
-					if (categories || !defined(pick(options.min, userMin))) {
-						min -= catPad;
-					}
-					if (categories || !defined(pick(options.max, userMax))) {
-						max += catPad;
-					}
-				}
-
-				// reset min/max or remove extremes based on start/end on tick
-				var roundedMin = tickPositions[0],
-					roundedMax = tickPositions[tickPositions.length - 1];
-
-				if (options.startOnTick) {
-					min = roundedMin;
-				} else if (min > roundedMin) {
-					tickPositions.shift();
-				}
-
-				if (options.endOnTick) {
-					max = roundedMax;
-				} else if (max < roundedMax) {
-					tickPositions.pop();
-				}
-
-				// record the greatest number of ticks for multi axis
-				if (!maxTicks) { // first call, or maxTicks have been reset after a zoom operation
-					maxTicks = {
-						x: 0,
-						y: 0
-					};
-				}
-
-				if (!isDatetimeAxis && tickPositions.length > maxTicks[xOrY]) {
-					maxTicks[xOrY] = tickPositions.length;
-				}
-			}
-
-
-		}
-
-		/**
-		 * When using multiple axes, adjust the number of ticks to match the highest
-		 * number of ticks in that group
-		 */
-		function adjustTickAmount() {
-
-			if (maxTicks && !isDatetimeAxis && !categories && !isLinked) { // only apply to linear scale
-				var oldTickAmount = tickAmount,
-					calculatedTickAmount = tickPositions.length;
-
-				// set the axis-level tickAmount to use below
-				tickAmount = maxTicks[xOrY];
-
-				if (calculatedTickAmount < tickAmount) {
-					while (tickPositions.length < tickAmount) {
-						tickPositions.push(correctFloat(
-							tickPositions[tickPositions.length - 1] + tickInterval
-						));
-					}
-					transA *= (calculatedTickAmount - 1) / (tickAmount - 1);
-					max = tickPositions[tickPositions.length - 1];
-
-				}
-				if (defined(oldTickAmount) && tickAmount !== oldTickAmount) {
-					axis.isDirty = true;
-				}
-			}
-
-		}
-
-		/**
-		 * Set the scale based on data min and max, user set min and max or options
-		 *
-		 */
-		function setScale() {
-			var type,
-				i;
-
-			oldMin = min;
-			oldMax = max;
-
-			// get data extremes if needed
-			getSeriesExtremes();
-
-			// get fixed positions based on tickInterval
-			setTickPositions();
-
-			// the translation factor used in translate function
-			oldTransA = transA;
-			transA = axisLength / ((max - min) || 1);
-
-			// reset stacks
-			if (!isXAxis) {
-				for (type in stacks) {
-					for (i in stacks[type]) {
-						stacks[type][i].cum = stacks[type][i].total;
-					}
-				}
-			}
-
-			// mark as dirty if it is not already set to dirty and extremes have changed
-			if (!axis.isDirty) {
-				axis.isDirty = (min !== oldMin || max !== oldMax);
-			}
-
-		}
-
-		/**
-		 * Set the extremes and optionally redraw
-		 * @param {Number} newMin
-		 * @param {Number} newMax
-		 * @param {Boolean} redraw
-		 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-		 *    configuration
-		 *
-		 */
-		function setExtremes(newMin, newMax, redraw, animation) {
-
-			redraw = pick(redraw, true); // defaults to true
-
-			fireEvent(axis, 'setExtremes', { // fire an event to enable syncing of multiple charts
-				min: newMin,
-				max: newMax
-			}, function () { // the default event handler
-
-				userMin = newMin;
-				userMax = newMax;
-
-
-				// redraw
-				if (redraw) {
-					chart.redraw(animation);
-				}
-			});
-
-		}
-
-		/**
-		 * Get the actual axis extremes
-		 */
-		function getExtremes() {
-			return {
-				min: min,
-				max: max,
-				dataMin: dataMin,
-				dataMax: dataMax,
-				userMin: userMin,
-				userMax: userMax
-			};
-		}
-
-		/**
-		 * Get the zero plane either based on zero or on the min or max value.
-		 * Used in bar and area plots
-		 */
-		function getThreshold(threshold) {
-			if (min > threshold) {
-				threshold = min;
-			} else if (max < threshold) {
-				threshold = max;
-			}
-
-			return translate(threshold, 0, 1);
-		}
-
-		/**
-		 * Add a plot band or plot line after render time
-		 *
-		 * @param options {Object} The plotBand or plotLine configuration object
-		 */
-		function addPlotBandOrLine(options) {
-			var obj = new PlotLineOrBand(options).render();
-			plotLinesAndBands.push(obj);
-			return obj;
-		}
-
-		/**
-		 * Render the tick labels to a preliminary position to get their sizes
-		 */
-		function getOffset() {
-
-			var hasData = associatedSeries.length && defined(min) && defined(max),
-				titleOffset = 0,
-				titleMargin = 0,
-				axisTitleOptions = options.title,
-				labelOptions = options.labels,
-				directionFactor = [-1, 1, 1, -1][side],
-				n;
-
-			if (!axisGroup) {
-				axisGroup = renderer.g('axis')
-					.attr({ zIndex: 7 })
-					.add();
-				gridGroup = renderer.g('grid')
-					.attr({ zIndex: 1 })
-					.add();
-			}
-
-			labelOffset = 0; // reset
-
-			if (hasData || isLinked) {
-				each(tickPositions, function (pos) {
-					if (!ticks[pos]) {
-						ticks[pos] = new Tick(pos);
-					} else {
-						ticks[pos].addLabel(); // update labels depending on tick interval
-					}
-
-					// left side must be align: right and right side must have align: left for labels
-					if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === labelOptions.align) {
-
-						// get the highest offset
-						labelOffset = mathMax(
-							ticks[pos].getLabelSize(),
-							labelOffset
-						);
-					}
-
-				});
-
-				if (staggerLines) {
-					labelOffset += (staggerLines - 1) * 16;
-				}
-
-			} else { // doesn't have data
-				for (n in ticks) {
-					ticks[n].destroy();
-					delete ticks[n];
-				}
-			}
-
-			if (axisTitleOptions && axisTitleOptions.text) {
-				if (!axisTitle) {
-					axisTitle = axis.axisTitle = renderer.text(
-						axisTitleOptions.text,
-						0,
-						0,
-						axisTitleOptions.useHTML
-					)
-					.attr({
-						zIndex: 7,
-						rotation: axisTitleOptions.rotation || 0,
-						align:
-							axisTitleOptions.textAlign ||
-							{ low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align]
-					})
-					.css(axisTitleOptions.style)
-					.add();
-					axisTitle.isNew = true;
-				}
-
-				titleOffset = axisTitle.getBBox()[horiz ? 'height' : 'width'];
-				titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10);
-
-			}
-
-			// handle automatic or user set offset
-			offset = directionFactor * (options.offset || axisOffset[side]);
-
-			axisTitleMargin =
-				labelOffset +
-				(side !== 2 && labelOffset && directionFactor * options.labels[horiz ? 'y' : 'x']) +
-				titleMargin;
-
-			axisOffset[side] = mathMax(
-				axisOffset[side],
-				axisTitleMargin + titleOffset + directionFactor * offset
-			);
-
-		}
-
-		/**
-		 * Render the axis
-		 */
-		function render() {
-			var axisTitleOptions = options.title,
-				stackLabelOptions = options.stackLabels,
-				alternateGridColor = options.alternateGridColor,
-				lineWidth = options.lineWidth,
-				lineLeft,
-				lineTop,
-				linePath,
-				hasRendered = chart.hasRendered,
-				slideInTicks = hasRendered && defined(oldMin) && !isNaN(oldMin),
-				hasData = associatedSeries.length && defined(min) && defined(max);
-
-			// update metrics
-			axisLength = horiz ? plotWidth : plotHeight;
-			transA = axisLength / ((max - min) || 1);
-			transB = horiz ? plotLeft : marginBottom; // translation addend
-
-			// If the series has data draw the ticks. Else only the line and title
-			if (hasData || isLinked) {
-
-				// minor ticks
-				if (minorTickInterval && !categories) {
-					var pos = min + (tickPositions[0] - min) % minorTickInterval;
-					for (; pos <= max; pos += minorTickInterval) {
-						if (!minorTicks[pos]) {
-							minorTicks[pos] = new Tick(pos, true);
-						}
-
-						// render new ticks in old position
-						if (slideInTicks && minorTicks[pos].isNew) {
-							minorTicks[pos].render(null, true);
-						}
-
-
-						minorTicks[pos].isActive = true;
-						minorTicks[pos].render();
-					}
-				}
-
-				// major ticks
-				each(tickPositions, function (pos, i) {
-					// linked axes need an extra check to find out if
-					if (!isLinked || (pos >= min && pos <= max)) {
-
-						// render new ticks in old position
-						if (slideInTicks && ticks[pos].isNew) {
-							ticks[pos].render(i, true);
-						}
-
-						ticks[pos].isActive = true;
-						ticks[pos].render(i);
-					}
-				});
-
-				// alternate grid color
-				if (alternateGridColor) {
-					each(tickPositions, function (pos, i) {
-						if (i % 2 === 0 && pos < max) {
-							/*plotLinesAndBands.push(new PlotLineOrBand({
-								from: pos,
-								to: tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] : max,
-								color: alternateGridColor
-							}));*/
-
-							if (!alternateBands[pos]) {
-								alternateBands[pos] = new PlotLineOrBand();
-							}
-							alternateBands[pos].options = {
-								from: pos,
-								to: tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] : max,
-								color: alternateGridColor
-							};
-							alternateBands[pos].render();
-							alternateBands[pos].isActive = true;
-						}
-					});
-				}
-
-				// custom plot bands (behind grid lines)
-				/*if (!hasRendered) { // only first time
-					each(options.plotBands || [], function(plotBandOptions) {
-						plotLinesAndBands.push(new PlotLineOrBand(
-							extend({ zIndex: 1 }, plotBandOptions)
-						).render());
-					});
-				}*/
-
-
-
-
-				// custom plot lines and bands
-				if (!hasRendered) { // only first time
-					each((options.plotLines || []).concat(options.plotBands || []), function (plotLineOptions) {
-						plotLinesAndBands.push(new PlotLineOrBand(plotLineOptions).render());
-					});
-				}
-
-
-
-			} // end if hasData
-
-			// remove inactive ticks
-			each([ticks, minorTicks, alternateBands], function (coll) {
-				var pos;
-				for (pos in coll) {
-					if (!coll[pos].isActive) {
-						coll[pos].destroy();
-						delete coll[pos];
-					} else {
-						coll[pos].isActive = false; // reset
-					}
-				}
-			});
-
-
-
-
-			// Static items. As the axis group is cleared on subsequent calls
-			// to render, these items are added outside the group.
-			// axis line
-			if (lineWidth) {
-				lineLeft = plotLeft + (opposite ? plotWidth : 0) + offset;
-				lineTop = chartHeight - marginBottom - (opposite ? plotHeight : 0) + offset;
-
-				linePath = renderer.crispLine([
-						M,
-						horiz ?
-							plotLeft :
-							lineLeft,
-						horiz ?
-							lineTop :
-							plotTop,
-						L,
-						horiz ?
-							chartWidth - marginRight :
-							lineLeft,
-						horiz ?
-							lineTop :
-							chartHeight - marginBottom
-					], lineWidth);
-				if (!axisLine) {
-					axisLine = renderer.path(linePath)
-						.attr({
-							stroke: options.lineColor,
-							'stroke-width': lineWidth,
-							zIndex: 7
-						})
-						.add();
-				} else {
-					axisLine.animate({ d: linePath });
-				}
-
-			}
-
-			if (axisTitle) {
-				// compute anchor points for each of the title align options
-				var margin = horiz ? plotLeft : plotTop,
-					fontSize = pInt(axisTitleOptions.style.fontSize || 12),
-				// the position in the length direction of the axis
-				alongAxis = {
-					low: margin + (horiz ? 0 : axisLength),
-					middle: margin + axisLength / 2,
-					high: margin + (horiz ? axisLength : 0)
-				}[axisTitleOptions.align],
-
-				// the position in the perpendicular direction of the axis
-				offAxis = (horiz ? plotTop + plotHeight : plotLeft) +
-					(horiz ? 1 : -1) * // horizontal axis reverses the margin
-					(opposite ? -1 : 1) * // so does opposite axes
-					axisTitleMargin +
-					//(isIE ? fontSize / 3 : 0)+ // preliminary fix for vml's centerline
-					(side === 2 ? fontSize : 0);
-
-				axisTitle[axisTitle.isNew ? 'attr' : 'animate']({
-					x: horiz ?
-						alongAxis :
-						offAxis + (opposite ? plotWidth : 0) + offset +
-							(axisTitleOptions.x || 0), // x
-					y: horiz ?
-						offAxis - (opposite ? plotHeight : 0) + offset :
-						alongAxis + (axisTitleOptions.y || 0) // y
-				});
-				axisTitle.isNew = false;
-			}
-
-			// Stacked totals:
-			if (stackLabelOptions && stackLabelOptions.enabled) {
-				var stackKey, oneStack, stackCategory,
-					stackTotalGroup = axis.stackTotalGroup;
-
-				// Create a separate group for the stack total labels
-				if (!stackTotalGroup) {
-					axis.stackTotalGroup = stackTotalGroup =
-						renderer.g('stack-labels')
-							.attr({
-								visibility: VISIBLE,
-								zIndex: 6
-							})
-							.translate(plotLeft, plotTop)
-							.add();
-				}
-
-				// Render each stack total
-				for (stackKey in stacks) {
-					oneStack = stacks[stackKey];
-					for (stackCategory in oneStack) {
-						oneStack[stackCategory].render(stackTotalGroup);
-					}
-				}
-			}
-			// End stacked totals
-
-			axis.isDirty = false;
-		}
-
-		/**
-		 * Remove a plot band or plot line from the chart by id
-		 * @param {Object} id
-		 */
-		function removePlotBandOrLine(id) {
-			var i = plotLinesAndBands.length;
-			while (i--) {
-				if (plotLinesAndBands[i].id === id) {
-					plotLinesAndBands[i].destroy();
-				}
-			}
-		}
-
-		/**
-		 * Redraw the axis to reflect changes in the data or axis extremes
-		 */
-		function redraw() {
-
-			// hide tooltip and hover states
-			if (tracker.resetTracker) {
-				tracker.resetTracker();
-			}
-
-			// render the axis
-			render();
-
-			// move plot lines and bands
-			each(plotLinesAndBands, function (plotLine) {
-				plotLine.render();
-			});
-
-			// mark associated series as dirty and ready for redraw
-			each(associatedSeries, function (series) {
-				series.isDirty = true;
-			});
-
-		}
-
-		/**
-		 * Set new axis categories and optionally redraw
-		 * @param {Array} newCategories
-		 * @param {Boolean} doRedraw
-		 */
-		function setCategories(newCategories, doRedraw) {
-				// set the categories
-				axis.categories = userOptions.categories = categories = newCategories;
-
-				// force reindexing tooltips
-				each(associatedSeries, function (series) {
-					series.translate();
-					series.setTooltipPoints(true);
-				});
-
-
-				// optionally redraw
-				axis.isDirty = true;
-
-				if (pick(doRedraw, true)) {
-					chart.redraw();
-				}
-		}
-
-		/**
-		 * Destroys an Axis instance.
-		 */
-		function destroy() {
-			var stackKey;
-
-			// Remove the events
-			removeEvent(axis);
-
-			// Destroy each stack total
-			for (stackKey in stacks) {
-				destroyObjectProperties(stacks[stackKey]);
-
-				stacks[stackKey] = null;
-			}
-
-			// Destroy stack total group
-			if (axis.stackTotalGroup) {
-				axis.stackTotalGroup = axis.stackTotalGroup.destroy();
-			}
-
-			// Destroy collections
-			each([ticks, minorTicks, alternateBands, plotLinesAndBands], function (coll) {
-				destroyObjectProperties(coll);
-			});
-
-			// Destroy local variables
-			each([axisLine, axisGroup, gridGroup, axisTitle], function (obj) {
-				if (obj) {
-					obj.destroy();
-				}
-			});
-			axisLine = axisGroup = gridGroup = axisTitle = null;
-		}
-
-
-		// Run Axis
-
-		// inverted charts have reversed xAxes as default
-		if (inverted && isXAxis && reversed === UNDEFINED) {
-			reversed = true;
-		}
-
-
-		// expose some variables
-		extend(axis, {
-			addPlotBand: addPlotBandOrLine,
-			addPlotLine: addPlotBandOrLine,
-			adjustTickAmount: adjustTickAmount,
-			categories: categories,
-			getExtremes: getExtremes,
-			getPlotLinePath: getPlotLinePath,
-			getThreshold: getThreshold,
-			isXAxis: isXAxis,
-			options: options,
-			plotLinesAndBands: plotLinesAndBands,
-			getOffset: getOffset,
-			render: render,
-			setCategories: setCategories,
-			setExtremes: setExtremes,
-			setScale: setScale,
-			setTickPositions: setTickPositions,
-			translate: translate,
-			redraw: redraw,
-			removePlotBand: removePlotBandOrLine,
-			removePlotLine: removePlotBandOrLine,
-			reversed: reversed,
-			stacks: stacks,
-			destroy: destroy
-		});
-
-		// register event listeners
-		for (eventType in events) {
-			addEvent(axis, eventType, events[eventType]);
-		}
-
-		// set min and max
-		setScale();
-
-	} // end Axis
-
-
-	/**
-	 * The toolbar object
-	 */
-	function Toolbar() {
-		var buttons = {};
-
-		/*jslint unparam: true*//* allow the unused param title until Toolbar rewrite*/
-		function add(id, text, title, fn) {
-			if (!buttons[id]) {
-				var button = renderer.text(
-					text,
-					0,
-					0
-				)
-				.css(options.toolbar.itemStyle)
-				.align({
-					align: 'right',
-					x: -marginRight - 20,
-					y: plotTop + 30
-				})
-				.on('click', fn)
-				/*.on('touchstart', function(e) {
-					e.stopPropagation(); // don't fire the container event
-					fn();
-				})*/
-				.attr({
-					align: 'right',
-					zIndex: 20
-				})
-				.add();
-				buttons[id] = button;
-			}
-		}
-		/*jslint unparam: false*/
-
-		function remove(id) {
-			discardElement(buttons[id].element);
-			buttons[id] = null;
-		}
-
-		// public
-		return {
-			add: add,
-			remove: remove
-		};
-	}
-
-	/**
-	 * The tooltip object
-	 * @param {Object} options Tooltip options
-	 */
-	function Tooltip(options) {
-		var currentSeries,
-			borderWidth = options.borderWidth,
-			crosshairsOptions = options.crosshairs,
-			crosshairs = [],
-			style = options.style,
-			shared = options.shared,
-			padding = pInt(style.padding),
-			boxOffLeft = borderWidth + padding, // off left/top position as IE can't
-				//properly handle negative positioned shapes
-			tooltipIsHidden = true,
-			boxWidth,
-			boxHeight,
-			currentX = 0,
-			currentY = 0;
-
-		// remove padding CSS and apply padding on box instead
-		style.padding = 0;
-
-		// create the elements
-		var group = renderer.g('tooltip')
-			.attr({	zIndex: 8 })
-			.add(),
-
-			box = renderer.rect(boxOffLeft, boxOffLeft, 0, 0, options.borderRadius, borderWidth)
-				.attr({
-					fill: options.backgroundColor,
-					'stroke-width': borderWidth
-				})
-				.add(group)
-				.shadow(options.shadow),
-			label = renderer.text('', padding + boxOffLeft, pInt(style.fontSize) + padding + boxOffLeft, options.useHTML)
-				.attr({ zIndex: 1 })
-				.css(style)
-				.add(group);
-
-		group.hide();
-
-		/**
-		 * Destroy the tooltip and its elements.
-		 */
-		function destroy() {
-			each(crosshairs, function (crosshair) {
-				if (crosshair) {
-					crosshair.destroy();
-				}
-			});
-
-			// Destroy and clear local variables
-			each([box, label, group], function (obj) {
-				if (obj) {
-					obj.destroy();
-				}
-			});
-			box = label = group = null;
-		}
-
-		/**
-		 * In case no user defined formatter is given, this will be used
-		 */
-		function defaultFormatter() {
-			var pThis = this,
-				items = pThis.points || splat(pThis),
-				xAxis = items[0].series.xAxis,
-				x = pThis.x,
-				isDateTime = xAxis && xAxis.options.type === 'datetime',
-				useHeader = isString(x) || isDateTime,
-				s;
-
-			// build the header
-			s = useHeader ?
-				['<span style="font-size: 10px">' +
-				(isDateTime ? dateFormat('%A, %b %e, %Y', x) :  x) +
-				'</span>'] : [];
-
-			// build the values
-			each(items, function (item) {
-				s.push(item.point.tooltipFormatter(useHeader));
-			});
-			return s.join('<br/>');
-		}
-
-		/**
-		 * Provide a soft movement for the tooltip
-		 *
-		 * @param {Number} finalX
-		 * @param {Number} finalY
-		 */
-		function move(finalX, finalY) {
-
-			currentX = tooltipIsHidden ? finalX : (2 * currentX + finalX) / 3;
-			currentY = tooltipIsHidden ? finalY : (currentY + finalY) / 2;
-
-			group.translate(currentX, currentY);
-
-
-			// run on next tick of the mouse tracker
-			if (mathAbs(finalX - currentX) > 1 || mathAbs(finalY - currentY) > 1) {
-				tooltipTick = function () {
-					move(finalX, finalY);
-				};
-			} else {
-				tooltipTick = null;
-			}
-		}
-
-		/**
-		 * Hide the tooltip
-		 */
-		function hide() {
-			if (!tooltipIsHidden) {
-				var hoverPoints = chart.hoverPoints;
-
-				group.hide();
-
-				each(crosshairs, function (crosshair) {
-					if (crosshair) {
-						crosshair.hide();
-					}
-				});
-
-				// hide previous hoverPoints and set new
-				if (hoverPoints) {
-					each(hoverPoints, function (point) {
-						point.setState();
-					});
-				}
-				chart.hoverPoints = null;
-
-
-				tooltipIsHidden = true;
-			}
-
-		}
-
-		/**
-		 * Refresh the tooltip's text and position.
-		 * @param {Object} point
-		 *
-		 */
-		function refresh(point) {
-			var x,
-				y,
-				show,
-				bBox,
-				plotX,
-				plotY = 0,
-				textConfig = {},
-				text,
-				pointConfig = [],
-				tooltipPos = point.tooltipPos,
-				formatter = options.formatter || defaultFormatter,
-				hoverPoints = chart.hoverPoints,
-				placedTooltipPoint;
-
-			// shared tooltip, array is sent over
-			if (shared) {
-
-				// hide previous hoverPoints and set new
-				if (hoverPoints) {
-					each(hoverPoints, function (point) {
-						point.setState();
-					});
-				}
-				chart.hoverPoints = point;
-
-				each(point, function (item) {
-					/*var series = item.series,
-						hoverPoint = series.hoverPoint;
-					if (hoverPoint) {
-						hoverPoint.setState();
-					}
-					series.hoverPoint = item;*/
-					item.setState(HOVER_STATE);
-					plotY += item.plotY; // for average
-
-					pointConfig.push(item.getLabelConfig());
-				});
-
-				plotX = point[0].plotX;
-				plotY = mathRound(plotY) / point.length; // mathRound because Opera 10 has problems here
-
-				textConfig = {
-					x: point[0].category
-				};
-				textConfig.points = pointConfig;
-				point = point[0];
-
-			// single point tooltip
-			} else {
-				textConfig = point.getLabelConfig();
-			}
-			text = formatter.call(textConfig);
-
-			// register the current series
-			currentSeries = point.series;
-
-			// get the reference point coordinates (pie charts use tooltipPos)
-			plotX = shared ? plotX : point.plotX;
-			plotY = shared ? plotY : point.plotY;
-			x = mathRound(tooltipPos ? tooltipPos[0] : (inverted ? plotWidth - plotY : plotX));
-			y = mathRound(tooltipPos ? tooltipPos[1] : (inverted ? plotHeight - plotX : plotY));
-
-
-			// hide tooltip if the point falls outside the plot
-			show = shared || !point.series.isCartesian || isInsidePlot(x, y);
-
-			// update the inner HTML
-			if (text === false || !show) {
-				hide();
-			} else {
-
-				// show it
-				if (tooltipIsHidden) {
-					group.show();
-					tooltipIsHidden = false;
-				}
-
-				// update text
-				label.attr({
-					text: text
-				});
-
-				// get the bounding box
-				bBox = label.getBBox();
-				boxWidth = bBox.width + 2 * padding;
-				boxHeight = bBox.height + 2 * padding;
-
-				// set the size of the box
-				box.attr({
-					width: boxWidth,
-					height: boxHeight,
-					stroke: options.borderColor || point.color || currentSeries.color || '#606060'
-				});
-
-				placedTooltipPoint = placeBox(boxWidth, boxHeight, plotLeft, plotTop, plotWidth, plotHeight, {x: x, y: y});
-
-				// do the move
-				move(mathRound(placedTooltipPoint.x - boxOffLeft), mathRound(placedTooltipPoint.y - boxOffLeft));
-			}
-
-
-			// crosshairs
-			if (crosshairsOptions) {
-				crosshairsOptions = splat(crosshairsOptions); // [x, y]
-
-				var path,
-					i = crosshairsOptions.length,
-					attribs,
-					axis;
-
-				while (i--) {
-					axis = point.series[i ? 'yAxis' : 'xAxis'];
-					if (crosshairsOptions[i] && axis) {
-						path = axis
-							.getPlotLinePath(point[i ? 'y' : 'x'], 1);
-						if (crosshairs[i]) {
-							crosshairs[i].attr({ d: path, visibility: VISIBLE });
-
-						} else {
-							attribs = {
-								'stroke-width': crosshairsOptions[i].width || 1,
-								stroke: crosshairsOptions[i].color || '#C0C0C0',
-								zIndex: 2
-							};
-							if (crosshairsOptions[i].dashStyle) {
-								attribs.dashstyle = crosshairsOptions[i].dashStyle;
-							}
-							crosshairs[i] = renderer.path(path)
-								.attr(attribs)
-								.add();
-						}
-					}
-				}
-			}
-		}
-
-
-
-		// public members
-		return {
-			shared: shared,
-			refresh: refresh,
-			hide: hide,
-			destroy: destroy
-		};
-	}
-
-	/**
-	 * The mouse tracker object
-	 * @param {Object} options
-	 */
-	function MouseTracker(options) {
-
-
-		var mouseDownX,
-			mouseDownY,
-			hasDragged,
-			selectionMarker,
-			zoomType = optionsChart.zoomType,
-			zoomX = /x/.test(zoomType),
-			zoomY = /y/.test(zoomType),
-			zoomHor = (zoomX && !inverted) || (zoomY && inverted),
-			zoomVert = (zoomY && !inverted) || (zoomX && inverted);
-
-		/**
-		 * Add crossbrowser support for chartX and chartY
-		 * @param {Object} e The event object in standard browsers
-		 */
-		function normalizeMouseEvent(e) {
-			var ePos,
-				pageZoomFix = isWebKit &&
-					doc.width / doc.body.scrollWidth -
-					1, // #224, #348
-				chartPosLeft,
-				chartPosTop,
-				chartX,
-				chartY;
-
-			// common IE normalizing
-			e = e || win.event;
-			if (!e.target) {
-				e.target = e.srcElement;
-			}
-
-			// iOS
-			ePos = e.touches ? e.touches.item(0) : e;
-
-			// in certain cases, get mouse position
-			if (e.type !== 'mousemove' || win.opera || pageZoomFix) { // only Opera needs position on mouse move, see below
-				chartPosition = getPosition(container);
-				chartPosLeft = chartPosition.left;
-				chartPosTop = chartPosition.top;
-			}
-
-			// chartX and chartY
-			if (isIE) { // IE including IE9 that has chartX but in a different meaning
-				chartX = e.x;
-				chartY = e.y;
-			} else {
-				if (ePos.layerX === UNDEFINED) { // Opera and iOS
-					chartX = ePos.pageX - chartPosLeft;
-					chartY = ePos.pageY - chartPosTop;
-				} else {
-					chartX = e.layerX;
-					chartY = e.layerY;
-				}
-			}
-
-			// correct for page zoom bug in WebKit
-			if (pageZoomFix) {
-				chartX += mathRound((pageZoomFix + 1) * chartPosLeft - chartPosLeft);
-				chartY += mathRound((pageZoomFix + 1) * chartPosTop - chartPosTop);
-			}
-
-			return extend(e, {
-				chartX: chartX,
-				chartY: chartY
-			});
-		}
-
-		/**
-		 * Get the click position in terms of axis values.
-		 *
-		 * @param {Object} e A mouse event
-		 */
-		function getMouseCoordinates(e) {
-			var coordinates = {
-				xAxis: [],
-				yAxis: []
-			};
-			each(axes, function (axis) {
-				var translate = axis.translate,
-					isXAxis = axis.isXAxis,
-					isHorizontal = inverted ? !isXAxis : isXAxis;
-
-				coordinates[isXAxis ? 'xAxis' : 'yAxis'].push({
-					axis: axis,
-					value: translate(
-						isHorizontal ?
-							e.chartX - plotLeft  :
-							plotHeight - e.chartY + plotTop,
-						true
-					)
-				});
-			});
-			return coordinates;
-		}
-
-		/**
-		 * With line type charts with a single tracker, get the point closest to the mouse
-		 */
-		function onmousemove(e) {
-			var point,
-				points,
-				hoverPoint = chart.hoverPoint,
-				hoverSeries = chart.hoverSeries,
-				i,
-				j,
-				distance = chartWidth,
-				index = inverted ? e.chartY : e.chartX - plotLeft; // wtf?
-
-			// shared tooltip
-			if (tooltip && options.shared) {
-				points = [];
-
-				// loop over all series and find the ones with points closest to the mouse
-				i = series.length;
-				for (j = 0; j < i; j++) {
-					if (series[j].visible && series[j].tooltipPoints.length) {
-						point = series[j].tooltipPoints[index];
-						point._dist = mathAbs(index - point.plotX);
-						distance = mathMin(distance, point._dist);
-						points.push(point);
-					}
-				}
-				// remove furthest points
-				i = points.length;
-				while (i--) {
-					if (points[i]._dist > distance) {
-						points.splice(i, 1);
-					}
-				}
-				// refresh the tooltip if necessary
-				if (points.length && (points[0].plotX !== hoverX)) {
-					tooltip.refresh(points);
-					hoverX = points[0].plotX;
-				}
-			}
-
-			// separate tooltip and general mouse events
-			if (hoverSeries && hoverSeries.tracker) { // only use for line-type series with common tracker
-
-				// get the point
-				point = hoverSeries.tooltipPoints[index];
-
-				// a new point is hovered, refresh the tooltip
-				if (point && point !== hoverPoint) {
-
-					// trigger the events
-					point.onMouseOver();
-
-				}
-			}
-		}
-
-
-
-		/**
-		 * Reset the tracking by hiding the tooltip, the hover series state and the hover point
-		 */
-		function resetTracker() {
-			var hoverSeries = chart.hoverSeries,
-				hoverPoint = chart.hoverPoint;
-
-			if (hoverPoint) {
-				hoverPoint.onMouseOut();
-			}
-
-			if (hoverSeries) {
-				hoverSeries.onMouseOut();
-			}
-
-			if (tooltip) {
-				tooltip.hide();
-			}
-
-			hoverX = null;
-		}
-
-		/**
-		 * Mouse up or outside the plot area
-		 */
-		function drop() {
-			if (selectionMarker) {
-				var selectionData = {
-						xAxis: [],
-						yAxis: []
-					},
-					selectionBox = selectionMarker.getBBox(),
-					selectionLeft = selectionBox.x - plotLeft,
-					selectionTop = selectionBox.y - plotTop;
-
-
-				// a selection has been made
-				if (hasDragged) {
-
-					// record each axis' min and max
-					each(axes, function (axis) {
-						var translate = axis.translate,
-							isXAxis = axis.isXAxis,
-							isHorizontal = inverted ? !isXAxis : isXAxis,
-							selectionMin = translate(
-								isHorizontal ?
-									selectionLeft :
-									plotHeight - selectionTop - selectionBox.height,
-								true,
-								0,
-								0,
-								1
-							),
-							selectionMax = translate(
-								isHorizontal ?
-									selectionLeft + selectionBox.width :
-									plotHeight - selectionTop,
-								true,
-								0,
-								0,
-								1
-							);
-
-							selectionData[isXAxis ? 'xAxis' : 'yAxis'].push({
-								axis: axis,
-								min: mathMin(selectionMin, selectionMax), // for reversed axes,
-								max: mathMax(selectionMin, selectionMax)
-							});
-
-					});
-					fireEvent(chart, 'selection', selectionData, zoom);
-
-				}
-				selectionMarker = selectionMarker.destroy();
-			}
-
-			chart.mouseIsDown = mouseIsDown = hasDragged = false;
-			removeEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop);
-
-		}
-
-		/**
-		 * Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea.
-		 */
-		function hideTooltipOnMouseMove(e) {
-			var pageX = defined(e.pageX) ? e.pageX : e.page.x, // In mootools the event is wrapped and the page x/y position is named e.page.x
-				pageY = defined(e.pageX) ? e.pageY : e.page.y; // Ref: http://mootools.net/docs/core/Types/DOMEvent
-
-			if (chartPosition &&
-					!isInsidePlot(pageX - chartPosition.left - plotLeft,
-						pageY - chartPosition.top - plotTop)) {
-				resetTracker();
-			}
-		}
-
-		/**
-		 * Set the JS events on the container element
-		 */
-		function setDOMEvents() {
-			var lastWasOutsidePlot = true;
-			/*
-			 * Record the starting position of a dragoperation
-			 */
-			container.onmousedown = function (e) {
-				e = normalizeMouseEvent(e);
-
-				// issue #295, dragging not always working in Firefox
-				if (!hasTouch && e.preventDefault) {
-					e.preventDefault();
-				}
-
-				// record the start position
-				chart.mouseIsDown = mouseIsDown = true;
-				mouseDownX = e.chartX;
-				mouseDownY = e.chartY;
-
-				addEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop);
-			};
-
-			// The mousemove, touchmove and touchstart event handler
-			var mouseMove = function (e) {
-
-				// let the system handle multitouch operations like two finger scroll
-				// and pinching
-				if (e && e.touches && e.touches.length > 1) {
-					return;
-				}
-
-				// normalize
-				e = normalizeMouseEvent(e);
-				if (!hasTouch) { // not for touch devices
-					e.returnValue = false;
-				}
-
-				var chartX = e.chartX,
-					chartY = e.chartY,
-					isOutsidePlot = !isInsidePlot(chartX - plotLeft, chartY - plotTop);
-
-				// cache chart position for issue #149 fix
-				if (!chartPosition) {
-					chartPosition = getPosition(container);
-				}
-
-				// on touch devices, only trigger click if a handler is defined
-				if (hasTouch && e.type === 'touchstart') {
-					if (attr(e.target, 'isTracker')) {
-						if (!chart.runTrackerClick) {
-							e.preventDefault();
-						}
-					} else if (!runChartClick && !isOutsidePlot) {
-						e.preventDefault();
-					}
-				}
-
-				// cancel on mouse outside
-				if (isOutsidePlot) {
-
-					/*if (!lastWasOutsidePlot) {
-						// reset the tracker
-						resetTracker();
-					}*/
-
-					// drop the selection if any and reset mouseIsDown and hasDragged
-					//drop();
-					if (chartX < plotLeft) {
-						chartX = plotLeft;
-					} else if (chartX > plotLeft + plotWidth) {
-						chartX = plotLeft + plotWidth;
-					}
-
-					if (chartY < plotTop) {
-						chartY = plotTop;
-					} else if (chartY > plotTop + plotHeight) {
-						chartY = plotTop + plotHeight;
-					}
-
-				}
-
-				if (mouseIsDown && e.type !== 'touchstart') { // make selection
-
-					// determine if the mouse has moved more than 10px
-					hasDragged = Math.sqrt(
-						Math.pow(mouseDownX - chartX, 2) +
-						Math.pow(mouseDownY - chartY, 2)
-					);
-					if (hasDragged > 10) {
-
-						// make a selection
-						if (hasCartesianSeries && (zoomX || zoomY) &&
-								isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop)) {
-							if (!selectionMarker) {
-								selectionMarker = renderer.rect(
-									plotLeft,
-									plotTop,
-									zoomHor ? 1 : plotWidth,
-									zoomVert ? 1 : plotHeight,
-									0
-								)
-								.attr({
-									fill: optionsChart.selectionMarkerFill || 'rgba(69,114,167,0.25)',
-									zIndex: 7
-								})
-								.add();
-							}
-						}
-
-						// adjust the width of the selection marker
-						if (selectionMarker && zoomHor) {
-							var xSize = chartX - mouseDownX;
-							selectionMarker.attr({
-								width: mathAbs(xSize),
-								x: (xSize > 0 ? 0 : xSize) + mouseDownX
-							});
-						}
-						// adjust the height of the selection marker
-						if (selectionMarker && zoomVert) {
-							var ySize = chartY - mouseDownY;
-							selectionMarker.attr({
-								height: mathAbs(ySize),
-								y: (ySize > 0 ? 0 : ySize) + mouseDownY
-							});
-						}
-					}
-
-				} else if (!isOutsidePlot) {
-					// show the tooltip
-					onmousemove(e);
-				}
-
-				lastWasOutsidePlot = isOutsidePlot;
-
-				// when outside plot, allow touch-drag by returning true
-				return isOutsidePlot || !hasCartesianSeries;
-			};
-
-			/*
-			 * When the mouse enters the container, run mouseMove
-			 */
-			container.onmousemove = mouseMove;
-
-			/*
-			 * When the mouse leaves the container, hide the tracking (tooltip).
-			 */
-			addEvent(container, 'mouseleave', resetTracker);
-
-			// issue #149 workaround
-			// The mouseleave event above does not always fire. Whenever the mouse is moving
-			// outside the plotarea, hide the tooltip
-			addEvent(doc, 'mousemove', hideTooltipOnMouseMove);
-
-			container.ontouchstart = function (e) {
-				// For touch devices, use touchmove to zoom
-				if (zoomX || zoomY) {
-					container.onmousedown(e);
-				}
-				// Show tooltip and prevent the lower mouse pseudo event
-				mouseMove(e);
-			};
-
-			/*
-			 * Allow dragging the finger over the chart to read the values on touch
-			 * devices
-			 */
-			container.ontouchmove = mouseMove;
-
-			/*
-			 * Allow dragging the finger over the chart to read the values on touch
-			 * devices
-			 */
-			container.ontouchend = function () {
-				if (hasDragged) {
-					resetTracker();
-				}
-			};
-
-
-			// MooTools 1.2.3 doesn't fire this in IE when using addEvent
-			container.onclick = function (e) {
-				var hoverPoint = chart.hoverPoint;
-				e = normalizeMouseEvent(e);
-
-				e.cancelBubble = true; // IE specific
-
-
-				if (!hasDragged) {
-					if (hoverPoint && attr(e.target, 'isTracker')) {
-						var plotX = hoverPoint.plotX,
-							plotY = hoverPoint.plotY;
-
-						// add page position info
-						extend(hoverPoint, {
-							pageX: chartPosition.left + plotLeft +
-								(inverted ? plotWidth - plotY : plotX),
-							pageY: chartPosition.top + plotTop +
-								(inverted ? plotHeight - plotX : plotY)
-						});
-
-						// the series click event
-						fireEvent(hoverPoint.series, 'click', extend(e, {
-							point: hoverPoint
-						}));
-
-						// the point click event
-						hoverPoint.firePointEvent('click', e);
-
-					} else {
-						extend(e, getMouseCoordinates(e));
-
-						// fire a click event in the chart
-						if (isInsidePlot(e.chartX - plotLeft, e.chartY - plotTop)) {
-							fireEvent(chart, 'click', e);
-						}
-					}
-
-
-				}
-				// reset mouseIsDown and hasDragged
-				hasDragged = false;
-			};
-
-		}
-
-		/**
-		 * Destroys the MouseTracker object and disconnects DOM events.
-		 */
-		function destroy() {
-			// Destroy the tracker group element
-			if (chart.trackerGroup) {
-				chart.trackerGroup = trackerGroup = chart.trackerGroup.destroy();
-			}
-
-			removeEvent(doc, 'mousemove', hideTooltipOnMouseMove);
-			container.onclick = container.onmousedown = container.onmousemove = container.ontouchstart = container.ontouchend = container.ontouchmove = null;
-		}
-
-		/**
-		 * Create the image map that listens for mouseovers
-		 */
-		placeTrackerGroup = function () {
-
-			// first create - plot positions is not final at this stage
-			if (!trackerGroup) {
-				chart.trackerGroup = trackerGroup = renderer.g('tracker')
-					.attr({ zIndex: 9 })
-					.add();
-
-			// then position - this happens on load and after resizing and changing
-			// axis or box positions
-			} else {
-				trackerGroup.translate(plotLeft, plotTop);
-				if (inverted) {
-					trackerGroup.attr({
-						width: chart.plotWidth,
-						height: chart.plotHeight
-					}).invert();
-				}
-			}
-		};
-
-
-		// Run MouseTracker
-		placeTrackerGroup();
-		if (options.enabled) {
-			chart.tooltip = tooltip = Tooltip(options);
-		}
-
-		setDOMEvents();
-
-		// set the fixed interval ticking for the smooth tooltip
-		tooltipInterval = setInterval(function () {
-			if (tooltipTick) {
-				tooltipTick();
-			}
-		}, 32);
-
-		// expose properties
-		extend(this, {
-			zoomX: zoomX,
-			zoomY: zoomY,
-			resetTracker: resetTracker,
-			destroy: destroy
-		});
-	}
-
-
-
-	/**
-	 * The overview of the chart's series
-	 */
-	var Legend = function () {
-
-		var options = chart.options.legend;
-
-		if (!options.enabled) {
-			return;
-		}
-
-		var horizontal = options.layout === 'horizontal',
-			symbolWidth = options.symbolWidth,
-			symbolPadding = options.symbolPadding,
-			allItems,
-			style = options.style,
-			itemStyle = options.itemStyle,
-			itemHoverStyle = options.itemHoverStyle,
-			itemHiddenStyle = options.itemHiddenStyle,
-			padding = pInt(style.padding),
-			y = 18,
-			initialItemX = 4 + padding + symbolWidth + symbolPadding,
-			itemX,
-			itemY,
-			lastItemY,
-			itemHeight = 0,
-			box,
-			legendBorderWidth = options.borderWidth,
-			legendBackgroundColor = options.backgroundColor,
-			legendGroup,
-			offsetWidth,
-			widthOption = options.width,
-			series = chart.series,
-			reversedLegend = options.reversed;
-
-
-
-		/**
-		 * Set the colors for the legend item
-		 * @param {Object} item A Series or Point instance
-		 * @param {Object} visible Dimmed or colored
-		 */
-		function colorizeItem(item, visible) {
-			var legendItem = item.legendItem,
-				legendLine = item.legendLine,
-				legendSymbol = item.legendSymbol,
-				hiddenColor = itemHiddenStyle.color,
-				textColor = visible ? options.itemStyle.color : hiddenColor,
-				lineColor = visible ? item.color : hiddenColor,
-				symbolAttr = visible ? item.pointAttr[NORMAL_STATE] : {
-					stroke: hiddenColor,
-					fill: hiddenColor
-				};
-
-			if (legendItem) {
-				legendItem.css({ fill: textColor });
-			}
-			if (legendLine) {
-				legendLine.attr({ stroke: lineColor });
-			}
-			if (legendSymbol) {
-				legendSymbol.attr(symbolAttr);
-			}
-
-		}
-
-		/**
-		 * Position the legend item
-		 * @param {Object} item A Series or Point instance
-		 * @param {Object} visible Dimmed or colored
-		 */
-		function positionItem(item, itemX, itemY) {
-			var legendItem = item.legendItem,
-				legendLine = item.legendLine,
-				legendSymbol = item.legendSymbol,
-				checkbox = item.checkbox;
-			if (legendItem) {
-				legendItem.attr({
-					x: itemX,
-					y: itemY
-				});
-			}
-			if (legendLine) {
-				legendLine.translate(itemX, itemY - 4);
-			}
-			if (legendSymbol) {
-				legendSymbol.attr({
-					x: itemX + legendSymbol.xOff,
-					y: itemY + legendSymbol.yOff
-				});
-			}
-			if (checkbox) {
-				checkbox.x = itemX;
-				checkbox.y = itemY;
-			}
-		}
-
-		/**
-		 * Destroy a single legend item
-		 * @param {Object} item The series or point
-		 */
-		function destroyItem(item) {
-			var checkbox = item.checkbox;
-
-			// pull out from the array
-			//erase(allItems, item);
-
-			// destroy SVG elements
-			each(['legendItem', 'legendLine', 'legendSymbol'], function (key) {
-				if (item[key]) {
-					item[key].destroy();
-				}
-			});
-
-			if (checkbox) {
-				discardElement(item.checkbox);
-			}
-
-
-		}
-
-		/**
-		 * Destroys the legend.
-		 */
-		function destroy() {
-			if (box) {
-				box = box.destroy();
-			}
-
-			if (legendGroup) {
-				legendGroup = legendGroup.destroy();
-			}
-		}
-
-		/**
-		 * Position the checkboxes after the width is determined
-		 */
-		function positionCheckboxes() {
-			each(allItems, function (item) {
-				var checkbox = item.checkbox,
-					alignAttr = legendGroup.alignAttr;
-				if (checkbox) {
-					css(checkbox, {
-						left: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 40) + PX,
-						top: (alignAttr.translateY + checkbox.y - 11) + PX
-					});
-				}
-			});
-		}
-
-		/**
-		 * Render a single specific legend item
-		 * @param {Object} item A series or point
-		 */
-		function renderItem(item) {
-			var bBox,
-				itemWidth,
-				legendSymbol,
-				symbolX,
-				symbolY,
-				simpleSymbol,
-				li = item.legendItem,
-				series = item.series || item,
-				itemOptions = series.options,
-				strokeWidth = (itemOptions && itemOptions.borderWidth) || 0;
-
-			if (!li) { // generate it once, later move it
-
-				// let these series types use a simple symbol
-				simpleSymbol = /^(bar|pie|area|column)$/.test(series.type);
-
-				// generate the list item text
-				item.legendItem = li = renderer.text(
-						options.labelFormatter.call(item),
-						0,
-						0
-					)
-					.css(item.visible ? itemStyle : itemHiddenStyle)
-					.on('mouseover', function () {
-						item.setState(HOVER_STATE);
-						li.css(itemHoverStyle);
-					})
-					.on('mouseout', function () {
-						li.css(item.visible ? itemStyle : itemHiddenStyle);
-						item.setState();
-					})
-					.on('click', function () {
-						var strLegendItemClick = 'legendItemClick',
-							fnLegendItemClick = function () {
-								item.setVisible();
-							};
-
-						// click the name or symbol
-						if (item.firePointEvent) { // point
-							item.firePointEvent(strLegendItemClick, null, fnLegendItemClick);
-						} else {
-							fireEvent(item, strLegendItemClick, null, fnLegendItemClick);
-						}
-					})
-					.attr({ zIndex: 2 })
-					.add(legendGroup);
-
-				// draw the line
-				if (!simpleSymbol && itemOptions && itemOptions.lineWidth) {
-					var attrs = {
-							'stroke-width': itemOptions.lineWidth,
-							zIndex: 2
-						};
-					if (itemOptions.dashStyle) {
-						attrs.dashstyle = itemOptions.dashStyle;
-					}
-					item.legendLine = renderer.path([
-						M,
-						-symbolWidth - symbolPadding,
-						0,
-						L,
-						-symbolPadding,
-						0
-					])
-					.attr(attrs)
-					.add(legendGroup);
-				}
-
-				// draw a simple symbol
-				if (simpleSymbol) { // bar|pie|area|column
-
-					legendSymbol = renderer.rect(
-						(symbolX = -symbolWidth - symbolPadding),
-						(symbolY = -11),
-						symbolWidth,
-						12,
-						2
-					).attr({
-						//'stroke-width': 0,
-						zIndex: 3
-					}).add(legendGroup);
-
-				// draw the marker
-				} else if (itemOptions && itemOptions.marker && itemOptions.marker.enabled) {
-					legendSymbol = renderer.symbol(
-						item.symbol,
-						(symbolX = -symbolWidth / 2 - symbolPadding),
-						(symbolY = -4),
-						itemOptions.marker.radius
-					)
-					//.attr(item.pointAttr[NORMAL_STATE])
-					.attr({ zIndex: 3 })
-					.add(legendGroup);
-
-				}
-				if (legendSymbol) {
-					legendSymbol.xOff = symbolX + (strokeWidth % 2 / 2);
-					legendSymbol.yOff = symbolY + (strokeWidth % 2 / 2);
-				}
-
-				item.legendSymbol = legendSymbol;
-
-				// colorize the items
-				colorizeItem(item, item.visible);
-
-
-				// add the HTML checkbox on top
-				if (itemOptions && itemOptions.showCheckbox) {
-					item.checkbox = createElement('input', {
-						type: 'checkbox',
-						checked: item.selected,
-						defaultChecked: item.selected // required by IE7
-					}, options.itemCheckboxStyle, container);
-
-					addEvent(item.checkbox, 'click', function (event) {
-						var target = event.target;
-						fireEvent(item, 'checkboxClick', {
-								checked: target.checked
-							},
-							function () {
-								item.select();
-							}
-						);
-					});
-				}
-			}
-
-
-			// calculate the positions for the next line
-			bBox = li.getBBox();
-
-			itemWidth = item.legendItemWidth =
-				options.itemWidth || symbolWidth + symbolPadding + bBox.width + padding;
-			itemHeight = bBox.height;
-
-			// if the item exceeds the width, start a new line
-			if (horizontal && itemX - initialItemX + itemWidth >
-					(widthOption || (chartWidth - 2 * padding - initialItemX))) {
-				itemX = initialItemX;
-				itemY += itemHeight;
-			}
-			lastItemY = itemY;
-
-			// position the newly generated or reordered items
-			positionItem(item, itemX, itemY);
-
-			// advance
-			if (horizontal) {
-				itemX += itemWidth;
-			} else {
-				itemY += itemHeight;
-			}
-
-			// the width of the widest item
-			offsetWidth = widthOption || mathMax(
-				horizontal ? itemX - initialItemX : itemWidth,
-				offsetWidth
-			);
-
-
-
-			// add it all to an array to use below
-			//allItems.push(item);
-		}
-
-		/**
-		 * Render the legend. This method can be called both before and after
-		 * chart.render. If called after, it will only rearrange items instead
-		 * of creating new ones.
-		 */
-		function renderLegend() {
-			itemX = initialItemX;
-			itemY = y;
-			offsetWidth = 0;
-			lastItemY = 0;
-
-			if (!legendGroup) {
-				legendGroup = renderer.g('legend')
-					.attr({ zIndex: 7 })
-					.add();
-			}
-
-
-			// add each series or point
-			allItems = [];
-			each(series, function (serie) {
-				var seriesOptions = serie.options;
-
-				if (!seriesOptions.showInLegend) {
-					return;
-				}
-
-				// use points or series for the legend item depending on legendType
-				allItems = allItems.concat(seriesOptions.legendType === 'point' ?
-					serie.data :
-					serie
-				);
-
-			});
-
-			// sort by legendIndex
-			stableSort(allItems, function (a, b) {
-				return (a.options.legendIndex || 0) - (b.options.legendIndex || 0);
-			});
-
-			// reversed legend
-			if (reversedLegend) {
-				allItems.reverse();
-			}
-
-			// render the items
-			each(allItems, renderItem);
-
-
-
-			// Draw the border
-			legendWidth = widthOption || offsetWidth;
-			legendHeight = lastItemY - y + itemHeight;
-
-			if (legendBorderWidth || legendBackgroundColor) {
-				legendWidth += 2 * padding;
-				legendHeight += 2 * padding;
-
-				if (!box) {
-					box = renderer.rect(
-						0,
-						0,
-						legendWidth,
-						legendHeight,
-						options.borderRadius,
-						legendBorderWidth || 0
-					).attr({
-						stroke: options.borderColor,
-						'stroke-width': legendBorderWidth || 0,
-						fill: legendBackgroundColor || NONE
-					})
-					.add(legendGroup)
-					.shadow(options.shadow);
-					box.isNew = true;
-
-				} else if (legendWidth > 0 && legendHeight > 0) {
-					box[box.isNew ? 'attr' : 'animate'](
-						box.crisp(null, null, null, legendWidth, legendHeight)
-					);
-					box.isNew = false;
-				}
-
-				// hide the border if no items
-				box[allItems.length ? 'show' : 'hide']();
-			}
-
-			// 1.x compatibility: positioning based on style
-			var props = ['left', 'right', 'top', 'bottom'],
-				prop,
-				i = 4;
-			while (i--) {
-				prop = props[i];
-				if (style[prop] && style[prop] !== 'auto') {
-					options[i < 2 ? 'align' : 'verticalAlign'] = prop;
-					options[i < 2 ? 'x' : 'y'] = pInt(style[prop]) * (i % 2 ? -1 : 1);
-				}
-			}
-
-			if (allItems.length) {
-				legendGroup.align(extend(options, {
-					width: legendWidth,
-					height: legendHeight
-				}), true, spacingBox);
-			}
-
-			if (!isResizing) {
-				positionCheckboxes();
-			}
-		}
-
-
-		// run legend
-		renderLegend();
-
-		// move checkboxes
-		addEvent(chart, 'endResize', positionCheckboxes);
-
-		// expose
-		return {
-			colorizeItem: colorizeItem,
-			destroyItem: destroyItem,
-			renderLegend: renderLegend,
-			destroy: destroy
-		};
-	};
-
-
-
-
-
-
-	/**
-	 * Initialize an individual series, called internally before render time
-	 */
-	function initSeries(options) {
-		var type = options.type || optionsChart.type || optionsChart.defaultSeriesType,
-			typeClass = seriesTypes[type],
-			serie,
-			hasRendered = chart.hasRendered;
-
-		// an inverted chart can't take a column series and vice versa
-		if (hasRendered) {
-			if (inverted && type === 'column') {
-				typeClass = seriesTypes.bar;
-			} else if (!inverted && type === 'bar') {
-				typeClass = seriesTypes.column;
-			}
-		}
-
-		serie = new typeClass();
-
-		serie.init(chart, options);
-
-		// set internal chart properties
-		if (!hasRendered && serie.inverted) {
-			inverted = true;
-		}
-		if (serie.isCartesian) {
-			hasCartesianSeries = serie.isCartesian;
-		}
-
-		series.push(serie);
-
-		return serie;
-	}
-
-	/**
-	 * Add a series dynamically after  time
-	 *
-	 * @param {Object} options The config options
-	 * @param {Boolean} redraw Whether to redraw the chart after adding. Defaults to true.
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 *
-	 * @return {Object} series The newly created series object
-	 */
-	function addSeries(options, redraw, animation) {
-		var series;
-
-		if (options) {
-			setAnimation(animation, chart);
-			redraw = pick(redraw, true); // defaults to true
-
-			fireEvent(chart, 'addSeries', { options: options }, function () {
-				series = initSeries(options);
-				series.isDirty = true;
-
-				chart.isDirtyLegend = true; // the series array is out of sync with the display
-				if (redraw) {
-					chart.redraw();
-				}
-			});
-		}
-
-		return series;
-	}
-
-	/**
-	 * Check whether a given point is within the plot area
-	 *
-	 * @param {Number} x Pixel x relative to the coordinateSystem
-	 * @param {Number} y Pixel y relative to the coordinateSystem
-	 */
-	isInsidePlot = function (x, y) {
-		return x >= 0 &&
-			x <= plotWidth &&
-			y >= 0 &&
-			y <= plotHeight;
-	};
-
-	/**
-	 * Adjust all axes tick amounts
-	 */
-	function adjustTickAmounts() {
-		if (optionsChart.alignTicks !== false) {
-			each(axes, function (axis) {
-				axis.adjustTickAmount();
-			});
-		}
-		maxTicks = null;
-	}
-
-	/**
-	 * Redraw legend, axes or series based on updated data
-	 *
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 */
-	function redraw(animation) {
-		var redrawLegend = chart.isDirtyLegend,
-			hasStackedSeries,
-			isDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed?
-			seriesLength = series.length,
-			i = seriesLength,
-			clipRect = chart.clipRect,
-			serie;
-
-		setAnimation(animation, chart);
-
-		// link stacked series
-		while (i--) {
-			serie = series[i];
-			if (serie.isDirty && serie.options.stacking) {
-				hasStackedSeries = true;
-				break;
-			}
-		}
-		if (hasStackedSeries) { // mark others as dirty
-			i = seriesLength;
-			while (i--) {
-				serie = series[i];
-				if (serie.options.stacking) {
-					serie.isDirty = true;
-				}
-			}
-		}
-
-		// handle updated data in the series
-		each(series, function (serie) {
-			if (serie.isDirty) { // prepare the data so axis can read it
-				serie.cleanData();
-				serie.getSegments();
-
-				if (serie.options.legendType === 'point') {
-					redrawLegend = true;
-				}
-			}
-		});
-
-		// handle added or removed series
-		if (redrawLegend && legend.renderLegend) { // series or pie points are added or removed
-			// draw legend graphics
-			legend.renderLegend();
-
-			chart.isDirtyLegend = false;
-		}
-
-		if (hasCartesianSeries) {
-			if (!isResizing) {
-
-				// reset maxTicks
-				maxTicks = null;
-
-				// set axes scales
-				each(axes, function (axis) {
-					axis.setScale();
-				});
-			}
-			adjustTickAmounts();
-			getMargins();
-
-			// redraw axes
-			each(axes, function (axis) {
-				if (axis.isDirty || isDirtyBox) {
-					axis.redraw();
-					isDirtyBox = true; // always redraw box to reflect changes in the axis labels
-				}
-			});
-
-
-		}
-
-		// the plot areas size has changed
-		if (isDirtyBox) {
-			drawChartBox();
-			placeTrackerGroup();
-
-			// move clip rect
-			if (clipRect) {
-				stop(clipRect);
-				clipRect.animate({ // for chart resize
-					width: chart.plotSizeX,
-					height: chart.plotSizeY
-				});
-			}
-
-		}
-
-
-		// redraw affected series
-		each(series, function (serie) {
-			if (serie.isDirty && serie.visible &&
-					(!serie.isCartesian || serie.xAxis)) { // issue #153
-				serie.redraw();
-			}
-		});
-
-
-		// hide tooltip and hover states
-		if (tracker && tracker.resetTracker) {
-			tracker.resetTracker();
-		}
-
-		// fire the event
-		fireEvent(chart, 'redraw');
-	}
-
-
-
-	/**
-	 * Dim the chart and show a loading text or symbol
-	 * @param {String} str An optional text to show in the loading label instead of the default one
-	 */
-	function showLoading(str) {
-		var loadingOptions = options.loading;
-
-		// create the layer at the first call
-		if (!loadingDiv) {
-			loadingDiv = createElement(DIV, {
-				className: 'highcharts-loading'
-			}, extend(loadingOptions.style, {
-				left: plotLeft + PX,
-				top: plotTop + PX,
-				width: plotWidth + PX,
-				height: plotHeight + PX,
-				zIndex: 10,
-				display: NONE
-			}), container);
-
-			loadingSpan = createElement(
-				'span',
-				null,
-				loadingOptions.labelStyle,
-				loadingDiv
-			);
-
-		}
-
-		// update text
-		loadingSpan.innerHTML = str || options.lang.loading;
-
-		// show it
-		if (!loadingShown) {
-			css(loadingDiv, { opacity: 0, display: '' });
-			animate(loadingDiv, {
-				opacity: loadingOptions.style.opacity
-			}, {
-				duration: loadingOptions.showDuration
-			});
-			loadingShown = true;
-		}
-	}
-	/**
-	 * Hide the loading layer
-	 */
-	function hideLoading() {
-		animate(loadingDiv, {
-			opacity: 0
-		}, {
-			duration: options.loading.hideDuration,
-			complete: function () {
-				css(loadingDiv, { display: NONE });
-			}
-		});
-		loadingShown = false;
-	}
-
-	/**
-	 * Get an axis, series or point object by id.
-	 * @param id {String} The id as given in the configuration options
-	 */
-	function get(id) {
-		var i,
-			j,
-			data;
-
-		// search axes
-		for (i = 0; i < axes.length; i++) {
-			if (axes[i].options.id === id) {
-				return axes[i];
-			}
-		}
-
-		// search series
-		for (i = 0; i < series.length; i++) {
-			if (series[i].options.id === id) {
-				return series[i];
-			}
-		}
-
-		// search points
-		for (i = 0; i < series.length; i++) {
-			data = series[i].data;
-			for (j = 0; j < data.length; j++) {
-				if (data[j].id === id) {
-					return data[j];
-				}
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Create the Axis instances based on the config options
-	 */
-	function getAxes() {
-		var xAxisOptions = options.xAxis || {},
-			yAxisOptions = options.yAxis || {},
-			axis;
-
-		// make sure the options are arrays and add some members
-		xAxisOptions = splat(xAxisOptions);
-		each(xAxisOptions, function (axis, i) {
-			axis.index = i;
-			axis.isX = true;
-		});
-
-		yAxisOptions = splat(yAxisOptions);
-		each(yAxisOptions, function (axis, i) {
-			axis.index = i;
-		});
-
-		// concatenate all axis options into one array
-		axes = xAxisOptions.concat(yAxisOptions);
-
-		// loop the options and construct axis objects
-		chart.xAxis = [];
-		chart.yAxis = [];
-		axes = map(axes, function (axisOptions) {
-			axis = new Axis(axisOptions);
-			chart[axis.isXAxis ? 'xAxis' : 'yAxis'].push(axis);
-
-			return axis;
-		});
-
-		adjustTickAmounts();
-	}
-
-
-	/**
-	 * Get the currently selected points from all series
-	 */
-	function getSelectedPoints() {
-		var points = [];
-		each(series, function (serie) {
-			points = points.concat(grep(serie.data, function (point) {
-				return point.selected;
-			}));
-		});
-		return points;
-	}
-
-	/**
-	 * Get the currently selected series
-	 */
-	function getSelectedSeries() {
-		return grep(series, function (serie) {
-			return serie.selected;
-		});
-	}
-
-	/**
-	 * Zoom out to 1:1
-	 */
-	zoomOut = function () {
-		fireEvent(chart, 'selection', { resetSelection: true }, zoom);
-		chart.toolbar.remove('zoom');
-
-	};
-	/**
-	 * Zoom into a given portion of the chart given by axis coordinates
-	 * @param {Object} event
-	 */
-	zoom = function (event) {
-
-		// add button to reset selection
-		var lang = defaultOptions.lang,
-			animate = chart.pointCount < 100;
-		chart.toolbar.add('zoom', lang.resetZoom, lang.resetZoomTitle, zoomOut);
-
-		// if zoom is called with no arguments, reset the axes
-		if (!event || event.resetSelection) {
-			each(axes, function (axis) {
-				axis.setExtremes(null, null, false, animate);
-			});
-		} else { // else, zoom in on all axes
-			each(event.xAxis.concat(event.yAxis), function (axisData) {
-				var axis = axisData.axis;
-
-				// don't zoom more than maxZoom
-				if (chart.tracker[axis.isXAxis ? 'zoomX' : 'zoomY']) {
-					axis.setExtremes(axisData.min, axisData.max, false, animate);
-				}
-			});
-		}
-
-		// redraw chart
-		redraw();
-	};
-
-	/**
-	 * Show the title and subtitle of the chart
-	 *
-	 * @param titleOptions {Object} New title options
-	 * @param subtitleOptions {Object} New subtitle options
-	 *
-	 */
-	function setTitle(titleOptions, subtitleOptions) {
-
-		chartTitleOptions = merge(options.title, titleOptions);
-		chartSubtitleOptions = merge(options.subtitle, subtitleOptions);
-
-		// add title and subtitle
-		each([
-			['title', titleOptions, chartTitleOptions],
-			['subtitle', subtitleOptions, chartSubtitleOptions]
-		], function (arr) {
-			var name = arr[0],
-				title = chart[name],
-				titleOptions = arr[1],
-				chartTitleOptions = arr[2];
-
-			if (title && titleOptions) {
-				title = title.destroy(); // remove old
-			}
-			if (chartTitleOptions && chartTitleOptions.text && !title) {
-				chart[name] = renderer.text(
-					chartTitleOptions.text,
-					0,
-					0,
-					chartTitleOptions.useHTML
-				)
-				.attr({
-					align: chartTitleOptions.align,
-					'class': 'highcharts-' + name,
-					zIndex: 1
-				})
-				.css(chartTitleOptions.style)
-				.add()
-				.align(chartTitleOptions, false, spacingBox);
-			}
-		});
-
-	}
-
-	/**
-	 * Get chart width and height according to options and container size
-	 */
-	function getChartSize() {
-
-		containerWidth = (renderToClone || renderTo).offsetWidth;
-		containerHeight = (renderToClone || renderTo).offsetHeight;
-		chart.chartWidth = chartWidth = optionsChart.width || containerWidth || 600;
-		chart.chartHeight = chartHeight = optionsChart.height ||
-			// the offsetHeight of an empty container is 0 in standard browsers, but 19 in IE7:
-			(containerHeight > 19 ? containerHeight : 400);
-	}
-
-
-	/**
-	 * Get the containing element, determine the size and create the inner container
-	 * div to hold the chart
-	 */
-	function getContainer() {
-		renderTo = optionsChart.renderTo;
-		containerId = PREFIX + idCounter++;
-
-		if (isString(renderTo)) {
-			renderTo = doc.getElementById(renderTo);
-		}
-
-		// remove previous chart
-		renderTo.innerHTML = '';
-
-		// If the container doesn't have an offsetWidth, it has or is a child of a node
-		// that has display:none. We need to temporarily move it out to a visible
-		// state to determine the size, else the legend and tooltips won't render
-		// properly
-		if (!renderTo.offsetWidth) {
-			renderToClone = renderTo.cloneNode(0);
-			css(renderToClone, {
-				position: ABSOLUTE,
-				top: '-9999px',
-				display: ''
-			});
-			doc.body.appendChild(renderToClone);
-		}
-
-		// get the width and height
-		getChartSize();
-
-		// create the inner container
-		chart.container = container = createElement(DIV, {
-				className: 'highcharts-container' +
-					(optionsChart.className ? ' ' + optionsChart.className : ''),
-				id: containerId
-			}, extend({
-				position: RELATIVE,
-				overflow: HIDDEN, // needed for context menu (avoid scrollbars) and
-					// content overflow in IE
-				width: chartWidth + PX,
-				height: chartHeight + PX,
-				textAlign: 'left'
-			}, optionsChart.style),
-			renderToClone || renderTo
-		);
-
-		chart.renderer = renderer =
-			optionsChart.forExport ? // force SVG, used for SVG export
-				new SVGRenderer(container, chartWidth, chartHeight, true) :
-				new Renderer(container, chartWidth, chartHeight);
-
-		// Issue 110 workaround:
-		// In Firefox, if a div is positioned by percentage, its pixel position may land
-		// between pixels. The container itself doesn't display this, but an SVG element
-		// inside this container will be drawn at subpixel precision. In order to draw
-		// sharp lines, this must be compensated for. This doesn't seem to work inside
-		// iframes though (like in jsFiddle).
-		var subPixelFix, rect;
-		if (isFirefox && container.getBoundingClientRect) {
-			subPixelFix = function () {
-				css(container, { left: 0, top: 0 });
-				rect = container.getBoundingClientRect();
-				css(container, {
-					left: (-(rect.left - pInt(rect.left))) + PX,
-					top: (-(rect.top - pInt(rect.top))) + PX
-				});
-			};
-
-			// run the fix now
-			subPixelFix();
-
-			// run it on resize
-			addEvent(win, 'resize', subPixelFix);
-
-			// remove it on chart destroy
-			addEvent(chart, 'destroy', function () {
-				removeEvent(win, 'resize', subPixelFix);
-			});
-		}
-	}
-
-	/**
-	 * Calculate margins by rendering axis labels in a preliminary position. Title,
-	 * subtitle and legend have already been rendered at this stage, but will be
-	 * moved into their final positions
-	 */
-	getMargins = function () {
-		var legendOptions = options.legend,
-			legendMargin = pick(legendOptions.margin, 10),
-			legendX = legendOptions.x,
-			legendY = legendOptions.y,
-			align = legendOptions.align,
-			verticalAlign = legendOptions.verticalAlign,
-			titleOffset;
-
-		resetMargins();
-
-		// adjust for title and subtitle
-		if ((chart.title || chart.subtitle) && !defined(optionsMarginTop)) {
-			titleOffset = mathMax(
-				(chart.title && !chartTitleOptions.floating && !chartTitleOptions.verticalAlign && chartTitleOptions.y) || 0,
-				(chart.subtitle && !chartSubtitleOptions.floating && !chartSubtitleOptions.verticalAlign && chartSubtitleOptions.y) || 0
-			);
-			if (titleOffset) {
-				plotTop = mathMax(plotTop, titleOffset + pick(chartTitleOptions.margin, 15) + spacingTop);
-			}
-		}
-		// adjust for legend
-		if (legendOptions.enabled && !legendOptions.floating) {
-			if (align === 'right') { // horizontal alignment handled first
-				if (!defined(optionsMarginRight)) {
-					marginRight = mathMax(
-						marginRight,
-						legendWidth - legendX + legendMargin + spacingRight
-					);
-				}
-			} else if (align === 'left') {
-				if (!defined(optionsMarginLeft)) {
-					plotLeft = mathMax(
-						plotLeft,
-						legendWidth + legendX + legendMargin + spacingLeft
-					);
-				}
-
-			} else if (verticalAlign === 'top') {
-				if (!defined(optionsMarginTop)) {
-					plotTop = mathMax(
-						plotTop,
-						legendHeight + legendY + legendMargin + spacingTop
-					);
-				}
-
-			} else if (verticalAlign === 'bottom') {
-				if (!defined(optionsMarginBottom)) {
-					marginBottom = mathMax(
-						marginBottom,
-						legendHeight - legendY + legendMargin + spacingBottom
-					);
-				}
-			}
-		}
-
-		// pre-render axes to get labels offset width
-		if (hasCartesianSeries) {
-			each(axes, function (axis) {
-				axis.getOffset();
-			});
-		}
-
-		if (!defined(optionsMarginLeft)) {
-			plotLeft += axisOffset[3];
-		}
-		if (!defined(optionsMarginTop)) {
-			plotTop += axisOffset[0];
-		}
-		if (!defined(optionsMarginBottom)) {
-			marginBottom += axisOffset[2];
-		}
-		if (!defined(optionsMarginRight)) {
-			marginRight += axisOffset[1];
-		}
-
-		setChartSize();
-
-	};
-
-	/**
-	 * Add the event handlers necessary for auto resizing
-	 *
-	 */
-	function initReflow() {
-		var reflowTimeout;
-		function reflow() {
-			var width = optionsChart.width || renderTo.offsetWidth,
-				height = optionsChart.height || renderTo.offsetHeight;
-
-			if (width && height) { // means container is display:none
-				if (width !== containerWidth || height !== containerHeight) {
-					clearTimeout(reflowTimeout);
-					reflowTimeout = setTimeout(function () {
-						resize(width, height, false);
-					}, 100);
-				}
-				containerWidth = width;
-				containerHeight = height;
-			}
-		}
-		addEvent(win, 'resize', reflow);
-		addEvent(chart, 'destroy', function () {
-			removeEvent(win, 'resize', reflow);
-		});
-	}
-
-	/**
-	 * Fires endResize event on chart instance.
-	 */
-	function fireEndResize() {
-		fireEvent(chart, 'endResize', null, function () {
-			isResizing -= 1;
-		});
-	}
-
-	/**
-	 * Resize the chart to a given width and height
-	 * @param {Number} width
-	 * @param {Number} height
-	 * @param {Object|Boolean} animation
-	 */
-	resize = function (width, height, animation) {
-		var chartTitle = chart.title,
-			chartSubtitle = chart.subtitle;
-
-		isResizing += 1;
-
-		// set the animation for the current process
-		setAnimation(animation, chart);
-
-		oldChartHeight = chartHeight;
-		oldChartWidth = chartWidth;
-		chart.chartWidth = chartWidth = mathRound(width);
-		chart.chartHeight = chartHeight = mathRound(height);
-
-		css(container, {
-			width: chartWidth + PX,
-			height: chartHeight + PX
-		});
-		renderer.setSize(chartWidth, chartHeight, animation);
-
-		// update axis lengths for more correct tick intervals:
-		plotWidth = chartWidth - plotLeft - marginRight;
-		plotHeight = chartHeight - plotTop - marginBottom;
-
-		// handle axes
-		maxTicks = null;
-		each(axes, function (axis) {
-			axis.isDirty = true;
-			axis.setScale();
-		});
-
-		// make sure non-cartesian series are also handled
-		each(series, function (serie) {
-			serie.isDirty = true;
-		});
-
-		chart.isDirtyLegend = true; // force legend redraw
-		chart.isDirtyBox = true; // force redraw of plot and chart border
-
-		getMargins();
-
-		// move titles
-		if (chartTitle) {
-			chartTitle.align(null, null, spacingBox);
-		}
-		if (chartSubtitle) {
-			chartSubtitle.align(null, null, spacingBox);
-		}
-
-		redraw(animation);
-
-
-		oldChartHeight = null;
-		fireEvent(chart, 'resize');
-
-		// fire endResize and set isResizing back
-		// If animation is disabled, fire without delay
-		if (globalAnimation === false) {
-			fireEndResize();
-		} else { // else set a timeout with the animation duration
-			setTimeout(fireEndResize, (globalAnimation && globalAnimation.duration) || 500);
-		}
-	};
-
-	/**
-	 * Set the public chart properties. This is done before and after the pre-render
-	 * to determine margin sizes
-	 */
-	setChartSize = function () {
-
-		chart.plotLeft = plotLeft = mathRound(plotLeft);
-		chart.plotTop = plotTop = mathRound(plotTop);
-		chart.plotWidth = plotWidth = mathRound(chartWidth - plotLeft - marginRight);
-		chart.plotHeight = plotHeight = mathRound(chartHeight - plotTop - marginBottom);
-
-		chart.plotSizeX = inverted ? plotHeight : plotWidth;
-		chart.plotSizeY = inverted ? plotWidth : plotHeight;
-
-		spacingBox = {
-			x: spacingLeft,
-			y: spacingTop,
-			width: chartWidth - spacingLeft - spacingRight,
-			height: chartHeight - spacingTop - spacingBottom
-		};
-	};
-
-	/**
-	 * Initial margins before auto size margins are applied
-	 */
-	resetMargins = function () {
-		plotTop = pick(optionsMarginTop, spacingTop);
-		marginRight = pick(optionsMarginRight, spacingRight);
-		marginBottom = pick(optionsMarginBottom, spacingBottom);
-		plotLeft = pick(optionsMarginLeft, spacingLeft);
-		axisOffset = [0, 0, 0, 0]; // top, right, bottom, left
-	};
-
-	/**
-	 * Draw the borders and backgrounds for chart and plot area
-	 */
-	drawChartBox = function () {
-		var chartBorderWidth = optionsChart.borderWidth || 0,
-			chartBackgroundColor = optionsChart.backgroundColor,
-			plotBackgroundColor = optionsChart.plotBackgroundColor,
-			plotBackgroundImage = optionsChart.plotBackgroundImage,
-			mgn,
-			plotSize = {
-				x: plotLeft,
-				y: plotTop,
-				width: plotWidth,
-				height: plotHeight
-			};
-
-		// Chart area
-		mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0);
-
-		if (chartBorderWidth || chartBackgroundColor) {
-			if (!chartBackground) {
-				chartBackground = renderer.rect(mgn / 2, mgn / 2, chartWidth - mgn, chartHeight - mgn,
-						optionsChart.borderRadius, chartBorderWidth)
-					.attr({
-						stroke: optionsChart.borderColor,
-						'stroke-width': chartBorderWidth,
-						fill: chartBackgroundColor || NONE
-					})
-					.add()
-					.shadow(optionsChart.shadow);
-			} else { // resize
-				chartBackground.animate(
-					chartBackground.crisp(null, null, null, chartWidth - mgn, chartHeight - mgn)
-				);
-			}
-		}
-
-
-		// Plot background
-		if (plotBackgroundColor) {
-			if (!plotBackground) {
-				plotBackground = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0)
-					.attr({
-						fill: plotBackgroundColor
-					})
-					.add()
-					.shadow(optionsChart.plotShadow);
-			} else {
-				plotBackground.animate(plotSize);
-			}
-		}
-		if (plotBackgroundImage) {
-			if (!plotBGImage) {
-				plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight)
-					.add();
-			} else {
-				plotBGImage.animate(plotSize);
-			}
-		}
-
-		// Plot area border
-		if (optionsChart.plotBorderWidth) {
-			if (!plotBorder) {
-				plotBorder = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0, optionsChart.plotBorderWidth)
-					.attr({
-						stroke: optionsChart.plotBorderColor,
-						'stroke-width': optionsChart.plotBorderWidth,
-						zIndex: 4
-					})
-					.add();
-			} else {
-				plotBorder.animate(
-					plotBorder.crisp(null, plotLeft, plotTop, plotWidth, plotHeight)
-				);
-			}
-		}
-
-		// reset
-		chart.isDirtyBox = false;
-	};
-
-	/**
-	 * Render all graphics for the chart
-	 */
-	function render() {
-		var labels = options.labels,
-			credits = options.credits,
-			creditsHref;
-
-		// Title
-		setTitle();
-
-
-		// Legend
-		legend = chart.legend = new Legend();
-
-		// Get margins by pre-rendering axes
-		getMargins();
-		each(axes, function (axis) {
-			axis.setTickPositions(true); // update to reflect the new margins
-		});
-		adjustTickAmounts();
-		getMargins(); // second pass to check for new labels
-
-
-		// Draw the borders and backgrounds
-		drawChartBox();
-
-		// Axes
-		if (hasCartesianSeries) {
-			each(axes, function (axis) {
-				axis.render();
-			});
-		}
-
-
-		// The series
-		if (!chart.seriesGroup) {
-			chart.seriesGroup = renderer.g('series-group')
-				.attr({ zIndex: 3 })
-				.add();
-		}
-		each(series, function (serie) {
-			serie.translate();
-			serie.setTooltipPoints();
-			serie.render();
-		});
-
-
-		// Labels
-		if (labels.items) {
-			each(labels.items, function () {
-				var style = extend(labels.style, this.style),
-					x = pInt(style.left) + plotLeft,
-					y = pInt(style.top) + plotTop + 12;
-
-				// delete to prevent rewriting in IE
-				delete style.left;
-				delete style.top;
-
-				renderer.text(
-					this.html,
-					x,
-					y
-				)
-				.attr({ zIndex: 2 })
-				.css(style)
-				.add();
-
-			});
-		}
-
-		// Toolbar (don't redraw)
-		if (!chart.toolbar) {
-			chart.toolbar = Toolbar();
-		}
-
-		// Credits
-		if (credits.enabled && !chart.credits) {
-			creditsHref = credits.href;
-			chart.credits = renderer.text(
-				credits.text,
-				0,
-				0
-			)
-			.on('click', function () {
-				if (creditsHref) {
-					location.href = creditsHref;
-				}
-			})
-			.attr({
-				align: credits.position.align,
-				zIndex: 8
-			})
-			.css(credits.style)
-			.add()
-			.align(credits.position);
-		}
-
-		placeTrackerGroup();
-
-		// Set flag
-		chart.hasRendered = true;
-
-		// If the chart was rendered outside the top container, put it back in
-		if (renderToClone) {
-			renderTo.appendChild(container);
-			discardElement(renderToClone);
-			//updatePosition(container);
-		}
-	}
-
-	/**
-	 * Clean up memory usage
-	 */
-	function destroy() {
-		var i,
-			parentNode = container && container.parentNode;
-
-		// If the chart is destroyed already, do nothing.
-		// This will happen if if a script invokes chart.destroy and
-		// then it will be called again on win.unload
-		if (chart === null) {
-			return;
-		}
-
-		// fire the chart.destoy event
-		fireEvent(chart, 'destroy');
-
-		// remove events
-		removeEvent(win, 'unload', destroy);
-		removeEvent(chart);
-
-		// ==== Destroy collections:
-		// Destroy axes
-		i = axes.length;
-		while (i--) {
-			axes[i] = axes[i].destroy();
-		}
-
-		// Destroy each series
-		i = series.length;
-		while (i--) {
-			series[i] = series[i].destroy();
-		}
-
-		// ==== Destroy chart properties:
-		each(['title', 'subtitle', 'seriesGroup', 'clipRect', 'credits', 'tracker'], function (name) {
-			var prop = chart[name];
-
-			if (prop) {
-				chart[name] = prop.destroy();
-			}
-		});
-
-		// ==== Destroy local variables:
-		each([chartBackground, plotBorder, plotBackground, legend, tooltip, renderer, tracker], function (obj) {
-			if (obj && obj.destroy) {
-				obj.destroy();
-			}
-		});
-		chartBackground = plotBorder = plotBackground = legend = tooltip = renderer = tracker = null;
-
-		// remove container and all SVG
-		if (container) { // can break in IE when destroyed before finished loading
-			container.innerHTML = '';
-			removeEvent(container);
-			if (parentNode) {
-				discardElement(container);
-			}
-
-			// IE6 leak
-			container = null;
-		}
-
-		// memory and CPU leak
-		clearInterval(tooltipInterval);
-
-		// clean it all up
-		for (i in chart) {
-			delete chart[i];
-		}
-
-		chart = null;
-	}
-	/**
-	 * Prepare for first rendering after all data are loaded
-	 */
-	function firstRender() {
-
-		// VML namespaces can't be added until after complete. Listening
-		// for Perini's doScroll hack is not enough.
-		var ONREADYSTATECHANGE = 'onreadystatechange',
-			COMPLETE = 'complete';
-		// Note: in spite of JSLint's complaints, win == win.top is required
-		/*jslint eqeq: true*/
-		if (!hasSVG && win == win.top && doc.readyState !== COMPLETE) {
-		/*jslint eqeq: false*/
-			doc.attachEvent(ONREADYSTATECHANGE, function () {
-				doc.detachEvent(ONREADYSTATECHANGE, firstRender);
-				if (doc.readyState === COMPLETE) {
-					firstRender();
-				}
-			});
-			return;
-		}
-
-		// create the container
-		getContainer();
-
-		resetMargins();
-		setChartSize();
-
-		// Initialize the series
-		each(options.series || [], function (serieOptions) {
-			initSeries(serieOptions);
-		});
-
-		// Set the common inversion and transformation for inverted series after initSeries
-		chart.inverted = inverted = pick(inverted, options.chart.inverted);
-
-
-		getAxes();
-
-
-		chart.render = render;
-
-		// depends on inverted and on margins being set
-		chart.tracker = tracker = new MouseTracker(options.tooltip);
-
-		//globalAnimation = false;
-		render();
-
-		fireEvent(chart, 'load');
-
-		//globalAnimation = true;
-
-		// run callbacks
-		if (callback) {
-			callback.apply(chart, [chart]);
-		}
-		each(chart.callbacks, function (fn) {
-			fn.apply(chart, [chart]);
-		});
-	}
-
-	// Run chart
-
-
-	// Destroy the chart and free up memory.
-	addEvent(win, 'unload', destroy);
-
-	// Set up auto resize
-	if (optionsChart.reflow !== false) {
-		addEvent(chart, 'load', initReflow);
-	}
-
-	// Chart event handlers
-	if (chartEvents) {
-		for (eventType in chartEvents) {
-			addEvent(chart, eventType, chartEvents[eventType]);
-		}
-	}
-
-
-	chart.options = options;
-	chart.series = series;
-
-
-
-
-
-	// Expose methods and variables
-	chart.addSeries = addSeries;
-	chart.animation = pick(optionsChart.animation, true);
-	chart.destroy = destroy;
-	chart.get = get;
-	chart.getSelectedPoints = getSelectedPoints;
-	chart.getSelectedSeries = getSelectedSeries;
-	chart.hideLoading = hideLoading;
-	chart.isInsidePlot = isInsidePlot;
-	chart.redraw = redraw;
-	chart.setSize = resize;
-	chart.setTitle = setTitle;
-	chart.showLoading = showLoading;
-	chart.pointCount = 0;
-	chart.counters = new ChartCounters();
-	/*
-	if ($) $(function() {
-		$container = $('#container');
-		var origChartWidth,
-			origChartHeight;
-		if ($container) {
-			$('<button>+</button>')
-				.insertBefore($container)
-				.click(function() {
-					if (origChartWidth === UNDEFINED) {
-						origChartWidth = chartWidth;
-						origChartHeight = chartHeight;
-					}
-					chart.resize(chartWidth *= 1.1, chartHeight *= 1.1);
-				});
-			$('<button>-</button>')
-				.insertBefore($container)
-				.click(function() {
-					if (origChartWidth === UNDEFINED) {
-						origChartWidth = chartWidth;
-						origChartHeight = chartHeight;
-					}
-					chart.resize(chartWidth *= 0.9, chartHeight *= 0.9);
-				});
-			$('<button>1:1</button>')
-				.insertBefore($container)
-				.click(function() {
-					if (origChartWidth === UNDEFINED) {
-						origChartWidth = chartWidth;
-						origChartHeight = chartHeight;
-					}
-					chart.resize(origChartWidth, origChartHeight);
-				});
-		}
-	})
-	*/
-
-
-
-
-	firstRender();
-
-
-} // end Chart
-
-// Hook for exporting module
-Chart.prototype.callbacks = [];
-/**
- * The Point object and prototype. Inheritable and used as base for PiePoint
- */
-var Point = function () {};
-Point.prototype = {
-
-	/**
-	 * Initialize the point
-	 * @param {Object} series The series object containing this point
-	 * @param {Object} options The data in either number, array or object format
-	 */
-	init: function (series, options) {
-		var point = this,
-			counters = series.chart.counters,
-			defaultColors;
-		point.series = series;
-		point.applyOptions(options);
-		point.pointAttr = {};
-
-		if (series.options.colorByPoint) {
-			defaultColors = series.chart.options.colors;
-			if (!point.options) {
-				point.options = {};
-			}
-			point.color = point.options.color = point.color || defaultColors[counters.color++];
-
-			// loop back to zero
-			counters.wrapColor(defaultColors.length);
-		}
-
-		series.chart.pointCount++;
-		return point;
-	},
-	/**
-	 * Apply the options containing the x and y data and possible some extra properties.
-	 * This is called on point init or from point.update.
-	 *
-	 * @param {Object} options
-	 */
-	applyOptions: function (options) {
-		var point = this,
-			series = point.series;
-
-		point.config = options;
-
-		// onedimensional array input
-		if (isNumber(options) || options === null) {
-			point.y = options;
-		} else if (isObject(options) && !isNumber(options.length)) { // object input
-			// copy options directly to point
-			extend(point, options);
-			point.options = options;
-		} else if (isString(options[0])) { // categorized data with name in first position
-			point.name = options[0];
-			point.y = options[1];
-		} else if (isNumber(options[0])) { // two-dimentional array
-			point.x = options[0];
-			point.y = options[1];
-		}
-
-		/*
-		 * If no x is set by now, get auto incremented value. All points must have an
-		 * x value, however the y value can be null to create a gap in the series
-		 */
-		if (point.x === UNDEFINED) {
-			point.x = series.autoIncrement();
-		}
-
-	},
-
-	/**
-	 * Destroy a point to clear memory. Its reference still stays in series.data.
-	 */
-	destroy: function () {
-		var point = this,
-			series = point.series,
-			hoverPoints = series.chart.hoverPoints,
-			prop;
-
-		series.chart.pointCount--;
-
-		if (hoverPoints) {
-			point.setState();
-			erase(hoverPoints, point);
-		}
-		if (point === series.chart.hoverPoint) {
-			point.onMouseOut();
-		}
-
-
-		// remove all events
-		removeEvent(point);
-
-		each(['graphic', 'tracker', 'group', 'dataLabel', 'connector', 'shadowGroup'], function (prop) {
-			if (point[prop]) {
-				point[prop].destroy();
-			}
-		});
-
-		if (point.legendItem) { // pies have legend items
-			point.series.chart.legend.destroyItem(point);
-		}
-
-		for (prop in point) {
-			point[prop] = null;
-		}
-
-
-	},
-
-	/**
-	 * Return the configuration hash needed for the data label and tooltip formatters
-	 */
-	getLabelConfig: function () {
-		var point = this;
-		return {
-			x: point.category,
-			y: point.y,
-			series: point.series,
-			point: point,
-			percentage: point.percentage,
-			total: point.total || point.stackTotal
-		};
-	},
-
-	/**
-	 * Toggle the selection status of a point
-	 * @param {Boolean} selected Whether to select or unselect the point.
-	 * @param {Boolean} accumulate Whether to add to the previous selection. By default,
-	 *     this happens if the control key (Cmd on Mac) was pressed during clicking.
-	 */
-	select: function (selected, accumulate) {
-		var point = this,
-			series = point.series,
-			chart = series.chart;
-
-		selected = pick(selected, !point.selected);
-
-		// fire the event with the defalut handler
-		point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () {
-			point.selected = selected;
-			point.setState(selected && SELECT_STATE);
-
-			// unselect all other points unless Ctrl or Cmd + click
-			if (!accumulate) {
-				each(chart.getSelectedPoints(), function (loopPoint) {
-					if (loopPoint.selected && loopPoint !== point) {
-						loopPoint.selected = false;
-						loopPoint.setState(NORMAL_STATE);
-						loopPoint.firePointEvent('unselect');
-					}
-				});
-			}
-		});
-	},
-
-	onMouseOver: function () {
-		var point = this,
-			chart = point.series.chart,
-			tooltip = chart.tooltip,
-			hoverPoint = chart.hoverPoint;
-
-		// set normal state to previous series
-		if (hoverPoint && hoverPoint !== point) {
-			hoverPoint.onMouseOut();
-		}
-
-		// trigger the event
-		point.firePointEvent('mouseOver');
-
-		// update the tooltip
-		if (tooltip && !tooltip.shared) {
-			tooltip.refresh(point);
-		}
-
-		// hover this
-		point.setState(HOVER_STATE);
-		chart.hoverPoint = point;
-	},
-
-	onMouseOut: function () {
-		var point = this;
-		point.firePointEvent('mouseOut');
-
-		point.setState();
-		point.series.chart.hoverPoint = null;
-	},
-
-	/**
-	 * Extendable method for formatting each point's tooltip line
-	 *
-	 * @param {Boolean} useHeader Whether a common header is used for multiple series in the tooltip
-	 *
-	 * @return {String} A string to be concatenated in to the common tooltip text
-	 */
-	tooltipFormatter: function (useHeader) {
-		var point = this,
-			series = point.series;
-
-		return ['<span style="color:' + series.color + '">', (point.name || series.name), '</span>: ',
-			(!useHeader ? ('<b>x = ' + (point.name || point.x) + ',</b> ') : ''),
-			'<b>', (!useHeader ? 'y = ' : ''), point.y, '</b>'].join('');
-
-	},
-
-	/**
-	 * Update the point with new options (typically x/y data) and optionally redraw the series.
-	 *
-	 * @param {Object} options Point options as defined in the series.data array
-	 * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 *
-	 */
-	update: function (options, redraw, animation) {
-		var point = this,
-			series = point.series,
-			graphic = point.graphic,
-			chart = series.chart;
-
-		redraw = pick(redraw, true);
-
-		// fire the event with a default handler of doing the update
-		point.firePointEvent('update', { options: options }, function () {
-
-			point.applyOptions(options);
-
-			// update visuals
-			if (isObject(options)) {
-				series.getAttribs();
-				if (graphic) {
-					graphic.attr(point.pointAttr[series.state]);
-				}
-			}
-
-			// redraw
-			series.isDirty = true;
-			if (redraw) {
-				chart.redraw(animation);
-			}
-		});
-	},
-
-	/**
-	 * Remove a point and optionally redraw the series and if necessary the axes
-	 * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 */
-	remove: function (redraw, animation) {
-		var point = this,
-			series = point.series,
-			chart = series.chart,
-			data = series.data;
-
-		setAnimation(animation, chart);
-		redraw = pick(redraw, true);
-
-		// fire the event with a default handler of removing the point
-		point.firePointEvent('remove', null, function () {
-
-			erase(data, point);
-
-			point.destroy();
-
-
-			// redraw
-			series.isDirty = true;
-			if (redraw) {
-				chart.redraw();
-			}
-		});
-
-
-	},
-
-	/**
-	 * Fire an event on the Point object. Must not be renamed to fireEvent, as this
-	 * causes a name clash in MooTools
-	 * @param {String} eventType
-	 * @param {Object} eventArgs Additional event arguments
-	 * @param {Function} defaultFunction Default event handler
-	 */
-	firePointEvent: function (eventType, eventArgs, defaultFunction) {
-		var point = this,
-			series = this.series,
-			seriesOptions = series.options;
-
-		// load event handlers on demand to save time on mouseover/out
-		if (seriesOptions.point.events[eventType] ||
-			(point.options && point.options.events && point.options.events[eventType])) {
-			this.importEvents();
-		}
-
-		// add default handler if in selection mode
-		if (eventType === 'click' && seriesOptions.allowPointSelect) {
-			defaultFunction = function (event) {
-				// Control key is for Windows, meta (= Cmd key) for Mac, Shift for Opera
-				point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
-			};
-		}
-
-		fireEvent(this, eventType, eventArgs, defaultFunction);
-	},
-	/**
-	 * Import events from the series' and point's options. Only do it on
-	 * demand, to save processing time on hovering.
-	 */
-	importEvents: function () {
-		if (!this.hasImportedEvents) {
-			var point = this,
-				options = merge(point.series.options.point, point.options),
-				events = options.events,
-				eventType;
-
-			point.events = events;
-
-			for (eventType in events) {
-				addEvent(point, eventType, events[eventType]);
-			}
-			this.hasImportedEvents = true;
-
-		}
-	},
-
-	/**
-	 * Set the point's state
-	 * @param {String} state
-	 */
-	setState: function (state) {
-		var point = this,
-			series = point.series,
-			stateOptions = series.options.states,
-			markerOptions = defaultPlotOptions[series.type].marker && series.options.marker,
-			normalDisabled = markerOptions && !markerOptions.enabled,
-			markerStateOptions = markerOptions && markerOptions.states[state],
-			stateDisabled = markerStateOptions && markerStateOptions.enabled === false,
-			stateMarkerGraphic = series.stateMarkerGraphic,
-			chart = series.chart,
-			pointAttr = point.pointAttr;
-
-		state = state || NORMAL_STATE; // empty string
-
-		if (
-				// already has this state
-				state === point.state ||
-				// selected points don't respond to hover
-				(point.selected && state !== SELECT_STATE) ||
-				// series' state options is disabled
-				(stateOptions[state] && stateOptions[state].enabled === false) ||
-				// point marker's state options is disabled
-				(state && (stateDisabled || (normalDisabled && !markerStateOptions.enabled)))
-
-			) {
-			return;
-		}
-
-		// apply hover styles to the existing point
-		if (point.graphic) {
-			point.graphic.attr(pointAttr[state]);
-		} else {
-			// if a graphic is not applied to each point in the normal state, create a shared
-			// graphic for the hover state
-			if (state) {
-				if (!stateMarkerGraphic) {
-					series.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.circle(
-						0,
-						0,
-						pointAttr[state].r
-					)
-					.attr(pointAttr[state])
-					.add(series.group);
-				}
-
-				stateMarkerGraphic.translate(
-					point.plotX,
-					point.plotY
-				);
-			}
-
-			if (stateMarkerGraphic) {
-				stateMarkerGraphic[state ? 'show' : 'hide']();
-			}
-		}
-
-		point.state = state;
-	}
-};
-
-/**
- * The base function which all other series types inherit from
- * @param {Object} chart
- * @param {Object} options
- */
-var Series = function () {};
-
-Series.prototype = {
-
-	isCartesian: true,
-	type: 'line',
-	pointClass: Point,
-	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
-		stroke: 'lineColor',
-		'stroke-width': 'lineWidth',
-		fill: 'fillColor',
-		r: 'radius'
-	},
-	init: function (chart, options) {
-		var series = this,
-			eventType,
-			events,
-			//pointEvent,
-			index = chart.series.length;
-
-		series.chart = chart;
-		options = series.setOptions(options); // merge with plotOptions
-
-		// set some variables
-		extend(series, {
-			index: index,
-			options: options,
-			name: options.name || 'Series ' + (index + 1),
-			state: NORMAL_STATE,
-			pointAttr: {},
-			visible: options.visible !== false, // true by default
-			selected: options.selected === true // false by default
-		});
-
-		// register event listeners
-		events = options.events;
-		for (eventType in events) {
-			addEvent(series, eventType, events[eventType]);
-		}
-		if (
-			(events && events.click) ||
-			(options.point && options.point.events && options.point.events.click) ||
-			options.allowPointSelect
-		) {
-			chart.runTrackerClick = true;
-		}
-
-		series.getColor();
-		series.getSymbol();
-
-
-		// set the data
-		series.setData(options.data, false);
-
-	},
-
-
-	/**
-	 * Return an auto incremented x value based on the pointStart and pointInterval options.
-	 * This is only used if an x value is not given for the point that calls autoIncrement.
-	 */
-	autoIncrement: function () {
-		var series = this,
-			options = series.options,
-			xIncrement = series.xIncrement;
-
-		xIncrement = pick(xIncrement, options.pointStart, 0);
-
-		series.pointInterval = pick(series.pointInterval, options.pointInterval, 1);
-
-		series.xIncrement = xIncrement + series.pointInterval;
-		return xIncrement;
-	},
-
-	/**
-	 * Sort the data and remove duplicates
-	 */
-	cleanData: function () {
-		var series = this,
-			chart = series.chart,
-			data = series.data,
-			closestPoints,
-			smallestInterval,
-			chartSmallestInterval = chart.smallestInterval,
-			interval,
-			i;
-
-		// sort the data points
-		stableSort(data, function (a, b) {
-			return (a.x - b.x);
-		});
-
-		// remove points with equal x values
-		// record the closest distance for calculation of column widths
-		/*for (i = data.length - 1; i >= 0; i--) {
-			if (data[i - 1]) {
-				if (data[i - 1].x == data[i].x)	{
-					data[i - 1].destroy();
-					data.splice(i - 1, 1); // remove the duplicate
-				}
-			}
-		}*/
-
-		// connect nulls
-		if (series.options.connectNulls) {
-			for (i = data.length - 1; i >= 0; i--) {
-				if (data[i].y === null && data[i - 1] && data[i + 1]) {
-					data.splice(i, 1);
-				}
-			}
-		}
-
-		// find the closes pair of points
-		for (i = data.length - 1; i >= 0; i--) {
-			if (data[i - 1]) {
-				interval = data[i].x - data[i - 1].x;
-				if (interval > 0 && (smallestInterval === UNDEFINED || interval < smallestInterval)) {
-					smallestInterval = interval;
-					closestPoints = i;
-				}
-			}
-		}
-
-		if (chartSmallestInterval === UNDEFINED || smallestInterval < chartSmallestInterval) {
-			chart.smallestInterval = smallestInterval;
-		}
-		series.closestPoints = closestPoints;
-	},
-
-	/**
-	 * Divide the series data into segments divided by null values. Also sort
-	 * the data points and delete duplicate values.
-	 */
-	getSegments: function () {
-		var lastNull = -1,
-			segments = [],
-			data = this.data;
-
-		// create the segments
-		each(data, function (point, i) {
-			if (point.y === null) {
-				if (i > lastNull + 1) {
-					segments.push(data.slice(lastNull + 1, i));
-				}
-				lastNull = i;
-			} else if (i === data.length - 1) { // last value
-				segments.push(data.slice(lastNull + 1, i + 1));
-			}
-		});
-		this.segments = segments;
-
-
-	},
-	/**
-	 * Set the series options by merging from the options tree
-	 * @param {Object} itemOptions
-	 */
-	setOptions: function (itemOptions) {
-		var plotOptions = this.chart.options.plotOptions,
-			options = merge(
-				plotOptions[this.type],
-				plotOptions.series,
-				itemOptions
-			);
-
-		return options;
-
-	},
-	/**
-	 * Get the series' color
-	 */
-	getColor: function () {
-		var defaultColors = this.chart.options.colors,
-			counters = this.chart.counters;
-		this.color = this.options.color || defaultColors[counters.color++] || '#0000ff';
-		counters.wrapColor(defaultColors.length);
-	},
-	/**
-	 * Get the series' symbol
-	 */
-	getSymbol: function () {
-		var defaultSymbols = this.chart.options.symbols,
-			counters = this.chart.counters;
-		this.symbol = this.options.marker.symbol || defaultSymbols[counters.symbol++];
-		counters.wrapSymbol(defaultSymbols.length);
-	},
-
-	/**
-	 * Add a point dynamically after chart load time
-	 * @param {Object} options Point options as given in series.data
-	 * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
-	 * @param {Boolean} shift If shift is true, a point is shifted off the start
-	 *    of the series as one is appended to the end.
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 */
-	addPoint: function (options, redraw, shift, animation) {
-		var series = this,
-			data = series.data,
-			graph = series.graph,
-			area = series.area,
-			chart = series.chart,
-			point = (new series.pointClass()).init(series, options);
-
-		setAnimation(animation, chart);
-
-		if (graph && shift) { // make graph animate sideways
-			graph.shift = shift;
-		}
-		if (area) {
-			area.shift = shift;
-			area.isArea = true;
-		}
-
-		redraw = pick(redraw, true);
-
-		data.push(point);
-		if (shift) {
-			data[0].remove(false);
-		}
-		series.getAttribs();
-
-
-		// redraw
-		series.isDirty = true;
-		if (redraw) {
-			chart.redraw();
-		}
-	},
-
-	/**
-	 * Replace the series data with a new set of data
-	 * @param {Object} data
-	 * @param {Object} redraw
-	 */
-	setData: function (data, redraw) {
-		var series = this,
-			oldData = series.data,
-			initialColor = series.initialColor,
-			chart = series.chart,
-			i = (oldData && oldData.length) || 0;
-
-		series.xIncrement = null; // reset for new data
-		if (defined(initialColor)) { // reset colors for pie
-			chart.counters.color = initialColor;
-		}
-
-		data = map(splat(data || []), function (pointOptions) {
-			return (new series.pointClass()).init(series, pointOptions);
-		});
-
-		// destroy old points
-		while (i--) {
-			oldData[i].destroy();
-		}
-
-		// set the data
-		series.data = data;
-
-		series.cleanData();
-		series.getSegments();
-
-
-		// cache attributes for shapes
-		series.getAttribs();
-
-		// redraw
-		series.isDirty = true;
-		chart.isDirtyBox = true;
-		if (pick(redraw, true)) {
-			chart.redraw(false);
-		}
-	},
-
-	/**
-	 * Remove a series and optionally redraw the chart
-	 *
-	 * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call
-	 * @param {Boolean|Object} animation Whether to apply animation, and optionally animation
-	 *    configuration
-	 */
-
-	remove: function (redraw, animation) {
-		var series = this,
-			chart = series.chart;
-		redraw = pick(redraw, true);
-
-		if (!series.isRemoving) {  /* prevent triggering native event in jQuery
-				(calling the remove function from the remove event) */
-			series.isRemoving = true;
-
-			// fire the event with a default handler of removing the point
-			fireEvent(series, 'remove', null, function () {
-
-
-				// destroy elements
-				series.destroy();
-
-
-				// redraw
-				chart.isDirtyLegend = chart.isDirtyBox = true;
-				if (redraw) {
-					chart.redraw(animation);
-				}
-			});
-
-		}
-		series.isRemoving = false;
-	},
-
-	/**
-	 * Translate data points from raw data values to chart specific positioning data
-	 * needed later in drawPoints, drawGraph and drawTracker.
-	 */
-	translate: function () {
-		var series = this,
-			chart = series.chart,
-			stacking = series.options.stacking,
-			categories = series.xAxis.categories,
-			yAxis = series.yAxis,
-			data = series.data,
-			i = data.length;
-
-		// do the translation
-		while (i--) {
-			var point = data[i],
-				xValue = point.x,
-				yValue = point.y,
-				yBottom = point.low,
-				stack = yAxis.stacks[(yValue < 0 ? '-' : '') + series.stackKey],
-				pointStack,
-				pointStackTotal;
-			point.plotX = series.xAxis.translate(xValue);
-
-			// calculate the bottom y value for stacked series
-			if (stacking && series.visible && stack && stack[xValue]) {
-				pointStack = stack[xValue];
-				pointStackTotal = pointStack.total;
-				pointStack.cum = yBottom = pointStack.cum - yValue; // start from top
-				yValue = yBottom + yValue;
-
-				if (stacking === 'percent') {
-					yBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0;
-					yValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0;
-				}
-
-				point.percentage = pointStackTotal ? point.y * 100 / pointStackTotal : 0;
-				point.stackTotal = pointStackTotal;
-			}
-
-			if (defined(yBottom)) {
-				point.yBottom = yAxis.translate(yBottom, 0, 1, 0, 1);
-			}
-
-			// set the y value
-			if (yValue !== null) {
-				point.plotY = yAxis.translate(yValue, 0, 1, 0, 1);
-			}
-
-			// set client related positions for mouse tracking
-			point.clientX = chart.inverted ?
-				chart.plotHeight - point.plotX :
-				point.plotX; // for mouse tracking
-
-			// some API data
-			point.category = categories && categories[point.x] !== UNDEFINED ?
-				categories[point.x] : point.x;
-
-		}
-	},
-	/**
-	 * Memoize tooltip texts and positions
-	 */
-	setTooltipPoints: function (renew) {
-		var series = this,
-			chart = series.chart,
-			inverted = chart.inverted,
-			data = [],
-			plotSize = mathRound((inverted ? chart.plotTop : chart.plotLeft) + chart.plotSizeX),
-			low,
-			high,
-			tooltipPoints = []; // a lookup array for each pixel in the x dimension
-
-		// renew
-		if (renew) {
-			series.tooltipPoints = null;
-		}
-
-		// concat segments to overcome null values
-		each(series.segments, function (segment) {
-			data = data.concat(segment);
-		});
-
-		// loop the concatenated data and apply each point to all the closest
-		// pixel positions
-		if (series.xAxis && series.xAxis.reversed) {
-			data = data.reverse();//reverseArray(data);
-		}
-
-		each(data, function (point, i) {
-
-			low = data[i - 1] ? data[i - 1]._high + 1 : 0;
-			high = point._high = data[i + 1] ?
-				(mathFloor((point.plotX + (data[i + 1] ? data[i + 1].plotX : plotSize)) / 2)) :
-				plotSize;
-
-			while (low <= high) {
-				tooltipPoints[inverted ? plotSize - low++ : low++] = point;
-			}
-		});
-		series.tooltipPoints = tooltipPoints;
-	},
-
-
-
-
-	/**
-	 * Series mouse over handler
-	 */
-	onMouseOver: function () {
-		var series = this,
-			chart = series.chart,
-			hoverSeries = chart.hoverSeries;
-
-		if (!hasTouch && chart.mouseIsDown) {
-			return;
-		}
-
-		// set normal state to previous series
-		if (hoverSeries && hoverSeries !== series) {
-			hoverSeries.onMouseOut();
-		}
-
-		// trigger the event, but to save processing time,
-		// only if defined
-		if (series.options.events.mouseOver) {
-			fireEvent(series, 'mouseOver');
-		}
-
-
-		// bring to front
-		// Todo: optimize. This is one of two operations slowing down the tooltip in Firefox.
-		// Can the tracking be done otherwise?
-		if (series.tracker) {
-			series.tracker.toFront();
-		}
-
-		// hover this
-		series.setState(HOVER_STATE);
-		chart.hoverSeries = series;
-	},
-
-	/**
-	 * Series mouse out handler
-	 */
-	onMouseOut: function () {
-		// trigger the event only if listeners exist
-		var series = this,
-			options = series.options,
-			chart = series.chart,
-			tooltip = chart.tooltip,
-			hoverPoint = chart.hoverPoint;
-
-		// trigger mouse out on the point, which must be in this series
-		if (hoverPoint) {
-			hoverPoint.onMouseOut();
-		}
-
-		// fire the mouse out event
-		if (series && options.events.mouseOut) {
-			fireEvent(series, 'mouseOut');
-		}
-
-
-		// hide the tooltip
-		if (tooltip && !options.stickyTracking) {
-			tooltip.hide();
-		}
-
-		// set normal state
-		series.setState();
-		chart.hoverSeries = null;
-	},
-
-	/**
-	 * Animate in the series
-	 */
-	animate: function (init) {
-		var series = this,
-			chart = series.chart,
-			clipRect = series.clipRect,
-			animation = series.options.animation;
-
-		if (animation && !isObject(animation)) {
-			animation = {};
-		}
-
-		if (init) { // initialize the animation
-			if (!clipRect.isAnimating) { // apply it only for one of the series
-				clipRect.attr('width', 0);
-				clipRect.isAnimating = true;
-			}
-
-		} else { // run the animation
-			clipRect.animate({
-				width: chart.plotSizeX
-			}, animation);
-
-			// delete this function to allow it only once
-			this.animate = null;
-		}
-	},
-
-
-	/**
-	 * Draw the markers
-	 */
-	drawPoints: function () {
-		var series = this,
-			pointAttr,
-			data = series.data,
-			chart = series.chart,
-			plotX,
-			plotY,
-			i,
-			point,
-			radius,
-			graphic;
-
-		if (series.options.marker.enabled) {
-			i = data.length;
-			while (i--) {
-				point = data[i];
-				plotX = point.plotX;
-				plotY = point.plotY;
-				graphic = point.graphic;
-
-				// only draw the point if y is defined
-				if (plotY !== UNDEFINED && !isNaN(plotY)) {
-
-					/* && removed this code because points stayed after zoom
-						point.plotX >= 0 && point.plotX <= chart.plotSizeX &&
-						point.plotY >= 0 && point.plotY <= chart.plotSizeY*/
-
-					// shortcuts
-					pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE];
-					radius = pointAttr.r;
-
-					if (graphic) { // update
-						graphic.animate({
-							x: plotX,
-							y: plotY,
-							r: radius
-						});
-					} else {
-						point.graphic = chart.renderer.symbol(
-							pick(point.marker && point.marker.symbol, series.symbol),
-							plotX,
-							plotY,
-							radius
-						)
-						.attr(pointAttr)
-						.add(series.group);
-					}
-				}
-			}
-		}
-
-	},
-
-	/**
-	 * Convert state properties from API naming conventions to SVG attributes
-	 *
-	 * @param {Object} options API options object
-	 * @param {Object} base1 SVG attribute object to inherit from
-	 * @param {Object} base2 Second level SVG attribute object to inherit from
-	 */
-	convertAttribs: function (options, base1, base2, base3) {
-		var conversion = this.pointAttrToOptions,
-			attr,
-			option,
-			obj = {};
-
-		options = options || {};
-		base1 = base1 || {};
-		base2 = base2 || {};
-		base3 = base3 || {};
-
-		for (attr in conversion) {
-			option = conversion[attr];
-			obj[attr] = pick(options[option], base1[attr], base2[attr], base3[attr]);
-		}
-		return obj;
-	},
-
-	/**
-	 * Get the state attributes. Each series type has its own set of attributes
-	 * that are allowed to change on a point's state change. Series wide attributes are stored for
-	 * all series, and additionally point specific attributes are stored for all
-	 * points with individual marker options. If such options are not defined for the point,
-	 * a reference to the series wide attributes is stored in point.pointAttr.
-	 */
-	getAttribs: function () {
-		var series = this,
-			normalOptions = defaultPlotOptions[series.type].marker ? series.options.marker : series.options,
-			stateOptions = normalOptions.states,
-			stateOptionsHover = stateOptions[HOVER_STATE],
-			pointStateOptionsHover,
-			seriesColor = series.color,
-			normalDefaults = {
-				stroke: seriesColor,
-				fill: seriesColor
-			},
-			data = series.data,
-			i,
-			point,
-			seriesPointAttr = [],
-			pointAttr,
-			pointAttrToOptions = series.pointAttrToOptions,
-			hasPointSpecificOptions,
-			key;
-
-		// series type specific modifications
-		if (series.options.marker) { // line, spline, area, areaspline, scatter
-
-			// if no hover radius is given, default to normal radius + 2
-			stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + 2;
-			stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + 1;
-
-		} else { // column, bar, pie
-
-			// if no hover color is given, brighten the normal color
-			stateOptionsHover.color = stateOptionsHover.color ||
-				Color(stateOptionsHover.color || seriesColor)
-					.brighten(stateOptionsHover.brightness).get();
-		}
-
-		// general point attributes for the series normal state
-		seriesPointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, normalDefaults);
-
-		// HOVER_STATE and SELECT_STATE states inherit from normal state except the default radius
-		each([HOVER_STATE, SELECT_STATE], function (state) {
-			seriesPointAttr[state] =
-					series.convertAttribs(stateOptions[state], seriesPointAttr[NORMAL_STATE]);
-		});
-
-		// set it
-		series.pointAttr = seriesPointAttr;
-
-
-		// Generate the point-specific attribute collections if specific point
-		// options are given. If not, create a referance to the series wide point
-		// attributes
-		i = data.length;
-		while (i--) {
-			point = data[i];
-			normalOptions = (point.options && point.options.marker) || point.options;
-			if (normalOptions && normalOptions.enabled === false) {
-				normalOptions.radius = 0;
-			}
-			hasPointSpecificOptions = false;
-
-			// check if the point has specific visual options
-			if (point.options) {
-				for (key in pointAttrToOptions) {
-					if (defined(normalOptions[pointAttrToOptions[key]])) {
-						hasPointSpecificOptions = true;
-					}
-				}
-			}
-
-
-
-			// a specific marker config object is defined for the individual point:
-			// create it's own attribute collection
-			if (hasPointSpecificOptions) {
-
-				pointAttr = [];
-				stateOptions = normalOptions.states || {}; // reassign for individual point
-				pointStateOptionsHover = stateOptions[HOVER_STATE] = stateOptions[HOVER_STATE] || {};
-
-				// if no hover color is given, brighten the normal color
-				if (!series.options.marker) { // column, bar, point
-					pointStateOptionsHover.color =
-						Color(pointStateOptionsHover.color || point.options.color)
-							.brighten(pointStateOptionsHover.brightness ||
-								stateOptionsHover.brightness).get();
-
-				}
-
-				// normal point state inherits series wide normal state
-				pointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, seriesPointAttr[NORMAL_STATE]);
-
-				// inherit from point normal and series hover
-				pointAttr[HOVER_STATE] = series.convertAttribs(
-					stateOptions[HOVER_STATE],
-					seriesPointAttr[HOVER_STATE],
-					pointAttr[NORMAL_STATE]
-				);
-				// inherit from point normal and series hover
-				pointAttr[SELECT_STATE] = series.convertAttribs(
-					stateOptions[SELECT_STATE],
-					seriesPointAttr[SELECT_STATE],
-					pointAttr[NORMAL_STATE]
-				);
-
-
-
-			// no marker config object is created: copy a reference to the series-wide
-			// attribute collection
-			} else {
-				pointAttr = seriesPointAttr;
-			}
-
-			point.pointAttr = pointAttr;
-
-		}
-
-	},
-
-
-	/**
-	 * Clear DOM objects and free up memory
-	 */
-	destroy: function () {
-		var series = this,
-			chart = series.chart,
-			seriesClipRect = series.clipRect,
-			//chartSeries = series.chart.series,
-			issue134 = /\/5[0-9\.]+ (Safari|Mobile)\//.test(userAgent), // todo: update when Safari bug is fixed
-			destroy,
-			prop;
-
-		// add event hook
-		fireEvent(series, 'destroy');
-
-		// remove all events
-		removeEvent(series);
-
-		// remove legend items
-		if (series.legendItem) {
-			series.chart.legend.destroyItem(series);
-		}
-
-		// destroy all points with their elements
-		each(series.data, function (point) {
-			point.destroy();
-		});
-
-		// If this series clipRect is not the global one (which is removed on chart.destroy) we
-		// destroy it here.
-		if (seriesClipRect && seriesClipRect !== chart.clipRect) {
-			series.clipRect = seriesClipRect.destroy();
-		}
-
-		// destroy all SVGElements associated to the series
-		each(['area', 'graph', 'dataLabelsGroup', 'group', 'tracker'], function (prop) {
-			if (series[prop]) {
-
-				// issue 134 workaround
-				destroy = issue134 && prop === 'group' ?
-					'hide' :
-					'destroy';
-
-				series[prop][destroy]();
-			}
-		});
-
-		// remove from hoverSeries
-		if (chart.hoverSeries === series) {
-			chart.hoverSeries = null;
-		}
-		erase(chart.series, series);
-
-		// clear all members
-		for (prop in series) {
-			delete series[prop];
-		}
-	},
-
-	/**
-	 * Draw the data labels
-	 */
-	drawDataLabels: function () {
-		if (this.options.dataLabels.enabled) {
-			var series = this,
-				x,
-				y,
-				data = series.data,
-				seriesOptions = series.options,
-				options = seriesOptions.dataLabels,
-				str,
-				dataLabelsGroup = series.dataLabelsGroup,
-				chart = series.chart,
-				renderer = chart.renderer,
-				inverted = chart.inverted,
-				seriesType = series.type,
-				color,
-				stacking = seriesOptions.stacking,
-				isBarLike = seriesType === 'column' || seriesType === 'bar',
-				vAlignIsNull = options.verticalAlign === null,
-				yIsNull = options.y === null;
-
-			if (isBarLike) {
-				if (stacking) {
-					// In stacked series the default label placement is inside the bars
-					if (vAlignIsNull) {
-						options = merge(options, {verticalAlign: 'middle'});
-					}
-
-					// If no y delta is specified, try to create a good default
-					if (yIsNull) {
-						options = merge(options, {y: {top: 14, middle: 4, bottom: -6}[options.verticalAlign]});
-					}
-				} else {
-					// In non stacked series the default label placement is on top of the bars
-					if (vAlignIsNull) {
-						options = merge(options, {verticalAlign: 'top'});
-					}
-				}
-			}
-
-			// create a separate group for the data labels to avoid rotation
-			if (!dataLabelsGroup) {
-				dataLabelsGroup = series.dataLabelsGroup =
-					renderer.g('data-labels')
-						.attr({
-							visibility: series.visible ? VISIBLE : HIDDEN,
-							zIndex: 6
-						})
-						.translate(chart.plotLeft, chart.plotTop)
-						.add();
-			} else {
-				dataLabelsGroup.translate(chart.plotLeft, chart.plotTop);
-			}
-
-			// determine the color
-			color = options.color;
-			if (color === 'auto') { // 1.0 backwards compatibility
-				color = null;
-			}
-			options.style.color = pick(color, series.color, 'black');
-
-			// make the labels for each point
-			each(data, function (point) {
-				var barX = point.barX,
-					plotX = (barX && barX + point.barW / 2) || point.plotX || -999,
-					plotY = pick(point.plotY, -999),
-					dataLabel = point.dataLabel,
-					align = options.align,
-					individualYDelta = yIsNull ? (point.y >= 0 ? -6 : 12) : options.y;
-
-				// get the string
-				str = options.formatter.call(point.getLabelConfig());
-				x = (inverted ? chart.plotWidth - plotY : plotX) + options.x;
-				y = (inverted ? chart.plotHeight - plotX : plotY) + individualYDelta;
-
-				// in columns, align the string to the column
-				if (seriesType === 'column') {
-					x += { left: -1, right: 1 }[align] * point.barW / 2 || 0;
-				}
-
-				if (inverted && point.y < 0) {
-					align = 'right';
-					x -= 10;
-				}
-
-				// update existing label
-				if (dataLabel) {
-					// vertically centered
-					if (inverted && !options.y) {
-						y = y + pInt(dataLabel.styles.lineHeight) * 0.9 - dataLabel.getBBox().height / 2;
-					}
-					dataLabel
-						.attr({
-							text: str
-						}).animate({
-							x: x,
-							y: y
-						});
-				// create new label
-				} else if (defined(str)) {
-					dataLabel = point.dataLabel = renderer.text(
-						str,
-						x,
-						y
-					)
-					.attr({
-						align: align,
-						rotation: options.rotation,
-						zIndex: 1
-					})
-					.css(options.style)
-					.add(dataLabelsGroup);
-					// vertically centered
-					if (inverted && !options.y) {
-						dataLabel.attr({
-							y: y + pInt(dataLabel.styles.lineHeight) * 0.9 - dataLabel.getBBox().height / 2
-						});
-					}
-				}
-
-
-				/*if (series.isCartesian) {
-					dataLabel[chart.isInsidePlot(plotX, plotY) ? 'show' : 'hide']();
-				}*/
-
-				if (isBarLike && seriesOptions.stacking && dataLabel) {
-					var barY = point.barY,
-						barW = point.barW,
-						barH = point.barH;
-
-					dataLabel.align(options, null,
-						{
-							x: inverted ? chart.plotWidth - barY - barH : barX,
-							y: inverted ? chart.plotHeight - barX - barW : barY,
-							width: inverted ? barH : barW,
-							height: inverted ? barW : barH
-						});
-				}
-			});
-		}
-	},
-
-	/**
-	 * Draw the actual graph
-	 */
-	drawGraph: function () {
-		var series = this,
-			options = series.options,
-			chart = series.chart,
-			graph = series.graph,
-			graphPath = [],
-			fillColor,
-			area = series.area,
-			group = series.group,
-			color = options.lineColor || series.color,
-			lineWidth = options.lineWidth,
-			dashStyle =  options.dashStyle,
-			segmentPath,
-			renderer = chart.renderer,
-			translatedThreshold = series.yAxis.getThreshold(options.threshold || 0),
-			useArea = /^area/.test(series.type),
-			singlePoints = [], // used in drawTracker
-			areaPath = [],
-			attribs;
-
-
-		// divide into segments and build graph and area paths
-		each(series.segments, function (segment) {
-			segmentPath = [];
-
-			// build the segment line
-			each(segment, function (point, i) {
-
-				if (series.getPointSpline) { // generate the spline as defined in the SplineSeries object
-					segmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i));
-
-				} else {
-
-					// moveTo or lineTo
-					segmentPath.push(i ? L : M);
-
-					// step line?
-					if (i && options.step) {
-						var lastPoint = segment[i - 1];
-						segmentPath.push(
-							point.plotX,
-							lastPoint.plotY
-						);
-					}
-
-					// normal line to next point
-					segmentPath.push(
-						point.plotX,
-						point.plotY
-					);
-				}
-			});
-
-			// add the segment to the graph, or a single point for tracking
-			if (segment.length > 1) {
-				graphPath = graphPath.concat(segmentPath);
-			} else {
-				singlePoints.push(segment[0]);
-			}
-
-			// build the area
-			if (useArea) {
-				var areaSegmentPath = [],
-					i,
-					segLength = segmentPath.length;
-				for (i = 0; i < segLength; i++) {
-					areaSegmentPath.push(segmentPath[i]);
-				}
-				if (segLength === 3) { // for animation from 1 to two points
-					areaSegmentPath.push(L, segmentPath[1], segmentPath[2]);
-				}
-				if (options.stacking && series.type !== 'areaspline') {
-					// follow stack back. Todo: implement areaspline
-					for (i = segment.length - 1; i >= 0; i--) {
-						areaSegmentPath.push(segment[i].plotX, segment[i].yBottom);
-					}
-
-				} else { // follow zero line back
-					areaSegmentPath.push(
-						L,
-						segment[segment.length - 1].plotX,
-						translatedThreshold,
-						L,
-						segment[0].plotX,
-						translatedThreshold
-					);
-				}
-				areaPath = areaPath.concat(areaSegmentPath);
-			}
-		});
-
-		// used in drawTracker:
-		series.graphPath = graphPath;
-		series.singlePoints = singlePoints;
-
-		// draw the area if area series or areaspline
-		if (useArea) {
-			fillColor = pick(
-				options.fillColor,
-				Color(series.color).setOpacity(options.fillOpacity || 0.75).get()
-			);
-			if (area) {
-				area.animate({ d: areaPath });
-
-			} else {
-				// draw the area
-				series.area = series.chart.renderer.path(areaPath)
-					.attr({
-						fill: fillColor
-					}).add(group);
-			}
-		}
-
-		// draw the graph
-		if (graph) {
-			stop(graph); // cancel running animations, #459
-			graph.animate({ d: graphPath });
-
-		} else {
-			if (lineWidth) {
-				attribs = {
-					'stroke': color,
-					'stroke-width': lineWidth
-				};
-				if (dashStyle) {
-					attribs.dashstyle = dashStyle;
-				}
-
-				series.graph = renderer.path(graphPath)
-					.attr(attribs).add(group).shadow(options.shadow);
-			}
-		}
-	},
-
-
-	/**
-	 * Render the graph and markers
-	 */
-	render: function () {
-		var series = this,
-			chart = series.chart,
-			group,
-			setInvert,
-			options = series.options,
-			animation = options.animation,
-			doAnimation = animation && series.animate,
-			duration = doAnimation ? (animation && animation.duration) || 500 : 0,
-			clipRect = series.clipRect,
-			renderer = chart.renderer;
-
-
-		// Add plot area clipping rectangle. If this is before chart.hasRendered,
-		// create one shared clipRect.
-		if (!clipRect) {
-			clipRect = series.clipRect = !chart.hasRendered && chart.clipRect ?
-				chart.clipRect :
-				renderer.clipRect(0, 0, chart.plotSizeX, chart.plotSizeY);
-			if (!chart.clipRect) {
-				chart.clipRect = clipRect;
-			}
-		}
-
-
-		// the group
-		if (!series.group) {
-			group = series.group = renderer.g('series');
-
-			if (chart.inverted) {
-				setInvert = function () {
-					group.attr({
-						width: chart.plotWidth,
-						height: chart.plotHeight
-					}).invert();
-				};
-
-				setInvert(); // do it now
-				addEvent(chart, 'resize', setInvert); // do it on resize
-				addEvent(series, 'destroy', function () {
-					removeEvent(chart, 'resize', setInvert);
-				});
-			}
-			group.clip(series.clipRect)
-				.attr({
-					visibility: series.visible ? VISIBLE : HIDDEN,
-					zIndex: options.zIndex
-				})
-				.translate(chart.plotLeft, chart.plotTop)
-				.add(chart.seriesGroup);
-		}
-
-		series.drawDataLabels();
-
-		// initiate the animation
-		if (doAnimation) {
-			series.animate(true);
-		}
-
-		// cache attributes for shapes
-		//series.getAttribs();
-
-		// draw the graph if any
-		if (series.drawGraph) {
-			series.drawGraph();
-		}
-
-		// draw the points
-		series.drawPoints();
-
-		// draw the mouse tracking area
-		if (series.options.enableMouseTracking !== false) {
-			series.drawTracker();
-		}
-
-		// run the animation
-		if (doAnimation) {
-			series.animate();
-		}
-
-		// finish the individual clipRect
-		setTimeout(function () {
-			clipRect.isAnimating = false;
-			group = series.group; // can be destroyed during the timeout
-			if (group && clipRect !== chart.clipRect && clipRect.renderer) {
-				group.clip((series.clipRect = chart.clipRect));
-				clipRect.destroy();
-			}
-		}, duration);
-
-
-		series.isDirty = false; // means data is in accordance with what you see
-
-	},
-
-	/**
-	 * Redraw the series after an update in the axes.
-	 */
-	redraw: function () {
-		var series = this,
-			chart = series.chart,
-			group = series.group;
-
-		/*if (clipRect) {
-			stop(clipRect);
-			clipRect.animate({ // for chart resize
-				width: chart.plotSizeX,
-				height: chart.plotSizeY
-			});
-		}*/
-
-		// reposition on resize
-		if (group) {
-			if (chart.inverted) {
-				group.attr({
-					width: chart.plotWidth,
-					height: chart.plotHeight
-				});
-			}
-
-			group.animate({
-				translateX: chart.plotLeft,
-				translateY: chart.plotTop
-			});
-		}
-
-		series.translate();
-		series.setTooltipPoints(true);
-		series.render();
-	},
-
-	/**
-	 * Set the state of the graph
-	 */
-	setState: function (state) {
-		var series = this,
-			options = series.options,
-			graph = series.graph,
-			stateOptions = options.states,
-			lineWidth = options.lineWidth;
-
-		state = state || NORMAL_STATE;
-
-		if (series.state !== state) {
-			series.state = state;
-
-			if (stateOptions[state] && stateOptions[state].enabled === false) {
-				return;
-			}
-
-			if (state) {
-				lineWidth = stateOptions[state].lineWidth || lineWidth + 1;
-			}
-
-			if (graph && !graph.dashstyle) { // hover is turned off for dashed lines in VML
-				graph.attr({ // use attr because animate will cause any other animation on the graph to stop
-					'stroke-width': lineWidth
-				}, state ? 0 : 500);
-			}
-		}
-	},
-
-	/**
-	 * Set the visibility of the graph
-	 *
-	 * @param vis {Boolean} True to show the series, false to hide. If UNDEFINED,
-	 *        the visibility is toggled.
-	 */
-	setVisible: function (vis, redraw) {
-		var series = this,
-			chart = series.chart,
-			legendItem = series.legendItem,
-			seriesGroup = series.group,
-			seriesTracker = series.tracker,
-			dataLabelsGroup = series.dataLabelsGroup,
-			showOrHide,
-			i,
-			data = series.data,
-			point,
-			ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,
-			oldVisibility = series.visible;
-
-		// if called without an argument, toggle visibility
-		series.visible = vis = vis === UNDEFINED ? !oldVisibility : vis;
-		showOrHide = vis ? 'show' : 'hide';
-
-		// show or hide series
-		if (seriesGroup) { // pies don't have one
-			seriesGroup[showOrHide]();
-		}
-
-		// show or hide trackers
-		if (seriesTracker) {
-			seriesTracker[showOrHide]();
-		} else {
-			i = data.length;
-			while (i--) {
-				point = data[i];
-				if (point.tracker) {
-					point.tracker[showOrHide]();
-				}
-			}
-		}
-
-
-		if (dataLabelsGroup) {
-			dataLabelsGroup[showOrHide]();
-		}
-
-		if (legendItem) {
-			chart.legend.colorizeItem(series, vis);
-		}
-
-
-		// rescale or adapt to resized chart
-		series.isDirty = true;
-		// in a stack, all other series are affected
-		if (series.options.stacking) {
-			each(chart.series, function (otherSeries) {
-				if (otherSeries.options.stacking && otherSeries.visible) {
-					otherSeries.isDirty = true;
-				}
-			});
-		}
-
-		if (ignoreHiddenSeries) {
-			chart.isDirtyBox = true;
-		}
-		if (redraw !== false) {
-			chart.redraw();
-		}
-
-		fireEvent(series, showOrHide);
-	},
-
-	/**
-	 * Show the graph
-	 */
-	show: function () {
-		this.setVisible(true);
-	},
-
-	/**
-	 * Hide the graph
-	 */
-	hide: function () {
-		this.setVisible(false);
-	},
-
-
-	/**
-	 * Set the selected state of the graph
-	 *
-	 * @param selected {Boolean} True to select the series, false to unselect. If
-	 *        UNDEFINED, the selection state is toggled.
-	 */
-	select: function (selected) {
-		var series = this;
-		// if called without an argument, toggle
-		series.selected = selected = (selected === UNDEFINED) ? !series.selected : selected;
-
-		if (series.checkbox) {
-			series.checkbox.checked = selected;
-		}
-
-		fireEvent(series, selected ? 'select' : 'unselect');
-	},
-
-
-	/**
-	 * Draw the tracker object that sits above all data labels and markers to
-	 * track mouse events on the graph or points. For the line type charts
-	 * the tracker uses the same graphPath, but with a greater stroke width
-	 * for better control.
-	 */
-	drawTracker: function () {
-		var series = this,
-			options = series.options,
-			trackerPath = [].concat(series.graphPath),
-			trackerPathLength = trackerPath.length,
-			chart = series.chart,
-			snap = chart.options.tooltip.snap,
-			tracker = series.tracker,
-			cursor = options.cursor,
-			css = cursor && { cursor: cursor },
-			singlePoints = series.singlePoints,
-			singlePoint,
-			i;
-
-		// Extend end points. A better way would be to use round linecaps,
-		// but those are not clickable in VML.
-		if (trackerPathLength) {
-			i = trackerPathLength + 1;
-			while (i--) {
-				if (trackerPath[i] === M) { // extend left side
-					trackerPath.splice(i + 1, 0, trackerPath[i + 1] - snap, trackerPath[i + 2], L);
-				}
-				if ((i && trackerPath[i] === M) || i === trackerPathLength) { // extend right side
-					trackerPath.splice(i, 0, L, trackerPath[i - 2] + snap, trackerPath[i - 1]);
-				}
-			}
-		}
-
-		// handle single points
-		for (i = 0; i < singlePoints.length; i++) {
-			singlePoint = singlePoints[i];
-			trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY,
-				L, singlePoint.plotX + snap, singlePoint.plotY);
-		}
-
-		// draw the tracker
-		if (tracker) {
-			tracker.attr({ d: trackerPath });
-
-		} else { // create
-			series.tracker = chart.renderer.path(trackerPath)
-				.attr({
-					isTracker: true,
-					stroke: TRACKER_FILL,
-					fill: NONE,
-					'stroke-width' : options.lineWidth + 2 * snap,
-					visibility: series.visible ? VISIBLE : HIDDEN,
-					zIndex: options.zIndex || 1
-				})
-				.on(hasTouch ? 'touchstart' : 'mouseover', function () {
-					if (chart.hoverSeries !== series) {
-						series.onMouseOver();
-					}
-				})
-				.on('mouseout', function () {
-					if (!options.stickyTracking) {
-						series.onMouseOut();
-					}
-				})
-				.css(css)
-				.add(chart.trackerGroup);
-		}
-
-	}
-
-}; // end Series prototype
-
-
-/**
- * LineSeries object
- */
-var LineSeries = extendClass(Series);
-seriesTypes.line = LineSeries;
-
-/**
- * AreaSeries object
- */
-var AreaSeries = extendClass(Series, {
-	type: 'area'
-});
-seriesTypes.area = AreaSeries;
-
-
-
-
-/**
- * SplineSeries object
- */
-var SplineSeries = extendClass(Series, {
-	type: 'spline',
-
-	/**
-	 * Draw the actual graph
-	 */
-	getPointSpline: function (segment, point, i) {
-		var 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 = point.plotX,
-			plotY = point.plotY,
-			lastPoint = segment[i - 1],
-			nextPoint = segment[i + 1],
-			leftContX,
-			leftContY,
-			rightContX,
-			rightContY,
-			ret;
-
-		// find control points
-		if (i && i < segment.length - 1) {
-			var lastX = lastPoint.plotX,
-				lastY = lastPoint.plotY,
-				nextX = nextPoint.plotX,
-				nextY = nextPoint.plotY,
-				correction;
-
-			leftContX = (smoothing * plotX + lastX) / denom;
-			leftContY = (smoothing * plotY + lastY) / denom;
-			rightContX = (smoothing * plotX + nextX) / denom;
-			rightContY = (smoothing * plotY + nextY) / denom;
-
-			// have the two control points make a straight line through main point
-			correction = ((rightContY - leftContY) * (rightContX - plotX)) /
-				(rightContX - leftContX) + plotY - rightContY;
-
-			leftContY += correction;
-			rightContY += correction;
-
-			// to prevent false extremes, check that control points are between
-			// neighbouring points' y values
-			if (leftContY > lastY && leftContY > plotY) {
-				leftContY = mathMax(lastY, plotY);
-				rightContY = 2 * plotY - leftContY; // mirror of left control point
-			} else if (leftContY < lastY && leftContY < plotY) {
-				leftContY = mathMin(lastY, plotY);
-				rightContY = 2 * plotY - leftContY;
-			}
-			if (rightContY > nextY && rightContY > plotY) {
-				rightContY = mathMax(nextY, plotY);
-				leftContY = 2 * plotY - rightContY;
-			} else if (rightContY < nextY && rightContY < plotY) {
-				rightContY = mathMin(nextY, plotY);
-				leftContY = 2 * plotY - rightContY;
-			}
-
-			// 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
-		}
-		return ret;
-	}
-});
-seriesTypes.spline = SplineSeries;
-
-
-
-/**
- * AreaSplineSeries object
- */
-var AreaSplineSeries = extendClass(SplineSeries, {
-	type: 'areaspline'
-});
-seriesTypes.areaspline = AreaSplineSeries;
-
-/**
- * ColumnSeries object
- */
-var ColumnSeries = extendClass(Series, {
-	type: 'column',
-	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
-		stroke: 'borderColor',
-		'stroke-width': 'borderWidth',
-		fill: 'color',
-		r: 'borderRadius'
-	},
-	init: function () {
-		Series.prototype.init.apply(this, arguments);
-
-		var series = this,
-			chart = series.chart;
-
-		// flag the chart in order to pad the x axis
-		chart.hasColumn = true;
-
-		// if the series is added dynamically, force redraw of other
-		// series affected by a new column
-		if (chart.hasRendered) {
-			each(chart.series, function (otherSeries) {
-				if (otherSeries.type === series.type) {
-					otherSeries.isDirty = true;
-				}
-			});
-		}
-	},
-
-	/**
-	 * Translate each point to the plot area coordinate system and find shape positions
-	 */
-	translate: function () {
-		var series = this,
-			chart = series.chart,
-			options = series.options,
-			stacking = options.stacking,
-			borderWidth = options.borderWidth,
-			columnCount = 0,
-			reversedXAxis = series.xAxis.reversed,
-			categories = series.xAxis.categories,
-			stackGroups = {},
-			stackKey,
-			columnIndex;
-
-		Series.prototype.translate.apply(series);
-
-		// Get the total number of column type series.
-		// This is called on every series. Consider moving this logic to a
-		// chart.orderStacks() function and call it on init, addSeries and removeSeries
-		each(chart.series, function (otherSeries) {
-			if (otherSeries.type === series.type && otherSeries.visible) {
-				if (otherSeries.options.stacking) {
-					stackKey = otherSeries.stackKey;
-					if (stackGroups[stackKey] === UNDEFINED) {
-						stackGroups[stackKey] = columnCount++;
-					}
-					columnIndex = stackGroups[stackKey];
-				} else {
-					columnIndex = columnCount++;
-				}
-				otherSeries.columnIndex = columnIndex;
-			}
-		});
-
-		// calculate the width and position of each column based on
-		// the number of column series in the plot, the groupPadding
-		// and the pointPadding options
-		var data = series.data,
-			closestPoints = series.closestPoints,
-			categoryWidth = mathAbs(
-				data[1] ? data[closestPoints].plotX - data[closestPoints - 1].plotX :
-				chart.plotSizeX / ((categories && categories.length) || 1)
-			),
-			groupPadding = categoryWidth * options.groupPadding,
-			groupWidth = categoryWidth - 2 * groupPadding,
-			pointOffsetWidth = groupWidth / columnCount,
-			optionPointWidth = options.pointWidth,
-			pointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 :
-				pointOffsetWidth * options.pointPadding,
-			pointWidth = mathMax(pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), 1),
-			colIndex = (reversedXAxis ? columnCount -
-				series.columnIndex : series.columnIndex) || 0,
-			pointXOffset = pointPadding + (groupPadding + colIndex *
-				pointOffsetWidth - (categoryWidth / 2)) *
-				(reversedXAxis ? -1 : 1),
-			threshold = options.threshold || 0,
-			translatedThreshold = series.yAxis.getThreshold(threshold),
-			minPointLength = pick(options.minPointLength, 5);
-
-		// record the new values
-		each(data, function (point) {
-			var plotY = point.plotY,
-				yBottom = point.yBottom || translatedThreshold,
-				barX = point.plotX + pointXOffset,
-				barY = mathCeil(mathMin(plotY, yBottom)),
-				barH = mathCeil(mathMax(plotY, yBottom) - barY),
-				stack = series.yAxis.stacks[(point.y < 0 ? '-' : '') + series.stackKey],
-				trackerY,
-				shapeArgs;
-
-			// Record the offset'ed position and width of the bar to be able to align the stacking total correctly
-			if (stacking && series.visible && stack && stack[point.x]) {
-				stack[point.x].setOffset(pointXOffset, pointWidth);
-			}
-
-			// handle options.minPointLength and tracker for small points
-			if (mathAbs(barH) < minPointLength) {
-				if (minPointLength) {
-					barH = minPointLength;
-					barY =
-						mathAbs(barY - translatedThreshold) > minPointLength ? // stacked
-							yBottom - minPointLength : // keep position
-							translatedThreshold - (plotY <= translatedThreshold ? minPointLength : 0);
-				}
-				trackerY = barY - 3;
-			}
-
-			extend(point, {
-				barX: barX,
-				barY: barY,
-				barW: pointWidth,
-				barH: barH
-			});
-
-			// create shape type and shape args that are reused in drawPoints and drawTracker
-			point.shapeType = 'rect';
-			shapeArgs = extend(chart.renderer.Element.prototype.crisp.apply({}, [
-				borderWidth,
-				barX,
-				barY,
-				pointWidth,
-				barH
-			]), {
-				r: options.borderRadius
-			});
-			if (borderWidth % 2) { // correct for shorting in crisp method, visible in stacked columns with 1px border
-				shapeArgs.y -= 1;
-				shapeArgs.height += 1;
-			}
-			point.shapeArgs = shapeArgs;
-
-			// make small columns responsive to mouse
-			point.trackerArgs = defined(trackerY) && merge(point.shapeArgs, {
-				height: mathMax(6, barH + 3),
-				y: trackerY
-			});
-		});
-
-	},
-
-	getSymbol: function () {
-	},
-
-	/**
-	 * Columns have no graph
-	 */
-	drawGraph: function () {},
-
-	/**
-	 * Draw the columns. For bars, the series.group is rotated, so the same coordinates
-	 * apply for columns and bars. This method is inherited by scatter series.
-	 *
-	 */
-	drawPoints: function () {
-		var series = this,
-			options = series.options,
-			renderer = series.chart.renderer,
-			graphic,
-			shapeArgs;
-
-
-		// draw the columns
-		each(series.data, function (point) {
-			var plotY = point.plotY;
-			if (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {
-				graphic = point.graphic;
-				shapeArgs = point.shapeArgs;
-				if (graphic) { // update
-					stop(graphic);
-					graphic.animate(shapeArgs);
-
-				} else {
-					point.graphic = renderer[point.shapeType](shapeArgs)
-						.attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE])
-						.add(series.group)
-						.shadow(options.shadow);
-				}
-
-			}
-		});
-	},
-	/**
-	 * Draw the individual tracker elements.
-	 * This method is inherited by scatter and pie charts too.
-	 */
-	drawTracker: function () {
-		var series = this,
-			chart = series.chart,
-			renderer = chart.renderer,
-			shapeArgs,
-			tracker,
-			trackerLabel = +new Date(),
-			options = series.options,
-			cursor = options.cursor,
-			css = cursor && { cursor: cursor },
-			rel;
-
-		each(series.data, function (point) {
-			tracker = point.tracker;
-			shapeArgs = point.trackerArgs || point.shapeArgs;
-			delete shapeArgs.strokeWidth;
-			if (point.y !== null) {
-				if (tracker) {// update
-					tracker.attr(shapeArgs);
-
-				} else {
-					point.tracker =
-						renderer[point.shapeType](shapeArgs)
-						.attr({
-							isTracker: trackerLabel,
-							fill: TRACKER_FILL,
-							visibility: series.visible ? VISIBLE : HIDDEN,
-							zIndex: options.zIndex || 1
-						})
-						.on(hasTouch ? 'touchstart' : 'mouseover', function (event) {
-							rel = event.relatedTarget || event.fromElement;
-							if (chart.hoverSeries !== series && attr(rel, 'isTracker') !== trackerLabel) {
-								series.onMouseOver();
-							}
-							point.onMouseOver();
-
-						})
-						.on('mouseout', function (event) {
-							if (!options.stickyTracking) {
-								rel = event.relatedTarget || event.toElement;
-								if (attr(rel, 'isTracker') !== trackerLabel) {
-									series.onMouseOut();
-								}
-							}
-						})
-						.css(css)
-						.add(point.group || chart.trackerGroup); // pies have point group - see issue #118
-				}
-			}
-		});
-	},
-
-
-	/**
-	 * Animate the column heights one by one from zero
-	 * @param {Boolean} init Whether to initialize the animation or run it
-	 */
-	animate: function (init) {
-		var series = this,
-			data = series.data;
-
-		if (!init) { // run the animation
-			/*
-			 * Note: Ideally the animation should be initialized by calling
-			 * series.group.hide(), and then calling series.group.show()
-			 * after the animation was started. But this rendered the shadows
-			 * invisible in IE8 standards mode. If the columns flicker on large
-			 * datasets, this is the cause.
-			 */
-
-			each(data, function (point) {
-				var graphic = point.graphic,
-					shapeArgs = point.shapeArgs;
-
-				if (graphic) {
-					// start values
-					graphic.attr({
-						height: 0,
-						y: series.yAxis.translate(0, 0, 1)
-					});
-
-					// animate
-					graphic.animate({
-						height: shapeArgs.height,
-						y: shapeArgs.y
-					}, series.options.animation);
-				}
-			});
-
-
-			// delete this function to allow it only once
-			series.animate = null;
-		}
-
-	},
-	/**
-	 * Remove this series from the chart
-	 */
-	remove: function () {
-		var series = this,
-			chart = series.chart;
-
-		// column and bar series affects other series of the same type
-		// as they are either stacked or grouped
-		if (chart.hasRendered) {
-			each(chart.series, function (otherSeries) {
-				if (otherSeries.type === series.type) {
-					otherSeries.isDirty = true;
-				}
-			});
-		}
-
-		Series.prototype.remove.apply(series, arguments);
-	}
-});
-seriesTypes.column = ColumnSeries;
-
-var BarSeries = extendClass(ColumnSeries, {
-	type: 'bar',
-	init: function (chart) {
-		chart.inverted = this.inverted = true;
-		ColumnSeries.prototype.init.apply(this, arguments);
-	}
-});
-seriesTypes.bar = BarSeries;
-
-/**
- * The scatter series class
- */
-var ScatterSeries = extendClass(Series, {
-	type: 'scatter',
-
-	/**
-	 * Extend the base Series' translate method by adding shape type and
-	 * arguments for the point trackers
-	 */
-	translate: function () {
-		var series = this;
-
-		Series.prototype.translate.apply(series);
-
-		each(series.data, function (point) {
-			point.shapeType = 'circle';
-			point.shapeArgs = {
-				x: point.plotX,
-				y: point.plotY,
-				r: series.chart.options.tooltip.snap
-			};
-		});
-	},
-
-
-	/**
-	 * Create individual tracker elements for each point
-	 */
-	//drawTracker: ColumnSeries.prototype.drawTracker,
-	drawTracker: function () {
-		var series = this,
-			cursor = series.options.cursor,
-			css = cursor && { cursor: cursor },
-			graphic;
-
-		each(series.data, function (point) {
-			graphic = point.graphic;
-			if (graphic) { // doesn't exist for null points
-				graphic
-					.attr({ isTracker: true })
-					.on('mouseover', function () {
-						series.onMouseOver();
-						point.onMouseOver();
-					})
-					.on('mouseout', function () {
-						if (!series.options.stickyTracking) {
-							series.onMouseOut();
-						}
-					})
-					.css(css);
-			}
-		});
-
-	},
-
-	/**
-	 * Cleaning the data is not necessary in a scatter plot
-	 */
-	cleanData: function () {}
-});
-seriesTypes.scatter = ScatterSeries;
-
-/**
- * Extended point object for pies
- */
-var PiePoint = extendClass(Point, {
-	/**
-	 * Initiate the pie slice
-	 */
-	init: function () {
-
-		Point.prototype.init.apply(this, arguments);
-
-		var point = this,
-			toggleSlice;
-
-		//visible: options.visible !== false,
-		extend(point, {
-			visible: point.visible !== false,
-			name: pick(point.name, 'Slice')
-		});
-
-		// add event listener for select
-		toggleSlice = function () {
-			point.slice();
-		};
-		addEvent(point, 'select', toggleSlice);
-		addEvent(point, 'unselect', toggleSlice);
-
-		return point;
-	},
-
-	/**
-	 * Toggle the visibility of the pie slice
-	 * @param {Boolean} vis Whether to show the slice or not. If undefined, the
-	 *    visibility is toggled
-	 */
-	setVisible: function (vis) {
-		var point = this,
-			chart = point.series.chart,
-			tracker = point.tracker,
-			dataLabel = point.dataLabel,
-			connector = point.connector,
-			shadowGroup = point.shadowGroup,
-			method;
-
-		// if called without an argument, toggle visibility
-		point.visible = vis = vis === UNDEFINED ? !point.visible : vis;
-
-		method = vis ? 'show' : 'hide';
-
-		point.group[method]();
-		if (tracker) {
-			tracker[method]();
-		}
-		if (dataLabel) {
-			dataLabel[method]();
-		}
-		if (connector) {
-			connector[method]();
-		}
-		if (shadowGroup) {
-			shadowGroup[method]();
-		}
-		if (point.legendItem) {
-			chart.legend.colorizeItem(point, vis);
-		}
-	},
-
-	/**
-	 * Set or toggle whether the slice is cut out from the pie
-	 * @param {Boolean} sliced When undefined, the slice state is toggled
-	 * @param {Boolean} redraw Whether to redraw the chart. True by default.
-	 */
-	slice: function (sliced, redraw, animation) {
-		var point = this,
-			series = point.series,
-			chart = series.chart,
-			slicedTranslation = point.slicedTranslation,
-			translation;
-
-		setAnimation(animation, chart);
-
-		// redraw is true by default
-		redraw = pick(redraw, true);
-
-		// if called without an argument, toggle
-		sliced = point.sliced = defined(sliced) ? sliced : !point.sliced;
-
-		translation = {
-			translateX: (sliced ? slicedTranslation[0] : chart.plotLeft),
-			translateY: (sliced ? slicedTranslation[1] : chart.plotTop)
-		};
-		point.group.animate(translation);
-		if (point.shadowGroup) {
-			point.shadowGroup.animate(translation);
-		}
-
-	}
-});
-
-/**
- * The Pie series class
- */
-var PieSeries = extendClass(Series, {
-	type: 'pie',
-	isCartesian: false,
-	pointClass: PiePoint,
-	pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
-		stroke: 'borderColor',
-		'stroke-width': 'borderWidth',
-		fill: 'color'
-	},
-
-	/**
-	 * Pies have one color each point
-	 */
-	getColor: function () {
-		// record first color for use in setData
-		this.initialColor = this.chart.counters.color;
-	},
-
-	/**
-	 * Animate the column heights one by one from zero
-	 */
-	animate: function () {
-		var series = this,
-			data = series.data;
-
-		each(data, function (point) {
-			var graphic = point.graphic,
-				args = point.shapeArgs,
-				up = -mathPI / 2;
-
-			if (graphic) {
-				// start values
-				graphic.attr({
-					r: 0,
-					start: up,
-					end: up
-				});
-
-				// animate
-				graphic.animate({
-					r: args.r,
-					start: args.start,
-					end: args.end
-				}, series.options.animation);
-			}
-		});
-
-		// delete this function to allow it only once
-		series.animate = null;
-
-	},
-	/**
-	 * Do translation for pie slices
-	 */
-	translate: function () {
-		var total = 0,
-			series = this,
-			cumulative = -0.25, // start at top
-			precision = 1000, // issue #172
-			options = series.options,
-			slicedOffset = options.slicedOffset,
-			connectorOffset = slicedOffset + options.borderWidth,
-			positions = options.center.concat([options.size, options.innerSize || 0]),
-			chart = series.chart,
-			plotWidth = chart.plotWidth,
-			plotHeight = chart.plotHeight,
-			start,
-			end,
-			angle,
-			data = series.data,
-			circ = 2 * mathPI,
-			fraction,
-			smallestSize = mathMin(plotWidth, plotHeight),
-			isPercent,
-			radiusX, // the x component of the radius vector for a given point
-			radiusY,
-			labelDistance = options.dataLabels.distance;
-
-		// get positions - either an integer or a percentage string must be given
-		positions = map(positions, function (length, i) {
-
-			isPercent = /%$/.test(length);
-			return isPercent ?
-				// i == 0: centerX, relative to width
-				// i == 1: centerY, relative to height
-				// i == 2: size, relative to smallestSize
-				// i == 4: innerSize, relative to smallestSize
-				[plotWidth, plotHeight, smallestSize, smallestSize][i] *
-					pInt(length) / 100 :
-				length;
-		});
-
-		// utility for getting the x value from a given y, used for anticollision logic in data labels
-		series.getX = function (y, left) {
-
-			angle = math.asin((y - positions[1]) / (positions[2] / 2 + labelDistance));
-
-			return positions[0] +
-				(left ? -1 : 1) *
-				(mathCos(angle) * (positions[2] / 2 + labelDistance));
-		};
-
-		// set center for later use
-		series.center = positions;
-
-		// get the total sum
-		each(data, function (point) {
-			total += point.y;
-		});
-
-		each(data, function (point) {
-			// set start and end angle
-			fraction = total ? point.y / total : 0;
-			start = mathRound(cumulative * circ * precision) / precision;
-			cumulative += fraction;
-			end = mathRound(cumulative * circ * precision) / precision;
-
-			// set the shape
-			point.shapeType = 'arc';
-			point.shapeArgs = {
-				x: positions[0],
-				y: positions[1],
-				r: positions[2] / 2,
-				innerR: positions[3] / 2,
-				start: start,
-				end: end
-			};
-
-			// center for the sliced out slice
-			angle = (end + start) / 2;
-			point.slicedTranslation = map([
-				mathCos(angle) * slicedOffset + chart.plotLeft,
-				mathSin(angle) * slicedOffset + chart.plotTop
-			], mathRound);
-
-			// set the anchor point for tooltips
-			radiusX = mathCos(angle) * positions[2] / 2;
-			radiusY = mathSin(angle) * positions[2] / 2;
-			point.tooltipPos = [
-				positions[0] + radiusX * 0.7,
-				positions[1] + radiusY * 0.7
-			];
-
-			// set the anchor point for data labels
-			point.labelPos = [
-				positions[0] + radiusX + mathCos(angle) * labelDistance, // first break of connector
-				positions[1] + radiusY + mathSin(angle) * labelDistance, // a/a
-				positions[0] + radiusX + mathCos(angle) * connectorOffset, // second break, right outside pie
-				positions[1] + radiusY + mathSin(angle) * connectorOffset, // a/a
-				positions[0] + radiusX, // landing point for connector
-				positions[1] + radiusY, // a/a
-				labelDistance < 0 ? // alignment
-					'center' :
-					angle < circ / 4 ? 'left' : 'right', // alignment
-				angle // center angle
-			];
-
-			// API properties
-			point.percentage = fraction * 100;
-			point.total = total;
-
-		});
-
-
-		this.setTooltipPoints();
-	},
-
-	/**
-	 * Render the slices
-	 */
-	render: function () {
-		var series = this;
-
-		// cache attributes for shapes
-		//series.getAttribs();
-
-		this.drawPoints();
-
-		// draw the mouse tracking area
-		if (series.options.enableMouseTracking !== false) {
-			series.drawTracker();
-		}
-
-		this.drawDataLabels();
-
-		if (series.options.animation && series.animate) {
-			series.animate();
-		}
-
-		series.isDirty = false; // means data is in accordance with what you see
-	},
-
-	/**
-	 * Draw the data points
-	 */
-	drawPoints: function () {
-		var series = this,
-			chart = series.chart,
-			renderer = chart.renderer,
-			groupTranslation,
-			//center,
-			graphic,
-			group,
-			shadow = series.options.shadow,
-			shadowGroup,
-			shapeArgs;
-
-
-		// draw the slices
-		each(series.data, function (point) {
-			graphic = point.graphic;
-			shapeArgs = point.shapeArgs;
-			group = point.group;
-			shadowGroup = point.shadowGroup;
-
-			// put the shadow behind all points
-			if (shadow && !shadowGroup) {
-				shadowGroup = point.shadowGroup = renderer.g('shadow')
-					.attr({ zIndex: 4 })
-					.add();
-			}
-
-			// create the group the first time
-			if (!group) {
-				group = point.group = renderer.g('point')
-					.attr({ zIndex: 5 })
-					.add();
-			}
-
-			// if the point is sliced, use special translation, else use plot area traslation
-			groupTranslation = point.sliced ? point.slicedTranslation : [chart.plotLeft, chart.plotTop];
-			group.translate(groupTranslation[0], groupTranslation[1]);
-			if (shadowGroup) {
-				shadowGroup.translate(groupTranslation[0], groupTranslation[1]);
-			}
-
-
-			// draw the slice
-			if (graphic) {
-				graphic.animate(shapeArgs);
-			} else {
-				point.graphic =
-					renderer.arc(shapeArgs)
-					.attr(extend(
-						point.pointAttr[NORMAL_STATE],
-						{ 'stroke-linejoin': 'round' }
-					))
-					.add(point.group)
-					.shadow(shadow, shadowGroup);
-			}
-
-			// detect point specific visibility
-			if (point.visible === false) {
-				point.setVisible(false);
-			}
-
-		});
-
-	},
-
-	/**
-	 * Override the base drawDataLabels method by pie specific functionality
-	 */
-	drawDataLabels: function () {
-		var series = this,
-			data = series.data,
-			point,
-			chart = series.chart,
-			options = series.options.dataLabels,
-			connectorPadding = pick(options.connectorPadding, 10),
-			connectorWidth = pick(options.connectorWidth, 1),
-			connector,
-			connectorPath,
-			softConnector = pick(options.softConnector, true),
-			distanceOption = options.distance,
-			seriesCenter = series.center,
-			radius = seriesCenter[2] / 2,
-			centerY = seriesCenter[1],
-			outside = distanceOption > 0,
-			dataLabel,
-			labelPos,
-			labelHeight,
-			halves = [// divide the points into right and left halves for anti collision
-				[], // right
-				[]  // left
-			],
-			x,
-			y,
-			visibility,
-			rankArr,
-			sort,
-			i = 2,
-			j;
-
-		// get out if not enabled
-		if (!options.enabled) {
-			return;
-		}
-
-		// run parent method
-		Series.prototype.drawDataLabels.apply(series);
-
-		// arrange points for detection collision
-		each(data, function (point) {
-			if (point.dataLabel) { // it may have been cancelled in the base method (#407)
-				halves[
-					point.labelPos[7] < mathPI / 2 ? 0 : 1
-				].push(point);
-			}
-		});
-		halves[1].reverse();
-
-		// define the sorting algorithm
-		sort = function (a, b) {
-			return b.y - a.y;
-		};
-
-		// assume equal label heights
-		labelHeight = halves[0][0] && halves[0][0].dataLabel && pInt(halves[0][0].dataLabel.styles.lineHeight);
-
-		/* Loop over the points in each quartile, starting from the top and bottom
-		 * of the pie to detect overlapping labels.
-		 */
-		while (i--) {
-
-			var slots = [],
-				slotsLength,
-				usedSlots = [],
-				points = halves[i],
-				pos,
-				length = points.length,
-				slotIndex;
-
-
-			// build the slots
-			for (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) {
-				slots.push(pos);
-				// visualize the slot
-				/*
-				var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0),
-					slotY = pos + chart.plotTop;
-				if (!isNaN(slotX)) {
-					chart.renderer.rect(slotX, slotY - 7, 100, labelHeight)
-						.attr({
-							'stroke-width': 1,
-							stroke: 'silver'
-						})
-						.add();
-					chart.renderer.text('Slot '+ (slots.length - 1), slotX, slotY + 4)
-						.attr({
-							fill: 'silver'
-						}).add();
-				}
-				// */
-			}
-			slotsLength = slots.length;
-
-			// if there are more values than available slots, remove lowest values
-			if (length > slotsLength) {
-				// create an array for sorting and ranking the points within each quarter
-				rankArr = [].concat(points);
-				rankArr.sort(sort);
-				j = length;
-				while (j--) {
-					rankArr[j].rank = j;
-				}
-				j = length;
-				while (j--) {
-					if (points[j].rank >= slotsLength) {
-						points.splice(j, 1);
-					}
-				}
-				length = points.length;
-			}
-
-			// The label goes to the nearest open slot, but not closer to the edge than
-			// the label's index.
-			for (j = 0; j < length; j++) {
-
-				point = points[j];
-				labelPos = point.labelPos;
-
-				var closest = 9999,
-					distance,
-					slotI;
-
-				// find the closest slot index
-				for (slotI = 0; slotI < slotsLength; slotI++) {
-					distance = mathAbs(slots[slotI] - labelPos[1]);
-					if (distance < closest) {
-						closest = distance;
-						slotIndex = slotI;
-					}
-				}
-
-				// if that slot index is closer to the edges of the slots, move it
-				// to the closest appropriate slot
-				if (slotIndex < j && slots[j] !== null) { // cluster at the top
-					slotIndex = j;
-				} else if (slotsLength  < length - j + slotIndex && slots[j] !== null) { // cluster at the bottom
-					slotIndex = slotsLength - length + j;
-					while (slots[slotIndex] === null) { // make sure it is not taken
-						slotIndex++;
-					}
-				} else {
-					// Slot is taken, find next free slot below. In the next run, the next slice will find the
-					// slot above these, because it is the closest one
-					while (slots[slotIndex] === null) { // make sure it is not taken
-						slotIndex++;
-					}
-				}
-
-				usedSlots.push({ i: slotIndex, y: slots[slotIndex] });
-				slots[slotIndex] = null; // mark as taken
-			}
-			// sort them in order to fill in from the top
-			usedSlots.sort(sort);
-
-
-			// now the used slots are sorted, fill them up sequentially
-			for (j = 0; j < length; j++) {
-
-				point = points[j];
-				labelPos = point.labelPos;
-				dataLabel = point.dataLabel;
-				var slot = usedSlots.pop(),
-					naturalY = labelPos[1];
-
-				visibility = point.visible === false ? HIDDEN : VISIBLE;
-				slotIndex = slot.i;
-
-				// if the slot next to currrent slot is free, the y value is allowed
-				// to fall back to the natural position
-				y = slot.y;
-				if ((naturalY > y && slots[slotIndex + 1] !== null) ||
-						(naturalY < y &&  slots[slotIndex - 1] !== null)) {
-					y = naturalY;
-				}
-
-				// get the x - use the natural x position for first and last slot, to prevent the top
-				// and botton slice connectors from touching each other on either side
-				x = series.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i);
-
-				// move or place the data label
-				dataLabel
-					.attr({
-						visibility: visibility,
-						align: labelPos[6]
-					})[dataLabel.moved ? 'animate' : 'attr']({
-						x: x + options.x +
-							({ left: connectorPadding, right: -connectorPadding }[labelPos[6]] || 0),
-						y: y + options.y
-					});
-				dataLabel.moved = true;
-
-				// draw the connector
-				if (outside && connectorWidth) {
-					connector = point.connector;
-
-					connectorPath = softConnector ? [
-						M,
-						x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label
-						'C',
-						x, y, // first break, next to the label
-						2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5],
-						labelPos[2], labelPos[3], // second break
-						L,
-						labelPos[4], labelPos[5] // base
-					] : [
-						M,
-						x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label
-						L,
-						labelPos[2], labelPos[3], // second break
-						L,
-						labelPos[4], labelPos[5] // base
-					];
-
-					if (connector) {
-						connector.animate({ d: connectorPath });
-						connector.attr('visibility', visibility);
-
-					} else {
-						point.connector = connector = series.chart.renderer.path(connectorPath).attr({
-							'stroke-width': connectorWidth,
-							stroke: options.connectorColor || point.color || '#606060',
-							visibility: visibility,
-							zIndex: 3
-						})
-						.translate(chart.plotLeft, chart.plotTop)
-						.add();
-					}
-				}
-			}
-		}
-	},
-
-	/**
-	 * Draw point specific tracker objects. Inherit directly from column series.
-	 */
-	drawTracker: ColumnSeries.prototype.drawTracker,
-
-	/**
-	 * Pies don't have point marker symbols
-	 */
-	getSymbol: function () {}
-
-});
-seriesTypes.pie = PieSeries;
-
-
-// global variables
-win.Highcharts = {
-	Chart: Chart,
-	dateFormat: dateFormat,
-	pathAnim: pathAnim,
-	getOptions: getOptions,
-	hasRtlBug: hasRtlBug,
-	numberFormat: numberFormat,
-	Point: Point,
-	Color: Color,
-	Renderer: Renderer,
-	seriesTypes: seriesTypes,
-	setOptions: setOptions,
-	Series: Series,
-
-	// Expose utility funcitons for modules
-	addEvent: addEvent,
-	removeEvent: removeEvent,
-	createElement: createElement,
-	discardElement: discardElement,
-	css: css,
-	each: each,
-	extend: extend,
-	map: map,
-	merge: merge,
-	pick: pick,
-	extendClass: extendClass,
-	product: 'Highcharts',
-	version: '2.1.9'
-};
-}());

=== removed directory 'media/js/highcharts_219/modules'
=== removed file 'media/js/highcharts_219/modules/exporting.js'
--- media/js/highcharts_219/modules/exporting.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/modules/exporting.js	1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
-/*
- Highcharts JS v2.1.9 (2011-11-11)
- Exporting module
-
- (c) 2010-2011 Torstein H?nsi
-
- License: www.highcharts.com/license
-*/
-(function(){var n=Highcharts,A=n.Chart,B=n.addEvent,E=n.removeEvent,t=n.createElement,w=n.discardElement,u=n.css,x=n.merge,q=n.each,r=n.extend,F=Math.max,s=document,G=window,C=s.documentElement.ontouchstart!==undefined,y=n.getOptions();r(y.lang,{downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",exportButtonTitle:"Export to raster or vector image",printButtonTitle:"Print the chart"});y.navigation={menuStyle:{border:"1px solid #A0A0A0",
-background:"#FFFFFF"},menuItemStyle:{padding:"0 5px",background:"none",color:"#303030",fontSize:C?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{align:"right",backgroundColor:{linearGradient:[0,0,0,20],stops:[[0.4,"#F7F7F7"],[0.6,"#E3E3E3"]]},borderColor:"#B0B0B0",borderRadius:3,borderWidth:1,height:20,hoverBorderColor:"#909090",hoverSymbolFill:"#81A7CF",hoverSymbolStroke:"#4572A5",symbolFill:"#E0E0E0",symbolStroke:"#A0A0A0",symbolX:11.5,symbolY:10.5,verticalAlign:"top",
-width:24,y:10}};y.exporting={type:"image/png",url:"http://export.highcharts.com/",width:800,enableImages:false,buttons:{exportButton:{symbol:"exportIcon",x:-10,symbolFill:"#A8BF77",hoverSymbolFill:"#768F3E",_id:"exportButton",_titleKey:"exportButtonTitle",menuItems:[{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",
-onclick:function(){this.exportChart({type:"image/svg+xml"})}}]},printButton:{symbol:"printIcon",x:-36,symbolFill:"#B5C9DF",hoverSymbolFill:"#779ABF",_id:"printButton",_titleKey:"printButtonTitle",onclick:function(){this.print()}}}};r(A.prototype,{getSVG:function(b){var c=this,a,f,d,k,e,j,h=x(c.options,b);if(!s.createElementNS)s.createElementNS=function(i,g){var o=s.createElement(g);o.getBBox=function(){return n.Renderer.prototype.Element.prototype.getBBox.apply({element:o})};return o};b=t("div",null,
-{position:"absolute",top:"-9999em",width:c.chartWidth+"px",height:c.chartHeight+"px"},s.body);r(h.chart,{renderTo:b,forExport:true});h.exporting.enabled=false;if(!h.exporting.enableImages)h.chart.plotBackgroundImage=null;h.series=[];q(c.series,function(i){d=i.options;d.animation=false;d.showCheckbox=false;d.visible=i.visible;if(!h.exporting.enableImages)if(d&&d.marker&&/^url\(/.test(d.marker.symbol))d.marker.symbol="circle";d.data=[];q(i.data,function(g){k=g.config;e={x:g.x,y:g.y,name:g.name};typeof k===
-"object"&&g.config&&k.constructor!==Array&&r(e,k);e.visible=g.visible;d.data.push(e);if(!h.exporting.enableImages)(j=g.config&&g.config.marker)&&/^url\(/.test(j.symbol)&&delete j.symbol});h.series.push(d)});a=new Highcharts.Chart(h);q(["xAxis","yAxis"],function(i){q(c[i],function(g,o){var l=a[i][o],m=g.getExtremes(),p=m.userMin;m=m.userMax;if(p!==void 0||m!==void 0)l.setExtremes(p,m,true,false)})});f=a.container.innerHTML;h=null;a.destroy();w(b);f=f.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,
-"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/isTracker="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/<svg /,'<svg xmlns:xlink="http://www.w3.org/1999/xlink"; ').replace(/ href=/g," xlink:href=").replace(/&nbsp;/g,"\u00a0").replace(/&shy;/g,"\u00ad").replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" ]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/<img ([^>]*)>/gi,"<image $1 />").replace(/<\/image>/g,"").replace(/<image ([^>]*)([^\/])>/gi,
-"<image $1$2 />").replace(/width=(\d+)/g,'width="$1"').replace(/height=(\d+)/g,'height="$1"').replace(/hc-svg-href="/g,'xlink:href="').replace(/style="([^"]+)"/g,function(i){return i.toLowerCase()});f=f.replace(/(url\(#highcharts-[0-9]+)&quot;/g,"$1").replace(/&quot;/g,"'");if(f.match(/ xmlns="/g).length===2)f=f.replace(/xmlns="[^"]+"/,"");return f},exportChart:function(b,c){var a,f=this.getSVG(c);b=x(this.options.exporting,b);a=t("form",{method:"post",action:b.url},{display:"none"},s.body);q(["filename",
-"type","width","svg"],function(d){t("input",{type:"hidden",name:d,value:{filename:b.filename||"chart",type:b.type,width:b.width,svg:f}[d]},null,a)});a.submit();w(a)},print:function(){var b=this,c=b.container,a=[],f=c.parentNode,d=s.body,k=d.childNodes;if(!b.isPrinting){b.isPrinting=true;q(k,function(e,j){if(e.nodeType===1){a[j]=e.style.display;e.style.display="none"}});d.appendChild(c);G.print();setTimeout(function(){f.appendChild(c);q(k,function(e,j){if(e.nodeType===1)e.style.display=a[j]});b.isPrinting=
-false},1E3)}},contextMenu:function(b,c,a,f,d,k){var e=this,j=e.options.navigation,h=j.menuItemStyle,i=e.chartWidth,g=e.chartHeight,o="cache-"+b,l=e[o],m=F(d,k),p,z;if(!l){e[o]=l=t("div",{className:"highcharts-"+b},{position:"absolute",zIndex:1E3,padding:m+"px"},e.container);p=t("div",null,r({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},j.menuStyle),l);z=function(){u(l,{display:"none"})};B(l,"mouseleave",z);q(c,function(v){if(v){var D=t("div",
-{onmouseover:function(){u(this,j.menuItemHoverStyle)},onmouseout:function(){u(this,h)},innerHTML:v.text||e.options.lang[v.textKey]},r({cursor:"pointer"},h),p);D[C?"ontouchstart":"onclick"]=function(){z();v.onclick.apply(e,arguments)};e.exportDivElements.push(D)}});e.exportDivElements.push(p,l);e.exportMenuWidth=l.offsetWidth;e.exportMenuHeight=l.offsetHeight}b={display:"block"};if(a+e.exportMenuWidth>i)b.right=i-a-d-m+"px";else b.left=a-m+"px";if(f+k+e.exportMenuHeight>g)b.bottom=g-f-m+"px";else b.top=
-f+k-m+"px";u(l,b)},addButton:function(b){function c(){g.attr(m);i.attr(l)}var a=this,f=a.renderer,d=x(a.options.navigation.buttonOptions,b),k=d.onclick,e=d.menuItems,j=d.width,h=d.height,i,g,o;b=d.borderWidth;var l={stroke:d.borderColor},m={stroke:d.symbolStroke,fill:d.symbolFill};if(!a.exportDivElements){a.exportDivElements=[];a.exportSVGElements=[]}if(d.enabled!==false){i=f.rect(0,0,j,h,d.borderRadius,b).align(d,true).attr(r({fill:d.backgroundColor,"stroke-width":b,zIndex:19},l)).add();o=f.rect(0,
-0,j,h,0).align(d).attr({id:d._id,fill:"rgba(255, 255, 255, 0.001)",title:a.options.lang[d._titleKey],zIndex:21}).css({cursor:"pointer"}).on("mouseover",function(){g.attr({stroke:d.hoverSymbolStroke,fill:d.hoverSymbolFill});i.attr({stroke:d.hoverBorderColor})}).on("mouseout",c).on("click",c).add();if(e)k=function(){c();var p=o.getBBox();a.contextMenu("export-menu",e,p.x,p.y,j,h)};o.on("click",function(){k.apply(a,arguments)});g=f.symbol(d.symbol,d.symbolX,d.symbolY,(d.symbolSize||12)/2).align(d,true).attr(r(m,
-{"stroke-width":d.symbolStrokeWidth||1,zIndex:20})).add();a.exportSVGElements.push(i,o,g)}},destroyExport:function(){var b,c;for(b=0;b<this.exportSVGElements.length;b++){c=this.exportSVGElements[b];c.onclick=c.ontouchstart=null;this.exportSVGElements[b]=c.destroy()}for(b=0;b<this.exportDivElements.length;b++){c=this.exportDivElements[b];E(c,"mouseleave");this.exportDivElements[b]=c.onmouseout=c.onmouseover=c.ontouchstart=c.onclick=null;w(c)}}});n.Renderer.prototype.symbols.exportIcon=function(b,c,
-a){return["M",b-a,c+a,"L",b+a,c+a,b+a,c+a*0.5,b-a,c+a*0.5,"Z","M",b,c+a*0.5,"L",b-a*0.5,c-a/3,b-a/6,c-a/3,b-a/6,c-a,b+a/6,c-a,b+a/6,c-a/3,b+a*0.5,c-a/3,"Z"]};n.Renderer.prototype.symbols.printIcon=function(b,c,a){return["M",b-a,c+a*0.5,"L",b+a,c+a*0.5,b+a,c-a/3,b-a,c-a/3,"Z","M",b-a*0.5,c-a/3,"L",b-a*0.5,c-a,b+a*0.5,c-a,b+a*0.5,c-a/3,"Z","M",b-a*0.5,c+a*0.5,"L",b-a*0.75,c+a,b+a*0.75,c+a,b+a*0.5,c+a*0.5,"Z"]};A.prototype.callbacks.push(function(b){var c,a=b.options.exporting,f=a.buttons;if(a.enabled!==
-false){for(c in f)b.addButton(f[c]);B(b,"destroy",b.destroyExport)}})})();

=== removed file 'media/js/highcharts_219/modules/exporting.src.js'
--- media/js/highcharts_219/modules/exporting.src.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/modules/exporting.src.js	1970-01-01 00:00:00 +0000
@@ -1,758 +0,0 @@
-/**
- * @license Highcharts JS v2.1.9 (2011-11-11)
- * Exporting module
- *
- * (c) 2010-2011 Torstein Hønsi
- *
- * License: www.highcharts.com/license
- */
-
-// JSLint options:
-/*global Highcharts, document, window, Math, setTimeout */
-
-(function () { // encapsulate
-
-// create shortcuts
-var HC = Highcharts,
-	Chart = HC.Chart,
-	addEvent = HC.addEvent,
-	removeEvent = HC.removeEvent,
-	createElement = HC.createElement,
-	discardElement = HC.discardElement,
-	css = HC.css,
-	merge = HC.merge,
-	each = HC.each,
-	extend = HC.extend,
-	math = Math,
-	mathMax = math.max,
-	doc = document,
-	win = window,
-	hasTouch = doc.documentElement.ontouchstart !== undefined,
-	M = 'M',
-	L = 'L',
-	DIV = 'div',
-	HIDDEN = 'hidden',
-	NONE = 'none',
-	PREFIX = 'highcharts-',
-	ABSOLUTE = 'absolute',
-	PX = 'px',
-	UNDEFINED,
-	defaultOptions = HC.getOptions();
-
-	// Add language
-	extend(defaultOptions.lang, {
-		downloadPNG: 'Download PNG image',
-		downloadJPEG: 'Download JPEG image',
-		downloadPDF: 'Download PDF document',
-		downloadSVG: 'Download SVG vector image',
-		exportButtonTitle: 'Export to raster or vector image',
-		printButtonTitle: 'Print the chart'
-	});
-
-// Buttons and menus are collected in a separate config option set called 'navigation'.
-// This can be extended later to add control buttons like zoom and pan right click menus.
-defaultOptions.navigation = {
-	menuStyle: {
-		border: '1px solid #A0A0A0',
-		background: '#FFFFFF'
-	},
-	menuItemStyle: {
-		padding: '0 5px',
-		background: NONE,
-		color: '#303030',
-		fontSize: hasTouch ? '14px' : '11px'
-	},
-	menuItemHoverStyle: {
-		background: '#4572A5',
-		color: '#FFFFFF'
-	},
-
-	buttonOptions: {
-		align: 'right',
-		backgroundColor: {
-			linearGradient: [0, 0, 0, 20],
-			stops: [
-				[0.4, '#F7F7F7'],
-				[0.6, '#E3E3E3']
-			]
-		},
-		borderColor: '#B0B0B0',
-		borderRadius: 3,
-		borderWidth: 1,
-		//enabled: true,
-		height: 20,
-		hoverBorderColor: '#909090',
-		hoverSymbolFill: '#81A7CF',
-		hoverSymbolStroke: '#4572A5',
-		symbolFill: '#E0E0E0',
-		//symbolSize: 12,
-		symbolStroke: '#A0A0A0',
-		//symbolStrokeWidth: 1,
-		symbolX: 11.5,
-		symbolY: 10.5,
-		verticalAlign: 'top',
-		width: 24,
-		y: 10
-	}
-};
-
-
-
-// Add the export related options
-defaultOptions.exporting = {
-	//enabled: true,
-	//filename: 'chart',
-	type: 'image/png',
-	url: 'http://export.highcharts.com/',
-	width: 800,
-	enableImages: false,
-	buttons: {
-		exportButton: {
-			//enabled: true,
-			symbol: 'exportIcon',
-			x: -10,
-			symbolFill: '#A8BF77',
-			hoverSymbolFill: '#768F3E',
-			_id: 'exportButton',
-			_titleKey: 'exportButtonTitle',
-			menuItems: [{
-				textKey: 'downloadPNG',
-				onclick: function () {
-					this.exportChart();
-				}
-			}, {
-				textKey: 'downloadJPEG',
-				onclick: function () {
-					this.exportChart({
-						type: 'image/jpeg'
-					});
-				}
-			}, {
-				textKey: 'downloadPDF',
-				onclick: function () {
-					this.exportChart({
-						type: 'application/pdf'
-					});
-				}
-			}, {
-				textKey: 'downloadSVG',
-				onclick: function () {
-					this.exportChart({
-						type: 'image/svg+xml'
-					});
-				}
-			}/*, {
-				text: 'View SVG',
-				onclick: function() {
-					var svg = this.getSVG()
-						.replace(/</g, '\n&lt;')
-						.replace(/>/g, '&gt;');
-
-					doc.body.innerHTML = '<pre>'+ svg +'</pre>';
-				}
-			}*/]
-
-		},
-		printButton: {
-			//enabled: true,
-			symbol: 'printIcon',
-			x: -36,
-			symbolFill: '#B5C9DF',
-			hoverSymbolFill: '#779ABF',
-			_id: 'printButton',
-			_titleKey: 'printButtonTitle',
-			onclick: function () {
-				this.print();
-			}
-		}
-	}
-};
-
-
-
-extend(Chart.prototype, {
-	/**
-	 * Return an SVG representation of the chart
-	 *
-	 * @param additionalOptions {Object} Additional chart options for the generated SVG representation
-	 */
-	getSVG: function (additionalOptions) {
-		var chart = this,
-			chartCopy,
-			sandbox,
-			svg,
-			seriesOptions,
-			config,
-			pointOptions,
-			pointMarker,
-			options = merge(chart.options, additionalOptions); // copy the options and add extra options
-
-		// IE compatibility hack for generating SVG content that it doesn't really understand
-		if (!doc.createElementNS) {
-			/*jslint unparam: true*//* allow unused parameter ns in function below */
-			doc.createElementNS = function (ns, tagName) {
-				var elem = doc.createElement(tagName);
-				elem.getBBox = function () {
-					return HC.Renderer.prototype.Element.prototype.getBBox.apply({ element: elem });
-				};
-				return elem;
-			};
-			/*jslint unparam: false*/
-		}
-
-		// create a sandbox where a new chart will be generated
-		sandbox = createElement(DIV, null, {
-			position: ABSOLUTE,
-			top: '-9999em',
-			width: chart.chartWidth + PX,
-			height: chart.chartHeight + PX
-		}, doc.body);
-
-		// override some options
-		extend(options.chart, {
-			renderTo: sandbox,
-			forExport: true
-		});
-		options.exporting.enabled = false; // hide buttons in print
-
-		if (!options.exporting.enableImages) {
-			options.chart.plotBackgroundImage = null; // the converter doesn't handle images
-		}
-
-		// prepare for replicating the chart
-		options.series = [];
-		each(chart.series, function (serie) {
-			seriesOptions = serie.options;
-
-			seriesOptions.animation = false; // turn off animation
-			seriesOptions.showCheckbox = false;
-			seriesOptions.visible = serie.visible;
-
-			if (!options.exporting.enableImages) {
-				// remove image markers
-				if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) {
-					seriesOptions.marker.symbol = 'circle';
-				}
-			}
-
-			seriesOptions.data = [];
-
-			each(serie.data, function (point) {
-
-				// extend the options by those values that can be expressed in a number or array config
-				config = point.config;
-				pointOptions = {
-					x: point.x,
-					y: point.y,
-					name: point.name
-				};
-
-				if (typeof config === 'object' && point.config && config.constructor !== Array) {
-					extend(pointOptions, config);
-				}
-
-				pointOptions.visible = point.visible;
-				seriesOptions.data.push(pointOptions); // copy fresh updated data
-
-				if (!options.exporting.enableImages) {
-					// remove image markers
-					pointMarker = point.config && point.config.marker;
-					if (pointMarker && /^url\(/.test(pointMarker.symbol)) {
-						delete pointMarker.symbol;
-					}
-				}
-			});
-
-			options.series.push(seriesOptions);
-		});
-
-		// generate the chart copy
-		chartCopy = new Highcharts.Chart(options);
-
-		// reflect axis extremes in the export
-		each(['xAxis', 'yAxis'], function (axisType) {
-			each(chart[axisType], function (axis, i) {
-				var axisCopy = chartCopy[axisType][i],
-					extremes = axis.getExtremes(),
-					userMin = extremes.userMin,
-					userMax = extremes.userMax;
-
-				if (userMin !== UNDEFINED || userMax !== UNDEFINED) {
-					axisCopy.setExtremes(userMin, userMax, true, false);
-				}
-			});
-		});
-
-		// get the SVG from the container's innerHTML
-		svg = chartCopy.container.innerHTML;
-
-		// free up memory
-		options = null;
-		chartCopy.destroy();
-		discardElement(sandbox);
-
-		// sanitize
-		svg = svg
-			.replace(/zIndex="[^"]+"/g, '')
-			.replace(/isShadow="[^"]+"/g, '')
-			.replace(/symbolName="[^"]+"/g, '')
-			.replace(/jQuery[0-9]+="[^"]+"/g, '')
-			.replace(/isTracker="[^"]+"/g, '')
-			.replace(/url\([^#]+#/g, 'url(#')
-			.replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"; ')
-			.replace(/ href=/g, ' xlink:href=')
-			/*.replace(/preserveAspectRatio="none">/g, 'preserveAspectRatio="none"/>')*/
-			/* This fails in IE < 8
-			.replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
-				return s2 +'.'+ s3[0];
-			})*/
-
-			// Replace HTML entities, issue #347
-			.replace(/&nbsp;/g, '\u00A0') // no-break space
-			.replace(/&shy;/g,  '\u00AD') // soft hyphen
-
-			// IE specific
-			.replace(/id=([^" >]+)/g, 'id="$1"')
-			.replace(/class=([^" ]+)/g, 'class="$1"')
-			.replace(/ transform /g, ' ')
-			.replace(/:(path|rect)/g, '$1')
-			.replace(/<img ([^>]*)>/gi, '<image $1 />')
-			.replace(/<\/image>/g, '') // remove closing tags for images as they'll never have any content
-			.replace(/<image ([^>]*)([^\/])>/gi, '<image $1$2 />') // closes image tags for firefox
-			.replace(/width=(\d+)/g, 'width="$1"')
-			.replace(/height=(\d+)/g, 'height="$1"')
-			.replace(/hc-svg-href="/g, 'xlink:href="')
-			.replace(/style="([^"]+)"/g, function (s) {
-				return s.toLowerCase();
-			});
-
-		// IE9 beta bugs with innerHTML. Test again with final IE9.
-		svg = svg.replace(/(url\(#highcharts-[0-9]+)&quot;/g, '$1')
-			.replace(/&quot;/g, "'");
-		if (svg.match(/ xmlns="/g).length === 2) {
-			svg = svg.replace(/xmlns="[^"]+"/, '');
-		}
-
-		return svg;
-	},
-
-	/**
-	 * Submit the SVG representation of the chart to the server
-	 * @param {Object} options Exporting options. Possible members are url, type and width.
-	 * @param {Object} chartOptions Additional chart options for the SVG representation of the chart
-	 */
-	exportChart: function (options, chartOptions) {
-		var form,
-			chart = this,
-			svg = chart.getSVG(chartOptions);
-
-		// merge the options
-		options = merge(chart.options.exporting, options);
-
-		// create the form
-		form = createElement('form', {
-			method: 'post',
-			action: options.url
-		}, {
-			display: NONE
-		}, doc.body);
-
-		// add the values
-		each(['filename', 'type', 'width', 'svg'], function (name) {
-			createElement('input', {
-				type: HIDDEN,
-				name: name,
-				value: {
-					filename: options.filename || 'chart',
-					type: options.type,
-					width: options.width,
-					svg: svg
-				}[name]
-			}, null, form);
-		});
-
-		// submit
-		form.submit();
-
-		// clean up
-		discardElement(form);
-	},
-
-	/**
-	 * Print the chart
-	 */
-	print: function () {
-
-		var chart = this,
-			container = chart.container,
-			origDisplay = [],
-			origParent = container.parentNode,
-			body = doc.body,
-			childNodes = body.childNodes;
-
-		if (chart.isPrinting) { // block the button while in printing mode
-			return;
-		}
-
-		chart.isPrinting = true;
-
-		// hide all body content
-		each(childNodes, function (node, i) {
-			if (node.nodeType === 1) {
-				origDisplay[i] = node.style.display;
-				node.style.display = NONE;
-			}
-		});
-
-		// pull out the chart
-		body.appendChild(container);
-
-		// print
-		win.print();
-
-		// allow the browser to prepare before reverting
-		setTimeout(function () {
-
-			// put the chart back in
-			origParent.appendChild(container);
-
-			// restore all body content
-			each(childNodes, function (node, i) {
-				if (node.nodeType === 1) {
-					node.style.display = origDisplay[i];
-				}
-			});
-
-			chart.isPrinting = false;
-
-		}, 1000);
-
-	},
-
-	/**
-	 * Display a popup menu for choosing the export type
-	 *
-	 * @param {String} name An identifier for the menu
-	 * @param {Array} items A collection with text and onclicks for the items
-	 * @param {Number} x The x position of the opener button
-	 * @param {Number} y The y position of the opener button
-	 * @param {Number} width The width of the opener button
-	 * @param {Number} height The height of the opener button
-	 */
-	contextMenu: function (name, items, x, y, width, height) {
-		var chart = this,
-			navOptions = chart.options.navigation,
-			menuItemStyle = navOptions.menuItemStyle,
-			chartWidth = chart.chartWidth,
-			chartHeight = chart.chartHeight,
-			cacheName = 'cache-' + name,
-			menu = chart[cacheName],
-			menuPadding = mathMax(width, height), // for mouse leave detection
-			boxShadow = '3px 3px 10px #888',
-			innerMenu,
-			hide,
-			menuStyle;
-
-		// create the menu only the first time
-		if (!menu) {
-
-			// create a HTML element above the SVG
-			chart[cacheName] = menu = createElement(DIV, {
-				className: PREFIX + name
-			}, {
-				position: ABSOLUTE,
-				zIndex: 1000,
-				padding: menuPadding + PX
-			}, chart.container);
-
-			innerMenu = createElement(DIV, null,
-				extend({
-					MozBoxShadow: boxShadow,
-					WebkitBoxShadow: boxShadow,
-					boxShadow: boxShadow
-				}, navOptions.menuStyle), menu);
-
-			// hide on mouse out
-			hide = function () {
-				css(menu, { display: NONE });
-			};
-
-			addEvent(menu, 'mouseleave', hide);
-
-
-			// create the items
-			each(items, function (item) {
-				if (item) {
-					var div = createElement(DIV, {
-						onmouseover: function () {
-							css(this, navOptions.menuItemHoverStyle);
-						},
-						onmouseout: function () {
-							css(this, menuItemStyle);
-						},
-						innerHTML: item.text || chart.options.lang[item.textKey]
-					}, extend({
-						cursor: 'pointer'
-					}, menuItemStyle), innerMenu);
-
-					div[hasTouch ? 'ontouchstart' : 'onclick'] = function () {
-						hide();
-						item.onclick.apply(chart, arguments);
-					};
-
-					// Keep references to menu divs to be able to destroy them
-					chart.exportDivElements.push(div);
-				}
-			});
-
-			// Keep references to menu and innerMenu div to be able to destroy them
-			chart.exportDivElements.push(innerMenu, menu);
-
-			chart.exportMenuWidth = menu.offsetWidth;
-			chart.exportMenuHeight = menu.offsetHeight;
-		}
-
-		menuStyle = { display: 'block' };
-
-		// if outside right, right align it
-		if (x + chart.exportMenuWidth > chartWidth) {
-			menuStyle.right = (chartWidth - x - width - menuPadding) + PX;
-		} else {
-			menuStyle.left = (x - menuPadding) + PX;
-		}
-		// if outside bottom, bottom align it
-		if (y + height + chart.exportMenuHeight > chartHeight) {
-			menuStyle.bottom = (chartHeight - y - menuPadding)  + PX;
-		} else {
-			menuStyle.top = (y + height - menuPadding) + PX;
-		}
-
-		css(menu, menuStyle);
-	},
-
-	/**
-	 * Add the export button to the chart
-	 */
-	addButton: function (options) {
-		var chart = this,
-			renderer = chart.renderer,
-			btnOptions = merge(chart.options.navigation.buttonOptions, options),
-			onclick = btnOptions.onclick,
-			menuItems = btnOptions.menuItems,
-			/*position = chart.getAlignment(btnOptions),
-			buttonLeft = position.x,
-			buttonTop = position.y,*/
-			buttonWidth = btnOptions.width,
-			buttonHeight = btnOptions.height,
-			box,
-			symbol,
-			button,
-			borderWidth = btnOptions.borderWidth,
-			boxAttr = {
-				stroke: btnOptions.borderColor
-
-			},
-			symbolAttr = {
-				stroke: btnOptions.symbolStroke,
-				fill: btnOptions.symbolFill
-			};
-
-		// Keeps references to the button elements
-		if (!chart.exportDivElements) {
-			chart.exportDivElements = [];
-			chart.exportSVGElements = [];
-		}
-
-		if (btnOptions.enabled === false) {
-			return;
-		}
-
-		// element to capture the click
-		function revert() {
-			symbol.attr(symbolAttr);
-			box.attr(boxAttr);
-		}
-
-		// the box border
-		box = renderer.rect(
-			0,
-			0,
-			buttonWidth,
-			buttonHeight,
-			btnOptions.borderRadius,
-			borderWidth
-		)
-		//.translate(buttonLeft, buttonTop) // to allow gradients
-		.align(btnOptions, true)
-		.attr(extend({
-			fill: btnOptions.backgroundColor,
-			'stroke-width': borderWidth,
-			zIndex: 19
-		}, boxAttr)).add();
-
-		// the invisible element to track the clicks
-		button = renderer.rect(
-				0,
-				0,
-				buttonWidth,
-				buttonHeight,
-				0
-			)
-			.align(btnOptions)
-			.attr({
-				id: btnOptions._id,
-				fill: 'rgba(255, 255, 255, 0.001)',
-				title: chart.options.lang[btnOptions._titleKey],
-				zIndex: 21
-			}).css({
-				cursor: 'pointer'
-			})
-			.on('mouseover', function () {
-				symbol.attr({
-					stroke: btnOptions.hoverSymbolStroke,
-					fill: btnOptions.hoverSymbolFill
-				});
-				box.attr({
-					stroke: btnOptions.hoverBorderColor
-				});
-			})
-			.on('mouseout', revert)
-			.on('click', revert)
-			.add();
-
-		//addEvent(button.element, 'click', revert);
-
-		// add the click event
-		if (menuItems) {
-			onclick = function () {
-				revert();
-				var bBox = button.getBBox();
-				chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);
-			};
-		}
-		/*addEvent(button.element, 'click', function() {
-			onclick.apply(chart, arguments);
-		});*/
-		button.on('click', function () {
-			onclick.apply(chart, arguments);
-		});
-
-		// the icon
-		symbol = renderer.symbol(
-				btnOptions.symbol,
-				btnOptions.symbolX,
-				btnOptions.symbolY,
-				(btnOptions.symbolSize || 12) / 2
-			)
-			.align(btnOptions, true)
-			.attr(extend(symbolAttr, {
-				'stroke-width': btnOptions.symbolStrokeWidth || 1,
-				zIndex: 20
-			})).add();
-
-		// Keep references to the renderer element so to be able to destroy them later.
-		chart.exportSVGElements.push(box, button, symbol);
-	},
-
-	/**
-	 * Destroy the buttons.
-	 */
-	destroyExport: function () {
-		var i,
-			chart = this,
-			elem;
-
-		// Destroy the extra buttons added
-		for (i = 0; i < chart.exportSVGElements.length; i++) {
-			elem = chart.exportSVGElements[i];
-			// Destroy and null the svg/vml elements
-			elem.onclick = elem.ontouchstart = null;
-			chart.exportSVGElements[i] = elem.destroy();
-		}
-
-		// Destroy the divs for the menu
-		for (i = 0; i < chart.exportDivElements.length; i++) {
-			elem = chart.exportDivElements[i];
-
-			// Remove the event handler
-			removeEvent(elem, 'mouseleave');
-
-			// Remove inline events
-			chart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null;
-
-			// Destroy the div by moving to garbage bin
-			discardElement(elem);
-		}
-	}
-});
-
-// Create the export icon
-HC.Renderer.prototype.symbols.exportIcon = function (x, y, radius) {
-	return [
-		M, // the disk
-		x - radius, y + radius,
-		L,
-		x + radius, y + radius,
-		x + radius, y + radius * 0.5,
-		x - radius, y + radius * 0.5,
-		'Z',
-		M, // the arrow
-		x, y + radius * 0.5,
-		L,
-		x - radius * 0.5, y - radius / 3,
-		x - radius / 6, y - radius / 3,
-		x - radius / 6, y - radius,
-		x + radius / 6, y - radius,
-		x + radius / 6, y - radius / 3,
-		x + radius * 0.5, y - radius / 3,
-		'Z'
-	];
-};
-// Create the print icon
-HC.Renderer.prototype.symbols.printIcon = function (x, y, radius) {
-	return [
-		M, // the printer
-		x - radius, y + radius * 0.5,
-		L,
-		x + radius, y + radius * 0.5,
-		x + radius, y - radius / 3,
-		x - radius, y - radius / 3,
-		'Z',
-		M, // the upper sheet
-		x - radius * 0.5, y - radius / 3,
-		L,
-		x - radius * 0.5, y - radius,
-		x + radius * 0.5, y - radius,
-		x + radius * 0.5, y - radius / 3,
-		'Z',
-		M, // the lower sheet
-		x - radius * 0.5, y + radius * 0.5,
-		L,
-		x - radius * 0.75, y + radius,
-		x + radius * 0.75, y + radius,
-		x + radius * 0.5, y + radius * 0.5,
-		'Z'
-	];
-};
-
-
-// Add the buttons on chart load
-Chart.prototype.callbacks.push(function (chart) {
-	var n,
-		exportingOptions = chart.options.exporting,
-		buttons = exportingOptions.buttons;
-
-	if (exportingOptions.enabled !== false) {
-
-		for (n in buttons) {
-			chart.addButton(buttons[n]);
-		}
-
-		// Destroy the export elements at chart destroy
-		addEvent(chart, 'destroy', chart.destroyExport);
-	}
-
-});
-
-
-}());

=== removed directory 'media/js/highcharts_219/themes'
=== removed file 'media/js/highcharts_219/themes/dark-blue.js'
--- media/js/highcharts_219/themes/dark-blue.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/themes/dark-blue.js	1970-01-01 00:00:00 +0000
@@ -1,263 +0,0 @@
-/**
- * Dark blue theme for Highcharts JS
- * @author Torstein Hønsi
- */
-
-Highcharts.theme = {
-	colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
-		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
-	chart: {
-		backgroundColor: {
-			linearGradient: [0, 0, 250, 500],
-			stops: [
-				[0, 'rgb(48, 48, 96)'],
-				[1, 'rgb(0, 0, 0)']
-			]
-		},
-		borderColor: '#000000',
-		borderWidth: 2,
-		className: 'dark-container',
-		plotBackgroundColor: 'rgba(255, 255, 255, .1)',
-		plotBorderColor: '#CCCCCC',
-		plotBorderWidth: 1
-	},
-	title: {
-		style: {
-			color: '#C0C0C0',
-			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	subtitle: {
-		style: {
-			color: '#666666',
-			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	xAxis: {
-		gridLineColor: '#333333',
-		gridLineWidth: 1,
-		labels: {
-			style: {
-				color: '#A0A0A0'
-			}
-		},
-		lineColor: '#A0A0A0',
-		tickColor: '#A0A0A0',
-		title: {
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-
-			}
-		}
-	},
-	yAxis: {
-		gridLineColor: '#333333',
-		labels: {
-			style: {
-				color: '#A0A0A0'
-			}
-		},
-		lineColor: '#A0A0A0',
-		minorTickInterval: null,
-		tickColor: '#A0A0A0',
-		tickWidth: 1,
-		title: {
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-			}
-		}
-	},
-	tooltip: {
-		backgroundColor: 'rgba(0, 0, 0, 0.75)',
-		style: {
-			color: '#F0F0F0'
-		}
-	},
-	toolbar: {
-		itemStyle: {
-			color: 'silver'
-		}
-	},
-	plotOptions: {
-		line: {
-			dataLabels: {
-				color: '#CCC'
-			},
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		spline: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		scatter: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		candlestick: {
-			lineColor: 'white'
-		}
-	},
-	legend: {
-		itemStyle: {
-			font: '9pt Trebuchet MS, Verdana, sans-serif',
-			color: '#A0A0A0'
-		},
-		itemHoverStyle: {
-			color: '#FFF'
-		},
-		itemHiddenStyle: {
-			color: '#444'
-		}
-	},
-	credits: {
-		style: {
-			color: '#666'
-		}
-	},
-	labels: {
-		style: {
-			color: '#CCC'
-		}
-	},
-
-	navigation: {
-		buttonOptions: {
-			backgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#606060'],
-					[0.6, '#333333']
-				]
-			},
-			borderColor: '#000000',
-			symbolStroke: '#C0C0C0',
-			hoverSymbolStroke: '#FFFFFF'
-		}
-	},
-
-	exporting: {
-		buttons: {
-			exportButton: {
-				symbolFill: '#55BE3B'
-			},
-			printButton: {
-				symbolFill: '#7797BE'
-			}
-		}
-	},
-
-	// scroll charts
-	rangeSelector: {
-		buttonTheme: {
-			fill: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-			stroke: '#000000',
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold'
-			},
-			states: {
-				hover: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.4, '#BBB'],
-							[0.6, '#888']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'white'
-					}
-				},
-				select: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.1, '#000'],
-							[0.3, '#333']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'yellow'
-					}
-				}
-			}
-		},
-		inputStyle: {
-			backgroundColor: '#333',
-			color: 'silver'
-		},
-		labelStyle: {
-			color: 'silver'
-		}
-	},
-
-	navigator: {
-		handles: {
-			backgroundColor: '#666',
-			borderColor: '#AAA'
-		},
-		outlineColor: '#CCC',
-		maskFill: 'rgba(16, 16, 16, 0.5)',
-		series: {
-			color: '#7798BF',
-			lineColor: '#A6C7ED'
-		}
-	},
-
-	scrollbar: {
-		barBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		barBorderColor: '#CCC',
-		buttonArrowColor: '#CCC',
-		buttonBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		buttonBorderColor: '#CCC',
-		rifleColor: '#FFF',
-		trackBackgroundColor: {
-			linearGradient: [0, 0, 0, 10],
-			stops: [
-				[0, '#000'],
-				[1, '#333']
-			]
-		},
-		trackBorderColor: '#666'
-	},
-
-	// special colors for some of the
-	legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
-	legendBackgroundColorSolid: 'rgb(35, 35, 70)',
-	dataLabelsColor: '#444',
-	textColor: '#C0C0C0',
-	maskColor: 'rgba(255,255,255,0.3)'
-};
-
-// Apply the theme
-var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
\ No newline at end of file

=== removed file 'media/js/highcharts_219/themes/dark-green.js'
--- media/js/highcharts_219/themes/dark-green.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/themes/dark-green.js	1970-01-01 00:00:00 +0000
@@ -1,263 +0,0 @@
-/**
- * Dark blue theme for Highcharts JS
- * @author Torstein Hønsi
- */
-
-Highcharts.theme = {
-	colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
-		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
-	chart: {
-		backgroundColor: {
-			linearGradient: [0, 0, 250, 500],
-			stops: [
-				[0, 'rgb(48, 96, 48)'],
-				[1, 'rgb(0, 0, 0)']
-			]
-		},
-		borderColor: '#000000',
-		borderWidth: 2,
-		className: 'dark-container',
-		plotBackgroundColor: 'rgba(255, 255, 255, .1)',
-		plotBorderColor: '#CCCCCC',
-		plotBorderWidth: 1
-	},
-	title: {
-		style: {
-			color: '#C0C0C0',
-			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	subtitle: {
-		style: {
-			color: '#666666',
-			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	xAxis: {
-		gridLineColor: '#333333',
-		gridLineWidth: 1,
-		labels: {
-			style: {
-				color: '#A0A0A0'
-			}
-		},
-		lineColor: '#A0A0A0',
-		tickColor: '#A0A0A0',
-		title: {
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-
-			}
-		}
-	},
-	yAxis: {
-		gridLineColor: '#333333',
-		labels: {
-			style: {
-				color: '#A0A0A0'
-			}
-		},
-		lineColor: '#A0A0A0',
-		minorTickInterval: null,
-		tickColor: '#A0A0A0',
-		tickWidth: 1,
-		title: {
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-			}
-		}
-	},
-	tooltip: {
-		backgroundColor: 'rgba(0, 0, 0, 0.75)',
-		style: {
-			color: '#F0F0F0'
-		}
-	},
-	toolbar: {
-		itemStyle: {
-			color: 'silver'
-		}
-	},
-	plotOptions: {
-		line: {
-			dataLabels: {
-				color: '#CCC'
-			},
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		spline: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		scatter: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		candlestick: {
-			lineColor: 'white'
-		}
-	},
-	legend: {
-		itemStyle: {
-			font: '9pt Trebuchet MS, Verdana, sans-serif',
-			color: '#A0A0A0'
-		},
-		itemHoverStyle: {
-			color: '#FFF'
-		},
-		itemHiddenStyle: {
-			color: '#444'
-		}
-	},
-	credits: {
-		style: {
-			color: '#666'
-		}
-	},
-	labels: {
-		style: {
-			color: '#CCC'
-		}
-	},
-
-	navigation: {
-		buttonOptions: {
-			backgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#606060'],
-					[0.6, '#333333']
-				]
-			},
-			borderColor: '#000000',
-			symbolStroke: '#C0C0C0',
-			hoverSymbolStroke: '#FFFFFF'
-		}
-	},
-
-	exporting: {
-		buttons: {
-			exportButton: {
-				symbolFill: '#55BE3B'
-			},
-			printButton: {
-				symbolFill: '#7797BE'
-			}
-		}
-	},
-
-	// scroll charts
-	rangeSelector: {
-		buttonTheme: {
-			fill: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-			stroke: '#000000',
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold'
-			},
-			states: {
-				hover: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.4, '#BBB'],
-							[0.6, '#888']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'white'
-					}
-				},
-				select: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.1, '#000'],
-							[0.3, '#333']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'yellow'
-					}
-				}
-			}
-		},
-		inputStyle: {
-			backgroundColor: '#333',
-			color: 'silver'
-		},
-		labelStyle: {
-			color: 'silver'
-		}
-	},
-
-	navigator: {
-		handles: {
-			backgroundColor: '#666',
-			borderColor: '#AAA'
-		},
-		outlineColor: '#CCC',
-		maskFill: 'rgba(16, 16, 16, 0.5)',
-		series: {
-			color: '#7798BF',
-			lineColor: '#A6C7ED'
-		}
-	},
-
-	scrollbar: {
-		barBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		barBorderColor: '#CCC',
-		buttonArrowColor: '#CCC',
-		buttonBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		buttonBorderColor: '#CCC',
-		rifleColor: '#FFF',
-		trackBackgroundColor: {
-			linearGradient: [0, 0, 0, 10],
-			stops: [
-				[0, '#000'],
-				[1, '#333']
-			]
-		},
-		trackBorderColor: '#666'
-	},
-
-	// special colors for some of the
-	legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
-	legendBackgroundColorSolid: 'rgb(35, 35, 70)',
-	dataLabelsColor: '#444',
-	textColor: '#C0C0C0',
-	maskColor: 'rgba(255,255,255,0.3)'
-};
-
-// Apply the theme
-var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
\ No newline at end of file

=== removed file 'media/js/highcharts_219/themes/gray.js'
--- media/js/highcharts_219/themes/gray.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/themes/gray.js	1970-01-01 00:00:00 +0000
@@ -1,262 +0,0 @@
-/**
- * Gray theme for Highcharts JS
- * @author Torstein Hønsi
- */
-
-Highcharts.theme = {
-	colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee",
-		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
-	chart: {
-		backgroundColor: {
-			linearGradient: [0, 0, 0, 400],
-			stops: [
-				[0, 'rgb(96, 96, 96)'],
-				[1, 'rgb(16, 16, 16)']
-			]
-		},
-		borderWidth: 0,
-		borderRadius: 15,
-		plotBackgroundColor: null,
-		plotShadow: false,
-		plotBorderWidth: 0
-	},
-	title: {
-		style: {
-			color: '#FFF',
-			font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
-		}
-	},
-	subtitle: {
-		style: {
-			color: '#DDD',
-			font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
-		}
-	},
-	xAxis: {
-		gridLineWidth: 0,
-		lineColor: '#999',
-		tickColor: '#999',
-		labels: {
-			style: {
-				color: '#999',
-				fontWeight: 'bold'
-			}
-		},
-		title: {
-			style: {
-				color: '#AAA',
-				font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
-			}
-		}
-	},
-	yAxis: {
-		alternateGridColor: null,
-		minorTickInterval: null,
-		gridLineColor: 'rgba(255, 255, 255, .1)',
-		lineWidth: 0,
-		tickWidth: 0,
-		labels: {
-			style: {
-				color: '#999',
-				fontWeight: 'bold'
-			}
-		},
-		title: {
-			style: {
-				color: '#AAA',
-				font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
-			}
-		}
-	},
-	legend: {
-		itemStyle: {
-			color: '#CCC'
-		},
-		itemHoverStyle: {
-			color: '#FFF'
-		},
-		itemHiddenStyle: {
-			color: '#333'
-		}
-	},
-	labels: {
-		style: {
-			color: '#CCC'
-		}
-	},
-	tooltip: {
-		backgroundColor: {
-			linearGradient: [0, 0, 0, 50],
-			stops: [
-				[0, 'rgba(96, 96, 96, .8)'],
-				[1, 'rgba(16, 16, 16, .8)']
-			]
-		},
-		borderWidth: 0,
-		style: {
-			color: '#FFF'
-		}
-	},
-
-
-	plotOptions: {
-		line: {
-			dataLabels: {
-				color: '#CCC'
-			},
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		spline: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		scatter: {
-			marker: {
-				lineColor: '#333'
-			}
-		},
-		candlestick: {
-			lineColor: 'white'
-		}
-	},
-
-	toolbar: {
-		itemStyle: {
-			color: '#CCC'
-		}
-	},
-
-	navigation: {
-		buttonOptions: {
-			backgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#606060'],
-					[0.6, '#333333']
-				]
-			},
-			borderColor: '#000000',
-			symbolStroke: '#C0C0C0',
-			hoverSymbolStroke: '#FFFFFF'
-		}
-	},
-
-	exporting: {
-		buttons: {
-			exportButton: {
-				symbolFill: '#55BE3B'
-			},
-			printButton: {
-				symbolFill: '#7797BE'
-			}
-		}
-	},
-
-	// scroll charts
-	rangeSelector: {
-		buttonTheme: {
-			fill: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-			stroke: '#000000',
-			style: {
-				color: '#CCC',
-				fontWeight: 'bold'
-			},
-			states: {
-				hover: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.4, '#BBB'],
-							[0.6, '#888']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'white'
-					}
-				},
-				select: {
-					fill: {
-						linearGradient: [0, 0, 0, 20],
-						stops: [
-							[0.1, '#000'],
-							[0.3, '#333']
-						]
-					},
-					stroke: '#000000',
-					style: {
-						color: 'yellow'
-					}
-				}
-			}
-		},
-		inputStyle: {
-			backgroundColor: '#333',
-			color: 'silver'
-		},
-		labelStyle: {
-			color: 'silver'
-		}
-	},
-
-	navigator: {
-		handles: {
-			backgroundColor: '#666',
-			borderColor: '#AAA'
-		},
-		outlineColor: '#CCC',
-		maskFill: 'rgba(16, 16, 16, 0.5)',
-		series: {
-			color: '#7798BF',
-			lineColor: '#A6C7ED'
-		}
-	},
-
-	scrollbar: {
-		barBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		barBorderColor: '#CCC',
-		buttonArrowColor: '#CCC',
-		buttonBackgroundColor: {
-				linearGradient: [0, 0, 0, 20],
-				stops: [
-					[0.4, '#888'],
-					[0.6, '#555']
-				]
-			},
-		buttonBorderColor: '#CCC',
-		rifleColor: '#FFF',
-		trackBackgroundColor: {
-			linearGradient: [0, 0, 0, 10],
-			stops: [
-				[0, '#000'],
-				[1, '#333']
-			]
-		},
-		trackBorderColor: '#666'
-	},
-
-	// special colors for some of the demo examples
-	legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
-	legendBackgroundColorSolid: 'rgb(70, 70, 70)',
-	dataLabelsColor: '#444',
-	textColor: '#E0E0E0',
-	maskColor: 'rgba(255,255,255,0.3)'
-};
-
-// Apply the theme
-var highchartsOptions = Highcharts.setOptions(Highcharts.theme);

=== removed file 'media/js/highcharts_219/themes/grid.js'
--- media/js/highcharts_219/themes/grid.js	2011-11-18 22:51:37 +0000
+++ media/js/highcharts_219/themes/grid.js	1970-01-01 00:00:00 +0000
@@ -1,96 +0,0 @@
-/**
- * Grid theme for Highcharts JS
- * @author Torstein Hønsi
- */
-
-Highcharts.theme = {
-	colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],
-	chart: {
-		backgroundColor: {
-			linearGradient: [0, 0, 500, 500],
-			stops: [
-				[0, 'rgb(255, 255, 255)'],
-				[1, 'rgb(240, 240, 255)']
-			]
-		},
-		borderWidth: 2,
-		plotBackgroundColor: 'rgba(255, 255, 255, .9)',
-		plotShadow: true,
-		plotBorderWidth: 1
-	},
-	title: {
-		style: {
-			color: '#000',
-			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	subtitle: {
-		style: {
-			color: '#666666',
-			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
-		}
-	},
-	xAxis: {
-		gridLineWidth: 1,
-		lineColor: '#000',
-		tickColor: '#000',
-		labels: {
-			style: {
-				color: '#000',
-				font: '11px Trebuchet MS, Verdana, sans-serif'
-			}
-		},
-		title: {
-			style: {
-				color: '#333',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-
-			}
-		}
-	},
-	yAxis: {
-		minorTickInterval: 'auto',
-		lineColor: '#000',
-		lineWidth: 1,
-		tickWidth: 1,
-		tickColor: '#000',
-		labels: {
-			style: {
-				color: '#000',
-				font: '11px Trebuchet MS, Verdana, sans-serif'
-			}
-		},
-		title: {
-			style: {
-				color: '#333',
-				fontWeight: 'bold',
-				fontSize: '12px',
-				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
-			}
-		}
-	},
-	legend: {
-		itemStyle: {
-			font: '9pt Trebuchet MS, Verdana, sans-serif',
-			color: 'black'
-
-		},
-		itemHoverStyle: {
-			color: '#039'
-		},
-		itemHiddenStyle: {
-			color: 'gray'
-		}
-	},
-	labels: {
-		style: {
-			color: '#99b'
-		}
-	}
-};
-
-// Apply the theme
-var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
-

=== removed file 'media/js/hoverIntent.js'
--- media/js/hoverIntent.js	2009-03-21 13:00:37 +0000
+++ media/js/hoverIntent.js	1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-/**
-* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
-* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
-* 
-* @param  f  onMouseOver function || An object with configuration options
-* @param  g  onMouseOut function  || Nothing (use configuration options object)
-* @author    Brian Cherne <brian@xxxxxxxxxx>
-*/
-(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);
\ No newline at end of file

=== removed file 'media/js/jqModal.js'
--- media/js/jqModal.js	2009-04-05 16:28:57 +0000
+++ media/js/jqModal.js	1970-01-01 00:00:00 +0000
@@ -1,100 +0,0 @@
-/*
- * jqModal - Minimalist Modaling with jQuery
- *   (http://dev.iceburg.net/jquery/jqModal/)
- *
- * Copyright (c) 2007,2008 Brice Burgess <bhb@xxxxxxxxxxx>
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
- * 
- * $Version: 03/01/2009 +r14
- */
-(function($) {
-$.fn.jqm=function(o){
-var p={
-overlay: 50,
-overlayClass: 'jqmOverlay',
-closeClass: 'jqmClose',
-trigger: '.jqModal',
-ajax: F,
-ajaxText: '',
-target: F,
-modal: F,
-toTop: F,
-onShow: F,
-onHide: F,
-onLoad: F
-};
-return this.each(function(){if(this._jqm)return H[this._jqm].c=$.extend({},H[this._jqm].c,o);s++;this._jqm=s;
-H[s]={c:$.extend(p,$.jqm.params,o),a:F,w:$(this).addClass('jqmID'+s),s:s};
-if(p.trigger)$(this).jqmAddTrigger(p.trigger);
-});};
-
-$.fn.jqmAddClose=function(e){return hs(this,e,'jqmHide');};
-$.fn.jqmAddTrigger=function(e){return hs(this,e,'jqmShow');};
-$.fn.jqmShow=function(t){return this.each(function(){t=t||window.event;$.jqm.open(this._jqm,t);});};
-$.fn.jqmHide=function(t){return this.each(function(){t=t||window.event;$.jqm.close(this._jqm,t)});};
-
-$.jqm = {
-hash:{},
-open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=(parseInt(h.w.css('z-index'))),z=(z>0)?z:3000,o=$('<div></div>').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});if(h.a)return F;h.t=t;h.a=true;h.w.css('z-index',z);
- if(c.modal) {if(!A[0])L('bind');A.push(s);}
- else if(c.overlay > 0)h.w.jqmAddClose(o);
- else o=F;
-
- h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):F;
- if(ie6){$('html,body').css({height:'100%',width:'100%'});if(o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}}
-
- if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u;
-  r.html(c.ajaxText).load(u,function(){if(c.onLoad)c.onLoad.call(this,h);if(cc)h.w.jqmAddClose($(cc,h.w));e(h);});}
- else if(cc)h.w.jqmAddClose($(cc,h.w));
-
- if(c.toTop&&h.o)h.w.before('<span id="jqmP'+h.w[0]._jqm+'"></span>').insertAfter(h.o);	
- (c.onShow)?c.onShow(h):h.w.show();e(h);return F;
-},
-close:function(s){var h=H[s];if(!h.a)return F;h.a=F;
- if(A[0]){A.pop();if(!A[0])L('unbind');}
- if(h.c.toTop&&h.o)$('#jqmP'+h.w[0]._jqm).after(h.w).remove();
- if(h.c.onHide)h.c.onHide(h);else{h.w.hide();if(h.o)h.o.remove();} return F;
-},
-params:{}};
-var s=0,H=$.jqm.hash,A=[],ie6=$.browser.msie&&($.browser.version == "6.0"),F=false,
-i=$('<iframe src="javascript:false;document.write(\'\');" class="jqm"></iframe>').css({opacity:0}),
-e=function(h){if(ie6)if(h.o)h.o.html('<p style="width:100%;height:100%"/>').prepend(i);else if(!$('iframe.jqm',h.w)[0])h.w.prepend(i); f(h);},
-f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(_){}},
-L=function(t){$()[t]("keypress",m)[t]("keydown",m)[t]("mousedown",m);},
-m=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);if(r)f(h);return !r;},
-hs=function(w,t,c){return w.each(function(){var s=this._jqm;$(t).each(function() {
- if(!this[c]){this[c]=[];$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});};
-})(jQuery);/*
- * jqDnR - Minimalistic Drag'n'Resize for jQuery.
- *
- * Copyright (c) 2007 Brice Burgess <bhb@xxxxxxxxxxx>, http://www.iceburg.net
- * Licensed under the MIT License:
- * http://www.opensource.org/licenses/mit-license.php
- * 
- * $Version: 2007.08.19 +r2
- */
-
-(function($){
-$.fn.jqDrag=function(h){return i(this,h,'d');};
-$.fn.jqResize=function(h){return i(this,h,'r');};
-$.jqDnR={dnr:{},e:0,
-drag:function(v){
- if(M.k == 'd')E.css({left:M.X+v.pageX-M.pX,top:M.Y+v.pageY-M.pY});
- else E.css({width:Math.max(v.pageX-M.pX+M.W,0),height:Math.max(v.pageY-M.pY+M.H,0)});
-  return false;},
-stop:function(){E.css('opacity',M.o);$().unbind('mousemove',J.drag).unbind('mouseup',J.stop);}
-};
-var J=$.jqDnR,M=J.dnr,E=J.e,
-i=function(e,h,k){return e.each(function(){h=(h)?$(h,e):e;
- h.bind('mousedown',{e:e,k:k},function(v){var d=v.data,p={};E=d.e;
- // attempt utilization of dimensions plugin to fix IE issues
- if(E.css('position') != 'relative'){try{E.position(p);}catch(e){}}
- M={X:p.left||f('left')||0,Y:p.top||f('top')||0,W:f('width')||E[0].scrollWidth||0,H:f('height')||E[0].scrollHeight||0,pX:v.pageX,pY:v.pageY,k:d.k,o:E.css('opacity')};
- E.css({opacity:0.8});$().mousemove($.jqDnR.drag).mouseup($.jqDnR.stop);
- return false;
- });
-});},
-f=function(k){return parseInt(E.css(k))||false;};
-})(jQuery);
\ No newline at end of file

=== added file 'media/js/jquery-3.2.1.js'
--- media/js/jquery-3.2.1.js	1970-01-01 00:00:00 +0000
+++ media/js/jquery-3.2.1.js	2017-09-23 09:21:04 +0000
@@ -0,0 +1,10253 @@
+/*!
+ * jQuery JavaScript Library v3.2.1
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright JS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-03-20T18:59Z
+ */
+( function( global, factory ) {
+
+	"use strict";
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+		// For CommonJS and CommonJS-like environments where a proper `window`
+		// is present, execute the factory and get jQuery.
+		// For environments that do not have a `window` with a `document`
+		// (such as Node.js), expose a factory as module.exports.
+		// This accentuates the need for the creation of a real `window`.
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info.
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
+
+var arr = [];
+
+var document = window.document;
+
+var getProto = Object.getPrototypeOf;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
+var support = {};
+
+
+
+	function DOMEval( code, doc ) {
+		doc = doc || document;
+
+		var script = doc.createElement( "script" );
+
+		script.text = code;
+		doc.head.appendChild( script ).parentNode.removeChild( script );
+	}
+/* global Symbol */
+// Defining this global in .eslintrc.json would create a danger of using the global
+// unguarded in another place, it seems safer to define global only for this module
+
+
+
+var
+	version = "3.2.1",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android <=4.0 only
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([a-z])/g,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+
+		// Return all the elements in a clean array
+		if ( num == null ) {
+			return slice.call( this );
+		}
+
+		// Return just the one element from the set
+		return num < 0 ? this[ num + this.length ] : this[ num ];
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	each: function( callback ) {
+		return jQuery.each( this, callback );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map( this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		} ) );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ) );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	eq: function( i ) {
+		var len = this.length,
+			j = +i + ( i < 0 ? len : 0 );
+		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor();
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: arr.sort,
+	splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[ 0 ] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+
+		// Skip the boolean and the target
+		target = arguments[ i ] || {};
+		i++;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+		target = {};
+	}
+
+	// Extend jQuery itself if only one argument is passed
+	if ( i === length ) {
+		target = this;
+		i--;
+	}
+
+	for ( ; i < length; i++ ) {
+
+		// Only deal with non-null/undefined values
+		if ( ( options = arguments[ i ] ) != null ) {
+
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+					( copyIsArray = Array.isArray( copy ) ) ) ) {
+
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && Array.isArray( src ) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject( src ) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend( {
+
+	// Unique for each copy of jQuery on the page
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+	// Assume jQuery is ready without the ready module
+	isReady: true,
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	noop: function() {},
+
+	isFunction: function( obj ) {
+		return jQuery.type( obj ) === "function";
+	},
+
+	isWindow: function( obj ) {
+		return obj != null && obj === obj.window;
+	},
+
+	isNumeric: function( obj ) {
+
+		// As of jQuery 3.0, isNumeric is limited to
+		// strings and numbers (primitives or objects)
+		// that can be coerced to finite numbers (gh-2662)
+		var type = jQuery.type( obj );
+		return ( type === "number" || type === "string" ) &&
+
+			// parseFloat NaNs numeric-cast false positives ("")
+			// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+			// subtraction forces infinities to NaN
+			!isNaN( obj - parseFloat( obj ) );
+	},
+
+	isPlainObject: function( obj ) {
+		var proto, Ctor;
+
+		// Detect obvious negatives
+		// Use toString instead of jQuery.type to catch host objects
+		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
+			return false;
+		}
+
+		proto = getProto( obj );
+
+		// Objects with no prototype (e.g., `Object.create( null )`) are plain
+		if ( !proto ) {
+			return true;
+		}
+
+		// Objects with prototype are plain iff they were constructed by a global Object function
+		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
+		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
+	},
+
+	isEmptyObject: function( obj ) {
+
+		/* eslint-disable no-unused-vars */
+		// See https://github.com/eslint/eslint/issues/6125
+		var name;
+
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+
+		// Support: Android <=2.3 only (functionish RegExp)
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call( obj ) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	globalEval: function( code ) {
+		DOMEval( code );
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Support: IE <=9 - 11, Edge 12 - 13
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	each: function( obj, callback ) {
+		var length, i = 0;
+
+		if ( isArrayLike( obj ) ) {
+			length = obj.length;
+			for ( ; i < length; i++ ) {
+				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+					break;
+				}
+			}
+		} else {
+			for ( i in obj ) {
+				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+					break;
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android <=4.0 only
+	trim: function( text ) {
+		return text == null ?
+			"" :
+			( text + "" ).replace( rtrim, "" );
+	},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var ret = results || [];
+
+		if ( arr != null ) {
+			if ( isArrayLike( Object( arr ) ) ) {
+				jQuery.merge( ret,
+					typeof arr === "string" ?
+					[ arr ] : arr
+				);
+			} else {
+				push.call( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		return arr == null ? -1 : indexOf.call( arr, elem, i );
+	},
+
+	// Support: Android <=4.0 only, PhantomJS 1 only
+	// push.apply(_, arraylike) throws on ancient WebKit
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		for ( ; j < len; j++ ) {
+			first[ i++ ] = second[ j ];
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
+			i = 0,
+			length = elems.length,
+			callbackExpect = !invert;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
+			}
+		}
+
+		return matches;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var length, value,
+			i = 0,
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArrayLike( elems ) ) {
+			length = elems.length;
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( i in elems ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var tmp, args, proxy;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	now: Date.now,
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+} );
+
+if ( typeof Symbol === "function" ) {
+	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+	// Support: real iOS 8.2 only (not reproducible in simulator)
+	// `in` check used to prevent JIT error (gh-2145)
+	// hasOwn isn't used here due to false negatives
+	// regarding Nodelist length in IE
+	var length = !!obj && "length" in obj && obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.3.3
+ * https://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-08-08
+ */
+(function( window ) {
+
+var i,
+	support,
+	Expr,
+	getText,
+	isXML,
+	tokenize,
+	compile,
+	select,
+	outermostContext,
+	sortInput,
+	hasDuplicate,
+
+	// Local document vars
+	setDocument,
+	document,
+	docElem,
+	documentIsHTML,
+	rbuggyQSA,
+	rbuggyMatches,
+	matches,
+	contains,
+
+	// Instance-specific data
+	expando = "sizzle" + 1 * new Date(),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf as it's faster than native
+	// https://jsperf.com/thor-indexof-vs-for/5
+	indexOf = function( list, elem ) {
+		var i = 0,
+			len = list.length;
+		for ( ; i < len; i++ ) {
+			if ( list[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+	// Regular expressions
+
+	// http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+
+	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + identifier + ")(?:\\((" +
+		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+		// 1. quoted (capture 3; capture 4 or capture 5)
+		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+		// 2. simple (capture 6)
+		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+		// 3. anything else (capture 2)
+		".*" +
+		")\\)|)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rwhitespace = new RegExp( whitespace + "+", "g" ),
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+	rpseudo = new RegExp( pseudos ),
+	ridentifier = new RegExp( "^" + identifier + "$" ),
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + identifier + ")" ),
+		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+
+	// CSS escapes
+	// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	},
+
+	// CSS string/identifier serialization
+	// https://drafts.csswg.org/cssom/#common-serializing-idioms
+	rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
+	fcssescape = function( ch, asCodePoint ) {
+		if ( asCodePoint ) {
+
+			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+			if ( ch === "\0" ) {
+				return "\uFFFD";
+			}
+
+			// Control characters and (dependent upon position) numbers get escaped as code points
+			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+		}
+
+		// Other potentially-special ASCII characters get backslash-escaped
+		return "\\" + ch;
+	},
+
+	// Used for iframes
+	// See setDocument()
+	// Removing the function wrapper causes a "Permission Denied"
+	// error in IE
+	unloadHandler = function() {
+		setDocument();
+	},
+
+	disabledAncestor = addCombinator(
+		function( elem ) {
+			return elem.disabled === true && ("form" in elem || "label" in elem);
+		},
+		{ dir: "parentNode", next: "legend" }
+	);
+
+// Optimize for push.apply( _, NodeList )
+try {
+	push.apply(
+		(arr = slice.call( preferredDoc.childNodes )),
+		preferredDoc.childNodes
+	);
+	// Support: Android<4.0
+	// Detect silently failing push.apply
+	arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+	push = { apply: arr.length ?
+
+		// Leverage slice if possible
+		function( target, els ) {
+			push_native.apply( target, slice.call(els) );
+		} :
+
+		// Support: IE<9
+		// Otherwise append directly
+		function( target, els ) {
+			var j = target.length,
+				i = 0;
+			// Can't trust NodeList.length
+			while ( (target[j++] = els[i++]) ) {}
+			target.length = j - 1;
+		}
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	var m, i, elem, nid, match, groups, newSelector,
+		newContext = context && context.ownerDocument,
+
+		// nodeType defaults to 9, since context defaults to document
+		nodeType = context ? context.nodeType : 9;
+
+	results = results || [];
+
+	// Return early from calls with invalid selector or context
+	if ( typeof selector !== "string" || !selector ||
+		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+		return results;
+	}
+
+	// Try to shortcut find operations (as opposed to filters) in HTML documents
+	if ( !seed ) {
+
+		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+			setDocument( context );
+		}
+		context = context || document;
+
+		if ( documentIsHTML ) {
+
+			// If the selector is sufficiently simple, try using a "get*By*" DOM method
+			// (excepting DocumentFragment context, where the methods don't exist)
+			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+				// ID selector
+				if ( (m = match[1]) ) {
+
+					// Document context
+					if ( nodeType === 9 ) {
+						if ( (elem = context.getElementById( m )) ) {
+
+							// Support: IE, Opera, Webkit
+							// TODO: identify versions
+							// getElementById can match elements by name instead of ID
+							if ( elem.id === m ) {
+								results.push( elem );
+								return results;
+							}
+						} else {
+							return results;
+						}
+
+					// Element context
+					} else {
+
+						// Support: IE, Opera, Webkit
+						// TODO: identify versions
+						// getElementById can match elements by name instead of ID
+						if ( newContext && (elem = newContext.getElementById( m )) &&
+							contains( context, elem ) &&
+							elem.id === m ) {
+
+							results.push( elem );
+							return results;
+						}
+					}
+
+				// Type selector
+				} else if ( match[2] ) {
+					push.apply( results, context.getElementsByTagName( selector ) );
+					return results;
+
+				// Class selector
+				} else if ( (m = match[3]) && support.getElementsByClassName &&
+					context.getElementsByClassName ) {
+
+					push.apply( results, context.getElementsByClassName( m ) );
+					return results;
+				}
+			}
+
+			// Take advantage of querySelectorAll
+			if ( support.qsa &&
+				!compilerCache[ selector + " " ] &&
+				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+				if ( nodeType !== 1 ) {
+					newContext = context;
+					newSelector = selector;
+
+				// qSA looks outside Element context, which is not what we want
+				// Thanks to Andrew Dupont for this workaround technique
+				// Support: IE <=8
+				// Exclude object elements
+				} else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+					// Capture the context ID, setting it first if necessary
+					if ( (nid = context.getAttribute( "id" )) ) {
+						nid = nid.replace( rcssescape, fcssescape );
+					} else {
+						context.setAttribute( "id", (nid = expando) );
+					}
+
+					// Prefix every selector in the list
+					groups = tokenize( selector );
+					i = groups.length;
+					while ( i-- ) {
+						groups[i] = "#" + nid + " " + toSelector( groups[i] );
+					}
+					newSelector = groups.join( "," );
+
+					// Expand context for sibling selectors
+					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+						context;
+				}
+
+				if ( newSelector ) {
+					try {
+						push.apply( results,
+							newContext.querySelectorAll( newSelector )
+						);
+						return results;
+					} catch ( qsaError ) {
+					} finally {
+						if ( nid === expando ) {
+							context.removeAttribute( "id" );
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created element and returns a boolean result
+ */
+function assert( fn ) {
+	var el = document.createElement("fieldset");
+
+	try {
+		return !!fn( el );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( el.parentNode ) {
+			el.parentNode.removeChild( el );
+		}
+		// release memory in IE
+		el = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = arr.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			a.sourceIndex - b.sourceIndex;
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for :enabled/:disabled
+ * @param {Boolean} disabled true for :disabled; false for :enabled
+ */
+function createDisabledPseudo( disabled ) {
+
+	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
+	return function( elem ) {
+
+		// Only certain elements can match :enabled or :disabled
+		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
+		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
+		if ( "form" in elem ) {
+
+			// Check for inherited disabledness on relevant non-disabled elements:
+			// * listed form-associated elements in a disabled fieldset
+			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
+			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
+			// * option elements in a disabled optgroup
+			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
+			// All such elements have a "form" property.
+			if ( elem.parentNode && elem.disabled === false ) {
+
+				// Option elements defer to a parent optgroup if present
+				if ( "label" in elem ) {
+					if ( "label" in elem.parentNode ) {
+						return elem.parentNode.disabled === disabled;
+					} else {
+						return elem.disabled === disabled;
+					}
+				}
+
+				// Support: IE 6 - 11
+				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
+				return elem.isDisabled === disabled ||
+
+					// Where there is no isDisabled, check manually
+					/* jshint -W018 */
+					elem.isDisabled !== !disabled &&
+						disabledAncestor( elem ) === disabled;
+			}
+
+			return elem.disabled === disabled;
+
+		// Try to winnow out elements that can't be disabled before trusting the disabled property.
+		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
+		// even exist on them, let alone have a boolean value.
+		} else if ( "label" in elem ) {
+			return elem.disabled === disabled;
+		}
+
+		// Remaining elements are neither :enabled nor :disabled
+		return false;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare, subWindow,
+		doc = node ? node.ownerDocument || node : preferredDoc;
+
+	// Return early if doc is invalid or already selected
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Update global variables
+	document = doc;
+	docElem = document.documentElement;
+	documentIsHTML = !isXML( document );
+
+	// Support: IE 9-11, Edge
+	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+	if ( preferredDoc !== document &&
+		(subWindow = document.defaultView) && subWindow.top !== subWindow ) {
+
+		// Support: IE 11, Edge
+		if ( subWindow.addEventListener ) {
+			subWindow.addEventListener( "unload", unloadHandler, false );
+
+		// Support: IE 9 - 10 only
+		} else if ( subWindow.attachEvent ) {
+			subWindow.attachEvent( "onunload", unloadHandler );
+		}
+	}
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties
+	// (excepting IE8 booleans)
+	support.attributes = assert(function( el ) {
+		el.className = "i";
+		return !el.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( el ) {
+		el.appendChild( document.createComment("") );
+		return !el.getElementsByTagName("*").length;
+	});
+
+	// Support: IE<9
+	support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programmatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( el ) {
+		docElem.appendChild( el ).id = expando;
+		return !document.getElementsByName || !document.getElementsByName( expando ).length;
+	});
+
+	// ID filter and find
+	if ( support.getById ) {
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+				var elem = context.getElementById( id );
+				return elem ? [ elem ] : [];
+			}
+		};
+	} else {
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== "undefined" &&
+					elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+
+		// Support: IE 6 - 7 only
+		// getElementById is not reliable as a find shortcut
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+				var node, i, elems,
+					elem = context.getElementById( id );
+
+				if ( elem ) {
+
+					// Verify the id attribute
+					node = elem.getAttributeNode("id");
+					if ( node && node.value === id ) {
+						return [ elem ];
+					}
+
+					// Fall back on getElementsByName
+					elems = context.getElementsByName( id );
+					i = 0;
+					while ( (elem = elems[i++]) ) {
+						node = elem.getAttributeNode("id");
+						if ( node && node.value === id ) {
+							return [ elem ];
+						}
+					}
+				}
+
+				return [];
+			}
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
+				return context.getElementsByTagName( tag );
+
+			// DocumentFragment nodes don't have gEBTN
+			} else if ( support.qsa ) {
+				return context.querySelectorAll( tag );
+			}
+		} :
+
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See https://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( el ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// https://bugs.jquery.com/ticket/12359
+			docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
+				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
+				"<option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( el.querySelectorAll("[msallowcapture^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !el.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+			if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+				rbuggyQSA.push("~=");
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !el.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+
+			// Support: Safari 8+, iOS 8+
+			// https://bugs.webkit.org/show_bug.cgi?id=136851
+			// In-page `selector#id sibling-combinator selector` fails
+			if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
+				rbuggyQSA.push(".#.+[+~]");
+			}
+		});
+
+		assert(function( el ) {
+			el.innerHTML = "<a href='' disabled='disabled'></a>" +
+				"<select disabled='disabled'><option/></select>";
+
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = document.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			el.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( el.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( el.querySelectorAll(":enabled").length !== 2 ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Support: IE9-11+
+			// IE's :disabled selector does not pick up the children of disabled fieldsets
+			docElem.appendChild( el ).disabled = true;
+			if ( el.querySelectorAll(":disabled").length !== 2 ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			el.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( el ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( el, "*" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( el, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully self-exclusive
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === document ? -1 :
+				b === document ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		!compilerCache[ expr + " " ] &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch (e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.escape = function( sel ) {
+	return (sel + "").replace( rcssescape, fcssescape );
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, uniqueCache, outerCache, node, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType,
+						diff = false;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ?
+										node.nodeName.toLowerCase() === name :
+										node.nodeType === 1 ) {
+
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+
+							// Seek `elem` from a previously-cached index
+
+							// ...in a gzip-friendly way
+							node = parent;
+							outerCache = node[ expando ] || (node[ expando ] = {});
+
+							// Support: IE <9 only
+							// Defend against cloned attroperties (jQuery gh-1709)
+							uniqueCache = outerCache[ node.uniqueID ] ||
+								(outerCache[ node.uniqueID ] = {});
+
+							cache = uniqueCache[ type ] || [];
+							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+							diff = nodeIndex && cache[ 2 ];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						} else {
+							// Use previously-cached element index if available
+							if ( useCache ) {
+								// ...in a gzip-friendly way
+								node = elem;
+								outerCache = node[ expando ] || (node[ expando ] = {});
+
+								// Support: IE <9 only
+								// Defend against cloned attroperties (jQuery gh-1709)
+								uniqueCache = outerCache[ node.uniqueID ] ||
+									(outerCache[ node.uniqueID ] = {});
+
+								cache = uniqueCache[ type ] || [];
+								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+								diff = nodeIndex;
+							}
+
+							// xml :nth-child(...)
+							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
+							if ( diff === false ) {
+								// Use the same loop as above to seek `elem` from the start
+								while ( (node = ++nodeIndex && node && node[ dir ] ||
+									(diff = nodeIndex = 0) || start.pop()) ) {
+
+									if ( ( ofType ?
+										node.nodeName.toLowerCase() === name :
+										node.nodeType === 1 ) &&
+										++diff ) {
+
+										// Cache the index of each encountered element
+										if ( useCache ) {
+											outerCache = node[ expando ] || (node[ expando ] = {});
+
+											// Support: IE <9 only
+											// Defend against cloned attroperties (jQuery gh-1709)
+											uniqueCache = outerCache[ node.uniqueID ] ||
+												(outerCache[ node.uniqueID ] = {});
+
+											uniqueCache[ type ] = [ dirruns, diff ];
+										}
+
+										if ( node === elem ) {
+											break;
+										}
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							see

Follow ups