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