| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 | (function (Highcharts, HighchartsAdapter) {var UNDEFINED,	ALIGN_FACTOR,	ALLOWED_SHAPES,	Chart = Highcharts.Chart,	extend = Highcharts.extend,	each = Highcharts.each;ALLOWED_SHAPES = ["path", "rect", "circle"];ALIGN_FACTOR = {	top: 0,	left: 0,	center: 0.5,	middle: 0.5,	bottom: 1,	right: 1};// Highcharts helper methodsvar inArray = HighchartsAdapter.inArray,	merge = Highcharts.merge;function defaultOptions(shapeType) {	var shapeOptions,		options;	options = {		xAxis: 0,		yAxis: 0,		title: {			style: {},			text: "",			x: 0,			y: 0		},		shape: {			params: {				stroke: "#000000",				fill: "transparent",				strokeWidth: 2			}		}	};	shapeOptions = {		circle: {			params: {				x: 0,				y: 0			}		}	};	if (shapeOptions[shapeType]) {		options.shape = merge(options.shape, shapeOptions[shapeType]);	}	return options;}function isArray(obj) {	return Object.prototype.toString.call(obj) === '[object Array]';}function isNumber(n) {	return typeof n === 'number';}function defined(obj) {	return obj !== UNDEFINED && obj !== null;}function translatePath(d, xAxis, yAxis, xOffset, yOffset) {	var len = d.length,		i = 0;	while (i < len) {		if (typeof d[i] === 'number' && typeof d[i + 1] === 'number') {			d[i] = xAxis.toPixels(d[i]) - xOffset;			d[i + 1] = yAxis.toPixels(d[i + 1]) - yOffset;			i += 2;		} else {			i += 1;		}	}	return d;}// Define annotation prototypevar Annotation = function () {	this.init.apply(this, arguments);};Annotation.prototype = {	/* 	 * Initialize the annotation	 */	init: function (chart, options) {		var shapeType = options.shape && options.shape.type;		this.chart = chart;		this.options = merge({}, defaultOptions(shapeType), options);	},	/*	 * Render the annotation	 */	render: function (redraw) {		var annotation = this,			chart = this.chart,			renderer = annotation.chart.renderer,			group = annotation.group,			title = annotation.title,			shape = annotation.shape,			options = annotation.options,			titleOptions = options.title,			shapeOptions = options.shape;		if (!group) {			group = annotation.group = renderer.g();		}		if (!shape && shapeOptions && inArray(shapeOptions.type, ALLOWED_SHAPES) !== -1) {			shape = annotation.shape = renderer[options.shape.type](shapeOptions.params);			shape.add(group);		}		if (!title && titleOptions) {			title = annotation.title = renderer.label(titleOptions);			title.add(group);		}		group.add(chart.annotations.group);		// link annotations to point or series		annotation.linkObjects();		if (redraw !== false) {			annotation.redraw();		}	},	/*	 * Redraw the annotation title or shape after options update	 */	redraw: function () {		var options = this.options,			chart = this.chart,			group = this.group,			title = this.title,			shape = this.shape,			linkedTo = this.linkedObject,			xAxis = chart.xAxis[options.xAxis],			yAxis = chart.yAxis[options.yAxis],			width = options.width,			height = options.height,			anchorY = ALIGN_FACTOR[options.anchorY],			anchorX = ALIGN_FACTOR[options.anchorX],			resetBBox = false,			shapeParams,			linkType,			series,			param,			bbox,			x,			y;		if (linkedTo) {			linkType = (linkedTo instanceof Highcharts.Point) ? 'point' :						(linkedTo instanceof Highcharts.Series) ? 'series' : null;			if (linkType === 'point') {				options.xValue = linkedTo.x;				options.yValue = linkedTo.y;				series = linkedTo.series;			} else if (linkType === 'series') {				series = linkedTo;			}			if (group.visibility !== series.group.visibility) {				group.attr({					visibility: series.group.visibility				});			}		}		// Based on given options find annotation pixel position		x = (defined(options.xValue) ? xAxis.toPixels(options.xValue + xAxis.minPointOffset) - xAxis.minPixelPadding : options.x);		y = defined(options.yValue) ? yAxis.toPixels(options.yValue) : options.y;		if (isNaN(x) || isNaN(y) || !isNumber(x) || !isNumber(y)) {			return;		}		if (title) {			title.attr(options.title);			title.css(options.title.style);			resetBBox = true;		}		if (shape) {			shapeParams = extend({}, options.shape.params);			if (options.units === 'values') {				for (param in shapeParams) {					if (inArray(param, ['width', 'x']) > -1) {						shapeParams[param] = xAxis.translate(shapeParams[param]);					} else if (inArray(param, ['height', 'y']) > -1) {						shapeParams[param] = yAxis.translate(shapeParams[param]);					}				}				if (shapeParams.width) {					shapeParams.width -= xAxis.toPixels(0) - xAxis.left;				}				if (shapeParams.x) {					shapeParams.x += xAxis.minPixelPadding;				}				if (options.shape.type === 'path') {					translatePath(shapeParams.d, xAxis, yAxis, x, y);				}			}			// move the center of the circle to shape x/y			if (options.shape.type === 'circle') {				shapeParams.x += shapeParams.r;				shapeParams.y += shapeParams.r;			}			resetBBox = true;			shape.attr(shapeParams);		}		group.bBox = null;		// If annotation width or height is not defined in options use bounding box size		if (!isNumber(width)) {			bbox = group.getBBox();			width = bbox.width;		}		if (!isNumber(height)) {			// get bbox only if it wasn't set before			if (!bbox) {				bbox = group.getBBox();			}			height = bbox.height;		}		// Calculate anchor point		if (!isNumber(anchorX)) {			anchorX = ALIGN_FACTOR.center;		}		if (!isNumber(anchorY)) {			anchorY = ALIGN_FACTOR.center;		}		// Translate group according to its dimension and anchor point		x = x - width * anchorX;		y = y - height * anchorY;		if (chart.animation && defined(group.translateX) && defined(group.translateY)) {			group.animate({				translateX: x,				translateY: y			});		} else {			group.translate(x, y);		}	},	/*	 * Destroy the annotation	 */	destroy: function () {		var annotation = this,			chart = this.chart,			allItems = chart.annotations.allItems,			index = allItems.indexOf(annotation);		if (index > -1) {			allItems.splice(index, 1);		}		each(['title', 'shape', 'group'], function (element) {			if (annotation[element]) {				annotation[element].destroy();				annotation[element] = null;			}		});		annotation.group = annotation.title = annotation.shape = annotation.chart = annotation.options = null;	},	/*	 * Update the annotation with a given options	 */	update: function (options, redraw) {		extend(this.options, options);		// update link to point or series		this.linkObjects();		this.render(redraw);	},	linkObjects: function () {		var annotation = this,			chart = annotation.chart,			linkedTo = annotation.linkedObject,			linkedId = linkedTo && (linkedTo.id || linkedTo.options.id),			options = annotation.options,			id = options.linkedTo;		if (!defined(id)) {			annotation.linkedObject = null;		} else if (!defined(linkedTo) || id !== linkedId) {			annotation.linkedObject = chart.get(id);		}	}};// Add annotations methods to chart prototypeextend(Chart.prototype, {	annotations: {		/*		 * Unified method for adding annotations to the chart		 */		add: function (options, redraw) {			var annotations = this.allItems,				chart = this.chart,				item,				len;			if (!isArray(options)) {				options = [options];			}			len = options.length;			while (len--) {				item = new Annotation(chart, options[len]);				annotations.push(item);				item.render(redraw);			}		},		/**		 * Redraw all annotations, method used in chart events		 */		redraw: function () {			each(this.allItems, function (annotation) {				annotation.redraw();			});		}	}});// Initialize on chart loadChart.prototype.callbacks.push(function (chart) {	var options = chart.options.annotations,		group;	group = chart.renderer.g("annotations");	group.attr({		zIndex: 7	});	group.add();	// initialize empty array for annotations	chart.annotations.allItems = [];	// link chart object to annotations	chart.annotations.chart = chart;	// link annotations group element to the chart	chart.annotations.group = group;	if (isArray(options) && options.length > 0) {		chart.annotations.add(chart.options.annotations);	}	// update annotations after chart redraw	Highcharts.addEvent(chart, 'redraw', function () {		chart.annotations.redraw();	});});}(Highcharts, HighchartsAdapter));
 |