app/assets/javascripts/highcharts/modules/drilldown.js in highcharts-rails-3.0.9 vs app/assets/javascripts/highcharts/modules/drilldown.js in highcharts-rails-3.0.10
- old
+ new
@@ -14,10 +14,11 @@
var noop = function () {},
defaultOptions = H.getOptions(),
each = H.each,
extend = H.extend,
+ format = H.format,
wrap = H.wrap,
Chart = H.Chart,
seriesTypes = H.seriesTypes,
PieSeries = seriesTypes.pie,
ColumnSeries = seriesTypes.column,
@@ -71,55 +72,79 @@
*/
H.SVGRenderer.prototype.Element.prototype.fadeIn = function (animation) {
this
.attr({
opacity: 0.1,
- visibility: 'visible'
+ visibility: 'inherit'
})
.animate({
opacity: 1
}, animation || {
duration: 250
});
};
- // Extend the Chart prototype
- Chart.prototype.drilldownLevels = [];
-
Chart.prototype.addSeriesAsDrilldown = function (point, ddOptions) {
+ this.addSingleSeriesAsDrilldown(point, ddOptions);
+ this.applyDrilldown();
+ };
+ Chart.prototype.addSingleSeriesAsDrilldown = function (point, ddOptions) {
var oldSeries = point.series,
xAxis = oldSeries.xAxis,
yAxis = oldSeries.yAxis,
newSeries,
color = point.color || oldSeries.color,
pointIndex,
- level;
+ levelSeries = [],
+ levelSeriesOptions = [],
+ level,
+ levelNumber;
+
+ levelNumber = oldSeries.levelNumber || 0;
ddOptions = extend({
color: color
}, ddOptions);
pointIndex = inArray(point, oldSeries.points);
+
+ // Record options for all current series
+ each(oldSeries.chart.series, function (series) {
+ if (series.xAxis === xAxis && series.yAxis === yAxis) {
+ levelSeries.push(series);
+ levelSeriesOptions.push(series.userOptions);
+ series.levelNumber = series.levelNumber || 0;
+ }
+ });
+ // Add a record of properties for each drilldown level
level = {
+ levelNumber: levelNumber,
seriesOptions: oldSeries.userOptions,
+ levelSeriesOptions: levelSeriesOptions,
+ levelSeries: levelSeries,
shapeArgs: point.shapeArgs,
bBox: point.graphic.getBBox(),
color: color,
- newSeries: ddOptions,
+ lowerSeriesOptions: 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
}
};
+ // Generate and push it to a lookup array
+ if (!this.drilldownLevels) {
+ this.drilldownLevels = [];
+ }
this.drilldownLevels.push(level);
- newSeries = this.addSeries(ddOptions, false);
+ newSeries = level.lowerSeries = this.addSeries(ddOptions, false);
+ newSeries.levelNumber = levelNumber + 1;
if (xAxis) {
xAxis.oldPos = xAxis.pos;
xAxis.userMin = xAxis.userMax = null;
yAxis.userMin = yAxis.userMax = null;
}
@@ -127,22 +152,35 @@
// Run fancy cross-animation on supported and equal types
if (oldSeries.type === newSeries.type) {
newSeries.animate = newSeries.animateDrilldown || noop;
newSeries.options.animation = true;
}
+ };
+
+ Chart.prototype.applyDrilldown = function () {
+ var drilldownLevels = this.drilldownLevels,
+ levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber;
- oldSeries.remove(false);
+ each(this.drilldownLevels, function (level) {
+ if (level.levelNumber === levelToRemove) {
+ each(level.levelSeries, function (series) {
+ if (series.levelNumber === levelToRemove) { // Not removed, not added as part of a multi-series drilldown
+ series.remove(false);
+ }
+ });
+ }
+ });
this.redraw();
this.showDrillUpButton();
};
Chart.prototype.getDrilldownBackText = function () {
var lastLevel = this.drilldownLevels[this.drilldownLevels.length - 1];
+ lastLevel.series = lastLevel.seriesOptions;
+ return format(this.options.lang.drillUpText, lastLevel);
- return this.options.lang.drillUpText.replace('{series.name}', lastLevel.seriesOptions.name);
-
};
Chart.prototype.showDrillUpButton = function () {
var chart = this,
backText = this.getDrilldownBackText(),
@@ -180,36 +218,66 @@
}
};
Chart.prototype.drillUp = function () {
var chart = this,
- level = chart.drilldownLevels.pop(),
- oldSeries = chart.series[0],
- oldExtremes = level.oldExtremes,
- newSeries = chart.addSeries(level.seriesOptions, false);
+ drilldownLevels = chart.drilldownLevels,
+ levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
+ i = drilldownLevels.length,
+ level,
+ oldSeries,
+ newSeries,
+ oldExtremes,
+ addSeries = function (seriesOptions) {
+ var addedSeries;
+ each(chart.series, function (series) {
+ if (series.userOptions === seriesOptions) {
+ addedSeries = series;
+ }
+ });
+
+ addedSeries = addedSeries || chart.addSeries(seriesOptions, false);
+ if (addedSeries.type === oldSeries.type && addedSeries.animateDrillupTo) {
+ addedSeries.animate = addedSeries.animateDrillupTo;
+ }
+ if (seriesOptions === level.seriesOptions) {
+ newSeries = addedSeries;
+ }
+ };
- fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
+ while (i--) {
- if (newSeries.type === oldSeries.type) {
- newSeries.drilldownLevel = level;
- newSeries.animate = newSeries.animateDrillupTo || noop;
- newSeries.options.animation = true;
+ level = drilldownLevels[i];
+ if (level.levelNumber === levelNumber) {
+ drilldownLevels.pop();
+
+ oldSeries = level.lowerSeries;
- if (oldSeries.animateDrillupFrom) {
- oldSeries.animateDrillupFrom(level);
- }
- }
+ each(level.levelSeriesOptions, addSeries);
+
+ fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
- oldSeries.remove(false);
+ if (newSeries.type === oldSeries.type) {
+ newSeries.drilldownLevel = level;
+ newSeries.options.animation = true;
- // 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);
+ if (oldSeries.animateDrillupFrom) {
+ oldSeries.animateDrillupFrom(level);
+ }
+ }
+
+ oldSeries.remove(false);
+
+ // Reset the zoom level of the upper series
+ if (newSeries.xAxis) {
+ oldExtremes = level.oldExtremes;
+ 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 {
@@ -218,50 +286,18 @@
})
.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*/
- });
- }
- };
-
-
+ ColumnSeries.prototype.supportsDrilldown = true;
+
/**
* When drilling up, keep the upper series invisible until the lower series has
* moved into place
*/
- PieSeries.prototype.animateDrillupTo =
- ColumnSeries.prototype.animateDrillupTo = function (init) {
+ ColumnSeries.prototype.animateDrillupTo = function (init) {
if (!init) {
var newSeries = this,
level = newSeries.drilldownLevel;
each(this.points, function (point) {
@@ -277,17 +313,18 @@
// 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]();
+ var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn',
+ inherit = verb === 'show' ? true : undefined;
+ point.graphic[verb](inherit);
if (point.dataLabel) {
- point.dataLabel[verb]();
+ point.dataLabel[verb](inherit);
}
if (point.connector) {
- point.connector[verb]();
+ point.connector[verb](inherit);
}
});
}, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
// Reset
@@ -295,68 +332,121 @@
}
};
ColumnSeries.prototype.animateDrilldown = function (init) {
- var animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs,
+ var series = this,
+ drilldownLevels = this.chart.drilldownLevels,
+ animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs,
animationOptions = this.chart.options.drilldown.animation;
if (!init) {
+ each(drilldownLevels, function (level) {
+ if (series.userOptions === level.lowerSeriesOptions) {
+ animateFrom = level.shapeArgs;
+ }
+ });
animateFrom.x += (this.xAxis.oldPos - this.xAxis.pos);
each(this.points, function (point) {
- point.graphic
- .attr(animateFrom)
- .animate(point.shapeArgs, animationOptions);
+ if (point.graphic) {
+ point.graphic
+ .attr(animateFrom)
+ .animate(point.shapeArgs, animationOptions);
+ }
if (point.dataLabel) {
point.dataLabel.fadeIn(animationOptions);
}
});
+ this.animate = null;
}
};
/**
* 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) {
+ ColumnSeries.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;
+ if (graphic) {
+
+ delete point.graphic;
- /*jslint unparam: true*/
- graphic.animate(level.shapeArgs, H.merge(animationOptions, {
+ /*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)
- });
+ 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();
+ }
}
- },
- complete: function () {
- graphic.destroy();
- if (group) {
- group = group.destroy();
- }
- }
- }));
- /*jslint unparam: false*/
+ }));
+ /*jslint unparam: false*/
+ }
});
};
+
+ if (PieSeries) {
+ extend(PieSeries.prototype, {
+ supportsDrilldown: true,
+ animateDrillupTo: ColumnSeries.prototype.animateDrillupTo,
+ animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom,
+
+ 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*/
+ });
+ this.animate = null;
+ }
+ }
+ });
+ }
- H.Point.prototype.doDrilldown = function () {
+ H.Point.prototype.doDrilldown = function (_holdRedraw) {
var series = this.series,
chart = series.chart,
drilldown = chart.options.drilldown,
i = (drilldown.series || []).length,
seriesOptions;
@@ -373,11 +463,15 @@
point: this,
seriesOptions: seriesOptions
});
if (seriesOptions) {
- chart.addSeriesAsDrilldown(this, seriesOptions);
+ if (_holdRedraw) {
+ chart.addSingleSeriesAsDrilldown(this, seriesOptions);
+ } else {
+ chart.addSeriesAsDrilldown(this, seriesOptions);
+ }
}
};
wrap(H.Point.prototype, 'init', function (proceed, series, options, x) {
@@ -400,14 +494,21 @@
}
tickLabel
.addClass('highcharts-drilldown-axis-label')
.css(chart.options.drilldown.activeAxisLabelStyle)
.on('click', function () {
- if (point.doDrilldown) {
- point.doDrilldown();
- }
+ each(tickLabel.ddPoints, function (point) {
+ if (point.doDrilldown) {
+ point.doDrilldown(true);
+ }
+ });
+ chart.applyDrilldown();
});
+ if (!tickLabel.ddPoints) {
+ tickLabel.ddPoints = [];
+ }
+ tickLabel.ddPoints.push(point);
}
} else if (tickLabel && tickLabel._basicStyle) {
tickLabel.element.setAttribute('style', tickLabel._basicStyle);
}
@@ -433,11 +534,9 @@
}
});
});
// 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) {