highcharts-rails 4.2.7 → 5.0.0
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 +4 -4
- data/CHANGELOG.markdown +34 -0
- data/Gemfile +4 -0
- data/Rakefile +53 -32
- data/app/assets/javascripts/highcharts.js +18775 -17176
- data/app/assets/javascripts/highcharts/highcharts-3d.js +1849 -1563
- data/app/assets/javascripts/highcharts/highcharts-more.js +2162 -1988
- data/app/assets/javascripts/highcharts/modules/accessibility.js +1005 -0
- data/app/assets/javascripts/highcharts/modules/annotations.js +408 -401
- data/app/assets/javascripts/highcharts/modules/boost.js +561 -546
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +330 -324
- data/app/assets/javascripts/highcharts/modules/data.js +973 -965
- data/app/assets/javascripts/highcharts/modules/drilldown.js +783 -723
- data/app/assets/javascripts/highcharts/modules/exporting.js +864 -785
- data/app/assets/javascripts/highcharts/modules/funnel.js +290 -306
- data/app/assets/javascripts/highcharts/modules/heatmap.js +701 -645
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +150 -132
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +414 -355
- data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +164 -0
- data/app/assets/javascripts/highcharts/modules/series-label.js +473 -448
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +279 -271
- data/app/assets/javascripts/highcharts/modules/treemap.js +921 -886
- data/app/assets/javascripts/highcharts/themes/dark-blue.js +307 -244
- data/app/assets/javascripts/highcharts/themes/dark-green.js +303 -244
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +231 -201
- data/app/assets/javascripts/highcharts/themes/gray.js +314 -245
- data/app/assets/javascripts/highcharts/themes/grid-light.js +91 -66
- data/app/assets/javascripts/highcharts/themes/grid.js +124 -96
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +119 -94
- data/app/assets/javascripts/highcharts/themes/skies.js +108 -85
- data/lib/highcharts/version.rb +1 -1
- metadata +13 -14
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +0 -1
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +0 -3115
- data/app/assets/javascripts/highcharts/modules/map.js +0 -2117
@@ -1,1005 +1,1057 @@
|
|
1
|
-
// ==ClosureCompiler==
|
2
|
-
// @compilation_level SIMPLE_OPTIMIZATIONS
|
3
|
-
|
4
1
|
/**
|
5
|
-
* @license Highcharts JS
|
2
|
+
* @license Highcharts JS v5.0.0 (2016-09-29)
|
6
3
|
*
|
7
4
|
* (c) 2009-2016 Torstein Honsi
|
8
5
|
*
|
9
6
|
* License: www.highcharts.com/license
|
10
7
|
*/
|
11
|
-
|
12
|
-
(function (factory) {
|
8
|
+
(function(factory) {
|
13
9
|
if (typeof module === 'object' && module.exports) {
|
14
10
|
module.exports = factory;
|
15
11
|
} else {
|
16
12
|
factory(Highcharts);
|
17
13
|
}
|
18
|
-
}(function
|
19
|
-
|
20
|
-
arrayMax = Highcharts.arrayMax,
|
21
|
-
each = Highcharts.each,
|
22
|
-
extend = Highcharts.extend,
|
23
|
-
isNumber = Highcharts.isNumber,
|
24
|
-
merge = Highcharts.merge,
|
25
|
-
map = Highcharts.map,
|
26
|
-
pick = Highcharts.pick,
|
27
|
-
pInt = Highcharts.pInt,
|
28
|
-
correctFloat = Highcharts.correctFloat,
|
29
|
-
defaultPlotOptions = Highcharts.getOptions().plotOptions,
|
30
|
-
seriesTypes = Highcharts.seriesTypes,
|
31
|
-
extendClass = Highcharts.extendClass,
|
32
|
-
splat = Highcharts.splat,
|
33
|
-
wrap = Highcharts.wrap,
|
34
|
-
Axis = Highcharts.Axis,
|
35
|
-
Tick = Highcharts.Tick,
|
36
|
-
Point = Highcharts.Point,
|
37
|
-
Pointer = Highcharts.Pointer,
|
38
|
-
CenteredSeriesMixin = Highcharts.CenteredSeriesMixin,
|
39
|
-
TrackerMixin = Highcharts.TrackerMixin,
|
40
|
-
Series = Highcharts.Series,
|
41
|
-
math = Math,
|
42
|
-
mathRound = math.round,
|
43
|
-
mathFloor = math.floor,
|
44
|
-
mathMax = math.max,
|
45
|
-
Color = Highcharts.Color,
|
46
|
-
noop = function () {},
|
47
|
-
UNDEFINED;/**
|
48
|
-
* The Pane object allows options that are common to a set of X and Y axes.
|
49
|
-
*
|
50
|
-
* In the future, this can be extended to basic Highcharts and Highstock.
|
51
|
-
*/
|
52
|
-
function Pane(options, chart, firstAxis) {
|
53
|
-
this.init(options, chart, firstAxis);
|
54
|
-
}
|
55
|
-
|
56
|
-
// Extend the Pane prototype
|
57
|
-
extend(Pane.prototype, {
|
58
|
-
|
59
|
-
/**
|
60
|
-
* Initiate the Pane object
|
61
|
-
*/
|
62
|
-
init: function (options, chart, firstAxis) {
|
63
|
-
var pane = this,
|
64
|
-
backgroundOption,
|
65
|
-
defaultOptions = pane.defaultOptions;
|
66
|
-
|
67
|
-
pane.chart = chart;
|
68
|
-
|
69
|
-
// Set options. Angular charts have a default background (#3318)
|
70
|
-
pane.options = options = merge(defaultOptions, chart.angular ? { background: {} } : undefined, options);
|
71
|
-
|
72
|
-
backgroundOption = options.background;
|
73
|
-
|
74
|
-
// To avoid having weighty logic to place, update and remove the backgrounds,
|
75
|
-
// push them to the first axis' plot bands and borrow the existing logic there.
|
76
|
-
if (backgroundOption) {
|
77
|
-
each([].concat(splat(backgroundOption)).reverse(), function (config) {
|
78
|
-
var backgroundColor = config.backgroundColor, // if defined, replace the old one (specific for gradients)
|
79
|
-
axisUserOptions = firstAxis.userOptions;
|
80
|
-
config = merge(pane.defaultBackgroundOptions, config);
|
81
|
-
if (backgroundColor) {
|
82
|
-
config.backgroundColor = backgroundColor;
|
83
|
-
}
|
84
|
-
config.color = config.backgroundColor; // due to naming in plotBands
|
85
|
-
firstAxis.options.plotBands.unshift(config);
|
86
|
-
axisUserOptions.plotBands = axisUserOptions.plotBands || []; // #3176
|
87
|
-
if (axisUserOptions.plotBands !== firstAxis.options.plotBands) {
|
88
|
-
axisUserOptions.plotBands.unshift(config);
|
89
|
-
}
|
90
|
-
});
|
91
|
-
}
|
92
|
-
},
|
93
|
-
|
14
|
+
}(function(Highcharts) {
|
15
|
+
(function(H) {
|
94
16
|
/**
|
95
|
-
*
|
17
|
+
* (c) 2010-2016 Torstein Honsi
|
18
|
+
*
|
19
|
+
* License: www.highcharts.com/license
|
96
20
|
*/
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
//endAngle: startAngle + 360
|
103
|
-
},
|
104
|
-
|
21
|
+
'use strict';
|
22
|
+
var each = H.each,
|
23
|
+
extend = H.extend,
|
24
|
+
merge = H.merge,
|
25
|
+
splat = H.splat;
|
105
26
|
/**
|
106
|
-
* The
|
27
|
+
* The Pane object allows options that are common to a set of X and Y axes.
|
28
|
+
*
|
29
|
+
* In the future, this can be extended to basic Highcharts and Highstock.
|
107
30
|
*/
|
108
|
-
|
109
|
-
|
110
|
-
borderWidth: 1,
|
111
|
-
borderColor: 'silver',
|
112
|
-
backgroundColor: {
|
113
|
-
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
114
|
-
stops: [
|
115
|
-
[0, '#FFF'],
|
116
|
-
[1, '#DDD']
|
117
|
-
]
|
118
|
-
},
|
119
|
-
from: -Number.MAX_VALUE, // corrected to axis min
|
120
|
-
innerRadius: 0,
|
121
|
-
to: Number.MAX_VALUE, // corrected to axis max
|
122
|
-
outerRadius: '105%'
|
31
|
+
function Pane(options, chart, firstAxis) {
|
32
|
+
this.init(options, chart, firstAxis);
|
123
33
|
}
|
124
|
-
});
|
125
|
-
|
126
|
-
var axisProto = Axis.prototype,
|
127
|
-
tickProto = Tick.prototype;
|
128
|
-
|
129
|
-
/**
|
130
|
-
* Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
|
131
|
-
*/
|
132
|
-
var hiddenAxisMixin = {
|
133
|
-
getOffset: noop,
|
134
|
-
redraw: function () {
|
135
|
-
this.isDirty = false; // prevent setting Y axis dirty
|
136
|
-
},
|
137
|
-
render: function () {
|
138
|
-
this.isDirty = false; // prevent setting Y axis dirty
|
139
|
-
},
|
140
|
-
setScale: noop,
|
141
|
-
setCategories: noop,
|
142
|
-
setTitle: noop
|
143
|
-
};
|
144
|
-
|
145
|
-
/**
|
146
|
-
* Augmented methods for the value axis
|
147
|
-
*/
|
148
|
-
var radialAxisMixin = {
|
149
|
-
isRadial: true,
|
150
34
|
|
151
|
-
|
152
|
-
|
153
|
-
*/
|
154
|
-
defaultRadialGaugeOptions: {
|
155
|
-
labels: {
|
156
|
-
align: 'center',
|
157
|
-
x: 0,
|
158
|
-
y: null // auto
|
159
|
-
},
|
160
|
-
minorGridLineWidth: 0,
|
161
|
-
minorTickInterval: 'auto',
|
162
|
-
minorTickLength: 10,
|
163
|
-
minorTickPosition: 'inside',
|
164
|
-
minorTickWidth: 1,
|
165
|
-
tickLength: 10,
|
166
|
-
tickPosition: 'inside',
|
167
|
-
tickWidth: 2,
|
168
|
-
title: {
|
169
|
-
rotation: 0
|
170
|
-
},
|
171
|
-
zIndex: 2 // behind dials, points in the series group
|
172
|
-
},
|
173
|
-
|
174
|
-
// Circular axis around the perimeter of a polar chart
|
175
|
-
defaultRadialXOptions: {
|
176
|
-
gridLineWidth: 1, // spokes
|
177
|
-
labels: {
|
178
|
-
align: null, // auto
|
179
|
-
distance: 15,
|
180
|
-
x: 0,
|
181
|
-
y: null // auto
|
182
|
-
},
|
183
|
-
maxPadding: 0,
|
184
|
-
minPadding: 0,
|
185
|
-
showLastLabel: false,
|
186
|
-
tickLength: 0
|
187
|
-
},
|
188
|
-
|
189
|
-
// Radial axis, like a spoke in a polar chart
|
190
|
-
defaultRadialYOptions: {
|
191
|
-
gridLineInterpolation: 'circle',
|
192
|
-
labels: {
|
193
|
-
align: 'right',
|
194
|
-
x: -3,
|
195
|
-
y: -2
|
196
|
-
},
|
197
|
-
showLastLabel: false,
|
198
|
-
title: {
|
199
|
-
x: 4,
|
200
|
-
text: null,
|
201
|
-
rotation: 90
|
202
|
-
}
|
203
|
-
},
|
35
|
+
// Extend the Pane prototype
|
36
|
+
extend(Pane.prototype, {
|
204
37
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
38
|
+
/**
|
39
|
+
* Initiate the Pane object
|
40
|
+
*/
|
41
|
+
init: function(options, chart, firstAxis) {
|
42
|
+
var pane = this,
|
43
|
+
backgroundOption,
|
44
|
+
defaultOptions = pane.defaultOptions;
|
209
45
|
|
210
|
-
|
211
|
-
this.defaultOptions,
|
212
|
-
this.defaultRadialOptions,
|
213
|
-
userOptions
|
214
|
-
);
|
46
|
+
pane.chart = chart;
|
215
47
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
48
|
+
// Set options. Angular charts have a default background (#3318)
|
49
|
+
pane.options = options = merge(defaultOptions, chart.angular ? {
|
50
|
+
background: {}
|
51
|
+
} : undefined, options);
|
220
52
|
|
221
|
-
|
53
|
+
backgroundOption = options.background;
|
222
54
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
55
|
+
// To avoid having weighty logic to place, update and remove the backgrounds,
|
56
|
+
// push them to the first axis' plot bands and borrow the existing logic there.
|
57
|
+
if (backgroundOption) {
|
58
|
+
each([].concat(splat(backgroundOption)).reverse(), function(config) {
|
59
|
+
var mConfig,
|
60
|
+
axisUserOptions = firstAxis.userOptions;
|
61
|
+
mConfig = merge(pane.defaultBackgroundOptions, config);
|
230
62
|
|
231
|
-
// Title or label offsets are not counted
|
232
|
-
this.chart.axisOffset[this.side] = 0;
|
233
63
|
|
234
|
-
|
235
|
-
|
236
|
-
|
64
|
+
if (config.backgroundColor) {
|
65
|
+
mConfig.backgroundColor = config.backgroundColor;
|
66
|
+
}
|
67
|
+
mConfig.color = mConfig.backgroundColor; // due to naming in plotBands
|
68
|
+
|
237
69
|
|
70
|
+
firstAxis.options.plotBands.unshift(mConfig);
|
71
|
+
axisUserOptions.plotBands = axisUserOptions.plotBands || []; // #3176
|
72
|
+
if (axisUserOptions.plotBands !== firstAxis.options.plotBands) {
|
73
|
+
axisUserOptions.plotBands.unshift(mConfig);
|
74
|
+
}
|
75
|
+
});
|
76
|
+
}
|
77
|
+
},
|
78
|
+
|
79
|
+
/**
|
80
|
+
* The default options object
|
81
|
+
*/
|
82
|
+
defaultOptions: {
|
83
|
+
// background: {conditional},
|
84
|
+
center: ['50%', '50%'],
|
85
|
+
size: '85%',
|
86
|
+
startAngle: 0
|
87
|
+
//endAngle: startAngle + 360
|
88
|
+
},
|
238
89
|
|
90
|
+
/**
|
91
|
+
* The default background options
|
92
|
+
*/
|
93
|
+
defaultBackgroundOptions: {
|
94
|
+
className: 'highcharts-pane',
|
95
|
+
shape: 'circle',
|
96
|
+
|
97
|
+
borderWidth: 1,
|
98
|
+
borderColor: '#cccccc',
|
99
|
+
backgroundColor: {
|
100
|
+
linearGradient: {
|
101
|
+
x1: 0,
|
102
|
+
y1: 0,
|
103
|
+
x2: 0,
|
104
|
+
y2: 1
|
105
|
+
},
|
106
|
+
stops: [
|
107
|
+
[0, '#ffffff'],
|
108
|
+
[1, '#e6e6e6']
|
109
|
+
]
|
110
|
+
},
|
111
|
+
|
112
|
+
from: -Number.MAX_VALUE, // corrected to axis min
|
113
|
+
innerRadius: 0,
|
114
|
+
to: Number.MAX_VALUE, // corrected to axis max
|
115
|
+
outerRadius: '105%'
|
116
|
+
}
|
117
|
+
|
118
|
+
});
|
119
|
+
|
120
|
+
H.Pane = Pane;
|
121
|
+
|
122
|
+
}(Highcharts));
|
123
|
+
(function(H) {
|
239
124
|
/**
|
240
|
-
*
|
241
|
-
*
|
125
|
+
* (c) 2010-2016 Torstein Honsi
|
126
|
+
*
|
127
|
+
* License: www.highcharts.com/license
|
242
128
|
*/
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
129
|
+
'use strict';
|
130
|
+
var Axis = H.Axis,
|
131
|
+
CenteredSeriesMixin = H.CenteredSeriesMixin,
|
132
|
+
each = H.each,
|
133
|
+
extend = H.extend,
|
134
|
+
map = H.map,
|
135
|
+
merge = H.merge,
|
136
|
+
noop = H.noop,
|
137
|
+
Pane = H.Pane,
|
138
|
+
pick = H.pick,
|
139
|
+
pInt = H.pInt,
|
140
|
+
Tick = H.Tick,
|
141
|
+
splat = H.splat,
|
142
|
+
wrap = H.wrap,
|
143
|
+
|
144
|
+
|
145
|
+
hiddenAxisMixin, // @todo Extract this to a new file
|
146
|
+
radialAxisMixin, // @todo Extract this to a new file
|
147
|
+
axisProto = Axis.prototype,
|
148
|
+
tickProto = Tick.prototype;
|
149
|
+
|
150
|
+
/**
|
151
|
+
* Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
|
152
|
+
*/
|
153
|
+
hiddenAxisMixin = {
|
154
|
+
getOffset: noop,
|
155
|
+
redraw: function() {
|
156
|
+
this.isDirty = false; // prevent setting Y axis dirty
|
157
|
+
},
|
158
|
+
render: function() {
|
159
|
+
this.isDirty = false; // prevent setting Y axis dirty
|
160
|
+
},
|
161
|
+
setScale: noop,
|
162
|
+
setCategories: noop,
|
163
|
+
setTitle: noop
|
164
|
+
};
|
269
165
|
|
270
166
|
/**
|
271
|
-
*
|
272
|
-
* in rotation. This allows the translate method to return angle for
|
273
|
-
* any given value.
|
167
|
+
* Augmented methods for the value axis
|
274
168
|
*/
|
275
|
-
|
169
|
+
radialAxisMixin = {
|
276
170
|
|
277
|
-
|
278
|
-
|
171
|
+
/**
|
172
|
+
* The default options extend defaultYAxisOptions
|
173
|
+
*/
|
174
|
+
defaultRadialGaugeOptions: {
|
175
|
+
labels: {
|
176
|
+
align: 'center',
|
177
|
+
x: 0,
|
178
|
+
y: null // auto
|
179
|
+
},
|
180
|
+
minorGridLineWidth: 0,
|
181
|
+
minorTickInterval: 'auto',
|
182
|
+
minorTickLength: 10,
|
183
|
+
minorTickPosition: 'inside',
|
184
|
+
minorTickWidth: 1,
|
185
|
+
tickLength: 10,
|
186
|
+
tickPosition: 'inside',
|
187
|
+
tickWidth: 2,
|
188
|
+
title: {
|
189
|
+
rotation: 0
|
190
|
+
},
|
191
|
+
zIndex: 2 // behind dials, points in the series group
|
192
|
+
},
|
279
193
|
|
280
|
-
//
|
281
|
-
|
282
|
-
|
194
|
+
// Circular axis around the perimeter of a polar chart
|
195
|
+
defaultRadialXOptions: {
|
196
|
+
gridLineWidth: 1, // spokes
|
197
|
+
labels: {
|
198
|
+
align: null, // auto
|
199
|
+
distance: 15,
|
200
|
+
x: 0,
|
201
|
+
y: null // auto
|
202
|
+
},
|
203
|
+
maxPadding: 0,
|
204
|
+
minPadding: 0,
|
205
|
+
showLastLabel: false,
|
206
|
+
tickLength: 0
|
207
|
+
},
|
283
208
|
|
284
|
-
|
285
|
-
|
209
|
+
// Radial axis, like a spoke in a polar chart
|
210
|
+
defaultRadialYOptions: {
|
211
|
+
gridLineInterpolation: 'circle',
|
212
|
+
labels: {
|
213
|
+
align: 'right',
|
214
|
+
x: -3,
|
215
|
+
y: -2
|
216
|
+
},
|
217
|
+
showLastLabel: false,
|
218
|
+
title: {
|
219
|
+
x: 4,
|
220
|
+
text: null,
|
221
|
+
rotation: 90
|
222
|
+
}
|
223
|
+
},
|
286
224
|
|
225
|
+
/**
|
226
|
+
* Merge and set options
|
227
|
+
*/
|
228
|
+
setOptions: function(userOptions) {
|
287
229
|
|
288
|
-
|
289
|
-
this.
|
230
|
+
var options = this.options = merge(
|
231
|
+
this.defaultOptions,
|
232
|
+
this.defaultRadialOptions,
|
233
|
+
userOptions
|
234
|
+
);
|
235
|
+
|
236
|
+
// Make sure the plotBands array is instanciated for each Axis (#2649)
|
237
|
+
if (!options.plotBands) {
|
238
|
+
options.plotBands = [];
|
290
239
|
}
|
291
240
|
|
292
|
-
|
293
|
-
|
241
|
+
},
|
242
|
+
|
243
|
+
/**
|
244
|
+
* Wrap the getOffset method to return zero offset for title or labels in a radial
|
245
|
+
* axis
|
246
|
+
*/
|
247
|
+
getOffset: function() {
|
248
|
+
// Call the Axis prototype method (the method we're in now is on the instance)
|
249
|
+
axisProto.getOffset.call(this);
|
250
|
+
|
251
|
+
// Title or label offsets are not counted
|
252
|
+
this.chart.axisOffset[this.side] = 0;
|
253
|
+
|
254
|
+
// Set the center array
|
255
|
+
this.center = this.pane.center = CenteredSeriesMixin.getCenter.call(this.pane);
|
256
|
+
},
|
257
|
+
|
258
|
+
|
259
|
+
/**
|
260
|
+
* Get the path for the axis line. This method is also referenced in the getPlotLinePath
|
261
|
+
* method.
|
262
|
+
*/
|
263
|
+
getLinePath: function(lineWidth, radius) {
|
264
|
+
var center = this.center,
|
265
|
+
end,
|
266
|
+
chart = this.chart,
|
267
|
+
r = pick(radius, center[2] / 2 - this.offset),
|
268
|
+
path;
|
269
|
+
|
270
|
+
if (this.isCircular || radius !== undefined) {
|
271
|
+
path = this.chart.renderer.symbols.arc(
|
272
|
+
this.left + center[0],
|
273
|
+
this.top + center[1],
|
274
|
+
r,
|
275
|
+
r, {
|
276
|
+
start: this.startAngleRad,
|
277
|
+
end: this.endAngleRad,
|
278
|
+
open: true,
|
279
|
+
innerR: 0
|
280
|
+
}
|
281
|
+
);
|
294
282
|
} else {
|
295
|
-
|
296
|
-
|
283
|
+
end = this.postTranslate(this.angleRad, r);
|
284
|
+
path = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
|
297
285
|
}
|
298
|
-
|
299
|
-
|
286
|
+
return path;
|
287
|
+
},
|
300
288
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
// is added to the X axis to prevent the last point from overlapping the first.
|
308
|
-
this.autoConnect = this.isCircular && pick(this.userMax, this.options.max) === undefined &&
|
309
|
-
this.endAngleRad - this.startAngleRad === 2 * Math.PI;
|
310
|
-
|
311
|
-
if (this.autoConnect) {
|
312
|
-
this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260
|
313
|
-
}
|
314
|
-
},
|
289
|
+
/**
|
290
|
+
* Override setAxisTranslation by setting the translation to the difference
|
291
|
+
* in rotation. This allows the translate method to return angle for
|
292
|
+
* any given value.
|
293
|
+
*/
|
294
|
+
setAxisTranslation: function() {
|
315
295
|
|
316
|
-
|
317
|
-
|
318
|
-
* allows tickPixelInterval to apply to pixel lengths along the perimeter
|
319
|
-
*/
|
320
|
-
setAxisSize: function () {
|
296
|
+
// Call uber method
|
297
|
+
axisProto.setAxisTranslation.call(this);
|
321
298
|
|
322
|
-
|
299
|
+
// Set transA and minPixelPadding
|
300
|
+
if (this.center) { // it's not defined the first time
|
301
|
+
if (this.isCircular) {
|
323
302
|
|
324
|
-
|
303
|
+
this.transA = (this.endAngleRad - this.startAngleRad) /
|
304
|
+
((this.max - this.min) || 1);
|
325
305
|
|
326
|
-
// Set the center array
|
327
|
-
this.center = this.pane.center = Highcharts.CenteredSeriesMixin.getCenter.call(this.pane);
|
328
306
|
|
329
|
-
|
330
|
-
|
331
|
-
|
307
|
+
} else {
|
308
|
+
this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
|
309
|
+
}
|
310
|
+
|
311
|
+
if (this.isXAxis) {
|
312
|
+
this.minPixelPadding = this.transA * this.minPointOffset;
|
313
|
+
} else {
|
314
|
+
// This is a workaround for regression #2593, but categories still don't position correctly.
|
315
|
+
this.minPixelPadding = 0;
|
316
|
+
}
|
332
317
|
}
|
318
|
+
},
|
333
319
|
|
334
|
-
|
335
|
-
|
320
|
+
/**
|
321
|
+
* In case of auto connect, add one closestPointRange to the max value right before
|
322
|
+
* tickPositions are computed, so that ticks will extend passed the real max.
|
323
|
+
*/
|
324
|
+
beforeSetTickPositions: function() {
|
325
|
+
// If autoConnect is true, polygonal grid lines are connected, and one closestPointRange
|
326
|
+
// is added to the X axis to prevent the last point from overlapping the first.
|
327
|
+
this.autoConnect = this.isCircular && pick(this.userMax, this.options.max) === undefined &&
|
328
|
+
this.endAngleRad - this.startAngleRad === 2 * Math.PI;
|
329
|
+
|
330
|
+
if (this.autoConnect) {
|
331
|
+
this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260
|
332
|
+
}
|
333
|
+
},
|
336
334
|
|
335
|
+
/**
|
336
|
+
* Override the setAxisSize method to use the arc's circumference as length. This
|
337
|
+
* allows tickPixelInterval to apply to pixel lengths along the perimeter
|
338
|
+
*/
|
339
|
+
setAxisSize: function() {
|
337
340
|
|
338
|
-
|
339
|
-
},
|
341
|
+
axisProto.setAxisSize.call(this);
|
340
342
|
|
341
|
-
|
342
|
-
* Returns the x, y coordinate of a point given by a value and a pixel distance
|
343
|
-
* from center
|
344
|
-
*/
|
345
|
-
getPosition: function (value, length) {
|
346
|
-
return this.postTranslate(
|
347
|
-
this.isCircular ? this.translate(value) : this.angleRad, // #2848
|
348
|
-
pick(this.isCircular ? length : this.translate(value), this.center[2] / 2) - this.offset
|
349
|
-
);
|
350
|
-
},
|
343
|
+
if (this.isRadial) {
|
351
344
|
|
352
|
-
|
353
|
-
|
354
|
-
*/
|
355
|
-
postTranslate: function (angle, radius) {
|
345
|
+
// Set the center array
|
346
|
+
this.center = this.pane.center = CenteredSeriesMixin.getCenter.call(this.pane);
|
356
347
|
|
357
|
-
|
358
|
-
|
348
|
+
// The sector is used in Axis.translate to compute the translation of reversed axis points (#2570)
|
349
|
+
if (this.isCircular) {
|
350
|
+
this.sector = this.endAngleRad - this.startAngleRad;
|
351
|
+
}
|
359
352
|
|
360
|
-
|
353
|
+
// Axis len is used to lay out the ticks
|
354
|
+
this.len = this.width = this.height = this.center[2] * pick(this.sector, 1) / 2;
|
361
355
|
|
362
|
-
return {
|
363
|
-
x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
|
364
|
-
y: chart.plotTop + center[1] + Math.sin(angle) * radius
|
365
|
-
};
|
366
356
|
|
367
|
-
|
357
|
+
}
|
358
|
+
},
|
368
359
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
pick(options.thickness, 10)
|
380
|
-
],
|
381
|
-
offset = Math.min(this.offset, 0),
|
382
|
-
percentRegex = /%$/,
|
383
|
-
start,
|
384
|
-
end,
|
385
|
-
open,
|
386
|
-
isCircular = this.isCircular, // X axis in a polar chart
|
387
|
-
ret;
|
360
|
+
/**
|
361
|
+
* Returns the x, y coordinate of a point given by a value and a pixel distance
|
362
|
+
* from center
|
363
|
+
*/
|
364
|
+
getPosition: function(value, length) {
|
365
|
+
return this.postTranslate(
|
366
|
+
this.isCircular ? this.translate(value) : this.angleRad, // #2848
|
367
|
+
pick(this.isCircular ? length : this.translate(value), this.center[2] / 2) - this.offset
|
368
|
+
);
|
369
|
+
},
|
388
370
|
|
389
|
-
|
390
|
-
|
391
|
-
|
371
|
+
/**
|
372
|
+
* Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates.
|
373
|
+
*/
|
374
|
+
postTranslate: function(angle, radius) {
|
392
375
|
|
393
|
-
|
394
|
-
|
376
|
+
var chart = this.chart,
|
377
|
+
center = this.center;
|
395
378
|
|
396
|
-
|
397
|
-
from = Math.max(from, this.min);
|
398
|
-
to = Math.min(to, this.max);
|
379
|
+
angle = this.startAngleRad + angle;
|
399
380
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
}
|
381
|
+
return {
|
382
|
+
x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
|
383
|
+
y: chart.plotTop + center[1] + Math.sin(angle) * radius
|
384
|
+
};
|
405
385
|
|
406
|
-
|
407
|
-
radii = map(radii, function (radius) {
|
408
|
-
if (percentRegex.test(radius)) {
|
409
|
-
radius = (pInt(radius, 10) * fullRadius) / 100;
|
410
|
-
}
|
411
|
-
return radius;
|
412
|
-
});
|
386
|
+
},
|
413
387
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
388
|
+
/**
|
389
|
+
* Find the path for plot bands along the radial axis
|
390
|
+
*/
|
391
|
+
getPlotBandPath: function(from, to, options) {
|
392
|
+
var center = this.center,
|
393
|
+
startAngleRad = this.startAngleRad,
|
394
|
+
fullRadius = center[2] / 2,
|
395
|
+
radii = [
|
396
|
+
pick(options.outerRadius, '100%'),
|
397
|
+
options.innerRadius,
|
398
|
+
pick(options.thickness, 10)
|
399
|
+
],
|
400
|
+
offset = Math.min(this.offset, 0),
|
401
|
+
percentRegex = /%$/,
|
402
|
+
start,
|
403
|
+
end,
|
404
|
+
open,
|
405
|
+
isCircular = this.isCircular, // X axis in a polar chart
|
406
|
+
ret;
|
407
|
+
|
408
|
+
// Polygonal plot bands
|
409
|
+
if (this.options.gridLineInterpolation === 'polygon') {
|
410
|
+
ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
|
411
|
+
|
412
|
+
// Circular grid bands
|
419
413
|
} else {
|
420
|
-
start = startAngleRad + this.translate(from);
|
421
|
-
end = startAngleRad + this.translate(to);
|
422
|
-
}
|
423
414
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
ret = this.chart.renderer.symbols.arc(
|
428
|
-
this.left + center[0],
|
429
|
-
this.top + center[1],
|
430
|
-
radii[0],
|
431
|
-
radii[0],
|
432
|
-
{
|
433
|
-
start: Math.min(start, end), // Math is for reversed yAxis (#3606)
|
434
|
-
end: Math.max(start, end),
|
435
|
-
innerR: pick(radii[1], radii[0] - radii[2]),
|
436
|
-
open: open
|
437
|
-
}
|
438
|
-
);
|
439
|
-
}
|
415
|
+
// Keep within bounds
|
416
|
+
from = Math.max(from, this.min);
|
417
|
+
to = Math.min(to, this.max);
|
440
418
|
|
441
|
-
|
442
|
-
|
419
|
+
// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
|
420
|
+
if (!isCircular) {
|
421
|
+
radii[0] = this.translate(from);
|
422
|
+
radii[1] = this.translate(to);
|
423
|
+
}
|
443
424
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
end = axis.getPosition(value),
|
452
|
-
xAxis,
|
453
|
-
xy,
|
454
|
-
tickPositions,
|
455
|
-
ret;
|
425
|
+
// Convert percentages to pixel values
|
426
|
+
radii = map(radii, function(radius) {
|
427
|
+
if (percentRegex.test(radius)) {
|
428
|
+
radius = (pInt(radius, 10) * fullRadius) / 100;
|
429
|
+
}
|
430
|
+
return radius;
|
431
|
+
});
|
456
432
|
|
457
|
-
|
458
|
-
|
459
|
-
|
433
|
+
// Handle full circle
|
434
|
+
if (options.shape === 'circle' || !isCircular) {
|
435
|
+
start = -Math.PI / 2;
|
436
|
+
end = Math.PI * 1.5;
|
437
|
+
open = true;
|
438
|
+
} else {
|
439
|
+
start = startAngleRad + this.translate(from);
|
440
|
+
end = startAngleRad + this.translate(to);
|
441
|
+
}
|
460
442
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
443
|
+
radii[0] -= offset; // #5283
|
444
|
+
radii[2] -= offset; // #5283
|
445
|
+
|
446
|
+
ret = this.chart.renderer.symbols.arc(
|
447
|
+
this.left + center[0],
|
448
|
+
this.top + center[1],
|
449
|
+
radii[0],
|
450
|
+
radii[0], {
|
451
|
+
start: Math.min(start, end), // Math is for reversed yAxis (#3606)
|
452
|
+
end: Math.max(start, end),
|
453
|
+
innerR: pick(radii[1], radii[0] - radii[2]),
|
454
|
+
open: open
|
455
|
+
}
|
456
|
+
);
|
466
457
|
}
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
458
|
+
|
459
|
+
return ret;
|
460
|
+
},
|
461
|
+
|
462
|
+
/**
|
463
|
+
* Find the path for plot lines perpendicular to the radial axis.
|
464
|
+
*/
|
465
|
+
getPlotLinePath: function(value, reverse) {
|
466
|
+
var axis = this,
|
467
|
+
center = axis.center,
|
468
|
+
chart = axis.chart,
|
469
|
+
end = axis.getPosition(value),
|
470
|
+
xAxis,
|
471
|
+
xy,
|
472
|
+
tickPositions,
|
473
|
+
ret;
|
474
|
+
|
475
|
+
// Spokes
|
476
|
+
if (axis.isCircular) {
|
477
|
+
ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
|
478
|
+
|
479
|
+
// Concentric circles
|
480
|
+
} else if (axis.options.gridLineInterpolation === 'circle') {
|
481
|
+
value = axis.translate(value);
|
482
|
+
if (value) { // a value of 0 is in the center
|
483
|
+
ret = axis.getLinePath(0, value);
|
484
|
+
}
|
485
|
+
// Concentric polygons
|
486
|
+
} else {
|
487
|
+
// Find the X axis in the same pane
|
488
|
+
each(chart.xAxis, function(a) {
|
489
|
+
if (a.pane === axis.pane) {
|
490
|
+
xAxis = a;
|
491
|
+
}
|
492
|
+
});
|
493
|
+
ret = [];
|
494
|
+
value = axis.translate(value);
|
495
|
+
tickPositions = xAxis.tickPositions;
|
496
|
+
if (xAxis.autoConnect) {
|
497
|
+
tickPositions = tickPositions.concat([tickPositions[0]]);
|
498
|
+
}
|
499
|
+
// Reverse the positions for concatenation of polygonal plot bands
|
500
|
+
if (reverse) {
|
501
|
+
tickPositions = [].concat(tickPositions).reverse();
|
473
502
|
}
|
474
|
-
});
|
475
|
-
ret = [];
|
476
|
-
value = axis.translate(value);
|
477
|
-
tickPositions = xAxis.tickPositions;
|
478
|
-
if (xAxis.autoConnect) {
|
479
|
-
tickPositions = tickPositions.concat([tickPositions[0]]);
|
480
|
-
}
|
481
|
-
// Reverse the positions for concatenation of polygonal plot bands
|
482
|
-
if (reverse) {
|
483
|
-
tickPositions = [].concat(tickPositions).reverse();
|
484
|
-
}
|
485
503
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
504
|
+
each(tickPositions, function(pos, i) {
|
505
|
+
xy = xAxis.getPosition(pos, value);
|
506
|
+
ret.push(i ? 'L' : 'M', xy.x, xy.y);
|
507
|
+
});
|
490
508
|
|
509
|
+
}
|
510
|
+
return ret;
|
511
|
+
},
|
512
|
+
|
513
|
+
/**
|
514
|
+
* Find the position for the axis title, by default inside the gauge
|
515
|
+
*/
|
516
|
+
getTitlePosition: function() {
|
517
|
+
var center = this.center,
|
518
|
+
chart = this.chart,
|
519
|
+
titleOptions = this.options.title;
|
520
|
+
|
521
|
+
return {
|
522
|
+
x: chart.plotLeft + center[0] + (titleOptions.x || 0),
|
523
|
+
y: chart.plotTop + center[1] - ({
|
524
|
+
high: 0.5,
|
525
|
+
middle: 0.25,
|
526
|
+
low: 0
|
527
|
+
}[titleOptions.align] *
|
528
|
+
center[2]) + (titleOptions.y || 0)
|
529
|
+
};
|
491
530
|
}
|
492
|
-
|
493
|
-
}
|
531
|
+
|
532
|
+
};
|
494
533
|
|
495
534
|
/**
|
496
|
-
*
|
535
|
+
* Override axisProto.init to mix in special axis instance functions and function overrides
|
497
536
|
*/
|
498
|
-
|
499
|
-
var
|
500
|
-
|
501
|
-
|
537
|
+
wrap(axisProto, 'init', function(proceed, chart, userOptions) {
|
538
|
+
var axis = this,
|
539
|
+
angular = chart.angular,
|
540
|
+
polar = chart.polar,
|
541
|
+
isX = userOptions.isX,
|
542
|
+
isHidden = angular && isX,
|
543
|
+
isCircular,
|
544
|
+
options,
|
545
|
+
chartOptions = chart.options,
|
546
|
+
paneIndex = userOptions.pane || 0,
|
547
|
+
pane,
|
548
|
+
paneOptions;
|
549
|
+
|
550
|
+
// Before prototype.init
|
551
|
+
if (angular) {
|
552
|
+
extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
|
553
|
+
isCircular = !isX;
|
554
|
+
if (isCircular) {
|
555
|
+
this.defaultRadialOptions = this.defaultRadialGaugeOptions;
|
556
|
+
}
|
502
557
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
};
|
508
|
-
}
|
558
|
+
} else if (polar) {
|
559
|
+
extend(this, radialAxisMixin);
|
560
|
+
isCircular = isX;
|
561
|
+
this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
|
509
562
|
|
510
|
-
};
|
511
|
-
|
512
|
-
/**
|
513
|
-
* Override axisProto.init to mix in special axis instance functions and function overrides
|
514
|
-
*/
|
515
|
-
wrap(axisProto, 'init', function (proceed, chart, userOptions) {
|
516
|
-
var axis = this,
|
517
|
-
angular = chart.angular,
|
518
|
-
polar = chart.polar,
|
519
|
-
isX = userOptions.isX,
|
520
|
-
isHidden = angular && isX,
|
521
|
-
isCircular,
|
522
|
-
options,
|
523
|
-
chartOptions = chart.options,
|
524
|
-
paneIndex = userOptions.pane || 0,
|
525
|
-
pane,
|
526
|
-
paneOptions;
|
527
|
-
|
528
|
-
// Before prototype.init
|
529
|
-
if (angular) {
|
530
|
-
extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
|
531
|
-
isCircular = !isX;
|
532
|
-
if (isCircular) {
|
533
|
-
this.defaultRadialOptions = this.defaultRadialGaugeOptions;
|
534
563
|
}
|
535
564
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
565
|
+
// Disable certain features on angular and polar axes
|
566
|
+
if (angular || polar) {
|
567
|
+
this.isRadial = true;
|
568
|
+
chart.inverted = false;
|
569
|
+
chartOptions.chart.zoomType = null;
|
570
|
+
} else {
|
571
|
+
this.isRadial = false;
|
572
|
+
}
|
541
573
|
|
542
|
-
|
574
|
+
// Run prototype.init
|
575
|
+
proceed.call(this, chart, userOptions);
|
543
576
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
577
|
+
if (!isHidden && (angular || polar)) {
|
578
|
+
options = this.options;
|
579
|
+
|
580
|
+
// Create the pane and set the pane options.
|
581
|
+
if (!chart.panes) {
|
582
|
+
chart.panes = [];
|
583
|
+
}
|
584
|
+
this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
|
585
|
+
splat(chartOptions.pane)[paneIndex],
|
586
|
+
chart,
|
587
|
+
axis
|
588
|
+
);
|
589
|
+
paneOptions = pane.options;
|
549
590
|
|
550
|
-
|
551
|
-
|
591
|
+
// Start and end angle options are
|
592
|
+
// given in degrees relative to top, while internal computations are
|
593
|
+
// in radians relative to right (like SVG).
|
594
|
+
this.angleRad = (options.angle || 0) * Math.PI / 180; // Y axis in polar charts
|
595
|
+
this.startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180; // Gauges
|
596
|
+
this.endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180; // Gauges
|
597
|
+
this.offset = options.offset || 0;
|
552
598
|
|
553
|
-
|
554
|
-
options = this.options;
|
599
|
+
this.isCircular = isCircular;
|
555
600
|
|
556
|
-
// Create the pane and set the pane options.
|
557
|
-
if (!chart.panes) {
|
558
|
-
chart.panes = [];
|
559
601
|
}
|
560
|
-
this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
|
561
|
-
splat(chartOptions.pane)[paneIndex],
|
562
|
-
chart,
|
563
|
-
axis
|
564
|
-
);
|
565
|
-
paneOptions = pane.options;
|
566
|
-
|
567
|
-
// Start and end angle options are
|
568
|
-
// given in degrees relative to top, while internal computations are
|
569
|
-
// in radians relative to right (like SVG).
|
570
|
-
this.angleRad = (options.angle || 0) * Math.PI / 180; // Y axis in polar charts
|
571
|
-
this.startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180; // Gauges
|
572
|
-
this.endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180; // Gauges
|
573
|
-
this.offset = options.offset || 0;
|
574
|
-
|
575
|
-
this.isCircular = isCircular;
|
576
602
|
|
577
|
-
}
|
603
|
+
});
|
604
|
+
|
605
|
+
/**
|
606
|
+
* Wrap auto label align to avoid setting axis-wide rotation on radial axes (#4920)
|
607
|
+
* @param {Function} proceed
|
608
|
+
* @returns {String} Alignment
|
609
|
+
*/
|
610
|
+
wrap(axisProto, 'autoLabelAlign', function(proceed) {
|
611
|
+
if (!this.isRadial) {
|
612
|
+
return proceed.apply(this, [].slice.call(arguments, 1));
|
613
|
+
} // else return undefined
|
614
|
+
});
|
578
615
|
|
579
|
-
|
616
|
+
/**
|
617
|
+
* Add special cases within the Tick class' methods for radial axes.
|
618
|
+
*/
|
619
|
+
wrap(tickProto, 'getPosition', function(proceed, horiz, pos, tickmarkOffset, old) {
|
620
|
+
var axis = this.axis;
|
580
621
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
*/
|
586
|
-
wrap(axisProto, 'autoLabelAlign', function (proceed) {
|
587
|
-
if (!this.isRadial) {
|
588
|
-
return proceed.apply(this, [].slice.call(arguments, 1));
|
589
|
-
} // else return undefined
|
590
|
-
});
|
591
|
-
|
592
|
-
/**
|
593
|
-
* Add special cases within the Tick class' methods for radial axes.
|
594
|
-
*/
|
595
|
-
wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
|
596
|
-
var axis = this.axis;
|
597
|
-
|
598
|
-
return axis.getPosition ?
|
599
|
-
axis.getPosition(pos) :
|
600
|
-
proceed.call(this, horiz, pos, tickmarkOffset, old);
|
601
|
-
});
|
602
|
-
|
603
|
-
/**
|
604
|
-
* Wrap the getLabelPosition function to find the center position of the label
|
605
|
-
* based on the distance option
|
606
|
-
*/
|
607
|
-
wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
|
608
|
-
var axis = this.axis,
|
609
|
-
optionsY = labelOptions.y,
|
610
|
-
ret,
|
611
|
-
centerSlot = 20, // 20 degrees to each side at the top and bottom
|
612
|
-
align = labelOptions.align,
|
613
|
-
angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
|
614
|
-
|
615
|
-
if (axis.isRadial) { // Both X and Y axes in a polar chart
|
616
|
-
ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
|
617
|
-
|
618
|
-
// Automatically rotated
|
619
|
-
if (labelOptions.rotation === 'auto') {
|
620
|
-
label.attr({
|
621
|
-
rotation: angle
|
622
|
-
});
|
622
|
+
return axis.getPosition ?
|
623
|
+
axis.getPosition(pos) :
|
624
|
+
proceed.call(this, horiz, pos, tickmarkOffset, old);
|
625
|
+
});
|
623
626
|
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
627
|
+
/**
|
628
|
+
* Wrap the getLabelPosition function to find the center position of the label
|
629
|
+
* based on the distance option
|
630
|
+
*/
|
631
|
+
wrap(tickProto, 'getLabelPosition', function(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
|
632
|
+
var axis = this.axis,
|
633
|
+
optionsY = labelOptions.y,
|
634
|
+
ret,
|
635
|
+
centerSlot = 20, // 20 degrees to each side at the top and bottom
|
636
|
+
align = labelOptions.align,
|
637
|
+
angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
|
638
|
+
|
639
|
+
if (axis.isRadial) { // Both X and Y axes in a polar chart
|
640
|
+
ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
|
641
|
+
|
642
|
+
// Automatically rotated
|
643
|
+
if (labelOptions.rotation === 'auto') {
|
644
|
+
label.attr({
|
645
|
+
rotation: angle
|
646
|
+
});
|
628
647
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
648
|
+
// Vertically centered
|
649
|
+
} else if (optionsY === null) {
|
650
|
+
optionsY = axis.chart.renderer.fontMetrics(label.styles.fontSize).b - label.getBBox().height / 2;
|
651
|
+
}
|
652
|
+
|
653
|
+
// Automatic alignment
|
654
|
+
if (align === null) {
|
655
|
+
if (axis.isCircular) { // Y axis
|
656
|
+
if (this.label.getBBox().width > axis.len * axis.tickInterval / (axis.max - axis.min)) { // #3506
|
657
|
+
centerSlot = 0;
|
658
|
+
}
|
659
|
+
if (angle > centerSlot && angle < 180 - centerSlot) {
|
660
|
+
align = 'left'; // right hemisphere
|
661
|
+
} else if (angle > 180 + centerSlot && angle < 360 - centerSlot) {
|
662
|
+
align = 'right'; // left hemisphere
|
663
|
+
} else {
|
664
|
+
align = 'center'; // top or bottom
|
665
|
+
}
|
639
666
|
} else {
|
640
|
-
align = 'center';
|
667
|
+
align = 'center';
|
641
668
|
}
|
642
|
-
|
643
|
-
|
669
|
+
label.attr({
|
670
|
+
align: align
|
671
|
+
});
|
644
672
|
}
|
645
|
-
label.attr({
|
646
|
-
align: align
|
647
|
-
});
|
648
|
-
}
|
649
673
|
|
650
|
-
|
651
|
-
|
674
|
+
ret.x += labelOptions.x;
|
675
|
+
ret.y += optionsY;
|
652
676
|
|
653
|
-
|
654
|
-
|
655
|
-
}
|
656
|
-
return ret;
|
657
|
-
});
|
658
|
-
|
659
|
-
/**
|
660
|
-
* Wrap the getMarkPath function to return the path of the radial marker
|
661
|
-
*/
|
662
|
-
wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
|
663
|
-
var axis = this.axis,
|
664
|
-
endPoint,
|
665
|
-
ret;
|
666
|
-
|
667
|
-
if (axis.isRadial) {
|
668
|
-
endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
|
669
|
-
ret = [
|
670
|
-
'M',
|
671
|
-
x,
|
672
|
-
y,
|
673
|
-
'L',
|
674
|
-
endPoint.x,
|
675
|
-
endPoint.y
|
676
|
-
];
|
677
|
-
} else {
|
678
|
-
ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
|
679
|
-
}
|
680
|
-
return ret;
|
681
|
-
});
|
682
|
-
/*
|
683
|
-
* The AreaRangeSeries class
|
684
|
-
*
|
685
|
-
*/
|
686
|
-
|
687
|
-
/**
|
688
|
-
* Extend the default options with map options
|
689
|
-
*/
|
690
|
-
defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
|
691
|
-
lineWidth: 1,
|
692
|
-
marker: null,
|
693
|
-
threshold: null,
|
694
|
-
tooltip: {
|
695
|
-
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
|
696
|
-
},
|
697
|
-
trackByArea: true,
|
698
|
-
dataLabels: {
|
699
|
-
align: null,
|
700
|
-
verticalAlign: null,
|
701
|
-
xLow: 0,
|
702
|
-
xHigh: 0,
|
703
|
-
yLow: 0,
|
704
|
-
yHigh: 0
|
705
|
-
},
|
706
|
-
states: {
|
707
|
-
hover: {
|
708
|
-
halo: false
|
677
|
+
} else {
|
678
|
+
ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
|
709
679
|
}
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
/**
|
714
|
-
* Add the series type
|
715
|
-
*/
|
716
|
-
seriesTypes.arearange = extendClass(seriesTypes.area, {
|
717
|
-
type: 'arearange',
|
718
|
-
pointArrayMap: ['low', 'high'],
|
719
|
-
dataLabelCollections: ['dataLabel', 'dataLabelUpper'],
|
720
|
-
toYData: function (point) {
|
721
|
-
return [point.low, point.high];
|
722
|
-
},
|
723
|
-
pointValKey: 'low',
|
724
|
-
deferTranslatePolar: true,
|
680
|
+
return ret;
|
681
|
+
});
|
725
682
|
|
726
683
|
/**
|
727
|
-
*
|
728
|
-
* true plotHigh coordinates. This is an addition of the toXY method found in
|
729
|
-
* Polar.js, because it runs too early for arearanges to be considered (#3419).
|
684
|
+
* Wrap the getMarkPath function to return the path of the radial marker
|
730
685
|
*/
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
point.plotHighX = xy.x - chart.plotLeft;
|
736
|
-
point.plotHigh = xy.y - chart.plotTop;
|
737
|
-
},
|
686
|
+
wrap(tickProto, 'getMarkPath', function(proceed, x, y, tickLength, tickWidth, horiz, renderer) {
|
687
|
+
var axis = this.axis,
|
688
|
+
endPoint,
|
689
|
+
ret;
|
738
690
|
|
691
|
+
if (axis.isRadial) {
|
692
|
+
endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
|
693
|
+
ret = [
|
694
|
+
'M',
|
695
|
+
x,
|
696
|
+
y,
|
697
|
+
'L',
|
698
|
+
endPoint.x,
|
699
|
+
endPoint.y
|
700
|
+
];
|
701
|
+
} else {
|
702
|
+
ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
|
703
|
+
}
|
704
|
+
return ret;
|
705
|
+
});
|
706
|
+
|
707
|
+
}(Highcharts));
|
708
|
+
(function(H) {
|
739
709
|
/**
|
740
|
-
*
|
710
|
+
* (c) 2010-2016 Torstein Honsi
|
711
|
+
*
|
712
|
+
* License: www.highcharts.com/license
|
741
713
|
*/
|
742
|
-
|
743
|
-
|
744
|
-
|
714
|
+
'use strict';
|
715
|
+
var each = H.each,
|
716
|
+
noop = H.noop,
|
717
|
+
pick = H.pick,
|
718
|
+
Series = H.Series,
|
719
|
+
seriesType = H.seriesType,
|
720
|
+
seriesTypes = H.seriesTypes;
|
721
|
+
/*
|
722
|
+
* The arearangeseries series type
|
723
|
+
*/
|
724
|
+
seriesType('arearange', 'area', {
|
745
725
|
|
746
|
-
|
726
|
+
lineWidth: 1,
|
747
727
|
|
748
|
-
|
749
|
-
|
728
|
+
marker: null,
|
729
|
+
threshold: null,
|
730
|
+
tooltip: {
|
750
731
|
|
751
|
-
|
752
|
-
high = point.high,
|
753
|
-
plotY = point.plotY;
|
732
|
+
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>' // eslint-disable-line no-dupe-keys
|
754
733
|
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
734
|
+
},
|
735
|
+
trackByArea: true,
|
736
|
+
dataLabels: {
|
737
|
+
align: null,
|
738
|
+
verticalAlign: null,
|
739
|
+
xLow: 0,
|
740
|
+
xHigh: 0,
|
741
|
+
yLow: 0,
|
742
|
+
yHigh: 0
|
743
|
+
},
|
744
|
+
states: {
|
745
|
+
hover: {
|
746
|
+
halo: false
|
760
747
|
}
|
761
|
-
}
|
748
|
+
}
|
749
|
+
|
750
|
+
// Prototype members
|
751
|
+
}, {
|
752
|
+
pointArrayMap: ['low', 'high'],
|
753
|
+
dataLabelCollections: ['dataLabel', 'dataLabelUpper'],
|
754
|
+
toYData: function(point) {
|
755
|
+
return [point.low, point.high];
|
756
|
+
},
|
757
|
+
pointValKey: 'low',
|
758
|
+
deferTranslatePolar: true,
|
759
|
+
|
760
|
+
/**
|
761
|
+
* Translate a point's plotHigh from the internal angle and radius measures to
|
762
|
+
* true plotHigh coordinates. This is an addition of the toXY method found in
|
763
|
+
* Polar.js, because it runs too early for arearanges to be considered (#3419).
|
764
|
+
*/
|
765
|
+
highToXY: function(point) {
|
766
|
+
// Find the polar plotX and plotY
|
767
|
+
var chart = this.chart,
|
768
|
+
xy = this.xAxis.postTranslate(point.rectPlotX, this.yAxis.len - point.plotHigh);
|
769
|
+
point.plotHighX = xy.x - chart.plotLeft;
|
770
|
+
point.plotHigh = xy.y - chart.plotTop;
|
771
|
+
},
|
772
|
+
|
773
|
+
/**
|
774
|
+
* Translate data points from raw values x and y to plotX and plotY
|
775
|
+
*/
|
776
|
+
translate: function() {
|
777
|
+
var series = this,
|
778
|
+
yAxis = series.yAxis;
|
779
|
+
|
780
|
+
seriesTypes.area.prototype.translate.apply(series);
|
781
|
+
|
782
|
+
// Set plotLow and plotHigh
|
783
|
+
each(series.points, function(point) {
|
784
|
+
|
785
|
+
var low = point.low,
|
786
|
+
high = point.high,
|
787
|
+
plotY = point.plotY;
|
788
|
+
|
789
|
+
if (high === null || low === null) {
|
790
|
+
point.isNull = true;
|
791
|
+
} else {
|
792
|
+
point.plotLow = plotY;
|
793
|
+
point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
|
794
|
+
}
|
795
|
+
});
|
796
|
+
|
797
|
+
// Postprocess plotHigh
|
798
|
+
if (this.chart.polar) {
|
799
|
+
each(this.points, function(point) {
|
800
|
+
series.highToXY(point);
|
801
|
+
});
|
802
|
+
}
|
803
|
+
},
|
804
|
+
|
805
|
+
/**
|
806
|
+
* Extend the line series' getSegmentPath method by applying the segment
|
807
|
+
* path to both lower and higher values of the range
|
808
|
+
*/
|
809
|
+
getGraphPath: function(points) {
|
810
|
+
|
811
|
+
var highPoints = [],
|
812
|
+
highAreaPoints = [],
|
813
|
+
i,
|
814
|
+
getGraphPath = seriesTypes.area.prototype.getGraphPath,
|
815
|
+
point,
|
816
|
+
pointShim,
|
817
|
+
linePath,
|
818
|
+
lowerPath,
|
819
|
+
options = this.options,
|
820
|
+
step = options.step,
|
821
|
+
higherPath,
|
822
|
+
higherAreaPath;
|
823
|
+
|
824
|
+
points = points || this.points;
|
825
|
+
i = points.length;
|
826
|
+
|
827
|
+
// Create the top line and the top part of the area fill. The area fill compensates for
|
828
|
+
// null points by drawing down to the lower graph, moving across the null gap and
|
829
|
+
// starting again at the lower graph.
|
830
|
+
i = points.length;
|
831
|
+
while (i--) {
|
832
|
+
point = points[i];
|
762
833
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
834
|
+
if (!point.isNull && !options.connectEnds && (!points[i + 1] || points[i + 1].isNull)) {
|
835
|
+
highAreaPoints.push({
|
836
|
+
plotX: point.plotX,
|
837
|
+
plotY: point.plotY,
|
838
|
+
doCurve: false // #5186, gaps in areasplinerange fill
|
839
|
+
});
|
840
|
+
}
|
770
841
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
higherAreaPath;
|
789
|
-
|
790
|
-
points = points || this.points;
|
791
|
-
i = points.length;
|
792
|
-
|
793
|
-
// Create the top line and the top part of the area fill. The area fill compensates for
|
794
|
-
// null points by drawing down to the lower graph, moving across the null gap and
|
795
|
-
// starting again at the lower graph.
|
796
|
-
i = points.length;
|
797
|
-
while (i--) {
|
798
|
-
point = points[i];
|
799
|
-
|
800
|
-
if (!point.isNull && !options.connectEnds && (!points[i + 1] || points[i + 1].isNull)) {
|
801
|
-
highAreaPoints.push({
|
802
|
-
plotX: point.plotX,
|
803
|
-
plotY: point.plotY,
|
804
|
-
doCurve: false // #5186, gaps in areasplinerange fill
|
805
|
-
});
|
806
|
-
}
|
807
|
-
|
808
|
-
pointShim = {
|
809
|
-
polarPlotY: point.polarPlotY,
|
810
|
-
rectPlotX: point.rectPlotX,
|
811
|
-
yBottom: point.yBottom,
|
812
|
-
plotX: pick(point.plotHighX, point.plotX), // plotHighX is for polar charts
|
813
|
-
plotY: point.plotHigh,
|
814
|
-
isNull: point.isNull
|
815
|
-
};
|
816
|
-
highAreaPoints.push(pointShim);
|
817
|
-
highPoints.push(pointShim);
|
818
|
-
if (!point.isNull && !options.connectEnds && (!points[i - 1] || points[i - 1].isNull)) {
|
819
|
-
highAreaPoints.push({
|
820
|
-
plotX: point.plotX,
|
821
|
-
plotY: point.plotY,
|
822
|
-
doCurve: false // #5186, gaps in areasplinerange fill
|
823
|
-
});
|
842
|
+
pointShim = {
|
843
|
+
polarPlotY: point.polarPlotY,
|
844
|
+
rectPlotX: point.rectPlotX,
|
845
|
+
yBottom: point.yBottom,
|
846
|
+
plotX: pick(point.plotHighX, point.plotX), // plotHighX is for polar charts
|
847
|
+
plotY: point.plotHigh,
|
848
|
+
isNull: point.isNull
|
849
|
+
};
|
850
|
+
highAreaPoints.push(pointShim);
|
851
|
+
highPoints.push(pointShim);
|
852
|
+
if (!point.isNull && !options.connectEnds && (!points[i - 1] || points[i - 1].isNull)) {
|
853
|
+
highAreaPoints.push({
|
854
|
+
plotX: point.plotX,
|
855
|
+
plotY: point.plotY,
|
856
|
+
doCurve: false // #5186, gaps in areasplinerange fill
|
857
|
+
});
|
858
|
+
}
|
824
859
|
}
|
825
|
-
}
|
826
860
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
861
|
+
// Get the paths
|
862
|
+
lowerPath = getGraphPath.call(this, points);
|
863
|
+
if (step) {
|
864
|
+
if (step === true) {
|
865
|
+
step = 'left';
|
866
|
+
}
|
867
|
+
options.step = {
|
868
|
+
left: 'right',
|
869
|
+
center: 'center',
|
870
|
+
right: 'left'
|
871
|
+
}[step]; // swap for reading in getGraphPath
|
832
872
|
}
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
higherAreaPath = getGraphPath.call(this, highAreaPoints);
|
837
|
-
options.step = step;
|
873
|
+
higherPath = getGraphPath.call(this, highPoints);
|
874
|
+
higherAreaPath = getGraphPath.call(this, highAreaPoints);
|
875
|
+
options.step = step;
|
838
876
|
|
839
|
-
|
840
|
-
|
877
|
+
// Create a line on both top and bottom of the range
|
878
|
+
linePath = [].concat(lowerPath, higherPath);
|
841
879
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
880
|
+
// For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
|
881
|
+
if (!this.chart.polar && higherAreaPath[0] === 'M') {
|
882
|
+
higherAreaPath[0] = 'L'; // this probably doesn't work for spline
|
883
|
+
}
|
846
884
|
|
847
|
-
|
848
|
-
|
885
|
+
this.graphPath = linePath;
|
886
|
+
this.areaPath = this.areaPath.concat(lowerPath, higherAreaPath);
|
849
887
|
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
888
|
+
// Prepare for sideways animation
|
889
|
+
linePath.isArea = true;
|
890
|
+
linePath.xMap = lowerPath.xMap;
|
891
|
+
this.areaPath.xMap = lowerPath.xMap;
|
854
892
|
|
855
|
-
|
856
|
-
|
893
|
+
return linePath;
|
894
|
+
},
|
857
895
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
896
|
+
/**
|
897
|
+
* Extend the basic drawDataLabels method by running it for both lower and higher
|
898
|
+
* values.
|
899
|
+
*/
|
900
|
+
drawDataLabels: function() {
|
901
|
+
|
902
|
+
var data = this.data,
|
903
|
+
length = data.length,
|
904
|
+
i,
|
905
|
+
originalDataLabels = [],
|
906
|
+
seriesProto = Series.prototype,
|
907
|
+
dataLabelOptions = this.options.dataLabels,
|
908
|
+
align = dataLabelOptions.align,
|
909
|
+
verticalAlign = dataLabelOptions.verticalAlign,
|
910
|
+
inside = dataLabelOptions.inside,
|
911
|
+
point,
|
912
|
+
up,
|
913
|
+
inverted = this.chart.inverted;
|
863
914
|
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
originalDataLabels[i] = point.dataLabel;
|
894
|
-
point.dataLabel = point.dataLabelUpper;
|
895
|
-
|
896
|
-
// Set the default offset
|
897
|
-
point.below = up;
|
898
|
-
if (inverted) {
|
899
|
-
if (!align) {
|
900
|
-
dataLabelOptions.align = up ? 'right' : 'left';
|
901
|
-
}
|
902
|
-
} else {
|
903
|
-
if (!verticalAlign) {
|
904
|
-
dataLabelOptions.verticalAlign = up ? 'top' : 'bottom';
|
915
|
+
if (dataLabelOptions.enabled || this._hasPointLabels) {
|
916
|
+
|
917
|
+
// Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
|
918
|
+
i = length;
|
919
|
+
while (i--) {
|
920
|
+
point = data[i];
|
921
|
+
if (point) {
|
922
|
+
up = inside ? point.plotHigh < point.plotLow : point.plotHigh > point.plotLow;
|
923
|
+
|
924
|
+
// Set preliminary values
|
925
|
+
point.y = point.high;
|
926
|
+
point._plotY = point.plotY;
|
927
|
+
point.plotY = point.plotHigh;
|
928
|
+
|
929
|
+
// Store original data labels and set preliminary label objects to be picked up
|
930
|
+
// in the uber method
|
931
|
+
originalDataLabels[i] = point.dataLabel;
|
932
|
+
point.dataLabel = point.dataLabelUpper;
|
933
|
+
|
934
|
+
// Set the default offset
|
935
|
+
point.below = up;
|
936
|
+
if (inverted) {
|
937
|
+
if (!align) {
|
938
|
+
dataLabelOptions.align = up ? 'right' : 'left';
|
939
|
+
}
|
940
|
+
} else {
|
941
|
+
if (!verticalAlign) {
|
942
|
+
dataLabelOptions.verticalAlign = up ? 'top' : 'bottom';
|
943
|
+
}
|
905
944
|
}
|
945
|
+
|
946
|
+
dataLabelOptions.x = dataLabelOptions.xHigh;
|
947
|
+
dataLabelOptions.y = dataLabelOptions.yHigh;
|
906
948
|
}
|
949
|
+
}
|
907
950
|
|
908
|
-
|
909
|
-
|
951
|
+
if (seriesProto.drawDataLabels) {
|
952
|
+
seriesProto.drawDataLabels.apply(this, arguments); // #1209
|
910
953
|
}
|
911
|
-
}
|
912
954
|
|
913
|
-
|
914
|
-
|
915
|
-
|
955
|
+
// Step 2: reorganize and handle data labels for the lower values
|
956
|
+
i = length;
|
957
|
+
while (i--) {
|
958
|
+
point = data[i];
|
959
|
+
if (point) {
|
960
|
+
up = inside ? point.plotHigh < point.plotLow : point.plotHigh > point.plotLow;
|
961
|
+
|
962
|
+
// Move the generated labels from step 1, and reassign the original data labels
|
963
|
+
point.dataLabelUpper = point.dataLabel;
|
964
|
+
point.dataLabel = originalDataLabels[i];
|
965
|
+
|
966
|
+
// Reset values
|
967
|
+
point.y = point.low;
|
968
|
+
point.plotY = point._plotY;
|
969
|
+
|
970
|
+
// Set the default offset
|
971
|
+
point.below = !up;
|
972
|
+
if (inverted) {
|
973
|
+
if (!align) {
|
974
|
+
dataLabelOptions.align = up ? 'left' : 'right';
|
975
|
+
}
|
976
|
+
} else {
|
977
|
+
if (!verticalAlign) {
|
978
|
+
dataLabelOptions.verticalAlign = up ? 'bottom' : 'top';
|
979
|
+
}
|
916
980
|
|
917
|
-
// Step 2: reorganize and handle data labels for the lower values
|
918
|
-
i = length;
|
919
|
-
while (i--) {
|
920
|
-
point = data[i];
|
921
|
-
if (point) {
|
922
|
-
up = inside ? point.plotHigh < point.plotLow : point.plotHigh > point.plotLow;
|
923
|
-
|
924
|
-
// Move the generated labels from step 1, and reassign the original data labels
|
925
|
-
point.dataLabelUpper = point.dataLabel;
|
926
|
-
point.dataLabel = originalDataLabels[i];
|
927
|
-
|
928
|
-
// Reset values
|
929
|
-
point.y = point.low;
|
930
|
-
point.plotY = point._plotY;
|
931
|
-
|
932
|
-
// Set the default offset
|
933
|
-
point.below = !up;
|
934
|
-
if (inverted) {
|
935
|
-
if (!align) {
|
936
|
-
dataLabelOptions.align = up ? 'left' : 'right';
|
937
981
|
}
|
938
|
-
} else {
|
939
|
-
if (!verticalAlign) {
|
940
|
-
dataLabelOptions.verticalAlign = up ? 'bottom' : 'top';
|
941
|
-
}
|
942
|
-
|
943
|
-
}
|
944
982
|
|
945
|
-
|
946
|
-
|
983
|
+
dataLabelOptions.x = dataLabelOptions.xLow;
|
984
|
+
dataLabelOptions.y = dataLabelOptions.yLow;
|
985
|
+
}
|
986
|
+
}
|
987
|
+
if (seriesProto.drawDataLabels) {
|
988
|
+
seriesProto.drawDataLabels.apply(this, arguments);
|
947
989
|
}
|
948
990
|
}
|
949
|
-
if (seriesProto.drawDataLabels) {
|
950
|
-
seriesProto.drawDataLabels.apply(this, arguments);
|
951
|
-
}
|
952
|
-
}
|
953
|
-
|
954
|
-
dataLabelOptions.align = align;
|
955
|
-
dataLabelOptions.verticalAlign = verticalAlign;
|
956
|
-
},
|
957
991
|
|
958
|
-
|
959
|
-
|
960
|
-
|
992
|
+
dataLabelOptions.align = align;
|
993
|
+
dataLabelOptions.verticalAlign = verticalAlign;
|
994
|
+
},
|
961
995
|
|
962
|
-
|
996
|
+
alignDataLabel: function() {
|
997
|
+
seriesTypes.column.prototype.alignDataLabel.apply(this, arguments);
|
998
|
+
},
|
963
999
|
|
964
|
-
|
1000
|
+
setStackedPoints: noop,
|
965
1001
|
|
966
|
-
|
967
|
-
});
|
968
|
-
/**
|
969
|
-
* The AreaSplineRangeSeries class
|
970
|
-
*/
|
1002
|
+
getSymbol: noop,
|
971
1003
|
|
972
|
-
|
1004
|
+
drawPoints: noop
|
1005
|
+
});
|
973
1006
|
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
1007
|
+
}(Highcharts));
|
1008
|
+
(function(H) {
|
1009
|
+
/**
|
1010
|
+
* (c) 2010-2016 Torstein Honsi
|
1011
|
+
*
|
1012
|
+
* License: www.highcharts.com/license
|
1013
|
+
*/
|
1014
|
+
'use strict';
|
1015
|
+
var seriesType = H.seriesType,
|
1016
|
+
seriesTypes = H.seriesTypes;
|
1017
|
+
/**
|
1018
|
+
* The areasplinerange series type
|
1019
|
+
*/
|
1020
|
+
seriesType('areasplinerange', 'arearange', null, {
|
1021
|
+
getPointSpline: seriesTypes.spline.prototype.getPointSpline
|
1022
|
+
});
|
981
1023
|
|
982
|
-
(
|
1024
|
+
}(Highcharts));
|
1025
|
+
(function(H) {
|
1026
|
+
/**
|
1027
|
+
* (c) 2010-2016 Torstein Honsi
|
1028
|
+
*
|
1029
|
+
* License: www.highcharts.com/license
|
1030
|
+
*/
|
1031
|
+
'use strict';
|
1032
|
+
var defaultPlotOptions = H.defaultPlotOptions,
|
1033
|
+
each = H.each,
|
1034
|
+
merge = H.merge,
|
1035
|
+
noop = H.noop,
|
1036
|
+
pick = H.pick,
|
1037
|
+
seriesType = H.seriesType,
|
1038
|
+
seriesTypes = H.seriesTypes;
|
983
1039
|
|
984
1040
|
var colProto = seriesTypes.column.prototype;
|
985
1041
|
|
986
1042
|
/**
|
987
1043
|
* The ColumnRangeSeries class
|
988
1044
|
*/
|
989
|
-
|
1045
|
+
seriesType('columnrange', 'arearange', merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
|
990
1046
|
lineWidth: 1,
|
991
1047
|
pointRange: null
|
992
|
-
});
|
993
1048
|
|
994
|
-
|
995
|
-
|
996
|
-
*/
|
997
|
-
seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
|
998
|
-
type: 'columnrange',
|
1049
|
+
// Prototype members
|
1050
|
+
}), {
|
999
1051
|
/**
|
1000
1052
|
* Translate data points from raw values x and y to plotX and plotY
|
1001
1053
|
*/
|
1002
|
-
translate: function
|
1054
|
+
translate: function() {
|
1003
1055
|
var series = this,
|
1004
1056
|
yAxis = series.yAxis,
|
1005
1057
|
xAxis = series.xAxis,
|
@@ -1012,7 +1064,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
1012
1064
|
colProto.translate.apply(series);
|
1013
1065
|
|
1014
1066
|
// Set plotLow and plotHigh
|
1015
|
-
each(series.points, function
|
1067
|
+
each(series.points, function(point) {
|
1016
1068
|
var shapeArgs = point.shapeArgs,
|
1017
1069
|
minPointLength = series.options.minPointLength,
|
1018
1070
|
heightDifference,
|
@@ -1032,7 +1084,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
1032
1084
|
height += heightDifference;
|
1033
1085
|
y -= heightDifference / 2;
|
1034
1086
|
|
1035
|
-
|
1087
|
+
// Adjust for negative ranges or reversed Y axis (#1457)
|
1036
1088
|
} else if (height < 0) {
|
1037
1089
|
height *= -1;
|
1038
1090
|
y -= height;
|
@@ -1049,16 +1101,15 @@ var arrayMin = Highcharts.arrayMin,
|
|
1049
1101
|
shapeArgs.height = height;
|
1050
1102
|
shapeArgs.y = y;
|
1051
1103
|
|
1052
|
-
point.tooltipPos = chart.inverted ?
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
]; // don't inherit from column tooltip position - #3372
|
1104
|
+
point.tooltipPos = chart.inverted ? [
|
1105
|
+
yAxis.len + yAxis.pos - chart.plotLeft - y - height / 2,
|
1106
|
+
xAxis.len + xAxis.pos - chart.plotTop - shapeArgs.x - shapeArgs.width / 2,
|
1107
|
+
height
|
1108
|
+
] : [
|
1109
|
+
xAxis.left - chart.plotLeft + shapeArgs.x + shapeArgs.width / 2,
|
1110
|
+
yAxis.pos - chart.plotTop + y + height / 2,
|
1111
|
+
height
|
1112
|
+
]; // don't inherit from column tooltip position - #3372
|
1062
1113
|
}
|
1063
1114
|
});
|
1064
1115
|
},
|
@@ -1066,1250 +1117,1368 @@ var arrayMin = Highcharts.arrayMin,
|
|
1066
1117
|
trackerGroups: ['group', 'dataLabelsGroup'],
|
1067
1118
|
drawGraph: noop,
|
1068
1119
|
crispCol: colProto.crispCol,
|
1069
|
-
pointAttrToOptions: colProto.pointAttrToOptions,
|
1070
1120
|
drawPoints: colProto.drawPoints,
|
1071
1121
|
drawTracker: colProto.drawTracker,
|
1072
1122
|
getColumnMetrics: colProto.getColumnMetrics,
|
1073
|
-
animate: function
|
1123
|
+
animate: function() {
|
1074
1124
|
return colProto.animate.apply(this, arguments);
|
1075
1125
|
},
|
1076
|
-
polarArc: function
|
1126
|
+
polarArc: function() {
|
1077
1127
|
return colProto.polarArc.apply(this, arguments);
|
1078
|
-
}
|
1128
|
+
},
|
1129
|
+
pointAttribs: colProto.pointAttribs
|
1079
1130
|
});
|
1080
|
-
}());
|
1081
|
-
|
1082
|
-
/*
|
1083
|
-
* The GaugeSeries class
|
1084
|
-
*/
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
/**
|
1089
|
-
* Extend the default options
|
1090
|
-
*/
|
1091
|
-
defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
|
1092
|
-
dataLabels: {
|
1093
|
-
enabled: true,
|
1094
|
-
defer: false,
|
1095
|
-
y: 15,
|
1096
|
-
borderWidth: 1,
|
1097
|
-
borderColor: 'silver',
|
1098
|
-
borderRadius: 3,
|
1099
|
-
crop: false,
|
1100
|
-
verticalAlign: 'top',
|
1101
|
-
zIndex: 2
|
1102
|
-
},
|
1103
|
-
dial: {
|
1104
|
-
// radius: '80%',
|
1105
|
-
// backgroundColor: 'black',
|
1106
|
-
// borderColor: 'silver',
|
1107
|
-
// borderWidth: 0,
|
1108
|
-
// baseWidth: 3,
|
1109
|
-
// topWidth: 1,
|
1110
|
-
// baseLength: '70%' // of radius
|
1111
|
-
// rearLength: '10%'
|
1112
|
-
},
|
1113
|
-
pivot: {
|
1114
|
-
//radius: 5,
|
1115
|
-
//borderWidth: 0
|
1116
|
-
//borderColor: 'silver',
|
1117
|
-
//backgroundColor: 'black'
|
1118
|
-
},
|
1119
|
-
tooltip: {
|
1120
|
-
headerFormat: ''
|
1121
|
-
},
|
1122
|
-
showInLegend: false
|
1123
|
-
});
|
1124
|
-
|
1125
|
-
/**
|
1126
|
-
* Extend the point object
|
1127
|
-
*/
|
1128
|
-
var GaugePoint = extendClass(Point, {
|
1129
|
-
/**
|
1130
|
-
* Don't do any hover colors or anything
|
1131
|
-
*/
|
1132
|
-
setState: function (state) {
|
1133
|
-
this.state = state;
|
1134
|
-
}
|
1135
|
-
});
|
1136
|
-
|
1137
|
-
|
1138
|
-
/**
|
1139
|
-
* Add the series type
|
1140
|
-
*/
|
1141
|
-
var GaugeSeries = {
|
1142
|
-
type: 'gauge',
|
1143
|
-
pointClass: GaugePoint,
|
1144
|
-
|
1145
|
-
// chart.angular will be set to true when a gauge series is present, and this will
|
1146
|
-
// be used on the axes
|
1147
|
-
angular: true,
|
1148
|
-
directTouch: true, // #5063
|
1149
|
-
drawGraph: noop,
|
1150
|
-
fixedBox: true,
|
1151
|
-
forceDL: true,
|
1152
|
-
noSharedTooltip: true,
|
1153
|
-
trackerGroups: ['group', 'dataLabelsGroup'],
|
1154
1131
|
|
1132
|
+
}(Highcharts));
|
1133
|
+
(function(H) {
|
1155
1134
|
/**
|
1156
|
-
*
|
1135
|
+
* (c) 2010-2016 Torstein Honsi
|
1136
|
+
*
|
1137
|
+
* License: www.highcharts.com/license
|
1138
|
+
*/
|
1139
|
+
'use strict';
|
1140
|
+
var each = H.each,
|
1141
|
+
isNumber = H.isNumber,
|
1142
|
+
merge = H.merge,
|
1143
|
+
noop = H.noop,
|
1144
|
+
pick = H.pick,
|
1145
|
+
pInt = H.pInt,
|
1146
|
+
Series = H.Series,
|
1147
|
+
seriesType = H.seriesType,
|
1148
|
+
TrackerMixin = H.TrackerMixin;
|
1149
|
+
/*
|
1150
|
+
* The GaugeSeries class
|
1157
1151
|
*/
|
1158
|
-
|
1152
|
+
seriesType('gauge', 'line', {
|
1153
|
+
dataLabels: {
|
1154
|
+
enabled: true,
|
1155
|
+
defer: false,
|
1156
|
+
y: 15,
|
1157
|
+
borderRadius: 3,
|
1158
|
+
crop: false,
|
1159
|
+
verticalAlign: 'top',
|
1160
|
+
zIndex: 2,
|
1161
|
+
|
1162
|
+
// Presentational
|
1163
|
+
borderWidth: 1,
|
1164
|
+
borderColor: '#cccccc'
|
1159
1165
|
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
each(series.points, function (point) {
|
1168
|
-
|
1169
|
-
var dialOptions = merge(options.dial, point.dial),
|
1170
|
-
radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
|
1171
|
-
baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
|
1172
|
-
rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
|
1173
|
-
baseWidth = dialOptions.baseWidth || 3,
|
1174
|
-
topWidth = dialOptions.topWidth || 1,
|
1175
|
-
overshoot = options.overshoot,
|
1176
|
-
rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
|
1177
|
-
|
1178
|
-
// Handle the wrap and overshoot options
|
1179
|
-
if (isNumber(overshoot)) {
|
1180
|
-
overshoot = overshoot / 180 * Math.PI;
|
1181
|
-
rotation = Math.max(yAxis.startAngleRad - overshoot, Math.min(yAxis.endAngleRad + overshoot, rotation));
|
1182
|
-
|
1183
|
-
} else if (options.wrap === false) {
|
1184
|
-
rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
|
1185
|
-
}
|
1166
|
+
},
|
1167
|
+
dial: {
|
1168
|
+
// radius: '80%',
|
1169
|
+
// baseWidth: 3,
|
1170
|
+
// topWidth: 1,
|
1171
|
+
// baseLength: '70%' // of radius
|
1172
|
+
// rearLength: '10%'
|
1186
1173
|
|
1187
|
-
|
1174
|
+
// backgroundColor: '#000000',
|
1175
|
+
// borderColor: '#cccccc',
|
1176
|
+
// borderWidth: 0
|
1188
1177
|
|
1189
|
-
point.shapeType = 'path';
|
1190
|
-
point.shapeArgs = {
|
1191
|
-
d: dialOptions.path || [
|
1192
|
-
'M',
|
1193
|
-
-rearLength, -baseWidth / 2,
|
1194
|
-
'L',
|
1195
|
-
baseLength, -baseWidth / 2,
|
1196
|
-
radius, -topWidth / 2,
|
1197
|
-
radius, topWidth / 2,
|
1198
|
-
baseLength, baseWidth / 2,
|
1199
|
-
-rearLength, baseWidth / 2,
|
1200
|
-
'z'
|
1201
|
-
],
|
1202
|
-
translateX: center[0],
|
1203
|
-
translateY: center[1],
|
1204
|
-
rotation: rotation
|
1205
|
-
};
|
1206
1178
|
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
});
|
1211
|
-
},
|
1179
|
+
},
|
1180
|
+
pivot: {
|
1181
|
+
//radius: 5,
|
1212
1182
|
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
drawPoints: function () {
|
1183
|
+
//borderWidth: 0
|
1184
|
+
//borderColor: '#cccccc',
|
1185
|
+
//backgroundColor: '#000000'
|
1217
1186
|
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1187
|
+
},
|
1188
|
+
tooltip: {
|
1189
|
+
headerFormat: ''
|
1190
|
+
},
|
1191
|
+
showInLegend: false
|
1192
|
+
|
1193
|
+
// Prototype members
|
1194
|
+
}, {
|
1195
|
+
// chart.angular will be set to true when a gauge series is present, and this will
|
1196
|
+
// be used on the axes
|
1197
|
+
angular: true,
|
1198
|
+
directTouch: true, // #5063
|
1199
|
+
drawGraph: noop,
|
1200
|
+
fixedBox: true,
|
1201
|
+
forceDL: true,
|
1202
|
+
noSharedTooltip: true,
|
1203
|
+
trackerGroups: ['group', 'dataLabelsGroup'],
|
1204
|
+
|
1205
|
+
/**
|
1206
|
+
* Calculate paths etc
|
1207
|
+
*/
|
1208
|
+
translate: function() {
|
1209
|
+
|
1210
|
+
var series = this,
|
1211
|
+
yAxis = series.yAxis,
|
1212
|
+
options = series.options,
|
1213
|
+
center = yAxis.center;
|
1214
|
+
|
1215
|
+
series.generatePoints();
|
1216
|
+
|
1217
|
+
each(series.points, function(point) {
|
1218
|
+
|
1219
|
+
var dialOptions = merge(options.dial, point.dial),
|
1220
|
+
radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
|
1221
|
+
baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
|
1222
|
+
rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
|
1223
|
+
baseWidth = dialOptions.baseWidth || 3,
|
1224
|
+
topWidth = dialOptions.topWidth || 1,
|
1225
|
+
overshoot = options.overshoot,
|
1226
|
+
rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
|
1227
|
+
|
1228
|
+
// Handle the wrap and overshoot options
|
1229
|
+
if (isNumber(overshoot)) {
|
1230
|
+
overshoot = overshoot / 180 * Math.PI;
|
1231
|
+
rotation = Math.max(yAxis.startAngleRad - overshoot, Math.min(yAxis.endAngleRad + overshoot, rotation));
|
1232
|
+
|
1233
|
+
} else if (options.wrap === false) {
|
1234
|
+
rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
|
1235
|
+
}
|
1236
|
+
|
1237
|
+
rotation = rotation * 180 / Math.PI;
|
1238
|
+
|
1239
|
+
point.shapeType = 'path';
|
1240
|
+
point.shapeArgs = {
|
1241
|
+
d: dialOptions.path || [
|
1242
|
+
'M', -rearLength, -baseWidth / 2,
|
1243
|
+
'L',
|
1244
|
+
baseLength, -baseWidth / 2,
|
1245
|
+
radius, -topWidth / 2,
|
1246
|
+
radius, topWidth / 2,
|
1247
|
+
baseLength, baseWidth / 2, -rearLength, baseWidth / 2,
|
1248
|
+
'z'
|
1249
|
+
],
|
1250
|
+
translateX: center[0],
|
1251
|
+
translateY: center[1],
|
1252
|
+
rotation: rotation
|
1253
|
+
};
|
1254
|
+
|
1255
|
+
// Positions for data label
|
1256
|
+
point.plotX = center[0];
|
1257
|
+
point.plotY = center[1];
|
1258
|
+
});
|
1259
|
+
},
|
1260
|
+
|
1261
|
+
/**
|
1262
|
+
* Draw the points where each point is one needle
|
1263
|
+
*/
|
1264
|
+
drawPoints: function() {
|
1265
|
+
|
1266
|
+
var series = this,
|
1267
|
+
center = series.yAxis.center,
|
1268
|
+
pivot = series.pivot,
|
1269
|
+
options = series.options,
|
1270
|
+
pivotOptions = options.pivot,
|
1271
|
+
renderer = series.chart.renderer;
|
1272
|
+
|
1273
|
+
each(series.points, function(point) {
|
1274
|
+
|
1275
|
+
var graphic = point.graphic,
|
1276
|
+
shapeArgs = point.shapeArgs,
|
1277
|
+
d = shapeArgs.d,
|
1278
|
+
dialOptions = merge(options.dial, point.dial); // #1233
|
1279
|
+
|
1280
|
+
if (graphic) {
|
1281
|
+
graphic.animate(shapeArgs);
|
1282
|
+
shapeArgs.d = d; // animate alters it
|
1283
|
+
} else {
|
1284
|
+
point.graphic = renderer[point.shapeType](shapeArgs)
|
1285
|
+
.attr({
|
1286
|
+
rotation: shapeArgs.rotation, // required by VML when animation is false
|
1287
|
+
zIndex: 1
|
1288
|
+
})
|
1289
|
+
.addClass('highcharts-dial')
|
1290
|
+
.add(series.group);
|
1291
|
+
|
1292
|
+
|
1293
|
+
// Presentational attributes
|
1294
|
+
point.graphic.attr({
|
1238
1295
|
stroke: dialOptions.borderColor || 'none',
|
1239
1296
|
'stroke-width': dialOptions.borderWidth || 0,
|
1240
|
-
fill: dialOptions.backgroundColor || '
|
1241
|
-
|
1242
|
-
|
1297
|
+
fill: dialOptions.backgroundColor || '#000000'
|
1298
|
+
});
|
1299
|
+
|
1300
|
+
}
|
1301
|
+
});
|
1302
|
+
|
1303
|
+
// Add or move the pivot
|
1304
|
+
if (pivot) {
|
1305
|
+
pivot.animate({ // #1235
|
1306
|
+
translateX: center[0],
|
1307
|
+
translateY: center[1]
|
1308
|
+
});
|
1309
|
+
} else {
|
1310
|
+
series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
|
1311
|
+
.attr({
|
1312
|
+
zIndex: 2
|
1243
1313
|
})
|
1314
|
+
.addClass('highcharts-pivot')
|
1315
|
+
.translate(center[0], center[1])
|
1244
1316
|
.add(series.group);
|
1245
|
-
}
|
1246
|
-
});
|
1247
1317
|
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
translateX: center[0],
|
1252
|
-
translateY: center[1]
|
1253
|
-
});
|
1254
|
-
} else {
|
1255
|
-
series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
|
1256
|
-
.attr({
|
1318
|
+
|
1319
|
+
// Presentational attributes
|
1320
|
+
series.pivot.attr({
|
1257
1321
|
'stroke-width': pivotOptions.borderWidth || 0,
|
1258
|
-
stroke: pivotOptions.borderColor || '
|
1259
|
-
fill: pivotOptions.backgroundColor || '
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1322
|
+
stroke: pivotOptions.borderColor || '#cccccc',
|
1323
|
+
fill: pivotOptions.backgroundColor || '#000000'
|
1324
|
+
});
|
1325
|
+
|
1326
|
+
}
|
1327
|
+
},
|
1328
|
+
|
1329
|
+
/**
|
1330
|
+
* Animate the arrow up from startAngle
|
1331
|
+
*/
|
1332
|
+
animate: function(init) {
|
1333
|
+
var series = this;
|
1334
|
+
|
1335
|
+
if (!init) {
|
1336
|
+
each(series.points, function(point) {
|
1337
|
+
var graphic = point.graphic;
|
1338
|
+
|
1339
|
+
if (graphic) {
|
1340
|
+
// start value
|
1341
|
+
graphic.attr({
|
1342
|
+
rotation: series.yAxis.startAngleRad * 180 / Math.PI
|
1343
|
+
});
|
1344
|
+
|
1345
|
+
// animate
|
1346
|
+
graphic.animate({
|
1347
|
+
rotation: point.shapeArgs.rotation
|
1348
|
+
}, series.options.animation);
|
1349
|
+
}
|
1350
|
+
});
|
1351
|
+
|
1352
|
+
// delete this function to allow it only once
|
1353
|
+
series.animate = null;
|
1354
|
+
}
|
1355
|
+
},
|
1356
|
+
|
1357
|
+
render: function() {
|
1358
|
+
this.group = this.plotGroup(
|
1359
|
+
'group',
|
1360
|
+
'series',
|
1361
|
+
this.visible ? 'visible' : 'hidden',
|
1362
|
+
this.options.zIndex,
|
1363
|
+
this.chart.seriesGroup
|
1364
|
+
);
|
1365
|
+
Series.prototype.render.call(this);
|
1366
|
+
this.group.clip(this.chart.clipRect);
|
1367
|
+
},
|
1368
|
+
|
1369
|
+
/**
|
1370
|
+
* Extend the basic setData method by running processData and generatePoints immediately,
|
1371
|
+
* in order to access the points from the legend.
|
1372
|
+
*/
|
1373
|
+
setData: function(data, redraw) {
|
1374
|
+
Series.prototype.setData.call(this, data, false);
|
1375
|
+
this.processData();
|
1376
|
+
this.generatePoints();
|
1377
|
+
if (pick(redraw, true)) {
|
1378
|
+
this.chart.redraw();
|
1379
|
+
}
|
1380
|
+
},
|
1381
|
+
|
1382
|
+
/**
|
1383
|
+
* If the tracking module is loaded, add the point tracker
|
1384
|
+
*/
|
1385
|
+
drawTracker: TrackerMixin && TrackerMixin.drawTrackerPoint
|
1386
|
+
|
1387
|
+
// Point members
|
1388
|
+
}, {
|
1389
|
+
/**
|
1390
|
+
* Don't do any hover colors or anything
|
1391
|
+
*/
|
1392
|
+
setState: function(state) {
|
1393
|
+
this.state = state;
|
1264
1394
|
}
|
1265
|
-
}
|
1395
|
+
});
|
1266
1396
|
|
1397
|
+
}(Highcharts));
|
1398
|
+
(function(H) {
|
1267
1399
|
/**
|
1268
|
-
*
|
1400
|
+
* (c) 2010-2016 Torstein Honsi
|
1401
|
+
*
|
1402
|
+
* License: www.highcharts.com/license
|
1269
1403
|
*/
|
1270
|
-
|
1271
|
-
|
1404
|
+
'use strict';
|
1405
|
+
var each = H.each,
|
1406
|
+
noop = H.noop,
|
1407
|
+
pick = H.pick,
|
1408
|
+
seriesType = H.seriesType,
|
1409
|
+
seriesTypes = H.seriesTypes;
|
1410
|
+
|
1411
|
+
/* ****************************************************************************
|
1412
|
+
* Start Box plot series code *
|
1413
|
+
*****************************************************************************/
|
1414
|
+
seriesType('boxplot', 'column', {
|
1415
|
+
threshold: null,
|
1416
|
+
tooltip: {
|
1417
|
+
|
1418
|
+
pointFormat: '<span style="color:{point.color}">\u25CF</span> <b> {series.name}</b><br/>' + // eslint-disable-line no-dupe-keys
|
1419
|
+
'Maximum: {point.high}<br/>' +
|
1420
|
+
'Upper quartile: {point.q3}<br/>' +
|
1421
|
+
'Median: {point.median}<br/>' +
|
1422
|
+
'Lower quartile: {point.q1}<br/>' +
|
1423
|
+
'Minimum: {point.low}<br/>'
|
1272
1424
|
|
1273
|
-
|
1274
|
-
|
1275
|
-
var graphic = point.graphic;
|
1425
|
+
},
|
1426
|
+
whiskerLength: '50%',
|
1276
1427
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1428
|
+
fillColor: '#ffffff',
|
1429
|
+
lineWidth: 1,
|
1430
|
+
//medianColor: null,
|
1431
|
+
medianWidth: 2,
|
1432
|
+
states: {
|
1433
|
+
hover: {
|
1434
|
+
brightness: -0.3
|
1435
|
+
}
|
1436
|
+
},
|
1437
|
+
//stemColor: null,
|
1438
|
+
//stemDashStyle: 'solid'
|
1439
|
+
//stemWidth: null,
|
1440
|
+
|
1441
|
+
//whiskerColor: null,
|
1442
|
+
whiskerWidth: 2
|
1443
|
+
|
1444
|
+
|
1445
|
+
// Prototype members
|
1446
|
+
}, {
|
1447
|
+
pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
|
1448
|
+
toYData: function(point) { // return a plain array for speedy calculation
|
1449
|
+
return [point.low, point.q1, point.median, point.q3, point.high];
|
1450
|
+
},
|
1451
|
+
pointValKey: 'high', // defines the top of the tracker
|
1452
|
+
|
1453
|
+
|
1454
|
+
/**
|
1455
|
+
* Get presentational attributes
|
1456
|
+
*/
|
1457
|
+
pointAttribs: function(point) {
|
1458
|
+
var options = this.options,
|
1459
|
+
color = (point && point.color) || this.color;
|
1460
|
+
|
1461
|
+
return {
|
1462
|
+
'fill': options.fillColor || color,
|
1463
|
+
'stroke': options.lineColor || color,
|
1464
|
+
'stroke-width': options.lineWidth || 0
|
1465
|
+
};
|
1466
|
+
},
|
1467
|
+
|
1468
|
+
|
1469
|
+
/**
|
1470
|
+
* Disable data labels for box plot
|
1471
|
+
*/
|
1472
|
+
drawDataLabels: noop,
|
1473
|
+
|
1474
|
+
/**
|
1475
|
+
* Translate data points from raw values x and y to plotX and plotY
|
1476
|
+
*/
|
1477
|
+
translate: function() {
|
1478
|
+
var series = this,
|
1479
|
+
yAxis = series.yAxis,
|
1480
|
+
pointArrayMap = series.pointArrayMap;
|
1481
|
+
|
1482
|
+
seriesTypes.column.prototype.translate.apply(series);
|
1483
|
+
|
1484
|
+
// do the translation on each point dimension
|
1485
|
+
each(series.points, function(point) {
|
1486
|
+
each(pointArrayMap, function(key) {
|
1487
|
+
if (point[key] !== null) {
|
1488
|
+
point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);
|
1489
|
+
}
|
1490
|
+
});
|
1491
|
+
});
|
1492
|
+
},
|
1493
|
+
|
1494
|
+
/**
|
1495
|
+
* Draw the data points
|
1496
|
+
*/
|
1497
|
+
drawPoints: function() {
|
1498
|
+
var series = this, //state = series.state,
|
1499
|
+
points = series.points,
|
1500
|
+
options = series.options,
|
1501
|
+
chart = series.chart,
|
1502
|
+
renderer = chart.renderer,
|
1503
|
+
q1Plot,
|
1504
|
+
q3Plot,
|
1505
|
+
highPlot,
|
1506
|
+
lowPlot,
|
1507
|
+
medianPlot,
|
1508
|
+
medianPath,
|
1509
|
+
crispCorr,
|
1510
|
+
crispX = 0,
|
1511
|
+
boxPath,
|
1512
|
+
width,
|
1513
|
+
left,
|
1514
|
+
right,
|
1515
|
+
halfWidth,
|
1516
|
+
doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
|
1517
|
+
pointWiskerLength,
|
1518
|
+
whiskerLength = series.options.whiskerLength;
|
1519
|
+
|
1520
|
+
|
1521
|
+
each(points, function(point) {
|
1522
|
+
|
1523
|
+
var graphic = point.graphic,
|
1524
|
+
verb = graphic ? 'animate' : 'attr',
|
1525
|
+
shapeArgs = point.shapeArgs; // the box
|
1526
|
+
|
1527
|
+
|
1528
|
+
var boxAttr,
|
1529
|
+
stemAttr = {},
|
1530
|
+
whiskersAttr = {},
|
1531
|
+
medianAttr = {},
|
1532
|
+
color = point.color || series.color;
|
1533
|
+
|
1534
|
+
|
1535
|
+
if (point.plotY !== undefined) {
|
1536
|
+
|
1537
|
+
// crisp vector coordinates
|
1538
|
+
width = shapeArgs.width;
|
1539
|
+
left = Math.floor(shapeArgs.x);
|
1540
|
+
right = left + width;
|
1541
|
+
halfWidth = Math.round(width / 2);
|
1542
|
+
q1Plot = Math.floor(doQuartiles ? point.q1Plot : point.lowPlot);
|
1543
|
+
q3Plot = Math.floor(doQuartiles ? point.q3Plot : point.lowPlot);
|
1544
|
+
highPlot = Math.floor(point.highPlot);
|
1545
|
+
lowPlot = Math.floor(point.lowPlot);
|
1546
|
+
|
1547
|
+
if (!graphic) {
|
1548
|
+
point.graphic = graphic = renderer.g('point')
|
1549
|
+
.add(series.group);
|
1550
|
+
|
1551
|
+
point.stem = renderer.path()
|
1552
|
+
.addClass('highcharts-boxplot-stem')
|
1553
|
+
.add(graphic);
|
1554
|
+
|
1555
|
+
if (whiskerLength) {
|
1556
|
+
point.whiskers = renderer.path()
|
1557
|
+
.addClass('highcharts-boxplot-whisker')
|
1558
|
+
.add(graphic);
|
1559
|
+
}
|
1560
|
+
if (doQuartiles) {
|
1561
|
+
point.box = renderer.path(boxPath)
|
1562
|
+
.addClass('highcharts-boxplot-box')
|
1563
|
+
.add(graphic);
|
1564
|
+
}
|
1565
|
+
point.medianShape = renderer.path(medianPath)
|
1566
|
+
.addClass('highcharts-boxplot-median')
|
1567
|
+
.add(graphic);
|
1568
|
+
|
1569
|
+
|
1570
|
+
|
1571
|
+
|
1572
|
+
// Stem attributes
|
1573
|
+
stemAttr.stroke = point.stemColor || options.stemColor || color;
|
1574
|
+
stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
|
1575
|
+
stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
|
1576
|
+
point.stem.attr(stemAttr);
|
1577
|
+
|
1578
|
+
// Whiskers attributes
|
1579
|
+
if (whiskerLength) {
|
1580
|
+
whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
|
1581
|
+
whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
|
1582
|
+
point.whiskers.attr(whiskersAttr);
|
1583
|
+
}
|
1584
|
+
|
1585
|
+
if (doQuartiles) {
|
1586
|
+
boxAttr = series.pointAttribs(point);
|
1587
|
+
point.box.attr(boxAttr);
|
1588
|
+
}
|
1589
|
+
|
1590
|
+
|
1591
|
+
// Median attributes
|
1592
|
+
medianAttr.stroke = point.medianColor || options.medianColor || color;
|
1593
|
+
medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
|
1594
|
+
point.medianShape.attr(medianAttr);
|
1595
|
+
|
1596
|
+
|
1597
|
+
}
|
1598
|
+
|
1599
|
+
|
1600
|
+
|
1601
|
+
// The stem
|
1602
|
+
crispCorr = (point.stem.strokeWidth() % 2) / 2;
|
1603
|
+
crispX = left + halfWidth + crispCorr;
|
1604
|
+
point.stem[verb]({
|
1605
|
+
d: [
|
1606
|
+
// stem up
|
1607
|
+
'M',
|
1608
|
+
crispX, q3Plot,
|
1609
|
+
'L',
|
1610
|
+
crispX, highPlot,
|
1611
|
+
|
1612
|
+
// stem down
|
1613
|
+
'M',
|
1614
|
+
crispX, q1Plot,
|
1615
|
+
'L',
|
1616
|
+
crispX, lowPlot
|
1617
|
+
]
|
1281
1618
|
});
|
1282
1619
|
|
1283
|
-
//
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1620
|
+
// The box
|
1621
|
+
if (doQuartiles) {
|
1622
|
+
crispCorr = (point.box.strokeWidth() % 2) / 2;
|
1623
|
+
q1Plot = Math.floor(q1Plot) + crispCorr;
|
1624
|
+
q3Plot = Math.floor(q3Plot) + crispCorr;
|
1625
|
+
left += crispCorr;
|
1626
|
+
right += crispCorr;
|
1627
|
+
point.box[verb]({
|
1628
|
+
d: [
|
1629
|
+
'M',
|
1630
|
+
left, q3Plot,
|
1631
|
+
'L',
|
1632
|
+
left, q1Plot,
|
1633
|
+
'L',
|
1634
|
+
right, q1Plot,
|
1635
|
+
'L',
|
1636
|
+
right, q3Plot,
|
1637
|
+
'L',
|
1638
|
+
left, q3Plot,
|
1639
|
+
'z'
|
1640
|
+
]
|
1641
|
+
});
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
// The whiskers
|
1645
|
+
if (whiskerLength) {
|
1646
|
+
crispCorr = (point.whiskers.strokeWidth() % 2) / 2;
|
1647
|
+
highPlot = highPlot + crispCorr;
|
1648
|
+
lowPlot = lowPlot + crispCorr;
|
1649
|
+
pointWiskerLength = (/%$/).test(whiskerLength) ? halfWidth * parseFloat(whiskerLength) / 100 : whiskerLength / 2;
|
1650
|
+
point.whiskers[verb]({
|
1651
|
+
d: [
|
1652
|
+
// High whisker
|
1653
|
+
'M',
|
1654
|
+
crispX - pointWiskerLength,
|
1655
|
+
highPlot,
|
1656
|
+
'L',
|
1657
|
+
crispX + pointWiskerLength,
|
1658
|
+
highPlot,
|
1659
|
+
|
1660
|
+
// Low whisker
|
1661
|
+
'M',
|
1662
|
+
crispX - pointWiskerLength,
|
1663
|
+
lowPlot,
|
1664
|
+
'L',
|
1665
|
+
crispX + pointWiskerLength,
|
1666
|
+
lowPlot
|
1667
|
+
]
|
1668
|
+
});
|
1669
|
+
}
|
1670
|
+
|
1671
|
+
// The median
|
1672
|
+
medianPlot = Math.round(point.medianPlot);
|
1673
|
+
crispCorr = (point.medianShape.strokeWidth() % 2) / 2;
|
1674
|
+
medianPlot = medianPlot + crispCorr;
|
1675
|
+
|
1676
|
+
point.medianShape[verb]({
|
1677
|
+
d: [
|
1678
|
+
'M',
|
1679
|
+
left,
|
1680
|
+
medianPlot,
|
1681
|
+
'L',
|
1682
|
+
right,
|
1683
|
+
medianPlot
|
1684
|
+
]
|
1685
|
+
});
|
1287
1686
|
}
|
1288
1687
|
});
|
1289
1688
|
|
1290
|
-
|
1291
|
-
|
1292
|
-
}
|
1293
|
-
},
|
1294
|
-
|
1295
|
-
render: function () {
|
1296
|
-
this.group = this.plotGroup(
|
1297
|
-
'group',
|
1298
|
-
'series',
|
1299
|
-
this.visible ? 'visible' : 'hidden',
|
1300
|
-
this.options.zIndex,
|
1301
|
-
this.chart.seriesGroup
|
1302
|
-
);
|
1303
|
-
Series.prototype.render.call(this);
|
1304
|
-
this.group.clip(this.chart.clipRect);
|
1305
|
-
},
|
1689
|
+
},
|
1690
|
+
setStackedPoints: noop // #3890
|
1306
1691
|
|
1307
|
-
/**
|
1308
|
-
* Extend the basic setData method by running processData and generatePoints immediately,
|
1309
|
-
* in order to access the points from the legend.
|
1310
|
-
*/
|
1311
|
-
setData: function (data, redraw) {
|
1312
|
-
Series.prototype.setData.call(this, data, false);
|
1313
|
-
this.processData();
|
1314
|
-
this.generatePoints();
|
1315
|
-
if (pick(redraw, true)) {
|
1316
|
-
this.chart.redraw();
|
1317
|
-
}
|
1318
|
-
},
|
1319
1692
|
|
1693
|
+
});
|
1694
|
+
|
1695
|
+
/* ****************************************************************************
|
1696
|
+
* End Box plot series code *
|
1697
|
+
*****************************************************************************/
|
1698
|
+
|
1699
|
+
}(Highcharts));
|
1700
|
+
(function(H) {
|
1320
1701
|
/**
|
1321
|
-
*
|
1702
|
+
* (c) 2010-2016 Torstein Honsi
|
1703
|
+
*
|
1704
|
+
* License: www.highcharts.com/license
|
1322
1705
|
*/
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1706
|
+
'use strict';
|
1707
|
+
var each = H.each,
|
1708
|
+
noop = H.noop,
|
1709
|
+
seriesType = H.seriesType,
|
1710
|
+
seriesTypes = H.seriesTypes;
|
1711
|
+
|
1712
|
+
|
1713
|
+
/* ****************************************************************************
|
1714
|
+
* Start error bar series code *
|
1715
|
+
*****************************************************************************/
|
1716
|
+
seriesType('errorbar', 'boxplot', {
|
1717
|
+
|
1718
|
+
color: '#000000',
|
1719
|
+
|
1720
|
+
grouping: false,
|
1721
|
+
linkedTo: ':previous',
|
1722
|
+
tooltip: {
|
1723
|
+
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
|
1724
|
+
},
|
1725
|
+
whiskerWidth: null
|
1726
|
+
|
1727
|
+
// Prototype members
|
1728
|
+
}, {
|
1729
|
+
type: 'errorbar',
|
1730
|
+
pointArrayMap: ['low', 'high'], // array point configs are mapped to this
|
1731
|
+
toYData: function(point) { // return a plain array for speedy calculation
|
1732
|
+
return [point.low, point.high];
|
1733
|
+
},
|
1734
|
+
pointValKey: 'high', // defines the top of the tracker
|
1735
|
+
doQuartiles: false,
|
1736
|
+
drawDataLabels: seriesTypes.arearange ? function() {
|
1737
|
+
var valKey = this.pointValKey;
|
1738
|
+
seriesTypes.arearange.prototype.drawDataLabels.call(this);
|
1739
|
+
// Arearange drawDataLabels does not reset point.y to high, but to low after drawing. #4133
|
1740
|
+
each(this.data, function(point) {
|
1741
|
+
point.y = point[valKey];
|
1742
|
+
});
|
1743
|
+
} : noop,
|
1744
|
+
|
1745
|
+
/**
|
1746
|
+
* Get the width and X offset, either on top of the linked series column
|
1747
|
+
* or standalone
|
1748
|
+
*/
|
1749
|
+
getColumnMetrics: function() {
|
1750
|
+
return (this.linkedParent && this.linkedParent.columnMetrics) ||
|
1751
|
+
seriesTypes.column.prototype.getColumnMetrics.call(this);
|
1340
1752
|
}
|
1341
|
-
}
|
1342
|
-
//stemColor: null,
|
1343
|
-
//stemDashStyle: 'solid'
|
1344
|
-
//stemWidth: null,
|
1345
|
-
threshold: null,
|
1346
|
-
tooltip: {
|
1347
|
-
pointFormat: '<span style="color:{point.color}">\u25CF</span> <b> {series.name}</b><br/>' +
|
1348
|
-
'Maximum: {point.high}<br/>' +
|
1349
|
-
'Upper quartile: {point.q3}<br/>' +
|
1350
|
-
'Median: {point.median}<br/>' +
|
1351
|
-
'Lower quartile: {point.q1}<br/>' +
|
1352
|
-
'Minimum: {point.low}<br/>'
|
1353
|
-
|
1354
|
-
},
|
1355
|
-
//whiskerColor: null,
|
1356
|
-
whiskerLength: '50%',
|
1357
|
-
whiskerWidth: 2
|
1358
|
-
});
|
1359
|
-
|
1360
|
-
// Create the series object
|
1361
|
-
seriesTypes.boxplot = extendClass(seriesTypes.column, {
|
1362
|
-
type: 'boxplot',
|
1363
|
-
pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
|
1364
|
-
toYData: function (point) { // return a plain array for speedy calculation
|
1365
|
-
return [point.low, point.q1, point.median, point.q3, point.high];
|
1366
|
-
},
|
1367
|
-
pointValKey: 'high', // defines the top of the tracker
|
1753
|
+
});
|
1368
1754
|
|
1369
|
-
|
1370
|
-
*
|
1371
|
-
|
1372
|
-
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
|
1373
|
-
fill: 'fillColor',
|
1374
|
-
stroke: 'color',
|
1375
|
-
'stroke-width': 'lineWidth'
|
1376
|
-
},
|
1755
|
+
/* ****************************************************************************
|
1756
|
+
* End error bar series code *
|
1757
|
+
*****************************************************************************/
|
1377
1758
|
|
1759
|
+
}(Highcharts));
|
1760
|
+
(function(H) {
|
1378
1761
|
/**
|
1379
|
-
*
|
1762
|
+
* (c) 2010-2016 Torstein Honsi
|
1763
|
+
*
|
1764
|
+
* License: www.highcharts.com/license
|
1380
1765
|
*/
|
1381
|
-
|
1766
|
+
'use strict';
|
1767
|
+
var correctFloat = H.correctFloat,
|
1768
|
+
isNumber = H.isNumber,
|
1769
|
+
noop = H.noop,
|
1770
|
+
pick = H.pick,
|
1771
|
+
Point = H.Point,
|
1772
|
+
Series = H.Series,
|
1773
|
+
seriesType = H.seriesType,
|
1774
|
+
seriesTypes = H.seriesTypes;
|
1775
|
+
|
1776
|
+
/* ****************************************************************************
|
1777
|
+
* Start Waterfall series code *
|
1778
|
+
*****************************************************************************/
|
1779
|
+
seriesType('waterfall', 'column', {
|
1780
|
+
dataLabels: {
|
1781
|
+
inside: true
|
1782
|
+
},
|
1382
1783
|
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1784
|
+
lineWidth: 1,
|
1785
|
+
lineColor: '#333333',
|
1786
|
+
dashStyle: 'dot',
|
1787
|
+
borderColor: '#333333',
|
1788
|
+
states: {
|
1789
|
+
hover: {
|
1790
|
+
lineWidthPlus: 0 // #3126
|
1791
|
+
}
|
1792
|
+
}
|
1390
1793
|
|
1391
|
-
seriesTypes.column.prototype.translate.apply(series);
|
1392
1794
|
|
1393
|
-
//
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1795
|
+
// Prototype members
|
1796
|
+
}, {
|
1797
|
+
pointValKey: 'y',
|
1798
|
+
|
1799
|
+
/**
|
1800
|
+
* Translate data points from raw values
|
1801
|
+
*/
|
1802
|
+
translate: function() {
|
1803
|
+
var series = this,
|
1804
|
+
options = series.options,
|
1805
|
+
yAxis = series.yAxis,
|
1806
|
+
len,
|
1807
|
+
i,
|
1808
|
+
points,
|
1809
|
+
point,
|
1810
|
+
shapeArgs,
|
1811
|
+
stack,
|
1812
|
+
y,
|
1813
|
+
yValue,
|
1814
|
+
previousY,
|
1815
|
+
previousIntermediate,
|
1816
|
+
range,
|
1817
|
+
minPointLength = pick(options.minPointLength, 5),
|
1818
|
+
threshold = options.threshold,
|
1819
|
+
stacking = options.stacking,
|
1820
|
+
tooltipY;
|
1821
|
+
|
1822
|
+
// run column series translate
|
1823
|
+
seriesTypes.column.prototype.translate.apply(this);
|
1824
|
+
series.minPointLengthOffset = 0;
|
1825
|
+
|
1826
|
+
previousY = previousIntermediate = threshold;
|
1827
|
+
points = series.points;
|
1828
|
+
|
1829
|
+
for (i = 0, len = points.length; i < len; i++) {
|
1830
|
+
// cache current point object
|
1831
|
+
point = points[i];
|
1832
|
+
yValue = this.processedYData[i];
|
1833
|
+
shapeArgs = point.shapeArgs;
|
1834
|
+
|
1835
|
+
// get current stack
|
1836
|
+
stack = stacking && yAxis.stacks[(series.negStacks && yValue < threshold ? '-' : '') + series.stackKey];
|
1837
|
+
range = stack ?
|
1838
|
+
stack[point.x].points[series.index + ',' + i] : [0, yValue];
|
1839
|
+
|
1840
|
+
// override point value for sums
|
1841
|
+
// #3710 Update point does not propagate to sum
|
1842
|
+
if (point.isSum) {
|
1843
|
+
point.y = correctFloat(yValue);
|
1844
|
+
} else if (point.isIntermediateSum) {
|
1845
|
+
point.y = correctFloat(yValue - previousIntermediate); // #3840
|
1398
1846
|
}
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1847
|
+
// up points
|
1848
|
+
y = Math.max(previousY, previousY + point.y) + range[0];
|
1849
|
+
shapeArgs.y = yAxis.toPixels(y, true);
|
1402
1850
|
|
1403
|
-
/**
|
1404
|
-
* Draw the data points
|
1405
|
-
*/
|
1406
|
-
drawPoints: function () {
|
1407
|
-
var series = this, //state = series.state,
|
1408
|
-
points = series.points,
|
1409
|
-
options = series.options,
|
1410
|
-
chart = series.chart,
|
1411
|
-
renderer = chart.renderer,
|
1412
|
-
pointAttr,
|
1413
|
-
q1Plot,
|
1414
|
-
q3Plot,
|
1415
|
-
highPlot,
|
1416
|
-
lowPlot,
|
1417
|
-
medianPlot,
|
1418
|
-
crispCorr,
|
1419
|
-
crispX,
|
1420
|
-
graphic,
|
1421
|
-
stemPath,
|
1422
|
-
stemAttr,
|
1423
|
-
boxPath,
|
1424
|
-
whiskersPath,
|
1425
|
-
whiskersAttr,
|
1426
|
-
medianPath,
|
1427
|
-
medianAttr,
|
1428
|
-
width,
|
1429
|
-
left,
|
1430
|
-
right,
|
1431
|
-
halfWidth,
|
1432
|
-
shapeArgs,
|
1433
|
-
color,
|
1434
|
-
doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
|
1435
|
-
pointWiskerLength,
|
1436
|
-
whiskerLength = series.options.whiskerLength;
|
1437
|
-
|
1438
|
-
|
1439
|
-
each(points, function (point) {
|
1440
|
-
|
1441
|
-
graphic = point.graphic;
|
1442
|
-
shapeArgs = point.shapeArgs; // the box
|
1443
|
-
stemAttr = {};
|
1444
|
-
whiskersAttr = {};
|
1445
|
-
medianAttr = {};
|
1446
|
-
color = point.color || series.color;
|
1447
|
-
|
1448
|
-
if (point.plotY !== UNDEFINED) {
|
1449
|
-
|
1450
|
-
pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
|
1451
|
-
|
1452
|
-
// crisp vector coordinates
|
1453
|
-
width = shapeArgs.width;
|
1454
|
-
left = mathFloor(shapeArgs.x);
|
1455
|
-
right = left + width;
|
1456
|
-
halfWidth = mathRound(width / 2);
|
1457
|
-
//crispX = mathRound(left + halfWidth) + crispCorr;
|
1458
|
-
q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;
|
1459
|
-
q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;
|
1460
|
-
highPlot = mathFloor(point.highPlot);// + crispCorr;
|
1461
|
-
lowPlot = mathFloor(point.lowPlot);// + crispCorr;
|
1462
|
-
|
1463
|
-
// Stem attributes
|
1464
|
-
stemAttr.stroke = point.stemColor || options.stemColor || color;
|
1465
|
-
stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
|
1466
|
-
stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
|
1467
|
-
|
1468
|
-
// Whiskers attributes
|
1469
|
-
whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
|
1470
|
-
whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
|
1471
|
-
|
1472
|
-
// Median attributes
|
1473
|
-
medianAttr.stroke = point.medianColor || options.medianColor || color;
|
1474
|
-
medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
|
1475
|
-
|
1476
|
-
// The stem
|
1477
|
-
crispCorr = (stemAttr['stroke-width'] % 2) / 2;
|
1478
|
-
crispX = left + halfWidth + crispCorr;
|
1479
|
-
stemPath = [
|
1480
|
-
// stem up
|
1481
|
-
'M',
|
1482
|
-
crispX, q3Plot,
|
1483
|
-
'L',
|
1484
|
-
crispX, highPlot,
|
1485
1851
|
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
crispX, lowPlot
|
1491
|
-
];
|
1852
|
+
// sum points
|
1853
|
+
if (point.isSum) {
|
1854
|
+
shapeArgs.y = yAxis.toPixels(range[1], true);
|
1855
|
+
shapeArgs.height = Math.min(yAxis.toPixels(range[0], true), yAxis.len) - shapeArgs.y + series.minPointLengthOffset; // #4256
|
1492
1856
|
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
'L',
|
1511
|
-
left, q3Plot,
|
1512
|
-
'z'
|
1513
|
-
];
|
1857
|
+
} else if (point.isIntermediateSum) {
|
1858
|
+
shapeArgs.y = yAxis.toPixels(range[1], true);
|
1859
|
+
shapeArgs.height = Math.min(yAxis.toPixels(previousIntermediate, true), yAxis.len) - shapeArgs.y + series.minPointLengthOffset;
|
1860
|
+
previousIntermediate = range[1];
|
1861
|
+
|
1862
|
+
// If it's not the sum point, update previous stack end position and get
|
1863
|
+
// shape height (#3886)
|
1864
|
+
} else {
|
1865
|
+
shapeArgs.height = yValue > 0 ?
|
1866
|
+
yAxis.toPixels(previousY, true) - shapeArgs.y :
|
1867
|
+
yAxis.toPixels(previousY, true) - yAxis.toPixels(previousY - yValue, true);
|
1868
|
+
previousY += yValue;
|
1869
|
+
}
|
1870
|
+
// #3952 Negative sum or intermediate sum not rendered correctly
|
1871
|
+
if (shapeArgs.height < 0) {
|
1872
|
+
shapeArgs.y += shapeArgs.height;
|
1873
|
+
shapeArgs.height *= -1;
|
1514
1874
|
}
|
1515
1875
|
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
highPlot = highPlot + crispCorr;
|
1520
|
-
lowPlot = lowPlot + crispCorr;
|
1521
|
-
pointWiskerLength = (/%$/).test(whiskerLength) ? halfWidth * parseFloat(whiskerLength) / 100 : whiskerLength / 2;
|
1522
|
-
whiskersPath = [
|
1523
|
-
// High whisker
|
1524
|
-
'M',
|
1525
|
-
crispX - pointWiskerLength,
|
1526
|
-
highPlot,
|
1527
|
-
'L',
|
1528
|
-
crispX + pointWiskerLength,
|
1529
|
-
highPlot,
|
1876
|
+
point.plotY = shapeArgs.y = Math.round(shapeArgs.y) - (series.borderWidth % 2) / 2;
|
1877
|
+
shapeArgs.height = Math.max(Math.round(shapeArgs.height), 0.001); // #3151
|
1878
|
+
point.yBottom = shapeArgs.y + shapeArgs.height;
|
1530
1879
|
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
lowPlot,
|
1535
|
-
'L',
|
1536
|
-
crispX + pointWiskerLength,
|
1537
|
-
lowPlot
|
1538
|
-
];
|
1880
|
+
if (shapeArgs.height <= minPointLength) {
|
1881
|
+
shapeArgs.height = minPointLength;
|
1882
|
+
series.minPointLengthOffset += minPointLength;
|
1539
1883
|
}
|
1540
1884
|
|
1541
|
-
|
1542
|
-
crispCorr = (medianAttr['stroke-width'] % 2) / 2;
|
1543
|
-
medianPlot = mathRound(point.medianPlot) + crispCorr;
|
1544
|
-
medianPath = [
|
1545
|
-
'M',
|
1546
|
-
left,
|
1547
|
-
medianPlot,
|
1548
|
-
'L',
|
1549
|
-
right,
|
1550
|
-
medianPlot
|
1551
|
-
];
|
1885
|
+
shapeArgs.y -= series.minPointLengthOffset;
|
1552
1886
|
|
1553
|
-
//
|
1554
|
-
|
1887
|
+
// Correct tooltip placement (#3014)
|
1888
|
+
tooltipY = point.plotY + (point.negative ? shapeArgs.height : 0) - series.minPointLengthOffset;
|
1889
|
+
if (series.chart.inverted) {
|
1890
|
+
point.tooltipPos[0] = yAxis.len - tooltipY;
|
1891
|
+
} else {
|
1892
|
+
point.tooltipPos[1] = tooltipY;
|
1893
|
+
}
|
1555
1894
|
|
1556
|
-
|
1557
|
-
|
1558
|
-
point.whiskers.animate({ d: whiskersPath });
|
1559
|
-
}
|
1560
|
-
if (doQuartiles) {
|
1561
|
-
point.box.animate({ d: boxPath });
|
1562
|
-
}
|
1563
|
-
point.medianShape.animate({ d: medianPath });
|
1895
|
+
}
|
1896
|
+
},
|
1564
1897
|
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1898
|
+
/**
|
1899
|
+
* Call default processData then override yData to reflect waterfall's extremes on yAxis
|
1900
|
+
*/
|
1901
|
+
processData: function(force) {
|
1902
|
+
var series = this,
|
1903
|
+
options = series.options,
|
1904
|
+
yData = series.yData,
|
1905
|
+
points = series.options.data, // #3710 Update point does not propagate to sum
|
1906
|
+
point,
|
1907
|
+
dataLength = yData.length,
|
1908
|
+
threshold = options.threshold || 0,
|
1909
|
+
subSum,
|
1910
|
+
sum,
|
1911
|
+
dataMin,
|
1912
|
+
dataMax,
|
1913
|
+
y,
|
1914
|
+
i;
|
1568
1915
|
|
1569
|
-
|
1570
|
-
.attr(stemAttr)
|
1571
|
-
.add(graphic);
|
1916
|
+
sum = subSum = dataMin = dataMax = threshold;
|
1572
1917
|
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
.attr(medianAttr)
|
1585
|
-
.add(graphic);
|
1918
|
+
for (i = 0; i < dataLength; i++) {
|
1919
|
+
y = yData[i];
|
1920
|
+
point = points && points[i] ? points[i] : {};
|
1921
|
+
|
1922
|
+
if (y === 'sum' || point.isSum) {
|
1923
|
+
yData[i] = correctFloat(sum);
|
1924
|
+
} else if (y === 'intermediateSum' || point.isIntermediateSum) {
|
1925
|
+
yData[i] = correctFloat(subSum);
|
1926
|
+
} else {
|
1927
|
+
sum += y;
|
1928
|
+
subSum += y;
|
1586
1929
|
}
|
1930
|
+
dataMin = Math.min(sum, dataMin);
|
1931
|
+
dataMax = Math.max(sum, dataMax);
|
1587
1932
|
}
|
1588
|
-
});
|
1589
|
-
|
1590
|
-
},
|
1591
|
-
setStackedPoints: noop // #3890
|
1592
|
-
|
1593
|
-
|
1594
|
-
});
|
1595
|
-
|
1596
|
-
/* ****************************************************************************
|
1597
|
-
* End Box plot series code *
|
1598
|
-
*****************************************************************************/
|
1599
|
-
/* ****************************************************************************
|
1600
|
-
* Start error bar series code *
|
1601
|
-
*****************************************************************************/
|
1602
|
-
|
1603
|
-
// 1 - set default options
|
1604
|
-
defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
|
1605
|
-
color: '#000000',
|
1606
|
-
grouping: false,
|
1607
|
-
linkedTo: ':previous',
|
1608
|
-
tooltip: {
|
1609
|
-
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
|
1610
|
-
},
|
1611
|
-
whiskerWidth: null
|
1612
|
-
});
|
1613
|
-
|
1614
|
-
// 2 - Create the series object
|
1615
|
-
seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
|
1616
|
-
type: 'errorbar',
|
1617
|
-
pointArrayMap: ['low', 'high'], // array point configs are mapped to this
|
1618
|
-
toYData: function (point) { // return a plain array for speedy calculation
|
1619
|
-
return [point.low, point.high];
|
1620
|
-
},
|
1621
|
-
pointValKey: 'high', // defines the top of the tracker
|
1622
|
-
doQuartiles: false,
|
1623
|
-
drawDataLabels: seriesTypes.arearange ? function () {
|
1624
|
-
var valKey = this.pointValKey;
|
1625
|
-
seriesTypes.arearange.prototype.drawDataLabels.call(this);
|
1626
|
-
// Arearange drawDataLabels does not reset point.y to high, but to low after drawing. #4133
|
1627
|
-
each(this.data, function (point) {
|
1628
|
-
point.y = point[valKey];
|
1629
|
-
});
|
1630
|
-
} : noop,
|
1631
1933
|
|
1632
|
-
|
1633
|
-
* Get the width and X offset, either on top of the linked series column
|
1634
|
-
* or standalone
|
1635
|
-
*/
|
1636
|
-
getColumnMetrics: function () {
|
1637
|
-
return (this.linkedParent && this.linkedParent.columnMetrics) ||
|
1638
|
-
seriesTypes.column.prototype.getColumnMetrics.call(this);
|
1639
|
-
}
|
1640
|
-
});
|
1641
|
-
|
1642
|
-
/* ****************************************************************************
|
1643
|
-
* End error bar series code *
|
1644
|
-
*****************************************************************************/
|
1645
|
-
/* ****************************************************************************
|
1646
|
-
* Start Waterfall series code *
|
1647
|
-
*****************************************************************************/
|
1648
|
-
|
1649
|
-
// 1 - set default options
|
1650
|
-
defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {
|
1651
|
-
lineWidth: 1,
|
1652
|
-
lineColor: '#333',
|
1653
|
-
dashStyle: 'dot',
|
1654
|
-
borderColor: '#333',
|
1655
|
-
dataLabels: {
|
1656
|
-
inside: true
|
1657
|
-
},
|
1658
|
-
states: {
|
1659
|
-
hover: {
|
1660
|
-
lineWidthPlus: 0 // #3126
|
1661
|
-
}
|
1662
|
-
}
|
1663
|
-
});
|
1934
|
+
Series.prototype.processData.call(this, force);
|
1664
1935
|
|
1936
|
+
// Record extremes
|
1937
|
+
series.dataMin = dataMin;
|
1938
|
+
series.dataMax = dataMax;
|
1939
|
+
},
|
1665
1940
|
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1941
|
+
/**
|
1942
|
+
* Return y value or string if point is sum
|
1943
|
+
*/
|
1944
|
+
toYData: function(pt) {
|
1945
|
+
if (pt.isSum) {
|
1946
|
+
return (pt.x === 0 ? null : 'sum'); //#3245 Error when first element is Sum or Intermediate Sum
|
1947
|
+
}
|
1948
|
+
if (pt.isIntermediateSum) {
|
1949
|
+
return (pt.x === 0 ? null : 'intermediateSum'); //#3245
|
1950
|
+
}
|
1951
|
+
return pt.y;
|
1952
|
+
},
|
1669
1953
|
|
1670
|
-
upColorProp: 'fill',
|
1671
1954
|
|
1672
|
-
|
1955
|
+
/**
|
1956
|
+
* Postprocess mapping between options and SVG attributes
|
1957
|
+
*/
|
1958
|
+
pointAttribs: function(point, state) {
|
1673
1959
|
|
1674
|
-
|
1675
|
-
|
1676
|
-
*/
|
1677
|
-
pointClass: extendClass(Point, {
|
1678
|
-
isValid: function () {
|
1679
|
-
return isNumber(this.y, true) || this.isSum || this.isIntermediateSum;
|
1680
|
-
}
|
1681
|
-
}),
|
1960
|
+
var upColor = this.options.upColor,
|
1961
|
+
attr;
|
1682
1962
|
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
translate: function () {
|
1687
|
-
var series = this,
|
1688
|
-
options = series.options,
|
1689
|
-
yAxis = series.yAxis,
|
1690
|
-
len,
|
1691
|
-
i,
|
1692
|
-
points,
|
1693
|
-
point,
|
1694
|
-
shapeArgs,
|
1695
|
-
stack,
|
1696
|
-
y,
|
1697
|
-
yValue,
|
1698
|
-
previousY,
|
1699
|
-
previousIntermediate,
|
1700
|
-
range,
|
1701
|
-
minPointLength = pick(options.minPointLength, 5),
|
1702
|
-
threshold = options.threshold,
|
1703
|
-
stacking = options.stacking,
|
1704
|
-
tooltipY;
|
1705
|
-
|
1706
|
-
// run column series translate
|
1707
|
-
seriesTypes.column.prototype.translate.apply(this);
|
1708
|
-
series.minPointLengthOffset = 0;
|
1709
|
-
|
1710
|
-
previousY = previousIntermediate = threshold;
|
1711
|
-
points = series.points;
|
1712
|
-
|
1713
|
-
for (i = 0, len = points.length; i < len; i++) {
|
1714
|
-
// cache current point object
|
1715
|
-
point = points[i];
|
1716
|
-
yValue = this.processedYData[i];
|
1717
|
-
shapeArgs = point.shapeArgs;
|
1718
|
-
|
1719
|
-
// get current stack
|
1720
|
-
stack = stacking && yAxis.stacks[(series.negStacks && yValue < threshold ? '-' : '') + series.stackKey];
|
1721
|
-
range = stack ?
|
1722
|
-
stack[point.x].points[series.index + ',' + i] :
|
1723
|
-
[0, yValue];
|
1724
|
-
|
1725
|
-
// override point value for sums
|
1726
|
-
// #3710 Update point does not propagate to sum
|
1727
|
-
if (point.isSum) {
|
1728
|
-
point.y = correctFloat(yValue);
|
1729
|
-
} else if (point.isIntermediateSum) {
|
1730
|
-
point.y = correctFloat(yValue - previousIntermediate); // #3840
|
1963
|
+
// Set or reset up color (#3710, update to negative)
|
1964
|
+
if (upColor && !point.options.color) {
|
1965
|
+
point.color = point.y > 0 ? upColor : null;
|
1731
1966
|
}
|
1732
|
-
// up points
|
1733
|
-
y = mathMax(previousY, previousY + point.y) + range[0];
|
1734
|
-
shapeArgs.y = yAxis.toPixels(y, true);
|
1735
1967
|
|
1968
|
+
attr = seriesTypes.column.prototype.pointAttribs.call(this, point, state);
|
1736
1969
|
|
1737
|
-
//
|
1738
|
-
|
1739
|
-
|
1740
|
-
shapeArgs.height = Math.min(yAxis.toPixels(range[0], true), yAxis.len) - shapeArgs.y + series.minPointLengthOffset; // #4256
|
1970
|
+
// The dashStyle option in waterfall applies to the graph, not
|
1971
|
+
// the points
|
1972
|
+
delete attr.dashstyle;
|
1741
1973
|
|
1742
|
-
|
1743
|
-
|
1744
|
-
shapeArgs.height = Math.min(yAxis.toPixels(previousIntermediate, true), yAxis.len) - shapeArgs.y + series.minPointLengthOffset;
|
1745
|
-
previousIntermediate = range[1];
|
1974
|
+
return attr;
|
1975
|
+
},
|
1746
1976
|
|
1747
|
-
// If it's not the sum point, update previous stack end position and get
|
1748
|
-
// shape height (#3886)
|
1749
|
-
} else {
|
1750
|
-
shapeArgs.height = yValue > 0 ?
|
1751
|
-
yAxis.toPixels(previousY, true) - shapeArgs.y :
|
1752
|
-
yAxis.toPixels(previousY, true) - yAxis.toPixels(previousY - yValue, true);
|
1753
|
-
previousY += yValue;
|
1754
|
-
}
|
1755
|
-
// #3952 Negative sum or intermediate sum not rendered correctly
|
1756
|
-
if (shapeArgs.height < 0) {
|
1757
|
-
shapeArgs.y += shapeArgs.height;
|
1758
|
-
shapeArgs.height *= -1;
|
1759
|
-
}
|
1760
1977
|
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1978
|
+
/**
|
1979
|
+
* Return an empty path initially, because we need to know the stroke-width in order
|
1980
|
+
* to set the final path.
|
1981
|
+
*/
|
1982
|
+
getGraphPath: function() {
|
1983
|
+
return ['M', 0, 0];
|
1984
|
+
},
|
1764
1985
|
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1986
|
+
/**
|
1987
|
+
* Draw columns' connector lines
|
1988
|
+
*/
|
1989
|
+
getCrispPath: function() {
|
1990
|
+
|
1991
|
+
var data = this.data,
|
1992
|
+
length = data.length,
|
1993
|
+
lineWidth = this.graph.strokeWidth() + this.borderWidth,
|
1994
|
+
normalizer = Math.round(lineWidth) % 2 / 2,
|
1995
|
+
path = [],
|
1996
|
+
prevArgs,
|
1997
|
+
pointArgs,
|
1998
|
+
i,
|
1999
|
+
d;
|
2000
|
+
|
2001
|
+
for (i = 1; i < length; i++) {
|
2002
|
+
pointArgs = data[i].shapeArgs;
|
2003
|
+
prevArgs = data[i - 1].shapeArgs;
|
2004
|
+
|
2005
|
+
d = [
|
2006
|
+
'M',
|
2007
|
+
prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
|
2008
|
+
'L',
|
2009
|
+
pointArgs.x, prevArgs.y + normalizer
|
2010
|
+
];
|
1769
2011
|
|
1770
|
-
|
2012
|
+
if (data[i - 1].y < 0) {
|
2013
|
+
d[2] += prevArgs.height;
|
2014
|
+
d[5] += prevArgs.height;
|
2015
|
+
}
|
1771
2016
|
|
1772
|
-
|
1773
|
-
tooltipY = point.plotY + (point.negative ? shapeArgs.height : 0) - series.minPointLengthOffset;
|
1774
|
-
if (series.chart.inverted) {
|
1775
|
-
point.tooltipPos[0] = yAxis.len - tooltipY;
|
1776
|
-
} else {
|
1777
|
-
point.tooltipPos[1] = tooltipY;
|
2017
|
+
path = path.concat(d);
|
1778
2018
|
}
|
1779
2019
|
|
1780
|
-
|
1781
|
-
|
2020
|
+
return path;
|
2021
|
+
},
|
1782
2022
|
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
threshold = options.threshold || 0,
|
1794
|
-
subSum,
|
1795
|
-
sum,
|
1796
|
-
dataMin,
|
1797
|
-
dataMax,
|
1798
|
-
y,
|
1799
|
-
i;
|
2023
|
+
/**
|
2024
|
+
* The graph is initally drawn with an empty definition, then updated with
|
2025
|
+
* crisp rendering.
|
2026
|
+
*/
|
2027
|
+
drawGraph: function() {
|
2028
|
+
Series.prototype.drawGraph.call(this);
|
2029
|
+
this.graph.attr({
|
2030
|
+
d: this.getCrispPath()
|
2031
|
+
});
|
2032
|
+
},
|
1800
2033
|
|
1801
|
-
|
2034
|
+
/**
|
2035
|
+
* Extremes are recorded in processData
|
2036
|
+
*/
|
2037
|
+
getExtremes: noop
|
1802
2038
|
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
2039
|
+
// Point members
|
2040
|
+
}, {
|
2041
|
+
getClassName: function() {
|
2042
|
+
var className = Point.prototype.getClassName.call(this);
|
1806
2043
|
|
1807
|
-
if (
|
1808
|
-
|
1809
|
-
} else if (
|
1810
|
-
|
1811
|
-
} else {
|
1812
|
-
sum += y;
|
1813
|
-
subSum += y;
|
2044
|
+
if (this.isSum) {
|
2045
|
+
className += ' highcharts-sum';
|
2046
|
+
} else if (this.isIntermediateSum) {
|
2047
|
+
className += ' highcharts-intermediate-sum';
|
1814
2048
|
}
|
1815
|
-
|
1816
|
-
|
2049
|
+
return className;
|
2050
|
+
},
|
2051
|
+
/**
|
2052
|
+
* Pass the null test in ColumnSeries.translate.
|
2053
|
+
*/
|
2054
|
+
isValid: function() {
|
2055
|
+
return isNumber(this.y, true) || this.isSum || this.isIntermediateSum;
|
1817
2056
|
}
|
1818
2057
|
|
1819
|
-
|
2058
|
+
});
|
1820
2059
|
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
},
|
2060
|
+
/* ****************************************************************************
|
2061
|
+
* End Waterfall series code *
|
2062
|
+
*****************************************************************************/
|
1825
2063
|
|
2064
|
+
}(Highcharts));
|
2065
|
+
(function(H) {
|
1826
2066
|
/**
|
1827
|
-
*
|
2067
|
+
* (c) 2010-2016 Torstein Honsi
|
2068
|
+
*
|
2069
|
+
* License: www.highcharts.com/license
|
1828
2070
|
*/
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
}
|
1836
|
-
return pt.y;
|
1837
|
-
},
|
1838
|
-
|
2071
|
+
'use strict';
|
2072
|
+
var LegendSymbolMixin = H.LegendSymbolMixin,
|
2073
|
+
noop = H.noop,
|
2074
|
+
Series = H.Series,
|
2075
|
+
seriesType = H.seriesType,
|
2076
|
+
seriesTypes = H.seriesTypes;
|
1839
2077
|
/**
|
1840
|
-
*
|
2078
|
+
* The polygon series prototype
|
1841
2079
|
*/
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
upColor = options.upColor || series.color,
|
1849
|
-
hoverColor = Highcharts.Color(upColor).brighten(options.states.hover.brightness).get(),
|
1850
|
-
seriesDownPointAttr = merge(series.pointAttr),
|
1851
|
-
upColorProp = series.upColorProp;
|
1852
|
-
|
1853
|
-
seriesDownPointAttr[''][upColorProp] = upColor;
|
1854
|
-
seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;
|
1855
|
-
seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;
|
1856
|
-
|
1857
|
-
each(series.points, function (point) {
|
1858
|
-
if (!point.options.color) {
|
1859
|
-
// Up color
|
1860
|
-
if (point.y > 0) {
|
1861
|
-
point.pointAttr = seriesDownPointAttr;
|
1862
|
-
point.color = upColor;
|
1863
|
-
|
1864
|
-
// Down color (#3710, update to negative)
|
1865
|
-
} else {
|
1866
|
-
point.pointAttr = series.pointAttr;
|
2080
|
+
seriesType('polygon', 'scatter', {
|
2081
|
+
marker: {
|
2082
|
+
enabled: false,
|
2083
|
+
states: {
|
2084
|
+
hover: {
|
2085
|
+
enabled: false
|
1867
2086
|
}
|
1868
2087
|
}
|
1869
|
-
}
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
var data = this.data,
|
1878
|
-
length = data.length,
|
1879
|
-
lineWidth = this.options.lineWidth + this.borderWidth,
|
1880
|
-
normalizer = mathRound(lineWidth) % 2 / 2,
|
1881
|
-
path = [],
|
1882
|
-
M = 'M',
|
1883
|
-
L = 'L',
|
1884
|
-
prevArgs,
|
1885
|
-
pointArgs,
|
1886
|
-
i,
|
1887
|
-
d;
|
2088
|
+
},
|
2089
|
+
stickyTracking: false,
|
2090
|
+
tooltip: {
|
2091
|
+
followPointer: true,
|
2092
|
+
pointFormat: ''
|
2093
|
+
},
|
2094
|
+
trackByArea: true
|
1888
2095
|
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
2096
|
+
// Prototype members
|
2097
|
+
}, {
|
2098
|
+
type: 'polygon',
|
2099
|
+
getGraphPath: function() {
|
1892
2100
|
|
1893
|
-
|
1894
|
-
|
1895
|
-
prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
|
1896
|
-
L,
|
1897
|
-
pointArgs.x, prevArgs.y + normalizer
|
1898
|
-
];
|
2101
|
+
var graphPath = Series.prototype.getGraphPath.call(this),
|
2102
|
+
i = graphPath.length + 1;
|
1899
2103
|
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
2104
|
+
// Close all segments
|
2105
|
+
while (i--) {
|
2106
|
+
if ((i === graphPath.length || graphPath[i] === 'M') && i > 0) {
|
2107
|
+
graphPath.splice(i, 0, 'z');
|
2108
|
+
}
|
1903
2109
|
}
|
2110
|
+
this.areaPath = graphPath;
|
2111
|
+
return graphPath;
|
2112
|
+
},
|
2113
|
+
drawGraph: function() {
|
1904
2114
|
|
1905
|
-
|
1906
|
-
}
|
2115
|
+
this.options.fillColor = this.color; // Hack into the fill logic in area.drawGraph
|
1907
2116
|
|
1908
|
-
|
1909
|
-
|
2117
|
+
seriesTypes.area.prototype.drawGraph.call(this);
|
2118
|
+
},
|
2119
|
+
drawLegendSymbol: LegendSymbolMixin.drawRectangle,
|
2120
|
+
drawTracker: Series.prototype.drawTracker,
|
2121
|
+
setStackedPoints: noop // No stacking points on polygons (#5310)
|
2122
|
+
});
|
1910
2123
|
|
2124
|
+
}(Highcharts));
|
2125
|
+
(function(H) {
|
1911
2126
|
/**
|
1912
|
-
*
|
2127
|
+
* (c) 2010-2016 Torstein Honsi
|
2128
|
+
*
|
2129
|
+
* License: www.highcharts.com/license
|
1913
2130
|
*/
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
2131
|
+
'use strict';
|
2132
|
+
var arrayMax = H.arrayMax,
|
2133
|
+
arrayMin = H.arrayMin,
|
2134
|
+
Axis = H.Axis,
|
2135
|
+
color = H.color,
|
2136
|
+
each = H.each,
|
2137
|
+
isNumber = H.isNumber,
|
2138
|
+
noop = H.noop,
|
2139
|
+
pick = H.pick,
|
2140
|
+
pInt = H.pInt,
|
2141
|
+
Point = H.Point,
|
2142
|
+
Series = H.Series,
|
2143
|
+
seriesType = H.seriesType,
|
2144
|
+
seriesTypes = H.seriesTypes;
|
2145
|
+
|
2146
|
+
/* ****************************************************************************
|
2147
|
+
* Start Bubble series code *
|
2148
|
+
*****************************************************************************/
|
2149
|
+
|
2150
|
+
seriesType('bubble', 'scatter', {
|
2151
|
+
dataLabels: {
|
2152
|
+
formatter: function() { // #2945
|
2153
|
+
return this.point.z;
|
2154
|
+
},
|
2155
|
+
inside: true,
|
2156
|
+
verticalAlign: 'middle'
|
2157
|
+
},
|
2158
|
+
// displayNegative: true,
|
2159
|
+
marker: {
|
2160
|
+
|
2161
|
+
// fillOpacity: 0.5,
|
2162
|
+
lineColor: null, // inherit from series.color
|
2163
|
+
lineWidth: 1,
|
2164
|
+
|
2165
|
+
// Avoid offset in Point.setState
|
2166
|
+
radius: null,
|
2167
|
+
states: {
|
2168
|
+
hover: {
|
2169
|
+
radiusPlus: 0
|
2170
|
+
}
|
2171
|
+
}
|
2172
|
+
},
|
2173
|
+
minSize: 8,
|
2174
|
+
maxSize: '20%',
|
2175
|
+
// negativeColor: null,
|
2176
|
+
// sizeBy: 'area'
|
2177
|
+
softThreshold: false,
|
1928
2178
|
states: {
|
1929
2179
|
hover: {
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
},
|
1934
|
-
stickyTracking: false,
|
1935
|
-
tooltip: {
|
1936
|
-
followPointer: true,
|
1937
|
-
pointFormat: ''
|
1938
|
-
},
|
1939
|
-
trackByArea: true
|
1940
|
-
});
|
1941
|
-
|
1942
|
-
/**
|
1943
|
-
* The polygon series class
|
1944
|
-
*/
|
1945
|
-
seriesTypes.polygon = extendClass(seriesTypes.scatter, {
|
1946
|
-
type: 'polygon',
|
1947
|
-
getGraphPath: function () {
|
1948
|
-
|
1949
|
-
var graphPath = Series.prototype.getGraphPath.call(this),
|
1950
|
-
i = graphPath.length + 1;
|
1951
|
-
|
1952
|
-
// Close all segments
|
1953
|
-
while (i--) {
|
1954
|
-
if ((i === graphPath.length || graphPath[i] === 'M') && i > 0) {
|
1955
|
-
graphPath.splice(i, 0, 'z');
|
1956
|
-
}
|
1957
|
-
}
|
1958
|
-
this.areaPath = graphPath;
|
1959
|
-
return graphPath;
|
1960
|
-
},
|
1961
|
-
drawGraph: function () {
|
1962
|
-
this.options.fillColor = this.color; // Hack into the fill logic in area.drawGraph
|
1963
|
-
seriesTypes.area.prototype.drawGraph.call(this);
|
1964
|
-
},
|
1965
|
-
drawLegendSymbol: Highcharts.LegendSymbolMixin.drawRectangle,
|
1966
|
-
drawTracker: Series.prototype.drawTracker,
|
1967
|
-
setStackedPoints: noop // No stacking points on polygons (#5310)
|
1968
|
-
});
|
1969
|
-
/* ****************************************************************************
|
1970
|
-
* Start Bubble series code *
|
1971
|
-
*****************************************************************************/
|
1972
|
-
|
1973
|
-
// 1 - set default options
|
1974
|
-
defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
|
1975
|
-
dataLabels: {
|
1976
|
-
formatter: function () { // #2945
|
1977
|
-
return this.point.z;
|
1978
|
-
},
|
1979
|
-
inside: true,
|
1980
|
-
verticalAlign: 'middle'
|
1981
|
-
},
|
1982
|
-
// displayNegative: true,
|
1983
|
-
marker: {
|
1984
|
-
// fillOpacity: 0.5,
|
1985
|
-
lineColor: null, // inherit from series.color
|
1986
|
-
lineWidth: 1
|
1987
|
-
},
|
1988
|
-
minSize: 8,
|
1989
|
-
maxSize: '20%',
|
1990
|
-
// negativeColor: null,
|
1991
|
-
// sizeBy: 'area'
|
1992
|
-
softThreshold: false,
|
1993
|
-
states: {
|
1994
|
-
hover: {
|
1995
|
-
halo: {
|
1996
|
-
size: 5
|
2180
|
+
halo: {
|
2181
|
+
size: 5
|
2182
|
+
}
|
1997
2183
|
}
|
1998
|
-
}
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
});
|
2014
|
-
|
2015
|
-
// 2 - Create the series object
|
2016
|
-
seriesTypes.bubble = extendClass(seriesTypes.scatter, {
|
2017
|
-
type: 'bubble',
|
2018
|
-
pointClass: BubblePoint,
|
2019
|
-
pointArrayMap: ['y', 'z'],
|
2020
|
-
parallelArrays: ['x', 'y', 'z'],
|
2021
|
-
trackerGroups: ['group', 'dataLabelsGroup'],
|
2022
|
-
bubblePadding: true,
|
2023
|
-
zoneAxis: 'z',
|
2184
|
+
},
|
2185
|
+
tooltip: {
|
2186
|
+
pointFormat: '({point.x}, {point.y}), Size: {point.z}'
|
2187
|
+
},
|
2188
|
+
turboThreshold: 0,
|
2189
|
+
zThreshold: 0,
|
2190
|
+
zoneAxis: 'z'
|
2191
|
+
|
2192
|
+
// Prototype members
|
2193
|
+
}, {
|
2194
|
+
pointArrayMap: ['y', 'z'],
|
2195
|
+
parallelArrays: ['x', 'y', 'z'],
|
2196
|
+
trackerGroups: ['group', 'dataLabelsGroup'],
|
2197
|
+
bubblePadding: true,
|
2198
|
+
zoneAxis: 'z',
|
2024
2199
|
|
2025
|
-
/**
|
2026
|
-
* Mapping between SVG attributes and the corresponding options
|
2027
|
-
*/
|
2028
|
-
pointAttrToOptions: {
|
2029
|
-
stroke: 'lineColor',
|
2030
|
-
'stroke-width': 'lineWidth',
|
2031
|
-
fill: 'fillColor'
|
2032
|
-
},
|
2033
2200
|
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
var markerOptions = this.options.marker,
|
2039
|
-
fillOpacity = pick(markerOptions.fillOpacity, 0.5);
|
2201
|
+
pointAttribs: function(point, state) {
|
2202
|
+
var markerOptions = this.options.marker,
|
2203
|
+
fillOpacity = pick(markerOptions.fillOpacity, 0.5),
|
2204
|
+
attr = Series.prototype.pointAttribs.call(this, point, state);
|
2040
2205
|
|
2041
|
-
|
2042
|
-
|
2206
|
+
if (fillOpacity !== 1) {
|
2207
|
+
attr.fill = color(attr.fill).setOpacity(fillOpacity).get('rgba');
|
2208
|
+
}
|
2043
2209
|
|
2044
|
-
|
2045
|
-
|
2046
|
-
}
|
2047
|
-
return fill;
|
2048
|
-
},
|
2210
|
+
return attr;
|
2211
|
+
},
|
2049
2212
|
|
2050
|
-
/**
|
2051
|
-
* Extend the convertAttribs method by applying opacity to the fill
|
2052
|
-
*/
|
2053
|
-
convertAttribs: function () {
|
2054
|
-
var obj = Series.prototype.convertAttribs.apply(this, arguments);
|
2055
2213
|
|
2056
|
-
|
2214
|
+
/**
|
2215
|
+
* Get the radius for each point based on the minSize, maxSize and each point's Z value. This
|
2216
|
+
* must be done prior to Series.translate because the axis needs to add padding in
|
2217
|
+
* accordance with the point sizes.
|
2218
|
+
*/
|
2219
|
+
getRadii: function(zMin, zMax, minSize, maxSize) {
|
2220
|
+
var len,
|
2221
|
+
i,
|
2222
|
+
pos,
|
2223
|
+
zData = this.zData,
|
2224
|
+
radii = [],
|
2225
|
+
options = this.options,
|
2226
|
+
sizeByArea = options.sizeBy !== 'width',
|
2227
|
+
zThreshold = options.zThreshold,
|
2228
|
+
zRange = zMax - zMin,
|
2229
|
+
value,
|
2230
|
+
radius;
|
2231
|
+
|
2232
|
+
// Set the shape type and arguments to be picked up in drawPoints
|
2233
|
+
for (i = 0, len = zData.length; i < len; i++) {
|
2234
|
+
|
2235
|
+
value = zData[i];
|
2236
|
+
|
2237
|
+
// When sizing by threshold, the absolute value of z determines the size
|
2238
|
+
// of the bubble.
|
2239
|
+
if (options.sizeByAbsoluteValue && value !== null) {
|
2240
|
+
value = Math.abs(value - zThreshold);
|
2241
|
+
zMax = Math.max(zMax - zThreshold, Math.abs(zMin - zThreshold));
|
2242
|
+
zMin = 0;
|
2243
|
+
}
|
2057
2244
|
|
2058
|
-
|
2059
|
-
|
2245
|
+
if (value === null) {
|
2246
|
+
radius = null;
|
2247
|
+
// Issue #4419 - if value is less than zMin, push a radius that's always smaller than the minimum size
|
2248
|
+
} else if (value < zMin) {
|
2249
|
+
radius = minSize / 2 - 1;
|
2250
|
+
} else {
|
2251
|
+
// Relative size, a number between 0 and 1
|
2252
|
+
pos = zRange > 0 ? (value - zMin) / zRange : 0.5;
|
2060
2253
|
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
var len,
|
2068
|
-
i,
|
2069
|
-
pos,
|
2070
|
-
zData = this.zData,
|
2071
|
-
radii = [],
|
2072
|
-
options = this.options,
|
2073
|
-
sizeByArea = options.sizeBy !== 'width',
|
2074
|
-
zThreshold = options.zThreshold,
|
2075
|
-
zRange = zMax - zMin,
|
2076
|
-
value,
|
2077
|
-
radius;
|
2078
|
-
|
2079
|
-
// Set the shape type and arguments to be picked up in drawPoints
|
2080
|
-
for (i = 0, len = zData.length; i < len; i++) {
|
2081
|
-
|
2082
|
-
value = zData[i];
|
2083
|
-
|
2084
|
-
// When sizing by threshold, the absolute value of z determines the size
|
2085
|
-
// of the bubble.
|
2086
|
-
if (options.sizeByAbsoluteValue && value !== null) {
|
2087
|
-
value = Math.abs(value - zThreshold);
|
2088
|
-
zMax = Math.max(zMax - zThreshold, Math.abs(zMin - zThreshold));
|
2089
|
-
zMin = 0;
|
2254
|
+
if (sizeByArea && pos >= 0) {
|
2255
|
+
pos = Math.sqrt(pos);
|
2256
|
+
}
|
2257
|
+
radius = Math.ceil(minSize + pos * (maxSize - minSize)) / 2;
|
2258
|
+
}
|
2259
|
+
radii.push(radius);
|
2090
2260
|
}
|
2261
|
+
this.radii = radii;
|
2262
|
+
},
|
2091
2263
|
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2264
|
+
/**
|
2265
|
+
* Perform animation on the bubbles
|
2266
|
+
*/
|
2267
|
+
animate: function(init) {
|
2268
|
+
var animation = this.options.animation;
|
2269
|
+
|
2270
|
+
if (!init) { // run the animation
|
2271
|
+
each(this.points, function(point) {
|
2272
|
+
var graphic = point.graphic,
|
2273
|
+
shapeArgs = point.shapeArgs;
|
2274
|
+
|
2275
|
+
if (graphic && shapeArgs) {
|
2276
|
+
// start values
|
2277
|
+
graphic.attr('r', 1);
|
2278
|
+
|
2279
|
+
// animate
|
2280
|
+
graphic.animate({
|
2281
|
+
r: shapeArgs.r
|
2282
|
+
}, animation);
|
2283
|
+
}
|
2284
|
+
});
|
2100
2285
|
|
2101
|
-
|
2102
|
-
|
2103
|
-
}
|
2104
|
-
radius = math.ceil(minSize + pos * (maxSize - minSize)) / 2;
|
2286
|
+
// delete this function to allow it only once
|
2287
|
+
this.animate = null;
|
2105
2288
|
}
|
2106
|
-
|
2107
|
-
}
|
2108
|
-
this.radii = radii;
|
2109
|
-
},
|
2289
|
+
},
|
2110
2290
|
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
var animation = this.options.animation;
|
2291
|
+
/**
|
2292
|
+
* Extend the base translate method to handle bubble size
|
2293
|
+
*/
|
2294
|
+
translate: function() {
|
2116
2295
|
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2296
|
+
var i,
|
2297
|
+
data = this.data,
|
2298
|
+
point,
|
2299
|
+
radius,
|
2300
|
+
radii = this.radii;
|
2301
|
+
|
2302
|
+
// Run the parent method
|
2303
|
+
seriesTypes.scatter.prototype.translate.call(this);
|
2304
|
+
|
2305
|
+
// Set the shape type and arguments to be picked up in drawPoints
|
2306
|
+
i = data.length;
|
2121
2307
|
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2308
|
+
while (i--) {
|
2309
|
+
point = data[i];
|
2310
|
+
radius = radii ? radii[i] : 0; // #1737
|
2311
|
+
|
2312
|
+
if (isNumber(radius) && radius >= this.minPxSize / 2) {
|
2313
|
+
// Shape arguments
|
2314
|
+
point.shapeType = 'circle';
|
2315
|
+
point.shapeArgs = {
|
2316
|
+
x: point.plotX,
|
2317
|
+
y: point.plotY,
|
2318
|
+
r: radius
|
2319
|
+
};
|
2125
2320
|
|
2126
|
-
//
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2321
|
+
// Alignment box for the data label
|
2322
|
+
point.dlBox = {
|
2323
|
+
x: point.plotX - radius,
|
2324
|
+
y: point.plotY - radius,
|
2325
|
+
width: 2 * radius,
|
2326
|
+
height: 2 * radius
|
2327
|
+
};
|
2328
|
+
} else { // below zThreshold
|
2329
|
+
point.shapeArgs = point.plotY = point.dlBox = undefined; // #1691
|
2130
2330
|
}
|
2131
|
-
}
|
2331
|
+
}
|
2332
|
+
},
|
2132
2333
|
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2136
|
-
|
2334
|
+
/**
|
2335
|
+
* Get the series' symbol in the legend
|
2336
|
+
*
|
2337
|
+
* @param {Object} legend The legend object
|
2338
|
+
* @param {Object} item The series (this) or point
|
2339
|
+
*/
|
2340
|
+
drawLegendSymbol: function(legend, item) {
|
2341
|
+
var renderer = this.chart.renderer,
|
2342
|
+
radius = renderer.fontMetrics(legend.itemStyle.fontSize).f / 2;
|
2343
|
+
|
2344
|
+
item.legendSymbol = renderer.circle(
|
2345
|
+
radius,
|
2346
|
+
legend.baseline - radius,
|
2347
|
+
radius
|
2348
|
+
).attr({
|
2349
|
+
zIndex: 3
|
2350
|
+
}).add(item.legendGroup);
|
2351
|
+
item.legendSymbol.isMarker = true;
|
2352
|
+
|
2353
|
+
},
|
2354
|
+
|
2355
|
+
drawPoints: seriesTypes.column.prototype.drawPoints,
|
2356
|
+
alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
|
2357
|
+
buildKDTree: noop,
|
2358
|
+
applyZones: noop
|
2359
|
+
|
2360
|
+
// Point class
|
2361
|
+
}, {
|
2362
|
+
haloPath: function() {
|
2363
|
+
return Point.prototype.haloPath.call(this, this.shapeArgs.r + this.series.options.states.hover.halo.size);
|
2364
|
+
},
|
2365
|
+
ttBelow: false
|
2366
|
+
});
|
2137
2367
|
|
2138
2368
|
/**
|
2139
|
-
*
|
2369
|
+
* Add logic to pad each axis with the amount of pixels
|
2370
|
+
* necessary to avoid the bubbles to overflow.
|
2140
2371
|
*/
|
2141
|
-
|
2372
|
+
Axis.prototype.beforePadding = function() {
|
2373
|
+
var axis = this,
|
2374
|
+
axisLength = this.len,
|
2375
|
+
chart = this.chart,
|
2376
|
+
pxMin = 0,
|
2377
|
+
pxMax = axisLength,
|
2378
|
+
isXAxis = this.isXAxis,
|
2379
|
+
dataKey = isXAxis ? 'xData' : 'yData',
|
2380
|
+
min = this.min,
|
2381
|
+
extremes = {},
|
2382
|
+
smallestSize = Math.min(chart.plotWidth, chart.plotHeight),
|
2383
|
+
zMin = Number.MAX_VALUE,
|
2384
|
+
zMax = -Number.MAX_VALUE,
|
2385
|
+
range = this.max - min,
|
2386
|
+
transA = axisLength / range,
|
2387
|
+
activeSeries = [];
|
2142
2388
|
|
2143
|
-
|
2144
|
-
|
2145
|
-
point,
|
2146
|
-
radius,
|
2147
|
-
radii = this.radii;
|
2389
|
+
// Handle padding on the second pass, or on redraw
|
2390
|
+
each(this.series, function(series) {
|
2148
2391
|
|
2149
|
-
|
2150
|
-
|
2392
|
+
var seriesOptions = series.options,
|
2393
|
+
zData;
|
2151
2394
|
|
2152
|
-
|
2153
|
-
i = data.length;
|
2395
|
+
if (series.bubblePadding && (series.visible || !chart.options.chart.ignoreHiddenSeries)) {
|
2154
2396
|
|
2155
|
-
|
2156
|
-
|
2157
|
-
radius = radii ? radii[i] : 0; // #1737
|
2397
|
+
// Correction for #1673
|
2398
|
+
axis.allowZoomOutside = true;
|
2158
2399
|
|
2159
|
-
|
2160
|
-
|
2161
|
-
point.shapeType = 'circle';
|
2162
|
-
point.shapeArgs = {
|
2163
|
-
x: point.plotX,
|
2164
|
-
y: point.plotY,
|
2165
|
-
r: radius
|
2166
|
-
};
|
2400
|
+
// Cache it
|
2401
|
+
activeSeries.push(series);
|
2167
2402
|
|
2168
|
-
//
|
2169
|
-
point.dlBox = {
|
2170
|
-
x: point.plotX - radius,
|
2171
|
-
y: point.plotY - radius,
|
2172
|
-
width: 2 * radius,
|
2173
|
-
height: 2 * radius
|
2174
|
-
};
|
2175
|
-
} else { // below zThreshold or z = null
|
2176
|
-
point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691
|
2177
|
-
}
|
2178
|
-
}
|
2179
|
-
},
|
2403
|
+
if (isXAxis) { // because X axis is evaluated first
|
2180
2404
|
|
2181
|
-
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2185
|
-
* @param {Object} item The series (this) or point
|
2186
|
-
*/
|
2187
|
-
drawLegendSymbol: function (legend, item) {
|
2188
|
-
var renderer = this.chart.renderer,
|
2189
|
-
radius = renderer.fontMetrics(legend.itemStyle.fontSize).f / 2;
|
2190
|
-
|
2191
|
-
item.legendSymbol = renderer.circle(
|
2192
|
-
radius,
|
2193
|
-
legend.baseline - radius,
|
2194
|
-
radius
|
2195
|
-
).attr({
|
2196
|
-
zIndex: 3
|
2197
|
-
}).add(item.legendGroup);
|
2198
|
-
item.legendSymbol.isMarker = true;
|
2199
|
-
|
2200
|
-
},
|
2201
|
-
|
2202
|
-
drawPoints: seriesTypes.column.prototype.drawPoints,
|
2203
|
-
alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
|
2204
|
-
buildKDTree: noop,
|
2205
|
-
applyZones: noop
|
2206
|
-
});
|
2207
|
-
|
2208
|
-
/**
|
2209
|
-
* Add logic to pad each axis with the amount of pixels
|
2210
|
-
* necessary to avoid the bubbles to overflow.
|
2211
|
-
*/
|
2212
|
-
Axis.prototype.beforePadding = function () {
|
2213
|
-
var axis = this,
|
2214
|
-
axisLength = this.len,
|
2215
|
-
chart = this.chart,
|
2216
|
-
pxMin = 0,
|
2217
|
-
pxMax = axisLength,
|
2218
|
-
isXAxis = this.isXAxis,
|
2219
|
-
dataKey = isXAxis ? 'xData' : 'yData',
|
2220
|
-
min = this.min,
|
2221
|
-
extremes = {},
|
2222
|
-
smallestSize = math.min(chart.plotWidth, chart.plotHeight),
|
2223
|
-
zMin = Number.MAX_VALUE,
|
2224
|
-
zMax = -Number.MAX_VALUE,
|
2225
|
-
range = this.max - min,
|
2226
|
-
transA = axisLength / range,
|
2227
|
-
activeSeries = [];
|
2228
|
-
|
2229
|
-
// Handle padding on the second pass, or on redraw
|
2230
|
-
each(this.series, function (series) {
|
2231
|
-
|
2232
|
-
var seriesOptions = series.options,
|
2233
|
-
zData;
|
2234
|
-
|
2235
|
-
if (series.bubblePadding && (series.visible || !chart.options.chart.ignoreHiddenSeries)) {
|
2236
|
-
|
2237
|
-
// Correction for #1673
|
2238
|
-
axis.allowZoomOutside = true;
|
2239
|
-
|
2240
|
-
// Cache it
|
2241
|
-
activeSeries.push(series);
|
2242
|
-
|
2243
|
-
if (isXAxis) { // because X axis is evaluated first
|
2244
|
-
|
2245
|
-
// For each series, translate the size extremes to pixel values
|
2246
|
-
each(['minSize', 'maxSize'], function (prop) {
|
2247
|
-
var length = seriesOptions[prop],
|
2248
|
-
isPercent = /%$/.test(length);
|
2249
|
-
|
2250
|
-
length = pInt(length);
|
2251
|
-
extremes[prop] = isPercent ?
|
2252
|
-
smallestSize * length / 100 :
|
2253
|
-
length;
|
2405
|
+
// For each series, translate the size extremes to pixel values
|
2406
|
+
each(['minSize', 'maxSize'], function(prop) {
|
2407
|
+
var length = seriesOptions[prop],
|
2408
|
+
isPercent = /%$/.test(length);
|
2254
2409
|
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2410
|
+
length = pInt(length);
|
2411
|
+
extremes[prop] = isPercent ?
|
2412
|
+
smallestSize * length / 100 :
|
2413
|
+
length;
|
2414
|
+
|
2415
|
+
});
|
2416
|
+
series.minPxSize = extremes.minSize;
|
2417
|
+
series.maxPxSize = extremes.maxSize;
|
2418
|
+
|
2419
|
+
// Find the min and max Z
|
2420
|
+
zData = series.zData;
|
2421
|
+
if (zData.length) { // #1735
|
2422
|
+
zMin = pick(seriesOptions.zMin, Math.min(
|
2423
|
+
zMin,
|
2424
|
+
Math.max(
|
2425
|
+
arrayMin(zData),
|
2426
|
+
seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE
|
2427
|
+
)
|
2428
|
+
));
|
2429
|
+
zMax = pick(seriesOptions.zMax, Math.max(zMax, arrayMax(zData)));
|
2430
|
+
}
|
2270
2431
|
}
|
2271
2432
|
}
|
2272
|
-
}
|
2273
|
-
});
|
2274
|
-
|
2275
|
-
each(activeSeries, function (series) {
|
2433
|
+
});
|
2276
2434
|
|
2277
|
-
|
2278
|
-
i = data.length,
|
2279
|
-
radius;
|
2435
|
+
each(activeSeries, function(series) {
|
2280
2436
|
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2437
|
+
var data = series[dataKey],
|
2438
|
+
i = data.length,
|
2439
|
+
radius;
|
2284
2440
|
|
2285
|
-
|
2286
|
-
|
2287
|
-
if (isNumber(data[i]) && axis.dataMin <= data[i] && data[i] <= axis.dataMax) {
|
2288
|
-
radius = series.radii[i];
|
2289
|
-
pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
|
2290
|
-
pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
|
2291
|
-
}
|
2441
|
+
if (isXAxis) {
|
2442
|
+
series.getRadii(zMin, zMax, series.minPxSize, series.maxPxSize);
|
2292
2443
|
}
|
2293
|
-
}
|
2294
|
-
});
|
2295
|
-
|
2296
2444
|
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2445
|
+
if (range > 0) {
|
2446
|
+
while (i--) {
|
2447
|
+
if (isNumber(data[i]) && axis.dataMin <= data[i] && data[i] <= axis.dataMax) {
|
2448
|
+
radius = series.radii[i];
|
2449
|
+
pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
|
2450
|
+
pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
|
2451
|
+
}
|
2452
|
+
}
|
2303
2453
|
}
|
2304
2454
|
});
|
2305
|
-
}
|
2306
|
-
};
|
2307
2455
|
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2456
|
+
if (activeSeries.length && range > 0 && !this.isLog) {
|
2457
|
+
pxMax -= axisLength;
|
2458
|
+
transA *= (axisLength + pxMin - pxMax) / axisLength;
|
2459
|
+
each([
|
2460
|
+
['min', 'userMin', pxMin],
|
2461
|
+
['max', 'userMax', pxMax]
|
2462
|
+
], function(keys) {
|
2463
|
+
if (pick(axis.options[keys[0]], axis[keys[1]]) === undefined) {
|
2464
|
+
axis[keys[0]] += keys[2] / transA;
|
2465
|
+
}
|
2466
|
+
});
|
2467
|
+
}
|
2468
|
+
};
|
2469
|
+
|
2470
|
+
/* ****************************************************************************
|
2471
|
+
* End Bubble series code *
|
2472
|
+
*****************************************************************************/
|
2311
2473
|
|
2312
|
-
(
|
2474
|
+
}(Highcharts));
|
2475
|
+
(function(H) {
|
2476
|
+
/**
|
2477
|
+
* (c) 2010-2016 Torstein Honsi
|
2478
|
+
*
|
2479
|
+
* License: www.highcharts.com/license
|
2480
|
+
*/
|
2481
|
+
'use strict';
|
2313
2482
|
|
2314
2483
|
/**
|
2315
2484
|
* Extensions for polar charts. Additionally, much of the geometry required for polar charts is
|
@@ -2317,14 +2486,21 @@ var arrayMin = Highcharts.arrayMin,
|
|
2317
2486
|
*
|
2318
2487
|
*/
|
2319
2488
|
|
2320
|
-
var
|
2489
|
+
var each = H.each,
|
2490
|
+
pick = H.pick,
|
2491
|
+
Pointer = H.Pointer,
|
2492
|
+
Series = H.Series,
|
2493
|
+
seriesTypes = H.seriesTypes,
|
2494
|
+
wrap = H.wrap,
|
2495
|
+
|
2496
|
+
seriesProto = Series.prototype,
|
2321
2497
|
pointerProto = Pointer.prototype,
|
2322
2498
|
colProto;
|
2323
2499
|
|
2324
2500
|
/**
|
2325
2501
|
* Search a k-d tree by the point angle, used for shared tooltips in polar charts
|
2326
2502
|
*/
|
2327
|
-
seriesProto.searchPointByAngle = function
|
2503
|
+
seriesProto.searchPointByAngle = function(e) {
|
2328
2504
|
var series = this,
|
2329
2505
|
chart = series.chart,
|
2330
2506
|
xAxis = series.xAxis,
|
@@ -2342,7 +2518,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2342
2518
|
* Wrap the buildKDTree function so that it searches by angle (clientX) in case of shared tooltip,
|
2343
2519
|
* and by two dimensional distance in case of non-shared.
|
2344
2520
|
*/
|
2345
|
-
wrap(seriesProto, 'buildKDTree', function
|
2521
|
+
wrap(seriesProto, 'buildKDTree', function(proceed) {
|
2346
2522
|
if (this.chart.polar) {
|
2347
2523
|
if (this.kdByAngle) {
|
2348
2524
|
this.searchPoint = this.searchPointByAngle;
|
@@ -2357,7 +2533,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2357
2533
|
* Translate a point's plotX and plotY from the internal angle and radius measures to
|
2358
2534
|
* true plotX, plotY coordinates
|
2359
2535
|
*/
|
2360
|
-
seriesProto.toXY = function
|
2536
|
+
seriesProto.toXY = function(point) {
|
2361
2537
|
var xy,
|
2362
2538
|
chart = this.chart,
|
2363
2539
|
plotX = point.plotX,
|
@@ -2390,7 +2566,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2390
2566
|
/**
|
2391
2567
|
* Overridden method for calculating a spline from one point to the next
|
2392
2568
|
*/
|
2393
|
-
wrap(seriesTypes.spline.prototype, 'getPointSpline', function
|
2569
|
+
wrap(seriesTypes.spline.prototype, 'getPointSpline', function(proceed, segment, point, i) {
|
2394
2570
|
|
2395
2571
|
var ret,
|
2396
2572
|
smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;
|
@@ -2496,7 +2672,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2496
2672
|
* cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from
|
2497
2673
|
* center.
|
2498
2674
|
*/
|
2499
|
-
wrap(seriesProto, 'translate', function
|
2675
|
+
wrap(seriesProto, 'translate', function(proceed) {
|
2500
2676
|
var chart = this.chart,
|
2501
2677
|
points,
|
2502
2678
|
i;
|
@@ -2524,11 +2700,11 @@ var arrayMin = Highcharts.arrayMin,
|
|
2524
2700
|
* Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in
|
2525
2701
|
* line-like series.
|
2526
2702
|
*/
|
2527
|
-
wrap(seriesProto, 'getGraphPath', function
|
2703
|
+
wrap(seriesProto, 'getGraphPath', function(proceed, points) {
|
2528
2704
|
var series = this,
|
2529
2705
|
i,
|
2530
2706
|
firstValid;
|
2531
|
-
|
2707
|
+
|
2532
2708
|
// Connect the path
|
2533
2709
|
if (this.chart.polar) {
|
2534
2710
|
points = points || this.points;
|
@@ -2546,7 +2722,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2546
2722
|
}
|
2547
2723
|
|
2548
2724
|
// For area charts, pseudo points are added to the graph, now we need to translate these
|
2549
|
-
each(points, function
|
2725
|
+
each(points, function(point) {
|
2550
2726
|
if (point.polarPlotY === undefined) {
|
2551
2727
|
series.toXY(point);
|
2552
2728
|
}
|
@@ -2555,7 +2731,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2555
2731
|
|
2556
2732
|
// Run uber method
|
2557
2733
|
return proceed.apply(this, [].slice.call(arguments, 1));
|
2558
|
-
|
2734
|
+
|
2559
2735
|
});
|
2560
2736
|
|
2561
2737
|
|
@@ -2597,7 +2773,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2597
2773
|
markerGroup.attr(attribs);
|
2598
2774
|
}
|
2599
2775
|
|
2600
|
-
|
2776
|
+
// Run the animation
|
2601
2777
|
} else {
|
2602
2778
|
attribs = {
|
2603
2779
|
translateX: plotLeft,
|
@@ -2615,7 +2791,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2615
2791
|
}
|
2616
2792
|
}
|
2617
2793
|
|
2618
|
-
|
2794
|
+
// For non-polar charts, revert to the basic animation
|
2619
2795
|
} else {
|
2620
2796
|
proceed.call(this, init);
|
2621
2797
|
}
|
@@ -2629,16 +2805,15 @@ var arrayMin = Highcharts.arrayMin,
|
|
2629
2805
|
|
2630
2806
|
colProto = seriesTypes.column.prototype;
|
2631
2807
|
|
2632
|
-
colProto.polarArc = function
|
2808
|
+
colProto.polarArc = function(low, high, start, end) {
|
2633
2809
|
var center = this.xAxis.center,
|
2634
2810
|
len = this.yAxis.len;
|
2635
|
-
|
2811
|
+
|
2636
2812
|
return this.chart.renderer.symbols.arc(
|
2637
2813
|
center[0],
|
2638
2814
|
center[1],
|
2639
2815
|
len - high,
|
2640
|
-
null,
|
2641
|
-
{
|
2816
|
+
null, {
|
2642
2817
|
start: start,
|
2643
2818
|
end: end,
|
2644
2819
|
innerR: len - pick(low, len)
|
@@ -2647,15 +2822,15 @@ var arrayMin = Highcharts.arrayMin,
|
|
2647
2822
|
};
|
2648
2823
|
|
2649
2824
|
/**
|
2650
|
-
|
2651
|
-
|
2825
|
+
* Define the animate method for columnseries
|
2826
|
+
*/
|
2652
2827
|
wrap(colProto, 'animate', polarAnimate);
|
2653
2828
|
|
2654
2829
|
|
2655
2830
|
/**
|
2656
2831
|
* Extend the column prototype's translate method
|
2657
2832
|
*/
|
2658
|
-
wrap(colProto, 'translate', function
|
2833
|
+
wrap(colProto, 'translate', function(proceed) {
|
2659
2834
|
|
2660
2835
|
var xAxis = this.xAxis,
|
2661
2836
|
startAngleRad = xAxis.startAngleRad,
|
@@ -2692,7 +2867,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2692
2867
|
/**
|
2693
2868
|
* Align column data labels outside the columns. #1199.
|
2694
2869
|
*/
|
2695
|
-
wrap(colProto, 'alignDataLabel', function
|
2870
|
+
wrap(colProto, 'alignDataLabel', function(proceed, point, dataLabel, options, alignTo, isNew) {
|
2696
2871
|
|
2697
2872
|
if (this.chart.polar) {
|
2698
2873
|
var angle = point.rectPlotX / Math.PI * 180,
|
@@ -2732,7 +2907,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2732
2907
|
/**
|
2733
2908
|
* Extend getCoordinates to prepare for polar axis values
|
2734
2909
|
*/
|
2735
|
-
wrap(pointerProto, 'getCoordinates', function
|
2910
|
+
wrap(pointerProto, 'getCoordinates', function(proceed, e) {
|
2736
2911
|
var chart = this.chart,
|
2737
2912
|
ret = {
|
2738
2913
|
xAxis: [],
|
@@ -2741,7 +2916,7 @@ var arrayMin = Highcharts.arrayMin,
|
|
2741
2916
|
|
2742
2917
|
if (chart.polar) {
|
2743
2918
|
|
2744
|
-
each(chart.axes, function
|
2919
|
+
each(chart.axes, function(axis) {
|
2745
2920
|
var isXAxis = axis.isXAxis,
|
2746
2921
|
center = axis.center,
|
2747
2922
|
x = e.chartX - center[0] - chart.plotLeft,
|
@@ -2751,8 +2926,8 @@ var arrayMin = Highcharts.arrayMin,
|
|
2751
2926
|
axis: axis,
|
2752
2927
|
value: axis.translate(
|
2753
2928
|
isXAxis ?
|
2754
|
-
|
2755
|
-
|
2929
|
+
Math.PI - Math.atan2(x, y) : // angle
|
2930
|
+
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center
|
2756
2931
|
true
|
2757
2932
|
)
|
2758
2933
|
});
|
@@ -2765,6 +2940,5 @@ var arrayMin = Highcharts.arrayMin,
|
|
2765
2940
|
return ret;
|
2766
2941
|
});
|
2767
2942
|
|
2768
|
-
}());
|
2769
|
-
|
2943
|
+
}(Highcharts));
|
2770
2944
|
}));
|