highcharts-rails 3.0.3 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);