Commits

Richard Shea committed bcbf23f

dmochrtit at hello world but no charts yet

Comments (0)

Files changed (25)

 [chartkick](https://github.com/mher/chartkick.py)
 
 
+ChartIt
+-------
+[ChartIt](http://chartit.shutupandship.com/). 
+
+License: The Python code is BSD but django-chartit has dependencies on [jQuery](http://jquery.com/) and [HighCharts](http://www.highcharts.com/products/highcharts). While jQuery is either MIT or LGPL2 HighCharts has the [HightCharts License](http://shop.highsoft.com/highcharts.html) and you have to decide whether you can live with that.
+
+[Full instructions at](http://chartit.shutupandship.com/docs/)
+
+1. `pip install django-chartit`
 
 
 

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/adapters/mootools-adapter.js

+/*
+ Highcharts JS v3.0.5 (2013-08-23)
+ MooTools adapter
+
+ (c) 2010-2013 Torstein Hønsi
+
+ License: www.highcharts.com/license
+*/
+(function(){var e=window,h=document,f=e.MooTools.version.substring(0,3),i=f==="1.2"||f==="1.1",j=i||f==="1.3",g=e.$extend||function(){return Object.append.apply(Object,arguments)};e.HighchartsAdapter={init:function(a){var b=Fx.prototype,c=b.start,d=Fx.Morph.prototype,e=d.compute;b.start=function(b,d){var e=this.element;if(b.d)this.paths=a.init(e,e.d,this.toD);c.apply(this,arguments);return this};d.compute=function(b,c,d){var f=this.paths;if(f)this.element.attr("d",a.step(f[0],f[1],d,this.toD));else return e.apply(this,
+arguments)}},adapterRun:function(a,b){if(b==="width"||b==="height")return parseInt($(a).getStyle(b),10)},getScript:function(a,b){var c=h.getElementsByTagName("head")[0],d=h.createElement("script");d.type="text/javascript";d.src=a;d.onload=b;c.appendChild(d)},animate:function(a,b,c){var d=a.attr,f=c&&c.complete;if(d&&!a.setStyle)a.getStyle=a.attr,a.setStyle=function(){var a=arguments;this.attr.call(this,a[0],a[1][0])},a.$family=function(){return!0};e.HighchartsAdapter.stop(a);c=new Fx.Morph(d?a:$(a),
+g({transition:Fx.Transitions.Quad.easeInOut},c));if(d)c.element=a;if(b.d)c.toD=b.d;f&&c.addEvent("complete",f);c.start(b);a.fx=c},each:function(a,b){return i?$each(a,b):Array.each(a,b)},map:function(a,b){return a.map(b)},grep:function(a,b){return a.filter(b)},inArray:function(a,b,c){return b?b.indexOf(a,c):-1},offset:function(a){a=a.getPosition();return{left:a.x,top:a.y}},extendWithEvents:function(a){a.addEvent||(a.nodeName?$(a):g(a,new Events))},addEvent:function(a,b,c){typeof b==="string"&&(b===
+"unload"&&(b="beforeunload"),e.HighchartsAdapter.extendWithEvents(a),a.addEvent(b,c))},removeEvent:function(a,b,c){typeof a!=="string"&&a.addEvent&&(b?(b==="unload"&&(b="beforeunload"),c?a.removeEvent(b,c):a.removeEvents&&a.removeEvents(b)):a.removeEvents())},fireEvent:function(a,b,c,d){b={type:b,target:a};b=j?new Event(b):new DOMEvent(b);b=g(b,c);if(!b.target&&b.event)b.target=b.event.target;b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)},washMouseEvent:function(a){if(a.page)a.pageX=
+a.page.x,a.pageY=a.page.y;return a},stop:function(a){a.fx&&a.fx.cancel()}}})();

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/adapters/mootools-adapter.src.js

+/**
+ * @license Highcharts JS v3.0.5 (2013-08-23)
+ * MooTools adapter
+ *
+ * (c) 2010-2013 Torstein Hønsi
+ *
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */
+
+(function () {
+
+var win = window,
+	doc = document,
+	mooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number
+	legacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not.
+	legacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent.
+	$extend = win.$extend || function () {
+		return Object.append.apply(Object, arguments);
+	};
+
+win.HighchartsAdapter = {
+	/**
+	 * Initialize the adapter. This is run once as Highcharts is first run.
+	 * @param {Object} pathAnim The helper object to do animations across adapters.
+	 */
+	init: function (pathAnim) {
+		var fxProto = Fx.prototype,
+			fxStart = fxProto.start,
+			morphProto = Fx.Morph.prototype,
+			morphCompute = morphProto.compute;
+
+		// override Fx.start to allow animation of SVG element wrappers
+		/*jslint unparam: true*//* allow unused parameters in fx functions */
+		fxProto.start = function (from, to) {
+			var fx = this,
+				elem = fx.element;
+
+			// special for animating paths
+			if (from.d) {
+				//this.fromD = this.element.d.split(' ');
+				fx.paths = pathAnim.init(
+					elem,
+					elem.d,
+					fx.toD
+				);
+			}
+			fxStart.apply(fx, arguments);
+
+			return this; // chainable
+		};
+
+		// override Fx.step to allow animation of SVG element wrappers
+		morphProto.compute = function (from, to, delta) {
+			var fx = this,
+				paths = fx.paths;
+
+			if (paths) {
+				fx.element.attr(
+					'd',
+					pathAnim.step(paths[0], paths[1], delta, fx.toD)
+				);
+			} else {
+				return morphCompute.apply(fx, arguments);
+			}
+		};
+		/*jslint unparam: false*/
+	},
+	
+	/**
+	 * Run a general method on the framework, following jQuery syntax
+	 * @param {Object} el The HTML element
+	 * @param {String} method Which method to run on the wrapped element
+	 */
+	adapterRun: function (el, method) {
+		
+		// This currently works for getting inner width and height. If adding
+		// more methods later, we need a conditional implementation for each.
+		if (method === 'width' || method === 'height') {
+			return parseInt($(el).getStyle(method), 10);
+		}
+	},
+
+	/**
+	 * Downloads a script and executes a callback when done.
+	 * @param {String} scriptLocation
+	 * @param {Function} callback
+	 */
+	getScript: function (scriptLocation, callback) {
+		// We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script.
+		var head = doc.getElementsByTagName('head')[0];
+		var script = doc.createElement('script');
+
+		script.type = 'text/javascript';
+		script.src = scriptLocation;
+		script.onload = callback;
+
+		head.appendChild(script);
+	},
+
+	/**
+	 * Animate a HTML element or SVG element wrapper
+	 * @param {Object} el
+	 * @param {Object} params
+	 * @param {Object} options jQuery-like animation options: duration, easing, callback
+	 */
+	animate: function (el, params, options) {
+		var isSVGElement = el.attr,
+			effect,
+			complete = options && options.complete;
+
+		if (isSVGElement && !el.setStyle) {
+			// add setStyle and getStyle methods for internal use in Moo
+			el.getStyle = el.attr;
+			el.setStyle = function () { // property value is given as array in Moo - break it down
+				var args = arguments;
+				this.attr.call(this, args[0], args[1][0]);
+			};
+			// dirty hack to trick Moo into handling el as an element wrapper
+			el.$family = function () { return true; };
+		}
+
+		// stop running animations
+		win.HighchartsAdapter.stop(el);
+
+		// define and run the effect
+		effect = new Fx.Morph(
+			isSVGElement ? el : $(el),
+			$extend({
+				transition: Fx.Transitions.Quad.easeInOut
+			}, options)
+		);
+
+		// Make sure that the element reference is set when animating svg elements
+		if (isSVGElement) {
+			effect.element = el;
+		}
+
+		// special treatment for paths
+		if (params.d) {
+			effect.toD = params.d;
+		}
+
+		// jQuery-like events
+		if (complete) {
+			effect.addEvent('complete', complete);
+		}
+
+		// run
+		effect.start(params);
+
+		// record for use in stop method
+		el.fx = effect;
+	},
+
+	/**
+	 * MooTool's each function
+	 *
+	 */
+	each: function (arr, fn) {
+		return legacy ?
+			$each(arr, fn) :
+			Array.each(arr, fn);
+	},
+
+	/**
+	 * Map an array
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	map: function (arr, fn) {
+		return arr.map(fn);
+	},
+
+	/**
+	 * Grep or filter an array
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	grep: function (arr, fn) {
+		return arr.filter(fn);
+	},
+	
+	/**
+	 * Return the index of an item in an array, or -1 if not matched
+	 */
+	inArray: function (item, arr, from) {
+		return arr ? arr.indexOf(item, from) : -1;
+	},
+
+	/**
+	 * Get the offset of an element relative to the top left corner of the web page
+	 */
+	offset: function (el) {
+		var offsets = el.getPosition(); // #1496
+		return {
+			left: offsets.x,
+			top: offsets.y
+		};
+	},
+
+	/**
+	 * Extends an object with Events, if its not done
+	 */
+	extendWithEvents: function (el) {
+		// if the addEvent method is not defined, el is a custom Highcharts object
+		// like series or point
+		if (!el.addEvent) {
+			if (el.nodeName) {
+				el = $(el); // a dynamically generated node
+			} else {
+				$extend(el, new Events()); // a custom object
+			}
+		}
+	},
+
+	/**
+	 * Add an event listener
+	 * @param {Object} el HTML element or custom object
+	 * @param {String} type Event type
+	 * @param {Function} fn Event handler
+	 */
+	addEvent: function (el, type, fn) {
+		if (typeof type === 'string') { // chart broke due to el being string, type function
+
+			if (type === 'unload') { // Moo self destructs before custom unload events
+				type = 'beforeunload';
+			}
+
+			win.HighchartsAdapter.extendWithEvents(el);
+
+			el.addEvent(type, fn);
+		}
+	},
+
+	removeEvent: function (el, type, fn) {
+		if (typeof el === 'string') {
+			// el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out.
+			return;
+		}
+		
+		if (el.addEvent) { // If el doesn't have an addEvent method, there are no events to remove
+			if (type) {
+				if (type === 'unload') { // Moo self destructs before custom unload events
+					type = 'beforeunload';
+				}
+	
+				if (fn) {
+					el.removeEvent(type, fn);
+				} else if (el.removeEvents) { // #958
+					el.removeEvents(type);
+				}
+			} else {
+				el.removeEvents();
+			}
+		}
+	},
+
+	fireEvent: function (el, event, eventArguments, defaultFunction) {
+		var eventArgs = {
+			type: event,
+			target: el
+		};
+		// create an event object that keeps all functions
+		event = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs);
+		event = $extend(event, eventArguments);
+
+		// When running an event on the Chart.prototype, MooTools nests the target in event.event
+		if (!event.target && event.event) {
+			event.target = event.event.target;
+		}
+
+		// override the preventDefault function to be able to use
+		// this for custom events
+		event.preventDefault = function () {
+			defaultFunction = null;
+		};
+		// if fireEvent is not available on the object, there hasn't been added
+		// any events to it above
+		if (el.fireEvent) {
+			el.fireEvent(event.type, event);
+		}
+
+		// fire the default if it is passed and it is not prevented above
+		if (defaultFunction) {
+			defaultFunction(event);
+		}
+	},
+	
+	/**
+	 * Set back e.pageX and e.pageY that MooTools has abstracted away. #1165, #1346.
+	 */
+	washMouseEvent: function (e) {
+		if (e.page) {
+			e.pageX = e.page.x;
+			e.pageY = e.page.y;
+		}
+		return e;
+	},
+
+	/**
+	 * Stop running animations on the object
+	 */
+	stop: function (el) {
+		if (el.fx) {
+			el.fx.cancel();
+		}
+	}
+};
+
+}());

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/adapters/prototype-adapter.js

+/*
+ Highcharts JS v3.0.5 (2013-08-23)
+ Prototype adapter
+
+ @author Michael Nelson, Torstein Hønsi.
+
+ Feel free to use and modify this script.
+ Highcharts license: www.highcharts.com/license.
+*/
+var HighchartsAdapter=function(){var f=typeof Effect!=="undefined";return{init:function(a){if(f)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(b,c,d,g){var e;this.element=b;this.key=c;e=b.attr?b.attr(c):$(b).getStyle(c);if(c==="d")this.paths=a.init(b,b.d,d),this.toD=d,e=0,d=1;this.start(Object.extend(g||{},{from:e,to:d,attribute:c}))},setup:function(){HighchartsAdapter._extend(this.element);if(!this.element._highchart_animation)this.element._highchart_animation={};this.element._highchart_animation[this.key]=
+this},update:function(b){var c=this.paths,d=this.element;c&&(b=a.step(c[0],c[1],b,this.toD));d.attr?d.element&&d.attr(this.options.attribute,b):(c={},c[this.options.attribute]=b,$(d).setStyle(c))},finish:function(){this.element&&this.element._highchart_animation&&delete this.element._highchart_animation[this.key]}})},adapterRun:function(a,b){return parseInt($(a).getStyle(b),10)},getScript:function(a,b){var c=$$("head")[0];c&&c.appendChild((new Element("script",{type:"text/javascript",src:a})).observe("load",
+b))},addNS:function(a){var b=/^(?:click|mouse(?:down|up|over|move|out))$/;return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(a)||b.test(a)?a:"h:"+a},addEvent:function(a,b,c){a.addEventListener||a.attachEvent?Event.observe($(a),HighchartsAdapter.addNS(b),c):(HighchartsAdapter._extend(a),a._highcharts_observe(b,c))},animate:function(a,b,c){var d,c=c||{};c.delay=0;c.duration=(c.duration||500)/1E3;c.afterFinish=c.complete;if(f)for(d in b)new Effect.HighchartsTransition($(a),
+d,b[d],c);else{if(a.attr)for(d in b)a.attr(d,b[d]);c.complete&&c.complete()}a.attr||$(a).setStyle(b)},stop:function(a){var b;if(a._highcharts_extended&&a._highchart_animation)for(b in a._highchart_animation)a._highchart_animation[b].cancel()},each:function(a,b){$A(a).each(b)},inArray:function(a,b,c){return b?b.indexOf(a,c):-1},offset:function(a){return $(a).cumulativeOffset()},fireEvent:function(a,b,c,d){a.fire?a.fire(HighchartsAdapter.addNS(b),c):a._highcharts_extended&&(c=c||{},a._highcharts_fire(b,
+c));c&&c.defaultPrevented&&(d=null);d&&d(c)},removeEvent:function(a,b,c){$(a).stopObserving&&(b&&(b=HighchartsAdapter.addNS(b)),$(a).stopObserving(b,c));window===a?Event.stopObserving(a,b,c):(HighchartsAdapter._extend(a),a._highcharts_stop_observing(b,c))},washMouseEvent:function(a){return a},grep:function(a,b){return a.findAll(b)},map:function(a,b){return a.map(b)},_extend:function(a){a._highcharts_extended||Object.extend(a,{_highchart_events:{},_highchart_animation:null,_highcharts_extended:!0,
+_highcharts_observe:function(b,a){this._highchart_events[b]=[this._highchart_events[b],a].compact().flatten()},_highcharts_stop_observing:function(b,a){b?a?this._highchart_events[b]=[this._highchart_events[b]].compact().flatten().without(a):delete this._highchart_events[b]:this._highchart_events={}},_highcharts_fire:function(a,c){var d=this;(this._highchart_events[a]||[]).each(function(a){if(!c.stopped)c.preventDefault=function(){c.defaultPrevented=!0},c.target=d,a.bind(this)(c)===!1&&c.preventDefault()}.bind(this))}})}}}();

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/adapters/prototype-adapter.src.js

+/**
+ * @license Highcharts JS v3.0.5 (2013-08-23)
+ * Prototype adapter
+ *
+ * @author Michael Nelson, Torstein Hønsi.
+ *
+ * Feel free to use and modify this script.
+ * Highcharts license: www.highcharts.com/license.
+ */
+
+// JSLint options:
+/*global Effect, Class, Event, Element, $, $$, $A */
+
+// Adapter interface between prototype and the Highcharts charting library
+var HighchartsAdapter = (function () {
+
+var hasEffect = typeof Effect !== 'undefined';
+
+return {
+
+	/**
+	 * Initialize the adapter. This is run once as Highcharts is first run.
+	 * @param {Object} pathAnim The helper object to do animations across adapters.
+	 */
+	init: function (pathAnim) {
+		if (hasEffect) {
+			/**
+			 * Animation for Highcharts SVG element wrappers only
+			 * @param {Object} element
+			 * @param {Object} attribute
+			 * @param {Object} to
+			 * @param {Object} options
+			 */
+			Effect.HighchartsTransition = Class.create(Effect.Base, {
+				initialize: function (element, attr, to, options) {
+					var from,
+						opts;
+
+					this.element = element;
+					this.key = attr;
+					from = element.attr ? element.attr(attr) : $(element).getStyle(attr);
+
+					// special treatment for paths
+					if (attr === 'd') {
+						this.paths = pathAnim.init(
+							element,
+							element.d,
+							to
+						);
+						this.toD = to;
+
+
+						// fake values in order to read relative position as a float in update
+						from = 0;
+						to = 1;
+					}
+
+					opts = Object.extend((options || {}), {
+						from: from,
+						to: to,
+						attribute: attr
+					});
+					this.start(opts);
+				},
+				setup: function () {
+					HighchartsAdapter._extend(this.element);
+					// If this is the first animation on this object, create the _highcharts_animation helper that
+					// contain pointers to the animation objects.
+					if (!this.element._highchart_animation) {
+						this.element._highchart_animation = {};
+					}
+
+					// Store a reference to this animation instance.
+					this.element._highchart_animation[this.key] = this;
+				},
+				update: function (position) {
+					var paths = this.paths,
+						element = this.element,
+						obj;
+
+					if (paths) {
+						position = pathAnim.step(paths[0], paths[1], position, this.toD);
+					}
+
+					if (element.attr) { // SVGElement
+						
+						if (element.element) { // If not, it has been destroyed (#1405)
+							element.attr(this.options.attribute, position);
+						}
+					
+					} else { // HTML, #409
+						obj = {};
+						obj[this.options.attribute] = position;
+						$(element).setStyle(obj);
+					}
+					
+				},
+				finish: function () {
+					// Delete the property that holds this animation now that it is finished.
+					// Both canceled animations and complete ones gets a 'finish' call.
+					if (this.element && this.element._highchart_animation) { // #1405
+						delete this.element._highchart_animation[this.key];
+					}
+				}
+			});
+		}
+	},
+	
+	/**
+	 * Run a general method on the framework, following jQuery syntax
+	 * @param {Object} el The HTML element
+	 * @param {String} method Which method to run on the wrapped element
+	 */
+	adapterRun: function (el, method) {
+		
+		// This currently works for getting inner width and height. If adding
+		// more methods later, we need a conditional implementation for each.
+		return parseInt($(el).getStyle(method), 10);
+		
+	},
+
+	/**
+	 * Downloads a script and executes a callback when done.
+	 * @param {String} scriptLocation
+	 * @param {Function} callback
+	 */
+	getScript: function (scriptLocation, callback) {
+		var head = $$('head')[0]; // Returns an array, so pick the first element.
+		if (head) {
+			// Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback
+			head.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback));
+		}
+	},
+
+	/**
+	 * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of
+	 * events that are not recognized as native.
+	 */
+	addNS: function (eventName) {
+		var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
+			MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/;
+		return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ?
+			eventName :
+			'h:' + eventName;
+	},
+
+	// el needs an event to be attached. el is not necessarily a dom element
+	addEvent: function (el, event, fn) {
+		if (el.addEventListener || el.attachEvent) {
+			Event.observe($(el), HighchartsAdapter.addNS(event), fn);
+
+		} else {
+			HighchartsAdapter._extend(el);
+			el._highcharts_observe(event, fn);
+		}
+	},
+
+	// motion makes things pretty. use it if effects is loaded, if not... still get to the end result.
+	animate: function (el, params, options) {
+		var key,
+			fx;
+
+		// default options
+		options = options || {};
+		options.delay = 0;
+		options.duration = (options.duration || 500) / 1000;
+		options.afterFinish = options.complete;
+
+		// animate wrappers and DOM elements
+		if (hasEffect) {
+			for (key in params) {
+				// The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object
+				// on the element itself so its not really lost.
+				fx = new Effect.HighchartsTransition($(el), key, params[key], options);
+			}
+		} else {
+			if (el.attr) { // #409 without effects
+				for (key in params) {
+					el.attr(key, params[key]);
+				}
+			}
+			if (options.complete) {
+				options.complete();
+			}
+		}
+
+		if (!el.attr) { // HTML element, #409
+			$(el).setStyle(params);
+		}
+	},
+
+	// this only occurs in higcharts 2.0+
+	stop: function (el) {
+		var key;
+		if (el._highcharts_extended && el._highchart_animation) {
+			for (key in el._highchart_animation) {
+				// Cancel the animation
+				// The 'finish' function in the Effect object will remove the reference
+				el._highchart_animation[key].cancel();
+			}
+		}
+	},
+
+	// um.. each
+	each: function (arr, fn) {
+		$A(arr).each(fn);
+	},
+	
+	inArray: function (item, arr, from) {
+		return arr ? arr.indexOf(item, from) : -1;
+	},
+
+	/**
+	 * Get the cumulative offset relative to the top left of the page. This method, unlike its
+	 * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position
+	 * of a chart within a fixed container.
+	 */
+	offset: function (el) {
+		return $(el).cumulativeOffset();
+	},
+
+	// fire an event based on an event name (event) and an object (el).
+	// again, el may not be a dom element
+	fireEvent: function (el, event, eventArguments, defaultFunction) {
+		if (el.fire) {
+			el.fire(HighchartsAdapter.addNS(event), eventArguments);
+		} else if (el._highcharts_extended) {
+			eventArguments = eventArguments || {};
+			el._highcharts_fire(event, eventArguments);
+		}
+
+		if (eventArguments && eventArguments.defaultPrevented) {
+			defaultFunction = null;
+		}
+
+		if (defaultFunction) {
+			defaultFunction(eventArguments);
+		}
+	},
+
+	removeEvent: function (el, event, handler) {
+		if ($(el).stopObserving) {
+			if (event) {
+				event = HighchartsAdapter.addNS(event);
+			}
+			$(el).stopObserving(event, handler);
+		} if (window === el) {
+			Event.stopObserving(el, event, handler);
+		} else {
+			HighchartsAdapter._extend(el);
+			el._highcharts_stop_observing(event, handler);
+		}
+	},
+	
+	washMouseEvent: function (e) {
+		return e;
+	},
+
+	// um, grep
+	grep: function (arr, fn) {
+		return arr.findAll(fn);
+	},
+
+	// um, map
+	map: function (arr, fn) {
+		return arr.map(fn);
+	},
+
+	// extend an object to handle highchart events (highchart objects, not svg elements).
+	// this is a very simple way of handling events but whatever, it works (i think)
+	_extend: function (object) {
+		if (!object._highcharts_extended) {
+			Object.extend(object, {
+				_highchart_events: {},
+				_highchart_animation: null,
+				_highcharts_extended: true,
+				_highcharts_observe: function (name, fn) {
+					this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();
+				},
+				_highcharts_stop_observing: function (name, fn) {
+					if (name) {
+						if (fn) {
+							this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);
+						} else {
+							delete this._highchart_events[name];
+						}
+					} else {
+						this._highchart_events = {};
+					}
+				},
+				_highcharts_fire: function (name, args) {
+					var target = this;
+					(this._highchart_events[name] || []).each(function (fn) {
+						// args is never null here
+						if (args.stopped) {
+							return; // "throw $break" wasn't working. i think because of the scope of 'this'.
+						}
+
+						// Attach a simple preventDefault function to skip default handler if called
+						args.preventDefault = function () {
+							args.defaultPrevented = true;
+						};
+						args.target = target;
+
+						// If the event handler return false, prevent the default handler from executing
+						if (fn.bind(this)(args) === false) {
+							args.preventDefault();
+						}
+					}
+.bind(this));
+				}
+			});
+		}
+	}
+};
+}());

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/highcharts-more.js

+/*
+ Highcharts JS v3.0.5 (2013-08-23)
+
+ (c) 2009-2013 Torstein Hønsi
+
+ License: www.highcharts.com/license
+*/
+(function(l,C){function J(a,b,c){this.init.call(this,a,b,c)}function K(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var c=this.xAxis.center;a.push("L",c[0],c[1])},this.closedStacks=!0}function L(a,b){var c=this.chart,d=this.options.animation,g=this.group,f=this.markerGroup,e=this.xAxis.center,i=c.plotLeft,o=c.plotTop;if(c.polar){if(c.renderer.isSVG)if(d===!0&&(d={}),b){if(c={translateX:e[0]+i,translateY:e[1]+o,scaleX:0.001,scaleY:0.001},g.attr(c),f)f.attrSetters=g.attrSetters,
+f.attr(c)}else c={translateX:i,translateY:o,scaleX:1,scaleY:1},g.animate(c,d),f&&f.animate(c,d),this.animate=null}else a.call(this,b)}var P=l.arrayMin,Q=l.arrayMax,r=l.each,F=l.extend,p=l.merge,R=l.map,q=l.pick,v=l.pInt,m=l.getOptions().plotOptions,h=l.seriesTypes,x=l.extendClass,M=l.splat,n=l.wrap,N=l.Axis,u=l.Tick,z=l.Series,t=h.column.prototype,s=Math,D=s.round,A=s.floor,S=s.max,w=function(){};F(J.prototype,{init:function(a,b,c){var d=this,g=d.defaultOptions;d.chart=b;if(b.angular)g.background=
+{};d.options=a=p(g,a);(a=a.background)&&r([].concat(M(a)).reverse(),function(a){var b=a.backgroundColor,a=p(d.defaultBackgroundOptions,a);if(b)a.backgroundColor=b;a.color=a.backgroundColor;c.options.plotBands.unshift(a)})},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"silver",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#FFF"],[1,"#DDD"]]},from:Number.MIN_VALUE,innerRadius:0,to:Number.MAX_VALUE,
+outerRadius:"105%"}});var G=N.prototype,u=u.prototype,T={getOffset:w,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:w,setCategories:w,setTitle:w},O={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:"center",x:0,y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,plotBands:[],tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,
+distance:15,x:0,y:null},maxPadding:0,minPadding:0,plotBands:[],showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},plotBands:[],showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){this.options=p(this.defaultOptions,this.defaultRadialOptions,a)},getOffset:function(){G.getOffset.call(this);this.chart.axisOffset[this.side]=0;this.center=this.pane.center=h.pie.prototype.getCenter.call(this.pane)},getLinePath:function(a,
+b){var c=this.center,b=q(b,c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){G.setAxisTranslation.call(this);if(this.center&&(this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.isXAxis))this.minPixelPadding=this.transA*this.minPointOffset+(this.reversed?(this.endAngleRad-this.startAngleRad)/
+4:0)},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&&1||this.pointRange||this.closestPointRange)},setAxisSize:function(){G.setAxisSize.call(this);if(this.center)this.len=this.width=this.height=this.isCircular?this.center[2]*(this.endAngleRad-this.startAngleRad)/2:this.center[2]/2},getPosition:function(a,b){if(!this.isCircular)b=this.translate(a),a=this.min;return this.postTranslate(this.translate(a),q(b,this.center[2]/2)-this.offset)},postTranslate:function(a,b){var c=
+this.chart,d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,g=this.startAngleRad,f=d[2]/2,e=[q(c.outerRadius,"100%"),c.innerRadius,q(c.thickness,10)],i=/%$/,o,k=this.isCircular;this.options.gridLineInterpolation==="polygon"?d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(k||(e[0]=this.translate(a),e[1]=this.translate(b)),e=R(e,function(a){i.test(a)&&(a=v(a,10)*f/100);return a}),
+c.shape==="circle"||!k?(a=-Math.PI/2,b=Math.PI*1.5,o=!0):(a=g+this.translate(a),b=g+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],e[0],e[0],{start:a,end:b,innerR:q(e[1],e[0]-e[2]),open:o}));return d},getPlotLinePath:function(a,b){var c=this.center,d=this.chart,g=this.getPosition(a),f,e,i;this.isCircular?i=["M",c[0]+d.plotLeft,c[1]+d.plotTop,"L",g.x,g.y]:this.options.gridLineInterpolation==="circle"?(a=this.translate(a))&&(i=this.getLinePath(0,a)):(f=d.xAxis[0],
+i=[],a=this.translate(a),c=f.tickPositions,f.autoConnect&&(c=c.concat([c[0]])),b&&(c=[].concat(c).reverse()),r(c,function(c,b){e=f.getPosition(c,a);i.push(b?"L":"M",e.x,e.y)}));return i},getTitlePosition:function(){var a=this.center,b=this.chart,c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};n(G,"init",function(a,b,c){var j;var d=b.angular,g=b.polar,f=c.isX,e=d&&f,i,o;o=b.options;var k=c.pane||0;if(d){if(F(this,e?T:O),
+i=!f)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else if(g)F(this,O),this.defaultRadialOptions=(i=f)?this.defaultRadialXOptions:p(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!e&&(d||g)){a=this.options;if(!b.panes)b.panes=[];this.pane=(j=b.panes[k]=b.panes[k]||new J(M(o.pane)[k],b,this),k=j);k=k.options;b.inverted=!1;o.chart.zoomType=null;this.startAngleRad=b=(k.startAngle-90)*Math.PI/180;this.endAngleRad=o=(q(k.endAngle,k.startAngle+360)-90)*Math.PI/180;this.offset=
+a.offset||0;if((this.isCircular=i)&&c.max===C&&o-b===2*Math.PI)this.autoConnect=!0}});n(u,"getPosition",function(a,b,c,d,g){var f=this.axis;return f.getPosition?f.getPosition(c):a.call(this,b,c,d,g)});n(u,"getLabelPosition",function(a,b,c,d,g,f,e,i,o){var k=this.axis,j=f.y,h=f.align,l=(k.translate(this.pos)+k.startAngleRad+Math.PI/2)/Math.PI*180%360;k.isRadial?(a=k.getPosition(this.pos,k.center[2]/2+q(f.distance,-25)),f.rotation==="auto"?d.attr({rotation:l}):j===null&&(j=v(d.styles.lineHeight)*0.9-
+d.getBBox().height/2),h===null&&(h=k.isCircular?l>20&&l<160?"left":l>200&&l<340?"right":"center":"center",d.attr({align:h})),a.x+=f.x,a.y+=j):a=a.call(this,b,c,d,g,f,e,i,o);return a});n(u,"getMarkPath",function(a,b,c,d,g,f,e){var i=this.axis;i.isRadial?(a=i.getPosition(this.pos,i.center[2]/2+d),b=["M",b,c,"L",a.x,a.y]):b=a.call(this,b,c,d,g,f,e);return b});m.arearange=p(m.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'},
+trackByArea:!0,dataLabels:{verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0}});h.arearange=l.extendClass(h.area,{type:"arearange",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"low",getSegments:function(){var a=this;r(a.points,function(b){if(!a.options.connectNulls&&(b.low===null||b.high===null))b.y=null;else if(b.low===null&&b.high!==null)b.y=b.high});z.prototype.getSegments.call(this)},translate:function(){var a=this.yAxis;h.area.prototype.translate.apply(this);
+r(this.points,function(b){var c=b.low,d=b.high,g=b.plotY;d===null&&c===null?b.y=null:c===null?(b.plotLow=b.plotY=null,b.plotHigh=a.translate(d,0,1,0,1)):d===null?(b.plotLow=g,b.plotHigh=null):(b.plotLow=g,b.plotHigh=a.translate(d,0,1,0,1))})},getSegmentPath:function(a){var b,c=[],d=a.length,g=z.prototype.getSegmentPath,f,e;e=this.options;var i=e.step;for(b=HighchartsAdapter.grep(a,function(a){return a.plotLow!==null});d--;)f=a[d],f.plotHigh!==null&&c.push({plotX:f.plotX,plotY:f.plotHigh});a=g.call(this,
+b);if(i)i===!0&&(i="left"),e.step={left:"right",center:"center",right:"left"}[i];c=g.call(this,c);e.step=i;e=[].concat(a,c);c[0]="L";this.areaPath=this.areaPath.concat(a,c);return e},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],g=z.prototype,f=this.options.dataLabels,e,i=this.chart.inverted;if(f.enabled||this._hasPointLabels){for(c=b;c--;)e=a[c],e.y=e.high,e.plotY=e.plotHigh,d[c]=e.dataLabel,e.dataLabel=e.dataLabelUpper,e.below=!1,i?(f.align="left",f.x=f.xHigh):f.y=f.yHigh;g.drawDataLabels.apply(this,
+arguments);for(c=b;c--;)e=a[c],e.dataLabelUpper=e.dataLabel,e.dataLabel=d[c],e.y=e.low,e.plotY=e.plotLow,e.below=!0,i?(f.align="right",f.x=f.xLow):f.y=f.yLow;g.drawDataLabels.apply(this,arguments)}},alignDataLabel:h.column.prototype.alignDataLabel,getSymbol:h.column.prototype.getSymbol,drawPoints:w});m.areasplinerange=p(m.arearange);h.areasplinerange=x(h.arearange,{type:"areasplinerange",getPointSpline:h.spline.prototype.getPointSpline});m.columnrange=p(m.column,m.arearange,{lineWidth:1,pointRange:null});
+h.columnrange=x(h.arearange,{type:"columnrange",translate:function(){var a=this,b=a.yAxis,c;t.translate.apply(a);r(a.points,function(d){var g=d.shapeArgs,f=a.options.minPointLength,e;d.plotHigh=c=b.translate(d.high,0,1,0,1);d.plotLow=d.plotY;e=c;d=d.plotY-c;d<f&&(f-=d,d+=f,e-=f/2);g.height=d;g.y=e})},trackerGroups:["group","dataLabels"],drawGraph:w,pointAttrToOptions:t.pointAttrToOptions,drawPoints:t.drawPoints,drawTracker:t.drawTracker,animate:t.animate,getColumnMetrics:t.getColumnMetrics});m.gauge=
+p(m.line,{dataLabels:{enabled:!0,y:15,borderWidth:1,borderColor:"silver",borderRadius:3,style:{fontWeight:"bold"},verticalAlign:"top",zIndex:2},dial:{},pivot:{},tooltip:{headerFormat:""},showInLegend:!1});u={type:"gauge",pointClass:l.extendClass(l.Point,{setState:function(a){this.state=a}}),angular:!0,drawGraph:w,trackerGroups:["group","dataLabels"],translate:function(){var a=this.yAxis,b=this.options,c=a.center;this.generatePoints();r(this.points,function(d){var g=p(b.dial,d.dial),f=v(q(g.radius,
+80))*c[2]/200,e=v(q(g.baseLength,70))*f/100,i=v(q(g.rearLength,10))*f/100,o=g.baseWidth||3,k=g.topWidth||1,j=a.startAngleRad+a.translate(d.y,null,null,null,!0);b.wrap===!1&&(j=Math.max(a.startAngleRad,Math.min(a.endAngleRad,j)));j=j*180/Math.PI;d.shapeType="path";d.shapeArgs={d:g.path||["M",-i,-o/2,"L",e,-o/2,f,-k/2,f,k/2,e,o/2,-i,o/2,"z"],translateX:c[0],translateY:c[1],rotation:j};d.plotX=c[0];d.plotY=c[1]})},drawPoints:function(){var a=this,b=a.yAxis.center,c=a.pivot,d=a.options,g=d.pivot,f=a.chart.renderer;
+r(a.points,function(c){var b=c.graphic,g=c.shapeArgs,k=g.d,j=p(d.dial,c.dial);b?(b.animate(g),g.d=k):c.graphic=f[c.shapeType](g).attr({stroke:j.borderColor||"none","stroke-width":j.borderWidth||0,fill:j.backgroundColor||"black",rotation:g.rotation}).add(a.group)});c?c.animate({translateX:b[0],translateY:b[1]}):a.pivot=f.circle(0,0,q(g.radius,5)).attr({"stroke-width":g.borderWidth||0,stroke:g.borderColor||"silver",fill:g.backgroundColor||"black"}).translate(b[0],b[1]).add(a.group)},animate:function(a){var b=
+this;if(!a)r(b.points,function(a){var d=a.graphic;d&&(d.attr({rotation:b.yAxis.startAngleRad*180/Math.PI}),d.animate({rotation:a.shapeArgs.rotation},b.options.animation))}),b.animate=null},render:function(){this.group=this.plotGroup("group","series",this.visible?"visible":"hidden",this.options.zIndex,this.chart.seriesGroup);h.pie.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:h.pie.prototype.setData,drawTracker:h.column.prototype.drawTracker};h.gauge=l.extendClass(h.line,
+u);m.boxplot=p(m.column,{fillColor:"#FFFFFF",lineWidth:1,medianWidth:2,states:{hover:{brightness:-0.3}},threshold:null,tooltip:{pointFormat:'<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>Maximum: {point.high}<br/>Upper quartile: {point.q3}<br/>Median: {point.median}<br/>Lower quartile: {point.q1}<br/>Minimum: {point.low}<br/>'},whiskerLength:"50%",whiskerWidth:2});h.boxplot=x(h.column,{type:"boxplot",pointArrayMap:["low","q1","median","q3","high"],toYData:function(a){return[a.low,
+a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"},drawDataLabels:w,translate:function(){var a=this.yAxis,b=this.pointArrayMap;h.column.prototype.translate.apply(this);r(this.points,function(c){r(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,g,f,e,i,o,k,j,h,l,m,n,H,p,E,I,t,w,s,v,u,z,y,x=a.doQuartiles!==!1,B=parseInt(a.options.whiskerLength,
+10)/100;r(b,function(b){l=b.graphic;z=b.shapeArgs;n={};E={};t={};y=b.color||a.color;if(b.plotY!==C)if(g=b.pointAttr[b.selected?"selected":""],w=z.width,s=A(z.x),v=s+w,u=D(w/2),f=A(x?b.q1Plot:b.lowPlot),e=A(x?b.q3Plot:b.lowPlot),i=A(b.highPlot),o=A(b.lowPlot),n.stroke=b.stemColor||c.stemColor||y,n["stroke-width"]=q(b.stemWidth,c.stemWidth,c.lineWidth),n.dashstyle=b.stemDashStyle||c.stemDashStyle,E.stroke=b.whiskerColor||c.whiskerColor||y,E["stroke-width"]=q(b.whiskerWidth,c.whiskerWidth,c.lineWidth),
+t.stroke=b.medianColor||c.medianColor||y,t["stroke-width"]=q(b.medianWidth,c.medianWidth,c.lineWidth),j=n["stroke-width"]%2/2,h=s+u+j,m=["M",h,e,"L",h,i,"M",h,f,"L",h,o,"z"],x&&(j=g["stroke-width"]%2/2,h=A(h)+j,f=A(f)+j,e=A(e)+j,s+=j,v+=j,H=["M",s,e,"L",s,f,"L",v,f,"L",v,e,"L",s,e,"z"]),B&&(j=E["stroke-width"]%2/2,i+=j,o+=j,p=["M",h-u*B,i,"L",h+u*B,i,"M",h-u*B,o,"L",h+u*B,o]),j=t["stroke-width"]%2/2,k=D(b.medianPlot)+j,I=["M",s,k,"L",v,k,"z"],l)b.stem.animate({d:m}),B&&b.whiskers.animate({d:p}),x&&
+b.box.animate({d:H}),b.medianShape.animate({d:I});else{b.graphic=l=d.g().add(a.group);b.stem=d.path(m).attr(n).add(l);if(B)b.whiskers=d.path(p).attr(E).add(l);if(x)b.box=d.path(H).attr(g).add(l);b.medianShape=d.path(I).attr(t).add(l)}})}});m.errorbar=p(m.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:m.arearange.tooltip.pointFormat},whiskerWidth:null});h.errorbar=x(h.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",
+doQuartiles:!1,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||h.column.prototype.getColumnMetrics.call(this)}});m.waterfall=p(m.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333"});h.waterfall=x(h.column,{type:"waterfall",upColorProp:"fill",pointArrayMap:["low","y"],pointValKey:"y",init:function(a,b){b.stacking=!0;h.column.prototype.init.call(this,a,b)},translate:function(){var a=this.options,b=this.yAxis,c,d,g,f,e,i,o,k,j;c=a.threshold;
+a=a.borderWidth%2/2;h.column.prototype.translate.apply(this);k=c;g=this.points;for(d=0,c=g.length;d<c;d++){f=g[d];e=f.shapeArgs;i=this.getStack(d);j=i.points[this.index];if(isNaN(f.y))f.y=this.yData[d];o=S(k,k+f.y)+j[0];e.y=b.translate(o,0,1);f.isSum||f.isIntermediateSum?(e.y=b.translate(j[1],0,1),e.height=b.translate(j[0],0,1)-e.y):k+=i.total;e.height<0&&(e.y+=e.height,e.height*=-1);f.plotY=e.y=D(e.y)-a;e.height=D(e.height);f.yBottom=e.y+e.height}},processData:function(a){var b=this.yData,c=this.points,
+d,g=b.length,f=this.options.threshold||0,e,i,h,k,j,l;i=e=h=k=f;for(l=0;l<g;l++)j=b[l],d=c?c[l]:{},j==="sum"||d.isSum?b[l]=i:j==="intermediateSum"||d.isIntermediateSum?(b[l]=e,e=f):(i+=j,e+=j),h=Math.min(i,h),k=Math.max(i,k);z.prototype.processData.call(this,a);this.dataMin=h;this.dataMax=k},toYData:function(a){if(a.isSum)return"sum";else if(a.isIntermediateSum)return"intermediateSum";return a.y},getAttribs:function(){h.column.prototype.getAttribs.apply(this,arguments);var a=this.options,b=a.states,
+c=a.upColor||this.color,a=l.Color(c).brighten(0.1).get(),d=p(this.pointAttr),g=this.upColorProp;d[""][g]=c;d.hover[g]=b.hover.upColor||a;d.select[g]=b.select.upColor||c;r(this.points,function(a){if(a.y>0&&!a.color)a.pointAttr=d,a.color=c})},getGraphPath:function(){var a=this.data,b=a.length,c=D(this.options.lineWidth+this.options.borderWidth)%2/2,d=[],g,f,e;for(e=1;e<b;e++)f=a[e].shapeArgs,g=a[e-1].shapeArgs,f=["M",g.x+g.width,g.y+c,"L",f.x,g.y+c],a[e-1].y<0&&(f[2]+=g.height,f[5]+=g.height),d=d.concat(f);
+return d},getExtremes:w,getStack:function(a){var b=this.yAxis.stacks,c=this.stackKey;this.processedYData[a]<this.options.threshold&&(c="-"+c);return b[c][a]},drawGraph:z.prototype.drawGraph});m.bubble=p(m.scatter,{dataLabels:{inside:!0,style:{color:"white",textShadow:"0px 0px 3px black"},verticalAlign:"middle"},marker:{lineColor:null,lineWidth:1},minSize:8,maxSize:"20%",tooltip:{pointFormat:"({point.x}, {point.y}), Size: {point.z}"},turboThreshold:0,zThreshold:0});h.bubble=x(h.scatter,{type:"bubble",
+pointArrayMap:["y","z"],trackerGroups:["group","dataLabelsGroup"],pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor"},applyOpacity:function(a){var b=this.options.marker,c=q(b.fillOpacity,0.5),a=a||b.fillColor||this.color;c!==1&&(a=l.Color(a).setOpacity(c).get("rgba"));return a},convertAttribs:function(){var a=z.prototype.convertAttribs.apply(this,arguments);a.fill=this.applyOpacity(a.fill);return a},getRadii:function(a,b,c,d){var g,f,e,i=this.zData,h=[];for(f=0,g=i.length;f<
+g;f++)e=b-a,e=e>0?(i[f]-a)/(b-a):0.5,h.push(s.ceil(c+e*(d-c))/2);this.radii=h},animate:function(a){var b=this.options.animation;if(!a)r(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,g=this.radii;h.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=g?g[a]:0,c.negative=c.z<(this.options.zThreshold||0),d>=this.minPxSize/2?(c.shapeType="circle",c.shapeArgs={x:c.plotX,y:c.plotY,
+r:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=C},drawLegendSymbol:function(a,b){var c=v(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:h.column.prototype.drawPoints,alignDataLabel:h.column.prototype.alignDataLabel});N.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,g=b,f=this.isXAxis,e=f?"xData":"yData",i=this.min,h={},
+k=s.min(c.plotWidth,c.plotHeight),j=Number.MAX_VALUE,l=-Number.MAX_VALUE,m=this.max-i,n=b/m,p=[];this.tickPositions&&(r(this.series,function(b){var c=b.options;if(b.type==="bubble"&&b.visible&&(a.allowZoomOutside=!0,p.push(b),f))r(["minSize","maxSize"],function(a){var b=c[a],d=/%$/.test(b),b=v(b);h[a]=d?k*b/100:b}),b.minPxSize=h.minSize,b=b.zData,b.length&&(j=s.min(j,s.max(P(b),c.displayNegative===!1?c.zThreshold:-Number.MAX_VALUE)),l=s.max(l,Q(b)))}),r(p,function(a){var b=a[e],c=b.length,k;f&&a.getRadii(j,
+l,h.minSize,h.maxSize);if(m>0)for(;c--;)k=a.radii[c],d=Math.min((b[c]-i)*n-k,d),g=Math.max((b[c]-i)*n+k,g)}),m>0&&q(this.options.min,this.userMin)===C&&q(this.options.max,this.userMax)===C&&(g-=b,n*=(b+d-g)/b,this.min+=d/n,this.max+=g/n))};var y=z.prototype,m=l.Pointer.prototype;y.toXY=function(a){var b,c=this.chart;b=a.plotX;var d=a.plotY;a.rectPlotX=b;a.rectPlotY=d;a.clientX=(b/Math.PI*180+this.xAxis.pane.options.startAngle)%360;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-d);a.plotX=a.polarPlotX=
+b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop};y.orderTooltipPoints=function(a){if(this.chart.polar&&(a.sort(function(a,c){return a.clientX-c.clientX}),a[0]))a[0].wrappedClientX=a[0].clientX+360,a.push(a[0])};n(h.area.prototype,"init",K);n(h.areaspline.prototype,"init",K);n(h.spline.prototype,"getPointSpline",function(a,b,c,d){var g,f,e,i,h,k,j;if(this.chart.polar){g=c.plotX;f=c.plotY;a=b[d-1];e=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),e||(e=b[1]));if(a&&e)i=a.plotX,h=a.plotY,b=e.plotX,
+k=e.plotY,i=(1.5*g+i)/2.5,h=(1.5*f+h)/2.5,e=(1.5*g+b)/2.5,j=(1.5*f+k)/2.5,b=Math.sqrt(Math.pow(i-g,2)+Math.pow(h-f,2)),k=Math.sqrt(Math.pow(e-g,2)+Math.pow(j-f,2)),i=Math.atan2(h-f,i-g),h=Math.atan2(j-f,e-g),j=Math.PI/2+(i+h)/2,Math.abs(i-j)>Math.PI/2&&(j-=Math.PI),i=g+Math.cos(j)*b,h=f+Math.sin(j)*b,e=g+Math.cos(Math.PI+j)*k,j=f+Math.sin(Math.PI+j)*k,c.rightContX=e,c.rightContY=j;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,i||g,h||f,g,f],a.rightContX=a.rightContY=null):c=["M",g,f]}else c=
+a.call(this,b,c,d);return c});n(y,"translate",function(a){a.call(this);if(this.chart.polar&&!this.preventPostTranslate)for(var a=this.points,b=a.length;b--;)this.toXY(a[b])});n(y,"getSegmentPath",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length-1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});n(y,"animate",L);n(t,"animate",L);n(y,"setTooltipPoints",function(a,b){this.chart.polar&&F(this.xAxis,{tooltipLen:360});
+return a.call(this,b)});n(t,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,g=b.startAngleRad,f=this.chart.renderer,e,h;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(h=b.length;h--;)e=b[h],a=e.barX+g,e.shapeType="path",e.shapeArgs={d:f.symbols.arc(d[0],d[1],c-e.plotY,null,{start:a,end:a+e.pointWidth,innerR:c-q(e.yBottom,c)})},this.toXY(e)}});n(t,"alignDataLabel",function(a,b,c,d,g,f){if(this.chart.polar){a=b.rectPlotX/Math.PI*180;if(d.align===null)d.align=
+a>20&&a<160?"left":a>200&&a<340?"right":"center";if(d.verticalAlign===null)d.verticalAlign=a<45||a>315?"bottom":a>135&&a<225?"top":"middle";y.alignDataLabel.call(this,b,c,d,g,f)}else a.call(this,b,c,d,g,f)});n(m,"getIndex",function(a,b){var c,d=this.chart,g;d.polar?(g=d.xAxis[0].center,c=b.chartX-g[0]-d.plotLeft,d=b.chartY-g[1]-d.plotTop,c=180-Math.round(Math.atan2(c,d)/Math.PI*180)):c=a.call(this,b);return c});n(m,"getCoordinates",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?r(c.axes,
+function(a){var f=a.isXAxis,e=a.center,h=b.chartX-e[0]-c.plotLeft,e=b.chartY-e[1]-c.plotTop;d[f?"xAxis":"yAxis"].push({axis:a,value:a.translate(f?Math.PI-Math.atan2(h,e):Math.sqrt(Math.pow(h,2)+Math.pow(e,2)),!0)})}):d=a.call(this,b);return d})})(Highcharts);

dcdemo/dcdemo/apps/dmochrtit/static/dmodjgra/js/highcharts/highcharts-more.src.js

+// ==ClosureCompiler==
+// @compilation_level SIMPLE_OPTIMIZATIONS
+
+/**
+ * @license Highcharts JS v3.0.5 (2013-08-23)
+ *
+ * (c) 2009-2013 Torstein Hønsi
+ *
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
+
+(function (Highcharts, UNDEFINED) {
+var arrayMin = Highcharts.arrayMin,
+	arrayMax = Highcharts.arrayMax,
+	each = Highcharts.each,
+	extend = Highcharts.extend,
+	merge = Highcharts.merge,
+	map = Highcharts.map,
+	pick = Highcharts.pick,
+	pInt = Highcharts.pInt,
+	defaultPlotOptions = Highcharts.getOptions().plotOptions,
+	seriesTypes = Highcharts.seriesTypes,
+	extendClass = Highcharts.extendClass,
+	splat = Highcharts.splat,
+	wrap = Highcharts.wrap,
+	Axis = Highcharts.Axis,
+	Tick = Highcharts.Tick,
+	Series = Highcharts.Series,
+	colProto = seriesTypes.column.prototype,
+	math = Math,
+	mathRound = math.round,
+	mathFloor = math.floor,
+	mathMax = math.max,
+	noop = function () {};/**
+ * The Pane object allows options that are common to a set of X and Y axes.
+ * 
+ * In the future, this can be extended to basic Highcharts and Highstock.
+ */
+function Pane(options, chart, firstAxis) {
+	this.init.call(this, options, chart, firstAxis);
+}
+
+// Extend the Pane prototype
+extend(Pane.prototype, {
+	
+	/**
+	 * Initiate the Pane object
+	 */
+	init: function (options, chart, firstAxis) {
+		var pane = this,
+			backgroundOption,
+			defaultOptions = pane.defaultOptions;
+		
+		pane.chart = chart;
+		
+		// Set options
+		if (chart.angular) { // gauges
+			defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions
+		}
+		pane.options = options = merge(defaultOptions, options);
+		
+		backgroundOption = options.background;
+		
+		// To avoid having weighty logic to place, update and remove the backgrounds,
+		// push them to the first axis' plot bands and borrow the existing logic there.
+		if (backgroundOption) {
+			each([].concat(splat(backgroundOption)).reverse(), function (config) {
+				var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)
+				config = merge(pane.defaultBackgroundOptions, config);
+				if (backgroundColor) {
+					config.backgroundColor = backgroundColor;
+				}
+				config.color = config.backgroundColor; // due to naming in plotBands
+				firstAxis.options.plotBands.unshift(config);
+			});
+		}
+	},
+	
+	/**
+	 * The default options object
+	 */
+	defaultOptions: {
+		// background: {conditional},
+		center: ['50%', '50%'],
+		size: '85%',
+		startAngle: 0
+		//endAngle: startAngle + 360
+	},	
+	
+	/**
+	 * The default background options
+	 */
+	defaultBackgroundOptions: {
+		shape: 'circle',
+		borderWidth: 1,
+		borderColor: 'silver',
+		backgroundColor: {
+			linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
+			stops: [
+				[0, '#FFF'],
+				[1, '#DDD']
+			]
+		},
+		from: Number.MIN_VALUE, // corrected to axis min
+		innerRadius: 0,
+		to: Number.MAX_VALUE, // corrected to axis max
+		outerRadius: '105%'
+	}
+	
+});
+var axisProto = Axis.prototype,
+	tickProto = Tick.prototype;
+	
+/**
+ * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
+ */
+var hiddenAxisMixin = {
+	getOffset: noop,
+	redraw: function () {
+		this.isDirty = false; // prevent setting Y axis dirty
+	},
+	render: function () {
+		this.isDirty = false; // prevent setting Y axis dirty
+	},
+	setScale: noop,
+	setCategories: noop,
+	setTitle: noop
+};
+
+/**
+ * Augmented methods for the value axis
+ */
+/*jslint unparam: true*/
+var radialAxisMixin = {
+	isRadial: true,
+	
+	/**
+	 * The default options extend defaultYAxisOptions
+	 */
+	defaultRadialGaugeOptions: {
+		labels: {
+			align: 'center',
+			x: 0,
+			y: null // auto
+		},
+		minorGridLineWidth: 0,
+		minorTickInterval: 'auto',
+		minorTickLength: 10,
+		minorTickPosition: 'inside',
+		minorTickWidth: 1,
+		plotBands: [],
+		tickLength: 10,
+		tickPosition: 'inside',
+		tickWidth: 2,
+		title: {
+			rotation: 0
+		},
+		zIndex: 2 // behind dials, points in the series group
+	},
+	
+	// Circular axis around the perimeter of a polar chart
+	defaultRadialXOptions: {
+		gridLineWidth: 1, // spokes
+		labels: {
+			align: null, // auto
+			distance: 15,
+			x: 0,
+			y: null // auto
+		},
+		maxPadding: 0,
+		minPadding: 0,
+		plotBands: [],
+		showLastLabel: false, 
+		tickLength: 0
+	},
+	
+	// Radial axis, like a spoke in a polar chart
+	defaultRadialYOptions: {
+		gridLineInterpolation: 'circle',
+		labels: {
+			align: 'right',
+			x: -3,
+			y: -2
+		},
+		plotBands: [],
+		showLastLabel: false,
+		title: {
+			x: 4,
+			text: null,
+			rotation: 90
+		}
+	},
+	
+	/**
+	 * Merge and set options
+	 */
+	setOptions: function (userOptions) {
+		
+		this.options = merge(
+			this.defaultOptions,
+			this.defaultRadialOptions,
+			userOptions
+		);
+		
+	},
+	
+	/**
+	 * Wrap the getOffset method to return zero offset for title or labels in a radial 
+	 * axis
+	 */
+	getOffset: function () {
+		// Call the Axis prototype method (the method we're in now is on the instance)
+		axisProto.getOffset.call(this);
+		
+		// Title or label offsets are not counted
+		this.chart.axisOffset[this.side] = 0;
+		
+		// Set the center array
+		this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);
+	},
+
+
+	/**
+	 * Get the path for the axis line. This method is also referenced in the getPlotLinePath
+	 * method.
+	 */
+	getLinePath: function (lineWidth, radius) {
+		var center = this.center;
+		radius = pick(radius, center[2] / 2 - this.offset);
+		
+		return this.chart.renderer.symbols.arc(
+			this.left + center[0],
+			this.top + center[1],
+			radius,
+			radius, 
+			{
+				start: this.startAngleRad,
+				end: this.endAngleRad,
+				open: true,
+				innerR: 0
+			}
+		);
+	},
+
+	/**
+	 * Override setAxisTranslation by setting the translation to the difference
+	 * in rotation. This allows the translate method to return angle for 
+	 * any given value.
+	 */
+	setAxisTranslation: function () {
+		
+		// Call uber method		
+		axisProto.setAxisTranslation.call(this);
+			
+		// Set transA and minPixelPadding
+		if (this.center) { // it's not defined the first time
+			if (this.isCircular) {
+				
+				this.transA = (this.endAngleRad - this.startAngleRad) / 
+					((this.max - this.min) || 1);
+					
+				
+			} else { 
+				this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
+			}
+			
+			if (this.isXAxis) {
+				this.minPixelPadding = this.transA * this.minPointOffset +
+					(this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
+			}
+		}
+	},
+	
+	/**
+	 * In case of auto connect, add one closestPointRange to the max value right before
+	 * tickPositions are computed, so that ticks will extend passed the real max.
+	 */
+	beforeSetTickPositions: function () {
+		if (this.autoConnect) {
+			this.max += (this.categories && 1) || this.pointRange || this.closestPointRange; // #1197
+		}
+	},
+	
+	/**
+	 * Override the setAxisSize method to use the arc's circumference as length. This
+	 * allows tickPixelInterval to apply to pixel lengths along the perimeter
+	 */
+	setAxisSize: function () {
+		
+		axisProto.setAxisSize.call(this);
+		
+		if (this.center) { // it's not defined the first time
+			this.len = this.width = this.height = this.isCircular ?
+				this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
+				this.center[2] / 2;
+		}
+	},
+	
+	/**
+	 * Returns the x, y coordinate of a point given by a value and a pixel distance
+	 * from center
+	 */
+	getPosition: function (value, length) {
+		if (!this.isCircular) {
+			length = this.translate(value);
+			value = this.min;	
+		}
+		
+		return this.postTranslate(
+			this.translate(value),
+			pick(length, this.center[2] / 2) - this.offset
+		);		
+	},
+	
+	/**
+	 * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates. 
+	 */
+	postTranslate: function (angle, radius) {
+		
+		var chart = this.chart,
+			center = this.center;
+			
+		angle = this.startAngleRad + angle;
+		
+		return {
+			x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
+			y: chart.plotTop + center[1] + Math.sin(angle) * radius
+		}; 
+		
+	},
+	
+	/**
+	 * Find the path for plot bands along the radial axis
+	 */
+	getPlotBandPath: function (from, to, options) {
+		var center = this.center,
+			startAngleRad = this.startAngleRad,
+			fullRadius = center[2] / 2,
+			radii = [
+				pick(options.outerRadius, '100%'),
+				options.innerRadius,
+				pick(options.thickness, 10)
+			],
+			percentRegex = /%$/,
+			start,
+			end,
+			open,
+			isCircular = this.isCircular, // X axis in a polar chart
+			ret;
+			
+		// Polygonal plot bands
+		if (this.options.gridLineInterpolation === 'polygon') {
+			ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
+		
+		// Circular grid bands
+		} else {
+			
+			// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
+			if (!isCircular) {
+				radii[0] = this.translate(from);
+				radii[1] = this.translate(to);
+			}
+			
+			// Convert percentages to pixel values
+			radii = map(radii, function (radius) {
+				if (percentRegex.test(radius)) {
+					radius = (pInt(radius, 10) * fullRadius) / 100;
+				}
+				return radius;
+			});
+			
+			// Handle full circle
+			if (options.shape === 'circle' || !isCircular) {
+				start = -Math.PI / 2;
+				end = Math.PI * 1.5;
+				open = true;
+			} else {
+				start = startAngleRad + this.translate(from);
+				end = startAngleRad + this.translate(to);
+			}
+		
+		
+			ret = this.chart.renderer.symbols.arc(
+				this.left + center[0],
+				this.top + center[1],
+				radii[0],
+				radii[0],
+				{
+					start: start,
+					end: end,
+					innerR: pick(radii[1], radii[0] - radii[2]),
+					open: open
+				}
+			);
+		}
+		 
+		return ret;
+	},
+	
+	/**
+	 * Find the path for plot lines perpendicular to the radial axis.
+	 */
+	getPlotLinePath: function (value, reverse) {
+		var axis = this,
+			center = axis.center,
+			chart = axis.chart,
+			end = axis.getPosition(value),
+			xAxis,
+			xy,
+			tickPositions,
+			ret;
+		
+		// Spokes
+		if (axis.isCircular) {
+			ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
+		
+		// Concentric circles			
+		} else if (axis.options.gridLineInterpolation === 'circle') {
+			value = axis.translate(value);
+			if (value) { // a value of 0 is in the center
+				ret = axis.getLinePath(0, value);
+			}
+		// Concentric polygons 
+		} else {
+			xAxis = chart.xAxis[0];
+			ret = [];
+			value = axis.translate(value);
+			tickPositions = xAxis.tickPositions;
+			if (xAxis.autoConnect) {
+				tickPositions = tickPositions.concat([tickPositions[0]]);
+			}
+			// Reverse the positions for concatenation of polygonal plot bands
+			if (reverse) {
+				tickPositions = [].concat(tickPositions).reverse();
+			}
+				
+			each(tickPositions, function (pos, i) {
+				xy = xAxis.getPosition(pos, value);
+				ret.push(i ? 'L' : 'M', xy.x, xy.y);
+			});
+			
+		}
+		return ret;
+	},
+	
+	/**
+	 * Find the position for the axis title, by default inside the gauge
+	 */
+	getTitlePosition: function () {
+		var center = this.center,
+			chart = this.chart,
+			titleOptions = this.options.title;
+		
+		return { 
+			x: chart.plotLeft + center[0] + (titleOptions.x || 0), 
+			y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] * 
+				center[2]) + (titleOptions.y || 0)  
+		};
+	}
+	
+};
+/*jslint unparam: false*/
+
+/**
+ * Override axisProto.init to mix in special axis instance functions and function overrides
+ */
+wrap(axisProto, 'init', function (proceed, chart, userOptions) {
+	var axis = this,
+		angular = chart.angular,
+		polar = chart.polar,
+		isX = userOptions.isX,
+		isHidden = angular && isX,
+		isCircular,
+		startAngleRad,
+		endAngleRad,
+		options,
+		chartOptions = chart.options,
+		paneIndex = userOptions.pane || 0,
+		pane,
+		paneOptions;
+		
+	// Before prototype.init
+	if (angular) {
+		extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
+		isCircular =  !isX;
+		if (isCircular) {
+			this.defaultRadialOptions = this.defaultRadialGaugeOptions;
+		}
+		
+	} else if (polar) {
+		//extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);
+		extend(this, radialAxisMixin);
+		isCircular = isX;
+		this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
+		
+	}
+	
+	// Run prototype.init
+	proceed.call(this, chart, userOptions);
+	
+	if (!isHidden && (angular || polar)) {
+		options = this.options;
+		
+		// Create the pane and set the pane options.
+		if (!chart.panes) {
+			chart.panes = [];
+		}
+		this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
+			splat(chartOptions.pane)[paneIndex],
+			chart,
+			axis
+		);
+		paneOptions = pane.options;
+		
+			
+		// Disable certain features on angular and polar axes
+		chart.inverted = false;
+		chartOptions.chart.zoomType = null;
+		
+		// Start and end angle options are
+		// given in degrees relative to top, while internal computations are
+		// in radians relative to right (like SVG).
+		this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
+		this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360)  - 90) * Math.PI / 180;
+		this.offset = options.offset || 0;
+		
+		this.isCircular = isCircular;
+		
+		// Automatically connect grid lines?
+		if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {
+			this.autoConnect = true;
+		}
+	}
+	
+});
+
+/**
+ * Add special cases within the Tick class' methods for radial axes.
+ */	
+wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
+	var axis = this.axis;
+	
+	return axis.getPosition ? 
+		axis.getPosition(pos) :
+		proceed.call(this, horiz, pos, tickmarkOffset, old);	
+});
+
+/**
+ * Wrap the getLabelPosition function to find the center position of the label
+ * based on the distance option
+ */	
+wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
+	var axis = this.axis,
+		optionsY = labelOptions.y,
+		ret,
+		align = labelOptions.align,
+		angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
+	
+	if (axis.isRadial) {
+		ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
+		
+		// Automatically rotated
+		if (labelOptions.rotation === 'auto') {
+			label.attr({ 
+				rotation: angle
+			});
+		
+		// Vertically centered
+		} else if (optionsY === null) {
+			optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
+		
+		}
+		
+		// Automatic alignment
+		if (align === null) {
+			if (axis.isCircular) {
+				if (angle > 20 && angle < 160) {
+					align = 'left'; // right hemisphere
+				} else if (angle > 200 && angle < 340) {
+					align = 'right'; // left hemisphere
+				} else {
+					align = 'center'; // top or bottom
+				}
+			} else {
+				align = 'center';
+			}
+			label.attr({
+				align: align
+			});
+		}
+		
+		ret.x += labelOptions.x;
+		ret.y += optionsY;
+		
+	} else {
+		ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
+	}
+	return ret;
+});
+
+/**
+ * Wrap the getMarkPath function to return the path of the radial marker
+ */
+wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
+	var axis = this.axis,
+		endPoint,
+		ret;
+		
+	if (axis.isRadial) {
+		endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
+		ret = [
+			'M',
+			x,
+			y,
+			'L',
+			endPoint.x,
+			endPoint.y
+		];
+	} else {
+		ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
+	}
+	return ret;
+});/* 
+ * The AreaRangeSeries class
+ * 
+ */
+
+/**
+ * Extend the default options with map options
+ */
+defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
+	lineWidth: 1,
+	marker: null,
+	threshold: null,
+	tooltip: {
+		pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>' 
+	},
+	trackByArea: true,
+	dataLabels: {
+		verticalAlign: null,
+		xLow: 0,
+		xHigh: 0,
+		yLow: 0,
+		yHigh: 0	
+	}
+});
+
+/**
+ * Add the series type
+ */
+seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {
+	type: 'arearange',
+	pointArrayMap: ['low', 'high'],
+	toYData: function (point) {
+		return [point.low, point.high];
+	},
+	pointValKey: 'low',
+	
+	/**
+	 * Extend getSegments to force null points if the higher value is null. #1703.
+	 */
+	getSegments: function () {
+		var series = this;
+
+		each(series.points, function (point) {
+			if (!series.options.connectNulls && (point.low === null || point.high === null)) {
+				point.y = null;
+			} else if (point.low === null && point.high !== null) {
+				point.y = point.high;
+			}
+		});
+		Series.prototype.getSegments.call(this);
+	},
+	
+	/**
+	 * Translate data points from raw values x and y to plotX and plotY
+	 */
+	translate: function () {
+		var series = this,
+			yAxis = series.yAxis;
+
+		seriesTypes.area.prototype.translate.apply(series);
+
+		// Set plotLow and plotHigh
+		each(series.points, function (point) {
+
+			var low = point.low,
+				high = point.high,
+				plotY = point.plotY;
+
+			if (high === null && low === null) {
+				point.y = null;
+			} else if (low === null) {
+				point.plotLow = point.plotY = null;
+				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
+			} else if (high === null) {
+				point.plotLow = plotY;
+				point.plotHigh = null;
+			} else {
+				point.plotLow = plotY;
+				point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
+			}
+		});
+	},
+	
+	/**
+	 * Extend the line series' getSegmentPath method by applying the segment
+	 * path to both lower and higher values of the range
+	 */
+	getSegmentPath: function (segment) {
+		
+		var lowSegment,
+			highSegment = [],
+			i = segment.length,
+			baseGetSegmentPath = Series.prototype.getSegmentPath,
+			point,
+			linePath,
+			lowerPath,
+			options = this.options,
+			step = options.step,
+			higherPath;
+			
+		// Remove nulls from low segment
+		lowSegment = HighchartsAdapter.grep(segment, function (point) {
+			return point.plotLow !== null;
+		});
+		
+		// Make a segment with plotX and plotY for the top values
+		while (i--) {
+			point = segment[i];
+			if (point.plotHigh !== null) {
+				highSegment.push({
+					plotX: point.plotX,
+					plotY: point.plotHigh
+				});
+			}
+		}
+		
+		// Get the paths
+		lowerPath = baseGetSegmentPath.call(this, lowSegment);
+		if (step) {
+			if (step === true) {
+				step = 'left';
+			}
+			options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath
+		}
+		higherPath = baseGetSegmentPath.call(this, highSegment);
+		options.step = step;
+		
+		// Create a line on both top and bottom of the range
+		linePath = [].concat(lowerPath, higherPath);
+		
+		// For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
+		higherPath[0] = 'L'; // this probably doesn't work for spline			
+		this.areaPath = this.areaPath.concat(lowerPath, higherPath);
+		
+		return linePath;
+	},
+	
+	/**
+	 * Extend the basic drawDataLabels method by running it for both lower and higher
+	 * values.
+	 */
+	drawDataLabels: function () {
+		
+		var data = this.data,
+			length = data.length,
+			i,
+			originalDataLabels = [],
+			seriesProto = Series.prototype,
+			dataLabelOptions = this.options.dataLabels,
+			point,
+			inverted = this.chart.inverted;
+			
+		if (dataLabelOptions.enabled || this._hasPointLabels) {
+			
+			// Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
+			i = length;
+			while (i--) {
+				point = data[i];
+				
+				// Set preliminary values
+				point.y = point.high;
+				point.plotY = point.plotHigh;
+				
+				// Store original data labels and set preliminary label objects to be picked up 
+				// in the uber method
+				originalDataLabels[i] = point.dataLabel;
+				point.dataLabel = point.dataLabelUpper;
+				
+				// Set the default offset
+				point.below = false;
+				if (inverted) {
+					dataLabelOptions.align = 'left';
+					dataLabelOptions.x = dataLabelOptions.xHigh;								
+				} else {
+					dataLabelOptions.y = dataLabelOptions.yHigh;
+				}
+			}
+			seriesProto.drawDataLabels.apply(this, arguments); // #1209
+			
+			// Step 2: reorganize and handle data labels for the lower values
+			i = length;
+			while (i--) {
+				point = data[i];
+				
+				// Move the generated labels from step 1, and reassign the original data labels
+				point.dataLabelUpper = point.dataLabel;
+				point.dataLabel = originalDataLabels[i];
+				
+				// Reset values
+				point.y = point.low;
+				point.plotY = point.plotLow;
+				
+				// Set the default offset
+				point.below = true;
+				if (inverted) {
+					dataLabelOptions.align = 'right';
+					dataLabelOptions.x = dataLabelOptions.xLow;
+				} else {
+					dataLabelOptions.y = dataLabelOptions.yLow;
+				}
+			}
+			seriesProto.drawDataLabels.apply(this, arguments);
+		}
+	
+	},
+	
+	alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
+	
+	getSymbol: seriesTypes.column.prototype.getSymbol,
+	
+	drawPoints: noop
+});/**
+ * The AreaSplineRangeSeries class
+ */
+
+defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);
+
+/**
+ * AreaSplineRangeSeries object
+ */
+seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
+	type: 'areasplinerange',
+	getPointSpline: seriesTypes.spline.prototype.getPointSpline
+});/**
+ * The ColumnRangeSeries class
+ */
+defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
+	lineWidth: 1,
+	pointRange: null
+});
+
+/**
+ * ColumnRangeSeries object
+ */
+seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
+	type: 'columnrange',
+	/**
+	 * Translate data points from raw values x and y to plotX and plotY
+	 */
+	translate: function () {
+		var series = this,
+			yAxis = series.yAxis,
+			plotHigh;
+
+		colProto.translate.apply(series);
+
+		// Set plotLow and plotHigh
+		each(series.points, function (point) {
+			var shapeArgs = point.shapeArgs,
+				minPointLength = series.options.minPointLength,
+				heightDifference,
+				height,
+				y;
+
+			point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
+			point.plotLow = point.plotY;
+
+			// adjust shape
+			y = plotHigh;
+			height = point.plotY - plotHigh;
+
+			if (height < minPointLength) {
+				heightDifference = (minPointLength - height);
+				height += heightDifference;
+				y -= heightDifference / 2;
+			}
+			shapeArgs.height = height;
+			shapeArgs.y = y;
+		});
+	},
+	trackerGroups: ['group', 'dataLabels'],
+	drawGraph: noop,
+	pointAttrToOptions: colProto.pointAttrToOptions,
+	drawPoints: colProto.drawPoints,
+	drawTracker: colProto.drawTracker,
+	animate: colProto.animate,