highcharts-rails 5.0.14 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +60 -0
- data/Rakefile +54 -5
- data/app/assets/images/highcharts/earth.svg +432 -0
- data/app/assets/javascripts/highcharts.js +5103 -3147
- data/app/assets/javascripts/highcharts/highcharts-3d.js +930 -277
- data/app/assets/javascripts/highcharts/highcharts-more.js +1374 -249
- data/app/assets/javascripts/highcharts/lib/canvg.js +3073 -0
- data/app/assets/javascripts/highcharts/lib/jspdf.js +16624 -0
- data/app/assets/javascripts/highcharts/lib/rgbcolor.js +299 -0
- data/app/assets/javascripts/highcharts/lib/svg2pdf.js +3488 -0
- data/app/assets/javascripts/highcharts/modules/accessibility.js +654 -212
- data/app/assets/javascripts/highcharts/modules/annotations.js +1552 -274
- data/app/assets/javascripts/highcharts/modules/boost-canvas.js +773 -0
- data/app/assets/javascripts/highcharts/modules/boost.js +636 -210
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +2 -2
- data/app/assets/javascripts/highcharts/modules/bullet.js +364 -0
- data/app/assets/javascripts/highcharts/modules/data.js +766 -38
- data/app/assets/javascripts/highcharts/modules/drag-panes.js +588 -0
- data/app/assets/javascripts/highcharts/modules/drilldown.js +106 -36
- data/app/assets/javascripts/highcharts/modules/export-data.js +597 -0
- data/app/assets/javascripts/highcharts/modules/exporting.js +424 -162
- data/app/assets/javascripts/highcharts/modules/funnel.js +144 -22
- data/app/assets/javascripts/highcharts/modules/gantt.js +1154 -0
- data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
- data/app/assets/javascripts/highcharts/modules/heatmap.js +406 -80
- data/app/assets/javascripts/highcharts/modules/histogram-bellcurve.js +513 -0
- data/app/assets/javascripts/highcharts/modules/item-series.js +126 -0
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +31 -13
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +179 -57
- data/app/assets/javascripts/highcharts/modules/oldie.js +1378 -0
- data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +8 -6
- data/app/assets/javascripts/highcharts/modules/parallel-coordinates.js +494 -0
- data/app/assets/javascripts/highcharts/modules/pareto.js +275 -0
- data/app/assets/javascripts/highcharts/modules/sankey.js +641 -0
- data/app/assets/javascripts/highcharts/modules/series-label.js +355 -145
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +122 -1
- data/app/assets/javascripts/highcharts/modules/static-scale.js +64 -0
- data/app/assets/javascripts/highcharts/modules/stock.js +1944 -676
- data/app/assets/javascripts/highcharts/modules/streamgraph.js +139 -0
- data/app/assets/javascripts/highcharts/modules/sunburst.js +2403 -0
- data/app/assets/javascripts/highcharts/modules/tilemap.js +1199 -0
- data/app/assets/javascripts/highcharts/modules/treemap.js +538 -134
- data/app/assets/javascripts/highcharts/modules/variable-pie.js +490 -0
- data/app/assets/javascripts/highcharts/modules/variwide.js +283 -0
- data/app/assets/javascripts/highcharts/modules/vector.js +294 -0
- data/app/assets/javascripts/highcharts/modules/windbarb.js +490 -0
- data/app/assets/javascripts/highcharts/modules/wordcloud.js +681 -0
- data/app/assets/javascripts/highcharts/modules/xrange.js +615 -0
- data/app/assets/javascripts/highcharts/themes/avocado.js +54 -0
- data/app/assets/javascripts/highcharts/themes/dark-blue.js +6 -6
- data/app/assets/javascripts/highcharts/themes/dark-green.js +6 -6
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +6 -6
- data/app/assets/javascripts/highcharts/themes/gray.js +14 -10
- data/app/assets/javascripts/highcharts/themes/grid-light.js +6 -6
- data/app/assets/javascripts/highcharts/themes/grid.js +7 -5
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +8 -7
- data/app/assets/javascripts/highcharts/themes/skies.js +15 -9
- data/app/assets/javascripts/highcharts/themes/sunset.js +53 -0
- data/app/assets/stylesheets/highcharts/highcharts.css +802 -0
- data/app/assets/stylesheets/highcharts/highcharts.scss +665 -0
- data/lib/highcharts/version.rb +1 -1
- metadata +31 -1
@@ -1,5 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS
|
2
|
+
* @license Highcharts JS v6.0.0 (2017-10-04)
|
3
|
+
* Annotations module
|
3
4
|
*
|
4
5
|
* (c) 2009-2017 Torstein Honsi
|
5
6
|
*
|
@@ -15,393 +16,1670 @@
|
|
15
16
|
}(function(Highcharts) {
|
16
17
|
(function(H) {
|
17
18
|
/**
|
18
|
-
* (c) 2009-2017
|
19
|
+
* (c) 2009-2017 Highsoft, Black Label
|
19
20
|
*
|
20
21
|
* License: www.highcharts.com/license
|
21
22
|
*/
|
22
23
|
|
23
|
-
var
|
24
|
+
var merge = H.merge,
|
25
|
+
addEvent = H.addEvent,
|
26
|
+
extend = H.extend,
|
27
|
+
each = H.each,
|
28
|
+
isString = H.isString,
|
24
29
|
isNumber = H.isNumber,
|
30
|
+
defined = H.defined,
|
31
|
+
isObject = H.isObject,
|
25
32
|
inArray = H.inArray,
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
33
|
+
erase = H.erase,
|
34
|
+
find = H.find,
|
35
|
+
format = H.format,
|
36
|
+
pick = H.pick,
|
37
|
+
destroyObjectProperties = H.destroyObjectProperties,
|
38
|
+
|
39
|
+
tooltipPrototype = H.Tooltip.prototype,
|
40
|
+
seriesPrototype = H.Series.prototype,
|
41
|
+
chartPrototype = H.Chart.prototype;
|
31
42
|
|
32
|
-
var ALIGN_FACTOR,
|
33
|
-
ALLOWED_SHAPES;
|
34
43
|
|
35
|
-
|
44
|
+
/* ***************************************************************************
|
45
|
+
*
|
46
|
+
* MARKER SECTION
|
47
|
+
* Contains objects and functions for adding a marker element to a path element
|
48
|
+
*
|
49
|
+
**************************************************************************** */
|
36
50
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
51
|
+
/**
|
52
|
+
* Options for configuring markers for annotations.
|
53
|
+
*
|
54
|
+
* An example of the arrow marker:
|
55
|
+
* <pre>
|
56
|
+
* {
|
57
|
+
* arrow: {
|
58
|
+
* id: 'arrow',
|
59
|
+
* refY: 5,
|
60
|
+
* refX: 5,
|
61
|
+
* markerWidth: 10,
|
62
|
+
* markerHeight: 10,
|
63
|
+
* children: [{
|
64
|
+
* tagName: 'path',
|
65
|
+
* attrs: {
|
66
|
+
* d: 'M 0 0 L 10 5 L 0 10 Z',
|
67
|
+
* strokeWidth: 0
|
68
|
+
* }
|
69
|
+
* }]
|
70
|
+
* }
|
71
|
+
* }
|
72
|
+
* </pre>
|
73
|
+
* @type {Object}
|
74
|
+
* @sample highcharts/annotations/custom-markers/
|
75
|
+
* Define a custom marker for annotations
|
76
|
+
* @since 6.0.0
|
77
|
+
* @apioption defs.markers
|
78
|
+
*/
|
79
|
+
var defaultMarkers = {
|
80
|
+
arrow: {
|
81
|
+
render: false,
|
82
|
+
id: 'arrow',
|
83
|
+
refY: 5,
|
84
|
+
refX: 5,
|
85
|
+
markerWidth: 10,
|
86
|
+
markerHeight: 10,
|
87
|
+
children: [{
|
88
|
+
tagName: 'path',
|
89
|
+
attrs: {
|
90
|
+
d: 'M 0 0 L 10 5 L 0 10 Z', // triangle (used as an arrow)
|
91
|
+
strokeWidth: 0
|
92
|
+
}
|
93
|
+
}]
|
94
|
+
}
|
44
95
|
};
|
45
96
|
|
46
|
-
|
47
|
-
|
48
|
-
|
97
|
+
var MarkerMixin = {
|
98
|
+
markerSetter: function(markerType) {
|
99
|
+
return function(value) {
|
100
|
+
this.attr(markerType, 'url(#' + value + ')');
|
101
|
+
};
|
102
|
+
}
|
103
|
+
};
|
49
104
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
105
|
+
extend(MarkerMixin, {
|
106
|
+
markerEndSetter: MarkerMixin.markerSetter('marker-end'),
|
107
|
+
markerStartSetter: MarkerMixin.markerSetter('marker-start')
|
108
|
+
});
|
109
|
+
|
110
|
+
|
111
|
+
H.SVGRenderer.prototype.addMarker = function(id, markerOptions) {
|
112
|
+
var markerId = pick(id, H.uniqueKey()),
|
113
|
+
marker = this.createElement('marker').attr({
|
114
|
+
id: markerId,
|
115
|
+
markerWidth: pick(markerOptions.markerWidth, 20),
|
116
|
+
markerHeight: pick(markerOptions.markerHeight, 20),
|
117
|
+
refX: markerOptions.refX || 0,
|
118
|
+
refY: markerOptions.refY || 0,
|
119
|
+
orient: markerOptions.orient || 'auto'
|
120
|
+
}).add(this.defs),
|
121
|
+
|
122
|
+
attrs = {
|
123
|
+
stroke: markerOptions.color || 'none',
|
124
|
+
fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)'
|
58
125
|
},
|
59
|
-
|
60
|
-
params: {
|
61
|
-
stroke: '#000000',
|
62
|
-
fill: 'transparent',
|
63
|
-
strokeWidth: 2
|
64
|
-
}
|
65
|
-
}
|
66
|
-
};
|
126
|
+
children = markerOptions.children;
|
67
127
|
|
68
|
-
|
69
|
-
circle: {
|
70
|
-
params: {
|
71
|
-
x: 0,
|
72
|
-
y: 0
|
73
|
-
}
|
74
|
-
}
|
75
|
-
};
|
128
|
+
marker.id = markerId;
|
76
129
|
|
77
|
-
|
78
|
-
|
79
|
-
|
130
|
+
each(children, function(child) {
|
131
|
+
this.createElement(child.tagName)
|
132
|
+
.attr(merge(attrs, child.attrs))
|
133
|
+
.add(marker);
|
134
|
+
}, this);
|
80
135
|
|
81
|
-
return
|
82
|
-
}
|
136
|
+
return marker;
|
137
|
+
};
|
83
138
|
|
84
|
-
function translatePath(d, xAxis, yAxis, xOffset, yOffset) {
|
85
|
-
var len = d.length,
|
86
|
-
i = 0;
|
87
139
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
140
|
+
/* ***************************************************************************
|
141
|
+
*
|
142
|
+
* MOCK POINT
|
143
|
+
*
|
144
|
+
**************************************************************************** */
|
145
|
+
|
146
|
+
/**
|
147
|
+
* A mock point configuration.
|
148
|
+
*
|
149
|
+
* @typedef {Object} MockPointOptions
|
150
|
+
* @property {Number} x - x value for the point in xAxis scale or pixels
|
151
|
+
* @property {Number} y - y value for the point in yAxis scale or pixels
|
152
|
+
* @property {String|Number} [xAxis] - xAxis index or id
|
153
|
+
* @property {String|Number} [yAxis] - yAxis index or id
|
154
|
+
*/
|
155
|
+
|
156
|
+
|
157
|
+
/**
|
158
|
+
* A trimmed point object which imitates {@link Highchart.Point} class.
|
159
|
+
* It is created when there is a need of pointing to some chart's position
|
160
|
+
* using axis values or pixel values
|
161
|
+
*
|
162
|
+
* @class MockPoint
|
163
|
+
* @memberOf Highcharts
|
164
|
+
*
|
165
|
+
* @param {Highcharts.Chart} - the chart object
|
166
|
+
* @param {MockPointOptions} - the options object
|
167
|
+
*/
|
168
|
+
var MockPoint = H.MockPoint = function(chart, options) {
|
169
|
+
this.mock = true;
|
170
|
+
this.series = {
|
171
|
+
visible: true,
|
172
|
+
chart: chart,
|
173
|
+
getPlotBox: seriesPrototype.getPlotBox
|
174
|
+
};
|
97
175
|
|
98
|
-
|
99
|
-
|
176
|
+
// this.plotX
|
177
|
+
// this.plotY
|
100
178
|
|
179
|
+
/* Those might not exist if a specific axis was not found/defined */
|
180
|
+
// this.x?
|
181
|
+
// this.y?
|
101
182
|
|
102
|
-
|
103
|
-
var Annotation = function() {
|
104
|
-
this.init.apply(this, arguments);
|
183
|
+
this.init(chart, options);
|
105
184
|
};
|
106
|
-
|
107
|
-
|
108
|
-
|
185
|
+
|
186
|
+
/**
|
187
|
+
* A factory function for creating a mock point object
|
188
|
+
*
|
189
|
+
* @function #mockPoint
|
190
|
+
* @memberOf Highcharts
|
191
|
+
*
|
192
|
+
* @param {MockPointOptions} mockPointOptions
|
193
|
+
* @return {MockPoint} a mock point
|
194
|
+
*/
|
195
|
+
var mockPoint = H.mockPoint = function(chart, mockPointOptions) {
|
196
|
+
return new MockPoint(chart, mockPointOptions);
|
197
|
+
};
|
198
|
+
|
199
|
+
MockPoint.prototype = {
|
200
|
+
/**
|
201
|
+
* Initialisation of the mock point
|
202
|
+
*
|
203
|
+
* @function #init
|
204
|
+
* @memberOf Highcharts.MockPoint#
|
205
|
+
*
|
206
|
+
* @param {Highcharts.Chart} chart - a chart object to which the mock point
|
207
|
+
* is attached
|
208
|
+
* @param {MockPointOptions} options - a config for the mock point
|
109
209
|
*/
|
110
210
|
init: function(chart, options) {
|
111
|
-
var
|
211
|
+
var xAxisId = options.xAxis,
|
212
|
+
xAxis = defined(xAxisId) ?
|
213
|
+
chart.xAxis[xAxisId] || chart.get(xAxisId) :
|
214
|
+
null,
|
215
|
+
|
216
|
+
yAxisId = options.yAxis,
|
217
|
+
yAxis = defined(yAxisId) ?
|
218
|
+
chart.yAxis[yAxisId] || chart.get(yAxisId) :
|
219
|
+
null;
|
112
220
|
|
113
|
-
|
114
|
-
|
221
|
+
|
222
|
+
if (xAxis) {
|
223
|
+
this.x = options.x;
|
224
|
+
this.series.xAxis = xAxis;
|
225
|
+
} else {
|
226
|
+
this.plotX = options.x;
|
227
|
+
}
|
228
|
+
|
229
|
+
if (yAxis) {
|
230
|
+
this.y = options.y;
|
231
|
+
this.series.yAxis = yAxis;
|
232
|
+
} else {
|
233
|
+
this.plotY = options.y;
|
234
|
+
}
|
115
235
|
},
|
116
236
|
|
117
|
-
|
118
|
-
*
|
237
|
+
/**
|
238
|
+
* Update of the point's coordinates (plotX/plotY)
|
239
|
+
*
|
240
|
+
* @function #translate
|
241
|
+
* @memberOf Highcharts.MockPoint#
|
242
|
+
*
|
243
|
+
* @return {undefined}
|
119
244
|
*/
|
120
|
-
|
121
|
-
var
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
group = annotation.group = renderer.g();
|
245
|
+
translate: function() {
|
246
|
+
var series = this.series,
|
247
|
+
xAxis = series.xAxis,
|
248
|
+
yAxis = series.yAxis,
|
249
|
+
plotX = this.plotX,
|
250
|
+
plotY = this.plotY,
|
251
|
+
isInside = true;
|
252
|
+
|
253
|
+
if (xAxis) {
|
254
|
+
this.plotX = plotX = xAxis.toPixels(this.x, true);
|
255
|
+
|
256
|
+
isInside = plotX >= 0 && plotX <= xAxis.len;
|
133
257
|
}
|
134
258
|
|
259
|
+
if (yAxis) {
|
260
|
+
this.plotY = plotY = yAxis.toPixels(this.y, true);
|
135
261
|
|
136
|
-
|
137
|
-
shape = annotation.shape = renderer[options.shape.type](shapeOptions.params);
|
138
|
-
shape.add(group);
|
262
|
+
isInside = isInside && plotY >= 0 && plotY <= yAxis.len;
|
139
263
|
}
|
140
264
|
|
141
|
-
|
142
|
-
|
143
|
-
|
265
|
+
this.isInside = isInside;
|
266
|
+
},
|
267
|
+
|
268
|
+
/**
|
269
|
+
* Returns a box to which an item can be aligned to
|
270
|
+
*
|
271
|
+
* @function #alignToBox
|
272
|
+
* @memberOf Highcharts.MockPoint#
|
273
|
+
*
|
274
|
+
* @param {Boolean} [forceTranslate=false] - whether to update the point's
|
275
|
+
* coordinates
|
276
|
+
* @return {Array.<Number>} A quadruple of numbers which denotes x, y,
|
277
|
+
* width and height of the box
|
278
|
+
**/
|
279
|
+
alignToBox: function(forceTranslate) {
|
280
|
+
if (forceTranslate) {
|
281
|
+
this.translate();
|
144
282
|
}
|
145
283
|
|
146
|
-
|
284
|
+
var x = this.plotX,
|
285
|
+
y = this.plotY,
|
286
|
+
temp;
|
147
287
|
|
148
|
-
// link annotations to point or series
|
149
|
-
annotation.linkObjects();
|
150
288
|
|
151
|
-
if (
|
152
|
-
|
289
|
+
if (this.series.chart.inverted) {
|
290
|
+
temp = x;
|
291
|
+
x = y;
|
292
|
+
y = temp;
|
153
293
|
}
|
294
|
+
|
295
|
+
return [x, y, 0, 0];
|
154
296
|
},
|
155
297
|
|
156
|
-
|
157
|
-
*
|
298
|
+
/**
|
299
|
+
* Returns a label config object -
|
300
|
+
* the same as Highcharts.Point.prototype.getLabelConfig
|
301
|
+
*
|
302
|
+
* @function #getLabelConfig
|
303
|
+
* @memberOf Highcharts.MockPoint#
|
304
|
+
*
|
305
|
+
* @return {Object} labelConfig - label config object
|
306
|
+
* @return {Number|undefined} labelConfig.x - x value translated to x axis scale
|
307
|
+
* @return {Number|undefined} labelConfig.y - y value translated to y axis scale
|
308
|
+
* @return {MockPoint} labelConfig.point - the instance of the point
|
309
|
+
*/
|
310
|
+
getLabelConfig: function() {
|
311
|
+
return {
|
312
|
+
x: this.x,
|
313
|
+
y: this.y,
|
314
|
+
point: this
|
315
|
+
};
|
316
|
+
}
|
317
|
+
};
|
318
|
+
|
319
|
+
|
320
|
+
/* ***************************************************************************
|
321
|
+
*
|
322
|
+
* ANNOTATION
|
323
|
+
*
|
324
|
+
**************************************************************************** */
|
325
|
+
|
326
|
+
H.defaultOptions.annotations = [];
|
327
|
+
|
328
|
+
/**
|
329
|
+
* An annotation class which serves as a container for items like labels or shapes.
|
330
|
+
* Created items are positioned on the chart either by linking them to
|
331
|
+
* existing points or created mock points
|
332
|
+
*
|
333
|
+
* @class Annotation
|
334
|
+
* @memberOf Highcharts
|
335
|
+
*
|
336
|
+
* @param {Highcharts.Chart} - the chart object
|
337
|
+
* @param {AnnotationOptions} - the options object
|
338
|
+
*/
|
339
|
+
var Annotation = H.Annotation = function(chart, userOptions) {
|
340
|
+
this.chart = chart;
|
341
|
+
|
342
|
+
this.labels = [];
|
343
|
+
this.shapes = [];
|
344
|
+
|
345
|
+
this.options = merge(this.defaultOptions, userOptions);
|
346
|
+
|
347
|
+
this.init(chart, userOptions);
|
348
|
+
};
|
349
|
+
|
350
|
+
Annotation.prototype = {
|
351
|
+
/**
|
352
|
+
* Shapes which do not have background - the object is used for proper
|
353
|
+
* setting of the contrast color
|
354
|
+
*
|
355
|
+
* @memberOf Highcharts.Annotation#
|
356
|
+
* @type {Array.<String>}
|
158
357
|
*/
|
358
|
+
shapesWithoutBackground: ['connector'],
|
359
|
+
|
360
|
+
/**
|
361
|
+
* A map object which allows to map options attributes to element attributes
|
362
|
+
*
|
363
|
+
* @memberOf Highcharts.Annotation#
|
364
|
+
* @type {Object}
|
365
|
+
*/
|
366
|
+
attrsMap: {
|
367
|
+
backgroundColor: 'fill',
|
368
|
+
borderColor: 'stroke',
|
369
|
+
borderWidth: 'stroke-width',
|
370
|
+
strokeWidth: 'stroke-width',
|
371
|
+
stroke: 'stroke',
|
372
|
+
fill: 'fill',
|
373
|
+
zIndex: 'zIndex',
|
374
|
+
width: 'width',
|
375
|
+
height: 'height',
|
376
|
+
borderRadius: 'r',
|
377
|
+
r: 'r',
|
378
|
+
padding: 'padding',
|
379
|
+
dashStyle: 'dashstyle'
|
380
|
+
},
|
381
|
+
|
382
|
+
/**
|
383
|
+
* Options for configuring annotations, for example labels, arrows or
|
384
|
+
* shapes. Annotations can be tied to points, axis coordinates or chart
|
385
|
+
* pixel coordinates.
|
386
|
+
*
|
387
|
+
* @type {Array<Object>}
|
388
|
+
* @sample highcharts/annotations/basic/
|
389
|
+
* Basic annotations
|
390
|
+
* @sample {highstock} stock/annotations/fibonacci-retracements
|
391
|
+
* Custom annotation, Fibonacci retracement
|
392
|
+
* @since 6.0.0
|
393
|
+
* @optionparent annotations
|
394
|
+
**/
|
395
|
+
defaultOptions: {
|
396
|
+
|
397
|
+
/**
|
398
|
+
* Whether the annotation is visible.
|
399
|
+
*
|
400
|
+
* @sample highcharts/annotations/visible/
|
401
|
+
* Set annotation visibility
|
402
|
+
*/
|
403
|
+
visible: true,
|
404
|
+
|
405
|
+
/**
|
406
|
+
* Options for annotation's labels. Each label inherits options
|
407
|
+
* from the labelOptions object. An option from the labelOptions can be
|
408
|
+
* overwritten by config for a specific label.
|
409
|
+
*/
|
410
|
+
labelOptions: {
|
411
|
+
|
412
|
+
/**
|
413
|
+
* The alignment of the annotation's label. If right,
|
414
|
+
* the right side of the label should be touching the point.
|
415
|
+
*
|
416
|
+
* @validvalue ["left", "center", "right"]
|
417
|
+
* @sample highcharts/annotations/label-position/
|
418
|
+
* Set labels position
|
419
|
+
*/
|
420
|
+
align: 'center',
|
421
|
+
|
422
|
+
/**
|
423
|
+
* Whether to allow the annotation's labels to overlap.
|
424
|
+
* To make the labels less sensitive for overlapping,
|
425
|
+
* the can be set to 0.
|
426
|
+
*
|
427
|
+
* @sample highcharts/annotations/tooltip-like/
|
428
|
+
* Hide overlapping labels
|
429
|
+
*/
|
430
|
+
allowOverlap: false,
|
431
|
+
|
432
|
+
/**
|
433
|
+
* The background color or gradient for the annotation's label.
|
434
|
+
*
|
435
|
+
* @type {Color}
|
436
|
+
* @sample highcharts/annotations/label-presentation/
|
437
|
+
* Set labels graphic options
|
438
|
+
*/
|
439
|
+
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
440
|
+
|
441
|
+
/**
|
442
|
+
* The border color for the annotation's label.
|
443
|
+
*
|
444
|
+
* @type {Color}
|
445
|
+
* @sample highcharts/annotations/label-presentation/
|
446
|
+
* Set labels graphic options
|
447
|
+
*/
|
448
|
+
borderColor: 'black',
|
449
|
+
|
450
|
+
/**
|
451
|
+
* The border radius in pixels for the annotaiton's label.
|
452
|
+
*
|
453
|
+
* @sample highcharts/annotations/label-presentation/
|
454
|
+
* Set labels graphic options
|
455
|
+
*/
|
456
|
+
borderRadius: 1,
|
457
|
+
|
458
|
+
/**
|
459
|
+
* The border width in pixels for the annotation's label
|
460
|
+
*
|
461
|
+
* @sample highcharts/annotations/label-presentation/
|
462
|
+
* Set labels graphic options
|
463
|
+
*/
|
464
|
+
borderWidth: 1,
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Whether to hide the annotation's label that is outside the plot area.
|
468
|
+
*
|
469
|
+
* @sample highcharts/annotations/label-crop-overflow/
|
470
|
+
* Crop or justify labels
|
471
|
+
*/
|
472
|
+
crop: false,
|
473
|
+
|
474
|
+
/**
|
475
|
+
* A [format](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) string for the data label.
|
476
|
+
*
|
477
|
+
* @type {String}
|
478
|
+
* @see [plotOptions.series.dataLabels.format](plotOptions.series.dataLabels.format.html)
|
479
|
+
* @sample highcharts/annotations/label-text/
|
480
|
+
* Set labels text
|
481
|
+
* @default undefined
|
482
|
+
* @apioption annotations.labelOptions.format
|
483
|
+
**/
|
484
|
+
|
485
|
+
/**
|
486
|
+
* Alias for the format option.
|
487
|
+
*
|
488
|
+
* @type {String}
|
489
|
+
* @see [format](annotations.labelOptions.format.html)
|
490
|
+
* @sample highcharts/annotations/label-text/
|
491
|
+
* Set labels text
|
492
|
+
* @default undefined
|
493
|
+
* @apioption annotations.labelOptions.text
|
494
|
+
*/
|
495
|
+
|
496
|
+
/**
|
497
|
+
* Callback JavaScript function to format the annotation's label. Note that
|
498
|
+
* if a `format` or `text` are defined, the format or text take precedence
|
499
|
+
* and the formatter is ignored. `This` refers to a point object.
|
500
|
+
*
|
501
|
+
* @type {Function}
|
502
|
+
* @sample highcharts/annotations/label-text/
|
503
|
+
* Set labels text
|
504
|
+
* @default function () {
|
505
|
+
* return defined(this.y) ? this.y : 'Annotation label';
|
506
|
+
* }
|
507
|
+
**/
|
508
|
+
formatter: function() {
|
509
|
+
return defined(this.y) ? this.y : 'Annotation label';
|
510
|
+
},
|
511
|
+
|
512
|
+
/**
|
513
|
+
* How to handle the annotation's label that flow outside the plot
|
514
|
+
* area. The justify option aligns the label inside the plot area.
|
515
|
+
*
|
516
|
+
* @validvalue ["none", "justify"]
|
517
|
+
* @sample highcharts/annotations/label-crop-overflow/
|
518
|
+
* Crop or justify labels
|
519
|
+
**/
|
520
|
+
overflow: 'justify',
|
521
|
+
|
522
|
+
/**
|
523
|
+
* When either the borderWidth or the backgroundColor is set,
|
524
|
+
* this is the padding within the box.
|
525
|
+
*
|
526
|
+
* @sample highcharts/annotations/label-presentation/
|
527
|
+
* Set labels graphic options
|
528
|
+
*/
|
529
|
+
padding: 5,
|
530
|
+
|
531
|
+
/**
|
532
|
+
* The shadow of the box. The shadow can be an object configuration
|
533
|
+
* containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
|
534
|
+
*
|
535
|
+
* @type {Boolean|Object}
|
536
|
+
* @sample highcharts/annotations/label-presentation/
|
537
|
+
* Set labels graphic options
|
538
|
+
*/
|
539
|
+
shadow: false,
|
540
|
+
|
541
|
+
/**
|
542
|
+
* The name of a symbol to use for the border around the label.
|
543
|
+
* Symbols are predefined functions on the Renderer object.
|
544
|
+
*
|
545
|
+
* @type {String}
|
546
|
+
* @sample highcharts/annotations/shapes/
|
547
|
+
* Available shapes for labels
|
548
|
+
**/
|
549
|
+
shape: 'callout',
|
550
|
+
|
551
|
+
/**
|
552
|
+
* Styles for the annotation's label.
|
553
|
+
*
|
554
|
+
* @type {CSSObject}
|
555
|
+
* @sample highcharts/annotations/label-presentation/
|
556
|
+
* Set labels graphic options
|
557
|
+
* @see [plotOptions.series.dataLabels.style](plotOptions.series.dataLabels.style.html)
|
558
|
+
**/
|
559
|
+
style: {
|
560
|
+
fontSize: '11px',
|
561
|
+
fontWeigth: 'bold',
|
562
|
+
color: 'contrast'
|
563
|
+
},
|
564
|
+
|
565
|
+
/**
|
566
|
+
* Whether to [use HTML](http://www.highcharts.com/docs/chart-concepts/labels-
|
567
|
+
* and-string-formatting#html) to render the annotation's label.
|
568
|
+
*
|
569
|
+
* @type {Boolean}
|
570
|
+
* @default false
|
571
|
+
**/
|
572
|
+
useHTML: false,
|
573
|
+
|
574
|
+
/**
|
575
|
+
* The vertical alignment of the annotation's label.
|
576
|
+
*
|
577
|
+
* @type {String}
|
578
|
+
* @validvalue ["top", "middle", "bottom"]
|
579
|
+
* @sample highcharts/annotations/label-position/
|
580
|
+
* Set labels position
|
581
|
+
**/
|
582
|
+
verticalAlign: 'bottom',
|
583
|
+
|
584
|
+
/**
|
585
|
+
* The x position offset of the label relative to the point.
|
586
|
+
* Note that if a `distance` is defined, the distance takes
|
587
|
+
* precedence over `x` and `y` options.
|
588
|
+
*
|
589
|
+
* @sample highcharts/annotations/label-position/
|
590
|
+
* Set labels position
|
591
|
+
**/
|
592
|
+
x: 0,
|
593
|
+
|
594
|
+
/**
|
595
|
+
* The y position offset of the label relative to the point.
|
596
|
+
* Note that if a `distance` is defined, the distance takes
|
597
|
+
* precedence over `x` and `y` options.
|
598
|
+
*
|
599
|
+
* @sample highcharts/annotations/label-position/
|
600
|
+
* Set labels position
|
601
|
+
**/
|
602
|
+
y: -16
|
603
|
+
|
604
|
+
/**
|
605
|
+
* The label's pixel distance from the point.
|
606
|
+
*
|
607
|
+
* @type {Number}
|
608
|
+
* @sample highcharts/annotations/label-position/
|
609
|
+
* Set labels position
|
610
|
+
* @default undefined
|
611
|
+
* @apioption annotations.labelOptions.distance
|
612
|
+
**/
|
613
|
+
},
|
614
|
+
|
615
|
+
/**
|
616
|
+
* An array of labels for the annotation. For options that apply to multiple
|
617
|
+
* labels, they can be added to the [labelOptions](annotations.labelOptions.html).
|
618
|
+
*
|
619
|
+
* @type {Array<Object>}
|
620
|
+
* @extends annotations.labelOptions
|
621
|
+
* @apioption annotations.labels
|
622
|
+
*/
|
623
|
+
|
624
|
+
/**
|
625
|
+
* This option defines the point to which the label will be connected.
|
626
|
+
* It can be either the point which exists in the series - it is referenced
|
627
|
+
* by the point's id - or a new point with defined x, y properies
|
628
|
+
* and optionally axes.
|
629
|
+
*
|
630
|
+
* @type {String|Object}
|
631
|
+
* @sample highcharts/annotations/mock-point/
|
632
|
+
* Attach annotation to a mock point
|
633
|
+
* @apioption annotations.labels.point
|
634
|
+
*/
|
635
|
+
|
636
|
+
/**
|
637
|
+
* The x position of the point. Units can be either in axis
|
638
|
+
* or chart pixel coordinates.
|
639
|
+
*
|
640
|
+
* @type {Number}
|
641
|
+
* @apioption annotations.labels.point.x
|
642
|
+
*/
|
643
|
+
|
644
|
+
/**
|
645
|
+
* The y position of the point. Units can be either in axis
|
646
|
+
* or chart pixel coordinates.
|
647
|
+
*
|
648
|
+
* @type {Number}
|
649
|
+
* @apioption annotations.labels.point.y
|
650
|
+
*/
|
651
|
+
|
652
|
+
/**
|
653
|
+
* This number defines which xAxis the point is connected to. It refers
|
654
|
+
* to either the axis id or the index of the axis in the xAxis array.
|
655
|
+
* If the option is not configured or the axis is not found the point's
|
656
|
+
* x coordinate refers to the chart pixels.
|
657
|
+
*
|
658
|
+
* @type {Number|String}
|
659
|
+
* @apioption annotations.labels.point.xAxis
|
660
|
+
*/
|
661
|
+
|
662
|
+
/**
|
663
|
+
* This number defines which yAxis the point is connected to. It refers
|
664
|
+
* to either the axis id or the index of the axis in the yAxis array.
|
665
|
+
* If the option is not configured or the axis is not found the point's
|
666
|
+
* y coordinate refers to the chart pixels.
|
667
|
+
*
|
668
|
+
* @type {Number|String}
|
669
|
+
* @apioption annotations.labels.point.yAxis
|
670
|
+
*/
|
671
|
+
|
672
|
+
|
673
|
+
/**
|
674
|
+
* Options for annotation's shapes. Each shape inherits options
|
675
|
+
* from the shapeOptions object. An option from the shapeOptions can be
|
676
|
+
* overwritten by config for a specific shape.
|
677
|
+
*
|
678
|
+
* @type {Object}
|
679
|
+
**/
|
680
|
+
shapeOptions: {
|
681
|
+
|
682
|
+
/**
|
683
|
+
* The color of the shape's stroke.
|
684
|
+
*
|
685
|
+
* @type {Color}
|
686
|
+
* @sample highcharts/annotations/shape/
|
687
|
+
* Basic shape annotation
|
688
|
+
**/
|
689
|
+
stroke: 'rgba(0, 0, 0, 0.75)',
|
690
|
+
|
691
|
+
/**
|
692
|
+
* The pixel stroke width of the shape.
|
693
|
+
*
|
694
|
+
* @sample highcharts/annotations/shape/
|
695
|
+
* Basic shape annotation
|
696
|
+
**/
|
697
|
+
strokeWidth: 1,
|
698
|
+
|
699
|
+
/**
|
700
|
+
* The color of the shape's fill.
|
701
|
+
*
|
702
|
+
* @type {Color}
|
703
|
+
* @sample highcharts/annotations/shape/
|
704
|
+
* Basic shape annotation
|
705
|
+
**/
|
706
|
+
fill: 'rgba(0, 0, 0, 0.75)',
|
707
|
+
|
708
|
+
/**
|
709
|
+
* The type of the shape, e.g. circle or rectangle.
|
710
|
+
*
|
711
|
+
* @type {String}
|
712
|
+
* @sample highcharts/annotations/shape/
|
713
|
+
* Basic shape annotation
|
714
|
+
* @default 'rect'
|
715
|
+
* @apioption annotations.shapeOptions.type
|
716
|
+
**/
|
717
|
+
|
718
|
+
/**
|
719
|
+
* The radius of the shape.
|
720
|
+
*
|
721
|
+
* @sample highcharts/annotations/shape/
|
722
|
+
* Basic shape annotation
|
723
|
+
**/
|
724
|
+
r: 0
|
725
|
+
|
726
|
+
/**
|
727
|
+
* The width of the shape.
|
728
|
+
*
|
729
|
+
* @type {Number}
|
730
|
+
* @sample highcharts/annotations/shape/
|
731
|
+
* Basic shape annotation
|
732
|
+
* @apioption annotations.shapeOptions.width
|
733
|
+
**/
|
734
|
+
|
735
|
+
/**
|
736
|
+
* The height of the shape.
|
737
|
+
*
|
738
|
+
* @type {Number}
|
739
|
+
* @sample highcharts/annotations/shape/
|
740
|
+
* Basic shape annotation
|
741
|
+
* @apioption annotations.shapeOptions.height
|
742
|
+
**/
|
743
|
+
},
|
744
|
+
|
745
|
+
/**
|
746
|
+
* The Z index of the annotation.
|
747
|
+
*
|
748
|
+
* @type {Number}
|
749
|
+
* @default 6
|
750
|
+
**/
|
751
|
+
zIndex: 6
|
752
|
+
|
753
|
+
/**
|
754
|
+
* An array of shapes for the annotation. For options that apply to multiple
|
755
|
+
* shapes, then can be added to the [shapeOptions](annotations.shapeOptions.html).
|
756
|
+
*
|
757
|
+
* @type {Array<Object>}
|
758
|
+
* @extends annotations.shapeOptions
|
759
|
+
* @apioption annotations.shapes
|
760
|
+
*/
|
761
|
+
|
762
|
+
/**
|
763
|
+
* This option defines the point to which the shape will be connected.
|
764
|
+
* It can be either the point which exists in the series - it is referenced
|
765
|
+
* by the point's id - or a new point with defined x, y properties
|
766
|
+
* and optionally axes.
|
767
|
+
*
|
768
|
+
* @type {String|Object}
|
769
|
+
* @extends annotations.labels.point
|
770
|
+
* @apioption annotations.shapes.point
|
771
|
+
*/
|
772
|
+
|
773
|
+
/**
|
774
|
+
* An array of points for the shape. This option is available for shapes
|
775
|
+
* which can use multiple points such as path. A point can be either
|
776
|
+
* a point object or a point's id.
|
777
|
+
*
|
778
|
+
* @type {Array}
|
779
|
+
* @see [annotations.shapes.point](annotations.shapes.point.html)
|
780
|
+
* @apioption annotations.shapes.points
|
781
|
+
*/
|
782
|
+
|
783
|
+
/**
|
784
|
+
* Id of the marker which will be drawn at the final vertex of the path.
|
785
|
+
* Custom markers can be defined in defs property.
|
786
|
+
*
|
787
|
+
* @type {String}
|
788
|
+
* @see [defs.markers](defs.markers.html)
|
789
|
+
* @sample highcharts/annotations/custom-markers/
|
790
|
+
* Define a custom marker for annotations
|
791
|
+
* @apioption annotations.shapes.markerEnd
|
792
|
+
**/
|
793
|
+
|
794
|
+
/**
|
795
|
+
* Id of the marker which will be drawn at the first vertex of the path.
|
796
|
+
* Custom markers can be defined in defs property.
|
797
|
+
*
|
798
|
+
* @type {String}
|
799
|
+
* @see [defs.markers](defs.markers.html)
|
800
|
+
* @sample {highcharts} highcharts/annotations/custom-markers/
|
801
|
+
* Define a custom marker for annotations
|
802
|
+
* @apioption annotations.shapes.markerStart
|
803
|
+
**/
|
804
|
+
},
|
805
|
+
|
806
|
+
/**
|
807
|
+
* Annotation initialisation
|
808
|
+
*
|
809
|
+
* @function #init
|
810
|
+
* @memberOf Highcharts.Annotation#
|
811
|
+
*
|
812
|
+
* @return {undefined}
|
813
|
+
**/
|
814
|
+
init: function() {
|
815
|
+
var anno = this;
|
816
|
+
each(this.options.labels || [], this.initLabel, this);
|
817
|
+
each(this.options.shapes || [], this.initShape, this);
|
818
|
+
|
819
|
+
// Push the callback that reports to the overlapping-labels module which
|
820
|
+
// labels it should account for.
|
821
|
+
this.chart.labelCollectors.push(function() {
|
822
|
+
var labels = [];
|
823
|
+
each(anno.labels, function(label) {
|
824
|
+
if (!label.options.allowOverlap) {
|
825
|
+
labels.push(label);
|
826
|
+
}
|
827
|
+
});
|
828
|
+
return labels;
|
829
|
+
});
|
830
|
+
},
|
831
|
+
|
832
|
+
/**
|
833
|
+
* Main method for drawing an annotation, it is called everytime on chart redraw
|
834
|
+
* and once on chart's load
|
835
|
+
*
|
836
|
+
* @function #redraw
|
837
|
+
* @memberOf Highcharts.Annotation#
|
838
|
+
*
|
839
|
+
* @return {undefined}
|
840
|
+
**/
|
159
841
|
redraw: function() {
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
title = this.title,
|
164
|
-
shape = this.shape,
|
165
|
-
linkedTo = this.linkedObject,
|
166
|
-
xAxis = chart.xAxis[options.xAxis],
|
167
|
-
yAxis = chart.yAxis[options.yAxis],
|
168
|
-
width = options.width,
|
169
|
-
height = options.height,
|
170
|
-
anchorY = ALIGN_FACTOR[options.anchorY],
|
171
|
-
anchorX = ALIGN_FACTOR[options.anchorX],
|
172
|
-
shapeParams,
|
173
|
-
linkType,
|
174
|
-
series,
|
175
|
-
bbox,
|
176
|
-
x,
|
177
|
-
y;
|
178
|
-
|
179
|
-
if (linkedTo) {
|
180
|
-
linkType = (linkedTo instanceof H.Point) ? 'point' :
|
181
|
-
(linkedTo instanceof H.Series) ? 'series' : null;
|
182
|
-
|
183
|
-
if (linkType === 'point') {
|
184
|
-
options.xValue = linkedTo.x;
|
185
|
-
options.yValue = linkedTo.y;
|
186
|
-
series = linkedTo.series;
|
187
|
-
} else if (linkType === 'series') {
|
188
|
-
series = linkedTo;
|
189
|
-
}
|
842
|
+
if (!this.group) {
|
843
|
+
this.render();
|
844
|
+
}
|
190
845
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
846
|
+
this.redrawItems(this.shapes);
|
847
|
+
this.redrawItems(this.labels);
|
848
|
+
},
|
849
|
+
|
850
|
+
/**
|
851
|
+
* @function #redrawItems
|
852
|
+
* @memberOf Highcharts.Annotation#
|
853
|
+
*
|
854
|
+
* @param {Array<Object>} items
|
855
|
+
* @return {undefined}
|
856
|
+
**/
|
857
|
+
redrawItems: function(items) {
|
858
|
+
var i = items.length;
|
859
|
+
|
860
|
+
// needs a backward loop
|
861
|
+
// labels/shapes array might be modified due to destruction of the item
|
862
|
+
while (i--) {
|
863
|
+
this.redrawItem(items[i]);
|
196
864
|
}
|
865
|
+
},
|
197
866
|
|
867
|
+
/**
|
868
|
+
* @function #render
|
869
|
+
* @memberOf Highcharts.Annotation#
|
870
|
+
*
|
871
|
+
* @return {undefined}
|
872
|
+
**/
|
873
|
+
render: function() {
|
874
|
+
var renderer = this.chart.renderer;
|
875
|
+
|
876
|
+
var group = this.group = renderer.g('annotation')
|
877
|
+
.attr({
|
878
|
+
zIndex: this.options.zIndex,
|
879
|
+
visibility: this.options.visible ? 'visible' : 'hidden'
|
880
|
+
})
|
881
|
+
.add();
|
882
|
+
|
883
|
+
this.shapesGroup = renderer.g('annotation-shapes').add(group);
|
884
|
+
this.labelsGroup = renderer.g('annotation-labels').attr({
|
885
|
+
// hideOverlappingLabels requires translation
|
886
|
+
translateX: 0,
|
887
|
+
translateY: 0
|
888
|
+
}).add(group);
|
889
|
+
|
890
|
+
this.shapesGroup.clip(this.chart.plotBoxClip);
|
891
|
+
},
|
198
892
|
|
199
|
-
|
200
|
-
|
201
|
-
|
893
|
+
/**
|
894
|
+
* @function #setVisible
|
895
|
+
* @memberOf Highcharts.Annotation#
|
896
|
+
*
|
897
|
+
* @param {Boolean} [visibility] - whether to show or hide an annotation.
|
898
|
+
* If the param is omitted, the annotation's visibility is toggled
|
899
|
+
* @return {undefined}
|
900
|
+
**/
|
901
|
+
setVisible: function(visibility) {
|
902
|
+
var options = this.options,
|
903
|
+
visible = pick(visibility, !options.visible);
|
904
|
+
|
905
|
+
this.group.attr({
|
906
|
+
visibility: visible ? 'visible' : 'hidden'
|
907
|
+
});
|
202
908
|
|
203
|
-
|
204
|
-
|
909
|
+
options.visible = visible;
|
910
|
+
},
|
911
|
+
|
912
|
+
|
913
|
+
/**
|
914
|
+
* Destroying an annotation
|
915
|
+
*
|
916
|
+
* @function #destroy
|
917
|
+
* @memberOf Highcharts.Annotation#
|
918
|
+
*
|
919
|
+
* @return {undefined}
|
920
|
+
**/
|
921
|
+
destroy: function() {
|
922
|
+
var chart = this.chart;
|
923
|
+
|
924
|
+
each(this.labels, function(label) {
|
925
|
+
label.destroy();
|
926
|
+
});
|
927
|
+
|
928
|
+
each(this.shapes, function(shape) {
|
929
|
+
shape.destroy();
|
930
|
+
});
|
931
|
+
|
932
|
+
destroyObjectProperties(this, chart);
|
933
|
+
},
|
934
|
+
|
935
|
+
|
936
|
+
/* ***********************************************************************
|
937
|
+
* ITEM SECTION
|
938
|
+
* Contains methods for handling a single item in an annotation
|
939
|
+
*********************************************************************** */
|
940
|
+
|
941
|
+
/**
|
942
|
+
* Initialisation of a single shape
|
943
|
+
*
|
944
|
+
* @function #initShape
|
945
|
+
* @memberOf Highcharts.Annotation#
|
946
|
+
*
|
947
|
+
* @param {Object} shapeOptions - a confg object for a single shape
|
948
|
+
* @return {undefined}
|
949
|
+
**/
|
950
|
+
initShape: function(shapeOptions) {
|
951
|
+
var renderer = this.chart.renderer,
|
952
|
+
options = merge(this.options.shapeOptions, shapeOptions),
|
953
|
+
attr = this.attrsFromOptions(options),
|
954
|
+
|
955
|
+
type = renderer[options.type] ? options.type : 'rect',
|
956
|
+
shape = renderer[type](0, -9e9, 0, 0);
|
957
|
+
|
958
|
+
shape.points = [];
|
959
|
+
shape.type = type;
|
960
|
+
shape.options = options;
|
961
|
+
shape.itemType = 'shape';
|
962
|
+
|
963
|
+
if (type === 'path') {
|
964
|
+
extend(shape, {
|
965
|
+
markerStartSetter: MarkerMixin.markerStartSetter,
|
966
|
+
markerEndSetter: MarkerMixin.markerEndSetter,
|
967
|
+
markerStart: MarkerMixin.markerStart,
|
968
|
+
markerEnd: MarkerMixin.markerEnd
|
969
|
+
});
|
205
970
|
}
|
206
971
|
|
972
|
+
shape.attr(attr);
|
207
973
|
|
208
|
-
|
209
|
-
|
210
|
-
|
974
|
+
this.shapes.push(shape);
|
975
|
+
},
|
976
|
+
|
977
|
+
/**
|
978
|
+
* Initialisation of a single label
|
979
|
+
*
|
980
|
+
* @function #initShape
|
981
|
+
* @memberOf Highcharts.Annotation#
|
982
|
+
*
|
983
|
+
* @param {Object} labelOptions
|
984
|
+
* @return {undefined}
|
985
|
+
**/
|
986
|
+
initLabel: function(labelOptions) {
|
987
|
+
var options = merge(this.options.labelOptions, labelOptions),
|
988
|
+
style = options.style,
|
989
|
+
attr = this.attrsFromOptions(options),
|
990
|
+
|
991
|
+
label = this.chart.renderer.label(
|
992
|
+
'',
|
993
|
+
0, -9e9,
|
994
|
+
options.shape,
|
995
|
+
null,
|
996
|
+
null,
|
997
|
+
options.useHTML,
|
998
|
+
null,
|
999
|
+
'annotation-label'
|
1000
|
+
);
|
1001
|
+
|
1002
|
+
if (style.color === 'contrast') {
|
1003
|
+
style.color = this.chart.renderer.getContrast(
|
1004
|
+
inArray(options.shape, this.shapesWithoutBackground) > -1 ?
|
1005
|
+
'#FFFFFF' :
|
1006
|
+
options.backgroundColor
|
1007
|
+
);
|
211
1008
|
}
|
212
1009
|
|
213
|
-
|
214
|
-
|
1010
|
+
label.points = [];
|
1011
|
+
label.options = options;
|
1012
|
+
label.itemType = 'label';
|
215
1013
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
shapeParams[param] = xAxis.translate(shapeParams[param]);
|
220
|
-
} else if (inArray(param, ['height', 'y']) > -1) {
|
221
|
-
shapeParams[param] = yAxis.translate(shapeParams[param]);
|
222
|
-
}
|
223
|
-
});
|
1014
|
+
// Labelrank required for hideOverlappingLabels()
|
1015
|
+
label.labelrank = options.labelrank;
|
1016
|
+
label.annotation = this;
|
224
1017
|
|
225
|
-
|
226
|
-
shapeParams.width -= xAxis.toPixels(0) - xAxis.left;
|
227
|
-
}
|
1018
|
+
label.attr(attr).css(style).shadow(options.shadow);
|
228
1019
|
|
229
|
-
|
230
|
-
|
231
|
-
}
|
1020
|
+
this.labels.push(label);
|
1021
|
+
},
|
232
1022
|
|
233
|
-
|
234
|
-
|
235
|
-
|
1023
|
+
/**
|
1024
|
+
* Redrawing a single item
|
1025
|
+
*
|
1026
|
+
* @function #redrawItem
|
1027
|
+
* @memberOf Highcharts.Annotation#
|
1028
|
+
*
|
1029
|
+
* @param {Object} item
|
1030
|
+
* @return {undefined}
|
1031
|
+
*/
|
1032
|
+
redrawItem: function(item) {
|
1033
|
+
var points = this.linkPoints(item),
|
1034
|
+
itemOptions = item.options,
|
1035
|
+
text;
|
1036
|
+
|
1037
|
+
if (!points.length) {
|
1038
|
+
this.destroyItem(item);
|
1039
|
+
|
1040
|
+
} else {
|
1041
|
+
if (!item.parentGroup) {
|
1042
|
+
this.renderItem(item);
|
236
1043
|
}
|
237
1044
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
1045
|
+
if (item.itemType === 'label') {
|
1046
|
+
text = itemOptions.format || itemOptions.text;
|
1047
|
+
item.attr({
|
1048
|
+
text: text ?
|
1049
|
+
format(text, points[0].getLabelConfig()) : itemOptions.formatter.call(points[0])
|
1050
|
+
});
|
242
1051
|
}
|
243
1052
|
|
244
|
-
|
1053
|
+
|
1054
|
+
if (item.type === 'path') {
|
1055
|
+
this.redrawPath(item);
|
1056
|
+
|
1057
|
+
} else {
|
1058
|
+
this.alignItem(item, !item.placed);
|
1059
|
+
}
|
245
1060
|
}
|
1061
|
+
},
|
246
1062
|
|
247
|
-
|
1063
|
+
/**
|
1064
|
+
* Destroing a single item
|
1065
|
+
*
|
1066
|
+
* @function #destroyItem
|
1067
|
+
* @memberOf Highcharts.Annotation#
|
1068
|
+
*
|
1069
|
+
* @param {Object} item
|
1070
|
+
* @return {undefined}
|
1071
|
+
*/
|
1072
|
+
destroyItem: function(item) {
|
1073
|
+
// erase from shapes or labels array
|
1074
|
+
erase(this[item.itemType + 's'], item);
|
1075
|
+
item.destroy();
|
1076
|
+
},
|
248
1077
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
1078
|
+
/**
|
1079
|
+
* Returns a point object
|
1080
|
+
*
|
1081
|
+
* @function #pointItem
|
1082
|
+
* @memberOf Highcharts.Annotation#
|
1083
|
+
*
|
1084
|
+
* @param {Object} pointOptions
|
1085
|
+
* @param {Highcharts.MockPoint|Highcharts.Point} point
|
1086
|
+
* @return {Highcharts.MockPoint|Highcharts.Point|null} if the point is
|
1087
|
+
* found/exists returns this point, otherwise null
|
1088
|
+
*/
|
1089
|
+
pointItem: function(pointOptions, point) {
|
1090
|
+
if (!point || point.series === null) {
|
1091
|
+
if (isObject(pointOptions)) {
|
1092
|
+
point = mockPoint(this.chart, pointOptions);
|
1093
|
+
|
1094
|
+
} else if (isString(pointOptions)) {
|
1095
|
+
point = this.chart.get(pointOptions) || null;
|
1096
|
+
}
|
253
1097
|
}
|
254
1098
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
1099
|
+
return point;
|
1100
|
+
},
|
1101
|
+
|
1102
|
+
/**
|
1103
|
+
* Linking item with the point or points and returning an array of linked points
|
1104
|
+
*
|
1105
|
+
* @function #linkPoints
|
1106
|
+
* @memberOf Highcharts.Annotation#
|
1107
|
+
*
|
1108
|
+
* @param {Object} item
|
1109
|
+
* @return {
|
1110
|
+
* Highcharts.Point|
|
1111
|
+
* Highcharts.MockPoint|
|
1112
|
+
* Array<Highcharts.Point|Highcharts.MockPoint>
|
1113
|
+
* }
|
1114
|
+
*/
|
1115
|
+
linkPoints: function(item) {
|
1116
|
+
var pointsOptions = item.options.points || (item.options.point && H.splat(item.options.point)),
|
1117
|
+
points = item.points,
|
1118
|
+
len = pointsOptions && pointsOptions.length,
|
1119
|
+
i,
|
1120
|
+
point;
|
1121
|
+
|
1122
|
+
for (i = 0; i < len; i++) {
|
1123
|
+
point = this.pointItem(pointsOptions[i], points[i]);
|
1124
|
+
|
1125
|
+
if (!point) {
|
1126
|
+
return (item.points = []);
|
259
1127
|
}
|
260
1128
|
|
261
|
-
|
1129
|
+
points[i] = point;
|
262
1130
|
}
|
263
1131
|
|
264
|
-
|
265
|
-
|
266
|
-
|
1132
|
+
return points;
|
1133
|
+
},
|
1134
|
+
|
1135
|
+
/**
|
1136
|
+
* Aligning the item and setting its anchor
|
1137
|
+
*
|
1138
|
+
* @function #alignItem
|
1139
|
+
* @memberOf Highcharts.Annotation#
|
1140
|
+
*
|
1141
|
+
* @param {Object} item
|
1142
|
+
* @param {Boolean} isNew - if the label is re-positioned (is not new) it is animated
|
1143
|
+
* @return {undefined}
|
1144
|
+
*/
|
1145
|
+
alignItem: function(item, isNew) {
|
1146
|
+
var anchor = this.itemAnchor(item, item.points[0]),
|
1147
|
+
attrs = this.itemPosition(item, anchor);
|
1148
|
+
|
1149
|
+
if (attrs) {
|
1150
|
+
item.alignAttr = attrs;
|
1151
|
+
item.placed = true;
|
1152
|
+
|
1153
|
+
attrs.anchorX = anchor.absolutePosition.x;
|
1154
|
+
attrs.anchorY = anchor.absolutePosition.y;
|
1155
|
+
|
1156
|
+
item[isNew ? 'attr' : 'animate'](attrs);
|
1157
|
+
|
1158
|
+
} else {
|
1159
|
+
item.placed = false;
|
1160
|
+
|
1161
|
+
item.attr({
|
1162
|
+
x: 0,
|
1163
|
+
y: -9e9
|
1164
|
+
});
|
267
1165
|
}
|
1166
|
+
},
|
1167
|
+
|
1168
|
+
redrawPath: function(pathItem, isNew) {
|
1169
|
+
var points = pathItem.points,
|
1170
|
+
strokeWidth = pathItem['stroke-width'],
|
1171
|
+
d = ['M'],
|
1172
|
+
pointIndex = 0,
|
1173
|
+
dIndex = 0,
|
1174
|
+
len = points && points.length,
|
1175
|
+
crispSegmentIndex,
|
1176
|
+
anchor,
|
1177
|
+
point,
|
1178
|
+
showPath;
|
1179
|
+
|
1180
|
+
if (len) {
|
1181
|
+
do {
|
1182
|
+
point = points[pointIndex];
|
1183
|
+
|
1184
|
+
anchor = this.itemAnchor(pathItem, point).absolutePosition;
|
1185
|
+
d[++dIndex] = anchor.x;
|
1186
|
+
d[++dIndex] = anchor.y;
|
1187
|
+
|
1188
|
+
// crisping line, it might be replaced with Renderer.prototype.crispLine
|
1189
|
+
// but it requires creating many temporary arrays
|
1190
|
+
crispSegmentIndex = dIndex % 5;
|
1191
|
+
if (crispSegmentIndex === 0) {
|
1192
|
+
if (d[crispSegmentIndex + 1] === d[crispSegmentIndex + 4]) {
|
1193
|
+
d[crispSegmentIndex + 1] = d[crispSegmentIndex + 4] = Math.round(d[crispSegmentIndex + 1]) - (strokeWidth % 2 / 2);
|
1194
|
+
}
|
268
1195
|
|
269
|
-
|
270
|
-
|
1196
|
+
if (d[crispSegmentIndex + 2] === d[crispSegmentIndex + 5]) {
|
1197
|
+
d[crispSegmentIndex + 2] = d[crispSegmentIndex + 5] = Math.round(d[crispSegmentIndex + 2]) + (strokeWidth % 2 / 2);
|
1198
|
+
}
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
if (pointIndex < len - 1) {
|
1202
|
+
d[++dIndex] = 'L';
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
showPath = point.series.visible;
|
1206
|
+
|
1207
|
+
} while (++pointIndex < len && showPath);
|
271
1208
|
}
|
272
1209
|
|
273
|
-
// Translate group according to its dimension and anchor point
|
274
|
-
x = x - width * anchorX;
|
275
|
-
y = y - height * anchorY;
|
276
1210
|
|
277
|
-
if (
|
278
|
-
|
279
|
-
|
280
|
-
translateY: y
|
1211
|
+
if (showPath) {
|
1212
|
+
pathItem[isNew ? 'attr' : 'animate']({
|
1213
|
+
d: d
|
281
1214
|
});
|
1215
|
+
|
282
1216
|
} else {
|
283
|
-
|
1217
|
+
pathItem.attr({
|
1218
|
+
d: 'M 0 ' + -9e9
|
1219
|
+
});
|
284
1220
|
}
|
1221
|
+
|
1222
|
+
pathItem.placed = showPath;
|
285
1223
|
},
|
286
1224
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
1225
|
+
renderItem: function(item) {
|
1226
|
+
item.add(item.itemType === 'label' ? this.labelsGroup : this.shapesGroup);
|
1227
|
+
|
1228
|
+
this.setItemMarkers(item);
|
1229
|
+
},
|
1230
|
+
|
1231
|
+
setItemMarkers: function(item) {
|
1232
|
+
var itemOptions = item.options,
|
292
1233
|
chart = this.chart,
|
293
|
-
|
294
|
-
|
1234
|
+
markers = chart.options.defs.markers,
|
1235
|
+
fill = itemOptions.fill,
|
1236
|
+
color = defined(fill) && fill !== 'none' ? fill : itemOptions.stroke,
|
1237
|
+
|
1238
|
+
|
1239
|
+
setMarker = function(markerType) {
|
1240
|
+
var markerId = itemOptions[markerType],
|
1241
|
+
marker,
|
1242
|
+
predefinedMarker,
|
1243
|
+
key;
|
1244
|
+
|
1245
|
+
if (markerId) {
|
1246
|
+
for (key in markers) {
|
1247
|
+
marker = markers[key];
|
1248
|
+
if (markerId === marker.id) {
|
1249
|
+
predefinedMarker = marker;
|
1250
|
+
break;
|
1251
|
+
}
|
1252
|
+
}
|
295
1253
|
|
296
|
-
|
297
|
-
|
298
|
-
|
1254
|
+
if (predefinedMarker) {
|
1255
|
+
marker = item[markerType] = chart.renderer.addMarker(
|
1256
|
+
null,
|
1257
|
+
merge(predefinedMarker, {
|
1258
|
+
color: color
|
1259
|
+
})
|
1260
|
+
);
|
299
1261
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
}
|
305
|
-
});
|
1262
|
+
item.attr(markerType, marker.id);
|
1263
|
+
}
|
1264
|
+
}
|
1265
|
+
};
|
306
1266
|
|
307
|
-
|
1267
|
+
each(['markerStart', 'markerEnd'], setMarker);
|
308
1268
|
},
|
309
1269
|
|
310
|
-
|
311
|
-
*
|
1270
|
+
/**
|
1271
|
+
* An object which denotes an anchor position
|
1272
|
+
*
|
1273
|
+
* @typedef {Object} AnchorPosition
|
1274
|
+
* @property {Number} AnchorPosition.x
|
1275
|
+
* @property {Number} AnchorPosition.y
|
1276
|
+
* @property {Number} AnchorPosition.height
|
1277
|
+
* @property {Number} AnchorPosition.width
|
1278
|
+
*/
|
1279
|
+
|
1280
|
+
/**
|
1281
|
+
* Returns object which denotes anchor position - relative and absolute
|
1282
|
+
*
|
1283
|
+
* @function #itemAnchor
|
1284
|
+
* @memberOf Highcharts.Annotation#
|
1285
|
+
*
|
1286
|
+
* @param {Object} item
|
1287
|
+
* @param {Highcharts.Point|Highcharts.MockPoint} point
|
1288
|
+
* @return {Object} anchor
|
1289
|
+
* @return {AnchorPosition} anchor.relativePosition - relative to the plot area position
|
1290
|
+
* @return {AnchorPosition} anchor.absolutePosition - absolute position
|
312
1291
|
*/
|
313
|
-
|
314
|
-
|
1292
|
+
itemAnchor: function(item, point) {
|
1293
|
+
var plotBox = point.series.getPlotBox(),
|
1294
|
+
|
1295
|
+
box = point.mock ?
|
1296
|
+
point.alignToBox(true) :
|
1297
|
+
tooltipPrototype.getAnchor.call({
|
1298
|
+
chart: this.chart
|
1299
|
+
}, point),
|
1300
|
+
|
1301
|
+
anchor = {
|
1302
|
+
x: box[0],
|
1303
|
+
y: box[1],
|
1304
|
+
height: box[2] || 0,
|
1305
|
+
width: box[3] || 0
|
1306
|
+
};
|
1307
|
+
|
1308
|
+
return {
|
1309
|
+
relativePosition: anchor,
|
1310
|
+
absolutePosition: merge(anchor, {
|
1311
|
+
x: anchor.x + plotBox.translateX,
|
1312
|
+
y: anchor.y + plotBox.translateY
|
1313
|
+
})
|
1314
|
+
};
|
1315
|
+
},
|
1316
|
+
|
1317
|
+
/**
|
1318
|
+
* Returns the item position
|
1319
|
+
*
|
1320
|
+
* @function #itemPosition
|
1321
|
+
* @memberOf Highcharts.Annotation#
|
1322
|
+
*
|
1323
|
+
* @param {Object} item
|
1324
|
+
* @param {AnchorPosition} anchor
|
1325
|
+
* @return {Object|null} position
|
1326
|
+
* @return {Number} position.x
|
1327
|
+
* @return {Number} position.y
|
1328
|
+
*/
|
1329
|
+
itemPosition: function(item, anchor) {
|
1330
|
+
var chart = this.chart,
|
1331
|
+
point = item.points[0],
|
1332
|
+
itemOptions = item.options,
|
1333
|
+
anchorAbsolutePosition = anchor.absolutePosition,
|
1334
|
+
anchorRelativePosition = anchor.relativePosition,
|
1335
|
+
itemPosition,
|
1336
|
+
alignTo,
|
1337
|
+
itemPosRelativeX,
|
1338
|
+
itemPosRelativeY,
|
1339
|
+
|
1340
|
+
showItem = point.series.visible && point.isInside !== false;
|
1341
|
+
|
1342
|
+
if (showItem) {
|
1343
|
+
|
1344
|
+
if (defined(itemOptions.distance) || itemOptions.positioner) {
|
1345
|
+
itemPosition = (itemOptions.positioner || tooltipPrototype.getPosition).call({
|
1346
|
+
chart: chart,
|
1347
|
+
distance: pick(itemOptions.distance, 16)
|
1348
|
+
},
|
1349
|
+
item.width,
|
1350
|
+
item.height, {
|
1351
|
+
plotX: anchorRelativePosition.x,
|
1352
|
+
plotY: anchorRelativePosition.y,
|
1353
|
+
negative: point.negative,
|
1354
|
+
ttBelow: point.ttBelow,
|
1355
|
+
h: anchorRelativePosition.height || anchorRelativePosition.width
|
1356
|
+
}
|
1357
|
+
);
|
1358
|
+
|
1359
|
+
} else {
|
1360
|
+
alignTo = {
|
1361
|
+
x: anchorAbsolutePosition.x,
|
1362
|
+
y: anchorAbsolutePosition.y,
|
1363
|
+
width: 0,
|
1364
|
+
height: 0
|
1365
|
+
};
|
1366
|
+
|
1367
|
+
itemPosition = this.alignedPosition(
|
1368
|
+
extend(itemOptions, {
|
1369
|
+
width: item.width,
|
1370
|
+
height: item.height
|
1371
|
+
}),
|
1372
|
+
alignTo
|
1373
|
+
);
|
1374
|
+
|
1375
|
+
if (item.options.overflow === 'justify') {
|
1376
|
+
itemPosition = this.alignedPosition(
|
1377
|
+
this.justifiedOptions(item, itemOptions, itemPosition),
|
1378
|
+
alignTo
|
1379
|
+
);
|
1380
|
+
}
|
1381
|
+
}
|
315
1382
|
|
316
|
-
// update link to point or series
|
317
|
-
this.linkObjects();
|
318
1383
|
|
319
|
-
|
1384
|
+
if (itemOptions.crop) {
|
1385
|
+
itemPosRelativeX = itemPosition.x - chart.plotLeft;
|
1386
|
+
itemPosRelativeY = itemPosition.y - chart.plotTop;
|
1387
|
+
|
1388
|
+
showItem =
|
1389
|
+
chart.isInsidePlot(itemPosRelativeX, itemPosRelativeY) &&
|
1390
|
+
chart.isInsidePlot(
|
1391
|
+
itemPosRelativeX + item.width,
|
1392
|
+
itemPosRelativeY + item.height
|
1393
|
+
);
|
1394
|
+
}
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
return showItem ? itemPosition : null;
|
320
1398
|
},
|
321
1399
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
1400
|
+
/**
|
1401
|
+
* Returns new aligned position based alignment options and box to align to.
|
1402
|
+
* It is almost a one-to-one copy from SVGElement.prototype.align
|
1403
|
+
* except it does not use and mutate an element
|
1404
|
+
*
|
1405
|
+
* @function #alignedPosition
|
1406
|
+
* @memberOf Highcharts.Annotation#
|
1407
|
+
*
|
1408
|
+
* @param {Object} alignOptions
|
1409
|
+
* @param {Object} box
|
1410
|
+
* @return {Object} aligned position
|
1411
|
+
**/
|
1412
|
+
alignedPosition: function(alignOptions, box) {
|
1413
|
+
var align = alignOptions.align,
|
1414
|
+
vAlign = alignOptions.verticalAlign,
|
1415
|
+
x = (box.x || 0) + (alignOptions.x || 0),
|
1416
|
+
y = (box.y || 0) + (alignOptions.y || 0),
|
1417
|
+
|
1418
|
+
alignFactor,
|
1419
|
+
vAlignFactor;
|
1420
|
+
|
1421
|
+
if (align === 'right') {
|
1422
|
+
alignFactor = 1;
|
1423
|
+
} else if (align === 'center') {
|
1424
|
+
alignFactor = 2;
|
1425
|
+
}
|
1426
|
+
if (alignFactor) {
|
1427
|
+
x += (box.width - (alignOptions.width || 0)) / alignFactor;
|
1428
|
+
}
|
329
1429
|
|
330
|
-
if (
|
331
|
-
|
332
|
-
} else if (
|
333
|
-
|
1430
|
+
if (vAlign === 'bottom') {
|
1431
|
+
vAlignFactor = 1;
|
1432
|
+
} else if (vAlign === 'middle') {
|
1433
|
+
vAlignFactor = 2;
|
1434
|
+
}
|
1435
|
+
if (vAlignFactor) {
|
1436
|
+
y += (box.height - (alignOptions.height || 0)) / vAlignFactor;
|
334
1437
|
}
|
335
|
-
}
|
336
|
-
};
|
337
1438
|
|
1439
|
+
return {
|
1440
|
+
x: Math.round(x),
|
1441
|
+
y: Math.round(y)
|
1442
|
+
};
|
1443
|
+
},
|
338
1444
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
1445
|
+
/**
|
1446
|
+
* Returns new alignment options for a label if the label is outside the plot area.
|
1447
|
+
* It is almost a one-to-one copy from Series.prototype.justifyDataLabel
|
1448
|
+
* except it does not mutate the label and it works with absolute instead of relative position
|
1449
|
+
*
|
1450
|
+
* @function #justifiedOptions
|
1451
|
+
* @memberOf Highcharts.Annotation#
|
1452
|
+
*
|
1453
|
+
* @param {Object} label
|
1454
|
+
* @param {Object} alignOptions
|
1455
|
+
* @param {Object} alignAttr
|
1456
|
+
* @return {Object} justified options
|
1457
|
+
**/
|
1458
|
+
justifiedOptions: function(label, alignOptions, alignAttr) {
|
1459
|
+
var chart = this.chart,
|
1460
|
+
align = alignOptions.align,
|
1461
|
+
verticalAlign = alignOptions.verticalAlign,
|
1462
|
+
padding = label.box ? 0 : (label.padding || 0),
|
1463
|
+
bBox = label.getBBox(),
|
1464
|
+
off,
|
1465
|
+
|
1466
|
+
options = {
|
1467
|
+
align: align,
|
1468
|
+
verticalAlign: verticalAlign,
|
1469
|
+
x: alignOptions.x,
|
1470
|
+
y: alignOptions.y,
|
1471
|
+
width: label.width,
|
1472
|
+
height: label.height
|
1473
|
+
},
|
1474
|
+
|
1475
|
+
x = alignAttr.x - chart.plotLeft,
|
1476
|
+
y = alignAttr.y - chart.plotTop;
|
1477
|
+
|
1478
|
+
// Off left
|
1479
|
+
off = x + padding;
|
1480
|
+
if (off < 0) {
|
1481
|
+
if (align === 'right') {
|
1482
|
+
options.align = 'left';
|
1483
|
+
} else {
|
1484
|
+
options.x = -off;
|
353
1485
|
}
|
1486
|
+
}
|
354
1487
|
|
355
|
-
|
1488
|
+
// Off right
|
1489
|
+
off = x + bBox.width - padding;
|
1490
|
+
if (off > chart.plotWidth) {
|
1491
|
+
if (align === 'left') {
|
1492
|
+
options.align = 'right';
|
1493
|
+
} else {
|
1494
|
+
options.x = chart.plotWidth - off;
|
1495
|
+
}
|
1496
|
+
}
|
356
1497
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
1498
|
+
// Off top
|
1499
|
+
off = y + padding;
|
1500
|
+
if (off < 0) {
|
1501
|
+
if (verticalAlign === 'bottom') {
|
1502
|
+
options.verticalAlign = 'top';
|
1503
|
+
} else {
|
1504
|
+
options.y = -off;
|
361
1505
|
}
|
362
|
-
}
|
1506
|
+
}
|
363
1507
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
1508
|
+
// Off bottom
|
1509
|
+
off = y + bBox.height - padding;
|
1510
|
+
if (off > chart.plotHeight) {
|
1511
|
+
if (verticalAlign === 'top') {
|
1512
|
+
options.verticalAlign = 'bottom';
|
1513
|
+
} else {
|
1514
|
+
options.y = chart.plotHeight - off;
|
1515
|
+
}
|
1516
|
+
}
|
1517
|
+
|
1518
|
+
return options;
|
1519
|
+
},
|
1520
|
+
|
1521
|
+
|
1522
|
+
/**
|
1523
|
+
* Utility function for mapping item's options to element's attribute
|
1524
|
+
*
|
1525
|
+
* @function #attrsFromOptions
|
1526
|
+
* @memberOf Highcharts.Annotation#
|
1527
|
+
*
|
1528
|
+
* @param {Object} options
|
1529
|
+
* @return {Object} mapped options
|
1530
|
+
**/
|
1531
|
+
attrsFromOptions: function(options) {
|
1532
|
+
var map = this.attrsMap,
|
1533
|
+
attrs = {},
|
1534
|
+
key,
|
1535
|
+
mappedKey;
|
1536
|
+
|
1537
|
+
for (key in options) {
|
1538
|
+
mappedKey = map[key];
|
1539
|
+
if (mappedKey) {
|
1540
|
+
attrs[mappedKey] = options[key];
|
1541
|
+
}
|
1542
|
+
}
|
1543
|
+
|
1544
|
+
return attrs;
|
1545
|
+
}
|
1546
|
+
};
|
1547
|
+
|
1548
|
+
/* ***************************************************************************
|
1549
|
+
*
|
1550
|
+
* EXTENDING CHART PROTOTYPE
|
1551
|
+
*
|
1552
|
+
**************************************************************************** */
|
1553
|
+
|
1554
|
+
H.extend(chartPrototype, {
|
1555
|
+
addAnnotation: function(userOptions, redraw) {
|
1556
|
+
var annotation = new Annotation(this, userOptions);
|
1557
|
+
|
1558
|
+
this.annotations.push(annotation);
|
1559
|
+
|
1560
|
+
if (pick(redraw, true)) {
|
1561
|
+
annotation.redraw();
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
return annotation;
|
1565
|
+
},
|
1566
|
+
|
1567
|
+
removeAnnotation: function(id) {
|
1568
|
+
var annotations = this.annotations,
|
1569
|
+
annotation = find(annotations, function(annotation) {
|
1570
|
+
return annotation.options.id === id;
|
370
1571
|
});
|
1572
|
+
|
1573
|
+
if (annotation) {
|
1574
|
+
erase(annotations, annotation);
|
1575
|
+
annotation.destroy();
|
1576
|
+
}
|
1577
|
+
},
|
1578
|
+
|
1579
|
+
drawAnnotations: function() {
|
1580
|
+
var clip = this.plotBoxClip,
|
1581
|
+
plotBox = this.plotBox;
|
1582
|
+
|
1583
|
+
if (clip) {
|
1584
|
+
clip.attr(plotBox);
|
1585
|
+
} else {
|
1586
|
+
this.plotBoxClip = this.renderer.clipRect(plotBox);
|
371
1587
|
}
|
1588
|
+
|
1589
|
+
each(this.annotations, function(annotation) {
|
1590
|
+
annotation.redraw();
|
1591
|
+
});
|
372
1592
|
}
|
373
1593
|
});
|
374
1594
|
|
375
1595
|
|
376
|
-
|
377
|
-
|
378
|
-
var options = chart.options.annotations,
|
379
|
-
group;
|
1596
|
+
chartPrototype.callbacks.push(function(chart) {
|
1597
|
+
chart.annotations = [];
|
380
1598
|
|
381
|
-
|
382
|
-
|
383
|
-
zIndex: 7
|
1599
|
+
each(chart.options.annotations, function(annotationOptions) {
|
1600
|
+
chart.addAnnotation(annotationOptions, false);
|
384
1601
|
});
|
385
|
-
group.add();
|
386
1602
|
|
387
|
-
|
388
|
-
chart
|
1603
|
+
chart.drawAnnotations();
|
1604
|
+
addEvent(chart, 'redraw', chart.drawAnnotations);
|
1605
|
+
addEvent(chart, 'destroy', function() {
|
1606
|
+
var plotBoxClip = chart.plotBoxClip;
|
389
1607
|
|
390
|
-
|
391
|
-
|
1608
|
+
if (plotBoxClip && plotBoxClip.destroy) {
|
1609
|
+
plotBoxClip.destroy();
|
1610
|
+
}
|
1611
|
+
});
|
1612
|
+
});
|
392
1613
|
|
393
|
-
// link annotations group element to the chart
|
394
|
-
chart.annotations.group = group;
|
395
1614
|
|
396
|
-
|
397
|
-
|
398
|
-
}
|
1615
|
+
H.wrap(chartPrototype, 'getContainer', function(p) {
|
1616
|
+
p.call(this);
|
399
1617
|
|
400
|
-
|
401
|
-
|
402
|
-
|
1618
|
+
var renderer = this.renderer,
|
1619
|
+
options = this.options,
|
1620
|
+
key,
|
1621
|
+
markers,
|
1622
|
+
marker;
|
1623
|
+
|
1624
|
+
options.defs = merge(options.defs || {}, {
|
1625
|
+
markers: defaultMarkers
|
403
1626
|
});
|
1627
|
+
markers = options.defs.markers;
|
1628
|
+
|
1629
|
+
for (key in markers) {
|
1630
|
+
marker = markers[key];
|
1631
|
+
|
1632
|
+
if (pick(marker.render, true)) {
|
1633
|
+
renderer.addMarker(marker.id, marker);
|
1634
|
+
}
|
1635
|
+
}
|
404
1636
|
});
|
405
1637
|
|
1638
|
+
|
1639
|
+
/* ************************************************************************* */
|
1640
|
+
|
1641
|
+
/**
|
1642
|
+
* General symbol definition for labels with connector
|
1643
|
+
*/
|
1644
|
+
H.SVGRenderer.prototype.symbols.connector = function(x, y, w, h, options) {
|
1645
|
+
var anchorX = options && options.anchorX,
|
1646
|
+
anchorY = options && options.anchorY,
|
1647
|
+
path,
|
1648
|
+
yOffset,
|
1649
|
+
lateral = w / 2;
|
1650
|
+
|
1651
|
+
if (isNumber(anchorX) && isNumber(anchorY)) {
|
1652
|
+
|
1653
|
+
path = ['M', anchorX, anchorY];
|
1654
|
+
|
1655
|
+
// Prefer 45 deg connectors
|
1656
|
+
yOffset = y - anchorY;
|
1657
|
+
if (yOffset < 0) {
|
1658
|
+
yOffset = -h - yOffset;
|
1659
|
+
}
|
1660
|
+
if (yOffset < w) {
|
1661
|
+
lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset;
|
1662
|
+
}
|
1663
|
+
|
1664
|
+
// Anchor below label
|
1665
|
+
if (anchorY > y + h) {
|
1666
|
+
path.push('L', x + lateral, y + h);
|
1667
|
+
|
1668
|
+
// Anchor above label
|
1669
|
+
} else if (anchorY < y) {
|
1670
|
+
path.push('L', x + lateral, y);
|
1671
|
+
|
1672
|
+
// Anchor left of label
|
1673
|
+
} else if (anchorX < x) {
|
1674
|
+
path.push('L', x, y + h / 2);
|
1675
|
+
|
1676
|
+
// Anchor right of label
|
1677
|
+
} else if (anchorX > x + w) {
|
1678
|
+
path.push('L', x + w, y + h / 2);
|
1679
|
+
}
|
1680
|
+
}
|
1681
|
+
return path || [];
|
1682
|
+
};
|
1683
|
+
|
406
1684
|
}(Highcharts));
|
407
1685
|
}));
|