| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 | 
							- /**
 
-  * Highcharts Drilldown plugin
 
-  * 
 
-  * Author: Torstein Honsi
 
-  * Last revision: 2013-02-18
 
-  * License: MIT License
 
-  *
 
-  * Demo: http://jsfiddle.net/highcharts/Vf3yT/
 
-  */
 
- /*global HighchartsAdapter*/
 
- (function (H) {
 
- 	"use strict";
 
- 	var noop = function () {},
 
- 		defaultOptions = H.getOptions(),
 
- 		each = H.each,
 
- 		extend = H.extend,
 
- 		wrap = H.wrap,
 
- 		Chart = H.Chart,
 
- 		seriesTypes = H.seriesTypes,
 
- 		PieSeries = seriesTypes.pie,
 
- 		ColumnSeries = seriesTypes.column,
 
- 		fireEvent = HighchartsAdapter.fireEvent;
 
- 	// Utilities
 
- 	function tweenColors(startColor, endColor, pos) {
 
- 		var rgba = [
 
- 				Math.round(startColor[0] + (endColor[0] - startColor[0]) * pos),
 
- 				Math.round(startColor[1] + (endColor[1] - startColor[1]) * pos),
 
- 				Math.round(startColor[2] + (endColor[2] - startColor[2]) * pos),
 
- 				startColor[3] + (endColor[3] - startColor[3]) * pos
 
- 			];
 
- 		return 'rgba(' + rgba.join(',') + ')';
 
- 	}
 
- 	// Add language
 
- 	extend(defaultOptions.lang, {
 
- 		drillUpText: '◁ Back to {series.name}'
 
- 	});
 
- 	defaultOptions.drilldown = {
 
- 		activeAxisLabelStyle: {
 
- 			cursor: 'pointer',
 
- 			color: '#039',
 
- 			fontWeight: 'bold',
 
- 			textDecoration: 'underline'			
 
- 		},
 
- 		activeDataLabelStyle: {
 
- 			cursor: 'pointer',
 
- 			color: '#039',
 
- 			fontWeight: 'bold',
 
- 			textDecoration: 'underline'			
 
- 		},
 
- 		animation: {
 
- 			duration: 500
 
- 		},
 
- 		drillUpButton: {
 
- 			position: { 
 
- 				align: 'right',
 
- 				x: -10,
 
- 				y: 10
 
- 			}
 
- 			// relativeTo: 'plotBox'
 
- 			// theme
 
- 		}
 
- 	};	
 
- 	/**
 
- 	 * A general fadeIn method
 
- 	 */
 
- 	H.SVGRenderer.prototype.Element.prototype.fadeIn = function () {
 
- 		this
 
- 		.attr({
 
- 			opacity: 0.1,
 
- 			visibility: 'visible'
 
- 		})
 
- 		.animate({
 
- 			opacity: 1
 
- 		}, {
 
- 			duration: 250
 
- 		});
 
- 	};
 
- 	// Extend the Chart prototype
 
- 	Chart.prototype.drilldownLevels = [];
 
- 	Chart.prototype.addSeriesAsDrilldown = function (point, ddOptions) {
 
- 		var oldSeries = point.series,
 
- 			xAxis = oldSeries.xAxis,
 
- 			yAxis = oldSeries.yAxis,
 
- 			newSeries,
 
- 			color = point.color || oldSeries.color,
 
- 			pointIndex,
 
- 			level;
 
- 			
 
- 		ddOptions = extend({
 
- 			color: color
 
- 		}, ddOptions);
 
- 		pointIndex = HighchartsAdapter.inArray(this, oldSeries.points);
 
- 		level = {
 
- 			seriesOptions: oldSeries.userOptions,
 
- 			shapeArgs: point.shapeArgs,
 
- 			bBox: point.graphic.getBBox(),
 
- 			color: color,
 
- 			newSeries: ddOptions,
 
- 			pointOptions: oldSeries.options.data[pointIndex],
 
- 			pointIndex: pointIndex,
 
- 			oldExtremes: {
 
- 				xMin: xAxis && xAxis.userMin,
 
- 				xMax: xAxis && xAxis.userMax,
 
- 				yMin: yAxis && yAxis.userMin,
 
- 				yMax: yAxis && yAxis.userMax
 
- 			}
 
- 		};
 
- 		this.drilldownLevels.push(level);
 
- 		newSeries = this.addSeries(ddOptions, false);
 
- 		if (xAxis) {
 
- 			xAxis.oldPos = xAxis.pos;
 
- 			xAxis.userMin = xAxis.userMax = null;
 
- 			yAxis.userMin = yAxis.userMax = null;
 
- 		}
 
- 		// Run fancy cross-animation on supported and equal types
 
- 		if (oldSeries.type === newSeries.type) {
 
- 			newSeries.animate = newSeries.animateDrilldown || noop;
 
- 			newSeries.options.animation = true;
 
- 		}
 
- 		
 
- 		oldSeries.remove(false);
 
- 		
 
- 		this.redraw();
 
- 		this.showDrillUpButton();
 
- 	};
 
- 	Chart.prototype.getDrilldownBackText = function () {
 
- 		var lastLevel = this.drilldownLevels[this.drilldownLevels.length - 1];
 
- 		return this.options.lang.drillUpText.replace('{series.name}', lastLevel.seriesOptions.name);
 
- 	};
 
- 	Chart.prototype.showDrillUpButton = function () {
 
- 		var chart = this,
 
- 			backText = this.getDrilldownBackText(),
 
- 			buttonOptions = chart.options.drilldown.drillUpButton;
 
- 			
 
- 		if (!this.drillUpButton) {
 
- 			this.drillUpButton = this.renderer.button(
 
- 				backText,
 
- 				null,
 
- 				null,
 
- 				function () {
 
- 					chart.drillUp(); 
 
- 				}
 
- 			)
 
- 			.attr(extend({
 
- 				align: buttonOptions.position.align,
 
- 				zIndex: 9
 
- 			}, buttonOptions.theme))
 
- 			.add()
 
- 			.align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
 
- 		} else {
 
- 			this.drillUpButton.attr({
 
- 				text: backText
 
- 			})
 
- 			.align();
 
- 		}
 
- 	};
 
- 	Chart.prototype.drillUp = function () {
 
- 		var chart = this,
 
- 			level = chart.drilldownLevels.pop(),
 
- 			oldSeries = chart.series[0],
 
- 			oldExtremes = level.oldExtremes,
 
- 			newSeries = chart.addSeries(level.seriesOptions, false);
 
- 		
 
- 		fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
 
- 		if (newSeries.type === oldSeries.type) {
 
- 			newSeries.drilldownLevel = level;
 
- 			newSeries.animate = newSeries.animateDrillupTo || noop;
 
- 			newSeries.options.animation = true;
 
- 			if (oldSeries.animateDrillupFrom) {
 
- 				oldSeries.animateDrillupFrom(level);
 
- 			}
 
- 		}
 
- 		oldSeries.remove(false);
 
- 		// Reset the zoom level of the upper series
 
- 		if (newSeries.xAxis) {
 
- 			newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false);
 
- 			newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false);
 
- 		}
 
- 		this.redraw();
 
- 		if (this.drilldownLevels.length === 0) {
 
- 			this.drillUpButton = this.drillUpButton.destroy();
 
- 		} else {
 
- 			this.drillUpButton.attr({
 
- 				text: this.getDrilldownBackText()
 
- 			})
 
- 			.align();
 
- 		}
 
- 	};
 
- 	PieSeries.prototype.animateDrilldown = function (init) {
 
- 		var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
 
- 			animationOptions = this.chart.options.drilldown.animation,
 
- 			animateFrom = level.shapeArgs,
 
- 			start = animateFrom.start,
 
- 			angle = animateFrom.end - start,
 
- 			startAngle = angle / this.points.length,
 
- 			startColor = H.Color(level.color).rgba;
 
- 		if (!init) {
 
- 			each(this.points, function (point, i) {
 
- 				var endColor = H.Color(point.color).rgba;
 
- 				/*jslint unparam: true*/
 
- 				point.graphic
 
- 					.attr(H.merge(animateFrom, {
 
- 						start: start + i * startAngle,
 
- 						end: start + (i + 1) * startAngle
 
- 					}))
 
- 					.animate(point.shapeArgs, H.merge(animationOptions, {
 
- 						step: function (val, fx) {
 
- 							if (fx.prop === 'start') {
 
- 								this.attr({
 
- 									fill: tweenColors(startColor, endColor, fx.pos)
 
- 								});
 
- 							}
 
- 						}
 
- 					}));
 
- 				/*jslint unparam: false*/
 
- 			});
 
- 		}
 
- 	};
 
- 	/**
 
- 	 * When drilling up, keep the upper series invisible until the lower series has
 
- 	 * moved into place
 
- 	 */
 
- 	PieSeries.prototype.animateDrillupTo = 
 
- 			ColumnSeries.prototype.animateDrillupTo = function (init) {
 
- 		if (!init) {
 
- 			var newSeries = this,
 
- 				level = newSeries.drilldownLevel;
 
- 			each(this.points, function (point) {
 
- 				point.graphic.hide();
 
- 				if (point.dataLabel) {
 
- 					point.dataLabel.hide();
 
- 				}
 
- 				if (point.connector) {
 
- 					point.connector.hide();
 
- 				}
 
- 			});
 
- 			// Do dummy animation on first point to get to complete
 
- 			setTimeout(function () {
 
- 				each(newSeries.points, function (point, i) {  
 
- 					// Fade in other points			  
 
- 					var verb = i === level.pointIndex ? 'show' : 'fadeIn';
 
- 					point.graphic[verb]();
 
- 					if (point.dataLabel) {
 
- 						point.dataLabel[verb]();
 
- 					}
 
- 					if (point.connector) {
 
- 						point.connector[verb]();
 
- 					}
 
- 				});
 
- 			}, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
 
- 			// Reset
 
- 			this.animate = noop;
 
- 		}
 
- 	};
 
- 	
 
- 	ColumnSeries.prototype.animateDrilldown = function (init) {
 
- 		var animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs,
 
- 			animationOptions = this.chart.options.drilldown.animation;
 
- 			
 
- 		if (!init) {
 
- 			animateFrom.x += (this.xAxis.oldPos - this.xAxis.pos);
 
- 	
 
- 			each(this.points, function (point) {
 
- 				point.graphic
 
- 					.attr(animateFrom)
 
- 					.animate(point.shapeArgs, animationOptions);
 
- 			});
 
- 		}
 
- 		
 
- 	};
 
- 	/**
 
- 	 * When drilling up, pull out the individual point graphics from the lower series
 
- 	 * and animate them into the origin point in the upper series.
 
- 	 */
 
- 	ColumnSeries.prototype.animateDrillupFrom = 
 
- 		PieSeries.prototype.animateDrillupFrom =
 
- 	function (level) {
 
- 		var animationOptions = this.chart.options.drilldown.animation,
 
- 			group = this.group;
 
- 		delete this.group;
 
- 		each(this.points, function (point) {
 
- 			var graphic = point.graphic,
 
- 				startColor = H.Color(point.color).rgba;
 
- 			delete point.graphic;
 
- 			/*jslint unparam: true*/
 
- 			graphic.animate(level.shapeArgs, H.merge(animationOptions, {
 
- 				step: function (val, fx) {
 
- 					if (fx.prop === 'start') {
 
- 						this.attr({
 
- 							fill: tweenColors(startColor, H.Color(level.color).rgba, fx.pos)
 
- 						});
 
- 					}
 
- 				},
 
- 				complete: function () {
 
- 					graphic.destroy();
 
- 					if (group) {
 
- 						group = group.destroy();
 
- 					}
 
- 				}
 
- 			}));
 
- 			/*jslint unparam: false*/
 
- 		});
 
- 	};
 
- 	
 
- 	H.Point.prototype.doDrilldown = function () {
 
- 		var series = this.series,
 
- 			chart = series.chart,
 
- 			drilldown = chart.options.drilldown,
 
- 			i = drilldown.series.length,
 
- 			seriesOptions;
 
- 		
 
- 		while (i-- && !seriesOptions) {
 
- 			if (drilldown.series[i].id === this.drilldown) {
 
- 				seriesOptions = drilldown.series[i];
 
- 			}
 
- 		}
 
- 		// Fire the event. If seriesOptions is undefined, the implementer can check for 
 
- 		// seriesOptions, and call addSeriesAsDrilldown async if necessary.
 
- 		fireEvent(chart, 'drilldown', { 
 
- 			point: this,
 
- 			seriesOptions: seriesOptions
 
- 		});
 
- 		
 
- 		if (seriesOptions) {
 
- 			chart.addSeriesAsDrilldown(this, seriesOptions);
 
- 		}
 
- 	};
 
- 	
 
- 	wrap(H.Point.prototype, 'init', function (proceed, series, options, x) {
 
- 		var point = proceed.call(this, series, options, x),
 
- 			chart = series.chart,
 
- 			tick = series.xAxis && series.xAxis.ticks[x],
 
- 			tickLabel = tick && tick.label;
 
- 		
 
- 		if (point.drilldown) {
 
- 			
 
- 			// Add the click event to the point label
 
- 			H.addEvent(point, 'click', function () {
 
- 				point.doDrilldown();
 
- 			});
 
- 			
 
- 			// Make axis labels clickable
 
- 			if (tickLabel) {
 
- 				if (!tickLabel._basicStyle) {
 
- 					tickLabel._basicStyle = tickLabel.element.getAttribute('style');
 
- 				}
 
- 				tickLabel
 
- 					.addClass('highcharts-drilldown-axis-label')
 
- 					.css(chart.options.drilldown.activeAxisLabelStyle)
 
- 					.on('click', function () {
 
- 						if (point.doDrilldown) {
 
- 							point.doDrilldown();
 
- 						}
 
- 					});
 
- 					
 
- 			}
 
- 		} else if (tickLabel && tickLabel._basicStyle) {
 
- 			tickLabel.element.setAttribute('style', tickLabel._basicStyle);
 
- 		}
 
- 		
 
- 		return point;
 
- 	});
 
- 	wrap(H.Series.prototype, 'drawDataLabels', function (proceed) {
 
- 		var css = this.chart.options.drilldown.activeDataLabelStyle;
 
- 		proceed.call(this);
 
- 		each(this.points, function (point) {
 
- 			if (point.drilldown && point.dataLabel) {
 
- 				point.dataLabel
 
- 					.attr({
 
- 						'class': 'highcharts-drilldown-data-label'
 
- 					})
 
- 					.css(css)
 
- 					.on('click', function () {
 
- 						point.doDrilldown();
 
- 					});
 
- 			}
 
- 		});
 
- 	});
 
- 	// Mark the trackers with a pointer 
 
- 	ColumnSeries.prototype.supportsDrilldown = true;
 
- 	PieSeries.prototype.supportsDrilldown = true;
 
- 	var type, 
 
- 		drawTrackerWrapper = function (proceed) {
 
- 			proceed.call(this);
 
- 			each(this.points, function (point) {
 
- 				if (point.drilldown && point.graphic) {
 
- 					point.graphic
 
- 						.attr({
 
- 							'class': 'highcharts-drilldown-point'
 
- 						})
 
- 						.css({ cursor: 'pointer' });
 
- 				}
 
- 			});
 
- 		};
 
- 	for (type in seriesTypes) {
 
- 		if (seriesTypes[type].prototype.supportsDrilldown) {
 
- 			wrap(seriesTypes[type].prototype, 'drawTracker', drawTrackerWrapper);
 
- 		}
 
- 	}
 
- 		
 
- }(Highcharts));
 
 
  |