highcharts-rails 3.0.9 → 3.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v3.0.9 (2014-01-15)
2
+ * @license Highcharts JS v3.0.10 (2014-03-10)
3
3
  * MooTools adapter
4
4
  *
5
5
  * (c) 2010-2014 Torstein Honsi
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v3.0.9 (2014-01-15)
2
+ * @license Highcharts JS v3.0.10 (2014-03-10)
3
3
  * Prototype adapter
4
4
  *
5
5
  * @author Michael Nelson, Torstein Honsi.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v3.0.9 (2014-01-15)
2
+ * @license Highcharts JS v3.0.10 (2014-03-10)
3
3
  *
4
4
  * Standalone Highcharts Framework
5
5
  *
@@ -304,7 +304,7 @@ return {
304
304
  // HTML styles
305
305
  } else {
306
306
  styles = {};
307
- styles[elem] = this.now + this.unit;
307
+ styles[this.prop] = this.now + this.unit;
308
308
  Highcharts.css(elem, styles);
309
309
  }
310
310
 
@@ -350,9 +350,10 @@ return {
350
350
  ret,
351
351
  done,
352
352
  options = this.options,
353
+ elem = this.elem,
353
354
  i;
354
-
355
- if (this.elem.stopAnimation) {
355
+
356
+ if (elem.stopAnimation || (elem.attr && !elem.element)) { // #2616, element including flag is destroyed
356
357
  ret = false;
357
358
 
358
359
  } else if (gotoEnd || t >= options.duration + this.startTime) {
@@ -371,7 +372,7 @@ return {
371
372
 
372
373
  if (done) {
373
374
  if (options.complete) {
374
- options.complete.call(this.elem);
375
+ options.complete.call(elem);
375
376
  }
376
377
  }
377
378
  ret = false;
@@ -504,19 +505,16 @@ return {
504
505
  return results;
505
506
  },
506
507
 
508
+ /**
509
+ * Get the element's offset position, corrected by overflow:auto. Loosely based on jQuery's offset method.
510
+ */
507
511
  offset: function (el) {
508
- var left = 0,
509
- top = 0;
510
-
511
- while (el) {
512
- left += el.offsetLeft;
513
- top += el.offsetTop;
514
- el = el.offsetParent;
515
- }
512
+ var docElem = document.documentElement,
513
+ box = el.getBoundingClientRect();
516
514
 
517
515
  return {
518
- left: left,
519
- top: top
516
+ top: box.top + (window.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
517
+ left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
520
518
  };
521
519
  },
522
520
 
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v3.0.9 (2014-01-15)
5
+ * @license Highcharts JS v3.0.10 (2014-03-10)
6
6
  *
7
7
  * (c) 2009-2014 Torstein Honsi
8
8
  *
@@ -155,7 +155,6 @@ var radialAxisMixin = {
155
155
  minorTickLength: 10,
156
156
  minorTickPosition: 'inside',
157
157
  minorTickWidth: 1,
158
- plotBands: [],
159
158
  tickLength: 10,
160
159
  tickPosition: 'inside',
161
160
  tickWidth: 2,
@@ -176,7 +175,6 @@ var radialAxisMixin = {
176
175
  },
177
176
  maxPadding: 0,
178
177
  minPadding: 0,
179
- plotBands: [],
180
178
  showLastLabel: false,
181
179
  tickLength: 0
182
180
  },
@@ -189,7 +187,6 @@ var radialAxisMixin = {
189
187
  x: -3,
190
188
  y: -2
191
189
  },
192
- plotBands: [],
193
190
  showLastLabel: false,
194
191
  title: {
195
192
  x: 4,
@@ -203,11 +200,16 @@ var radialAxisMixin = {
203
200
  */
204
201
  setOptions: function (userOptions) {
205
202
 
206
- this.options = merge(
203
+ var options = this.options = merge(
207
204
  this.defaultOptions,
208
205
  this.defaultRadialOptions,
209
206
  userOptions
210
207
  );
208
+
209
+ // Make sure the plotBands array is instanciated for each Axis (#2649)
210
+ if (!options.plotBands) {
211
+ options.plotBands = [];
212
+ }
211
213
 
212
214
  },
213
215
 
@@ -272,8 +274,7 @@ var radialAxisMixin = {
272
274
  }
273
275
 
274
276
  if (this.isXAxis) {
275
- this.minPixelPadding = this.transA * this.minPointOffset +
276
- (this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
277
+ this.minPixelPadding = this.transA * this.minPointOffset;
277
278
  } else {
278
279
  // This is a workaround for regression #2593, but categories still don't position correctly.
279
280
  // TODO: Implement true handling of Y axis categories on gauges.
@@ -304,10 +305,16 @@ var radialAxisMixin = {
304
305
 
305
306
  // Set the center array
306
307
  this.center = this.pane.center = Highcharts.CenteredSeriesMixin.getCenter.call(this.pane);
308
+
309
+ // The sector is used in Axis.translate to compute the translation of reversed axis points (#2570)
310
+ if (this.isCircular) {
311
+ this.sector = this.endAngleRad - this.startAngleRad;
312
+ }
307
313
 
308
- this.len = this.width = this.height = this.isCircular ?
309
- this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
310
- this.center[2] / 2;
314
+ // Axis len is used to lay out the ticks
315
+ this.len = this.width = this.height = this.center[2] * pick(this.sector, 1) / 2;
316
+
317
+
311
318
  }
312
319
  },
313
320
 
@@ -795,6 +802,7 @@ seriesTypes.arearange = extendClass(seriesTypes.area, {
795
802
 
796
803
  // Set preliminary values
797
804
  point.y = point.high;
805
+ point._plotY = point.plotY;
798
806
  point.plotY = point.plotHigh;
799
807
 
800
808
  // Store original data labels and set preliminary label objects to be picked up
@@ -827,7 +835,7 @@ seriesTypes.arearange = extendClass(seriesTypes.area, {
827
835
 
828
836
  // Reset values
829
837
  point.y = point.low;
830
- point.plotY = point.plotLow;
838
+ point.plotY = point._plotY;
831
839
 
832
840
  // Set the default offset
833
841
  point.below = true;
@@ -1020,12 +1028,18 @@ var GaugeSeries = {
1020
1028
  rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
1021
1029
  baseWidth = dialOptions.baseWidth || 3,
1022
1030
  topWidth = dialOptions.topWidth || 1,
1031
+ overshoot = options.overshoot,
1023
1032
  rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
1024
1033
 
1025
- // Handle the wrap option
1026
- if (options.wrap === false) {
1034
+ // Handle the wrap and overshoot options
1035
+ if (overshoot && typeof overshoot === 'number') {
1036
+ overshoot = overshoot / 180 * Math.PI;
1037
+ rotation = Math.max(yAxis.startAngleRad - overshoot, Math.min(yAxis.endAngleRad + overshoot, rotation));
1038
+
1039
+ } else if (options.wrap === false) {
1027
1040
  rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
1028
1041
  }
1042
+
1029
1043
  rotation = rotation * 180 / Math.PI;
1030
1044
 
1031
1045
  point.shapeType = 'path';
@@ -1457,6 +1471,7 @@ seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
1457
1471
  },
1458
1472
  pointValKey: 'high', // defines the top of the tracker
1459
1473
  doQuartiles: false,
1474
+ drawDataLabels: seriesTypes.arearange ? seriesTypes.arearange.prototype.drawDataLabels : noop,
1460
1475
 
1461
1476
  /**
1462
1477
  * Get the width and X offset, either on top of the linked series column
@@ -1947,7 +1962,7 @@ Axis.prototype.beforePadding = function () {
1947
1962
  var seriesOptions = series.options,
1948
1963
  zData;
1949
1964
 
1950
- if (series.bubblePadding && series.visible) {
1965
+ if (series.bubblePadding && (series.visible || !chart.options.chart.ignoreHiddenSeries)) {
1951
1966
 
1952
1967
  // Correction for #1673
1953
1968
  axis.allowZoomOutside = true;
@@ -2040,14 +2055,20 @@ Axis.prototype.beforePadding = function () {
2040
2055
  var xy,
2041
2056
  chart = this.chart,
2042
2057
  plotX = point.plotX,
2043
- plotY = point.plotY;
2058
+ plotY = point.plotY,
2059
+ clientX;
2044
2060
 
2045
2061
  // Save rectangular plotX, plotY for later computation
2046
2062
  point.rectPlotX = plotX;
2047
2063
  point.rectPlotY = plotY;
2048
2064
 
2049
2065
  // Record the angle in degrees for use in tooltip
2050
- point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
2066
+ clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
2067
+ if (clientX < 0) { // #2665
2068
+ clientX += 360;
2069
+ }
2070
+ point.clientX = clientX;
2071
+
2051
2072
 
2052
2073
  // Find the polar plotX and plotY
2053
2074
  xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
@@ -2330,7 +2351,6 @@ Axis.prototype.beforePadding = function () {
2330
2351
  tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array
2331
2352
  });
2332
2353
  }
2333
-
2334
2354
  // Run uber method
2335
2355
  return proceed.call(this, renew);
2336
2356
  });
@@ -2908,7 +2908,7 @@ if (CanvasRenderingContext2D) {
2908
2908
  });
2909
2909
  }
2910
2910
  }/**
2911
- * @license Highcharts JS v3.0.9 (2014-01-15)
2911
+ * @license Highcharts JS v3.0.10 (2014-03-10)
2912
2912
  * CanVGRenderer Extension module
2913
2913
  *
2914
2914
  * (c) 2011-2012 Torstein Honsi, Erik Olsson
@@ -232,9 +232,8 @@
232
232
  startRow = options.startRow || 0,
233
233
  endRow = options.endRow || Number.MAX_VALUE,
234
234
  startColumn = options.startColumn || 0,
235
- endColumn = options.endColumn || Number.MAX_VALUE,
236
- colNo;
237
-
235
+ endColumn = options.endColumn || Number.MAX_VALUE;
236
+
238
237
  if (table) {
239
238
 
240
239
  if (typeof table === 'string') {
@@ -242,16 +241,14 @@
242
241
  }
243
242
 
244
243
  each(table.getElementsByTagName('tr'), function (tr, rowNo) {
245
- colNo = 0;
246
244
  if (rowNo >= startRow && rowNo <= endRow) {
247
- each(tr.childNodes, function (item) {
245
+ each(tr.children, function (item, colNo) {
248
246
  if ((item.tagName === 'TD' || item.tagName === 'TH') && colNo >= startColumn && colNo <= endColumn) {
249
- if (!columns[colNo]) {
250
- columns[colNo] = [];
247
+ if (!columns[colNo - startColumn]) {
248
+ columns[colNo - startColumn] = [];
251
249
  }
252
- columns[colNo][rowNo - startRow] = item.innerHTML;
253
250
 
254
- colNo += 1;
251
+ columns[colNo - startColumn][rowNo - startRow] = item.innerHTML;
255
252
  }
256
253
  });
257
254
  }
@@ -276,53 +273,56 @@
276
273
  gc; // google column
277
274
 
278
275
  if (googleSpreadsheetKey) {
279
- jQuery.getJSON('https://spreadsheets.google.com/feeds/cells/' +
276
+ jQuery.ajax({
277
+ dataType: 'json',
278
+ url: 'https://spreadsheets.google.com/feeds/cells/' +
280
279
  googleSpreadsheetKey + '/' + (options.googleSpreadsheetWorksheet || 'od6') +
281
280
  '/public/values?alt=json-in-script&callback=?',
282
- function (json) {
283
-
284
- // Prepare the data from the spreadsheat
285
- var cells = json.feed.entry,
286
- cell,
287
- cellCount = cells.length,
288
- colCount = 0,
289
- rowCount = 0,
290
- i;
291
-
292
- // First, find the total number of columns and rows that
293
- // are actually filled with data
294
- for (i = 0; i < cellCount; i++) {
295
- cell = cells[i];
296
- colCount = Math.max(colCount, cell.gs$cell.col);
297
- rowCount = Math.max(rowCount, cell.gs$cell.row);
298
- }
299
-
300
- // Set up arrays containing the column data
301
- for (i = 0; i < colCount; i++) {
302
- if (i >= startColumn && i <= endColumn) {
303
- // Create new columns with the length of either end-start or rowCount
304
- columns[i - startColumn] = [];
305
-
306
- // Setting the length to avoid jslint warning
307
- columns[i - startColumn].length = Math.min(rowCount, endRow - startRow);
281
+ error: options.error,
282
+ success: function (json) {
283
+ // Prepare the data from the spreadsheat
284
+ var cells = json.feed.entry,
285
+ cell,
286
+ cellCount = cells.length,
287
+ colCount = 0,
288
+ rowCount = 0,
289
+ i;
290
+
291
+ // First, find the total number of columns and rows that
292
+ // are actually filled with data
293
+ for (i = 0; i < cellCount; i++) {
294
+ cell = cells[i];
295
+ colCount = Math.max(colCount, cell.gs$cell.col);
296
+ rowCount = Math.max(rowCount, cell.gs$cell.row);
308
297
  }
309
- }
310
298
 
311
- // Loop over the cells and assign the value to the right
312
- // place in the column arrays
313
- for (i = 0; i < cellCount; i++) {
314
- cell = cells[i];
315
- gr = cell.gs$cell.row - 1; // rows start at 1
316
- gc = cell.gs$cell.col - 1; // columns start at 1
317
-
318
- // If both row and col falls inside start and end
319
- // set the transposed cell value in the newly created columns
320
- if (gc >= startColumn && gc <= endColumn &&
321
- gr >= startRow && gr <= endRow) {
322
- columns[gc - startColumn][gr - startRow] = cell.content.$t;
299
+ // Set up arrays containing the column data
300
+ for (i = 0; i < colCount; i++) {
301
+ if (i >= startColumn && i <= endColumn) {
302
+ // Create new columns with the length of either end-start or rowCount
303
+ columns[i - startColumn] = [];
304
+
305
+ // Setting the length to avoid jslint warning
306
+ columns[i - startColumn].length = Math.min(rowCount, endRow - startRow);
307
+ }
323
308
  }
309
+
310
+ // Loop over the cells and assign the value to the right
311
+ // place in the column arrays
312
+ for (i = 0; i < cellCount; i++) {
313
+ cell = cells[i];
314
+ gr = cell.gs$cell.row - 1; // rows start at 1
315
+ gc = cell.gs$cell.col - 1; // columns start at 1
316
+
317
+ // If both row and col falls inside start and end
318
+ // set the transposed cell value in the newly created columns
319
+ if (gc >= startColumn && gc <= endColumn &&
320
+ gr >= startRow && gr <= endRow) {
321
+ columns[gc - startColumn][gr - startRow] = cell.content.$t;
322
+ }
323
+ }
324
+ self.dataFound();
324
325
  }
325
- self.dataFound();
326
326
  });
327
327
  }
328
328
  },
@@ -523,22 +523,27 @@
523
523
 
524
524
  // Iterate down the cells of each column and add data to the series
525
525
  data = [];
526
- for (j = 0; j < columns[i].length; j++) {
527
- data[j] = [
528
- firstCol[j],
529
- columns[i][j] !== undefined ? columns[i][j] : null
530
- ];
531
- if (valueCount > 1) {
532
- data[j].push(columns[i + 1][j] !== undefined ? columns[i + 1][j] : null);
533
- }
534
- if (valueCount > 2) {
535
- data[j].push(columns[i + 2][j] !== undefined ? columns[i + 2][j] : null);
536
- }
537
- if (valueCount > 3) {
538
- data[j].push(columns[i + 3][j] !== undefined ? columns[i + 3][j] : null);
539
- }
540
- if (valueCount > 4) {
541
- data[j].push(columns[i + 4][j] !== undefined ? columns[i + 4][j] : null);
526
+
527
+ // Only loop and fill the data series if there are columns available.
528
+ // We need this check to avoid reading outside the array bounds.
529
+ if (i + valueCount <= columns.length) {
530
+ for (j = 0; j < columns[i].length; j++) {
531
+ data[j] = [
532
+ firstCol[j],
533
+ columns[i][j] !== undefined ? columns[i][j] : null
534
+ ];
535
+ if (valueCount > 1) {
536
+ data[j].push(columns[i + 1][j] !== undefined ? columns[i + 1][j] : null);
537
+ }
538
+ if (valueCount > 2) {
539
+ data[j].push(columns[i + 2][j] !== undefined ? columns[i + 2][j] : null);
540
+ }
541
+ if (valueCount > 3) {
542
+ data[j].push(columns[i + 3][j] !== undefined ? columns[i + 3][j] : null);
543
+ }
544
+ if (valueCount > 4) {
545
+ data[j].push(columns[i + 4][j] !== undefined ? columns[i + 4][j] : null);
546
+ }
542
547
  }
543
548
  }
544
549
 
@@ -16,6 +16,7 @@
16
16
  defaultOptions = H.getOptions(),
17
17
  each = H.each,
18
18
  extend = H.extend,
19
+ format = H.format,
19
20
  wrap = H.wrap,
20
21
  Chart = H.Chart,
21
22
  seriesTypes = H.seriesTypes,
@@ -73,7 +74,7 @@
73
74
  this
74
75
  .attr({
75
76
  opacity: 0.1,
76
- visibility: 'visible'
77
+ visibility: 'inherit'
77
78
  })
78
79
  .animate({
79
80
  opacity: 1
@@ -82,29 +83,48 @@
82
83
  });
83
84
  };
84
85
 
85
- // Extend the Chart prototype
86
- Chart.prototype.drilldownLevels = [];
87
-
88
86
  Chart.prototype.addSeriesAsDrilldown = function (point, ddOptions) {
87
+ this.addSingleSeriesAsDrilldown(point, ddOptions);
88
+ this.applyDrilldown();
89
+ };
90
+ Chart.prototype.addSingleSeriesAsDrilldown = function (point, ddOptions) {
89
91
  var oldSeries = point.series,
90
92
  xAxis = oldSeries.xAxis,
91
93
  yAxis = oldSeries.yAxis,
92
94
  newSeries,
93
95
  color = point.color || oldSeries.color,
94
96
  pointIndex,
95
- level;
97
+ levelSeries = [],
98
+ levelSeriesOptions = [],
99
+ level,
100
+ levelNumber;
101
+
102
+ levelNumber = oldSeries.levelNumber || 0;
96
103
 
97
104
  ddOptions = extend({
98
105
  color: color
99
106
  }, ddOptions);
100
107
  pointIndex = inArray(point, oldSeries.points);
108
+
109
+ // Record options for all current series
110
+ each(oldSeries.chart.series, function (series) {
111
+ if (series.xAxis === xAxis && series.yAxis === yAxis) {
112
+ levelSeries.push(series);
113
+ levelSeriesOptions.push(series.userOptions);
114
+ series.levelNumber = series.levelNumber || 0;
115
+ }
116
+ });
101
117
 
118
+ // Add a record of properties for each drilldown level
102
119
  level = {
120
+ levelNumber: levelNumber,
103
121
  seriesOptions: oldSeries.userOptions,
122
+ levelSeriesOptions: levelSeriesOptions,
123
+ levelSeries: levelSeries,
104
124
  shapeArgs: point.shapeArgs,
105
125
  bBox: point.graphic.getBBox(),
106
126
  color: color,
107
- newSeries: ddOptions,
127
+ lowerSeriesOptions: ddOptions,
108
128
  pointOptions: oldSeries.options.data[pointIndex],
109
129
  pointIndex: pointIndex,
110
130
  oldExtremes: {
@@ -115,9 +135,14 @@
115
135
  }
116
136
  };
117
137
 
138
+ // Generate and push it to a lookup array
139
+ if (!this.drilldownLevels) {
140
+ this.drilldownLevels = [];
141
+ }
118
142
  this.drilldownLevels.push(level);
119
143
 
120
- newSeries = this.addSeries(ddOptions, false);
144
+ newSeries = level.lowerSeries = this.addSeries(ddOptions, false);
145
+ newSeries.levelNumber = levelNumber + 1;
121
146
  if (xAxis) {
122
147
  xAxis.oldPos = xAxis.pos;
123
148
  xAxis.userMin = xAxis.userMax = null;
@@ -129,8 +154,21 @@
129
154
  newSeries.animate = newSeries.animateDrilldown || noop;
130
155
  newSeries.options.animation = true;
131
156
  }
157
+ };
158
+
159
+ Chart.prototype.applyDrilldown = function () {
160
+ var drilldownLevels = this.drilldownLevels,
161
+ levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber;
132
162
 
133
- oldSeries.remove(false);
163
+ each(this.drilldownLevels, function (level) {
164
+ if (level.levelNumber === levelToRemove) {
165
+ each(level.levelSeries, function (series) {
166
+ if (series.levelNumber === levelToRemove) { // Not removed, not added as part of a multi-series drilldown
167
+ series.remove(false);
168
+ }
169
+ });
170
+ }
171
+ });
134
172
 
135
173
  this.redraw();
136
174
  this.showDrillUpButton();
@@ -138,8 +176,8 @@
138
176
 
139
177
  Chart.prototype.getDrilldownBackText = function () {
140
178
  var lastLevel = this.drilldownLevels[this.drilldownLevels.length - 1];
141
-
142
- return this.options.lang.drillUpText.replace('{series.name}', lastLevel.seriesOptions.name);
179
+ lastLevel.series = lastLevel.seriesOptions;
180
+ return format(this.options.lang.drillUpText, lastLevel);
143
181
 
144
182
  };
145
183
 
@@ -182,32 +220,62 @@
182
220
 
183
221
  Chart.prototype.drillUp = function () {
184
222
  var chart = this,
185
- level = chart.drilldownLevels.pop(),
186
- oldSeries = chart.series[0],
187
- oldExtremes = level.oldExtremes,
188
- newSeries = chart.addSeries(level.seriesOptions, false);
223
+ drilldownLevels = chart.drilldownLevels,
224
+ levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
225
+ i = drilldownLevels.length,
226
+ level,
227
+ oldSeries,
228
+ newSeries,
229
+ oldExtremes,
230
+ addSeries = function (seriesOptions) {
231
+ var addedSeries;
232
+ each(chart.series, function (series) {
233
+ if (series.userOptions === seriesOptions) {
234
+ addedSeries = series;
235
+ }
236
+ });
237
+
238
+ addedSeries = addedSeries || chart.addSeries(seriesOptions, false);
239
+ if (addedSeries.type === oldSeries.type && addedSeries.animateDrillupTo) {
240
+ addedSeries.animate = addedSeries.animateDrillupTo;
241
+ }
242
+ if (seriesOptions === level.seriesOptions) {
243
+ newSeries = addedSeries;
244
+ }
245
+ };
189
246
 
190
- fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
247
+ while (i--) {
191
248
 
192
- if (newSeries.type === oldSeries.type) {
193
- newSeries.drilldownLevel = level;
194
- newSeries.animate = newSeries.animateDrillupTo || noop;
195
- newSeries.options.animation = true;
249
+ level = drilldownLevels[i];
250
+ if (level.levelNumber === levelNumber) {
251
+ drilldownLevels.pop();
252
+
253
+ oldSeries = level.lowerSeries;
196
254
 
197
- if (oldSeries.animateDrillupFrom) {
198
- oldSeries.animateDrillupFrom(level);
199
- }
200
- }
255
+ each(level.levelSeriesOptions, addSeries);
256
+
257
+ fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
201
258
 
202
- oldSeries.remove(false);
259
+ if (newSeries.type === oldSeries.type) {
260
+ newSeries.drilldownLevel = level;
261
+ newSeries.options.animation = true;
203
262
 
204
- // Reset the zoom level of the upper series
205
- if (newSeries.xAxis) {
206
- newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false);
207
- newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false);
263
+ if (oldSeries.animateDrillupFrom) {
264
+ oldSeries.animateDrillupFrom(level);
265
+ }
266
+ }
267
+
268
+ oldSeries.remove(false);
269
+
270
+ // Reset the zoom level of the upper series
271
+ if (newSeries.xAxis) {
272
+ oldExtremes = level.oldExtremes;
273
+ newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false);
274
+ newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false);
275
+ }
276
+ }
208
277
  }
209
278
 
210
-
211
279
  this.redraw();
212
280
 
213
281
  if (this.drilldownLevels.length === 0) {
@@ -220,46 +288,14 @@
220
288
  }
221
289
  };
222
290
 
223
- PieSeries.prototype.animateDrilldown = function (init) {
224
- var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
225
- animationOptions = this.chart.options.drilldown.animation,
226
- animateFrom = level.shapeArgs,
227
- start = animateFrom.start,
228
- angle = animateFrom.end - start,
229
- startAngle = angle / this.points.length,
230
- startColor = H.Color(level.color).rgba;
231
-
232
- if (!init) {
233
- each(this.points, function (point, i) {
234
- var endColor = H.Color(point.color).rgba;
235
-
236
- /*jslint unparam: true*/
237
- point.graphic
238
- .attr(H.merge(animateFrom, {
239
- start: start + i * startAngle,
240
- end: start + (i + 1) * startAngle
241
- }))
242
- .animate(point.shapeArgs, H.merge(animationOptions, {
243
- step: function (val, fx) {
244
- if (fx.prop === 'start') {
245
- this.attr({
246
- fill: tweenColors(startColor, endColor, fx.pos)
247
- });
248
- }
249
- }
250
- }));
251
- /*jslint unparam: false*/
252
- });
253
- }
254
- };
255
-
256
291
 
292
+ ColumnSeries.prototype.supportsDrilldown = true;
293
+
257
294
  /**
258
295
  * When drilling up, keep the upper series invisible until the lower series has
259
296
  * moved into place
260
297
  */
261
- PieSeries.prototype.animateDrillupTo =
262
- ColumnSeries.prototype.animateDrillupTo = function (init) {
298
+ ColumnSeries.prototype.animateDrillupTo = function (init) {
263
299
  if (!init) {
264
300
  var newSeries = this,
265
301
  level = newSeries.drilldownLevel;
@@ -279,13 +315,14 @@
279
315
  setTimeout(function () {
280
316
  each(newSeries.points, function (point, i) {
281
317
  // Fade in other points
282
- var verb = i === level.pointIndex ? 'show' : 'fadeIn';
283
- point.graphic[verb]();
318
+ var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn',
319
+ inherit = verb === 'show' ? true : undefined;
320
+ point.graphic[verb](inherit);
284
321
  if (point.dataLabel) {
285
- point.dataLabel[verb]();
322
+ point.dataLabel[verb](inherit);
286
323
  }
287
324
  if (point.connector) {
288
- point.connector[verb]();
325
+ point.connector[verb](inherit);
289
326
  }
290
327
  });
291
328
  }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
@@ -297,21 +334,31 @@
297
334
  };
298
335
 
299
336
  ColumnSeries.prototype.animateDrilldown = function (init) {
300
- var animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs,
337
+ var series = this,
338
+ drilldownLevels = this.chart.drilldownLevels,
339
+ animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs,
301
340
  animationOptions = this.chart.options.drilldown.animation;
302
341
 
303
342
  if (!init) {
343
+ each(drilldownLevels, function (level) {
344
+ if (series.userOptions === level.lowerSeriesOptions) {
345
+ animateFrom = level.shapeArgs;
346
+ }
347
+ });
304
348
 
305
349
  animateFrom.x += (this.xAxis.oldPos - this.xAxis.pos);
306
350
 
307
351
  each(this.points, function (point) {
308
- point.graphic
309
- .attr(animateFrom)
310
- .animate(point.shapeArgs, animationOptions);
352
+ if (point.graphic) {
353
+ point.graphic
354
+ .attr(animateFrom)
355
+ .animate(point.shapeArgs, animationOptions);
356
+ }
311
357
  if (point.dataLabel) {
312
358
  point.dataLabel.fadeIn(animationOptions);
313
359
  }
314
360
  });
361
+ this.animate = null;
315
362
  }
316
363
 
317
364
  };
@@ -320,9 +367,7 @@
320
367
  * When drilling up, pull out the individual point graphics from the lower series
321
368
  * and animate them into the origin point in the upper series.
322
369
  */
323
- ColumnSeries.prototype.animateDrillupFrom =
324
- PieSeries.prototype.animateDrillupFrom =
325
- function (level) {
370
+ ColumnSeries.prototype.animateDrillupFrom = function (level) {
326
371
  var animationOptions = this.chart.options.drilldown.animation,
327
372
  group = this.group;
328
373
 
@@ -331,30 +376,75 @@
331
376
  var graphic = point.graphic,
332
377
  startColor = H.Color(point.color).rgba;
333
378
 
334
- delete point.graphic;
379
+ if (graphic) {
380
+
381
+ delete point.graphic;
335
382
 
336
- /*jslint unparam: true*/
337
- graphic.animate(level.shapeArgs, H.merge(animationOptions, {
383
+ /*jslint unparam: true*/
384
+ graphic.animate(level.shapeArgs, H.merge(animationOptions, {
338
385
 
339
- step: function (val, fx) {
340
- if (fx.prop === 'start') {
341
- this.attr({
342
- fill: tweenColors(startColor, H.Color(level.color).rgba, fx.pos)
343
- });
344
- }
345
- },
346
- complete: function () {
347
- graphic.destroy();
348
- if (group) {
349
- group = group.destroy();
386
+ step: function (val, fx) {
387
+ if (fx.prop === 'start') {
388
+ this.attr({
389
+ fill: tweenColors(startColor, H.Color(level.color).rgba, fx.pos)
390
+ });
391
+ }
392
+ },
393
+ complete: function () {
394
+ graphic.destroy();
395
+ if (group) {
396
+ group = group.destroy();
397
+ }
350
398
  }
351
- }
352
- }));
353
- /*jslint unparam: false*/
399
+ }));
400
+ /*jslint unparam: false*/
401
+ }
354
402
  });
355
403
  };
404
+
405
+ if (PieSeries) {
406
+ extend(PieSeries.prototype, {
407
+ supportsDrilldown: true,
408
+ animateDrillupTo: ColumnSeries.prototype.animateDrillupTo,
409
+ animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom,
410
+
411
+ animateDrilldown: function (init) {
412
+ var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
413
+ animationOptions = this.chart.options.drilldown.animation,
414
+ animateFrom = level.shapeArgs,
415
+ start = animateFrom.start,
416
+ angle = animateFrom.end - start,
417
+ startAngle = angle / this.points.length,
418
+ startColor = H.Color(level.color).rgba;
419
+
420
+ if (!init) {
421
+ each(this.points, function (point, i) {
422
+ var endColor = H.Color(point.color).rgba;
423
+
424
+ /*jslint unparam: true*/
425
+ point.graphic
426
+ .attr(H.merge(animateFrom, {
427
+ start: start + i * startAngle,
428
+ end: start + (i + 1) * startAngle
429
+ }))
430
+ .animate(point.shapeArgs, H.merge(animationOptions, {
431
+ step: function (val, fx) {
432
+ if (fx.prop === 'start') {
433
+ this.attr({
434
+ fill: tweenColors(startColor, endColor, fx.pos)
435
+ });
436
+ }
437
+ }
438
+ }));
439
+ /*jslint unparam: false*/
440
+ });
441
+ this.animate = null;
442
+ }
443
+ }
444
+ });
445
+ }
356
446
 
357
- H.Point.prototype.doDrilldown = function () {
447
+ H.Point.prototype.doDrilldown = function (_holdRedraw) {
358
448
  var series = this.series,
359
449
  chart = series.chart,
360
450
  drilldown = chart.options.drilldown,
@@ -375,7 +465,11 @@
375
465
  });
376
466
 
377
467
  if (seriesOptions) {
378
- chart.addSeriesAsDrilldown(this, seriesOptions);
468
+ if (_holdRedraw) {
469
+ chart.addSingleSeriesAsDrilldown(this, seriesOptions);
470
+ } else {
471
+ chart.addSeriesAsDrilldown(this, seriesOptions);
472
+ }
379
473
  }
380
474
 
381
475
  };
@@ -402,10 +496,17 @@
402
496
  .addClass('highcharts-drilldown-axis-label')
403
497
  .css(chart.options.drilldown.activeAxisLabelStyle)
404
498
  .on('click', function () {
405
- if (point.doDrilldown) {
406
- point.doDrilldown();
407
- }
499
+ each(tickLabel.ddPoints, function (point) {
500
+ if (point.doDrilldown) {
501
+ point.doDrilldown(true);
502
+ }
503
+ });
504
+ chart.applyDrilldown();
408
505
  });
506
+ if (!tickLabel.ddPoints) {
507
+ tickLabel.ddPoints = [];
508
+ }
509
+ tickLabel.ddPoints.push(point);
409
510
 
410
511
  }
411
512
  } else if (tickLabel && tickLabel._basicStyle) {
@@ -435,8 +536,6 @@
435
536
  });
436
537
 
437
538
  // Mark the trackers with a pointer
438
- ColumnSeries.prototype.supportsDrilldown = true;
439
- PieSeries.prototype.supportsDrilldown = true;
440
539
  var type,
441
540
  drawTrackerWrapper = function (proceed) {
442
541
  proceed.call(this);