highcharts-rails 3.0.3 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ /*
2
+ Highcharts JS v3.0.5 (2013-08-23)
3
+
4
+ Standalone Highcharts Framework
5
+
6
+ License: MIT License
7
+ */
8
+ var HighchartsAdapter=function(){function n(c){function a(a,b,d){a.removeEventListener(b,d,!1)}function d(a,b,d){d=a.HCProxiedMethods[d.toString()];a.detachEvent("on"+b,d)}function b(b,c){var g=b.HCEvents,i,h,l,f;if(b.removeEventListener)i=a;else if(b.attachEvent)i=d;else return;c?(h={},h[c]=!0):h=g;for(f in h)if(g[f])for(l=g[f].length;l--;)i(b,f,g[f][l])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(b,a){var d=this,c=this.HCEvents,h;if(d.addEventListener)d.addEventListener(b,
9
+ a,!1);else if(d.attachEvent){h=function(b){a.call(d,b)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[a.toString()]=h;d.attachEvent("on"+b,h)}c[b]===q&&(c[b]=[]);c[b].push(a)},unbind:function(c,k){var g,i;c?(g=this.HCEvents[c]||[],k?(i=HighchartsAdapter.inArray(k,g),i>-1&&(g.splice(i,1),this.HCEvents[c]=g),this.removeEventListener?a(this,c,k):this.attachEvent&&d(this,c,k)):(b(this,c),this.HCEvents[c]=[])):(b(this),this.HCEvents={})},trigger:function(b,a){var d=this.HCEvents[b]||
10
+ [],c=d.length,h,f;for(h=function(){a.defaultPrevented=!0};c--;){f=d[c];if(a.stopped)break;a.preventDefault=h;a.target=this;f.call(this,a)===!1&&a.preventDefault()}}});return c}var q,f=document,o=[],j=[],p,m;Math.easeInOutSine=function(c,a,d,b){return-d/2*(Math.cos(Math.PI*c/b)-1)+a};return{init:function(c){if(!f.defaultView)this._getStyle=function(a,d){var b;return a.style[d]?a.style[d]:(d==="opacity"&&(d="filter"),b=a.currentStyle[d.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()})],d==="filter"&&
11
+ (b=b.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),b===""?1:b)},this.adapterRun=function(a,d){var b={width:"clientWidth",height:"clientHeight"}[d];if(b)return a.style.zoom=1,a[b]-2*parseInt(HighchartsAdapter._getStyle(a,"padding"),10)};if(!Array.prototype.forEach)this.each=function(a,d){for(var b=0,c=a.length;b<c;b++)if(d.call(a[b],a[b],b,a)===!1)return b};if(!Array.prototype.indexOf)this.inArray=function(a,d){var b,c=0;if(d)for(b=d.length;c<b;c++)if(d[c]===a)return c;return-1};
12
+ if(!Array.prototype.filter)this.grep=function(a,d){for(var b=[],c=0,f=a.length;c<f;c++)d(a[c],c)&&b.push(a[c]);return b};m=function(a,c,b){this.options=c;this.elem=a;this.prop=b};m.prototype={update:function(){var a;a=this.paths;var d=this.elem,b=d.element;a&&b?d.attr("d",c.step(a[0],a[1],this.now,this.toD)):d.attr?b&&d.attr(this.prop,this.now):(a={},a[d]=this.now+this.unit,Highcharts.css(d,a));this.options.step&&this.options.step.call(this.elem,this.now,this)},custom:function(a,c,b){var e=this,f=
13
+ function(a){return e.step(a)},g;this.startTime=+new Date;this.start=a;this.end=c;this.unit=b;this.now=this.start;this.pos=this.state=0;f.elem=this.elem;f()&&j.push(f)===1&&(p=setInterval(function(){for(g=0;g<j.length;g++)j[g]()||j.splice(g--,1);j.length||clearInterval(p)},13))},step:function(a){var c=+new Date,b;b=this.options;var e;if(this.elem.stopAnimation)b=!1;else if(a||c>=b.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();a=this.options.curAnim[this.prop]=!0;for(e in b.curAnim)b.curAnim[e]!==
14
+ !0&&(a=!1);a&&b.complete&&b.complete.call(this.elem);b=!1}else e=c-this.startTime,this.state=e/b.duration,this.pos=b.easing(e,0,1,b.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),b=!0;return b}};this.animate=function(a,d,b){var e,f="",g,i,h;a.stopAnimation=!1;if(typeof b!=="object"||b===null)e=arguments,b={duration:e[2],easing:e[3],complete:e[4]};if(typeof b.duration!=="number")b.duration=400;b.easing=Math[b.easing]||Math.easeInOutSine;b.curAnim=Highcharts.extend({},d);
15
+ for(h in d)i=new m(a,b,h),g=null,h==="d"?(i.paths=c.init(a,a.d,d.d),i.toD=d.d,e=0,g=1):a.attr?e=a.attr(h):(e=parseFloat(this._getStyle(a,h))||0,h!=="opacity"&&(f="px")),g||(g=parseFloat(d[h])),i.custom(e,g,f)}},_getStyle:function(c,a){return window.getComputedStyle(c).getPropertyValue(a)},getScript:function(c,a){var d=f.getElementsByTagName("head")[0],b=f.createElement("script");b.type="text/javascript";b.src=c;b.onload=a;d.appendChild(b)},inArray:function(c,a){return a.indexOf?a.indexOf(c):o.indexOf.call(a,
16
+ c)},adapterRun:function(c,a){return parseInt(HighchartsAdapter._getStyle(c,a),10)},grep:function(c,a){return o.filter.call(c,a)},map:function(c,a){for(var d=[],b=0,e=c.length;b<e;b++)d[b]=a.call(c[b],c[b],b,c);return d},offset:function(c){for(var a=0,d=0;c;)a+=c.offsetLeft,d+=c.offsetTop,c=c.offsetParent;return{left:a,top:d}},addEvent:function(c,a,d){n(c).bind(a,d)},removeEvent:function(c,a,d){n(c).unbind(a,d)},fireEvent:function(c,a,d,b){var e;f.createEvent&&(c.dispatchEvent||c.fireEvent)?(e=f.createEvent("Events"),
17
+ e.initEvent(a,!0,!0),e.target=c,Highcharts.extend(e,d),c.dispatchEvent?c.dispatchEvent(e):c.fireEvent(a,e)):c.HCExtended===!0&&(d=d||{},c.trigger(a,d));d&&d.defaultPrevented&&(b=null);b&&b(d)},washMouseEvent:function(c){return c},stop:function(c){c.stopAnimation=!0},each:function(c,a){return Array.prototype.forEach.call(c,a)}}}();
@@ -1,2426 +1,50 @@
1
- // ==ClosureCompiler==
2
- // @compilation_level SIMPLE_OPTIMIZATIONS
3
-
4
- /**
5
- * @license Highcharts JS v3.0.3 (2013-07-31)
6
- *
7
- * (c) 2009-2013 Torstein Hønsi
8
- *
9
- * License: www.highcharts.com/license
10
- */
11
-
12
- // JSLint options:
13
- /*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
14
-
15
- (function (Highcharts, UNDEFINED) {
16
- var arrayMin = Highcharts.arrayMin,
17
- arrayMax = Highcharts.arrayMax,
18
- each = Highcharts.each,
19
- extend = Highcharts.extend,
20
- merge = Highcharts.merge,
21
- map = Highcharts.map,
22
- pick = Highcharts.pick,
23
- pInt = Highcharts.pInt,
24
- defaultPlotOptions = Highcharts.getOptions().plotOptions,
25
- seriesTypes = Highcharts.seriesTypes,
26
- extendClass = Highcharts.extendClass,
27
- splat = Highcharts.splat,
28
- wrap = Highcharts.wrap,
29
- Axis = Highcharts.Axis,
30
- Tick = Highcharts.Tick,
31
- Series = Highcharts.Series,
32
- colProto = seriesTypes.column.prototype,
33
- math = Math,
34
- mathRound = math.round,
35
- mathFloor = math.floor,
36
- mathMax = math.max,
37
- noop = function () {};/**
38
- * The Pane object allows options that are common to a set of X and Y axes.
39
- *
40
- * In the future, this can be extended to basic Highcharts and Highstock.
41
- */
42
- function Pane(options, chart, firstAxis) {
43
- this.init.call(this, options, chart, firstAxis);
44
- }
45
-
46
- // Extend the Pane prototype
47
- extend(Pane.prototype, {
48
-
49
- /**
50
- * Initiate the Pane object
51
- */
52
- init: function (options, chart, firstAxis) {
53
- var pane = this,
54
- backgroundOption,
55
- defaultOptions = pane.defaultOptions;
56
-
57
- pane.chart = chart;
58
-
59
- // Set options
60
- if (chart.angular) { // gauges
61
- defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions
62
- }
63
- pane.options = options = merge(defaultOptions, options);
64
-
65
- backgroundOption = options.background;
66
-
67
- // To avoid having weighty logic to place, update and remove the backgrounds,
68
- // push them to the first axis' plot bands and borrow the existing logic there.
69
- if (backgroundOption) {
70
- each([].concat(splat(backgroundOption)).reverse(), function (config) {
71
- var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)
72
- config = merge(pane.defaultBackgroundOptions, config);
73
- if (backgroundColor) {
74
- config.backgroundColor = backgroundColor;
75
- }
76
- config.color = config.backgroundColor; // due to naming in plotBands
77
- firstAxis.options.plotBands.unshift(config);
78
- });
79
- }
80
- },
81
-
82
- /**
83
- * The default options object
84
- */
85
- defaultOptions: {
86
- // background: {conditional},
87
- center: ['50%', '50%'],
88
- size: '85%',
89
- startAngle: 0
90
- //endAngle: startAngle + 360
91
- },
92
-
93
- /**
94
- * The default background options
95
- */
96
- defaultBackgroundOptions: {
97
- shape: 'circle',
98
- borderWidth: 1,
99
- borderColor: 'silver',
100
- backgroundColor: {
101
- linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
102
- stops: [
103
- [0, '#FFF'],
104
- [1, '#DDD']
105
- ]
106
- },
107
- from: Number.MIN_VALUE, // corrected to axis min
108
- innerRadius: 0,
109
- to: Number.MAX_VALUE, // corrected to axis max
110
- outerRadius: '105%'
111
- }
112
-
113
- });
114
- var axisProto = Axis.prototype,
115
- tickProto = Tick.prototype;
116
-
117
- /**
118
- * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
119
- */
120
- var hiddenAxisMixin = {
121
- getOffset: noop,
122
- redraw: function () {
123
- this.isDirty = false; // prevent setting Y axis dirty
124
- },
125
- render: function () {
126
- this.isDirty = false; // prevent setting Y axis dirty
127
- },
128
- setScale: noop,
129
- setCategories: noop,
130
- setTitle: noop
131
- };
132
-
133
- /**
134
- * Augmented methods for the value axis
135
- */
136
- /*jslint unparam: true*/
137
- var radialAxisMixin = {
138
- isRadial: true,
139
-
140
- /**
141
- * The default options extend defaultYAxisOptions
142
- */
143
- defaultRadialGaugeOptions: {
144
- labels: {
145
- align: 'center',
146
- x: 0,
147
- y: null // auto
148
- },
149
- minorGridLineWidth: 0,
150
- minorTickInterval: 'auto',
151
- minorTickLength: 10,
152
- minorTickPosition: 'inside',
153
- minorTickWidth: 1,
154
- plotBands: [],
155
- tickLength: 10,
156
- tickPosition: 'inside',
157
- tickWidth: 2,
158
- title: {
159
- rotation: 0
160
- },
161
- zIndex: 2 // behind dials, points in the series group
162
- },
163
-
164
- // Circular axis around the perimeter of a polar chart
165
- defaultRadialXOptions: {
166
- gridLineWidth: 1, // spokes
167
- labels: {
168
- align: null, // auto
169
- distance: 15,
170
- x: 0,
171
- y: null // auto
172
- },
173
- maxPadding: 0,
174
- minPadding: 0,
175
- plotBands: [],
176
- showLastLabel: false,
177
- tickLength: 0
178
- },
179
-
180
- // Radial axis, like a spoke in a polar chart
181
- defaultRadialYOptions: {
182
- gridLineInterpolation: 'circle',
183
- labels: {
184
- align: 'right',
185
- x: -3,
186
- y: -2
187
- },
188
- plotBands: [],
189
- showLastLabel: false,
190
- title: {
191
- x: 4,
192
- text: null,
193
- rotation: 90
194
- }
195
- },
196
-
197
- /**
198
- * Merge and set options
199
- */
200
- setOptions: function (userOptions) {
201
-
202
- this.options = merge(
203
- this.defaultOptions,
204
- this.defaultRadialOptions,
205
- userOptions
206
- );
207
-
208
- },
209
-
210
- /**
211
- * Wrap the getOffset method to return zero offset for title or labels in a radial
212
- * axis
213
- */
214
- getOffset: function () {
215
- // Call the Axis prototype method (the method we're in now is on the instance)
216
- axisProto.getOffset.call(this);
217
-
218
- // Title or label offsets are not counted
219
- this.chart.axisOffset[this.side] = 0;
220
-
221
- // Set the center array
222
- this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);
223
- },
224
-
225
-
226
- /**
227
- * Get the path for the axis line. This method is also referenced in the getPlotLinePath
228
- * method.
229
- */
230
- getLinePath: function (lineWidth, radius) {
231
- var center = this.center;
232
- radius = pick(radius, center[2] / 2 - this.offset);
233
-
234
- return this.chart.renderer.symbols.arc(
235
- this.left + center[0],
236
- this.top + center[1],
237
- radius,
238
- radius,
239
- {
240
- start: this.startAngleRad,
241
- end: this.endAngleRad,
242
- open: true,
243
- innerR: 0
244
- }
245
- );
246
- },
247
-
248
- /**
249
- * Override setAxisTranslation by setting the translation to the difference
250
- * in rotation. This allows the translate method to return angle for
251
- * any given value.
252
- */
253
- setAxisTranslation: function () {
254
-
255
- // Call uber method
256
- axisProto.setAxisTranslation.call(this);
257
-
258
- // Set transA and minPixelPadding
259
- if (this.center) { // it's not defined the first time
260
- if (this.isCircular) {
261
-
262
- this.transA = (this.endAngleRad - this.startAngleRad) /
263
- ((this.max - this.min) || 1);
264
-
265
-
266
- } else {
267
- this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
268
- }
269
-
270
- if (this.isXAxis) {
271
- this.minPixelPadding = this.transA * this.minPointOffset +
272
- (this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
273
- }
274
- }
275
- },
276
-
277
- /**
278
- * In case of auto connect, add one closestPointRange to the max value right before
279
- * tickPositions are computed, so that ticks will extend passed the real max.
280
- */
281
- beforeSetTickPositions: function () {
282
- if (this.autoConnect) {
283
- this.max += (this.categories && 1) || this.pointRange || this.closestPointRange; // #1197
284
- }
285
- },
286
-
287
- /**
288
- * Override the setAxisSize method to use the arc's circumference as length. This
289
- * allows tickPixelInterval to apply to pixel lengths along the perimeter
290
- */
291
- setAxisSize: function () {
292
-
293
- axisProto.setAxisSize.call(this);
294
-
295
- if (this.center) { // it's not defined the first time
296
- this.len = this.width = this.height = this.isCircular ?
297
- this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
298
- this.center[2] / 2;
299
- }
300
- },
301
-
302
- /**
303
- * Returns the x, y coordinate of a point given by a value and a pixel distance
304
- * from center
305
- */
306
- getPosition: function (value, length) {
307
- if (!this.isCircular) {
308
- length = this.translate(value);
309
- value = this.min;
310
- }
311
-
312
- return this.postTranslate(
313
- this.translate(value),
314
- pick(length, this.center[2] / 2) - this.offset
315
- );
316
- },
317
-
318
- /**
319
- * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates.
320
- */
321
- postTranslate: function (angle, radius) {
322
-
323
- var chart = this.chart,
324
- center = this.center;
325
-
326
- angle = this.startAngleRad + angle;
327
-
328
- return {
329
- x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
330
- y: chart.plotTop + center[1] + Math.sin(angle) * radius
331
- };
332
-
333
- },
334
-
335
- /**
336
- * Find the path for plot bands along the radial axis
337
- */
338
- getPlotBandPath: function (from, to, options) {
339
- var center = this.center,
340
- startAngleRad = this.startAngleRad,
341
- fullRadius = center[2] / 2,
342
- radii = [
343
- pick(options.outerRadius, '100%'),
344
- options.innerRadius,
345
- pick(options.thickness, 10)
346
- ],
347
- percentRegex = /%$/,
348
- start,
349
- end,
350
- open,
351
- isCircular = this.isCircular, // X axis in a polar chart
352
- ret;
353
-
354
- // Polygonal plot bands
355
- if (this.options.gridLineInterpolation === 'polygon') {
356
- ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
357
-
358
- // Circular grid bands
359
- } else {
360
-
361
- // Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
362
- if (!isCircular) {
363
- radii[0] = this.translate(from);
364
- radii[1] = this.translate(to);
365
- }
366
-
367
- // Convert percentages to pixel values
368
- radii = map(radii, function (radius) {
369
- if (percentRegex.test(radius)) {
370
- radius = (pInt(radius, 10) * fullRadius) / 100;
371
- }
372
- return radius;
373
- });
374
-
375
- // Handle full circle
376
- if (options.shape === 'circle' || !isCircular) {
377
- start = -Math.PI / 2;
378
- end = Math.PI * 1.5;
379
- open = true;
380
- } else {
381
- start = startAngleRad + this.translate(from);
382
- end = startAngleRad + this.translate(to);
383
- }
384
-
385
-
386
- ret = this.chart.renderer.symbols.arc(
387
- this.left + center[0],
388
- this.top + center[1],
389
- radii[0],
390
- radii[0],
391
- {
392
- start: start,
393
- end: end,
394
- innerR: pick(radii[1], radii[0] - radii[2]),
395
- open: open
396
- }
397
- );
398
- }
399
-
400
- return ret;
401
- },
402
-
403
- /**
404
- * Find the path for plot lines perpendicular to the radial axis.
405
- */
406
- getPlotLinePath: function (value, reverse) {
407
- var axis = this,
408
- center = axis.center,
409
- chart = axis.chart,
410
- end = axis.getPosition(value),
411
- xAxis,
412
- xy,
413
- tickPositions,
414
- ret;
415
-
416
- // Spokes
417
- if (axis.isCircular) {
418
- ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
419
-
420
- // Concentric circles
421
- } else if (axis.options.gridLineInterpolation === 'circle') {
422
- value = axis.translate(value);
423
- if (value) { // a value of 0 is in the center
424
- ret = axis.getLinePath(0, value);
425
- }
426
- // Concentric polygons
427
- } else {
428
- xAxis = chart.xAxis[0];
429
- ret = [];
430
- value = axis.translate(value);
431
- tickPositions = xAxis.tickPositions;
432
- if (xAxis.autoConnect) {
433
- tickPositions = tickPositions.concat([tickPositions[0]]);
434
- }
435
- // Reverse the positions for concatenation of polygonal plot bands
436
- if (reverse) {
437
- tickPositions = [].concat(tickPositions).reverse();
438
- }
439
-
440
- each(tickPositions, function (pos, i) {
441
- xy = xAxis.getPosition(pos, value);
442
- ret.push(i ? 'L' : 'M', xy.x, xy.y);
443
- });
444
-
445
- }
446
- return ret;
447
- },
448
-
449
- /**
450
- * Find the position for the axis title, by default inside the gauge
451
- */
452
- getTitlePosition: function () {
453
- var center = this.center,
454
- chart = this.chart,
455
- titleOptions = this.options.title;
456
-
457
- return {
458
- x: chart.plotLeft + center[0] + (titleOptions.x || 0),
459
- y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] *
460
- center[2]) + (titleOptions.y || 0)
461
- };
462
- }
463
-
464
- };
465
- /*jslint unparam: false*/
466
-
467
- /**
468
- * Override axisProto.init to mix in special axis instance functions and function overrides
469
- */
470
- wrap(axisProto, 'init', function (proceed, chart, userOptions) {
471
- var axis = this,
472
- angular = chart.angular,
473
- polar = chart.polar,
474
- isX = userOptions.isX,
475
- isHidden = angular && isX,
476
- isCircular,
477
- startAngleRad,
478
- endAngleRad,
479
- options,
480
- chartOptions = chart.options,
481
- paneIndex = userOptions.pane || 0,
482
- pane,
483
- paneOptions;
484
-
485
- // Before prototype.init
486
- if (angular) {
487
- extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
488
- isCircular = !isX;
489
- if (isCircular) {
490
- this.defaultRadialOptions = this.defaultRadialGaugeOptions;
491
- }
492
-
493
- } else if (polar) {
494
- //extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);
495
- extend(this, radialAxisMixin);
496
- isCircular = isX;
497
- this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
498
-
499
- }
500
-
501
- // Run prototype.init
502
- proceed.call(this, chart, userOptions);
503
-
504
- if (!isHidden && (angular || polar)) {
505
- options = this.options;
506
-
507
- // Create the pane and set the pane options.
508
- if (!chart.panes) {
509
- chart.panes = [];
510
- }
511
- this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
512
- splat(chartOptions.pane)[paneIndex],
513
- chart,
514
- axis
515
- );
516
- paneOptions = pane.options;
517
-
518
-
519
- // Disable certain features on angular and polar axes
520
- chart.inverted = false;
521
- chartOptions.chart.zoomType = null;
522
-
523
- // Start and end angle options are
524
- // given in degrees relative to top, while internal computations are
525
- // in radians relative to right (like SVG).
526
- this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
527
- this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180;
528
- this.offset = options.offset || 0;
529
-
530
- this.isCircular = isCircular;
531
-
532
- // Automatically connect grid lines?
533
- if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {
534
- this.autoConnect = true;
535
- }
536
- }
537
-
538
- });
539
-
540
- /**
541
- * Add special cases within the Tick class' methods for radial axes.
542
- */
543
- wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
544
- var axis = this.axis;
545
-
546
- return axis.getPosition ?
547
- axis.getPosition(pos) :
548
- proceed.call(this, horiz, pos, tickmarkOffset, old);
549
- });
550
-
551
- /**
552
- * Wrap the getLabelPosition function to find the center position of the label
553
- * based on the distance option
554
- */
555
- wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
556
- var axis = this.axis,
557
- optionsY = labelOptions.y,
558
- ret,
559
- align = labelOptions.align,
560
- angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
561
-
562
- if (axis.isRadial) {
563
- ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
564
-
565
- // Automatically rotated
566
- if (labelOptions.rotation === 'auto') {
567
- label.attr({
568
- rotation: angle
569
- });
570
-
571
- // Vertically centered
572
- } else if (optionsY === null) {
573
- optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
574
-
575
- }
576
-
577
- // Automatic alignment
578
- if (align === null) {
579
- if (axis.isCircular) {
580
- if (angle > 20 && angle < 160) {
581
- align = 'left'; // right hemisphere
582
- } else if (angle > 200 && angle < 340) {
583
- align = 'right'; // left hemisphere
584
- } else {
585
- align = 'center'; // top or bottom
586
- }
587
- } else {
588
- align = 'center';
589
- }
590
- label.attr({
591
- align: align
592
- });
593
- }
594
-
595
- ret.x += labelOptions.x;
596
- ret.y += optionsY;
597
-
598
- } else {
599
- ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
600
- }
601
- return ret;
602
- });
603
-
604
- /**
605
- * Wrap the getMarkPath function to return the path of the radial marker
606
- */
607
- wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
608
- var axis = this.axis,
609
- endPoint,
610
- ret;
611
-
612
- if (axis.isRadial) {
613
- endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
614
- ret = [
615
- 'M',
616
- x,
617
- y,
618
- 'L',
619
- endPoint.x,
620
- endPoint.y
621
- ];
622
- } else {
623
- ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
624
- }
625
- return ret;
626
- });/*
627
- * The AreaRangeSeries class
628
- *
629
- */
630
-
631
- /**
632
- * Extend the default options with map options
633
- */
634
- defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
635
- lineWidth: 1,
636
- marker: null,
637
- threshold: null,
638
- tooltip: {
639
- pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'
640
- },
641
- trackByArea: true,
642
- dataLabels: {
643
- verticalAlign: null,
644
- xLow: 0,
645
- xHigh: 0,
646
- yLow: 0,
647
- yHigh: 0
648
- }
649
- });
650
-
651
- /**
652
- * Add the series type
653
- */
654
- seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {
655
- type: 'arearange',
656
- pointArrayMap: ['low', 'high'],
657
- toYData: function (point) {
658
- return [point.low, point.high];
659
- },
660
- pointValKey: 'low',
661
-
662
- /**
663
- * Extend getSegments to force null points if the higher value is null. #1703.
664
- */
665
- getSegments: function () {
666
- var series = this;
667
-
668
- each(series.points, function (point) {
669
- if (!series.options.connectNulls && (point.low === null || point.high === null)) {
670
- point.y = null;
671
- } else if (point.low === null && point.high !== null) {
672
- point.y = point.high;
673
- }
674
- });
675
- Series.prototype.getSegments.call(this);
676
- },
677
-
678
- /**
679
- * Translate data points from raw values x and y to plotX and plotY
680
- */
681
- translate: function () {
682
- var series = this,
683
- yAxis = series.yAxis;
684
-
685
- seriesTypes.area.prototype.translate.apply(series);
686
-
687
- // Set plotLow and plotHigh
688
- each(series.points, function (point) {
689
-
690
- var low = point.low,
691
- high = point.high,
692
- plotY = point.plotY;
693
-
694
- if (high === null && low === null) {
695
- point.y = null;
696
- } else if (low === null) {
697
- point.plotLow = point.plotY = null;
698
- point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
699
- } else if (high === null) {
700
- point.plotLow = plotY;
701
- point.plotHigh = null;
702
- } else {
703
- point.plotLow = plotY;
704
- point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
705
- }
706
- });
707
- },
708
-
709
- /**
710
- * Extend the line series' getSegmentPath method by applying the segment
711
- * path to both lower and higher values of the range
712
- */
713
- getSegmentPath: function (segment) {
714
-
715
- var lowSegment,
716
- highSegment = [],
717
- i = segment.length,
718
- baseGetSegmentPath = Series.prototype.getSegmentPath,
719
- point,
720
- linePath,
721
- lowerPath,
722
- options = this.options,
723
- step = options.step,
724
- higherPath;
725
-
726
- // Remove nulls from low segment
727
- lowSegment = HighchartsAdapter.grep(segment, function (point) {
728
- return point.plotLow !== null;
729
- });
730
-
731
- // Make a segment with plotX and plotY for the top values
732
- while (i--) {
733
- point = segment[i];
734
- if (point.plotHigh !== null) {
735
- highSegment.push({
736
- plotX: point.plotX,
737
- plotY: point.plotHigh
738
- });
739
- }
740
- }
741
-
742
- // Get the paths
743
- lowerPath = baseGetSegmentPath.call(this, lowSegment);
744
- if (step) {
745
- if (step === true) {
746
- step = 'left';
747
- }
748
- options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath
749
- }
750
- higherPath = baseGetSegmentPath.call(this, highSegment);
751
- options.step = step;
752
-
753
- // Create a line on both top and bottom of the range
754
- linePath = [].concat(lowerPath, higherPath);
755
-
756
- // For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
757
- higherPath[0] = 'L'; // this probably doesn't work for spline
758
- this.areaPath = this.areaPath.concat(lowerPath, higherPath);
759
-
760
- return linePath;
761
- },
762
-
763
- /**
764
- * Extend the basic drawDataLabels method by running it for both lower and higher
765
- * values.
766
- */
767
- drawDataLabels: function () {
768
-
769
- var data = this.data,
770
- length = data.length,
771
- i,
772
- originalDataLabels = [],
773
- seriesProto = Series.prototype,
774
- dataLabelOptions = this.options.dataLabels,
775
- point,
776
- inverted = this.chart.inverted;
777
-
778
- if (dataLabelOptions.enabled || this._hasPointLabels) {
779
-
780
- // Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
781
- i = length;
782
- while (i--) {
783
- point = data[i];
784
-
785
- // Set preliminary values
786
- point.y = point.high;
787
- point.plotY = point.plotHigh;
788
-
789
- // Store original data labels and set preliminary label objects to be picked up
790
- // in the uber method
791
- originalDataLabels[i] = point.dataLabel;
792
- point.dataLabel = point.dataLabelUpper;
793
-
794
- // Set the default offset
795
- point.below = false;
796
- if (inverted) {
797
- dataLabelOptions.align = 'left';
798
- dataLabelOptions.x = dataLabelOptions.xHigh;
799
- } else {
800
- dataLabelOptions.y = dataLabelOptions.yHigh;
801
- }
802
- }
803
- seriesProto.drawDataLabels.apply(this, arguments); // #1209
804
-
805
- // Step 2: reorganize and handle data labels for the lower values
806
- i = length;
807
- while (i--) {
808
- point = data[i];
809
-
810
- // Move the generated labels from step 1, and reassign the original data labels
811
- point.dataLabelUpper = point.dataLabel;
812
- point.dataLabel = originalDataLabels[i];
813
-
814
- // Reset values
815
- point.y = point.low;
816
- point.plotY = point.plotLow;
817
-
818
- // Set the default offset
819
- point.below = true;
820
- if (inverted) {
821
- dataLabelOptions.align = 'right';
822
- dataLabelOptions.x = dataLabelOptions.xLow;
823
- } else {
824
- dataLabelOptions.y = dataLabelOptions.yLow;
825
- }
826
- }
827
- seriesProto.drawDataLabels.apply(this, arguments);
828
- }
829
-
830
- },
831
-
832
- alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
833
-
834
- getSymbol: seriesTypes.column.prototype.getSymbol,
835
-
836
- drawPoints: noop
837
- });/**
838
- * The AreaSplineRangeSeries class
839
- */
840
-
841
- defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);
842
-
843
- /**
844
- * AreaSplineRangeSeries object
845
- */
846
- seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
847
- type: 'areasplinerange',
848
- getPointSpline: seriesTypes.spline.prototype.getPointSpline
849
- });/**
850
- * The ColumnRangeSeries class
851
- */
852
- defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
853
- lineWidth: 1,
854
- pointRange: null
855
- });
856
-
857
- /**
858
- * ColumnRangeSeries object
859
- */
860
- seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
861
- type: 'columnrange',
862
- /**
863
- * Translate data points from raw values x and y to plotX and plotY
864
- */
865
- translate: function () {
866
- var series = this,
867
- yAxis = series.yAxis,
868
- plotHigh;
869
-
870
- colProto.translate.apply(series);
871
-
872
- // Set plotLow and plotHigh
873
- each(series.points, function (point) {
874
- var shapeArgs = point.shapeArgs,
875
- minPointLength = series.options.minPointLength,
876
- heightDifference,
877
- height,
878
- y;
879
-
880
- point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
881
- point.plotLow = point.plotY;
882
-
883
- // adjust shape
884
- y = plotHigh;
885
- height = point.plotY - plotHigh;
886
-
887
- if (height < minPointLength) {
888
- heightDifference = (minPointLength - height);
889
- height += heightDifference;
890
- y -= heightDifference / 2;
891
- }
892
- shapeArgs.height = height;
893
- shapeArgs.y = y;
894
- });
895
- },
896
- trackerGroups: ['group', 'dataLabels'],
897
- drawGraph: noop,
898
- pointAttrToOptions: colProto.pointAttrToOptions,
899
- drawPoints: colProto.drawPoints,
900
- drawTracker: colProto.drawTracker,
901
- animate: colProto.animate,
902
- getColumnMetrics: colProto.getColumnMetrics
903
- });
904
- /*
905
- * The GaugeSeries class
906
- */
907
-
908
-
909
-
910
- /**
911
- * Extend the default options
912
- */
913
- defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
914
- dataLabels: {
915
- enabled: true,
916
- y: 15,
917
- borderWidth: 1,
918
- borderColor: 'silver',
919
- borderRadius: 3,
920
- style: {
921
- fontWeight: 'bold'
922
- },
923
- verticalAlign: 'top',
924
- zIndex: 2
925
- },
926
- dial: {
927
- // radius: '80%',
928
- // backgroundColor: 'black',
929
- // borderColor: 'silver',
930
- // borderWidth: 0,
931
- // baseWidth: 3,
932
- // topWidth: 1,
933
- // baseLength: '70%' // of radius
934
- // rearLength: '10%'
935
- },
936
- pivot: {
937
- //radius: 5,
938
- //borderWidth: 0
939
- //borderColor: 'silver',
940
- //backgroundColor: 'black'
941
- },
942
- tooltip: {
943
- headerFormat: ''
944
- },
945
- showInLegend: false
946
- });
947
-
948
- /**
949
- * Extend the point object
950
- */
951
- var GaugePoint = Highcharts.extendClass(Highcharts.Point, {
952
- /**
953
- * Don't do any hover colors or anything
954
- */
955
- setState: function (state) {
956
- this.state = state;
957
- }
958
- });
959
-
960
-
961
- /**
962
- * Add the series type
963
- */
964
- var GaugeSeries = {
965
- type: 'gauge',
966
- pointClass: GaugePoint,
967
-
968
- // chart.angular will be set to true when a gauge series is present, and this will
969
- // be used on the axes
970
- angular: true,
971
- drawGraph: noop,
972
- trackerGroups: ['group', 'dataLabels'],
973
-
974
- /**
975
- * Calculate paths etc
976
- */
977
- translate: function () {
978
-
979
- var series = this,
980
- yAxis = series.yAxis,
981
- options = series.options,
982
- center = yAxis.center;
983
-
984
- series.generatePoints();
985
-
986
- each(series.points, function (point) {
987
-
988
- var dialOptions = merge(options.dial, point.dial),
989
- radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
990
- baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
991
- rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
992
- baseWidth = dialOptions.baseWidth || 3,
993
- topWidth = dialOptions.topWidth || 1,
994
- rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
995
-
996
- // Handle the wrap option
997
- if (options.wrap === false) {
998
- rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
999
- }
1000
- rotation = rotation * 180 / Math.PI;
1001
-
1002
- point.shapeType = 'path';
1003
- point.shapeArgs = {
1004
- d: dialOptions.path || [
1005
- 'M',
1006
- -rearLength, -baseWidth / 2,
1007
- 'L',
1008
- baseLength, -baseWidth / 2,
1009
- radius, -topWidth / 2,
1010
- radius, topWidth / 2,
1011
- baseLength, baseWidth / 2,
1012
- -rearLength, baseWidth / 2,
1013
- 'z'
1014
- ],
1015
- translateX: center[0],
1016
- translateY: center[1],
1017
- rotation: rotation
1018
- };
1019
-
1020
- // Positions for data label
1021
- point.plotX = center[0];
1022
- point.plotY = center[1];
1023
- });
1024
- },
1025
-
1026
- /**
1027
- * Draw the points where each point is one needle
1028
- */
1029
- drawPoints: function () {
1030
-
1031
- var series = this,
1032
- center = series.yAxis.center,
1033
- pivot = series.pivot,
1034
- options = series.options,
1035
- pivotOptions = options.pivot,
1036
- renderer = series.chart.renderer;
1037
-
1038
- each(series.points, function (point) {
1039
-
1040
- var graphic = point.graphic,
1041
- shapeArgs = point.shapeArgs,
1042
- d = shapeArgs.d,
1043
- dialOptions = merge(options.dial, point.dial); // #1233
1044
-
1045
- if (graphic) {
1046
- graphic.animate(shapeArgs);
1047
- shapeArgs.d = d; // animate alters it
1048
- } else {
1049
- point.graphic = renderer[point.shapeType](shapeArgs)
1050
- .attr({
1051
- stroke: dialOptions.borderColor || 'none',
1052
- 'stroke-width': dialOptions.borderWidth || 0,
1053
- fill: dialOptions.backgroundColor || 'black',
1054
- rotation: shapeArgs.rotation // required by VML when animation is false
1055
- })
1056
- .add(series.group);
1057
- }
1058
- });
1059
-
1060
- // Add or move the pivot
1061
- if (pivot) {
1062
- pivot.animate({ // #1235
1063
- translateX: center[0],
1064
- translateY: center[1]
1065
- });
1066
- } else {
1067
- series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
1068
- .attr({
1069
- 'stroke-width': pivotOptions.borderWidth || 0,
1070
- stroke: pivotOptions.borderColor || 'silver',
1071
- fill: pivotOptions.backgroundColor || 'black'
1072
- })
1073
- .translate(center[0], center[1])
1074
- .add(series.group);
1075
- }
1076
- },
1077
-
1078
- /**
1079
- * Animate the arrow up from startAngle
1080
- */
1081
- animate: function (init) {
1082
- var series = this;
1083
-
1084
- if (!init) {
1085
- each(series.points, function (point) {
1086
- var graphic = point.graphic;
1087
-
1088
- if (graphic) {
1089
- // start value
1090
- graphic.attr({
1091
- rotation: series.yAxis.startAngleRad * 180 / Math.PI
1092
- });
1093
-
1094
- // animate
1095
- graphic.animate({
1096
- rotation: point.shapeArgs.rotation
1097
- }, series.options.animation);
1098
- }
1099
- });
1100
-
1101
- // delete this function to allow it only once
1102
- series.animate = null;
1103
- }
1104
- },
1105
-
1106
- render: function () {
1107
- this.group = this.plotGroup(
1108
- 'group',
1109
- 'series',
1110
- this.visible ? 'visible' : 'hidden',
1111
- this.options.zIndex,
1112
- this.chart.seriesGroup
1113
- );
1114
- seriesTypes.pie.prototype.render.call(this);
1115
- this.group.clip(this.chart.clipRect);
1116
- },
1117
-
1118
- setData: seriesTypes.pie.prototype.setData,
1119
- drawTracker: seriesTypes.column.prototype.drawTracker
1120
- };
1121
- seriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* ****************************************************************************
1122
- * Start Box plot series code *
1123
- *****************************************************************************/
1124
-
1125
- // Set default options
1126
- defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
1127
- fillColor: '#FFFFFF',
1128
- lineWidth: 1,
1129
- //medianColor: null,
1130
- medianWidth: 2,
1131
- states: {
1132
- hover: {
1133
- brightness: -0.3
1134
- }
1135
- },
1136
- //stemColor: null,
1137
- //stemDashStyle: 'solid'
1138
- //stemWidth: null,
1139
- threshold: null,
1140
- tooltip: {
1141
- pointFormat: '<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>' +
1142
- 'Maximum: {point.high}<br/>' +
1143
- 'Upper quartile: {point.q3}<br/>' +
1144
- 'Median: {point.median}<br/>' +
1145
- 'Lower quartile: {point.q1}<br/>' +
1146
- 'Minimum: {point.low}<br/>'
1147
-
1148
- },
1149
- //whiskerColor: null,
1150
- whiskerLength: '50%',
1151
- whiskerWidth: 2
1152
- });
1153
-
1154
- // Create the series object
1155
- seriesTypes.boxplot = extendClass(seriesTypes.column, {
1156
- type: 'boxplot',
1157
- pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
1158
- toYData: function (point) { // return a plain array for speedy calculation
1159
- return [point.low, point.q1, point.median, point.q3, point.high];
1160
- },
1161
- pointValKey: 'high', // defines the top of the tracker
1162
-
1163
- /**
1164
- * One-to-one mapping from options to SVG attributes
1165
- */
1166
- pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
1167
- fill: 'fillColor',
1168
- stroke: 'color',
1169
- 'stroke-width': 'lineWidth'
1170
- },
1171
-
1172
- /**
1173
- * Disable data labels for box plot
1174
- */
1175
- drawDataLabels: noop,
1176
-
1177
- /**
1178
- * Translate data points from raw values x and y to plotX and plotY
1179
- */
1180
- translate: function () {
1181
- var series = this,
1182
- yAxis = series.yAxis,
1183
- pointArrayMap = series.pointArrayMap;
1184
-
1185
- seriesTypes.column.prototype.translate.apply(series);
1186
-
1187
- // do the translation on each point dimension
1188
- each(series.points, function (point) {
1189
- each(pointArrayMap, function (key) {
1190
- if (point[key] !== null) {
1191
- point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);
1192
- }
1193
- });
1194
- });
1195
- },
1196
-
1197
- /**
1198
- * Draw the data points
1199
- */
1200
- drawPoints: function () {
1201
- var series = this, //state = series.state,
1202
- points = series.points,
1203
- options = series.options,
1204
- chart = series.chart,
1205
- renderer = chart.renderer,
1206
- pointAttr,
1207
- q1Plot,
1208
- q3Plot,
1209
- highPlot,
1210
- lowPlot,
1211
- medianPlot,
1212
- crispCorr,
1213
- crispX,
1214
- graphic,
1215
- stemPath,
1216
- stemAttr,
1217
- boxPath,
1218
- whiskersPath,
1219
- whiskersAttr,
1220
- medianPath,
1221
- medianAttr,
1222
- width,
1223
- left,
1224
- right,
1225
- halfWidth,
1226
- shapeArgs,
1227
- color,
1228
- doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
1229
- whiskerLength = parseInt(series.options.whiskerLength, 10) / 100;
1230
-
1231
-
1232
- each(points, function (point) {
1233
-
1234
- graphic = point.graphic;
1235
- shapeArgs = point.shapeArgs; // the box
1236
- stemAttr = {};
1237
- whiskersAttr = {};
1238
- medianAttr = {};
1239
- color = point.color || series.color;
1240
-
1241
- if (point.plotY !== UNDEFINED) {
1242
-
1243
- pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
1244
-
1245
- // crisp vector coordinates
1246
- width = shapeArgs.width;
1247
- left = mathFloor(shapeArgs.x);
1248
- right = left + width;
1249
- halfWidth = mathRound(width / 2);
1250
- //crispX = mathRound(left + halfWidth) + crispCorr;
1251
- q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;
1252
- q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;
1253
- highPlot = mathFloor(point.highPlot);// + crispCorr;
1254
- lowPlot = mathFloor(point.lowPlot);// + crispCorr;
1255
-
1256
- // Stem attributes
1257
- stemAttr.stroke = point.stemColor || options.stemColor || color;
1258
- stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
1259
- stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
1260
-
1261
- // Whiskers attributes
1262
- whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
1263
- whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
1264
-
1265
- // Median attributes
1266
- medianAttr.stroke = point.medianColor || options.medianColor || color;
1267
- medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
1268
-
1269
-
1270
- // The stem
1271
- crispCorr = (stemAttr['stroke-width'] % 2) / 2;
1272
- crispX = left + halfWidth + crispCorr;
1273
- stemPath = [
1274
- // stem up
1275
- 'M',
1276
- crispX, q3Plot,
1277
- 'L',
1278
- crispX, highPlot,
1279
-
1280
- // stem down
1281
- 'M',
1282
- crispX, q1Plot,
1283
- 'L',
1284
- crispX, lowPlot,
1285
- 'z'
1286
- ];
1287
-
1288
- // The box
1289
- if (doQuartiles) {
1290
- crispCorr = (pointAttr['stroke-width'] % 2) / 2;
1291
- crispX = mathFloor(crispX) + crispCorr;
1292
- q1Plot = mathFloor(q1Plot) + crispCorr;
1293
- q3Plot = mathFloor(q3Plot) + crispCorr;
1294
- left += crispCorr;
1295
- right += crispCorr;
1296
- boxPath = [
1297
- 'M',
1298
- left, q3Plot,
1299
- 'L',
1300
- left, q1Plot,
1301
- 'L',
1302
- right, q1Plot,
1303
- 'L',
1304
- right, q3Plot,
1305
- 'L',
1306
- left, q3Plot,
1307
- 'z'
1308
- ];
1309
- }
1310
-
1311
- // The whiskers
1312
- if (whiskerLength) {
1313
- crispCorr = (whiskersAttr['stroke-width'] % 2) / 2;
1314
- highPlot = highPlot + crispCorr;
1315
- lowPlot = lowPlot + crispCorr;
1316
- whiskersPath = [
1317
- // High whisker
1318
- 'M',
1319
- crispX - halfWidth * whiskerLength,
1320
- highPlot,
1321
- 'L',
1322
- crispX + halfWidth * whiskerLength,
1323
- highPlot,
1324
-
1325
- // Low whisker
1326
- 'M',
1327
- crispX - halfWidth * whiskerLength,
1328
- lowPlot,
1329
- 'L',
1330
- crispX + halfWidth * whiskerLength,
1331
- lowPlot
1332
- ];
1333
- }
1334
-
1335
- // The median
1336
- crispCorr = (medianAttr['stroke-width'] % 2) / 2;
1337
- medianPlot = mathRound(point.medianPlot) + crispCorr;
1338
- medianPath = [
1339
- 'M',
1340
- left,
1341
- medianPlot,
1342
- 'L',
1343
- right,
1344
- medianPlot,
1345
- 'z'
1346
- ];
1347
-
1348
- // Create or update the graphics
1349
- if (graphic) { // update
1350
-
1351
- point.stem.animate({ d: stemPath });
1352
- if (whiskerLength) {
1353
- point.whiskers.animate({ d: whiskersPath });
1354
- }
1355
- if (doQuartiles) {
1356
- point.box.animate({ d: boxPath });
1357
- }
1358
- point.medianShape.animate({ d: medianPath });
1359
-
1360
- } else { // create new
1361
- point.graphic = graphic = renderer.g()
1362
- .add(series.group);
1363
-
1364
- point.stem = renderer.path(stemPath)
1365
- .attr(stemAttr)
1366
- .add(graphic);
1367
-
1368
- if (whiskerLength) {
1369
- point.whiskers = renderer.path(whiskersPath)
1370
- .attr(whiskersAttr)
1371
- .add(graphic);
1372
- }
1373
- if (doQuartiles) {
1374
- point.box = renderer.path(boxPath)
1375
- .attr(pointAttr)
1376
- .add(graphic);
1377
- }
1378
- point.medianShape = renderer.path(medianPath)
1379
- .attr(medianAttr)
1380
- .add(graphic);
1381
- }
1382
- }
1383
- });
1384
-
1385
- }
1386
-
1387
-
1388
- });
1389
-
1390
- /* ****************************************************************************
1391
- * End Box plot series code *
1392
- *****************************************************************************/
1393
- /* ****************************************************************************
1394
- * Start error bar series code *
1395
- *****************************************************************************/
1396
-
1397
- // 1 - set default options
1398
- defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
1399
- color: '#000000',
1400
- grouping: false,
1401
- linkedTo: ':previous',
1402
- tooltip: {
1403
- pointFormat: defaultPlotOptions.arearange.tooltip.pointFormat
1404
- },
1405
- whiskerWidth: null
1406
- });
1407
-
1408
- // 2 - Create the series object
1409
- seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
1410
- type: 'errorbar',
1411
- pointArrayMap: ['low', 'high'], // array point configs are mapped to this
1412
- toYData: function (point) { // return a plain array for speedy calculation
1413
- return [point.low, point.high];
1414
- },
1415
- pointValKey: 'high', // defines the top of the tracker
1416
- doQuartiles: false,
1417
-
1418
- /**
1419
- * Get the width and X offset, either on top of the linked series column
1420
- * or standalone
1421
- */
1422
- getColumnMetrics: function () {
1423
- return (this.linkedParent && this.linkedParent.columnMetrics) ||
1424
- seriesTypes.column.prototype.getColumnMetrics.call(this);
1425
- }
1426
- });
1427
-
1428
- /* ****************************************************************************
1429
- * End error bar series code *
1430
- *****************************************************************************/
1431
- /* ****************************************************************************
1432
- * Start Waterfall series code *
1433
- *****************************************************************************/
1434
-
1435
- // 1 - set default options
1436
- defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {
1437
- lineWidth: 1,
1438
- lineColor: '#333',
1439
- dashStyle: 'dot',
1440
- borderColor: '#333'
1441
- });
1442
-
1443
-
1444
- // 2 - Create the series object
1445
- seriesTypes.waterfall = extendClass(seriesTypes.column, {
1446
- type: 'waterfall',
1447
-
1448
- upColorProp: 'fill',
1449
-
1450
- pointArrayMap: ['low', 'y'],
1451
-
1452
- pointValKey: 'y',
1453
-
1454
- /**
1455
- * Init waterfall series, force stacking
1456
- */
1457
- init: function (chart, options) {
1458
- // force stacking
1459
- options.stacking = true;
1460
-
1461
- seriesTypes.column.prototype.init.call(this, chart, options);
1462
- },
1463
-
1464
-
1465
- /**
1466
- * Translate data points from raw values
1467
- */
1468
- translate: function () {
1469
- var series = this,
1470
- options = series.options,
1471
- axis = series.yAxis,
1472
- len,
1473
- i,
1474
- points,
1475
- point,
1476
- shapeArgs,
1477
- stack,
1478
- y,
1479
- previousY,
1480
- stackPoint,
1481
- threshold = options.threshold,
1482
- crispCorr = (options.borderWidth % 2) / 2;
1483
-
1484
- // run column series translate
1485
- seriesTypes.column.prototype.translate.apply(this);
1486
-
1487
- previousY = threshold;
1488
- points = series.points;
1489
-
1490
- for (i = 0, len = points.length; i < len; i++) {
1491
- // cache current point object
1492
- point = points[i];
1493
- shapeArgs = point.shapeArgs;
1494
-
1495
- // get current stack
1496
- stack = series.getStack(i);
1497
- stackPoint = stack.points[series.index];
1498
-
1499
- // override point value for sums
1500
- if (isNaN(point.y)) {
1501
- point.y = series.yData[i];
1502
- }
1503
-
1504
- // up points
1505
- y = mathMax(previousY, previousY + point.y) + stackPoint[0];
1506
- shapeArgs.y = axis.translate(y, 0, 1);
1507
-
1508
-
1509
- // sum points
1510
- if (point.isSum || point.isIntermediateSum) {
1511
- shapeArgs.y = axis.translate(stackPoint[1], 0, 1);
1512
- shapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y;
1513
-
1514
- // if it's not the sum point, update previous stack end position
1515
- } else {
1516
- previousY += stack.total;
1517
- }
1518
-
1519
- // negative points
1520
- if (shapeArgs.height < 0) {
1521
- shapeArgs.y += shapeArgs.height;
1522
- shapeArgs.height *= -1;
1523
- }
1524
-
1525
- point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;
1526
- shapeArgs.height = mathRound(shapeArgs.height);
1527
- point.yBottom = shapeArgs.y + shapeArgs.height;
1528
- }
1529
- },
1530
-
1531
- /**
1532
- * Call default processData then override yData to reflect waterfall's extremes on yAxis
1533
- */
1534
- processData: function (force) {
1535
- var series = this,
1536
- options = series.options,
1537
- yData = series.yData,
1538
- points = series.points,
1539
- point,
1540
- dataLength = yData.length,
1541
- threshold = options.threshold || 0,
1542
- subSum,
1543
- sum,
1544
- dataMin,
1545
- dataMax,
1546
- y,
1547
- i;
1548
-
1549
- sum = subSum = dataMin = dataMax = threshold;
1550
-
1551
- for (i = 0; i < dataLength; i++) {
1552
- y = yData[i];
1553
- point = points ? points[i] : {};
1554
-
1555
- if (y === "sum" || point.isSum) {
1556
- yData[i] = sum;
1557
- } else if (y === "intermediateSum" || point.isIntermediateSum) {
1558
- yData[i] = subSum;
1559
- subSum = threshold;
1560
- } else {
1561
- sum += y;
1562
- subSum += y;
1563
- }
1564
- dataMin = Math.min(sum, dataMin);
1565
- dataMax = Math.max(sum, dataMax);
1566
- }
1567
-
1568
- Series.prototype.processData.call(this, force);
1569
-
1570
- // Record extremes
1571
- series.dataMin = dataMin;
1572
- series.dataMax = dataMax;
1573
- },
1574
-
1575
- /**
1576
- * Return y value or string if point is sum
1577
- */
1578
- toYData: function (pt) {
1579
- if (pt.isSum) {
1580
- return "sum";
1581
- } else if (pt.isIntermediateSum) {
1582
- return "intermediateSum";
1583
- }
1584
-
1585
- return pt.y;
1586
- },
1587
-
1588
- /**
1589
- * Postprocess mapping between options and SVG attributes
1590
- */
1591
- getAttribs: function () {
1592
- seriesTypes.column.prototype.getAttribs.apply(this, arguments);
1593
-
1594
- var series = this,
1595
- options = series.options,
1596
- stateOptions = options.states,
1597
- upColor = options.upColor || series.color,
1598
- hoverColor = Highcharts.Color(upColor).brighten(0.1).get(),
1599
- seriesDownPointAttr = merge(series.pointAttr),
1600
- upColorProp = series.upColorProp;
1601
-
1602
- seriesDownPointAttr[''][upColorProp] = upColor;
1603
- seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;
1604
- seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;
1605
-
1606
- each(series.points, function (point) {
1607
- if (point.y > 0 && !point.color) {
1608
- point.pointAttr = seriesDownPointAttr;
1609
- point.color = upColor;
1610
- }
1611
- });
1612
- },
1613
-
1614
- /**
1615
- * Draw columns' connector lines
1616
- */
1617
- getGraphPath: function () {
1618
-
1619
- var data = this.data,
1620
- length = data.length,
1621
- lineWidth = this.options.lineWidth + this.options.borderWidth,
1622
- normalizer = mathRound(lineWidth) % 2 / 2,
1623
- path = [],
1624
- M = 'M',
1625
- L = 'L',
1626
- prevArgs,
1627
- pointArgs,
1628
- i,
1629
- d;
1630
-
1631
- for (i = 1; i < length; i++) {
1632
- pointArgs = data[i].shapeArgs;
1633
- prevArgs = data[i - 1].shapeArgs;
1634
-
1635
- d = [
1636
- M,
1637
- prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
1638
- L,
1639
- pointArgs.x, prevArgs.y + normalizer
1640
- ];
1641
-
1642
- if (data[i - 1].y < 0) {
1643
- d[2] += prevArgs.height;
1644
- d[5] += prevArgs.height;
1645
- }
1646
-
1647
- path = path.concat(d);
1648
- }
1649
-
1650
- return path;
1651
- },
1652
-
1653
- /**
1654
- * Extremes are recorded in processData
1655
- */
1656
- getExtremes: noop,
1657
-
1658
- /**
1659
- * Return stack for given index
1660
- */
1661
- getStack: function (i) {
1662
- var axis = this.yAxis,
1663
- stacks = axis.stacks,
1664
- key = this.stackKey;
1665
-
1666
- if (this.processedYData[i] < this.options.threshold) {
1667
- key = '-' + key;
1668
- }
1669
-
1670
- return stacks[key][i];
1671
- },
1672
-
1673
- drawGraph: Series.prototype.drawGraph
1674
- });
1675
-
1676
- /* ****************************************************************************
1677
- * End Waterfall series code *
1678
- *****************************************************************************/
1679
- /* ****************************************************************************
1680
- * Start Bubble series code *
1681
- *****************************************************************************/
1682
-
1683
- // 1 - set default options
1684
- defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
1685
- dataLabels: {
1686
- inside: true,
1687
- style: {
1688
- color: 'white',
1689
- textShadow: '0px 0px 3px black'
1690
- },
1691
- verticalAlign: 'middle'
1692
- },
1693
- // displayNegative: true,
1694
- marker: {
1695
- // fillOpacity: 0.5,
1696
- lineColor: null, // inherit from series.color
1697
- lineWidth: 1
1698
- },
1699
- minSize: 8,
1700
- maxSize: '20%',
1701
- // negativeColor: null,
1702
- tooltip: {
1703
- pointFormat: '({point.x}, {point.y}), Size: {point.z}'
1704
- },
1705
- turboThreshold: 0, // docs: exclude from bubbles
1706
- zThreshold: 0
1707
- });
1708
-
1709
- // 2 - Create the series object
1710
- seriesTypes.bubble = extendClass(seriesTypes.scatter, {
1711
- type: 'bubble',
1712
- pointArrayMap: ['y', 'z'],
1713
- trackerGroups: ['group', 'dataLabelsGroup'],
1714
-
1715
- /**
1716
- * Mapping between SVG attributes and the corresponding options
1717
- */
1718
- pointAttrToOptions: {
1719
- stroke: 'lineColor',
1720
- 'stroke-width': 'lineWidth',
1721
- fill: 'fillColor'
1722
- },
1723
-
1724
- /**
1725
- * Apply the fillOpacity to all fill positions
1726
- */
1727
- applyOpacity: function (fill) {
1728
- var markerOptions = this.options.marker,
1729
- fillOpacity = pick(markerOptions.fillOpacity, 0.5);
1730
-
1731
- // When called from Legend.colorizeItem, the fill isn't predefined
1732
- fill = fill || markerOptions.fillColor || this.color;
1733
-
1734
- if (fillOpacity !== 1) {
1735
- fill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba');
1736
- }
1737
- return fill;
1738
- },
1739
-
1740
- /**
1741
- * Extend the convertAttribs method by applying opacity to the fill
1742
- */
1743
- convertAttribs: function () {
1744
- var obj = Series.prototype.convertAttribs.apply(this, arguments);
1745
-
1746
- obj.fill = this.applyOpacity(obj.fill);
1747
-
1748
- return obj;
1749
- },
1750
-
1751
- /**
1752
- * Get the radius for each point based on the minSize, maxSize and each point's Z value. This
1753
- * must be done prior to Series.translate because the axis needs to add padding in
1754
- * accordance with the point sizes.
1755
- */
1756
- getRadii: function (zMin, zMax, minSize, maxSize) {
1757
- var len,
1758
- i,
1759
- pos,
1760
- zData = this.zData,
1761
- radii = [],
1762
- zRange;
1763
-
1764
- // Set the shape type and arguments to be picked up in drawPoints
1765
- for (i = 0, len = zData.length; i < len; i++) {
1766
- zRange = zMax - zMin;
1767
- pos = zRange > 0 ? // relative size, a number between 0 and 1
1768
- (zData[i] - zMin) / (zMax - zMin) :
1769
- 0.5;
1770
- radii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2);
1771
- }
1772
- this.radii = radii;
1773
- },
1774
-
1775
- /**
1776
- * Perform animation on the bubbles
1777
- */
1778
- animate: function (init) {
1779
- var animation = this.options.animation;
1780
-
1781
- if (!init) { // run the animation
1782
- each(this.points, function (point) {
1783
- var graphic = point.graphic,
1784
- shapeArgs = point.shapeArgs;
1785
-
1786
- if (graphic && shapeArgs) {
1787
- // start values
1788
- graphic.attr('r', 1);
1789
-
1790
- // animate
1791
- graphic.animate({
1792
- r: shapeArgs.r
1793
- }, animation);
1794
- }
1795
- });
1796
-
1797
- // delete this function to allow it only once
1798
- this.animate = null;
1799
- }
1800
- },
1801
-
1802
- /**
1803
- * Extend the base translate method to handle bubble size
1804
- */
1805
- translate: function () {
1806
-
1807
- var i,
1808
- data = this.data,
1809
- point,
1810
- radius,
1811
- radii = this.radii;
1812
-
1813
- // Run the parent method
1814
- seriesTypes.scatter.prototype.translate.call(this);
1815
-
1816
- // Set the shape type and arguments to be picked up in drawPoints
1817
- i = data.length;
1818
-
1819
- while (i--) {
1820
- point = data[i];
1821
- radius = radii ? radii[i] : 0; // #1737
1822
-
1823
- // Flag for negativeColor to be applied in Series.js
1824
- point.negative = point.z < (this.options.zThreshold || 0);
1825
-
1826
- if (radius >= this.minPxSize / 2) {
1827
- // Shape arguments
1828
- point.shapeType = 'circle';
1829
- point.shapeArgs = {
1830
- x: point.plotX,
1831
- y: point.plotY,
1832
- r: radius
1833
- };
1834
-
1835
- // Alignment box for the data label
1836
- point.dlBox = {
1837
- x: point.plotX - radius,
1838
- y: point.plotY - radius,
1839
- width: 2 * radius,
1840
- height: 2 * radius
1841
- };
1842
- } else { // below zThreshold
1843
- point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691
1844
- }
1845
- }
1846
- },
1847
-
1848
- /**
1849
- * Get the series' symbol in the legend
1850
- *
1851
- * @param {Object} legend The legend object
1852
- * @param {Object} item The series (this) or point
1853
- */
1854
- drawLegendSymbol: function (legend, item) {
1855
- var radius = pInt(legend.itemStyle.fontSize) / 2;
1856
-
1857
- item.legendSymbol = this.chart.renderer.circle(
1858
- radius,
1859
- legend.baseline - radius,
1860
- radius
1861
- ).attr({
1862
- zIndex: 3
1863
- }).add(item.legendGroup);
1864
- item.legendSymbol.isMarker = true;
1865
-
1866
- },
1867
-
1868
- drawPoints: seriesTypes.column.prototype.drawPoints,
1869
- alignDataLabel: seriesTypes.column.prototype.alignDataLabel
1870
- });
1871
-
1872
- /**
1873
- * Add logic to pad each axis with the amount of pixels
1874
- * necessary to avoid the bubbles to overflow.
1875
- */
1876
- Axis.prototype.beforePadding = function () {
1877
- var axis = this,
1878
- axisLength = this.len,
1879
- chart = this.chart,
1880
- pxMin = 0,
1881
- pxMax = axisLength,
1882
- isXAxis = this.isXAxis,
1883
- dataKey = isXAxis ? 'xData' : 'yData',
1884
- min = this.min,
1885
- extremes = {},
1886
- smallestSize = math.min(chart.plotWidth, chart.plotHeight),
1887
- zMin = Number.MAX_VALUE,
1888
- zMax = -Number.MAX_VALUE,
1889
- range = this.max - min,
1890
- transA = axisLength / range,
1891
- activeSeries = [];
1892
-
1893
- // Handle padding on the second pass, or on redraw
1894
- if (this.tickPositions) {
1895
- each(this.series, function (series) {
1896
-
1897
- var seriesOptions = series.options,
1898
- zData;
1899
-
1900
- if (series.type === 'bubble' && series.visible) {
1901
-
1902
- // Correction for #1673
1903
- axis.allowZoomOutside = true;
1904
-
1905
- // Cache it
1906
- activeSeries.push(series);
1907
-
1908
- if (isXAxis) { // because X axis is evaluated first
1909
-
1910
- // For each series, translate the size extremes to pixel values
1911
- each(['minSize', 'maxSize'], function (prop) {
1912
- var length = seriesOptions[prop],
1913
- isPercent = /%$/.test(length);
1914
-
1915
- length = pInt(length);
1916
- extremes[prop] = isPercent ?
1917
- smallestSize * length / 100 :
1918
- length;
1919
-
1920
- });
1921
- series.minPxSize = extremes.minSize;
1922
-
1923
- // Find the min and max Z
1924
- zData = series.zData;
1925
- if (zData.length) { // #1735
1926
- zMin = math.min(
1927
- zMin,
1928
- math.max(
1929
- arrayMin(zData),
1930
- seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE
1931
- )
1932
- );
1933
- zMax = math.max(zMax, arrayMax(zData));
1934
- }
1935
- }
1936
- }
1937
- });
1938
-
1939
- each(activeSeries, function (series) {
1940
-
1941
- var data = series[dataKey],
1942
- i = data.length,
1943
- radius;
1944
-
1945
- if (isXAxis) {
1946
- series.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize);
1947
- }
1948
-
1949
- if (range > 0) {
1950
- while (i--) {
1951
- radius = series.radii[i];
1952
- pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
1953
- pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
1954
- }
1955
- }
1956
- });
1957
-
1958
- if (range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) {
1959
- pxMax -= axisLength;
1960
- transA *= (axisLength + pxMin - pxMax) / axisLength;
1961
- this.min += pxMin / transA;
1962
- this.max += pxMax / transA;
1963
- }
1964
- }
1965
- };
1966
-
1967
- /* ****************************************************************************
1968
- * End Bubble series code *
1969
- *****************************************************************************/
1970
- /**
1971
- * Extensions for polar charts. Additionally, much of the geometry required for polar charts is
1972
- * gathered in RadialAxes.js.
1973
- *
1974
- */
1975
-
1976
- var seriesProto = Series.prototype,
1977
- pointerProto = Highcharts.Pointer.prototype;
1978
-
1979
-
1980
-
1981
- /**
1982
- * Translate a point's plotX and plotY from the internal angle and radius measures to
1983
- * true plotX, plotY coordinates
1984
- */
1985
- seriesProto.toXY = function (point) {
1986
- var xy,
1987
- chart = this.chart,
1988
- plotX = point.plotX,
1989
- plotY = point.plotY;
1990
-
1991
- // Save rectangular plotX, plotY for later computation
1992
- point.rectPlotX = plotX;
1993
- point.rectPlotY = plotY;
1994
-
1995
- // Record the angle in degrees for use in tooltip
1996
- point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
1997
-
1998
- // Find the polar plotX and plotY
1999
- xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
2000
- point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
2001
- point.plotY = point.polarPlotY = xy.y - chart.plotTop;
2002
- };
2003
-
2004
- /**
2005
- * Order the tooltip points to get the mouse capture ranges correct. #1915.
2006
- */
2007
- seriesProto.orderTooltipPoints = function (points) {
2008
- if (this.chart.polar) {
2009
- points.sort(function (a, b) {
2010
- return a.clientX - b.clientX;
2011
- });
2012
-
2013
- // Wrap mouse tracking around to capture movement on the segment to the left
2014
- // of the north point (#1469).
2015
- points[0].wrappedClientX = points[0].clientX + 360;
2016
- points.push(points[0]);
2017
- }
2018
- };
2019
-
2020
-
2021
- /**
2022
- * Add some special init logic to areas and areasplines
2023
- */
2024
- function initArea(proceed, chart, options) {
2025
- proceed.call(this, chart, options);
2026
- if (this.chart.polar) {
2027
-
2028
- /**
2029
- * Overridden method to close a segment path. While in a cartesian plane the area
2030
- * goes down to the threshold, in the polar chart it goes to the center.
2031
- */
2032
- this.closeSegment = function (path) {
2033
- var center = this.xAxis.center;
2034
- path.push(
2035
- 'L',
2036
- center[0],
2037
- center[1]
2038
- );
2039
- };
2040
-
2041
- // Instead of complicated logic to draw an area around the inner area in a stack,
2042
- // just draw it behind
2043
- this.closedStacks = true;
2044
- }
2045
- }
2046
- wrap(seriesTypes.area.prototype, 'init', initArea);
2047
- wrap(seriesTypes.areaspline.prototype, 'init', initArea);
2048
-
2049
-
2050
- /**
2051
- * Overridden method for calculating a spline from one point to the next
2052
- */
2053
- wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) {
2054
-
2055
- var ret,
2056
- smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;
2057
- denom = smoothing + 1,
2058
- plotX,
2059
- plotY,
2060
- lastPoint,
2061
- nextPoint,
2062
- lastX,
2063
- lastY,
2064
- nextX,
2065
- nextY,
2066
- leftContX,
2067
- leftContY,
2068
- rightContX,
2069
- rightContY,
2070
- distanceLeftControlPoint,
2071
- distanceRightControlPoint,
2072
- leftContAngle,
2073
- rightContAngle,
2074
- jointAngle;
2075
-
2076
-
2077
- if (this.chart.polar) {
2078
-
2079
- plotX = point.plotX;
2080
- plotY = point.plotY;
2081
- lastPoint = segment[i - 1];
2082
- nextPoint = segment[i + 1];
2083
-
2084
- // Connect ends
2085
- if (this.connectEnds) {
2086
- if (!lastPoint) {
2087
- lastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected
2088
- }
2089
- if (!nextPoint) {
2090
- nextPoint = segment[1];
2091
- }
2092
- }
2093
-
2094
- // find control points
2095
- if (lastPoint && nextPoint) {
2096
-
2097
- lastX = lastPoint.plotX;
2098
- lastY = lastPoint.plotY;
2099
- nextX = nextPoint.plotX;
2100
- nextY = nextPoint.plotY;
2101
- leftContX = (smoothing * plotX + lastX) / denom;
2102
- leftContY = (smoothing * plotY + lastY) / denom;
2103
- rightContX = (smoothing * plotX + nextX) / denom;
2104
- rightContY = (smoothing * plotY + nextY) / denom;
2105
- distanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2));
2106
- distanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2));
2107
- leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
2108
- rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
2109
- jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
2110
-
2111
-
2112
- // Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle
2113
- if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
2114
- jointAngle -= Math.PI;
2115
- }
2116
-
2117
- // Find the corrected control points for a spline straight through the point
2118
- leftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint;
2119
- leftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint;
2120
- rightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint;
2121
- rightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint;
2122
-
2123
- // Record for drawing in next point
2124
- point.rightContX = rightContX;
2125
- point.rightContY = rightContY;
2126
-
2127
- }
2128
-
2129
-
2130
- // moveTo or lineTo
2131
- if (!i) {
2132
- ret = ['M', plotX, plotY];
2133
- } else { // curve from last point to this
2134
- ret = [
2135
- 'C',
2136
- lastPoint.rightContX || lastPoint.plotX,
2137
- lastPoint.rightContY || lastPoint.plotY,
2138
- leftContX || plotX,
2139
- leftContY || plotY,
2140
- plotX,
2141
- plotY
2142
- ];
2143
- lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later
2144
- }
2145
-
2146
-
2147
- } else {
2148
- ret = proceed.call(this, segment, point, i);
2149
- }
2150
- return ret;
2151
- });
2152
-
2153
- /**
2154
- * Extend translate. The plotX and plotY values are computed as if the polar chart were a
2155
- * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from
2156
- * center.
2157
- */
2158
- wrap(seriesProto, 'translate', function (proceed) {
2159
-
2160
- // Run uber method
2161
- proceed.call(this);
2162
-
2163
- // Postprocess plot coordinates
2164
- if (this.chart.polar && !this.preventPostTranslate) {
2165
- var points = this.points,
2166
- i = points.length;
2167
- while (i--) {
2168
- // Translate plotX, plotY from angle and radius to true plot coordinates
2169
- this.toXY(points[i]);
2170
- }
2171
- }
2172
- });
2173
-
2174
- /**
2175
- * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in
2176
- * line-like series.
2177
- */
2178
- wrap(seriesProto, 'getSegmentPath', function (proceed, segment) {
2179
-
2180
- var points = this.points;
2181
-
2182
- // Connect the path
2183
- if (this.chart.polar && this.options.connectEnds !== false &&
2184
- segment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) {
2185
- this.connectEnds = true; // re-used in splines
2186
- segment = [].concat(segment, [points[0]]);
2187
- }
2188
-
2189
- // Run uber method
2190
- return proceed.call(this, segment);
2191
-
2192
- });
2193
-
2194
-
2195
- function polarAnimate(proceed, init) {
2196
- var chart = this.chart,
2197
- animation = this.options.animation,
2198
- group = this.group,
2199
- markerGroup = this.markerGroup,
2200
- center = this.xAxis.center,
2201
- plotLeft = chart.plotLeft,
2202
- plotTop = chart.plotTop,
2203
- attribs;
2204
-
2205
- // Specific animation for polar charts
2206
- if (chart.polar) {
2207
-
2208
- // Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation
2209
- // would be so slow it would't matter.
2210
- if (chart.renderer.isSVG) {
2211
-
2212
- if (animation === true) {
2213
- animation = {};
2214
- }
2215
-
2216
- // Initialize the animation
2217
- if (init) {
2218
-
2219
- // Scale down the group and place it in the center
2220
- attribs = {
2221
- translateX: center[0] + plotLeft,
2222
- translateY: center[1] + plotTop,
2223
- scaleX: 0.001, // #1499
2224
- scaleY: 0.001
2225
- };
2226
-
2227
- group.attr(attribs);
2228
- if (markerGroup) {
2229
- markerGroup.attrSetters = group.attrSetters;
2230
- markerGroup.attr(attribs);
2231
- }
2232
-
2233
- // Run the animation
2234
- } else {
2235
- attribs = {
2236
- translateX: plotLeft,
2237
- translateY: plotTop,
2238
- scaleX: 1,
2239
- scaleY: 1
2240
- };
2241
- group.animate(attribs, animation);
2242
- if (markerGroup) {
2243
- markerGroup.animate(attribs, animation);
2244
- }
2245
-
2246
- // Delete this function to allow it only once
2247
- this.animate = null;
2248
- }
2249
- }
2250
-
2251
- // For non-polar charts, revert to the basic animation
2252
- } else {
2253
- proceed.call(this, init);
2254
- }
2255
- }
2256
-
2257
- // Define the animate method for both regular series and column series and their derivatives
2258
- wrap(seriesProto, 'animate', polarAnimate);
2259
- wrap(colProto, 'animate', polarAnimate);
2260
-
2261
-
2262
- /**
2263
- * Throw in a couple of properties to let setTooltipPoints know we're indexing the points
2264
- * in degrees (0-360), not plot pixel width.
2265
- */
2266
- wrap(seriesProto, 'setTooltipPoints', function (proceed, renew) {
2267
-
2268
- if (this.chart.polar) {
2269
- extend(this.xAxis, {
2270
- tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array
2271
- });
2272
- }
2273
-
2274
- // Run uber method
2275
- return proceed.call(this, renew);
2276
- });
2277
-
2278
-
2279
- /**
2280
- * Extend the column prototype's translate method
2281
- */
2282
- wrap(colProto, 'translate', function (proceed) {
2283
-
2284
- var xAxis = this.xAxis,
2285
- len = this.yAxis.len,
2286
- center = xAxis.center,
2287
- startAngleRad = xAxis.startAngleRad,
2288
- renderer = this.chart.renderer,
2289
- start,
2290
- points,
2291
- point,
2292
- i;
2293
-
2294
- this.preventPostTranslate = true;
2295
-
2296
- // Run uber method
2297
- proceed.call(this);
2298
-
2299
- // Postprocess plot coordinates
2300
- if (xAxis.isRadial) {
2301
- points = this.points;
2302
- i = points.length;
2303
- while (i--) {
2304
- point = points[i];
2305
- start = point.barX + startAngleRad;
2306
- point.shapeType = 'path';
2307
- point.shapeArgs = {
2308
- d: renderer.symbols.arc(
2309
- center[0],
2310
- center[1],
2311
- len - point.plotY,
2312
- null,
2313
- {
2314
- start: start,
2315
- end: start + point.pointWidth,
2316
- innerR: len - pick(point.yBottom, len)
2317
- }
2318
- )
2319
- };
2320
- this.toXY(point); // provide correct plotX, plotY for tooltip
2321
- }
2322
- }
2323
- });
2324
-
2325
-
2326
- /**
2327
- * Align column data labels outside the columns. #1199.
2328
- */
2329
- wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) {
2330
-
2331
- if (this.chart.polar) {
2332
- var angle = point.rectPlotX / Math.PI * 180,
2333
- align,
2334
- verticalAlign;
2335
-
2336
- // Align nicely outside the perimeter of the columns
2337
- if (options.align === null) {
2338
- if (angle > 20 && angle < 160) {
2339
- align = 'left'; // right hemisphere
2340
- } else if (angle > 200 && angle < 340) {
2341
- align = 'right'; // left hemisphere
2342
- } else {
2343
- align = 'center'; // top or bottom
2344
- }
2345
- options.align = align;
2346
- }
2347
- if (options.verticalAlign === null) {
2348
- if (angle < 45 || angle > 315) {
2349
- verticalAlign = 'bottom'; // top part
2350
- } else if (angle > 135 && angle < 225) {
2351
- verticalAlign = 'top'; // bottom part
2352
- } else {
2353
- verticalAlign = 'middle'; // left or right
2354
- }
2355
- options.verticalAlign = verticalAlign;
2356
- }
2357
-
2358
- seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
2359
- } else {
2360
- proceed.call(this, point, dataLabel, options, alignTo, isNew);
2361
- }
2362
-
2363
- });
2364
-
2365
- /**
2366
- * Extend the mouse tracker to return the tooltip position index in terms of
2367
- * degrees rather than pixels
2368
- */
2369
- wrap(pointerProto, 'getIndex', function (proceed, e) {
2370
- var ret,
2371
- chart = this.chart,
2372
- center,
2373
- x,
2374
- y;
2375
-
2376
- if (chart.polar) {
2377
- center = chart.xAxis[0].center;
2378
- x = e.chartX - center[0] - chart.plotLeft;
2379
- y = e.chartY - center[1] - chart.plotTop;
2380
-
2381
- ret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180);
2382
-
2383
- } else {
2384
-
2385
- // Run uber method
2386
- ret = proceed.call(this, e);
2387
- }
2388
- return ret;
2389
- });
2390
-
2391
- /**
2392
- * Extend getCoordinates to prepare for polar axis values
2393
- */
2394
- wrap(pointerProto, 'getCoordinates', function (proceed, e) {
2395
- var chart = this.chart,
2396
- ret = {
2397
- xAxis: [],
2398
- yAxis: []
2399
- };
2400
-
2401
- if (chart.polar) {
2402
-
2403
- each(chart.axes, function (axis) {
2404
- var isXAxis = axis.isXAxis,
2405
- center = axis.center,
2406
- x = e.chartX - center[0] - chart.plotLeft,
2407
- y = e.chartY - center[1] - chart.plotTop;
2408
-
2409
- ret[isXAxis ? 'xAxis' : 'yAxis'].push({
2410
- axis: axis,
2411
- value: axis.translate(
2412
- isXAxis ?
2413
- Math.PI - Math.atan2(x, y) : // angle
2414
- Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center
2415
- true
2416
- )
2417
- });
2418
- });
2419
-
2420
- } else {
2421
- ret = proceed.call(this, e);
2422
- }
2423
-
2424
- return ret;
2425
- });
2426
- }(Highcharts));
1
+ /*
2
+ Highcharts JS v3.0.5 (2013-08-23)
3
+
4
+ (c) 2009-2013 Torstein Hønsi
5
+
6
+ License: www.highcharts.com/license
7
+ */
8
+ (function(l,C){function J(a,b,c){this.init.call(this,a,b,c)}function K(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var c=this.xAxis.center;a.push("L",c[0],c[1])},this.closedStacks=!0}function L(a,b){var c=this.chart,d=this.options.animation,g=this.group,f=this.markerGroup,e=this.xAxis.center,i=c.plotLeft,o=c.plotTop;if(c.polar){if(c.renderer.isSVG)if(d===!0&&(d={}),b){if(c={translateX:e[0]+i,translateY:e[1]+o,scaleX:0.001,scaleY:0.001},g.attr(c),f)f.attrSetters=g.attrSetters,
9
+ f.attr(c)}else c={translateX:i,translateY:o,scaleX:1,scaleY:1},g.animate(c,d),f&&f.animate(c,d),this.animate=null}else a.call(this,b)}var P=l.arrayMin,Q=l.arrayMax,r=l.each,F=l.extend,p=l.merge,R=l.map,q=l.pick,v=l.pInt,m=l.getOptions().plotOptions,h=l.seriesTypes,x=l.extendClass,M=l.splat,n=l.wrap,N=l.Axis,u=l.Tick,z=l.Series,t=h.column.prototype,s=Math,D=s.round,A=s.floor,S=s.max,w=function(){};F(J.prototype,{init:function(a,b,c){var d=this,g=d.defaultOptions;d.chart=b;if(b.angular)g.background=
10
+ {};d.options=a=p(g,a);(a=a.background)&&r([].concat(M(a)).reverse(),function(a){var b=a.backgroundColor,a=p(d.defaultBackgroundOptions,a);if(b)a.backgroundColor=b;a.color=a.backgroundColor;c.options.plotBands.unshift(a)})},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"silver",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#FFF"],[1,"#DDD"]]},from:Number.MIN_VALUE,innerRadius:0,to:Number.MAX_VALUE,
11
+ outerRadius:"105%"}});var G=N.prototype,u=u.prototype,T={getOffset:w,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:w,setCategories:w,setTitle:w},O={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:"center",x:0,y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,plotBands:[],tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,
12
+ distance:15,x:0,y:null},maxPadding:0,minPadding:0,plotBands:[],showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},plotBands:[],showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){this.options=p(this.defaultOptions,this.defaultRadialOptions,a)},getOffset:function(){G.getOffset.call(this);this.chart.axisOffset[this.side]=0;this.center=this.pane.center=h.pie.prototype.getCenter.call(this.pane)},getLinePath:function(a,
13
+ b){var c=this.center,b=q(b,c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){G.setAxisTranslation.call(this);if(this.center&&(this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.isXAxis))this.minPixelPadding=this.transA*this.minPointOffset+(this.reversed?(this.endAngleRad-this.startAngleRad)/
14
+ 4:0)},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&&1||this.pointRange||this.closestPointRange)},setAxisSize:function(){G.setAxisSize.call(this);if(this.center)this.len=this.width=this.height=this.isCircular?this.center[2]*(this.endAngleRad-this.startAngleRad)/2:this.center[2]/2},getPosition:function(a,b){if(!this.isCircular)b=this.translate(a),a=this.min;return this.postTranslate(this.translate(a),q(b,this.center[2]/2)-this.offset)},postTranslate:function(a,b){var c=
15
+ this.chart,d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,g=this.startAngleRad,f=d[2]/2,e=[q(c.outerRadius,"100%"),c.innerRadius,q(c.thickness,10)],i=/%$/,o,k=this.isCircular;this.options.gridLineInterpolation==="polygon"?d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(k||(e[0]=this.translate(a),e[1]=this.translate(b)),e=R(e,function(a){i.test(a)&&(a=v(a,10)*f/100);return a}),
16
+ c.shape==="circle"||!k?(a=-Math.PI/2,b=Math.PI*1.5,o=!0):(a=g+this.translate(a),b=g+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],e[0],e[0],{start:a,end:b,innerR:q(e[1],e[0]-e[2]),open:o}));return d},getPlotLinePath:function(a,b){var c=this.center,d=this.chart,g=this.getPosition(a),f,e,i;this.isCircular?i=["M",c[0]+d.plotLeft,c[1]+d.plotTop,"L",g.x,g.y]:this.options.gridLineInterpolation==="circle"?(a=this.translate(a))&&(i=this.getLinePath(0,a)):(f=d.xAxis[0],
17
+ i=[],a=this.translate(a),c=f.tickPositions,f.autoConnect&&(c=c.concat([c[0]])),b&&(c=[].concat(c).reverse()),r(c,function(c,b){e=f.getPosition(c,a);i.push(b?"L":"M",e.x,e.y)}));return i},getTitlePosition:function(){var a=this.center,b=this.chart,c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};n(G,"init",function(a,b,c){var j;var d=b.angular,g=b.polar,f=c.isX,e=d&&f,i,o;o=b.options;var k=c.pane||0;if(d){if(F(this,e?T:O),
18
+ i=!f)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else if(g)F(this,O),this.defaultRadialOptions=(i=f)?this.defaultRadialXOptions:p(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!e&&(d||g)){a=this.options;if(!b.panes)b.panes=[];this.pane=(j=b.panes[k]=b.panes[k]||new J(M(o.pane)[k],b,this),k=j);k=k.options;b.inverted=!1;o.chart.zoomType=null;this.startAngleRad=b=(k.startAngle-90)*Math.PI/180;this.endAngleRad=o=(q(k.endAngle,k.startAngle+360)-90)*Math.PI/180;this.offset=
19
+ a.offset||0;if((this.isCircular=i)&&c.max===C&&o-b===2*Math.PI)this.autoConnect=!0}});n(u,"getPosition",function(a,b,c,d,g){var f=this.axis;return f.getPosition?f.getPosition(c):a.call(this,b,c,d,g)});n(u,"getLabelPosition",function(a,b,c,d,g,f,e,i,o){var k=this.axis,j=f.y,h=f.align,l=(k.translate(this.pos)+k.startAngleRad+Math.PI/2)/Math.PI*180%360;k.isRadial?(a=k.getPosition(this.pos,k.center[2]/2+q(f.distance,-25)),f.rotation==="auto"?d.attr({rotation:l}):j===null&&(j=v(d.styles.lineHeight)*0.9-
20
+ d.getBBox().height/2),h===null&&(h=k.isCircular?l>20&&l<160?"left":l>200&&l<340?"right":"center":"center",d.attr({align:h})),a.x+=f.x,a.y+=j):a=a.call(this,b,c,d,g,f,e,i,o);return a});n(u,"getMarkPath",function(a,b,c,d,g,f,e){var i=this.axis;i.isRadial?(a=i.getPosition(this.pos,i.center[2]/2+d),b=["M",b,c,"L",a.x,a.y]):b=a.call(this,b,c,d,g,f,e);return b});m.arearange=p(m.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'},
21
+ trackByArea:!0,dataLabels:{verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0}});h.arearange=l.extendClass(h.area,{type:"arearange",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"low",getSegments:function(){var a=this;r(a.points,function(b){if(!a.options.connectNulls&&(b.low===null||b.high===null))b.y=null;else if(b.low===null&&b.high!==null)b.y=b.high});z.prototype.getSegments.call(this)},translate:function(){var a=this.yAxis;h.area.prototype.translate.apply(this);
22
+ r(this.points,function(b){var c=b.low,d=b.high,g=b.plotY;d===null&&c===null?b.y=null:c===null?(b.plotLow=b.plotY=null,b.plotHigh=a.translate(d,0,1,0,1)):d===null?(b.plotLow=g,b.plotHigh=null):(b.plotLow=g,b.plotHigh=a.translate(d,0,1,0,1))})},getSegmentPath:function(a){var b,c=[],d=a.length,g=z.prototype.getSegmentPath,f,e;e=this.options;var i=e.step;for(b=HighchartsAdapter.grep(a,function(a){return a.plotLow!==null});d--;)f=a[d],f.plotHigh!==null&&c.push({plotX:f.plotX,plotY:f.plotHigh});a=g.call(this,
23
+ b);if(i)i===!0&&(i="left"),e.step={left:"right",center:"center",right:"left"}[i];c=g.call(this,c);e.step=i;e=[].concat(a,c);c[0]="L";this.areaPath=this.areaPath.concat(a,c);return e},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],g=z.prototype,f=this.options.dataLabels,e,i=this.chart.inverted;if(f.enabled||this._hasPointLabels){for(c=b;c--;)e=a[c],e.y=e.high,e.plotY=e.plotHigh,d[c]=e.dataLabel,e.dataLabel=e.dataLabelUpper,e.below=!1,i?(f.align="left",f.x=f.xHigh):f.y=f.yHigh;g.drawDataLabels.apply(this,
24
+ arguments);for(c=b;c--;)e=a[c],e.dataLabelUpper=e.dataLabel,e.dataLabel=d[c],e.y=e.low,e.plotY=e.plotLow,e.below=!0,i?(f.align="right",f.x=f.xLow):f.y=f.yLow;g.drawDataLabels.apply(this,arguments)}},alignDataLabel:h.column.prototype.alignDataLabel,getSymbol:h.column.prototype.getSymbol,drawPoints:w});m.areasplinerange=p(m.arearange);h.areasplinerange=x(h.arearange,{type:"areasplinerange",getPointSpline:h.spline.prototype.getPointSpline});m.columnrange=p(m.column,m.arearange,{lineWidth:1,pointRange:null});
25
+ h.columnrange=x(h.arearange,{type:"columnrange",translate:function(){var a=this,b=a.yAxis,c;t.translate.apply(a);r(a.points,function(d){var g=d.shapeArgs,f=a.options.minPointLength,e;d.plotHigh=c=b.translate(d.high,0,1,0,1);d.plotLow=d.plotY;e=c;d=d.plotY-c;d<f&&(f-=d,d+=f,e-=f/2);g.height=d;g.y=e})},trackerGroups:["group","dataLabels"],drawGraph:w,pointAttrToOptions:t.pointAttrToOptions,drawPoints:t.drawPoints,drawTracker:t.drawTracker,animate:t.animate,getColumnMetrics:t.getColumnMetrics});m.gauge=
26
+ p(m.line,{dataLabels:{enabled:!0,y:15,borderWidth:1,borderColor:"silver",borderRadius:3,style:{fontWeight:"bold"},verticalAlign:"top",zIndex:2},dial:{},pivot:{},tooltip:{headerFormat:""},showInLegend:!1});u={type:"gauge",pointClass:l.extendClass(l.Point,{setState:function(a){this.state=a}}),angular:!0,drawGraph:w,trackerGroups:["group","dataLabels"],translate:function(){var a=this.yAxis,b=this.options,c=a.center;this.generatePoints();r(this.points,function(d){var g=p(b.dial,d.dial),f=v(q(g.radius,
27
+ 80))*c[2]/200,e=v(q(g.baseLength,70))*f/100,i=v(q(g.rearLength,10))*f/100,o=g.baseWidth||3,k=g.topWidth||1,j=a.startAngleRad+a.translate(d.y,null,null,null,!0);b.wrap===!1&&(j=Math.max(a.startAngleRad,Math.min(a.endAngleRad,j)));j=j*180/Math.PI;d.shapeType="path";d.shapeArgs={d:g.path||["M",-i,-o/2,"L",e,-o/2,f,-k/2,f,k/2,e,o/2,-i,o/2,"z"],translateX:c[0],translateY:c[1],rotation:j};d.plotX=c[0];d.plotY=c[1]})},drawPoints:function(){var a=this,b=a.yAxis.center,c=a.pivot,d=a.options,g=d.pivot,f=a.chart.renderer;
28
+ r(a.points,function(c){var b=c.graphic,g=c.shapeArgs,k=g.d,j=p(d.dial,c.dial);b?(b.animate(g),g.d=k):c.graphic=f[c.shapeType](g).attr({stroke:j.borderColor||"none","stroke-width":j.borderWidth||0,fill:j.backgroundColor||"black",rotation:g.rotation}).add(a.group)});c?c.animate({translateX:b[0],translateY:b[1]}):a.pivot=f.circle(0,0,q(g.radius,5)).attr({"stroke-width":g.borderWidth||0,stroke:g.borderColor||"silver",fill:g.backgroundColor||"black"}).translate(b[0],b[1]).add(a.group)},animate:function(a){var b=
29
+ this;if(!a)r(b.points,function(a){var d=a.graphic;d&&(d.attr({rotation:b.yAxis.startAngleRad*180/Math.PI}),d.animate({rotation:a.shapeArgs.rotation},b.options.animation))}),b.animate=null},render:function(){this.group=this.plotGroup("group","series",this.visible?"visible":"hidden",this.options.zIndex,this.chart.seriesGroup);h.pie.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:h.pie.prototype.setData,drawTracker:h.column.prototype.drawTracker};h.gauge=l.extendClass(h.line,
30
+ u);m.boxplot=p(m.column,{fillColor:"#FFFFFF",lineWidth:1,medianWidth:2,states:{hover:{brightness:-0.3}},threshold:null,tooltip:{pointFormat:'<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>Maximum: {point.high}<br/>Upper quartile: {point.q3}<br/>Median: {point.median}<br/>Lower quartile: {point.q1}<br/>Minimum: {point.low}<br/>'},whiskerLength:"50%",whiskerWidth:2});h.boxplot=x(h.column,{type:"boxplot",pointArrayMap:["low","q1","median","q3","high"],toYData:function(a){return[a.low,
31
+ a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"},drawDataLabels:w,translate:function(){var a=this.yAxis,b=this.pointArrayMap;h.column.prototype.translate.apply(this);r(this.points,function(c){r(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,g,f,e,i,o,k,j,h,l,m,n,H,p,E,I,t,w,s,v,u,z,y,x=a.doQuartiles!==!1,B=parseInt(a.options.whiskerLength,
32
+ 10)/100;r(b,function(b){l=b.graphic;z=b.shapeArgs;n={};E={};t={};y=b.color||a.color;if(b.plotY!==C)if(g=b.pointAttr[b.selected?"selected":""],w=z.width,s=A(z.x),v=s+w,u=D(w/2),f=A(x?b.q1Plot:b.lowPlot),e=A(x?b.q3Plot:b.lowPlot),i=A(b.highPlot),o=A(b.lowPlot),n.stroke=b.stemColor||c.stemColor||y,n["stroke-width"]=q(b.stemWidth,c.stemWidth,c.lineWidth),n.dashstyle=b.stemDashStyle||c.stemDashStyle,E.stroke=b.whiskerColor||c.whiskerColor||y,E["stroke-width"]=q(b.whiskerWidth,c.whiskerWidth,c.lineWidth),
33
+ t.stroke=b.medianColor||c.medianColor||y,t["stroke-width"]=q(b.medianWidth,c.medianWidth,c.lineWidth),j=n["stroke-width"]%2/2,h=s+u+j,m=["M",h,e,"L",h,i,"M",h,f,"L",h,o,"z"],x&&(j=g["stroke-width"]%2/2,h=A(h)+j,f=A(f)+j,e=A(e)+j,s+=j,v+=j,H=["M",s,e,"L",s,f,"L",v,f,"L",v,e,"L",s,e,"z"]),B&&(j=E["stroke-width"]%2/2,i+=j,o+=j,p=["M",h-u*B,i,"L",h+u*B,i,"M",h-u*B,o,"L",h+u*B,o]),j=t["stroke-width"]%2/2,k=D(b.medianPlot)+j,I=["M",s,k,"L",v,k,"z"],l)b.stem.animate({d:m}),B&&b.whiskers.animate({d:p}),x&&
34
+ b.box.animate({d:H}),b.medianShape.animate({d:I});else{b.graphic=l=d.g().add(a.group);b.stem=d.path(m).attr(n).add(l);if(B)b.whiskers=d.path(p).attr(E).add(l);if(x)b.box=d.path(H).attr(g).add(l);b.medianShape=d.path(I).attr(t).add(l)}})}});m.errorbar=p(m.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:m.arearange.tooltip.pointFormat},whiskerWidth:null});h.errorbar=x(h.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",
35
+ doQuartiles:!1,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||h.column.prototype.getColumnMetrics.call(this)}});m.waterfall=p(m.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333"});h.waterfall=x(h.column,{type:"waterfall",upColorProp:"fill",pointArrayMap:["low","y"],pointValKey:"y",init:function(a,b){b.stacking=!0;h.column.prototype.init.call(this,a,b)},translate:function(){var a=this.options,b=this.yAxis,c,d,g,f,e,i,o,k,j;c=a.threshold;
36
+ a=a.borderWidth%2/2;h.column.prototype.translate.apply(this);k=c;g=this.points;for(d=0,c=g.length;d<c;d++){f=g[d];e=f.shapeArgs;i=this.getStack(d);j=i.points[this.index];if(isNaN(f.y))f.y=this.yData[d];o=S(k,k+f.y)+j[0];e.y=b.translate(o,0,1);f.isSum||f.isIntermediateSum?(e.y=b.translate(j[1],0,1),e.height=b.translate(j[0],0,1)-e.y):k+=i.total;e.height<0&&(e.y+=e.height,e.height*=-1);f.plotY=e.y=D(e.y)-a;e.height=D(e.height);f.yBottom=e.y+e.height}},processData:function(a){var b=this.yData,c=this.points,
37
+ d,g=b.length,f=this.options.threshold||0,e,i,h,k,j,l;i=e=h=k=f;for(l=0;l<g;l++)j=b[l],d=c?c[l]:{},j==="sum"||d.isSum?b[l]=i:j==="intermediateSum"||d.isIntermediateSum?(b[l]=e,e=f):(i+=j,e+=j),h=Math.min(i,h),k=Math.max(i,k);z.prototype.processData.call(this,a);this.dataMin=h;this.dataMax=k},toYData:function(a){if(a.isSum)return"sum";else if(a.isIntermediateSum)return"intermediateSum";return a.y},getAttribs:function(){h.column.prototype.getAttribs.apply(this,arguments);var a=this.options,b=a.states,
38
+ c=a.upColor||this.color,a=l.Color(c).brighten(0.1).get(),d=p(this.pointAttr),g=this.upColorProp;d[""][g]=c;d.hover[g]=b.hover.upColor||a;d.select[g]=b.select.upColor||c;r(this.points,function(a){if(a.y>0&&!a.color)a.pointAttr=d,a.color=c})},getGraphPath:function(){var a=this.data,b=a.length,c=D(this.options.lineWidth+this.options.borderWidth)%2/2,d=[],g,f,e;for(e=1;e<b;e++)f=a[e].shapeArgs,g=a[e-1].shapeArgs,f=["M",g.x+g.width,g.y+c,"L",f.x,g.y+c],a[e-1].y<0&&(f[2]+=g.height,f[5]+=g.height),d=d.concat(f);
39
+ return d},getExtremes:w,getStack:function(a){var b=this.yAxis.stacks,c=this.stackKey;this.processedYData[a]<this.options.threshold&&(c="-"+c);return b[c][a]},drawGraph:z.prototype.drawGraph});m.bubble=p(m.scatter,{dataLabels:{inside:!0,style:{color:"white",textShadow:"0px 0px 3px black"},verticalAlign:"middle"},marker:{lineColor:null,lineWidth:1},minSize:8,maxSize:"20%",tooltip:{pointFormat:"({point.x}, {point.y}), Size: {point.z}"},turboThreshold:0,zThreshold:0});h.bubble=x(h.scatter,{type:"bubble",
40
+ pointArrayMap:["y","z"],trackerGroups:["group","dataLabelsGroup"],pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor"},applyOpacity:function(a){var b=this.options.marker,c=q(b.fillOpacity,0.5),a=a||b.fillColor||this.color;c!==1&&(a=l.Color(a).setOpacity(c).get("rgba"));return a},convertAttribs:function(){var a=z.prototype.convertAttribs.apply(this,arguments);a.fill=this.applyOpacity(a.fill);return a},getRadii:function(a,b,c,d){var g,f,e,i=this.zData,h=[];for(f=0,g=i.length;f<
41
+ g;f++)e=b-a,e=e>0?(i[f]-a)/(b-a):0.5,h.push(s.ceil(c+e*(d-c))/2);this.radii=h},animate:function(a){var b=this.options.animation;if(!a)r(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,g=this.radii;h.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=g?g[a]:0,c.negative=c.z<(this.options.zThreshold||0),d>=this.minPxSize/2?(c.shapeType="circle",c.shapeArgs={x:c.plotX,y:c.plotY,
42
+ r:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=C},drawLegendSymbol:function(a,b){var c=v(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:h.column.prototype.drawPoints,alignDataLabel:h.column.prototype.alignDataLabel});N.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,g=b,f=this.isXAxis,e=f?"xData":"yData",i=this.min,h={},
43
+ k=s.min(c.plotWidth,c.plotHeight),j=Number.MAX_VALUE,l=-Number.MAX_VALUE,m=this.max-i,n=b/m,p=[];this.tickPositions&&(r(this.series,function(b){var c=b.options;if(b.type==="bubble"&&b.visible&&(a.allowZoomOutside=!0,p.push(b),f))r(["minSize","maxSize"],function(a){var b=c[a],d=/%$/.test(b),b=v(b);h[a]=d?k*b/100:b}),b.minPxSize=h.minSize,b=b.zData,b.length&&(j=s.min(j,s.max(P(b),c.displayNegative===!1?c.zThreshold:-Number.MAX_VALUE)),l=s.max(l,Q(b)))}),r(p,function(a){var b=a[e],c=b.length,k;f&&a.getRadii(j,
44
+ l,h.minSize,h.maxSize);if(m>0)for(;c--;)k=a.radii[c],d=Math.min((b[c]-i)*n-k,d),g=Math.max((b[c]-i)*n+k,g)}),m>0&&q(this.options.min,this.userMin)===C&&q(this.options.max,this.userMax)===C&&(g-=b,n*=(b+d-g)/b,this.min+=d/n,this.max+=g/n))};var y=z.prototype,m=l.Pointer.prototype;y.toXY=function(a){var b,c=this.chart;b=a.plotX;var d=a.plotY;a.rectPlotX=b;a.rectPlotY=d;a.clientX=(b/Math.PI*180+this.xAxis.pane.options.startAngle)%360;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-d);a.plotX=a.polarPlotX=
45
+ b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop};y.orderTooltipPoints=function(a){if(this.chart.polar&&(a.sort(function(a,c){return a.clientX-c.clientX}),a[0]))a[0].wrappedClientX=a[0].clientX+360,a.push(a[0])};n(h.area.prototype,"init",K);n(h.areaspline.prototype,"init",K);n(h.spline.prototype,"getPointSpline",function(a,b,c,d){var g,f,e,i,h,k,j;if(this.chart.polar){g=c.plotX;f=c.plotY;a=b[d-1];e=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),e||(e=b[1]));if(a&&e)i=a.plotX,h=a.plotY,b=e.plotX,
46
+ k=e.plotY,i=(1.5*g+i)/2.5,h=(1.5*f+h)/2.5,e=(1.5*g+b)/2.5,j=(1.5*f+k)/2.5,b=Math.sqrt(Math.pow(i-g,2)+Math.pow(h-f,2)),k=Math.sqrt(Math.pow(e-g,2)+Math.pow(j-f,2)),i=Math.atan2(h-f,i-g),h=Math.atan2(j-f,e-g),j=Math.PI/2+(i+h)/2,Math.abs(i-j)>Math.PI/2&&(j-=Math.PI),i=g+Math.cos(j)*b,h=f+Math.sin(j)*b,e=g+Math.cos(Math.PI+j)*k,j=f+Math.sin(Math.PI+j)*k,c.rightContX=e,c.rightContY=j;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,i||g,h||f,g,f],a.rightContX=a.rightContY=null):c=["M",g,f]}else c=
47
+ a.call(this,b,c,d);return c});n(y,"translate",function(a){a.call(this);if(this.chart.polar&&!this.preventPostTranslate)for(var a=this.points,b=a.length;b--;)this.toXY(a[b])});n(y,"getSegmentPath",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length-1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});n(y,"animate",L);n(t,"animate",L);n(y,"setTooltipPoints",function(a,b){this.chart.polar&&F(this.xAxis,{tooltipLen:360});
48
+ return a.call(this,b)});n(t,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,g=b.startAngleRad,f=this.chart.renderer,e,h;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(h=b.length;h--;)e=b[h],a=e.barX+g,e.shapeType="path",e.shapeArgs={d:f.symbols.arc(d[0],d[1],c-e.plotY,null,{start:a,end:a+e.pointWidth,innerR:c-q(e.yBottom,c)})},this.toXY(e)}});n(t,"alignDataLabel",function(a,b,c,d,g,f){if(this.chart.polar){a=b.rectPlotX/Math.PI*180;if(d.align===null)d.align=
49
+ a>20&&a<160?"left":a>200&&a<340?"right":"center";if(d.verticalAlign===null)d.verticalAlign=a<45||a>315?"bottom":a>135&&a<225?"top":"middle";y.alignDataLabel.call(this,b,c,d,g,f)}else a.call(this,b,c,d,g,f)});n(m,"getIndex",function(a,b){var c,d=this.chart,g;d.polar?(g=d.xAxis[0].center,c=b.chartX-g[0]-d.plotLeft,d=b.chartY-g[1]-d.plotTop,c=180-Math.round(Math.atan2(c,d)/Math.PI*180)):c=a.call(this,b);return c});n(m,"getCoordinates",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?r(c.axes,
50
+ function(a){var f=a.isXAxis,e=a.center,h=b.chartX-e[0]-c.plotLeft,e=b.chartY-e[1]-c.plotTop;d[f?"xAxis":"yAxis"].push({axis:a,value:a.translate(f?Math.PI-Math.atan2(h,e):Math.sqrt(Math.pow(h,2)+Math.pow(e,2)),!0)})}):d=a.call(this,b);return d})})(Highcharts);