highcharts-rails 3.0.7 → 3.0.8
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.
- checksums.yaml +6 -14
- checksums.yaml.gz.asc +14 -14
- data.tar.gz.asc +14 -14
- data/README.markdown +2 -0
- data/Rakefile +1 -1
- data/app/assets/javascripts/highcharts.js +6200 -5875
- data/app/assets/javascripts/highcharts/adapters/mootools-adapter.js +2 -2
- data/app/assets/javascripts/highcharts/adapters/prototype-adapter.js +2 -2
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +10 -2
- data/app/assets/javascripts/highcharts/highcharts-more.js +513 -455
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +2 -2
- data/app/assets/javascripts/highcharts/modules/data.js +7 -4
- data/app/assets/javascripts/highcharts/modules/drilldown.js +7 -5
- data/app/assets/javascripts/highcharts/modules/exporting.js +35 -29
- data/app/assets/javascripts/highcharts/modules/funnel.js +2 -2
- data/app/assets/javascripts/highcharts/modules/heatmap.js +36 -30
- data/app/assets/javascripts/highcharts/modules/map.js +785 -402
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +3 -3
- data/app/assets/javascripts/highcharts/themes/dark-blue.js +1 -1
- data/app/assets/javascripts/highcharts/themes/dark-green.js +1 -1
- data/app/assets/javascripts/highcharts/themes/gray.js +1 -1
- data/app/assets/javascripts/highcharts/themes/grid.js +1 -1
- data/app/assets/javascripts/highcharts/themes/skies.js +1 -1
- data/lib/highcharts/version.rb +1 -1
- metadata +18 -19
- metadata.gz.asc +14 -14
@@ -2908,10 +2908,10 @@ if (CanvasRenderingContext2D) {
|
|
2908
2908
|
});
|
2909
2909
|
}
|
2910
2910
|
}/**
|
2911
|
-
* @license Highcharts JS v3.0.
|
2911
|
+
* @license Highcharts JS v3.0.8 (2014-01-09)
|
2912
2912
|
* CanVGRenderer Extension module
|
2913
2913
|
*
|
2914
|
-
* (c) 2011-2012 Torstein
|
2914
|
+
* (c) 2011-2012 Torstein Honsi, Erik Olsson
|
2915
2915
|
*
|
2916
2916
|
* License: www.highcharts.com/license
|
2917
2917
|
*/
|
@@ -1,8 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @license Data plugin for Highcharts
|
3
3
|
*
|
4
|
-
* (c) 2012-
|
5
|
-
* Last revision 2013-06-07
|
4
|
+
* (c) 2012-2014 Torstein Honsi
|
6
5
|
*
|
7
6
|
* License: www.highcharts.com/license
|
8
7
|
*/
|
@@ -50,7 +49,8 @@
|
|
50
49
|
* https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic
|
51
50
|
*
|
52
51
|
* - itemDelimiter : String
|
53
|
-
* Item or cell delimiter for parsing CSV. Defaults to "
|
52
|
+
* Item or cell delimiter for parsing CSV. Defaults to the tab character "\t" if a tab character
|
53
|
+
* is found in the CSV string, if not it defaults to ",".
|
54
54
|
*
|
55
55
|
* - lineDelimiter : String
|
56
56
|
* Line delimiter for parsing CSV. Defaults to "\n".
|
@@ -172,6 +172,7 @@
|
|
172
172
|
endRow = options.endRow || Number.MAX_VALUE,
|
173
173
|
startColumn = options.startColumn || 0,
|
174
174
|
endColumn = options.endColumn || Number.MAX_VALUE,
|
175
|
+
itemDelimiter,
|
175
176
|
lines,
|
176
177
|
activeRowNo = 0;
|
177
178
|
|
@@ -181,6 +182,8 @@
|
|
181
182
|
.replace(/\r\n/g, "\n") // Unix
|
182
183
|
.replace(/\r/g, "\n") // Mac
|
183
184
|
.split(options.lineDelimiter || "\n");
|
185
|
+
|
186
|
+
itemDelimiter = options.itemDelimiter || (csv.indexOf('\t') !== -1 ? '\t' : ',');
|
184
187
|
|
185
188
|
each(lines, function (line, rowNo) {
|
186
189
|
var trimmed = self.trim(line),
|
@@ -189,7 +192,7 @@
|
|
189
192
|
items;
|
190
193
|
|
191
194
|
if (rowNo >= startRow && rowNo <= endRow && !isComment && !isBlank) {
|
192
|
-
items = line.split(
|
195
|
+
items = line.split(itemDelimiter);
|
193
196
|
each(items, function (item, colNo) {
|
194
197
|
if (colNo >= startColumn && colNo <= endColumn) {
|
195
198
|
if (!columns[colNo - startColumn]) {
|
@@ -2,7 +2,6 @@
|
|
2
2
|
* Highcharts Drilldown plugin
|
3
3
|
*
|
4
4
|
* Author: Torstein Honsi
|
5
|
-
* Last revision: 2013-02-18
|
6
5
|
* License: MIT License
|
7
6
|
*
|
8
7
|
* Demo: http://jsfiddle.net/highcharts/Vf3yT/
|
@@ -43,13 +42,13 @@
|
|
43
42
|
defaultOptions.drilldown = {
|
44
43
|
activeAxisLabelStyle: {
|
45
44
|
cursor: 'pointer',
|
46
|
-
color: '#
|
45
|
+
color: '#0d233a',
|
47
46
|
fontWeight: 'bold',
|
48
47
|
textDecoration: 'underline'
|
49
48
|
},
|
50
49
|
activeDataLabelStyle: {
|
51
50
|
cursor: 'pointer',
|
52
|
-
color: '#
|
51
|
+
color: '#0d233a',
|
53
52
|
fontWeight: 'bold',
|
54
53
|
textDecoration: 'underline'
|
55
54
|
},
|
@@ -70,7 +69,7 @@
|
|
70
69
|
/**
|
71
70
|
* A general fadeIn method
|
72
71
|
*/
|
73
|
-
H.SVGRenderer.prototype.Element.prototype.fadeIn = function () {
|
72
|
+
H.SVGRenderer.prototype.Element.prototype.fadeIn = function (animation) {
|
74
73
|
this
|
75
74
|
.attr({
|
76
75
|
opacity: 0.1,
|
@@ -78,7 +77,7 @@
|
|
78
77
|
})
|
79
78
|
.animate({
|
80
79
|
opacity: 1
|
81
|
-
}, {
|
80
|
+
}, animation || {
|
82
81
|
duration: 250
|
83
82
|
});
|
84
83
|
};
|
@@ -301,6 +300,9 @@
|
|
301
300
|
point.graphic
|
302
301
|
.attr(animateFrom)
|
303
302
|
.animate(point.shapeArgs, animationOptions);
|
303
|
+
if (point.dataLabel) {
|
304
|
+
point.dataLabel.fadeIn(animationOptions);
|
305
|
+
}
|
304
306
|
});
|
305
307
|
}
|
306
308
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v3.0.
|
2
|
+
* @license Highcharts JS v3.0.8 (2014-01-09)
|
3
3
|
* Exporting module
|
4
4
|
*
|
5
|
-
* (c) 2010-
|
5
|
+
* (c) 2010-2014 Torstein Honsi
|
6
6
|
*
|
7
7
|
* License: www.highcharts.com/license
|
8
8
|
*/
|
@@ -77,7 +77,7 @@ defaultOptions.navigation = {
|
|
77
77
|
symbolX: 12.5,
|
78
78
|
symbolY: 10.5,
|
79
79
|
align: 'right',
|
80
|
-
buttonSpacing: 3,
|
80
|
+
buttonSpacing: 3,
|
81
81
|
height: 22,
|
82
82
|
// text: null,
|
83
83
|
theme: {
|
@@ -158,16 +158,16 @@ defaultOptions.exporting = {
|
|
158
158
|
};
|
159
159
|
|
160
160
|
// Add the Highcharts.post utility
|
161
|
-
Highcharts.post = function (url, data) {
|
161
|
+
Highcharts.post = function (url, data, formAttributes) {
|
162
162
|
var name,
|
163
163
|
form;
|
164
|
-
|
164
|
+
|
165
165
|
// create the form
|
166
|
-
form = createElement('form', {
|
166
|
+
form = createElement('form', merge({
|
167
167
|
method: 'post',
|
168
168
|
action: url,
|
169
169
|
enctype: 'multipart/form-data'
|
170
|
-
}, {
|
170
|
+
}, formAttributes), { // docs
|
171
171
|
display: NONE
|
172
172
|
}, doc.body);
|
173
173
|
|
@@ -222,7 +222,7 @@ extend(Chart.prototype, {
|
|
222
222
|
width: chart.chartWidth + PX,
|
223
223
|
height: chart.chartHeight + PX
|
224
224
|
}, doc.body);
|
225
|
-
|
225
|
+
|
226
226
|
// get the source size
|
227
227
|
cssWidth = chart.renderTo.style.width;
|
228
228
|
cssHeight = chart.renderTo.style.height;
|
@@ -244,7 +244,7 @@ extend(Chart.prototype, {
|
|
244
244
|
height: sourceHeight
|
245
245
|
});
|
246
246
|
options.exporting.enabled = false; // hide buttons in print
|
247
|
-
|
247
|
+
|
248
248
|
// prepare for replicating the chart
|
249
249
|
options.series = [];
|
250
250
|
each(chart.series, function (serie) {
|
@@ -331,13 +331,13 @@ extend(Chart.prototype, {
|
|
331
331
|
*/
|
332
332
|
exportChart: function (options, chartOptions) {
|
333
333
|
options = options || {};
|
334
|
-
|
334
|
+
|
335
335
|
var chart = this,
|
336
336
|
chartExportingOptions = chart.options.exporting,
|
337
337
|
svg = chart.getSVG(merge(
|
338
338
|
{ chart: { borderRadius: 0 } },
|
339
339
|
chartExportingOptions.chartOptions,
|
340
|
-
chartOptions,
|
340
|
+
chartOptions,
|
341
341
|
{
|
342
342
|
exporting: {
|
343
343
|
sourceWidth: options.sourceWidth || chartExportingOptions.sourceWidth,
|
@@ -348,7 +348,7 @@ extend(Chart.prototype, {
|
|
348
348
|
|
349
349
|
// merge the options
|
350
350
|
options = merge(chart.options.exporting, options);
|
351
|
-
|
351
|
+
|
352
352
|
// do the post
|
353
353
|
Highcharts.post(options.url, {
|
354
354
|
filename: options.filename || 'chart',
|
@@ -356,10 +356,10 @@ extend(Chart.prototype, {
|
|
356
356
|
width: options.width || 0, // IE8 fails to post undefined correctly, so use 0
|
357
357
|
scale: options.scale || 2,
|
358
358
|
svg: svg
|
359
|
-
});
|
359
|
+
}, options.formAttributes);
|
360
360
|
|
361
361
|
},
|
362
|
-
|
362
|
+
|
363
363
|
/**
|
364
364
|
* Print the chart
|
365
365
|
*/
|
@@ -435,7 +435,12 @@ extend(Chart.prototype, {
|
|
435
435
|
innerMenu,
|
436
436
|
hide,
|
437
437
|
hideTimer,
|
438
|
-
menuStyle
|
438
|
+
menuStyle,
|
439
|
+
docMouseUpHandler = function (e) {
|
440
|
+
if (!chart.pointer.inClass(e.target, className)) {
|
441
|
+
hide();
|
442
|
+
}
|
443
|
+
};
|
439
444
|
|
440
445
|
// create the menu only the first time
|
441
446
|
if (!menu) {
|
@@ -472,18 +477,19 @@ extend(Chart.prototype, {
|
|
472
477
|
addEvent(menu, 'mouseenter', function () {
|
473
478
|
clearTimeout(hideTimer);
|
474
479
|
});
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
+
|
481
|
+
|
482
|
+
// Hide it on clicking or touching outside the menu (#2258, #2335, #2407)
|
483
|
+
addEvent(document, 'mouseup', docMouseUpHandler);
|
484
|
+
addEvent(chart, 'destroy', function () {
|
485
|
+
removeEvent(document, 'mouseup', docMouseUpHandler);
|
480
486
|
});
|
481
487
|
|
482
488
|
|
483
489
|
// create the items
|
484
490
|
each(items, function (item) {
|
485
491
|
if (item) {
|
486
|
-
var element = item.separator ?
|
492
|
+
var element = item.separator ?
|
487
493
|
createElement('hr', null, null, innerMenu) :
|
488
494
|
createElement(DIV, {
|
489
495
|
onmouseover: function () {
|
@@ -580,11 +586,11 @@ extend(Chart.prototype, {
|
|
580
586
|
} else if (menuItems) {
|
581
587
|
callback = function () {
|
582
588
|
chart.contextMenu(
|
583
|
-
button.menuClassName,
|
584
|
-
menuItems,
|
585
|
-
button.translateX,
|
586
|
-
button.translateY,
|
587
|
-
button.width,
|
589
|
+
button.menuClassName,
|
590
|
+
menuItems,
|
591
|
+
button.translateX,
|
592
|
+
button.translateY,
|
593
|
+
button.width,
|
588
594
|
button.height,
|
589
595
|
button
|
590
596
|
);
|
@@ -595,7 +601,7 @@ extend(Chart.prototype, {
|
|
595
601
|
|
596
602
|
if (btnOptions.text && btnOptions.symbol) {
|
597
603
|
attr.paddingLeft = Highcharts.pick(attr.paddingLeft, 25);
|
598
|
-
|
604
|
+
|
599
605
|
} else if (!btnOptions.text) {
|
600
606
|
extend(attr, {
|
601
607
|
width: btnOptions.width,
|
@@ -616,7 +622,7 @@ extend(Chart.prototype, {
|
|
616
622
|
btnOptions.symbol,
|
617
623
|
btnOptions.symbolX - (symbolSize / 2),
|
618
624
|
btnOptions.symbolY - (symbolSize / 2),
|
619
|
-
symbolSize,
|
625
|
+
symbolSize,
|
620
626
|
symbolSize
|
621
627
|
)
|
622
628
|
.attr(extend(symbolAttr, {
|
@@ -648,7 +654,7 @@ extend(Chart.prototype, {
|
|
648
654
|
// Destroy the extra buttons added
|
649
655
|
for (i = 0; i < chart.exportSVGElements.length; i++) {
|
650
656
|
elem = chart.exportSVGElements[i];
|
651
|
-
|
657
|
+
|
652
658
|
// Destroy and null the svg/vml elements
|
653
659
|
if (elem) { // #1822
|
654
660
|
elem.onclick = elem.ontouchstart = null;
|
@@ -3,51 +3,57 @@
|
|
3
3
|
each = H.each;
|
4
4
|
|
5
5
|
seriesTypes.heatmap = H.extendClass(seriesTypes.map, {
|
6
|
-
colorKey: 'z',
|
7
6
|
useMapGeometry: false,
|
8
|
-
pointArrayMap: ['y', '
|
7
|
+
pointArrayMap: ['y', 'value'],
|
8
|
+
init: function () {
|
9
|
+
seriesTypes.map.prototype.init.apply(this, arguments);
|
10
|
+
this.pointRange = this.options.colsize || 1;
|
11
|
+
// TODO: similar logic for the Y axis
|
12
|
+
},
|
9
13
|
translate: function () {
|
10
14
|
var series = this,
|
11
15
|
options = series.options,
|
12
|
-
|
13
|
-
|
16
|
+
xAxis = series.xAxis,
|
17
|
+
yAxis = series.yAxis;
|
14
18
|
|
15
19
|
series.generatePoints();
|
16
20
|
|
17
|
-
each(series.
|
18
|
-
var
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
each(series.points, function (point) {
|
22
|
+
var xPad = (options.colsize || 1) / 2,
|
23
|
+
yPad = (options.rowsize || 1) / 2,
|
24
|
+
x1 = Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)),
|
25
|
+
x2 = Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)),
|
26
|
+
y1 = Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
|
27
|
+
y2 = Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1));
|
28
|
+
|
29
|
+
|
30
|
+
point.plotY = 1; // Pass test in Column.drawPoints
|
23
31
|
|
24
|
-
point.
|
25
|
-
'M', x - xPad, y - yPad,
|
26
|
-
'L', x + xPad, y - yPad,
|
27
|
-
'L', x + xPad, y + yPad,
|
28
|
-
'L', x - xPad, y + yPad,
|
29
|
-
'Z'
|
30
|
-
];
|
31
|
-
|
32
|
-
point.shapeType = 'path';
|
32
|
+
point.shapeType = 'rect';
|
33
33
|
point.shapeArgs = {
|
34
|
-
|
34
|
+
x: Math.min(x1, x2),
|
35
|
+
y: Math.min(y1, y2),
|
36
|
+
width: Math.abs(x2 - x1),
|
37
|
+
height: Math.abs(y2 - y1)
|
35
38
|
};
|
36
|
-
|
37
|
-
if (typeof value === 'number') {
|
38
|
-
if (value > dataMax) {
|
39
|
-
dataMax = value;
|
40
|
-
} else if (value < dataMin) {
|
41
|
-
dataMin = value;
|
42
|
-
}
|
43
|
-
}
|
44
39
|
});
|
45
40
|
|
46
|
-
series.
|
41
|
+
series.pointRange = options.colsize || 1;
|
42
|
+
series.translateColors();
|
47
43
|
},
|
48
44
|
|
45
|
+
animate: function () {},
|
49
46
|
getBox: function () {},
|
50
|
-
|
47
|
+
|
48
|
+
getExtremes: function () {
|
49
|
+
// Get the extremes from the value data
|
50
|
+
H.Series.prototype.getExtremes.call(this, this.valueData);
|
51
|
+
this.valueMin = this.dataMin;
|
52
|
+
this.valueMax = this.dataMax;
|
53
|
+
|
54
|
+
// Get the extremes from the y data
|
55
|
+
H.Series.prototype.getExtremes.call(this);
|
56
|
+
}
|
51
57
|
|
52
58
|
});
|
53
59
|
|
@@ -1,27 +1,24 @@
|
|
1
1
|
/**
|
2
|
-
* @license Map plugin v0.
|
2
|
+
* @license Map plugin v0.2 for Highcharts
|
3
3
|
*
|
4
|
-
* (c) 2011-
|
4
|
+
* (c) 2011-2014 Torstein Honsi
|
5
5
|
*
|
6
6
|
* License: www.highcharts.com/license
|
7
7
|
*/
|
8
8
|
|
9
|
-
/*
|
10
|
-
* See www.H.com/studies/world-map.htm for use case.
|
11
|
-
*
|
12
|
-
* To do:
|
13
|
-
* - Optimize long variable names and alias adapter methods and Highcharts namespace variables
|
14
|
-
* - Zoom and pan GUI
|
15
|
-
*/
|
16
9
|
/*global HighchartsAdapter*/
|
17
10
|
(function (H) {
|
18
11
|
var UNDEFINED,
|
19
12
|
Axis = H.Axis,
|
20
13
|
Chart = H.Chart,
|
14
|
+
Color = H.Color,
|
21
15
|
Point = H.Point,
|
22
16
|
Pointer = H.Pointer,
|
17
|
+
Legend = H.Legend,
|
18
|
+
Series = H.Series,
|
23
19
|
SVGRenderer = H.SVGRenderer,
|
24
20
|
VMLRenderer = H.VMLRenderer,
|
21
|
+
|
25
22
|
symbols = SVGRenderer.prototype.symbols,
|
26
23
|
each = H.each,
|
27
24
|
extend = H.extend,
|
@@ -31,10 +28,8 @@
|
|
31
28
|
numberFormat = H.numberFormat,
|
32
29
|
defaultOptions = H.getOptions(),
|
33
30
|
seriesTypes = H.seriesTypes,
|
34
|
-
inArray = HighchartsAdapter.inArray,
|
35
31
|
plotOptions = defaultOptions.plotOptions,
|
36
32
|
wrap = H.wrap,
|
37
|
-
Color = H.Color,
|
38
33
|
noop = function () {};
|
39
34
|
|
40
35
|
// Add language
|
@@ -166,7 +161,7 @@
|
|
166
161
|
this.dataMax = dataMax;
|
167
162
|
}
|
168
163
|
});
|
169
|
-
|
164
|
+
|
170
165
|
/**
|
171
166
|
* Override axis translation to make sure the aspect ratio is always kept
|
172
167
|
*/
|
@@ -174,55 +169,51 @@
|
|
174
169
|
var chart = this.chart,
|
175
170
|
mapRatio,
|
176
171
|
plotRatio = chart.plotWidth / chart.plotHeight,
|
177
|
-
isXAxis = this.isXAxis,
|
178
172
|
adjustedAxisLength,
|
179
173
|
xAxis = chart.xAxis[0],
|
180
|
-
padAxis
|
174
|
+
padAxis,
|
175
|
+
fixTo,
|
176
|
+
fixDiff;
|
177
|
+
|
181
178
|
|
182
179
|
// Run the parent method
|
183
180
|
proceed.call(this);
|
184
181
|
|
185
182
|
// On Y axis, handle both
|
186
|
-
if (chart.options.chart.
|
183
|
+
if (chart.options.chart.preserveAspectRatio && this.coll === 'yAxis' && xAxis.transA !== UNDEFINED) {
|
187
184
|
|
188
185
|
// Use the same translation for both axes
|
189
186
|
this.transA = xAxis.transA = Math.min(this.transA, xAxis.transA);
|
190
187
|
|
191
|
-
mapRatio = (xAxis.max - xAxis.min) / (this.max - this.min);
|
188
|
+
mapRatio = chart.mapRatio = plotRatio / ((xAxis.max - xAxis.min) / (this.max - this.min));
|
192
189
|
|
193
190
|
// What axis to pad to put the map in the middle
|
194
|
-
padAxis = mapRatio
|
195
|
-
|
191
|
+
padAxis = mapRatio < 1 ? this : xAxis;
|
192
|
+
|
196
193
|
// Pad it
|
197
194
|
adjustedAxisLength = (padAxis.max - padAxis.min) * padAxis.transA;
|
198
|
-
padAxis.
|
195
|
+
padAxis.pixelPadding = padAxis.len - adjustedAxisLength;
|
196
|
+
padAxis.minPixelPadding = padAxis.pixelPadding / 2;
|
197
|
+
|
198
|
+
fixTo = padAxis.fixTo;
|
199
|
+
if (fixTo) {
|
200
|
+
fixDiff = fixTo[1] - padAxis.toValue(fixTo[0], true);
|
201
|
+
fixDiff *= padAxis.transA;
|
202
|
+
if (Math.abs(fixDiff) > padAxis.minPixelPadding) { // zooming out again, keep within restricted area
|
203
|
+
fixDiff = 0;
|
204
|
+
}
|
205
|
+
padAxis.minPixelPadding -= fixDiff;
|
206
|
+
|
207
|
+
}
|
199
208
|
}
|
200
209
|
});
|
201
210
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
proceed.call(chart);
|
209
|
-
|
210
|
-
// Render the plus and minus buttons
|
211
|
-
chart.renderMapNavigation();
|
212
|
-
|
213
|
-
// Add the double click event
|
214
|
-
if (pick(mapNavigation.enableDoubleClickZoom, mapNavigation.enabled) || mapNavigation.enableDoubleClickZoomTo) {
|
215
|
-
H.addEvent(chart.container, 'dblclick', function (e) {
|
216
|
-
chart.pointer.onContainerDblClick(e);
|
217
|
-
});
|
218
|
-
}
|
219
|
-
|
220
|
-
// Add the mousewheel event
|
221
|
-
if (pick(mapNavigation.enableMouseWheelZoom, mapNavigation.enabled)) {
|
222
|
-
H.addEvent(chart.container, document.onmousewheel === undefined ? 'DOMMouseScroll' : 'mousewheel', function (e) {
|
223
|
-
chart.pointer.onContainerMouseWheel(e);
|
224
|
-
});
|
225
|
-
}
|
211
|
+
/**
|
212
|
+
* Override Axis.render in order to delete the fixTo prop
|
213
|
+
*/
|
214
|
+
wrap(Axis.prototype, 'render', function (proceed) {
|
215
|
+
proceed.call(this);
|
216
|
+
this.fixTo = null;
|
226
217
|
});
|
227
218
|
|
228
219
|
// Extend the Pointer
|
@@ -238,13 +229,15 @@
|
|
238
229
|
|
239
230
|
if (chart.options.mapNavigation.enableDoubleClickZoomTo) {
|
240
231
|
if (chart.pointer.inClass(e.target, 'highcharts-tracker')) {
|
241
|
-
chart.
|
232
|
+
chart.hoverPoint.zoomTo();
|
242
233
|
}
|
243
234
|
} else if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) {
|
244
235
|
chart.mapZoom(
|
245
236
|
0.5,
|
246
237
|
chart.xAxis[0].toValue(e.chartX),
|
247
|
-
chart.yAxis[0].toValue(e.chartY)
|
238
|
+
chart.yAxis[0].toValue(e.chartY),
|
239
|
+
e.chartX,
|
240
|
+
e.chartY
|
248
241
|
);
|
249
242
|
}
|
250
243
|
},
|
@@ -262,9 +255,11 @@
|
|
262
255
|
delta = e.detail || -(e.wheelDelta / 120);
|
263
256
|
if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) {
|
264
257
|
chart.mapZoom(
|
265
|
-
delta > 0 ? 2 :
|
258
|
+
delta > 0 ? 2 : 1 / 2,
|
266
259
|
chart.xAxis[0].toValue(e.chartX),
|
267
|
-
chart.yAxis[0].toValue(e.chartY)
|
260
|
+
chart.yAxis[0].toValue(e.chartY),
|
261
|
+
delta > 0 ? undefined : e.chartX,
|
262
|
+
delta > 0 ? undefined : e.chartY
|
268
263
|
);
|
269
264
|
}
|
270
265
|
}
|
@@ -304,6 +299,402 @@
|
|
304
299
|
}
|
305
300
|
});
|
306
301
|
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
/**
|
306
|
+
* The ColorAxis object for inclusion in gradient legends
|
307
|
+
*/
|
308
|
+
var ColorAxis = H.ColorAxis = function () {
|
309
|
+
this.init.apply(this, arguments);
|
310
|
+
};
|
311
|
+
extend(ColorAxis.prototype, Axis.prototype);
|
312
|
+
extend(ColorAxis.prototype, {
|
313
|
+
defaultColorAxisOptions: {
|
314
|
+
lineWidth: 0,
|
315
|
+
gridLineWidth: 1,
|
316
|
+
tickPixelInterval: 72,
|
317
|
+
startOnTick: true,
|
318
|
+
endOnTick: true,
|
319
|
+
offset: 0,
|
320
|
+
marker: { // docs: use another name?
|
321
|
+
animation: {
|
322
|
+
duration: 50
|
323
|
+
},
|
324
|
+
color: 'gray',
|
325
|
+
width: 0.01
|
326
|
+
},
|
327
|
+
labels: {
|
328
|
+
overflow: 'justify'
|
329
|
+
},
|
330
|
+
minColor: '#EFEFFF',
|
331
|
+
maxColor: '#102d4c'
|
332
|
+
},
|
333
|
+
init: function (chart, userOptions) {
|
334
|
+
var horiz = chart.options.legend.layout !== 'vertical',
|
335
|
+
options;
|
336
|
+
|
337
|
+
// Build the options
|
338
|
+
options = merge(this.defaultColorAxisOptions, {
|
339
|
+
side: horiz ? 2 : 1,
|
340
|
+
reversed: !horiz
|
341
|
+
}, userOptions, {
|
342
|
+
isX: horiz,
|
343
|
+
opposite: !horiz,
|
344
|
+
showEmpty: false,
|
345
|
+
title: null
|
346
|
+
});
|
347
|
+
|
348
|
+
Axis.prototype.init.call(this, chart, options);
|
349
|
+
|
350
|
+
// Base init() pushes it to the xAxis array, now pop it again
|
351
|
+
//chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop();
|
352
|
+
|
353
|
+
// Prepare data classes
|
354
|
+
if (userOptions.dataClasses) {
|
355
|
+
this.initDataClasses(userOptions);
|
356
|
+
}
|
357
|
+
|
358
|
+
// Override original axis properties
|
359
|
+
this.isXAxis = true;
|
360
|
+
this.horiz = horiz;
|
361
|
+
},
|
362
|
+
|
363
|
+
initDataClasses: function (userOptions) {
|
364
|
+
var chart = this.chart,
|
365
|
+
dataClasses,
|
366
|
+
colorCounter = 0,
|
367
|
+
options = this.options;
|
368
|
+
this.dataClasses = dataClasses = [];
|
369
|
+
|
370
|
+
each(userOptions.dataClasses, function (dataClass, i) {
|
371
|
+
var colors;
|
372
|
+
|
373
|
+
dataClass = merge(dataClass);
|
374
|
+
dataClasses.push(dataClass);
|
375
|
+
if (!dataClass.color) {
|
376
|
+
if (options.dataClassColor === 'category') {
|
377
|
+
colors = chart.options.colors;
|
378
|
+
dataClass.color = colors[colorCounter++];
|
379
|
+
// loop back to zero
|
380
|
+
if (colorCounter === colors.length) {
|
381
|
+
colorCounter = 0;
|
382
|
+
}
|
383
|
+
} else {
|
384
|
+
dataClass.color = tweenColors(Color(options.minColor), Color(options.maxColor), i / (userOptions.dataClasses.length - 1));
|
385
|
+
}
|
386
|
+
}
|
387
|
+
});
|
388
|
+
},
|
389
|
+
|
390
|
+
/**
|
391
|
+
* Extend the setOptions method to process extreme colors and color
|
392
|
+
* stops.
|
393
|
+
*/
|
394
|
+
setOptions: function (userOptions) {
|
395
|
+
Axis.prototype.setOptions.call(this, userOptions);
|
396
|
+
|
397
|
+
this.options.crosshair = this.options.marker;
|
398
|
+
|
399
|
+
this.stops = userOptions.stops || [
|
400
|
+
[0, this.options.minColor],
|
401
|
+
[1, this.options.maxColor]
|
402
|
+
];
|
403
|
+
each(this.stops, function (stop) {
|
404
|
+
stop.color = Color(stop[1]);
|
405
|
+
});
|
406
|
+
this.coll = 'colorAxis';
|
407
|
+
},
|
408
|
+
|
409
|
+
setAxisSize: function () {
|
410
|
+
var symbol = this.legendSymbol,
|
411
|
+
chart = this.chart;
|
412
|
+
|
413
|
+
if (symbol) {
|
414
|
+
this.left = symbol.x;
|
415
|
+
this.top = symbol.y;
|
416
|
+
this.width = symbol.width;
|
417
|
+
this.height = symbol.height;
|
418
|
+
this.right = chart.chartWidth - this.left - this.width;
|
419
|
+
this.bottom = chart.chartHeight - this.top - this.height;
|
420
|
+
|
421
|
+
this.len = this.horiz ? this.width : this.height;
|
422
|
+
this.pos = this.horiz ? this.left : this.top;
|
423
|
+
}
|
424
|
+
},
|
425
|
+
|
426
|
+
/**
|
427
|
+
* Translate from a value to a color
|
428
|
+
*/
|
429
|
+
toColor: function (value, point) {
|
430
|
+
var pos,
|
431
|
+
stops = this.stops,
|
432
|
+
from,
|
433
|
+
to,
|
434
|
+
color,
|
435
|
+
dataClasses = this.dataClasses,
|
436
|
+
dataClass,
|
437
|
+
i;
|
438
|
+
|
439
|
+
if (dataClasses) {
|
440
|
+
i = dataClasses.length;
|
441
|
+
while (i--) {
|
442
|
+
dataClass = dataClasses[i];
|
443
|
+
from = dataClass.from;
|
444
|
+
to = dataClass.to;
|
445
|
+
if ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) {
|
446
|
+
color = dataClass.color;
|
447
|
+
if (point) {
|
448
|
+
point.dataClass = i;
|
449
|
+
}
|
450
|
+
break;
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
} else {
|
455
|
+
|
456
|
+
if (this.isLog) {
|
457
|
+
value = this.val2lin(value);
|
458
|
+
}
|
459
|
+
pos = 1 - ((this.max - value) / (this.max - this.min));
|
460
|
+
i = stops.length;
|
461
|
+
while (i--) {
|
462
|
+
if (pos > stops[i][0]) {
|
463
|
+
break;
|
464
|
+
}
|
465
|
+
}
|
466
|
+
from = stops[i] || stops[i + 1];
|
467
|
+
to = stops[i + 1] || from;
|
468
|
+
|
469
|
+
// The position within the gradient
|
470
|
+
pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1);
|
471
|
+
|
472
|
+
color = tweenColors(
|
473
|
+
from.color,
|
474
|
+
to.color,
|
475
|
+
pos
|
476
|
+
);
|
477
|
+
}
|
478
|
+
return color;
|
479
|
+
},
|
480
|
+
|
481
|
+
getOffset: function () {
|
482
|
+
var group = this.legendGroup;
|
483
|
+
if (group) {
|
484
|
+
|
485
|
+
Axis.prototype.getOffset.call(this);
|
486
|
+
|
487
|
+
if (!this.axisGroup.parentGroup) {
|
488
|
+
|
489
|
+
// Move the axis elements inside the legend group
|
490
|
+
this.axisGroup.add(group);
|
491
|
+
this.gridGroup.add(group);
|
492
|
+
this.labelGroup.add(group);
|
493
|
+
|
494
|
+
this.added = true;
|
495
|
+
}
|
496
|
+
}
|
497
|
+
},
|
498
|
+
|
499
|
+
/**
|
500
|
+
* Create the color gradient
|
501
|
+
*/
|
502
|
+
setLegendColor: function () {
|
503
|
+
var grad,
|
504
|
+
horiz = this.horiz,
|
505
|
+
options = this.options;
|
506
|
+
|
507
|
+
grad = horiz ? [0, 0, 1, 0] : [0, 0, 0, 1];
|
508
|
+
this.legendColor = {
|
509
|
+
linearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },
|
510
|
+
stops: options.stops || [
|
511
|
+
[0, options.minColor],
|
512
|
+
[1, options.maxColor]
|
513
|
+
]
|
514
|
+
};
|
515
|
+
},
|
516
|
+
|
517
|
+
/**
|
518
|
+
* The color axis appears inside the legend and has its own legend symbol
|
519
|
+
*/
|
520
|
+
drawLegendSymbol: function (legend, item) {
|
521
|
+
var padding = legend.padding,
|
522
|
+
legendOptions = legend.options,
|
523
|
+
horiz = this.horiz,
|
524
|
+
box,
|
525
|
+
width = pick(legendOptions.symbolWidth, horiz ? 200 : 12),
|
526
|
+
height = pick(legendOptions.symbolHeight, horiz ? 12 : 200),
|
527
|
+
labelPadding = pick(legendOptions.labelPadding, horiz ? 10 : 30);
|
528
|
+
|
529
|
+
this.setLegendColor();
|
530
|
+
|
531
|
+
// Create the gradient
|
532
|
+
item.legendSymbol = this.chart.renderer.rect(
|
533
|
+
0,
|
534
|
+
legend.baseline - 11,
|
535
|
+
width,
|
536
|
+
height
|
537
|
+
).attr({
|
538
|
+
zIndex: 1
|
539
|
+
}).add(item.legendGroup);
|
540
|
+
box = item.legendSymbol.getBBox();
|
541
|
+
|
542
|
+
// Set how much space this legend item takes up
|
543
|
+
this.legendItemWidth = width + padding + (horiz ? 0 : labelPadding);
|
544
|
+
this.legendItemHeight = height + padding + (horiz ? labelPadding : 0);
|
545
|
+
},
|
546
|
+
/**
|
547
|
+
* Fool the legend
|
548
|
+
*/
|
549
|
+
setState: noop,
|
550
|
+
visible: true,
|
551
|
+
setVisible: noop,
|
552
|
+
getSeriesExtremes: function () {
|
553
|
+
var series;
|
554
|
+
if (this.series.length) {
|
555
|
+
series = this.series[0];
|
556
|
+
this.dataMin = series.valueMin;
|
557
|
+
this.dataMax = series.valueMax;
|
558
|
+
}
|
559
|
+
},
|
560
|
+
drawCrosshair: function (e, point) {
|
561
|
+
var newCross = !this.cross,
|
562
|
+
plotX = point && point.plotX,
|
563
|
+
plotY = point && point.plotY,
|
564
|
+
crossPos,
|
565
|
+
axisPos = this.pos,
|
566
|
+
axisLen = this.len;
|
567
|
+
|
568
|
+
if (point) {
|
569
|
+
crossPos = this.toPixels(point.value);
|
570
|
+
if (crossPos < axisPos) {
|
571
|
+
crossPos = axisPos - 2;
|
572
|
+
} else if (crossPos > axisPos + axisLen) {
|
573
|
+
crossPos = axisPos + axisLen + 2;
|
574
|
+
}
|
575
|
+
|
576
|
+
point.plotX = crossPos;
|
577
|
+
point.plotY = this.len - crossPos;
|
578
|
+
Axis.prototype.drawCrosshair.call(this, e, point);
|
579
|
+
point.plotX = plotX;
|
580
|
+
point.plotY = plotY;
|
581
|
+
|
582
|
+
if (!newCross && this.cross) {
|
583
|
+
this.cross
|
584
|
+
.attr({
|
585
|
+
fill: this.crosshair.color
|
586
|
+
})
|
587
|
+
.add(this.labelGroup);
|
588
|
+
}
|
589
|
+
}
|
590
|
+
},
|
591
|
+
getPlotLinePath: function (a, b, c, d, pos) {
|
592
|
+
if (pos) { // crosshairs only
|
593
|
+
return this.horiz ?
|
594
|
+
['M', pos - 4, this.top - 6, 'L', pos + 4, this.top - 6, pos, this.top, 'Z'] :
|
595
|
+
['M', this.left, pos, 'L', this.left - 6, pos + 6, this.left - 6, pos - 6, 'Z'];
|
596
|
+
} else {
|
597
|
+
return Axis.prototype.getPlotLinePath.call(this, a, b, c, d);
|
598
|
+
}
|
599
|
+
},
|
600
|
+
|
601
|
+
update: function (newOptions, redraw) {
|
602
|
+
Axis.prototype.update.call(this, newOptions, redraw);
|
603
|
+
if (this.legendItem) {
|
604
|
+
this.setLegendColor();
|
605
|
+
this.chart.legend.colorizeItem(this, true);
|
606
|
+
}
|
607
|
+
},
|
608
|
+
|
609
|
+
/**
|
610
|
+
* Get the legend item symbols for data classes
|
611
|
+
*/
|
612
|
+
getDataClassLegendSymbols: function () {
|
613
|
+
var axis = this,
|
614
|
+
chart = this.chart,
|
615
|
+
legendItems = [],
|
616
|
+
legendOptions = chart.options.legend,
|
617
|
+
valueDecimals = legendOptions.valueDecimals,
|
618
|
+
valueSuffix = legendOptions.valueSuffix || '',
|
619
|
+
name;
|
620
|
+
|
621
|
+
each(this.dataClasses, function (dataClass, i) {
|
622
|
+
var vis = true,
|
623
|
+
from = dataClass.from,
|
624
|
+
to = dataClass.to;
|
625
|
+
|
626
|
+
// Assemble the default name. This can be overridden by legend.options.labelFormatter
|
627
|
+
name = '';
|
628
|
+
if (from === UNDEFINED) {
|
629
|
+
name = '< ';
|
630
|
+
} else if (to === UNDEFINED) {
|
631
|
+
name = '> ';
|
632
|
+
}
|
633
|
+
if (from !== UNDEFINED) {
|
634
|
+
name += numberFormat(from, valueDecimals) + valueSuffix;
|
635
|
+
}
|
636
|
+
if (from !== UNDEFINED && to !== UNDEFINED) {
|
637
|
+
name += ' - ';
|
638
|
+
}
|
639
|
+
if (to !== UNDEFINED) {
|
640
|
+
name += numberFormat(to, valueDecimals) + valueSuffix;
|
641
|
+
}
|
642
|
+
|
643
|
+
// Add a mock object to the legend items
|
644
|
+
legendItems.push(H.extend({
|
645
|
+
chart: chart,
|
646
|
+
name: name,
|
647
|
+
options: {},
|
648
|
+
drawLegendSymbol: H.LegendSymbolMixin.drawRectangle,
|
649
|
+
visible: true,
|
650
|
+
setState: noop,
|
651
|
+
setVisible: function () {
|
652
|
+
vis = this.visible = !vis;
|
653
|
+
each(axis.series, function (series) {
|
654
|
+
each(series.points, function (point) {
|
655
|
+
if (point.dataClass === i) {
|
656
|
+
point.setVisible(vis);
|
657
|
+
}
|
658
|
+
});
|
659
|
+
});
|
660
|
+
|
661
|
+
chart.legend.colorizeItem(this, vis);
|
662
|
+
}
|
663
|
+
}, dataClass));
|
664
|
+
});
|
665
|
+
return legendItems;
|
666
|
+
}
|
667
|
+
});
|
668
|
+
|
669
|
+
/**
|
670
|
+
* Wrap the legend getAllItems method to add the color axis. This also removes the
|
671
|
+
* axis' own series to prevent them from showing up individually.
|
672
|
+
*/
|
673
|
+
wrap(Legend.prototype, 'getAllItems', function (proceed) {
|
674
|
+
var allItems = [],
|
675
|
+
colorAxis = this.chart.colorAxis[0];
|
676
|
+
|
677
|
+
if (colorAxis) {
|
678
|
+
|
679
|
+
// Data classes
|
680
|
+
if (colorAxis.options.dataClasses) {
|
681
|
+
allItems = allItems.concat(colorAxis.getDataClassLegendSymbols());
|
682
|
+
// Gradient legend
|
683
|
+
} else {
|
684
|
+
// Add this axis on top
|
685
|
+
allItems.push(colorAxis);
|
686
|
+
}
|
687
|
+
|
688
|
+
// Don't add the color axis' series
|
689
|
+
each(colorAxis.series, function (series) {
|
690
|
+
series.options.showInLegend = false;
|
691
|
+
});
|
692
|
+
}
|
693
|
+
|
694
|
+
return allItems.concat(proceed.call(this));
|
695
|
+
});
|
696
|
+
|
697
|
+
|
307
698
|
// Add events to the Chart object itself
|
308
699
|
extend(Chart.prototype, {
|
309
700
|
renderMapNavigation: function () {
|
@@ -319,7 +710,7 @@
|
|
319
710
|
this.handler.call(chart);
|
320
711
|
};
|
321
712
|
|
322
|
-
if (pick(options.enableButtons, options.enabled)) {
|
713
|
+
if (pick(options.enableButtons, options.enabled) && !chart.renderer.forExport) {
|
323
714
|
for (n in buttons) {
|
324
715
|
if (buttons.hasOwnProperty(n)) {
|
325
716
|
buttonOptions = merge(options.buttonOptions, buttons[n]);
|
@@ -384,11 +775,11 @@
|
|
384
775
|
/**
|
385
776
|
* Zoom the map in or out by a certain amount. Less than 1 zooms in, greater than 1 zooms out.
|
386
777
|
*/
|
387
|
-
mapZoom: function (howMuch, centerXArg, centerYArg) {
|
388
|
-
|
389
|
-
|
778
|
+
mapZoom: function (howMuch, centerXArg, centerYArg, mouseX, mouseY) {
|
779
|
+
/*if (this.isMapZooming) {
|
780
|
+
this.mapZoomQueue = arguments;
|
390
781
|
return;
|
391
|
-
}
|
782
|
+
}*/
|
392
783
|
|
393
784
|
var chart = this,
|
394
785
|
xAxis = chart.xAxis[0],
|
@@ -399,10 +790,10 @@
|
|
399
790
|
yRange = yAxis.max - yAxis.min,
|
400
791
|
centerY = pick(centerYArg, yAxis.min + yRange / 2),
|
401
792
|
newYRange = yRange * howMuch,
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
793
|
+
fixToX = mouseX ? ((mouseX - xAxis.pos) / xAxis.len) : 0.5,
|
794
|
+
fixToY = mouseY ? ((mouseY - yAxis.pos) / yAxis.len) : 0.5,
|
795
|
+
newXMin = centerX - newXRange * fixToX,
|
796
|
+
newYMin = centerY - newYRange * fixToY,
|
406
797
|
newExt = chart.fitToBox({
|
407
798
|
x: newXMin,
|
408
799
|
y: newYMin,
|
@@ -415,47 +806,93 @@
|
|
415
806
|
height: yAxis.dataMax - yAxis.dataMin
|
416
807
|
});
|
417
808
|
|
418
|
-
|
419
|
-
|
809
|
+
// When mousewheel zooming, fix the point under the mouse
|
810
|
+
if (mouseX) {
|
811
|
+
xAxis.fixTo = [mouseX - xAxis.pos, centerXArg];
|
812
|
+
}
|
813
|
+
if (mouseY) {
|
814
|
+
yAxis.fixTo = [mouseY - yAxis.pos, centerYArg];
|
815
|
+
}
|
816
|
+
|
817
|
+
// Zoom
|
818
|
+
if (howMuch !== undefined) {
|
819
|
+
xAxis.setExtremes(newExt.x, newExt.x + newExt.width, false);
|
820
|
+
yAxis.setExtremes(newExt.y, newExt.y + newExt.height, false);
|
420
821
|
|
822
|
+
// Reset zoom
|
823
|
+
} else {
|
824
|
+
xAxis.setExtremes(undefined, undefined, false);
|
825
|
+
yAxis.setExtremes(undefined, undefined, false);
|
826
|
+
}
|
827
|
+
|
421
828
|
// Prevent zooming until this one is finished animating
|
422
|
-
delay = animation ? animation.duration || 500 : 0;
|
829
|
+
/*delay = animation ? animation.duration || 500 : 0;
|
423
830
|
if (delay) {
|
424
831
|
chart.isMapZooming = true;
|
425
832
|
setTimeout(function () {
|
426
833
|
chart.isMapZooming = false;
|
834
|
+
if (chart.mapZoomQueue) {
|
835
|
+
chart.mapZoom.apply(chart, chart.mapZoomQueue);
|
836
|
+
}
|
837
|
+
chart.mapZoomQueue = null;
|
427
838
|
}, delay);
|
428
|
-
}
|
429
|
-
|
839
|
+
}*/
|
430
840
|
|
431
841
|
chart.redraw();
|
432
|
-
}
|
842
|
+
}
|
843
|
+
});
|
433
844
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
var series = point.series,
|
439
|
-
chart = series.chart;
|
845
|
+
/**
|
846
|
+
* Extend the chart getAxes method to also get the color axis
|
847
|
+
*/
|
848
|
+
wrap(Chart.prototype, 'getAxes', function (proceed) {
|
440
849
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
850
|
+
var options = this.options,
|
851
|
+
colorAxisOptions = options.colorAxis;
|
852
|
+
|
853
|
+
proceed.call(this);
|
854
|
+
|
855
|
+
this.colorAxis = [];
|
856
|
+
if (colorAxisOptions) {
|
857
|
+
proceed = new ColorAxis(this, colorAxisOptions); // Fake assignment for jsLint
|
858
|
+
}
|
859
|
+
});
|
860
|
+
|
861
|
+
/**
|
862
|
+
* Extend the Chart.render method to add zooming and panning
|
863
|
+
*/
|
864
|
+
wrap(Chart.prototype, 'render', function (proceed) {
|
865
|
+
var chart = this,
|
866
|
+
mapNavigation = chart.options.mapNavigation;
|
867
|
+
|
868
|
+
proceed.call(chart);
|
869
|
+
|
870
|
+
// Render the plus and minus buttons
|
871
|
+
chart.renderMapNavigation();
|
872
|
+
|
873
|
+
// Add the double click event
|
874
|
+
if (pick(mapNavigation.enableDoubleClickZoom, mapNavigation.enabled) || mapNavigation.enableDoubleClickZoomTo) {
|
875
|
+
H.addEvent(chart.container, 'dblclick', function (e) {
|
876
|
+
chart.pointer.onContainerDblClick(e);
|
877
|
+
});
|
878
|
+
}
|
879
|
+
|
880
|
+
// Add the mousewheel event
|
881
|
+
if (pick(mapNavigation.enableMouseWheelZoom, mapNavigation.enabled)) {
|
882
|
+
H.addEvent(chart.container, document.onmousewheel === undefined ? 'DOMMouseScroll' : 'mousewheel', function (e) {
|
883
|
+
chart.pointer.onContainerMouseWheel(e);
|
884
|
+
return false;
|
885
|
+
});
|
452
886
|
}
|
453
887
|
});
|
888
|
+
|
889
|
+
|
454
890
|
|
455
891
|
/**
|
456
892
|
* Extend the default options with map options
|
457
893
|
*/
|
458
894
|
plotOptions.map = merge(plotOptions.scatter, {
|
895
|
+
allAreas: true,
|
459
896
|
animation: false, // makes the complex shapes slow
|
460
897
|
nullColor: '#F8F8F8',
|
461
898
|
borderColor: 'silver',
|
@@ -463,20 +900,27 @@
|
|
463
900
|
marker: null,
|
464
901
|
stickyTracking: false,
|
465
902
|
dataLabels: {
|
903
|
+
format: '{point.value}',
|
466
904
|
verticalAlign: 'middle'
|
467
905
|
},
|
468
906
|
turboThreshold: 0,
|
469
907
|
tooltip: {
|
470
908
|
followPointer: true,
|
471
|
-
pointFormat: '{point.name}: {point.
|
909
|
+
pointFormat: '{point.name}: {point.value}<br/>'
|
472
910
|
},
|
473
911
|
states: {
|
474
912
|
normal: {
|
475
913
|
animation: true
|
914
|
+
},
|
915
|
+
hover: {
|
916
|
+
brightness: 0.2
|
476
917
|
}
|
477
918
|
}
|
478
919
|
});
|
479
920
|
|
921
|
+
/**
|
922
|
+
* The MapAreaPoint object
|
923
|
+
*/
|
480
924
|
var MapAreaPoint = extendClass(Point, {
|
481
925
|
/**
|
482
926
|
* Extend the Point object to split paths
|
@@ -486,11 +930,13 @@
|
|
486
930
|
var point = Point.prototype.applyOptions.call(this, options, x),
|
487
931
|
series = this.series,
|
488
932
|
seriesOptions = series.options,
|
489
|
-
joinBy = seriesOptions.
|
933
|
+
joinBy = seriesOptions.joinBy,
|
490
934
|
mapPoint;
|
491
935
|
|
492
|
-
if (
|
493
|
-
mapPoint =
|
936
|
+
if (seriesOptions.mapData) {
|
937
|
+
mapPoint = joinBy ?
|
938
|
+
series.getMapData(joinBy, point[joinBy]) : // Join by a string
|
939
|
+
seriesOptions.mapData[point.x]; // Use array position (faster)
|
494
940
|
|
495
941
|
if (mapPoint) {
|
496
942
|
// This applies only to bubbles
|
@@ -500,7 +946,7 @@
|
|
500
946
|
}
|
501
947
|
extend(point, mapPoint); // copy over properties
|
502
948
|
} else {
|
503
|
-
point.
|
949
|
+
point.value = point.value || null;
|
504
950
|
}
|
505
951
|
}
|
506
952
|
|
@@ -543,7 +989,7 @@
|
|
543
989
|
animation = point.series.options.states.normal.animation,
|
544
990
|
duration = animation && (animation.duration || 500);
|
545
991
|
|
546
|
-
if (duration && normalColor.rgba.length === 4 && hoverColor.rgba.length === 4) {
|
992
|
+
if (duration && normalColor.rgba.length === 4 && hoverColor.rgba.length === 4 && point.state !== 'select') {
|
547
993
|
delete point.pointAttr[''].fill; // avoid resetting it in Point.setState
|
548
994
|
|
549
995
|
clearTimeout(point.colorInterval);
|
@@ -562,6 +1008,26 @@
|
|
562
1008
|
}, 13);
|
563
1009
|
}
|
564
1010
|
Point.prototype.onMouseOut.call(point);
|
1011
|
+
},
|
1012
|
+
|
1013
|
+
/**
|
1014
|
+
* Zoom the chart to view a specific area point
|
1015
|
+
*/
|
1016
|
+
zoomTo: function () {
|
1017
|
+
var point = this,
|
1018
|
+
series = point.series;
|
1019
|
+
|
1020
|
+
series.xAxis.setExtremes(
|
1021
|
+
point._minX,
|
1022
|
+
point._maxX,
|
1023
|
+
false
|
1024
|
+
);
|
1025
|
+
series.yAxis.setExtremes(
|
1026
|
+
point._minY,
|
1027
|
+
point._maxY,
|
1028
|
+
false
|
1029
|
+
);
|
1030
|
+
series.chart.redraw();
|
565
1031
|
}
|
566
1032
|
});
|
567
1033
|
|
@@ -573,201 +1039,19 @@
|
|
573
1039
|
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
|
574
1040
|
stroke: 'borderColor',
|
575
1041
|
'stroke-width': 'borderWidth',
|
576
|
-
fill: 'color'
|
1042
|
+
fill: 'color',
|
1043
|
+
dashstyle: 'dashStyle'
|
577
1044
|
},
|
578
|
-
colorKey: 'y',
|
579
1045
|
pointClass: MapAreaPoint,
|
1046
|
+
pointArrayMap: ['value'],
|
1047
|
+
axisTypes: ['xAxis', 'yAxis', 'colorAxis'],
|
1048
|
+
optionalAxis: 'colorAxis',
|
580
1049
|
trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
|
581
1050
|
getSymbol: noop,
|
582
1051
|
supportsDrilldown: true,
|
583
1052
|
getExtremesFromAll: true,
|
584
1053
|
useMapGeometry: true, // get axis extremes from paths, not values
|
585
|
-
|
586
|
-
var series = this,
|
587
|
-
legendOptions = chart.options.legend,
|
588
|
-
valueDecimals = legendOptions.valueDecimals,
|
589
|
-
valueSuffix = legendOptions.valueSuffix || '',
|
590
|
-
legendItems = [],
|
591
|
-
name,
|
592
|
-
from,
|
593
|
-
to,
|
594
|
-
fromLabel,
|
595
|
-
toLabel,
|
596
|
-
colorRange,
|
597
|
-
valueRanges,
|
598
|
-
gradientColor,
|
599
|
-
grad,
|
600
|
-
tmpLabel,
|
601
|
-
horizontal = chart.options.legend.layout === 'horizontal';
|
602
|
-
|
603
|
-
|
604
|
-
H.Series.prototype.init.apply(this, arguments);
|
605
|
-
colorRange = series.options.colorRange;
|
606
|
-
valueRanges = series.options.valueRanges;
|
607
|
-
|
608
|
-
if (valueRanges) {
|
609
|
-
each(valueRanges, function (range, i) {
|
610
|
-
var vis = true;
|
611
|
-
from = range.from;
|
612
|
-
to = range.to;
|
613
|
-
|
614
|
-
// Assemble the default name. This can be overridden by legend.options.labelFormatter
|
615
|
-
name = '';
|
616
|
-
if (from === UNDEFINED) {
|
617
|
-
name = '< ';
|
618
|
-
} else if (to === UNDEFINED) {
|
619
|
-
name = '> ';
|
620
|
-
}
|
621
|
-
if (from !== UNDEFINED) {
|
622
|
-
name += numberFormat(from, valueDecimals) + valueSuffix;
|
623
|
-
}
|
624
|
-
if (from !== UNDEFINED && to !== UNDEFINED) {
|
625
|
-
name += ' - ';
|
626
|
-
}
|
627
|
-
if (to !== UNDEFINED) {
|
628
|
-
name += numberFormat(to, valueDecimals) + valueSuffix;
|
629
|
-
}
|
630
|
-
|
631
|
-
// Add a mock object to the legend items
|
632
|
-
legendItems.push(H.extend({
|
633
|
-
chart: series.chart,
|
634
|
-
name: name,
|
635
|
-
options: {},
|
636
|
-
drawLegendSymbol: seriesTypes.area.prototype.drawLegendSymbol,
|
637
|
-
visible: true,
|
638
|
-
setState: noop,
|
639
|
-
setVisible: function () {
|
640
|
-
vis = this.visible = !vis;
|
641
|
-
each(series.points, function (point) {
|
642
|
-
if (point.valueRange === i) {
|
643
|
-
point.setVisible(vis);
|
644
|
-
}
|
645
|
-
});
|
646
|
-
|
647
|
-
chart.legend.colorizeItem(this, vis);
|
648
|
-
}
|
649
|
-
}, range));
|
650
|
-
});
|
651
|
-
series.legendItems = legendItems;
|
652
|
-
|
653
|
-
} else if (colorRange) {
|
654
|
-
|
655
|
-
from = colorRange.from;
|
656
|
-
to = colorRange.to;
|
657
|
-
fromLabel = colorRange.fromLabel;
|
658
|
-
toLabel = colorRange.toLabel;
|
659
|
-
|
660
|
-
// Flips linearGradient variables and label text.
|
661
|
-
grad = horizontal ? [0, 0, 1, 0] : [0, 1, 0, 0];
|
662
|
-
if (!horizontal) {
|
663
|
-
tmpLabel = fromLabel;
|
664
|
-
fromLabel = toLabel;
|
665
|
-
toLabel = tmpLabel;
|
666
|
-
}
|
667
|
-
|
668
|
-
// Creates color gradient.
|
669
|
-
gradientColor = {
|
670
|
-
linearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },
|
671
|
-
stops:
|
672
|
-
[
|
673
|
-
[0, from],
|
674
|
-
[1, to]
|
675
|
-
]
|
676
|
-
};
|
677
|
-
|
678
|
-
// Add a mock object to the legend items.
|
679
|
-
legendItems = [{
|
680
|
-
chart: series.chart,
|
681
|
-
options: {},
|
682
|
-
fromLabel: fromLabel,
|
683
|
-
toLabel: toLabel,
|
684
|
-
color: gradientColor,
|
685
|
-
drawLegendSymbol: this.drawLegendSymbolGradient,
|
686
|
-
visible: true,
|
687
|
-
setState: noop,
|
688
|
-
setVisible: noop
|
689
|
-
}];
|
690
|
-
|
691
|
-
series.legendItems = legendItems;
|
692
|
-
}
|
693
|
-
},
|
694
|
-
|
695
|
-
/**
|
696
|
-
* If neither valueRanges nor colorRanges are defined, use basic area symbol.
|
697
|
-
*/
|
698
|
-
drawLegendSymbol: seriesTypes.area.prototype.drawLegendSymbol,
|
699
|
-
|
700
|
-
/**
|
701
|
-
* Gets the series' symbol in the legend and extended legend with more information.
|
702
|
-
*
|
703
|
-
* @param {Object} legend The legend object
|
704
|
-
* @param {Object} item The series (this) or point
|
705
|
-
*/
|
706
|
-
drawLegendSymbolGradient: function (legend, item) {
|
707
|
-
var spacing = legend.options.symbolPadding,
|
708
|
-
padding = pick(legend.options.padding, 8),
|
709
|
-
positionY,
|
710
|
-
positionX,
|
711
|
-
gradientSize = this.chart.renderer.fontMetrics(legend.options.itemStyle.fontSize).h,
|
712
|
-
horizontal = legend.options.layout === 'horizontal',
|
713
|
-
box1,
|
714
|
-
box2,
|
715
|
-
box3,
|
716
|
-
rectangleLength = pick(legend.options.rectangleLength, 200);
|
717
|
-
|
718
|
-
// Set local variables based on option.
|
719
|
-
if (horizontal) {
|
720
|
-
positionY = -(spacing / 2);
|
721
|
-
positionX = 0;
|
722
|
-
} else {
|
723
|
-
positionY = -rectangleLength + legend.baseline - (spacing / 2);
|
724
|
-
positionX = padding + gradientSize;
|
725
|
-
}
|
726
|
-
|
727
|
-
// Creates the from text.
|
728
|
-
item.fromText = this.chart.renderer.text(
|
729
|
-
item.fromLabel, // Text.
|
730
|
-
positionX, // Lower left x.
|
731
|
-
positionY // Lower left y.
|
732
|
-
).attr({
|
733
|
-
zIndex: 2
|
734
|
-
}).add(item.legendGroup);
|
735
|
-
box1 = item.fromText.getBBox();
|
736
|
-
|
737
|
-
// Creates legend symbol.
|
738
|
-
// Ternary changes variables based on option.
|
739
|
-
item.legendSymbol = this.chart.renderer.rect(
|
740
|
-
horizontal ? box1.x + box1.width + spacing : box1.x - gradientSize - spacing, // Upper left x.
|
741
|
-
box1.y, // Upper left y.
|
742
|
-
horizontal ? rectangleLength : gradientSize, // Width.
|
743
|
-
horizontal ? gradientSize : rectangleLength, // Height.
|
744
|
-
2 // Corner radius.
|
745
|
-
).attr({
|
746
|
-
zIndex: 1
|
747
|
-
}).add(item.legendGroup);
|
748
|
-
box2 = item.legendSymbol.getBBox();
|
749
|
-
|
750
|
-
// Creates the to text.
|
751
|
-
// Vertical coordinate changed based on option.
|
752
|
-
item.toText = this.chart.renderer.text(
|
753
|
-
item.toLabel,
|
754
|
-
box2.x + box2.width + spacing,
|
755
|
-
horizontal ? positionY : box2.y + box2.height - spacing
|
756
|
-
).attr({
|
757
|
-
zIndex: 2
|
758
|
-
}).add(item.legendGroup);
|
759
|
-
box3 = item.toText.getBBox();
|
760
|
-
|
761
|
-
// Changes legend box settings based on option.
|
762
|
-
if (horizontal) {
|
763
|
-
legend.offsetWidth = box1.width + box2.width + box3.width + (spacing * 2) + padding;
|
764
|
-
legend.itemY = gradientSize + padding;
|
765
|
-
} else {
|
766
|
-
legend.offsetWidth = Math.max(box1.width, box3.width) + (spacing) + box2.width + padding;
|
767
|
-
legend.itemY = box2.height + padding;
|
768
|
-
legend.itemX = spacing;
|
769
|
-
}
|
770
|
-
},
|
1054
|
+
parallelArrays: ['x', 'y', 'value'],
|
771
1055
|
|
772
1056
|
/**
|
773
1057
|
* Get the bounding box of all paths in the map combined.
|
@@ -810,8 +1094,8 @@
|
|
810
1094
|
}
|
811
1095
|
}
|
812
1096
|
// Cache point bounding box for use to position data labels, bubbles etc
|
813
|
-
point._midX = pointMinX + (pointMaxX - pointMinX) *
|
814
|
-
point._midY = pointMinY + (pointMaxY - pointMinY) *
|
1097
|
+
point._midX = pointMinX + (pointMaxX - pointMinX) * (point.middleX || 0.5); // pick is slower and very marginally needed
|
1098
|
+
point._midY = pointMinY + (pointMaxY - pointMinY) * (point.middleY || 0.5);
|
815
1099
|
point._maxX = pointMaxX;
|
816
1100
|
point._minX = pointMinX;
|
817
1101
|
point._maxY = pointMaxY;
|
@@ -838,6 +1122,18 @@
|
|
838
1122
|
},
|
839
1123
|
|
840
1124
|
getExtremes: function () {
|
1125
|
+
// Get the actual value extremes for colors
|
1126
|
+
Series.prototype.getExtremes.call(this, this.valueData);
|
1127
|
+
|
1128
|
+
// Recalculate box on updated data
|
1129
|
+
if (this.chart.hasRendered && this.isDirtyData) {
|
1130
|
+
this.getBox(this.options.data);
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
this.valueMin = this.dataMin;
|
1134
|
+
this.valueMax = this.dataMax;
|
1135
|
+
|
1136
|
+
// Extremes for the mock Y axis
|
841
1137
|
this.dataMin = this.minY;
|
842
1138
|
this.dataMax = this.maxY;
|
843
1139
|
},
|
@@ -852,26 +1148,31 @@
|
|
852
1148
|
even = false, // while loop reads from the end
|
853
1149
|
xAxis = series.xAxis,
|
854
1150
|
yAxis = series.yAxis,
|
855
|
-
|
1151
|
+
xMin = xAxis.min,
|
1152
|
+
xTransA = xAxis.transA,
|
1153
|
+
xMinPixelPadding = xAxis.minPixelPadding,
|
1154
|
+
yMin = yAxis.min,
|
1155
|
+
yTransA = yAxis.transA,
|
1156
|
+
yMinPixelPadding = yAxis.minPixelPadding,
|
1157
|
+
i,
|
1158
|
+
ret = []; // Preserve the original
|
856
1159
|
|
857
|
-
// Preserve the original
|
858
|
-
path = [].concat(path);
|
859
|
-
|
860
1160
|
// Do the translation
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
if (
|
865
|
-
|
866
|
-
|
867
|
-
|
1161
|
+
if (path) {
|
1162
|
+
i = path.length;
|
1163
|
+
while (i--) {
|
1164
|
+
if (typeof path[i] === 'number') {
|
1165
|
+
ret[i] = even ?
|
1166
|
+
(path[i] - xMin) * xTransA + xMinPixelPadding :
|
1167
|
+
(path[i] - yMin) * yTransA + yMinPixelPadding;
|
1168
|
+
even = !even;
|
1169
|
+
} else {
|
1170
|
+
ret[i] = path[i];
|
868
1171
|
}
|
869
|
-
even = !even;
|
870
1172
|
}
|
871
1173
|
}
|
872
1174
|
|
873
|
-
|
874
|
-
return path;
|
1175
|
+
return ret;
|
875
1176
|
},
|
876
1177
|
|
877
1178
|
/**
|
@@ -882,7 +1183,7 @@
|
|
882
1183
|
setData: function (data, redraw) {
|
883
1184
|
var options = this.options,
|
884
1185
|
mapData = options.mapData,
|
885
|
-
joinBy = options.
|
1186
|
+
joinBy = options.joinBy,
|
886
1187
|
dataUsed = [];
|
887
1188
|
|
888
1189
|
|
@@ -900,13 +1201,14 @@
|
|
900
1201
|
}
|
901
1202
|
|
902
1203
|
// Add those map points that don't correspond to data, which will be drawn as null points
|
1204
|
+
dataUsed = '|' + dataUsed.join('|') + '|'; // String search is faster than array.indexOf
|
903
1205
|
each(mapData, function (mapPoint) {
|
904
|
-
if (!joinBy ||
|
905
|
-
data.push(merge(mapPoint, {
|
1206
|
+
if (!joinBy || dataUsed.indexOf('|' + mapPoint[joinBy] + '|') === -1) {
|
1207
|
+
data.push(merge(mapPoint, { value: null }));
|
906
1208
|
}
|
907
1209
|
});
|
908
1210
|
}
|
909
|
-
|
1211
|
+
Series.prototype.setData.call(this, data, redraw);
|
910
1212
|
},
|
911
1213
|
|
912
1214
|
/**
|
@@ -920,7 +1222,7 @@
|
|
920
1222
|
|
921
1223
|
// Create a cache for quicker lookup second time
|
922
1224
|
if (!mapMap) {
|
923
|
-
mapMap = this.mapMap =
|
1225
|
+
mapMap = this.mapMap = {};
|
924
1226
|
}
|
925
1227
|
if (mapMap[value] !== undefined) {
|
926
1228
|
return mapData[mapMap[value]];
|
@@ -935,92 +1237,29 @@
|
|
935
1237
|
}
|
936
1238
|
},
|
937
1239
|
|
938
|
-
/**
|
939
|
-
* Add the path option for data points. Find the max value for color calculation.
|
940
|
-
*/
|
941
|
-
translate: function () {
|
942
|
-
var series = this,
|
943
|
-
dataMin = Number.MAX_VALUE,
|
944
|
-
dataMax = Number.MIN_VALUE;
|
945
|
-
|
946
|
-
series.generatePoints();
|
947
|
-
|
948
|
-
each(series.data, function (point) {
|
949
|
-
|
950
|
-
point.shapeType = 'path';
|
951
|
-
point.shapeArgs = {
|
952
|
-
d: series.translatePath(point.path)
|
953
|
-
};
|
954
|
-
|
955
|
-
// TODO: do point colors in drawPoints instead of point.init
|
956
|
-
if (typeof point.y === 'number') {
|
957
|
-
if (point.y > dataMax) {
|
958
|
-
dataMax = point.y;
|
959
|
-
} else if (point.y < dataMin) {
|
960
|
-
dataMin = point.y;
|
961
|
-
}
|
962
|
-
}
|
963
|
-
});
|
964
|
-
|
965
|
-
series.translateColors(dataMin, dataMax);
|
966
|
-
},
|
967
|
-
|
968
1240
|
/**
|
969
1241
|
* In choropleth maps, the color is a result of the value, so this needs translation too
|
970
1242
|
*/
|
971
|
-
translateColors: function (
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
colorRange = seriesOptions.colorRange,
|
976
|
-
colorKey = this.colorKey,
|
977
|
-
nullColor = seriesOptions.nullColor,
|
978
|
-
from,
|
979
|
-
to;
|
1243
|
+
translateColors: function () {
|
1244
|
+
var series = this,
|
1245
|
+
nullColor = this.options.nullColor,
|
1246
|
+
colorAxis = this.colorAxis;
|
980
1247
|
|
981
|
-
if (colorRange) {
|
982
|
-
from = Color(colorRange.from);
|
983
|
-
to = Color(colorRange.to);
|
984
|
-
}
|
985
1248
|
each(this.data, function (point) {
|
986
|
-
var value = point
|
987
|
-
|
988
|
-
range,
|
989
|
-
color,
|
990
|
-
i,
|
991
|
-
pos;
|
992
|
-
|
993
|
-
if (valueRanges) {
|
994
|
-
i = valueRanges.length;
|
995
|
-
if (isNull) {
|
996
|
-
color = nullColor;
|
997
|
-
} else {
|
998
|
-
while (i--) {
|
999
|
-
range = valueRanges[i];
|
1000
|
-
from = range.from;
|
1001
|
-
to = range.to;
|
1002
|
-
if ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) {
|
1003
|
-
color = range.color;
|
1004
|
-
break;
|
1005
|
-
}
|
1006
|
-
}
|
1007
|
-
point.valueRange = i;
|
1008
|
-
}
|
1009
|
-
} else if (colorRange && !isNull) {
|
1249
|
+
var value = point.value,
|
1250
|
+
color;
|
1010
1251
|
|
1011
|
-
|
1012
|
-
color = tweenColors(from, to, pos);
|
1013
|
-
} else if (isNull) {
|
1014
|
-
color = nullColor;
|
1015
|
-
}
|
1252
|
+
color = value === null ? nullColor : colorAxis ? colorAxis.toColor(value, point) : (point.color) || series.color;
|
1016
1253
|
|
1017
1254
|
if (color) {
|
1018
|
-
point.color =
|
1019
|
-
point.options.color = color;
|
1255
|
+
point.color = point.options.color = color;
|
1020
1256
|
}
|
1021
1257
|
});
|
1022
1258
|
},
|
1023
1259
|
|
1260
|
+
/**
|
1261
|
+
* No graph for the map series
|
1262
|
+
*/
|
1024
1263
|
drawGraph: noop,
|
1025
1264
|
|
1026
1265
|
/**
|
@@ -1029,46 +1268,186 @@
|
|
1029
1268
|
*/
|
1030
1269
|
drawDataLabels: noop,
|
1031
1270
|
|
1032
|
-
/**
|
1033
|
-
*
|
1034
|
-
* Extend it by assigning the tooltip position.
|
1271
|
+
/**
|
1272
|
+
* Add the path option for data points. Find the max value for color calculation.
|
1035
1273
|
*/
|
1036
|
-
|
1274
|
+
translate: function () {
|
1037
1275
|
var series = this,
|
1038
1276
|
xAxis = series.xAxis,
|
1039
|
-
yAxis = series.yAxis
|
1040
|
-
|
1277
|
+
yAxis = series.yAxis;
|
1278
|
+
|
1279
|
+
series.generatePoints();
|
1041
1280
|
|
1042
|
-
// Make points pass test in drawing
|
1043
1281
|
each(series.data, function (point) {
|
1044
|
-
point.plotY = 1; // pass null test in column.drawPoints
|
1045
|
-
if (point[colorKey] === null) {
|
1046
|
-
point[colorKey] = 0;
|
1047
|
-
point.isNull = true;
|
1048
|
-
}
|
1049
|
-
});
|
1050
1282
|
|
1051
|
-
// Draw them
|
1052
|
-
seriesTypes.column.prototype.drawPoints.apply(series);
|
1053
|
-
|
1054
|
-
each(series.data, function (point) {
|
1055
|
-
|
1056
1283
|
// Record the middle point (loosely based on centroid), determined
|
1057
1284
|
// by the middleX and middleY options.
|
1058
1285
|
point.plotX = xAxis.toPixels(point._midX, true);
|
1059
1286
|
point.plotY = yAxis.toPixels(point._midY, true);
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
point
|
1287
|
+
|
1288
|
+
if (series.isDirtyData || series.chart.renderer.isVML) {
|
1289
|
+
|
1290
|
+
point.shapeType = 'path';
|
1291
|
+
point.shapeArgs = {
|
1292
|
+
//d: display ? series.translatePath(point.path) : ''
|
1293
|
+
d: series.translatePath(point.path),
|
1294
|
+
'vector-effect': 'non-scaling-stroke'
|
1295
|
+
};
|
1064
1296
|
}
|
1065
1297
|
});
|
1298
|
+
|
1299
|
+
series.translateColors();
|
1300
|
+
},
|
1301
|
+
|
1302
|
+
/**
|
1303
|
+
* Use the drawPoints method of column, that is able to handle simple shapeArgs.
|
1304
|
+
* Extend it by assigning the tooltip position.
|
1305
|
+
*/
|
1306
|
+
drawPoints: function () {
|
1307
|
+
var series = this,
|
1308
|
+
xAxis = series.xAxis,
|
1309
|
+
yAxis = series.yAxis,
|
1310
|
+
scale,
|
1311
|
+
translateX,
|
1312
|
+
group = series.group,
|
1313
|
+
chart = series.chart,
|
1314
|
+
renderer = chart.renderer,
|
1315
|
+
translateY,
|
1316
|
+
getTranslate = function (axis, mapRatio) {
|
1317
|
+
var dataMin = axis.dataMin,
|
1318
|
+
dataMax = axis.dataMax,
|
1319
|
+
fullDataMin = dataMin - ((dataMax - dataMin) * (mapRatio - 1) / 2),
|
1320
|
+
fullMin = axis.min - axis.minPixelPadding / axis.transA,
|
1321
|
+
minOffset = fullMin - fullDataMin,
|
1322
|
+
centerOffset = (dataMax - dataMin - axis.max + axis.min) * mapRatio,
|
1323
|
+
center = minOffset / centerOffset;
|
1324
|
+
return (axis.len * (1 - scale)) * center;
|
1325
|
+
};
|
1326
|
+
|
1327
|
+
// Set a group that handles transform during zooming and panning in order to preserve clipping
|
1328
|
+
// on series.group
|
1329
|
+
if (!series.transformGroup) {
|
1330
|
+
series.transformGroup = renderer.g()
|
1331
|
+
.attr({
|
1332
|
+
scaleX: 1,
|
1333
|
+
scaleY: 1
|
1334
|
+
})
|
1335
|
+
.add(group);
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
// Draw the shapes again
|
1339
|
+
if (series.isDirtyData || renderer.isVML) {
|
1340
|
+
|
1341
|
+
// Draw them in transformGroup
|
1342
|
+
series.group = series.transformGroup;
|
1343
|
+
seriesTypes.column.prototype.drawPoints.apply(series);
|
1344
|
+
series.group = group; // Reset
|
1345
|
+
|
1346
|
+
// Individual point actions
|
1347
|
+
each(series.points, function (point) {
|
1348
|
+
|
1349
|
+
// Reset color on update/redraw
|
1350
|
+
if (chart.hasRendered && point.graphic) {
|
1351
|
+
point.graphic.attr('fill', point.options.color);
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
});
|
1355
|
+
|
1356
|
+
// Set the base for later scale-zooming
|
1357
|
+
this.transA = xAxis.transA;
|
1066
1358
|
|
1359
|
+
// Just update the scale and transform for better performance
|
1360
|
+
} else {
|
1361
|
+
scale = xAxis.transA / this.transA;
|
1362
|
+
if (scale > 0.99 && scale < 1.01) { // rounding errors
|
1363
|
+
translateX = 0;
|
1364
|
+
translateY = 0;
|
1365
|
+
scale = 1;
|
1366
|
+
|
1367
|
+
} else {
|
1368
|
+
translateX = getTranslate(xAxis, Math.max(1, series.chart.mapRatio));
|
1369
|
+
translateY = getTranslate(yAxis, 1 / Math.min(1, series.chart.mapRatio));
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
this.transformGroup.animate({
|
1373
|
+
translateX: translateX,
|
1374
|
+
translateY: translateY,
|
1375
|
+
scaleX: scale,
|
1376
|
+
scaleY: scale
|
1377
|
+
});
|
1378
|
+
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
|
1067
1382
|
// Now draw the data labels
|
1068
|
-
|
1383
|
+
Series.prototype.drawDataLabels.call(series);
|
1069
1384
|
|
1070
1385
|
},
|
1071
1386
|
|
1387
|
+
/**
|
1388
|
+
* Override render to throw in an async call in IE8. Otherwise it chokes on the US counties demo.
|
1389
|
+
*/
|
1390
|
+
render: function () {
|
1391
|
+
var series = this,
|
1392
|
+
render = Series.prototype.render;
|
1393
|
+
|
1394
|
+
// Give IE8 some time to breathe.
|
1395
|
+
if (series.chart.renderer.isVML && series.data.length > 3000) {
|
1396
|
+
setTimeout(function () {
|
1397
|
+
render.call(series);
|
1398
|
+
});
|
1399
|
+
} else {
|
1400
|
+
render.call(series);
|
1401
|
+
}
|
1402
|
+
},
|
1403
|
+
|
1404
|
+
/**
|
1405
|
+
* The initial animation for the map series. By default, animation is disabled.
|
1406
|
+
* Animation of map shapes is not at all supported in VML browsers.
|
1407
|
+
*/
|
1408
|
+
animate: function (init) {
|
1409
|
+
var chart = this.chart,
|
1410
|
+
animation = this.options.animation,
|
1411
|
+
group = this.group,
|
1412
|
+
xAxis = this.xAxis,
|
1413
|
+
yAxis = this.yAxis,
|
1414
|
+
left = xAxis.pos,
|
1415
|
+
top = yAxis.pos;
|
1416
|
+
|
1417
|
+
if (chart.renderer.isSVG) {
|
1418
|
+
|
1419
|
+
if (animation === true) {
|
1420
|
+
animation = {
|
1421
|
+
duration: 1000
|
1422
|
+
};
|
1423
|
+
}
|
1424
|
+
|
1425
|
+
// Initialize the animation
|
1426
|
+
if (init) {
|
1427
|
+
|
1428
|
+
// Scale down the group and place it in the center
|
1429
|
+
group.attr({
|
1430
|
+
translateX: left + xAxis.len / 2,
|
1431
|
+
translateY: top + yAxis.len / 2,
|
1432
|
+
scaleX: 0.001, // #1499
|
1433
|
+
scaleY: 0.001
|
1434
|
+
});
|
1435
|
+
|
1436
|
+
// Run the animation
|
1437
|
+
} else {
|
1438
|
+
group.animate({
|
1439
|
+
translateX: left,
|
1440
|
+
translateY: top,
|
1441
|
+
scaleX: 1,
|
1442
|
+
scaleY: 1
|
1443
|
+
}, animation);
|
1444
|
+
|
1445
|
+
// Delete this function to allow it only once
|
1446
|
+
this.animate = null;
|
1447
|
+
}
|
1448
|
+
}
|
1449
|
+
},
|
1450
|
+
|
1072
1451
|
/**
|
1073
1452
|
* Animate in the new series from the clicked point in the old series.
|
1074
1453
|
* Depends on the drilldown.js module
|
@@ -1104,11 +1483,13 @@
|
|
1104
1483
|
|
1105
1484
|
});
|
1106
1485
|
|
1107
|
-
|
1486
|
+
this.animate = null;
|
1108
1487
|
}
|
1109
1488
|
|
1110
1489
|
},
|
1111
1490
|
|
1491
|
+
drawLegendSymbol: H.LegendSymbolMixin.drawRectangle,
|
1492
|
+
|
1112
1493
|
/**
|
1113
1494
|
* When drilling up, pull out the individual point graphics from the lower series
|
1114
1495
|
* and animate them into the origin point in the upper series.
|
@@ -1131,14 +1512,14 @@
|
|
1131
1512
|
// The mapline series type
|
1132
1513
|
plotOptions.mapline = merge(plotOptions.map, {
|
1133
1514
|
lineWidth: 1,
|
1134
|
-
|
1515
|
+
fillColor: 'none'
|
1135
1516
|
});
|
1136
1517
|
seriesTypes.mapline = extendClass(seriesTypes.map, {
|
1137
1518
|
type: 'mapline',
|
1138
1519
|
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
|
1139
1520
|
stroke: 'color',
|
1140
1521
|
'stroke-width': 'lineWidth',
|
1141
|
-
fill: '
|
1522
|
+
fill: 'fillColor'
|
1142
1523
|
},
|
1143
1524
|
drawLegendSymbol: seriesTypes.line.prototype.drawLegendSymbol
|
1144
1525
|
});
|
@@ -1233,15 +1614,14 @@
|
|
1233
1614
|
var hiddenAxis = {
|
1234
1615
|
endOnTick: false,
|
1235
1616
|
gridLineWidth: 0,
|
1236
|
-
labels: {
|
1237
|
-
enabled: false
|
1238
|
-
},
|
1239
1617
|
lineWidth: 0,
|
1240
1618
|
minPadding: 0,
|
1241
1619
|
maxPadding: 0,
|
1242
1620
|
startOnTick: false,
|
1243
|
-
|
1244
|
-
|
1621
|
+
title: null,
|
1622
|
+
tickPositions: []
|
1623
|
+
//tickInterval: 500,
|
1624
|
+
//gridZIndex: 10
|
1245
1625
|
},
|
1246
1626
|
seriesOptions;
|
1247
1627
|
|
@@ -1251,7 +1631,8 @@
|
|
1251
1631
|
|
1252
1632
|
options = merge({
|
1253
1633
|
chart: {
|
1254
|
-
panning: 'xy'
|
1634
|
+
panning: 'xy',
|
1635
|
+
type: 'map'
|
1255
1636
|
},
|
1256
1637
|
xAxis: hiddenAxis,
|
1257
1638
|
yAxis: merge(hiddenAxis, { reversed: true })
|
@@ -1260,8 +1641,9 @@
|
|
1260
1641
|
|
1261
1642
|
{ // forced options
|
1262
1643
|
chart: {
|
1263
|
-
|
1264
|
-
|
1644
|
+
inverted: false,
|
1645
|
+
alignTicks: false,
|
1646
|
+
preserveAspectRatio: true
|
1265
1647
|
}
|
1266
1648
|
});
|
1267
1649
|
|
@@ -1271,3 +1653,4 @@
|
|
1271
1653
|
return new Chart(options, callback);
|
1272
1654
|
};
|
1273
1655
|
}(Highcharts));
|
1656
|
+
|