@grafit/era-dependencies 1.0.0

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