highcharts-rails 4.0.4.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +92 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/highcharts.js +1865 -1219
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +1 -1
- data/app/assets/javascripts/highcharts/highcharts-3d.js +174 -239
- data/app/assets/javascripts/highcharts/highcharts-more.js +195 -187
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +1 -1
- data/app/assets/javascripts/highcharts/modules/data.js +125 -196
- data/app/assets/javascripts/highcharts/modules/drilldown.js +104 -80
- data/app/assets/javascripts/highcharts/modules/exporting.js +14 -4
- data/app/assets/javascripts/highcharts/modules/funnel.js +7 -7
- data/app/assets/javascripts/highcharts/modules/heatmap.js +26 -69
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +2 -2
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +32 -17
- data/app/assets/javascripts/highcharts/modules/treemap.js +806 -0
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +1 -1
- data/app/assets/javascripts/highcharts/themes/grid-light.js +1 -1
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +1 -1
- data/lib/highcharts/version.rb +1 -1
- metadata +13 -12
- checksums.yaml.gz.asc +0 -18
- data.tar.gz.asc +0 -18
- metadata.gz.asc +0 -18
@@ -2908,7 +2908,7 @@ if (CanvasRenderingContext2D) {
|
|
2908
2908
|
});
|
2909
2909
|
}
|
2910
2910
|
}/**
|
2911
|
-
* @license Highcharts JS v4.0
|
2911
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
2912
2912
|
* CanVGRenderer Extension module
|
2913
2913
|
*
|
2914
2914
|
* (c) 2011-2012 Torstein Honsi, Erik Olsson
|
@@ -1,113 +1,20 @@
|
|
1
1
|
/**
|
2
|
-
* @license
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
|
+
* Data module
|
3
4
|
*
|
4
5
|
* (c) 2012-2014 Torstein Honsi
|
5
6
|
*
|
6
7
|
* License: www.highcharts.com/license
|
7
8
|
*/
|
8
9
|
|
9
|
-
/*
|
10
|
-
* The Highcharts Data plugin is a utility to ease parsing of input sources like
|
11
|
-
* CSV, HTML tables or grid views into basic configuration options for use
|
12
|
-
* directly in the Highcharts constructor.
|
13
|
-
*
|
14
|
-
* Demo: http://jsfiddle.net/highcharts/SnLFj/
|
15
|
-
*
|
16
|
-
* --- OPTIONS ---
|
17
|
-
*
|
18
|
-
* - columns : Array<Array<Mixed>>
|
19
|
-
* A two-dimensional array representing the input data on tabular form. This input can
|
20
|
-
* be used when the data is already parsed, for example from a grid view component.
|
21
|
-
* Each cell can be a string or number. If not switchRowsAndColumns is set, the columns
|
22
|
-
* are interpreted as series. See also the rows option.
|
23
|
-
*
|
24
|
-
* - complete : Function(chartOptions)
|
25
|
-
* The callback that is evaluated when the data is finished loading, optionally from an
|
26
|
-
* external source, and parsed. The first argument passed is a finished chart options
|
27
|
-
* object, containing the series. Thise options
|
28
|
-
* can be extended with additional options and passed directly to the chart constructor. This is
|
29
|
-
* related to the parsed callback, that goes in at an earlier stage.
|
30
|
-
*
|
31
|
-
* - csv : String
|
32
|
-
* A comma delimited string to be parsed. Related options are startRow, endRow, startColumn
|
33
|
-
* and endColumn to delimit what part of the table is used. The lineDelimiter and
|
34
|
-
* itemDelimiter options define the CSV delimiter formats.
|
35
|
-
*
|
36
|
-
* - dateFormat: String
|
37
|
-
* Which of the predefined date formats in Date.prototype.dateFormats to use to parse date
|
38
|
-
* columns, for example "dd/mm/YYYY" or "YYYY-mm-dd". Defaults to a best guess based on
|
39
|
-
* what format gives valid dates, and prefers ordered dates.
|
40
|
-
*
|
41
|
-
* - endColumn : Integer
|
42
|
-
* In tabular input data, the first row (indexed by 0) to use. Defaults to the last
|
43
|
-
* column containing data.
|
44
|
-
*
|
45
|
-
* - endRow : Integer
|
46
|
-
* In tabular input data, the last row (indexed by 0) to use. Defaults to the last row
|
47
|
-
* containing data.
|
48
|
-
*
|
49
|
-
* - googleSpreadsheetKey : String
|
50
|
-
* A Google Spreadsheet key. See https://developers.google.com/gdata/samples/spreadsheet_sample
|
51
|
-
* for general information on GS.
|
52
|
-
*
|
53
|
-
* - googleSpreadsheetWorksheet : String
|
54
|
-
* The Google Spreadsheet worksheet. The available id's can be read from
|
55
|
-
* https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic
|
56
|
-
*
|
57
|
-
* - itemDelimiter : String
|
58
|
-
* Item or cell delimiter for parsing CSV. Defaults to the tab character "\t" if a tab character
|
59
|
-
* is found in the CSV string, if not it defaults to ",".
|
60
|
-
*
|
61
|
-
* - lineDelimiter : String
|
62
|
-
* Line delimiter for parsing CSV. Defaults to "\n".
|
63
|
-
*
|
64
|
-
* - parsed : Function
|
65
|
-
* A callback function to access the parsed columns, the two-dimentional input data
|
66
|
-
* array directly, before they are interpreted into series data and categories. See also
|
67
|
-
* the complete callback, that goes in on a later stage where the raw columns are interpreted
|
68
|
-
* into a Highcharts option structure. Return false to stop completion, or call this.complete()
|
69
|
-
* to continue async.
|
70
|
-
*
|
71
|
-
* - parseDate : Function
|
72
|
-
* A callback function to parse string representations of dates into JavaScript timestamps.
|
73
|
-
* Return an integer on success.
|
74
|
-
*
|
75
|
-
* - rows : Array<Array<Mixed>>
|
76
|
-
* The same as the columns input option, but defining rows intead of columns.
|
77
|
-
*
|
78
|
-
* - seriesMapping : Array<Object>
|
79
|
-
* An array containing object with Point property names along with what column id the
|
80
|
-
* property should be taken from.
|
81
|
-
*
|
82
|
-
* - startColumn : Integer
|
83
|
-
* In tabular input data, the first column (indexed by 0) to use.
|
84
|
-
*
|
85
|
-
* - startRow : Integer
|
86
|
-
* In tabular input data, the first row (indexed by 0) to use.
|
87
|
-
*
|
88
|
-
* - switchRowsAndColumns : Boolean
|
89
|
-
* Switch rows and columns of the input data, so that this.columns effectively becomes the
|
90
|
-
* rows of the data set, and the rows are interpreted as series.
|
91
|
-
*
|
92
|
-
* - table : String|HTMLElement
|
93
|
-
* A HTML table or the id of such to be parsed as input data. Related options ara startRow,
|
94
|
-
* endRow, startColumn and endColumn to delimit what part of the table is used.
|
95
|
-
*/
|
96
|
-
|
97
|
-
/*
|
98
|
-
* TODO:
|
99
|
-
* - Handle various date formats
|
100
|
-
* - http://jsfiddle.net/highcharts/114wejdx/
|
101
|
-
* - http://jsfiddle.net/highcharts/ryv67bkq/
|
102
|
-
*/
|
103
|
-
|
104
10
|
// JSLint options:
|
105
11
|
/*global jQuery, HighchartsAdapter */
|
106
12
|
|
107
|
-
(function (Highcharts) {
|
13
|
+
(function (Highcharts) {
|
108
14
|
|
109
15
|
// Utilities
|
110
16
|
var each = Highcharts.each,
|
17
|
+
pick = Highcharts.pick,
|
111
18
|
inArray = HighchartsAdapter.inArray,
|
112
19
|
splat = Highcharts.splat,
|
113
20
|
SeriesBuilder;
|
@@ -128,6 +35,8 @@
|
|
128
35
|
this.options = options;
|
129
36
|
this.chartOptions = chartOptions;
|
130
37
|
this.columns = options.columns || this.rowsToColumns(options.rows) || [];
|
38
|
+
this.firstRowAsNames = pick(options.firstRowAsNames, true);
|
39
|
+
this.decimalRegex = options.decimalPoint && new RegExp('^([0-9]+)' + options.decimalPoint + '([0-9]+)$');
|
131
40
|
|
132
41
|
// This is a two-dimensional array holding the raw, trimmed string values
|
133
42
|
// with the same organisation as the columns array. It makes it possible
|
@@ -172,7 +81,7 @@
|
|
172
81
|
globalType = chartOptions && chartOptions.chart && chartOptions.chart.type,
|
173
82
|
individualCounts = [],
|
174
83
|
seriesBuilders = [],
|
175
|
-
seriesIndex,
|
84
|
+
seriesIndex = 0,
|
176
85
|
i;
|
177
86
|
|
178
87
|
each((chartOptions && chartOptions.series) || [], function (series) {
|
@@ -253,9 +162,6 @@
|
|
253
162
|
// Interpret the values into right types
|
254
163
|
this.parseTypes();
|
255
164
|
|
256
|
-
// Use first row for series names?
|
257
|
-
this.findHeaderRow();
|
258
|
-
|
259
165
|
// Handle columns if a handleColumns callback is given
|
260
166
|
if (this.parsed() !== false) {
|
261
167
|
|
@@ -420,26 +326,23 @@
|
|
420
326
|
}
|
421
327
|
},
|
422
328
|
|
423
|
-
/**
|
424
|
-
* Find the header row. For now, we just check whether the first row contains
|
425
|
-
* numbers or strings. Later we could loop down and find the first row with
|
426
|
-
* numbers.
|
427
|
-
*/
|
428
|
-
findHeaderRow: function () {
|
429
|
-
var headerRow = 0;
|
430
|
-
each(this.columns, function (column) {
|
431
|
-
if (column.isNumeric && typeof column[0] !== 'string') {
|
432
|
-
headerRow = null;
|
433
|
-
}
|
434
|
-
});
|
435
|
-
this.headerRow = headerRow;
|
436
|
-
},
|
437
|
-
|
438
329
|
/**
|
439
330
|
* Trim a string from whitespace
|
440
331
|
*/
|
441
|
-
trim: function (str) {
|
442
|
-
|
332
|
+
trim: function (str, inside) {
|
333
|
+
if (typeof str === 'string') {
|
334
|
+
str = str.replace(/^\s+|\s+$/g, '');
|
335
|
+
|
336
|
+
// Clear white space insdie the string, like thousands separators
|
337
|
+
if (inside && /^[0-9\s]+$/.test(str)) {
|
338
|
+
str = str.replace(/\s/g, '');
|
339
|
+
}
|
340
|
+
|
341
|
+
if (this.decimalRegex) {
|
342
|
+
str = str.replace(this.decimalRegex, '$1.$2');
|
343
|
+
}
|
344
|
+
}
|
345
|
+
return str;
|
443
346
|
},
|
444
347
|
|
445
348
|
/**
|
@@ -447,97 +350,118 @@
|
|
447
350
|
*/
|
448
351
|
parseTypes: function () {
|
449
352
|
var columns = this.columns,
|
450
|
-
|
451
|
-
|
452
|
-
|
353
|
+
col = columns.length;
|
354
|
+
|
355
|
+
while (col--) {
|
356
|
+
this.parseColumn(columns[col], col);
|
357
|
+
}
|
358
|
+
|
359
|
+
},
|
360
|
+
|
361
|
+
/**
|
362
|
+
* Parse a single column. Set properties like .isDatetime and .isNumeric.
|
363
|
+
*/
|
364
|
+
parseColumn: function (column, col) {
|
365
|
+
var rawColumns = this.rawColumns,
|
366
|
+
columns = this.columns,
|
367
|
+
row = column.length,
|
453
368
|
val,
|
454
369
|
floatVal,
|
455
370
|
trimVal,
|
456
|
-
|
371
|
+
trimInsideVal,
|
372
|
+
firstRowAsNames = this.firstRowAsNames,
|
373
|
+
isXColumn = inArray(col, this.valueCount.xColumns) !== -1,
|
457
374
|
dateVal,
|
458
|
-
descending,
|
459
375
|
backup = [],
|
460
376
|
diff,
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
377
|
+
chartOptions = this.chartOptions,
|
378
|
+
descending,
|
379
|
+
columnTypes = this.options.columnTypes || [],
|
380
|
+
columnType = columnTypes[col],
|
381
|
+
forceCategory = isXColumn && ((chartOptions && chartOptions.xAxis && splat(chartOptions.xAxis)[0].type === 'category') || columnType === 'string');
|
382
|
+
|
383
|
+
if (!rawColumns[col]) {
|
467
384
|
rawColumns[col] = [];
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
columns[col].isNumeric = true;
|
489
|
-
}
|
385
|
+
}
|
386
|
+
while (row--) {
|
387
|
+
val = backup[row] || column[row];
|
388
|
+
|
389
|
+
trimVal = this.trim(val);
|
390
|
+
trimInsideVal = this.trim(val, true);
|
391
|
+
floatVal = parseFloat(trimInsideVal);
|
392
|
+
|
393
|
+
// Set it the first time
|
394
|
+
if (rawColumns[col][row] === undefined) {
|
395
|
+
rawColumns[col][row] = trimVal;
|
396
|
+
}
|
397
|
+
|
398
|
+
// Disable number or date parsing by setting the X axis type to category
|
399
|
+
if (forceCategory || (row === 0 && firstRowAsNames)) {
|
400
|
+
column[row] = trimVal;
|
401
|
+
|
402
|
+
} else if (+trimInsideVal === floatVal) { // is numeric
|
403
|
+
|
404
|
+
column[row] = floatVal;
|
490
405
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
406
|
+
// If the number is greater than milliseconds in a year, assume datetime
|
407
|
+
if (floatVal > 365 * 24 * 3600 * 1000 && columnType !== 'float') {
|
408
|
+
column.isDatetime = true;
|
409
|
+
} else {
|
410
|
+
column.isNumeric = true;
|
411
|
+
}
|
412
|
+
|
413
|
+
if (column[row + 1] !== undefined) {
|
414
|
+
descending = floatVal > column[row + 1];
|
415
|
+
}
|
416
|
+
|
417
|
+
// String, continue to determine if it is a date string or really a string
|
418
|
+
} else {
|
419
|
+
dateVal = this.parseDate(val);
|
420
|
+
// Only allow parsing of dates if this column is an x-column
|
421
|
+
if (isXColumn && typeof dateVal === 'number' && !isNaN(dateVal) && columnType !== 'float') { // is date
|
422
|
+
backup[row] = val;
|
423
|
+
column[row] = dateVal;
|
424
|
+
column.isDatetime = true;
|
425
|
+
|
426
|
+
// Check if the dates are uniformly descending or ascending. If they
|
427
|
+
// are not, chances are that they are a different time format, so check
|
428
|
+
// for alternative.
|
429
|
+
if (column[row + 1] !== undefined) {
|
430
|
+
diff = dateVal > column[row + 1];
|
431
|
+
if (diff !== descending && descending !== undefined) {
|
432
|
+
if (this.alternativeFormat) {
|
433
|
+
this.dateFormat = this.alternativeFormat;
|
434
|
+
row = column.length;
|
435
|
+
this.alternativeFormat = this.dateFormats[this.dateFormat].alternative;
|
436
|
+
} else {
|
437
|
+
column.unsorted = true;
|
512
438
|
}
|
513
|
-
descending = diff;
|
514
|
-
}
|
515
|
-
|
516
|
-
} else { // string
|
517
|
-
columns[col][row] = trimVal === '' ? null : trimVal;
|
518
|
-
if (row !== 0 && (columns[col].isDatetime || columns[col].isNumeric)) {
|
519
|
-
columns[col].mixed = true;
|
520
439
|
}
|
440
|
+
descending = diff;
|
441
|
+
}
|
442
|
+
|
443
|
+
} else { // string
|
444
|
+
column[row] = trimVal === '' ? null : trimVal;
|
445
|
+
if (row !== 0 && (column.isDatetime || column.isNumeric)) {
|
446
|
+
column.mixed = true;
|
521
447
|
}
|
522
448
|
}
|
523
449
|
}
|
450
|
+
}
|
524
451
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
}
|
452
|
+
// If strings are intermixed with numbers or dates in a parsed column, it is an indication
|
453
|
+
// that parsing went wrong or the data was not intended to display as numbers or dates and
|
454
|
+
// parsing is too aggressive. Fall back to categories. Demonstrated in the
|
455
|
+
// highcharts/demo/column-drilldown sample.
|
456
|
+
if (isXColumn && column.mixed) {
|
457
|
+
columns[col] = rawColumns[col];
|
532
458
|
}
|
533
459
|
|
534
|
-
// If the 0 column is date and descending, reverse all columns.
|
535
|
-
|
536
|
-
if (columns[0].isDatetime && descending) {
|
537
|
-
hasHeaderRow = typeof columns[0][0] !== 'number';
|
460
|
+
// If the 0 column is date or number and descending, reverse all columns.
|
461
|
+
if (isXColumn && descending && this.options.sort) {
|
538
462
|
for (col = 0; col < columns.length; col++) {
|
539
463
|
columns[col].reverse();
|
540
|
-
if (
|
464
|
+
if (firstRowAsNames) {
|
541
465
|
columns[col].unshift(columns[col].pop());
|
542
466
|
}
|
543
467
|
}
|
@@ -578,7 +502,6 @@
|
|
578
502
|
'mm/dd/YY': {
|
579
503
|
regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,
|
580
504
|
parser: function (match) {
|
581
|
-
console.log(match)
|
582
505
|
return Date.UTC(+match[3] + 2000, match[1] - 1, +match[2]);
|
583
506
|
}
|
584
507
|
}
|
@@ -731,7 +654,7 @@
|
|
731
654
|
|
732
655
|
// Get the names and shift the top row
|
733
656
|
for (i = 0; i < columns.length; i++) {
|
734
|
-
if (this.
|
657
|
+
if (this.firstRowAsNames) {
|
735
658
|
columns[i].name = columns[i].shift();
|
736
659
|
}
|
737
660
|
}
|
@@ -812,17 +735,23 @@
|
|
812
735
|
if (builder.name) {
|
813
736
|
series[seriesIndex].name = builder.name;
|
814
737
|
}
|
738
|
+
if (type === 'category') {
|
739
|
+
series[seriesIndex].turboThreshold = 0;
|
740
|
+
}
|
815
741
|
}
|
816
742
|
|
817
743
|
|
818
744
|
|
819
745
|
// Do the callback
|
820
746
|
chartOptions = {
|
821
|
-
xAxis: {
|
822
|
-
type: type
|
823
|
-
},
|
824
747
|
series: series
|
825
748
|
};
|
749
|
+
if (type) {
|
750
|
+
chartOptions.xAxis = {
|
751
|
+
type: type
|
752
|
+
};
|
753
|
+
}
|
754
|
+
|
826
755
|
if (options.complete) {
|
827
756
|
options.complete(chartOptions);
|
828
757
|
}
|
@@ -7,7 +7,7 @@
|
|
7
7
|
* Demo: http://jsfiddle.net/highcharts/Vf3yT/
|
8
8
|
*/
|
9
9
|
|
10
|
-
/*global HighchartsAdapter*/
|
10
|
+
/*global Highcharts,HighchartsAdapter*/
|
11
11
|
(function (H) {
|
12
12
|
|
13
13
|
"use strict";
|
@@ -25,18 +25,39 @@
|
|
25
25
|
ColumnSeries = seriesTypes.column,
|
26
26
|
fireEvent = HighchartsAdapter.fireEvent,
|
27
27
|
inArray = HighchartsAdapter.inArray,
|
28
|
-
dupes = []
|
28
|
+
dupes = [],
|
29
|
+
ddSeriesId = 1;
|
29
30
|
|
30
31
|
// Utilities
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
/*
|
33
|
+
* Return an intermediate color between two colors, according to pos where 0
|
34
|
+
* is the from color and 1 is the to color
|
35
|
+
*/
|
36
|
+
function tweenColors(from, to, pos) {
|
37
|
+
// Check for has alpha, because rgba colors perform worse due to lack of
|
38
|
+
// support in WebKit.
|
39
|
+
var hasAlpha;
|
40
|
+
|
41
|
+
from = from.rgba;
|
42
|
+
to = to.rgba;
|
43
|
+
hasAlpha = (to[3] !== 1 || from[3] !== 1);
|
44
|
+
if (!to.length || !from.length) {
|
45
|
+
Highcharts.error(23);
|
46
|
+
}
|
47
|
+
return (hasAlpha ? 'rgba(' : 'rgb(') +
|
48
|
+
Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' +
|
49
|
+
Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' +
|
50
|
+
Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) +
|
51
|
+
(hasAlpha ? (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) : '') + ')';
|
39
52
|
}
|
53
|
+
/**
|
54
|
+
* Handle animation of the color attributes directly
|
55
|
+
*/
|
56
|
+
each(['fill', 'stroke'], function (prop) {
|
57
|
+
HighchartsAdapter.addAnimSetter(prop, function (fx) {
|
58
|
+
fx.elem.attr(prop, tweenColors(H.Color(fx.start), H.Color(fx.end), fx.pos));
|
59
|
+
});
|
60
|
+
});
|
40
61
|
|
41
62
|
// Add language
|
42
63
|
extend(defaultOptions.lang, {
|
@@ -101,10 +122,11 @@
|
|
101
122
|
level,
|
102
123
|
levelNumber;
|
103
124
|
|
104
|
-
levelNumber = oldSeries.
|
125
|
+
levelNumber = oldSeries.options._levelNumber || 0;
|
105
126
|
|
106
127
|
ddOptions = extend({
|
107
|
-
color: color
|
128
|
+
color: color,
|
129
|
+
_ddSeriesId: ddSeriesId++
|
108
130
|
}, ddOptions);
|
109
131
|
pointIndex = inArray(point, oldSeries.points);
|
110
132
|
|
@@ -112,19 +134,21 @@
|
|
112
134
|
each(oldSeries.chart.series, function (series) {
|
113
135
|
if (series.xAxis === xAxis) {
|
114
136
|
levelSeries.push(series);
|
115
|
-
|
116
|
-
series.
|
137
|
+
series.options._ddSeriesId = series.options._ddSeriesId || ddSeriesId++;
|
138
|
+
series.options._colorIndex = series.userOptions._colorIndex;
|
139
|
+
levelSeriesOptions.push(series.options);
|
140
|
+
series.options._levelNumber = series.options._levelNumber || levelNumber; // #3182
|
117
141
|
}
|
118
142
|
});
|
119
143
|
|
120
144
|
// Add a record of properties for each drilldown level
|
121
145
|
level = {
|
122
146
|
levelNumber: levelNumber,
|
123
|
-
seriesOptions: oldSeries.
|
147
|
+
seriesOptions: oldSeries.options,
|
124
148
|
levelSeriesOptions: levelSeriesOptions,
|
125
149
|
levelSeries: levelSeries,
|
126
150
|
shapeArgs: point.shapeArgs,
|
127
|
-
bBox: point.graphic.getBBox(),
|
151
|
+
bBox: point.graphic ? point.graphic.getBBox() : {}, // no graphic in line series with markers disabled
|
128
152
|
color: color,
|
129
153
|
lowerSeriesOptions: ddOptions,
|
130
154
|
pointOptions: oldSeries.options.data[pointIndex],
|
@@ -144,7 +168,7 @@
|
|
144
168
|
this.drilldownLevels.push(level);
|
145
169
|
|
146
170
|
newSeries = level.lowerSeries = this.addSeries(ddOptions, false);
|
147
|
-
newSeries.
|
171
|
+
newSeries.options._levelNumber = levelNumber + 1;
|
148
172
|
if (xAxis) {
|
149
173
|
xAxis.oldPos = xAxis.pos;
|
150
174
|
xAxis.userMin = xAxis.userMax = null;
|
@@ -167,7 +191,7 @@
|
|
167
191
|
each(this.drilldownLevels, function (level) {
|
168
192
|
if (level.levelNumber === levelToRemove) {
|
169
193
|
each(level.levelSeries, function (series) {
|
170
|
-
if (series.
|
194
|
+
if (series.options && series.options._levelNumber === levelToRemove) { // Not removed, not added as part of a multi-series drilldown
|
171
195
|
series.remove(false);
|
172
196
|
}
|
173
197
|
});
|
@@ -233,7 +257,7 @@
|
|
233
257
|
levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber,
|
234
258
|
i = drilldownLevels.length,
|
235
259
|
chartSeries = chart.series,
|
236
|
-
seriesI
|
260
|
+
seriesI,
|
237
261
|
level,
|
238
262
|
oldSeries,
|
239
263
|
newSeries,
|
@@ -241,7 +265,7 @@
|
|
241
265
|
addSeries = function (seriesOptions) {
|
242
266
|
var addedSeries;
|
243
267
|
each(chartSeries, function (series) {
|
244
|
-
if (series.
|
268
|
+
if (series.options._ddSeriesId === seriesOptions._ddSeriesId) {
|
245
269
|
addedSeries = series;
|
246
270
|
}
|
247
271
|
});
|
@@ -254,7 +278,7 @@
|
|
254
278
|
newSeries = addedSeries;
|
255
279
|
}
|
256
280
|
};
|
257
|
-
|
281
|
+
|
258
282
|
while (i--) {
|
259
283
|
|
260
284
|
level = drilldownLevels[i];
|
@@ -264,6 +288,7 @@
|
|
264
288
|
// Get the lower series by reference or id
|
265
289
|
oldSeries = level.lowerSeries;
|
266
290
|
if (!oldSeries.chart) { // #2786
|
291
|
+
seriesI = chartSeries.length; // #2919
|
267
292
|
while (seriesI--) {
|
268
293
|
if (chartSeries[seriesI].options.id === level.lowerSeriesOptions.id) {
|
269
294
|
oldSeries = chartSeries[seriesI];
|
@@ -281,11 +306,11 @@
|
|
281
306
|
newSeries.drilldownLevel = level;
|
282
307
|
newSeries.options.animation = chart.options.drilldown.animation;
|
283
308
|
|
284
|
-
if (oldSeries.animateDrillupFrom) {
|
309
|
+
if (oldSeries.animateDrillupFrom && oldSeries.chart) { // #2919
|
285
310
|
oldSeries.animateDrillupFrom(level);
|
286
311
|
}
|
287
312
|
}
|
288
|
-
newSeries.
|
313
|
+
newSeries.options._levelNumber = levelNumber;
|
289
314
|
|
290
315
|
oldSeries.remove(false);
|
291
316
|
|
@@ -325,7 +350,9 @@
|
|
325
350
|
level = newSeries.drilldownLevel;
|
326
351
|
|
327
352
|
each(this.points, function (point) {
|
328
|
-
point.graphic
|
353
|
+
if (point.graphic) { // #3407
|
354
|
+
point.graphic.hide();
|
355
|
+
}
|
329
356
|
if (point.dataLabel) {
|
330
357
|
point.dataLabel.hide();
|
331
358
|
}
|
@@ -337,18 +364,22 @@
|
|
337
364
|
|
338
365
|
// Do dummy animation on first point to get to complete
|
339
366
|
setTimeout(function () {
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
367
|
+
if (newSeries.points) { // May be destroyed in the meantime, #3389
|
368
|
+
each(newSeries.points, function (point, i) {
|
369
|
+
// Fade in other points
|
370
|
+
var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn',
|
371
|
+
inherit = verb === 'show' ? true : undefined;
|
372
|
+
if (point.graphic) { // #3407
|
373
|
+
point.graphic[verb](inherit);
|
374
|
+
}
|
375
|
+
if (point.dataLabel) {
|
376
|
+
point.dataLabel[verb](inherit);
|
377
|
+
}
|
378
|
+
if (point.connector) {
|
379
|
+
point.connector[verb](inherit);
|
380
|
+
}
|
381
|
+
});
|
382
|
+
}
|
352
383
|
}, Math.max(this.chart.options.drilldown.animation.duration - 50, 0));
|
353
384
|
|
354
385
|
// Reset
|
@@ -360,23 +391,28 @@
|
|
360
391
|
ColumnSeries.prototype.animateDrilldown = function (init) {
|
361
392
|
var series = this,
|
362
393
|
drilldownLevels = this.chart.drilldownLevels,
|
363
|
-
animateFrom
|
364
|
-
animationOptions = this.chart.options.drilldown.animation
|
394
|
+
animateFrom,
|
395
|
+
animationOptions = this.chart.options.drilldown.animation,
|
396
|
+
xAxis = this.xAxis;
|
365
397
|
|
366
398
|
if (!init) {
|
367
399
|
each(drilldownLevels, function (level) {
|
368
|
-
if (series.
|
400
|
+
if (series.options._ddSeriesId === level.lowerSeriesOptions._ddSeriesId) {
|
369
401
|
animateFrom = level.shapeArgs;
|
402
|
+
animateFrom.fill = level.color;
|
370
403
|
}
|
371
404
|
});
|
372
405
|
|
373
|
-
animateFrom.x += (
|
374
|
-
|
406
|
+
animateFrom.x += (pick(xAxis.oldPos, xAxis.pos) - xAxis.pos);
|
407
|
+
|
375
408
|
each(this.points, function (point) {
|
376
409
|
if (point.graphic) {
|
377
410
|
point.graphic
|
378
411
|
.attr(animateFrom)
|
379
|
-
.animate(
|
412
|
+
.animate(
|
413
|
+
extend(point.shapeArgs, { fill: point.color }),
|
414
|
+
animationOptions
|
415
|
+
);
|
380
416
|
}
|
381
417
|
if (point.dataLabel) {
|
382
418
|
point.dataLabel.fadeIn(animationOptions);
|
@@ -407,8 +443,6 @@
|
|
407
443
|
delete this.group;
|
408
444
|
each(this.points, function (point) {
|
409
445
|
var graphic = point.graphic,
|
410
|
-
startColor = H.Color(point.color).rgba,
|
411
|
-
endColor = H.Color(level.color).rgba,
|
412
446
|
complete = function () {
|
413
447
|
graphic.destroy();
|
414
448
|
if (group) {
|
@@ -421,18 +455,10 @@
|
|
421
455
|
delete point.graphic;
|
422
456
|
|
423
457
|
if (animationOptions) {
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
this.attr({
|
429
|
-
fill: tweenColors(startColor, endColor, fx.pos)
|
430
|
-
});
|
431
|
-
}
|
432
|
-
},
|
433
|
-
complete: complete
|
434
|
-
}));
|
435
|
-
/*jslint unparam: false*/
|
458
|
+
graphic.animate(
|
459
|
+
extend(level.shapeArgs, { fill: level.color }),
|
460
|
+
H.merge(animationOptions, { complete: complete })
|
461
|
+
);
|
436
462
|
} else {
|
437
463
|
graphic.attr(level.shapeArgs);
|
438
464
|
complete();
|
@@ -453,28 +479,19 @@
|
|
453
479
|
animateFrom = level.shapeArgs,
|
454
480
|
start = animateFrom.start,
|
455
481
|
angle = animateFrom.end - start,
|
456
|
-
startAngle = angle / this.points.length
|
457
|
-
startColor = H.Color(level.color).rgba;
|
482
|
+
startAngle = angle / this.points.length;
|
458
483
|
|
459
484
|
if (!init) {
|
460
485
|
each(this.points, function (point, i) {
|
461
|
-
var endColor = H.Color(point.color).rgba;
|
462
|
-
|
463
|
-
/*jslint unparam: true*/
|
464
486
|
point.graphic
|
465
487
|
.attr(H.merge(animateFrom, {
|
466
488
|
start: start + i * startAngle,
|
467
|
-
end: start + (i + 1) * startAngle
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
});
|
474
|
-
}
|
475
|
-
}
|
476
|
-
}));
|
477
|
-
/*jslint unparam: false*/
|
489
|
+
end: start + (i + 1) * startAngle,
|
490
|
+
fill: level.color
|
491
|
+
}))[animationOptions ? 'animate' : 'attr'](
|
492
|
+
extend(point.shapeArgs, { fill: point.color }),
|
493
|
+
animationOptions
|
494
|
+
);
|
478
495
|
});
|
479
496
|
this.animate = null;
|
480
497
|
}
|
@@ -482,7 +499,7 @@
|
|
482
499
|
});
|
483
500
|
}
|
484
501
|
|
485
|
-
H.Point.prototype.doDrilldown = function (_holdRedraw) {
|
502
|
+
H.Point.prototype.doDrilldown = function (_holdRedraw, category) {
|
486
503
|
var series = this.series,
|
487
504
|
chart = series.chart,
|
488
505
|
drilldown = chart.options.drilldown,
|
@@ -500,7 +517,8 @@
|
|
500
517
|
// seriesOptions, and call addSeriesAsDrilldown async if necessary.
|
501
518
|
fireEvent(chart, 'drilldown', {
|
502
519
|
point: this,
|
503
|
-
seriesOptions: seriesOptions
|
520
|
+
seriesOptions: seriesOptions,
|
521
|
+
category: category
|
504
522
|
});
|
505
523
|
|
506
524
|
if (seriesOptions) {
|
@@ -510,7 +528,18 @@
|
|
510
528
|
chart.addSeriesAsDrilldown(this, seriesOptions);
|
511
529
|
}
|
512
530
|
}
|
531
|
+
};
|
513
532
|
|
533
|
+
/**
|
534
|
+
* Drill down to a given category. This is the same as clicking on an axis label.
|
535
|
+
*/
|
536
|
+
H.Axis.prototype.drilldownCategory = function (x) {
|
537
|
+
each(this.ticks[x].label.ddPoints, function (point) {
|
538
|
+
if (point.series && point.series.visible && point.doDrilldown) { // #3197
|
539
|
+
point.doDrilldown(true, x);
|
540
|
+
}
|
541
|
+
});
|
542
|
+
this.chart.applyDrilldown();
|
514
543
|
};
|
515
544
|
|
516
545
|
wrap(H.Point.prototype, 'init', function (proceed, series, options, x) {
|
@@ -543,12 +572,7 @@
|
|
543
572
|
.addClass('highcharts-drilldown-axis-label')
|
544
573
|
.css(chart.options.drilldown.activeAxisLabelStyle)
|
545
574
|
.on('click', function () {
|
546
|
-
|
547
|
-
if (point.doDrilldown) {
|
548
|
-
point.doDrilldown(true);
|
549
|
-
}
|
550
|
-
});
|
551
|
-
chart.applyDrilldown();
|
575
|
+
series.xAxis.drilldownCategory(x);
|
552
576
|
});
|
553
577
|
if (!tickLabel.ddPoints) {
|
554
578
|
tickLabel.ddPoints = [];
|