highcharts-rails 4.2.7 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +34 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +53 -32
  5. data/app/assets/javascripts/highcharts.js +18775 -17176
  6. data/app/assets/javascripts/highcharts/highcharts-3d.js +1849 -1563
  7. data/app/assets/javascripts/highcharts/highcharts-more.js +2162 -1988
  8. data/app/assets/javascripts/highcharts/modules/accessibility.js +1005 -0
  9. data/app/assets/javascripts/highcharts/modules/annotations.js +408 -401
  10. data/app/assets/javascripts/highcharts/modules/boost.js +561 -546
  11. data/app/assets/javascripts/highcharts/modules/broken-axis.js +330 -324
  12. data/app/assets/javascripts/highcharts/modules/data.js +973 -965
  13. data/app/assets/javascripts/highcharts/modules/drilldown.js +783 -723
  14. data/app/assets/javascripts/highcharts/modules/exporting.js +864 -785
  15. data/app/assets/javascripts/highcharts/modules/funnel.js +290 -306
  16. data/app/assets/javascripts/highcharts/modules/heatmap.js +701 -645
  17. data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +150 -132
  18. data/app/assets/javascripts/highcharts/modules/offline-exporting.js +414 -355
  19. data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +164 -0
  20. data/app/assets/javascripts/highcharts/modules/series-label.js +473 -448
  21. data/app/assets/javascripts/highcharts/modules/solid-gauge.js +279 -271
  22. data/app/assets/javascripts/highcharts/modules/treemap.js +921 -886
  23. data/app/assets/javascripts/highcharts/themes/dark-blue.js +307 -244
  24. data/app/assets/javascripts/highcharts/themes/dark-green.js +303 -244
  25. data/app/assets/javascripts/highcharts/themes/dark-unica.js +231 -201
  26. data/app/assets/javascripts/highcharts/themes/gray.js +314 -245
  27. data/app/assets/javascripts/highcharts/themes/grid-light.js +91 -66
  28. data/app/assets/javascripts/highcharts/themes/grid.js +124 -96
  29. data/app/assets/javascripts/highcharts/themes/sand-signika.js +119 -94
  30. data/app/assets/javascripts/highcharts/themes/skies.js +108 -85
  31. data/lib/highcharts/version.rb +1 -1
  32. metadata +13 -14
  33. data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +0 -1
  34. data/app/assets/javascripts/highcharts/modules/canvas-tools.js +0 -3115
  35. data/app/assets/javascripts/highcharts/modules/map.js +0 -2117
@@ -1,731 +1,791 @@
1
1
  /**
2
+ * @license Highcharts JS v5.0.0 (2016-09-29)
2
3
  * Highcharts Drilldown module
3
4
  *
4
5
  * Author: Torstein Honsi
5
6
  * License: www.highcharts.com/license
6
7
  *
7
8
  */
8
-
9
- (function (factory) {
10
- if (typeof module === 'object' && module.exports) {
11
- module.exports = factory;
12
- } else {
13
- factory(Highcharts);
14
- }
15
- }(function (H) {
16
-
17
- 'use strict';
18
-
19
- var noop = function () {},
20
- defaultOptions = H.getOptions(),
21
- each = H.each,
22
- extend = H.extend,
23
- format = H.format,
24
- merge = H.merge,
25
- pick = H.pick,
26
- wrap = H.wrap,
27
- Chart = H.Chart,
28
- seriesTypes = H.seriesTypes,
29
- PieSeries = seriesTypes.pie,
30
- ColumnSeries = seriesTypes.column,
31
- Tick = H.Tick,
32
- fireEvent = H.fireEvent,
33
- inArray = H.inArray,
34
- ddSeriesId = 1;
35
-
36
- // Utilities
37
- /*
38
- * Return an intermediate color between two colors, according to pos where 0
39
- * is the from color and 1 is the to color. This method is copied from ColorAxis.js
40
- * and should always be kept updated, until we get AMD support.
41
- */
42
- function tweenColors(from, to, pos) {
43
- // Check for has alpha, because rgba colors perform worse due to lack of
44
- // support in WebKit.
45
- var hasAlpha,
46
- ret;
47
-
48
- // Unsupported color, return to-color (#3920)
49
- if (!to.rgba.length || !from.rgba.length) {
50
- ret = to.input || 'none';
51
-
52
- // Interpolate
53
- } else {
54
- from = from.rgba;
55
- to = to.rgba;
56
- hasAlpha = (to[3] !== 1 || from[3] !== 1);
57
- ret = (hasAlpha ? 'rgba(' : 'rgb(') +
58
- Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' +
59
- Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' +
60
- Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) +
61
- (hasAlpha ? (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) : '') + ')';
62
- }
63
- return ret;
64
- }
65
- /**
66
- * Handle animation of the color attributes directly
67
- */
68
- each(['fill', 'stroke'], function (prop) {
69
- H.Fx.prototype[prop + 'Setter'] = function () {
70
- this.elem.attr(prop, tweenColors(H.Color(this.start), H.Color(this.end), this.pos));
71
- };
72
- });
73
-
74
- // Add language
75
- extend(defaultOptions.lang, {
76
- drillUpText: ' Back to {series.name}'
77
- });
78
- defaultOptions.drilldown = {
79
- activeAxisLabelStyle: {
80
- cursor: 'pointer',
81
- color: '#0d233a',
82
- fontWeight: 'bold',
83
- textDecoration: 'underline'
84
- },
85
- activeDataLabelStyle: {
86
- cursor: 'pointer',
87
- fontWeight: 'bold',
88
- textDecoration: 'underline'
89
- },
90
- animation: {
91
- duration: 500
92
- },
93
- drillUpButton: {
94
- position: {
95
- align: 'right',
96
- x: -10,
97
- y: 10
98
- }
99
- // relativeTo: 'plotBox'
100
- // theme
101
- }
102
- };
103
-
104
- /**
105
- * A general fadeIn method
106
- */
107
- H.SVGRenderer.prototype.Element.prototype.fadeIn = function (animation) {
108
- this
109
- .attr({
110
- opacity: 0.1,
111
- visibility: 'inherit'
112
- })
113
- .animate({
114
- opacity: pick(this.newOpacity, 1) // newOpacity used in maps
115
- }, animation || {
116
- duration: 250
117
- });
118
- };
119
-
120
- Chart.prototype.addSeriesAsDrilldown = function (point, ddOptions) {
121
- this.addSingleSeriesAsDrilldown(point, ddOptions);
122
- this.applyDrilldown();
123
- };
124
- Chart.prototype.addSingleSeriesAsDrilldown = function (point, ddOptions) {
125
- var oldSeries = point.series,
126
- xAxis = oldSeries.xAxis,
127
- yAxis = oldSeries.yAxis,
128
- newSeries,
129
- color = point.color || oldSeries.color,
130
- pointIndex,
131
- levelSeries = [],
132
- levelSeriesOptions = [],
133
- level,
134
- levelNumber,
135
- last;
136
-
137
- if (!this.drilldownLevels) {
138
- this.drilldownLevels = [];
139
- }
140
-
141
- levelNumber = oldSeries.options._levelNumber || 0;
142
-
143
- // See if we can reuse the registered series from last run
144
- last = this.drilldownLevels[this.drilldownLevels.length - 1];
145
- if (last && last.levelNumber !== levelNumber) {
146
- last = undefined;
147
- }
148
-
149
- if (!ddOptions.color) {
150
- ddOptions.color = color;
151
- }
152
- ddOptions._ddSeriesId = ddSeriesId++;
153
-
154
- pointIndex = inArray(point, oldSeries.points);
155
-
156
- // Record options for all current series
157
- each(oldSeries.chart.series, function (series) {
158
- if (series.xAxis === xAxis && !series.isDrilling) {
159
- series.options._ddSeriesId = series.options._ddSeriesId || ddSeriesId++;
160
- series.options._colorIndex = series.userOptions._colorIndex;
161
- series.options._levelNumber = series.options._levelNumber || levelNumber; // #3182
162
-
163
- if (last) {
164
- levelSeries = last.levelSeries;
165
- levelSeriesOptions = last.levelSeriesOptions;
166
- } else {
167
- levelSeries.push(series);
168
- levelSeriesOptions.push(series.options);
169
- }
170
- }
171
- });
172
-
173
- // Add a record of properties for each drilldown level
174
- level = {
175
- levelNumber: levelNumber,
176
- seriesOptions: oldSeries.options,
177
- levelSeriesOptions: levelSeriesOptions,
178
- levelSeries: levelSeries,
179
- shapeArgs: point.shapeArgs,
180
- bBox: point.graphic ? point.graphic.getBBox() : {}, // no graphic in line series with markers disabled
181
- color: point.isNull ? new Highcharts.Color(color).setOpacity(0).get() : color,
182
- lowerSeriesOptions: ddOptions,
183
- pointOptions: oldSeries.options.data[pointIndex],
184
- pointIndex: pointIndex,
185
- oldExtremes: {
186
- xMin: xAxis && xAxis.userMin,
187
- xMax: xAxis && xAxis.userMax,
188
- yMin: yAxis && yAxis.userMin,
189
- yMax: yAxis && yAxis.userMax
190
- }
191
- };
192
-
193
- // Push it to the lookup array
194
- this.drilldownLevels.push(level);
195
-
196
- newSeries = level.lowerSeries = this.addSeries(ddOptions, false);
197
- newSeries.options._levelNumber = levelNumber + 1;
198
- if (xAxis) {
199
- xAxis.oldPos = xAxis.pos;
200
- xAxis.userMin = xAxis.userMax = null;
201
- yAxis.userMin = yAxis.userMax = null;
202
- }
203
-
204
- // Run fancy cross-animation on supported and equal types
205
- if (oldSeries.type === newSeries.type) {
206
- newSeries.animate = newSeries.animateDrilldown || noop;
207
- newSeries.options.animation = true;
208
- }
209
- };
210
-
211
- Chart.prototype.applyDrilldown = function () {
212
- var drilldownLevels = this.drilldownLevels,
213
- levelToRemove;
214
-
215
- if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading
216
- levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber;
217
- each(this.drilldownLevels, function (level) {
218
- if (level.levelNumber === levelToRemove) {
219
- each(level.levelSeries, function (series) {
220
- if (series.options && series.options._levelNumber === levelToRemove) { // Not removed, not added as part of a multi-series drilldown
221
- series.remove(false);
222
- }
223
- });
224
- }
225
- });
226
- }
227
-
228
- this.redraw();
229
- this.showDrillUpButton();
230
- };
231
-
232
- Chart.prototype.getDrilldownBackText = function () {
233
- var drilldownLevels = this.drilldownLevels,
234
- lastLevel;
235
- if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading
236
- lastLevel = drilldownLevels[drilldownLevels.length - 1];
237
- lastLevel.series = lastLevel.seriesOptions;
238
- return format(this.options.lang.drillUpText, lastLevel);
239
- }
240
-
241
- };
242
-
243
- Chart.prototype.showDrillUpButton = function () {
244
- var chart = this,
245
- backText = this.getDrilldownBackText(),
246
- buttonOptions = chart.options.drilldown.drillUpButton,
247
- attr,
248
- states;
249
-
250
-
251
- if (!this.drillUpButton) {
252
- attr = buttonOptions.theme;
253
- states = attr && attr.states;
254
-
255
- this.drillUpButton = this.renderer.button(
256
- backText,
257
- null,
258
- null,
259
- function () {
260
- chart.drillUp();
261
- },
262
- attr,
263
- states && states.hover,
264
- states && states.select
265
- )
266
- .attr({
267
- align: buttonOptions.position.align,
268
- zIndex: 9
269
- })
270
- .add()
271
- .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
272
- } else {
273
- this.drillUpButton.attr({
274
- text: backText
275
- })
276
- .align();
277
- }
278
- };
279
-
280
- Chart.prototype.drillUp = function () {
281
- var chart = this,
282
- drilldownLevels = chart.drilldownLevels,
283
- levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
284
- i = drilldownLevels.length,
285
- chartSeries = chart.series,
286
- seriesI,
287
- level,
288
- oldSeries,
289
- newSeries,
290
- oldExtremes,
291
- addSeries = function (seriesOptions) {
292
- var addedSeries;
293
- each(chartSeries, function (series) {
294
- if (series.options._ddSeriesId === seriesOptions._ddSeriesId) {
295
- addedSeries = series;
296
- }
297
- });
298
-
299
- addedSeries = addedSeries || chart.addSeries(seriesOptions, false);
300
- if (addedSeries.type === oldSeries.type && addedSeries.animateDrillupTo) {
301
- addedSeries.animate = addedSeries.animateDrillupTo;
302
- }
303
- if (seriesOptions === level.seriesOptions) {
304
- newSeries = addedSeries;
305
- }
306
- };
307
-
308
- while (i--) {
309
-
310
- level = drilldownLevels[i];
311
- if (level.levelNumber === levelNumber) {
312
- drilldownLevels.pop();
313
-
314
- // Get the lower series by reference or id
315
- oldSeries = level.lowerSeries;
316
- if (!oldSeries.chart) { // #2786
317
- seriesI = chartSeries.length; // #2919
318
- while (seriesI--) {
319
- if (chartSeries[seriesI].options.id === level.lowerSeriesOptions.id &&
320
- chartSeries[seriesI].options._levelNumber === levelNumber + 1) { // #3867
321
- oldSeries = chartSeries[seriesI];
322
- break;
323
- }
324
- }
325
- }
326
- oldSeries.xData = []; // Overcome problems with minRange (#2898)
327
-
328
- each(level.levelSeriesOptions, addSeries);
329
-
330
- fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions });
331
-
332
- if (newSeries.type === oldSeries.type) {
333
- newSeries.drilldownLevel = level;
334
- newSeries.options.animation = chart.options.drilldown.animation;
335
-
336
- if (oldSeries.animateDrillupFrom && oldSeries.chart) { // #2919
337
- oldSeries.animateDrillupFrom(level);
338
- }
339
- }
340
- newSeries.options._levelNumber = levelNumber;
341
-
342
- oldSeries.remove(false);
343
-
344
- // Reset the zoom level of the upper series
345
- if (newSeries.xAxis) {
346
- oldExtremes = level.oldExtremes;
347
- newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false);
348
- newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false);
349
- }
350
- }
351
- }
352
-
353
- // Fire a once-off event after all series have been drilled up (#5158)
354
- fireEvent(chart, 'drillupall');
355
-
356
- this.redraw();
357
-
358
- if (this.drilldownLevels.length === 0) {
359
- this.drillUpButton = this.drillUpButton.destroy();
360
- } else {
361
- this.drillUpButton.attr({
362
- text: this.getDrilldownBackText()
363
- })
364
- .align();
365
- }
366
-
367
- this.ddDupes.length = []; // #3315
368
- };
369
-
370
-
371
- ColumnSeries.prototype.supportsDrilldown = true;
372
-
373
- /**
374
- * When drilling up, keep the upper series invisible until the lower series has
375
- * moved into place
376
- */
377
- ColumnSeries.prototype.animateDrillupTo = function (init) {
378
- if (!init) {
379
- var newSeries = this,
380
- level = newSeries.drilldownLevel;
381
-
382
- each(this.points, function (point) {
383
- if (point.graphic) { // #3407
384
- point.graphic.hide();
385
- }
386
- if (point.dataLabel) {
387
- point.dataLabel.hide();
388
- }
389
- if (point.connector) {
390
- point.connector.hide();
391
- }
392
- });
393
-
394
-
395
- // Do dummy animation on first point to get to complete
396
- setTimeout(function () {
397
- if (newSeries.points) { // May be destroyed in the meantime, #3389
398
- each(newSeries.points, function (point, i) {
399
- // Fade in other points
400
- var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn',
401
- inherit = verb === 'show' ? true : undefined;
402
- if (point.graphic) { // #3407
403
- point.graphic[verb](inherit);
404
- }
405
- if (point.dataLabel) {
406
- point.dataLabel[verb](inherit);
407
- }
408
- if (point.connector) {
409
- point.connector[verb](inherit);
410
- }
411
- });
412
- }
413
- }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
414
-
415
- // Reset
416
- this.animate = noop;
417
- }
418
-
419
- };
420
-
421
- ColumnSeries.prototype.animateDrilldown = function (init) {
422
- var series = this,
423
- drilldownLevels = this.chart.drilldownLevels,
424
- animateFrom,
425
- animationOptions = this.chart.options.drilldown.animation,
426
- xAxis = this.xAxis;
427
-
428
- if (!init) {
429
- each(drilldownLevels, function (level) {
430
- if (series.options._ddSeriesId === level.lowerSeriesOptions._ddSeriesId) {
431
- animateFrom = level.shapeArgs;
432
- animateFrom.fill = level.color;
433
- }
434
- });
435
-
436
- animateFrom.x += (pick(xAxis.oldPos, xAxis.pos) - xAxis.pos);
437
-
438
- each(this.points, function (point) {
439
- if (point.graphic) {
440
- point.graphic
441
- .attr(animateFrom)
442
- .animate(
443
- extend(point.shapeArgs, { fill: point.color || series.color }),
444
- animationOptions
445
- );
446
- }
447
- if (point.dataLabel) {
448
- point.dataLabel.fadeIn(animationOptions);
449
- }
450
- });
451
- this.animate = null;
452
- }
453
-
454
- };
455
-
456
- /**
457
- * When drilling up, pull out the individual point graphics from the lower series
458
- * and animate them into the origin point in the upper series.
459
- */
460
- ColumnSeries.prototype.animateDrillupFrom = function (level) {
461
- var animationOptions = this.chart.options.drilldown.animation,
462
- group = this.group,
463
- series = this;
464
-
465
- // Cancel mouse events on the series group (#2787)
466
- each(series.trackerGroups, function (key) {
467
- if (series[key]) { // we don't always have dataLabelsGroup
468
- series[key].on('mouseover');
469
- }
470
- });
471
-
472
-
473
- delete this.group;
474
- each(this.points, function (point) {
475
- var graphic = point.graphic,
476
- complete = function () {
477
- graphic.destroy();
478
- if (group) {
479
- group = group.destroy();
480
- }
481
- };
482
-
483
- if (graphic) {
484
-
485
- delete point.graphic;
486
-
487
- if (animationOptions) {
488
- graphic.animate(
489
- extend(level.shapeArgs, { fill: level.color }),
490
- H.merge(animationOptions, { complete: complete })
491
- );
492
- } else {
493
- graphic.attr(level.shapeArgs);
494
- complete();
495
- }
496
- }
497
- });
498
- };
499
-
500
- if (PieSeries) {
501
- extend(PieSeries.prototype, {
502
- supportsDrilldown: true,
503
- animateDrillupTo: ColumnSeries.prototype.animateDrillupTo,
504
- animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom,
505
-
506
- animateDrilldown: function (init) {
507
- var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
508
- animationOptions = this.chart.options.drilldown.animation,
509
- animateFrom = level.shapeArgs,
510
- start = animateFrom.start,
511
- angle = animateFrom.end - start,
512
- startAngle = angle / this.points.length;
513
-
514
- if (!init) {
515
- each(this.points, function (point, i) {
516
- if (point.graphic) {
517
- point.graphic
518
- .attr(H.merge(animateFrom, {
519
- start: start + i * startAngle,
520
- end: start + (i + 1) * startAngle,
521
- fill: level.color
522
- }))[animationOptions ? 'animate' : 'attr'](
523
- extend(point.shapeArgs, { fill: point.color }),
524
- animationOptions
525
- );
526
- }
527
- });
528
- this.animate = null;
529
- }
530
- }
531
- });
532
- }
533
-
534
- H.Point.prototype.doDrilldown = function (_holdRedraw, category, originalEvent) {
535
- var series = this.series,
536
- chart = series.chart,
537
- drilldown = chart.options.drilldown,
538
- i = (drilldown.series || []).length,
539
- seriesOptions;
540
-
541
- if (!chart.ddDupes) {
542
- chart.ddDupes = [];
543
- }
544
-
545
- while (i-- && !seriesOptions) {
546
- if (drilldown.series[i].id === this.drilldown && inArray(this.drilldown, chart.ddDupes) === -1) {
547
- seriesOptions = drilldown.series[i];
548
- chart.ddDupes.push(this.drilldown);
549
- }
550
- }
551
-
552
- // Fire the event. If seriesOptions is undefined, the implementer can check for
553
- // seriesOptions, and call addSeriesAsDrilldown async if necessary.
554
- fireEvent(chart, 'drilldown', {
555
- point: this,
556
- seriesOptions: seriesOptions,
557
- category: category,
558
- originalEvent: originalEvent,
559
- points: category !== undefined && this.series.xAxis.getDDPoints(category).slice(0)
560
- }, function (e) {
561
- var chart = e.point.series && e.point.series.chart,
562
- seriesOptions = e.seriesOptions;
563
- if (chart && seriesOptions) {
564
- if (_holdRedraw) {
565
- chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
566
- } else {
567
- chart.addSeriesAsDrilldown(e.point, seriesOptions);
568
- }
569
- }
570
- });
571
-
572
-
573
- };
574
-
575
- /**
576
- * Drill down to a given category. This is the same as clicking on an axis label.
577
- */
578
- H.Axis.prototype.drilldownCategory = function (x, e) {
579
- var key,
580
- point,
581
- ddPointsX = this.getDDPoints(x);
582
- for (key in ddPointsX) {
583
- point = ddPointsX[key];
584
- if (point && point.series && point.series.visible && point.doDrilldown) { // #3197
585
- point.doDrilldown(true, x, e);
586
- }
587
- }
588
- this.chart.applyDrilldown();
589
- };
590
-
591
- /**
592
- * Return drillable points for this specific X value
593
- */
594
- H.Axis.prototype.getDDPoints = function (x) {
595
- var ret = [];
596
- each(this.series, function (series) {
597
- var i,
598
- xData = series.xData,
599
- points = series.points;
600
-
601
- for (i = 0; i < xData.length; i++) {
602
- if (xData[i] === x && series.options.data[i].drilldown) {
603
- ret.push(points ? points[i] : true);
604
- break;
605
- }
606
- }
607
- });
608
- return ret;
609
- };
610
-
611
-
612
- /**
613
- * Make a tick label drillable, or remove drilling on update
614
- */
615
- Tick.prototype.drillable = function () {
616
- var pos = this.pos,
617
- label = this.label,
618
- axis = this.axis,
619
- isDrillable = axis.coll === 'xAxis' && axis.getDDPoints,
620
- ddPointsX = isDrillable && axis.getDDPoints(pos);
621
-
622
- if (isDrillable) {
623
- if (label && ddPointsX.length) {
624
- if (!label.basicStyles) {
625
- label.basicStyles = H.merge(label.styles);
626
- }
627
- label
628
- .addClass('highcharts-drilldown-axis-label')
629
- .css(axis.chart.options.drilldown.activeAxisLabelStyle)
630
- .on('click', function (e) {
631
- axis.drilldownCategory(pos, e);
632
- });
633
-
634
- } else if (label && label.basicStyles) {
635
- label.styles = {}; // reset for full overwrite of styles
636
- label.css(label.basicStyles);
637
- label.on('click', null); // #3806
638
- }
639
- }
640
- };
641
-
642
- /**
643
- * Always keep the drillability updated (#3951)
644
- */
645
- wrap(Tick.prototype, 'addLabel', function (proceed) {
646
- proceed.call(this);
647
- this.drillable();
648
- });
649
-
650
-
651
- /**
652
- * On initialization of each point, identify its label and make it clickable. Also, provide a
653
- * list of points associated to that label.
654
- */
655
- wrap(H.Point.prototype, 'init', function (proceed, series, options, x) {
656
- var point = proceed.call(this, series, options, x),
657
- xAxis = series.xAxis,
658
- tick = xAxis && xAxis.ticks[x];
659
-
660
- if (point.drilldown) {
661
-
662
- // Add the click event to the point
663
- H.addEvent(point, 'click', function (e) {
664
- if (series.xAxis && series.chart.options.drilldown.allowPointDrilldown === false) {
665
- series.xAxis.drilldownCategory(x, e);
666
- } else {
667
- point.doDrilldown(undefined, undefined, e);
668
- }
669
- });
670
- /*wrap(point, 'importEvents', function (proceed) { // wrapping importEvents makes point.click event work
671
- if (!this.hasImportedEvents) {
672
- proceed.call(this);
673
- H.addEvent(this, 'click', function () {
674
- this.doDrilldown();
675
- });
676
- }
677
- });*/
678
-
679
- }
680
-
681
- // Add or remove click handler and style on the tick label
682
- if (tick) {
683
- tick.drillable();
684
- }
685
-
686
- return point;
687
- });
688
-
689
- wrap(H.Series.prototype, 'drawDataLabels', function (proceed) {
690
- var series = this,
691
- css = series.chart.options.drilldown.activeDataLabelStyle,
692
- renderer = series.chart.renderer;
693
-
694
- proceed.call(series);
695
-
696
- each(series.points, function (point) {
697
- var pointCss = {};
698
- if (point.drilldown && point.dataLabel) {
699
- if (css.color === 'contrast') {
700
- pointCss.color = renderer.getContrast(point.color || series.color);
701
- }
702
- point.dataLabel
703
- .attr({
704
- 'class': 'highcharts-drilldown-data-label'
705
- })
706
- .css(merge(css, pointCss));
707
- }
708
- });
709
- });
710
-
711
- // Mark the trackers with a pointer
712
- var type,
713
- drawTrackerWrapper = function (proceed) {
714
- proceed.call(this);
715
- each(this.points, function (point) {
716
- if (point.drilldown && point.graphic) {
717
- point.graphic
718
- .attr({
719
- 'class': 'highcharts-drilldown-point'
720
- })
721
- .css({ cursor: 'pointer' });
722
- }
723
- });
724
- };
725
- for (type in seriesTypes) {
726
- if (seriesTypes[type].prototype.supportsDrilldown) {
727
- wrap(seriesTypes[type].prototype, 'drawTracker', drawTrackerWrapper);
728
- }
729
- }
730
-
9
+ (function(factory) {
10
+ if (typeof module === 'object' && module.exports) {
11
+ module.exports = factory;
12
+ } else {
13
+ factory(Highcharts);
14
+ }
15
+ }(function(Highcharts) {
16
+ (function(H) {
17
+ /**
18
+ * Highcharts Drilldown module
19
+ *
20
+ * Author: Torstein Honsi
21
+ * License: www.highcharts.com/license
22
+ *
23
+ */
24
+
25
+ 'use strict';
26
+
27
+ var noop = H.noop,
28
+ color = H.color,
29
+ defaultOptions = H.defaultOptions,
30
+ each = H.each,
31
+ extend = H.extend,
32
+ format = H.format,
33
+ pick = H.pick,
34
+ wrap = H.wrap,
35
+ Chart = H.Chart,
36
+ seriesTypes = H.seriesTypes,
37
+ PieSeries = seriesTypes.pie,
38
+ ColumnSeries = seriesTypes.column,
39
+ Tick = H.Tick,
40
+ fireEvent = H.fireEvent,
41
+ inArray = H.inArray,
42
+ ddSeriesId = 1;
43
+
44
+ // Utilities
45
+ /*
46
+ * Return an intermediate color between two colors, according to pos where 0
47
+ * is the from color and 1 is the to color. This method is copied from ColorAxis.js
48
+ * and should always be kept updated, until we get AMD support.
49
+ */
50
+ function tweenColors(from, to, pos) {
51
+ // Check for has alpha, because rgba colors perform worse due to lack of
52
+ // support in WebKit.
53
+ var hasAlpha,
54
+ ret;
55
+
56
+ // Unsupported color, return to-color (#3920)
57
+ if (!to.rgba.length || !from.rgba.length) {
58
+ ret = to.input || 'none';
59
+
60
+ // Interpolate
61
+ } else {
62
+ from = from.rgba;
63
+ to = to.rgba;
64
+ hasAlpha = (to[3] !== 1 || from[3] !== 1);
65
+ ret = (hasAlpha ? 'rgba(' : 'rgb(') +
66
+ Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' +
67
+ Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' +
68
+ Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) +
69
+ (hasAlpha ? (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) : '') + ')';
70
+ }
71
+ return ret;
72
+ }
73
+ /**
74
+ * Handle animation of the color attributes directly
75
+ */
76
+ each(['fill', 'stroke'], function(prop) {
77
+ H.Fx.prototype[prop + 'Setter'] = function() {
78
+ this.elem.attr(prop, tweenColors(color(this.start), color(this.end), this.pos));
79
+ };
80
+ });
81
+
82
+ // Add language
83
+ extend(defaultOptions.lang, {
84
+ drillUpText: '◁ Back to {series.name}'
85
+ });
86
+ defaultOptions.drilldown = {
87
+
88
+ activeAxisLabelStyle: {
89
+ cursor: 'pointer',
90
+ color: '#003399',
91
+ fontWeight: 'bold',
92
+ textDecoration: 'underline'
93
+ },
94
+ activeDataLabelStyle: {
95
+ cursor: 'pointer',
96
+ color: '#003399',
97
+ fontWeight: 'bold',
98
+ textDecoration: 'underline'
99
+ },
100
+
101
+ animation: {
102
+ duration: 500
103
+ },
104
+ drillUpButton: {
105
+ position: {
106
+ align: 'right',
107
+ x: -10,
108
+ y: 10
109
+ }
110
+ // relativeTo: 'plotBox'
111
+ // theme
112
+ }
113
+ };
114
+
115
+ /**
116
+ * A general fadeIn method
117
+ */
118
+ H.SVGRenderer.prototype.Element.prototype.fadeIn = function(animation) {
119
+ this
120
+ .attr({
121
+ opacity: 0.1,
122
+ visibility: 'inherit'
123
+ })
124
+ .animate({
125
+ opacity: pick(this.newOpacity, 1) // newOpacity used in maps
126
+ }, animation || {
127
+ duration: 250
128
+ });
129
+ };
130
+
131
+ Chart.prototype.addSeriesAsDrilldown = function(point, ddOptions) {
132
+ this.addSingleSeriesAsDrilldown(point, ddOptions);
133
+ this.applyDrilldown();
134
+ };
135
+ Chart.prototype.addSingleSeriesAsDrilldown = function(point, ddOptions) {
136
+ var oldSeries = point.series,
137
+ xAxis = oldSeries.xAxis,
138
+ yAxis = oldSeries.yAxis,
139
+ newSeries,
140
+ pointIndex,
141
+ levelSeries = [],
142
+ levelSeriesOptions = [],
143
+ level,
144
+ levelNumber,
145
+ last,
146
+ colorProp;
147
+
148
+
149
+
150
+ colorProp = {
151
+ color: point.color || oldSeries.color
152
+ };
153
+
154
+
155
+ if (!this.drilldownLevels) {
156
+ this.drilldownLevels = [];
157
+ }
158
+
159
+ levelNumber = oldSeries.options._levelNumber || 0;
160
+
161
+ // See if we can reuse the registered series from last run
162
+ last = this.drilldownLevels[this.drilldownLevels.length - 1];
163
+ if (last && last.levelNumber !== levelNumber) {
164
+ last = undefined;
165
+ }
166
+
167
+ ddOptions = extend(extend({
168
+ _ddSeriesId: ddSeriesId++
169
+ }, colorProp), ddOptions);
170
+ pointIndex = inArray(point, oldSeries.points);
171
+
172
+ // Record options for all current series
173
+ each(oldSeries.chart.series, function(series) {
174
+ if (series.xAxis === xAxis && !series.isDrilling) {
175
+ series.options._ddSeriesId = series.options._ddSeriesId || ddSeriesId++;
176
+ series.options._colorIndex = series.userOptions._colorIndex;
177
+ series.options._levelNumber = series.options._levelNumber || levelNumber; // #3182
178
+
179
+ if (last) {
180
+ levelSeries = last.levelSeries;
181
+ levelSeriesOptions = last.levelSeriesOptions;
182
+ } else {
183
+ levelSeries.push(series);
184
+ levelSeriesOptions.push(series.options);
185
+ }
186
+ }
187
+ });
188
+
189
+ // Add a record of properties for each drilldown level
190
+ level = extend({
191
+ levelNumber: levelNumber,
192
+ seriesOptions: oldSeries.options,
193
+ levelSeriesOptions: levelSeriesOptions,
194
+ levelSeries: levelSeries,
195
+ shapeArgs: point.shapeArgs,
196
+ bBox: point.graphic ? point.graphic.getBBox() : {}, // no graphic in line series with markers disabled
197
+ lowerSeriesOptions: ddOptions,
198
+ pointOptions: oldSeries.options.data[pointIndex],
199
+ pointIndex: pointIndex,
200
+ oldExtremes: {
201
+ xMin: xAxis && xAxis.userMin,
202
+ xMax: xAxis && xAxis.userMax,
203
+ yMin: yAxis && yAxis.userMin,
204
+ yMax: yAxis && yAxis.userMax
205
+ }
206
+ }, colorProp);
207
+
208
+ // Push it to the lookup array
209
+ this.drilldownLevels.push(level);
210
+
211
+ newSeries = level.lowerSeries = this.addSeries(ddOptions, false);
212
+ newSeries.options._levelNumber = levelNumber + 1;
213
+ if (xAxis) {
214
+ xAxis.oldPos = xAxis.pos;
215
+ xAxis.userMin = xAxis.userMax = null;
216
+ yAxis.userMin = yAxis.userMax = null;
217
+ }
218
+
219
+ // Run fancy cross-animation on supported and equal types
220
+ if (oldSeries.type === newSeries.type) {
221
+ newSeries.animate = newSeries.animateDrilldown || noop;
222
+ newSeries.options.animation = true;
223
+ }
224
+ };
225
+
226
+ Chart.prototype.applyDrilldown = function() {
227
+ var drilldownLevels = this.drilldownLevels,
228
+ levelToRemove;
229
+
230
+ if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading
231
+ levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber;
232
+ each(this.drilldownLevels, function(level) {
233
+ if (level.levelNumber === levelToRemove) {
234
+ each(level.levelSeries, function(series) {
235
+ if (series.options && series.options._levelNumber === levelToRemove) { // Not removed, not added as part of a multi-series drilldown
236
+ series.remove(false);
237
+ }
238
+ });
239
+ }
240
+ });
241
+ }
242
+
243
+ this.redraw();
244
+ this.showDrillUpButton();
245
+ };
246
+
247
+ Chart.prototype.getDrilldownBackText = function() {
248
+ var drilldownLevels = this.drilldownLevels,
249
+ lastLevel;
250
+ if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading
251
+ lastLevel = drilldownLevels[drilldownLevels.length - 1];
252
+ lastLevel.series = lastLevel.seriesOptions;
253
+ return format(this.options.lang.drillUpText, lastLevel);
254
+ }
255
+
256
+ };
257
+
258
+ Chart.prototype.showDrillUpButton = function() {
259
+ var chart = this,
260
+ backText = this.getDrilldownBackText(),
261
+ buttonOptions = chart.options.drilldown.drillUpButton,
262
+ attr,
263
+ states;
264
+
265
+
266
+ if (!this.drillUpButton) {
267
+ attr = buttonOptions.theme;
268
+ states = attr && attr.states;
269
+
270
+ this.drillUpButton = this.renderer.button(
271
+ backText,
272
+ null,
273
+ null,
274
+ function() {
275
+ chart.drillUp();
276
+ },
277
+ attr,
278
+ states && states.hover,
279
+ states && states.select
280
+ )
281
+ .addClass('highcharts-drillup-button')
282
+ .attr({
283
+ align: buttonOptions.position.align,
284
+ zIndex: 7
285
+ })
286
+ .add()
287
+ .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
288
+ } else {
289
+ this.drillUpButton.attr({
290
+ text: backText
291
+ })
292
+ .align();
293
+ }
294
+ };
295
+
296
+ Chart.prototype.drillUp = function() {
297
+ var chart = this,
298
+ drilldownLevels = chart.drilldownLevels,
299
+ levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
300
+ i = drilldownLevels.length,
301
+ chartSeries = chart.series,
302
+ seriesI,
303
+ level,
304
+ oldSeries,
305
+ newSeries,
306
+ oldExtremes,
307
+ addSeries = function(seriesOptions) {
308
+ var addedSeries;
309
+ each(chartSeries, function(series) {
310
+ if (series.options._ddSeriesId === seriesOptions._ddSeriesId) {
311
+ addedSeries = series;
312
+ }
313
+ });
314
+
315
+ addedSeries = addedSeries || chart.addSeries(seriesOptions, false);
316
+ if (addedSeries.type === oldSeries.type && addedSeries.animateDrillupTo) {
317
+ addedSeries.animate = addedSeries.animateDrillupTo;
318
+ }
319
+ if (seriesOptions === level.seriesOptions) {
320
+ newSeries = addedSeries;
321
+ }
322
+ };
323
+
324
+ while (i--) {
325
+
326
+ level = drilldownLevels[i];
327
+ if (level.levelNumber === levelNumber) {
328
+ drilldownLevels.pop();
329
+
330
+ // Get the lower series by reference or id
331
+ oldSeries = level.lowerSeries;
332
+ if (!oldSeries.chart) { // #2786
333
+ seriesI = chartSeries.length; // #2919
334
+ while (seriesI--) {
335
+ if (chartSeries[seriesI].options.id === level.lowerSeriesOptions.id &&
336
+ chartSeries[seriesI].options._levelNumber === levelNumber + 1) { // #3867
337
+ oldSeries = chartSeries[seriesI];
338
+ break;
339
+ }
340
+ }
341
+ }
342
+ oldSeries.xData = []; // Overcome problems with minRange (#2898)
343
+
344
+ each(level.levelSeriesOptions, addSeries);
345
+
346
+ fireEvent(chart, 'drillup', {
347
+ seriesOptions: level.seriesOptions
348
+ });
349
+
350
+ if (newSeries.type === oldSeries.type) {
351
+ newSeries.drilldownLevel = level;
352
+ newSeries.options.animation = chart.options.drilldown.animation;
353
+
354
+ if (oldSeries.animateDrillupFrom && oldSeries.chart) { // #2919
355
+ oldSeries.animateDrillupFrom(level);
356
+ }
357
+ }
358
+ newSeries.options._levelNumber = levelNumber;
359
+
360
+ oldSeries.remove(false);
361
+
362
+ // Reset the zoom level of the upper series
363
+ if (newSeries.xAxis) {
364
+ oldExtremes = level.oldExtremes;
365
+ newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false);
366
+ newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false);
367
+ }
368
+ }
369
+ }
370
+
371
+ // Fire a once-off event after all series have been drilled up (#5158)
372
+ fireEvent(chart, 'drillupall');
373
+
374
+ this.redraw();
375
+
376
+ if (this.drilldownLevels.length === 0) {
377
+ this.drillUpButton = this.drillUpButton.destroy();
378
+ } else {
379
+ this.drillUpButton.attr({
380
+ text: this.getDrilldownBackText()
381
+ })
382
+ .align();
383
+ }
384
+
385
+ this.ddDupes.length = []; // #3315
386
+ };
387
+
388
+
389
+ ColumnSeries.prototype.supportsDrilldown = true;
390
+
391
+ /**
392
+ * When drilling up, keep the upper series invisible until the lower series has
393
+ * moved into place
394
+ */
395
+ ColumnSeries.prototype.animateDrillupTo = function(init) {
396
+ if (!init) {
397
+ var newSeries = this,
398
+ level = newSeries.drilldownLevel;
399
+
400
+ each(this.points, function(point) {
401
+ if (point.graphic) { // #3407
402
+ point.graphic.hide();
403
+ }
404
+ if (point.dataLabel) {
405
+ point.dataLabel.hide();
406
+ }
407
+ if (point.connector) {
408
+ point.connector.hide();
409
+ }
410
+ });
411
+
412
+
413
+ // Do dummy animation on first point to get to complete
414
+ setTimeout(function() {
415
+ if (newSeries.points) { // May be destroyed in the meantime, #3389
416
+ each(newSeries.points, function(point, i) {
417
+ // Fade in other points
418
+ var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn',
419
+ inherit = verb === 'show' ? true : undefined;
420
+ if (point.graphic) { // #3407
421
+ point.graphic[verb](inherit);
422
+ }
423
+ if (point.dataLabel) {
424
+ point.dataLabel[verb](inherit);
425
+ }
426
+ if (point.connector) {
427
+ point.connector[verb](inherit);
428
+ }
429
+ });
430
+ }
431
+ }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
432
+
433
+ // Reset
434
+ this.animate = noop;
435
+ }
436
+
437
+ };
438
+
439
+ ColumnSeries.prototype.animateDrilldown = function(init) {
440
+ var series = this,
441
+ drilldownLevels = this.chart.drilldownLevels,
442
+ animateFrom,
443
+ animationOptions = this.chart.options.drilldown.animation,
444
+ xAxis = this.xAxis;
445
+
446
+ if (!init) {
447
+ each(drilldownLevels, function(level) {
448
+ if (series.options._ddSeriesId === level.lowerSeriesOptions._ddSeriesId) {
449
+ animateFrom = level.shapeArgs;
450
+
451
+ // Add the point colors to animate from
452
+ animateFrom.fill = level.color;
453
+
454
+ }
455
+ });
456
+
457
+ animateFrom.x += (pick(xAxis.oldPos, xAxis.pos) - xAxis.pos);
458
+
459
+ each(this.points, function(point) {
460
+ var animateTo = point.shapeArgs;
461
+
462
+
463
+ // Add the point colors to animate to
464
+ animateTo.fill = point.color;
465
+
466
+
467
+ if (point.graphic) {
468
+ point.graphic
469
+ .attr(animateFrom)
470
+ .animate(
471
+ extend(point.shapeArgs, {
472
+ fill: point.color || series.color
473
+ }),
474
+ animationOptions
475
+ );
476
+ }
477
+ if (point.dataLabel) {
478
+ point.dataLabel.fadeIn(animationOptions);
479
+ }
480
+ });
481
+ this.animate = null;
482
+ }
483
+
484
+ };
485
+
486
+ /**
487
+ * When drilling up, pull out the individual point graphics from the lower series
488
+ * and animate them into the origin point in the upper series.
489
+ */
490
+ ColumnSeries.prototype.animateDrillupFrom = function(level) {
491
+ var animationOptions = this.chart.options.drilldown.animation,
492
+ group = this.group,
493
+ series = this;
494
+
495
+ // Cancel mouse events on the series group (#2787)
496
+ each(series.trackerGroups, function(key) {
497
+ if (series[key]) { // we don't always have dataLabelsGroup
498
+ series[key].on('mouseover');
499
+ }
500
+ });
501
+
502
+
503
+ delete this.group;
504
+ each(this.points, function(point) {
505
+ var graphic = point.graphic,
506
+ animateTo = level.shapeArgs,
507
+ complete = function() {
508
+ graphic.destroy();
509
+ if (group) {
510
+ group = group.destroy();
511
+ }
512
+ };
513
+
514
+ if (graphic) {
515
+
516
+ delete point.graphic;
517
+
518
+
519
+ animateTo.fill = level.color;
520
+
521
+
522
+ if (animationOptions) {
523
+ graphic.animate(
524
+ animateTo,
525
+ H.merge(animationOptions, {
526
+ complete: complete
527
+ })
528
+ );
529
+ } else {
530
+ graphic.attr(animateTo);
531
+ complete();
532
+ }
533
+ }
534
+ });
535
+ };
536
+
537
+ if (PieSeries) {
538
+ extend(PieSeries.prototype, {
539
+ supportsDrilldown: true,
540
+ animateDrillupTo: ColumnSeries.prototype.animateDrillupTo,
541
+ animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom,
542
+
543
+ animateDrilldown: function(init) {
544
+ var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1],
545
+ animationOptions = this.chart.options.drilldown.animation,
546
+ animateFrom = level.shapeArgs,
547
+ start = animateFrom.start,
548
+ angle = animateFrom.end - start,
549
+ startAngle = angle / this.points.length;
550
+
551
+ if (!init) {
552
+ each(this.points, function(point, i) {
553
+ var animateTo = point.shapeArgs;
554
+
555
+
556
+ animateFrom.fill = level.color;
557
+ animateTo.fill = point.color;
558
+
559
+
560
+ if (point.graphic) {
561
+ point.graphic
562
+ .attr(H.merge(animateFrom, {
563
+ start: start + i * startAngle,
564
+ end: start + (i + 1) * startAngle
565
+ }))[animationOptions ? 'animate' : 'attr'](
566
+ animateTo,
567
+ animationOptions
568
+ );
569
+ }
570
+ });
571
+ this.animate = null;
572
+ }
573
+ }
574
+ });
575
+ }
576
+
577
+ H.Point.prototype.doDrilldown = function(_holdRedraw, category, originalEvent) {
578
+ var series = this.series,
579
+ chart = series.chart,
580
+ drilldown = chart.options.drilldown,
581
+ i = (drilldown.series || []).length,
582
+ seriesOptions;
583
+
584
+ if (!chart.ddDupes) {
585
+ chart.ddDupes = [];
586
+ }
587
+
588
+ while (i-- && !seriesOptions) {
589
+ if (drilldown.series[i].id === this.drilldown && inArray(this.drilldown, chart.ddDupes) === -1) {
590
+ seriesOptions = drilldown.series[i];
591
+ chart.ddDupes.push(this.drilldown);
592
+ }
593
+ }
594
+
595
+ // Fire the event. If seriesOptions is undefined, the implementer can check for
596
+ // seriesOptions, and call addSeriesAsDrilldown async if necessary.
597
+ fireEvent(chart, 'drilldown', {
598
+ point: this,
599
+ seriesOptions: seriesOptions,
600
+ category: category,
601
+ originalEvent: originalEvent,
602
+ points: category !== undefined && this.series.xAxis.getDDPoints(category).slice(0)
603
+ }, function(e) {
604
+ var chart = e.point.series && e.point.series.chart,
605
+ seriesOptions = e.seriesOptions;
606
+ if (chart && seriesOptions) {
607
+ if (_holdRedraw) {
608
+ chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
609
+ } else {
610
+ chart.addSeriesAsDrilldown(e.point, seriesOptions);
611
+ }
612
+ }
613
+ });
614
+
615
+
616
+ };
617
+
618
+ /**
619
+ * Drill down to a given category. This is the same as clicking on an axis label.
620
+ */
621
+ H.Axis.prototype.drilldownCategory = function(x, e) {
622
+ var key,
623
+ point,
624
+ ddPointsX = this.getDDPoints(x);
625
+ for (key in ddPointsX) {
626
+ point = ddPointsX[key];
627
+ if (point && point.series && point.series.visible && point.doDrilldown) { // #3197
628
+ point.doDrilldown(true, x, e);
629
+ }
630
+ }
631
+ this.chart.applyDrilldown();
632
+ };
633
+
634
+ /**
635
+ * Return drillable points for this specific X value
636
+ */
637
+ H.Axis.prototype.getDDPoints = function(x) {
638
+ var ret = [];
639
+ each(this.series, function(series) {
640
+ var i,
641
+ xData = series.xData,
642
+ points = series.points;
643
+
644
+ for (i = 0; i < xData.length; i++) {
645
+ if (xData[i] === x && series.options.data[i].drilldown) {
646
+ ret.push(points ? points[i] : true);
647
+ break;
648
+ }
649
+ }
650
+ });
651
+ return ret;
652
+ };
653
+
654
+
655
+ /**
656
+ * Make a tick label drillable, or remove drilling on update
657
+ */
658
+ Tick.prototype.drillable = function() {
659
+ var pos = this.pos,
660
+ label = this.label,
661
+ axis = this.axis,
662
+ isDrillable = axis.coll === 'xAxis' && axis.getDDPoints,
663
+ ddPointsX = isDrillable && axis.getDDPoints(pos);
664
+
665
+ if (isDrillable) {
666
+ if (label && ddPointsX.length) {
667
+ label.drillable = true;
668
+
669
+
670
+ if (!label.basicStyles) {
671
+ label.basicStyles = H.merge(label.styles);
672
+ }
673
+
674
+
675
+ label
676
+ .addClass('highcharts-drilldown-axis-label')
677
+
678
+ .css(axis.chart.options.drilldown.activeAxisLabelStyle)
679
+
680
+ .on('click', function(e) {
681
+ axis.drilldownCategory(pos, e);
682
+ });
683
+
684
+ } else if (label && label.drillable) {
685
+
686
+
687
+ label.styles = {}; // reset for full overwrite of styles
688
+ label.css(label.basicStyles);
689
+
690
+
691
+ label.on('click', null); // #3806
692
+ label.removeClass('highcharts-drilldown-axis-label');
693
+ }
694
+ }
695
+ };
696
+
697
+ /**
698
+ * Always keep the drillability updated (#3951)
699
+ */
700
+ wrap(Tick.prototype, 'addLabel', function(proceed) {
701
+ proceed.call(this);
702
+ this.drillable();
703
+ });
704
+
705
+
706
+ /**
707
+ * On initialization of each point, identify its label and make it clickable. Also, provide a
708
+ * list of points associated to that label.
709
+ */
710
+ wrap(H.Point.prototype, 'init', function(proceed, series, options, x) {
711
+ var point = proceed.call(this, series, options, x),
712
+ xAxis = series.xAxis,
713
+ tick = xAxis && xAxis.ticks[x];
714
+
715
+ if (point.drilldown) {
716
+
717
+ // Add the click event to the point
718
+ H.addEvent(point, 'click', function(e) {
719
+ if (series.xAxis && series.chart.options.drilldown.allowPointDrilldown === false) {
720
+ series.xAxis.drilldownCategory(x, e);
721
+ } else {
722
+ point.doDrilldown(undefined, undefined, e);
723
+ }
724
+ });
725
+ /*wrap(point, 'importEvents', function (proceed) { // wrapping importEvents makes point.click event work
726
+ if (!this.hasImportedEvents) {
727
+ proceed.call(this);
728
+ H.addEvent(this, 'click', function () {
729
+ this.doDrilldown();
730
+ });
731
+ }
732
+ });*/
733
+
734
+ }
735
+
736
+ // Add or remove click handler and style on the tick label
737
+ if (tick) {
738
+ tick.drillable();
739
+ }
740
+
741
+ return point;
742
+ });
743
+
744
+ wrap(H.Series.prototype, 'drawDataLabels', function(proceed) {
745
+ var css = this.chart.options.drilldown.activeDataLabelStyle,
746
+ renderer = this.chart.renderer;
747
+
748
+ proceed.call(this);
749
+
750
+ each(this.points, function(point) {
751
+ var pointCSS = {};
752
+ if (point.drilldown && point.dataLabel) {
753
+ if (css.color === 'contrast') {
754
+ pointCSS.color = renderer.getContrast(point.color || this.color);
755
+ }
756
+ point.dataLabel
757
+ .addClass('highcharts-drilldown-data-label');
758
+
759
+
760
+ point.dataLabel
761
+ .css(css)
762
+ .css(pointCSS);
763
+
764
+ }
765
+ }, this);
766
+ });
767
+
768
+ // Mark the trackers with a pointer
769
+ var type,
770
+ drawTrackerWrapper = function(proceed) {
771
+ proceed.call(this);
772
+ each(this.points, function(point) {
773
+ if (point.drilldown && point.graphic) {
774
+ point.graphic.addClass('highcharts-drilldown-point');
775
+
776
+
777
+ point.graphic.css({
778
+ cursor: 'pointer'
779
+ });
780
+
781
+ }
782
+ });
783
+ };
784
+ for (type in seriesTypes) {
785
+ if (seriesTypes[type].prototype.supportsDrilldown) {
786
+ wrap(seriesTypes[type].prototype, 'drawTracker', drawTrackerWrapper);
787
+ }
788
+ }
789
+
790
+ }(Highcharts));
731
791
  }));