highcharts-rails 4.0.4.1 → 4.1.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 +92 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/highcharts.js +1865 -1219
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +1 -1
- data/app/assets/javascripts/highcharts/highcharts-3d.js +174 -239
- data/app/assets/javascripts/highcharts/highcharts-more.js +195 -187
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +1 -1
- data/app/assets/javascripts/highcharts/modules/data.js +125 -196
- data/app/assets/javascripts/highcharts/modules/drilldown.js +104 -80
- data/app/assets/javascripts/highcharts/modules/exporting.js +14 -4
- data/app/assets/javascripts/highcharts/modules/funnel.js +7 -7
- data/app/assets/javascripts/highcharts/modules/heatmap.js +26 -69
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +2 -2
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +32 -17
- data/app/assets/javascripts/highcharts/modules/treemap.js +806 -0
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +1 -1
- data/app/assets/javascripts/highcharts/themes/grid-light.js +1 -1
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +1 -1
- data/lib/highcharts/version.rb +1 -1
- metadata +13 -12
- checksums.yaml.gz.asc +0 -18
- data.tar.gz.asc +0 -18
- metadata.gz.asc +0 -18
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.0
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
3
|
* Exporting module
|
4
4
|
*
|
5
5
|
* (c) 2010-2014 Torstein Honsi
|
@@ -8,7 +8,7 @@
|
|
8
8
|
*/
|
9
9
|
|
10
10
|
// JSLint options:
|
11
|
-
/*global Highcharts, document, window, Math, setTimeout */
|
11
|
+
/*global Highcharts, HighchartsAdapter, document, window, Math, setTimeout */
|
12
12
|
|
13
13
|
(function (Highcharts) { // encapsulate
|
14
14
|
|
@@ -16,6 +16,7 @@
|
|
16
16
|
var Chart = Highcharts.Chart,
|
17
17
|
addEvent = Highcharts.addEvent,
|
18
18
|
removeEvent = Highcharts.removeEvent,
|
19
|
+
fireEvent = HighchartsAdapter.fireEvent,
|
19
20
|
createElement = Highcharts.createElement,
|
20
21
|
discardElement = Highcharts.discardElement,
|
21
22
|
css = Highcharts.css,
|
@@ -244,6 +245,7 @@ extend(Chart.prototype, {
|
|
244
245
|
height: sourceHeight
|
245
246
|
});
|
246
247
|
options.exporting.enabled = false; // hide buttons in print
|
248
|
+
delete options.data; // #3004
|
247
249
|
|
248
250
|
// prepare for replicating the chart
|
249
251
|
options.series = [];
|
@@ -298,7 +300,9 @@ extend(Chart.prototype, {
|
|
298
300
|
// Any HTML added to the container after the SVG (#894)
|
299
301
|
.replace(/<\/svg>.*?$/, '</svg>')
|
300
302
|
// Batik doesn't support rgba fills and strokes (#3095)
|
301
|
-
.replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g, '$1="rgb($2)" $1-opacity="$3"')
|
303
|
+
.replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g, '$1="rgb($2)" $1-opacity="$3"')
|
304
|
+
// An issue with PhantomJS as of 2015-01-11. Revisit with newer versions. (#3649)
|
305
|
+
.replace(/(text-shadow:[ 0-9a-z]+),[^"]+([;"])/g, '$1$2')
|
302
306
|
/* This fails in IE < 8
|
303
307
|
.replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
|
304
308
|
return s2 +'.'+ s3[0];
|
@@ -382,6 +386,8 @@ extend(Chart.prototype, {
|
|
382
386
|
|
383
387
|
chart.isPrinting = true;
|
384
388
|
|
389
|
+
fireEvent(chart, 'beforePrint');
|
390
|
+
|
385
391
|
// hide all body content
|
386
392
|
each(childNodes, function (node, i) {
|
387
393
|
if (node.nodeType === 1) {
|
@@ -412,6 +418,8 @@ extend(Chart.prototype, {
|
|
412
418
|
|
413
419
|
chart.isPrinting = false;
|
414
420
|
|
421
|
+
fireEvent(chart, 'afterPrint');
|
422
|
+
|
415
423
|
}, 1000);
|
416
424
|
|
417
425
|
},
|
@@ -504,7 +512,9 @@ extend(Chart.prototype, {
|
|
504
512
|
},
|
505
513
|
onclick: function () {
|
506
514
|
hide();
|
507
|
-
item.onclick
|
515
|
+
if (item.onclick) {
|
516
|
+
item.onclick.apply(chart, arguments);
|
517
|
+
}
|
508
518
|
},
|
509
519
|
innerHTML: item.text || chart.options.lang[item.textKey]
|
510
520
|
}, extend({
|
@@ -18,7 +18,8 @@ var defaultOptions = Highcharts.getOptions(),
|
|
18
18
|
seriesTypes = Highcharts.seriesTypes,
|
19
19
|
merge = Highcharts.merge,
|
20
20
|
noop = function () {},
|
21
|
-
each = Highcharts.each
|
21
|
+
each = Highcharts.each,
|
22
|
+
pick = Highcharts.pick;
|
22
23
|
|
23
24
|
// set default options
|
24
25
|
defaultPlotOptions.funnel = merge(defaultPlotOptions.pie, {
|
@@ -49,7 +50,6 @@ seriesTypes.funnel = Highcharts.extendClass(seriesTypes.pie, {
|
|
49
50
|
|
50
51
|
type: 'funnel',
|
51
52
|
animate: noop,
|
52
|
-
singularTooltips: true,
|
53
53
|
|
54
54
|
/**
|
55
55
|
* Overrides the pie translate method
|
@@ -222,16 +222,16 @@ seriesTypes.funnel = Highcharts.extendClass(seriesTypes.pie, {
|
|
222
222
|
renderer = chart.renderer;
|
223
223
|
|
224
224
|
each(series.data, function (point) {
|
225
|
-
|
226
|
-
|
225
|
+
var pointOptions = point.options,
|
226
|
+
graphic = point.graphic,
|
227
227
|
shapeArgs = point.shapeArgs;
|
228
228
|
|
229
|
-
if (!graphic) { // Create the shapes
|
229
|
+
if (!graphic) { // Create the shapes
|
230
230
|
point.graphic = renderer.path(shapeArgs).
|
231
231
|
attr({
|
232
232
|
fill: point.color,
|
233
|
-
stroke: options.borderColor,
|
234
|
-
'stroke-width': options.borderWidth
|
233
|
+
stroke: pick(pointOptions.borderColor, options.borderColor),
|
234
|
+
'stroke-width': pick(pointOptions.borderWidth, options.borderWidth)
|
235
235
|
}).
|
236
236
|
add(series.group);
|
237
237
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.0
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
3
|
*
|
4
4
|
* (c) 2011-2014 Torstein Honsi
|
5
5
|
*
|
@@ -17,7 +17,6 @@ var UNDEFINED,
|
|
17
17
|
Legend = Highcharts.Legend,
|
18
18
|
LegendSymbolMixin = Highcharts.LegendSymbolMixin,
|
19
19
|
Series = Highcharts.Series,
|
20
|
-
SVGRenderer = Highcharts.SVGRenderer,
|
21
20
|
|
22
21
|
defaultOptions = Highcharts.getOptions(),
|
23
22
|
each = Highcharts.each,
|
@@ -25,7 +24,6 @@ var UNDEFINED,
|
|
25
24
|
extendClass = Highcharts.extendClass,
|
26
25
|
merge = Highcharts.merge,
|
27
26
|
pick = Highcharts.pick,
|
28
|
-
numberFormat = Highcharts.numberFormat,
|
29
27
|
seriesTypes = Highcharts.seriesTypes,
|
30
28
|
wrap = Highcharts.wrap,
|
31
29
|
noop = function () {};
|
@@ -103,12 +101,19 @@ extend(ColorAxis.prototype, {
|
|
103
101
|
tweenColors: function (from, to, pos) {
|
104
102
|
// Check for has alpha, because rgba colors perform worse due to lack of
|
105
103
|
// support in WebKit.
|
106
|
-
var hasAlpha
|
104
|
+
var hasAlpha;
|
105
|
+
|
106
|
+
from = from.rgba;
|
107
|
+
to = to.rgba;
|
108
|
+
hasAlpha = (to[3] !== 1 || from[3] !== 1);
|
109
|
+
if (!to.length || !from.length) {
|
110
|
+
Highcharts.error(23);
|
111
|
+
}
|
107
112
|
return (hasAlpha ? 'rgba(' : 'rgb(') +
|
108
|
-
Math.round(to
|
109
|
-
Math.round(to
|
110
|
-
Math.round(to
|
111
|
-
(hasAlpha ? (',' + (to
|
113
|
+
Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' +
|
114
|
+
Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' +
|
115
|
+
Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) +
|
116
|
+
(hasAlpha ? (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) : '') + ')';
|
112
117
|
},
|
113
118
|
|
114
119
|
initDataClasses: function (userOptions) {
|
@@ -258,6 +263,9 @@ extend(ColorAxis.prototype, {
|
|
258
263
|
this.labelGroup.add(group);
|
259
264
|
|
260
265
|
this.added = true;
|
266
|
+
|
267
|
+
this.labelLeft = 0;
|
268
|
+
this.labelRight = this.width;
|
261
269
|
}
|
262
270
|
// Reset it to avoid color axis reserving space
|
263
271
|
this.chart.axisOffset[this.side] = sideOffset;
|
@@ -270,9 +278,10 @@ extend(ColorAxis.prototype, {
|
|
270
278
|
setLegendColor: function () {
|
271
279
|
var grad,
|
272
280
|
horiz = this.horiz,
|
273
|
-
options = this.options
|
281
|
+
options = this.options,
|
282
|
+
reversed = this.reversed;
|
274
283
|
|
275
|
-
grad = horiz ? [
|
284
|
+
grad = horiz ? [+reversed, 0, +!reversed, 0] : [0, +!reversed, 0, +reversed]; // #3190
|
276
285
|
this.legendColor = {
|
277
286
|
linearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },
|
278
287
|
stops: options.stops || [
|
@@ -335,7 +344,7 @@ extend(ColorAxis.prototype, {
|
|
335
344
|
axisLen = this.len;
|
336
345
|
|
337
346
|
if (point) {
|
338
|
-
crossPos = this.toPixels(point.
|
347
|
+
crossPos = this.toPixels(point[point.series.colorKey]);
|
339
348
|
if (crossPos < axisPos) {
|
340
349
|
crossPos = axisPos - 2;
|
341
350
|
} else if (crossPos > axisPos + axisLen) {
|
@@ -353,7 +362,7 @@ extend(ColorAxis.prototype, {
|
|
353
362
|
.attr({
|
354
363
|
fill: this.crosshair.color
|
355
364
|
})
|
356
|
-
.add(this.
|
365
|
+
.add(this.legendGroup);
|
357
366
|
}
|
358
367
|
}
|
359
368
|
},
|
@@ -404,13 +413,13 @@ extend(ColorAxis.prototype, {
|
|
404
413
|
name = '> ';
|
405
414
|
}
|
406
415
|
if (from !== UNDEFINED) {
|
407
|
-
name += numberFormat(from, valueDecimals) + valueSuffix;
|
416
|
+
name += Highcharts.numberFormat(from, valueDecimals) + valueSuffix;
|
408
417
|
}
|
409
418
|
if (from !== UNDEFINED && to !== UNDEFINED) {
|
410
419
|
name += ' - ';
|
411
420
|
}
|
412
421
|
if (to !== UNDEFINED) {
|
413
|
-
name += numberFormat(to, valueDecimals) + valueSuffix;
|
422
|
+
name += Highcharts.numberFormat(to, valueDecimals) + valueSuffix;
|
414
423
|
}
|
415
424
|
|
416
425
|
// Add a mock object to the legend items
|
@@ -533,55 +542,6 @@ var colorSeriesMixin = {
|
|
533
542
|
});
|
534
543
|
}
|
535
544
|
};
|
536
|
-
|
537
|
-
|
538
|
-
/**
|
539
|
-
* Wrap the buildText method and add the hook for add text stroke
|
540
|
-
*/
|
541
|
-
wrap(SVGRenderer.prototype, 'buildText', function (proceed, wrapper) {
|
542
|
-
|
543
|
-
var textStroke = wrapper.styles && wrapper.styles.HcTextStroke;
|
544
|
-
|
545
|
-
proceed.call(this, wrapper);
|
546
|
-
|
547
|
-
// Apply the text stroke
|
548
|
-
if (textStroke && wrapper.applyTextStroke) {
|
549
|
-
wrapper.applyTextStroke(textStroke);
|
550
|
-
}
|
551
|
-
});
|
552
|
-
|
553
|
-
/**
|
554
|
-
* Apply an outside text stroke to data labels, based on the custom CSS property, HcTextStroke.
|
555
|
-
* Consider moving this to Highcharts core, also makes sense on stacked columns etc.
|
556
|
-
*/
|
557
|
-
SVGRenderer.prototype.Element.prototype.applyTextStroke = function (textStroke) {
|
558
|
-
var elem = this.element,
|
559
|
-
tspans,
|
560
|
-
firstChild;
|
561
|
-
|
562
|
-
textStroke = textStroke.split(' ');
|
563
|
-
tspans = elem.getElementsByTagName('tspan');
|
564
|
-
firstChild = elem.firstChild;
|
565
|
-
|
566
|
-
// In order to get the right y position of the clones,
|
567
|
-
// copy over the y setter
|
568
|
-
this.ySetter = this.xSetter;
|
569
|
-
|
570
|
-
each([].slice.call(tspans), function (tspan, y) {
|
571
|
-
var clone;
|
572
|
-
if (y === 0) {
|
573
|
-
tspan.setAttribute('x', elem.getAttribute('x'));
|
574
|
-
if ((y = elem.getAttribute('y')) !== null) {
|
575
|
-
tspan.setAttribute('y', y);
|
576
|
-
}
|
577
|
-
}
|
578
|
-
clone = tspan.cloneNode(1);
|
579
|
-
clone.setAttribute('stroke', textStroke[1]);
|
580
|
-
clone.setAttribute('stroke-width', textStroke[0]);
|
581
|
-
clone.setAttribute('stroke-linejoin', 'round');
|
582
|
-
elem.insertBefore(clone, firstChild);
|
583
|
-
});
|
584
|
-
};
|
585
545
|
/**
|
586
546
|
* Extend the default options with map options
|
587
547
|
*/
|
@@ -593,14 +553,10 @@ defaultOptions.plotOptions.heatmap = merge(defaultOptions.plotOptions.scatter, {
|
|
593
553
|
formatter: function () { // #2945
|
594
554
|
return this.point.value;
|
595
555
|
},
|
556
|
+
inside: true,
|
596
557
|
verticalAlign: 'middle',
|
597
558
|
crop: false,
|
598
|
-
overflow: false
|
599
|
-
style: {
|
600
|
-
color: 'white',
|
601
|
-
fontWeight: 'bold',
|
602
|
-
HcTextStroke: '1px rgba(0,0,0,0.5)'
|
603
|
-
}
|
559
|
+
overflow: false
|
604
560
|
},
|
605
561
|
marker: null,
|
606
562
|
tooltip: {
|
@@ -611,6 +567,7 @@ defaultOptions.plotOptions.heatmap = merge(defaultOptions.plotOptions.scatter, {
|
|
611
567
|
animation: true
|
612
568
|
},
|
613
569
|
hover: {
|
570
|
+
halo: false, // #3406, halo is not required on heatmaps
|
614
571
|
brightness: 0.2
|
615
572
|
}
|
616
573
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.0
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
3
|
* Plugin for displaying a message when there is no data visible in chart.
|
4
4
|
*
|
5
5
|
* (c) 2010-2014 Highsoft AS
|
@@ -57,7 +57,7 @@
|
|
57
57
|
}
|
58
58
|
|
59
59
|
H.Series.prototype.hasData = function () {
|
60
|
-
return this.dataMax !== undefined && this.dataMin !== undefined;
|
60
|
+
return this.visible && this.dataMax !== undefined && this.dataMin !== undefined; // #3703
|
61
61
|
};
|
62
62
|
|
63
63
|
/**
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.0
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
3
|
* Solid angular gauge module
|
4
4
|
*
|
5
5
|
* (c) 2010-2014 Torstein Honsi
|
@@ -7,7 +7,7 @@
|
|
7
7
|
* License: www.highcharts.com/license
|
8
8
|
*/
|
9
9
|
|
10
|
-
/*global Highcharts*/
|
10
|
+
/*global Highcharts, HighchartsAdapter*/
|
11
11
|
(function (H) {
|
12
12
|
"use strict";
|
13
13
|
|
@@ -136,6 +136,15 @@
|
|
136
136
|
}
|
137
137
|
};
|
138
138
|
|
139
|
+
/**
|
140
|
+
* Handle animation of the color attributes directly
|
141
|
+
*/
|
142
|
+
each(['fill', 'stroke'], function (prop) {
|
143
|
+
HighchartsAdapter.addAnimSetter(prop, function (fx) {
|
144
|
+
fx.elem.attr(prop, colorAxisMethods.tweenColors(H.Color(fx.start), H.Color(fx.end), fx.pos));
|
145
|
+
});
|
146
|
+
});
|
147
|
+
|
139
148
|
// The series prototype
|
140
149
|
H.seriesTypes.solidgauge = H.extendClass(H.seriesTypes.gauge, {
|
141
150
|
type: 'solidgauge',
|
@@ -162,18 +171,21 @@
|
|
162
171
|
yAxis = series.yAxis,
|
163
172
|
center = yAxis.center,
|
164
173
|
options = series.options,
|
174
|
+
radius = series.radius = (pInt(pick(options.radius, 100)) * center[2]) / 200,
|
165
175
|
renderer = series.chart.renderer;
|
166
176
|
|
167
177
|
H.each(series.points, function (point) {
|
168
178
|
var graphic = point.graphic,
|
169
179
|
rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true),
|
170
|
-
radius = (pInt(pick(options.radius, 100)) * center[2]) / 200,
|
171
180
|
innerRadius = (pInt(pick(options.innerRadius, 60)) * center[2]) / 200,
|
172
181
|
shapeArgs,
|
173
182
|
d,
|
174
183
|
toColor = yAxis.toColor(point.y, point),
|
175
184
|
fromColor;
|
176
185
|
|
186
|
+
if (toColor === 'none') { // #3708
|
187
|
+
toColor = point.color || series.color || 'none';
|
188
|
+
}
|
177
189
|
if (toColor !== 'none') {
|
178
190
|
fromColor = point.color;
|
179
191
|
point.color = toColor;
|
@@ -194,41 +206,44 @@
|
|
194
206
|
maxAngle = minAngle + 2 * Math.PI;
|
195
207
|
}
|
196
208
|
|
197
|
-
shapeArgs = {
|
209
|
+
point.shapeArgs = shapeArgs = {
|
198
210
|
x: center[0],
|
199
211
|
y: center[1],
|
200
212
|
r: radius,
|
201
213
|
innerR: innerRadius,
|
202
214
|
start: minAngle,
|
203
|
-
end: maxAngle
|
215
|
+
end: maxAngle,
|
216
|
+
fill: toColor
|
204
217
|
};
|
205
218
|
|
206
219
|
if (graphic) {
|
207
220
|
d = shapeArgs.d;
|
208
|
-
|
209
|
-
/*jslint unparam: true*/
|
210
|
-
graphic.attr({
|
211
|
-
fill: point.color
|
212
|
-
}).animate(shapeArgs, {
|
213
|
-
step: function (value, fx) {
|
214
|
-
graphic.attr('fill', colorAxisMethods.tweenColors(H.Color(fromColor), H.Color(toColor), fx.pos));
|
215
|
-
}
|
216
|
-
});
|
217
|
-
/*jslint unparam: false*/
|
221
|
+
graphic.animate(shapeArgs);
|
218
222
|
shapeArgs.d = d; // animate alters it
|
219
223
|
} else {
|
220
224
|
point.graphic = renderer.arc(shapeArgs)
|
221
225
|
.attr({
|
222
226
|
stroke: options.borderColor || 'none',
|
223
227
|
'stroke-width': options.borderWidth || 0,
|
224
|
-
fill:
|
228
|
+
fill: toColor,
|
225
229
|
'sweep-flag': 0
|
226
230
|
})
|
227
231
|
.add(series.group);
|
228
232
|
}
|
229
233
|
});
|
230
234
|
},
|
231
|
-
|
235
|
+
|
236
|
+
/**
|
237
|
+
* Extend the pie slice animation by animating from start angle and up
|
238
|
+
*/
|
239
|
+
animate: function (init) {
|
240
|
+
|
241
|
+
this.center = this.yAxis.center;
|
242
|
+
this.center[3] = 2 * this.radius;
|
243
|
+
this.startAngleRad = this.yAxis.startAngleRad;
|
244
|
+
|
245
|
+
H.seriesTypes.pie.prototype.animate.call(this, init);
|
246
|
+
}
|
232
247
|
});
|
233
248
|
|
234
249
|
}(Highcharts));
|
@@ -0,0 +1,806 @@
|
|
1
|
+
/**
|
2
|
+
* @license Highcharts JS v4.1.0 (2015-02-16)
|
3
|
+
*
|
4
|
+
* (c) 2014 Highsoft AS
|
5
|
+
* Authors: Jon Arild Nygard / Oystein Moseng
|
6
|
+
*
|
7
|
+
* License: www.highcharts.com/license
|
8
|
+
*/
|
9
|
+
|
10
|
+
/*global HighchartsAdapter */
|
11
|
+
(function (H) {
|
12
|
+
var seriesTypes = H.seriesTypes,
|
13
|
+
merge = H.merge,
|
14
|
+
extendClass = H.extendClass,
|
15
|
+
defaultOptions = H.getOptions(),
|
16
|
+
plotOptions = defaultOptions.plotOptions,
|
17
|
+
noop = function () { return; },
|
18
|
+
each = H.each,
|
19
|
+
pick = H.pick,
|
20
|
+
Series = H.Series,
|
21
|
+
Color = H.Color;
|
22
|
+
|
23
|
+
// Define default options
|
24
|
+
plotOptions.treemap = merge(plotOptions.scatter, {
|
25
|
+
showInLegend: false,
|
26
|
+
marker: false,
|
27
|
+
borderColor: '#E0E0E0',
|
28
|
+
borderWidth: 1,
|
29
|
+
dataLabels: {
|
30
|
+
enabled: true,
|
31
|
+
defer: false,
|
32
|
+
verticalAlign: 'middle',
|
33
|
+
formatter: function () { // #2945
|
34
|
+
return this.point.name || this.point.id;
|
35
|
+
},
|
36
|
+
inside: true
|
37
|
+
},
|
38
|
+
tooltip: {
|
39
|
+
headerFormat: '',
|
40
|
+
pointFormat: '<b>{point.name}</b>: {point.value}</b><br/>'
|
41
|
+
},
|
42
|
+
layoutAlgorithm: 'sliceAndDice',
|
43
|
+
layoutStartingDirection: 'vertical',
|
44
|
+
alternateStartingDirection: false,
|
45
|
+
levelIsConstant: true,
|
46
|
+
states: {
|
47
|
+
hover: {
|
48
|
+
borderColor: '#A0A0A0',
|
49
|
+
brightness: seriesTypes.heatmap ? 0 : 0.1,
|
50
|
+
shadow: false
|
51
|
+
}
|
52
|
+
},
|
53
|
+
drillUpButton: {
|
54
|
+
position: {
|
55
|
+
align: 'left',
|
56
|
+
x: 10,
|
57
|
+
y: -50
|
58
|
+
}
|
59
|
+
}
|
60
|
+
});
|
61
|
+
|
62
|
+
// Stolen from heatmap
|
63
|
+
var colorSeriesMixin = {
|
64
|
+
// mapping between SVG attributes and the corresponding options
|
65
|
+
pointAttrToOptions: {
|
66
|
+
stroke: 'borderColor',
|
67
|
+
'stroke-width': 'borderWidth',
|
68
|
+
fill: 'color',
|
69
|
+
dashstyle: 'borderDashStyle'
|
70
|
+
},
|
71
|
+
pointArrayMap: ['value'],
|
72
|
+
axisTypes: seriesTypes.heatmap ? ['xAxis', 'yAxis', 'colorAxis'] : ['xAxis', 'yAxis'],
|
73
|
+
optionalAxis: 'colorAxis',
|
74
|
+
getSymbol: noop,
|
75
|
+
parallelArrays: ['x', 'y', 'value', 'colorValue'],
|
76
|
+
colorKey: 'colorValue', // Point color option key
|
77
|
+
translateColors: seriesTypes.heatmap && seriesTypes.heatmap.prototype.translateColors
|
78
|
+
};
|
79
|
+
|
80
|
+
// The Treemap series type
|
81
|
+
seriesTypes.treemap = extendClass(seriesTypes.scatter, merge(colorSeriesMixin, {
|
82
|
+
type: 'treemap',
|
83
|
+
trackerGroups: ['group', 'dataLabelsGroup'],
|
84
|
+
pointClass: extendClass(H.Point, {
|
85
|
+
setState: function (state, move) {
|
86
|
+
H.Point.prototype.setState.call(this, state, move);
|
87
|
+
if (state === 'hover') {
|
88
|
+
if (this.dataLabel) {
|
89
|
+
this.dataLabel.attr({ zIndex: 1002 });
|
90
|
+
}
|
91
|
+
} else {
|
92
|
+
if (this.dataLabel) {
|
93
|
+
this.dataLabel.attr({ zIndex: (this.pointAttr[''].zIndex + 1) });
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}),
|
98
|
+
handleLayout: function () {
|
99
|
+
var series = this,
|
100
|
+
tree = this.tree,
|
101
|
+
seriesArea;
|
102
|
+
if (this.points.length) {
|
103
|
+
// Assign variables
|
104
|
+
if (!tree) {
|
105
|
+
this.nodeMap = [];
|
106
|
+
tree = this.tree = this.getTree();
|
107
|
+
}
|
108
|
+
if (!this.rootNode) {
|
109
|
+
this.rootNode = "";
|
110
|
+
}
|
111
|
+
this.levelMap = this.getLevels();
|
112
|
+
each(series.points, function (point) {
|
113
|
+
// Reset visibility
|
114
|
+
delete point.plotX;
|
115
|
+
delete point.plotY;
|
116
|
+
});
|
117
|
+
seriesArea = this.getSeriesArea(tree.val);
|
118
|
+
this.nodeMap[""].values = seriesArea;
|
119
|
+
this.calculateArea(tree, seriesArea);
|
120
|
+
this.setPointValues();
|
121
|
+
}
|
122
|
+
},
|
123
|
+
/**
|
124
|
+
* Creates a tree structured object from the series points
|
125
|
+
*/
|
126
|
+
getTree: function () {
|
127
|
+
var tree,
|
128
|
+
series = this,
|
129
|
+
i = 0,
|
130
|
+
parentList = [],
|
131
|
+
allIds = [],
|
132
|
+
key,
|
133
|
+
insertItem = function (key) {
|
134
|
+
each(parentList[key], function (item) {
|
135
|
+
parentList[""].push(item);
|
136
|
+
});
|
137
|
+
},
|
138
|
+
getNodeTree = function (id, i, level, list, points, parent) {
|
139
|
+
var children = [],
|
140
|
+
sortedChildren = [],
|
141
|
+
childrenTotal = 0,
|
142
|
+
val,
|
143
|
+
point = points[i],
|
144
|
+
nodeTree,
|
145
|
+
node,
|
146
|
+
insertNode,
|
147
|
+
name;
|
148
|
+
insertNode = function () {
|
149
|
+
var i = 0,
|
150
|
+
inserted = false;
|
151
|
+
if (sortedChildren.length !== 0) {
|
152
|
+
each(sortedChildren, function (child) {
|
153
|
+
if (node.val > child.val && !inserted) {
|
154
|
+
sortedChildren.splice(i, 0, node);
|
155
|
+
inserted = true;
|
156
|
+
}
|
157
|
+
i = i + 1;
|
158
|
+
});
|
159
|
+
}
|
160
|
+
if (!inserted) {
|
161
|
+
sortedChildren.push(node);
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
// Actions
|
166
|
+
if (point) {
|
167
|
+
name = point.name || "";
|
168
|
+
}
|
169
|
+
if (list[id] !== undefined) {
|
170
|
+
each(list[id], function (i) {
|
171
|
+
node = getNodeTree(points[i].id, i, (level + 1), list, points, id);
|
172
|
+
childrenTotal += node.val;
|
173
|
+
insertNode();
|
174
|
+
children.push(node);
|
175
|
+
});
|
176
|
+
}
|
177
|
+
val = pick((points[i] && points[i].value), childrenTotal, 0);
|
178
|
+
nodeTree = {
|
179
|
+
id: id,
|
180
|
+
i: i,
|
181
|
+
children: sortedChildren,
|
182
|
+
childrenTotal: childrenTotal,
|
183
|
+
val: val,
|
184
|
+
level: level,
|
185
|
+
parent: parent,
|
186
|
+
name: name
|
187
|
+
};
|
188
|
+
series.nodeMap[nodeTree.id] = nodeTree;
|
189
|
+
return nodeTree;
|
190
|
+
};
|
191
|
+
// Actions
|
192
|
+
// Map children to index
|
193
|
+
each(this.points, function (point) {
|
194
|
+
var parent = "";
|
195
|
+
allIds.push(point.id);
|
196
|
+
if (point.parent !== undefined) {
|
197
|
+
parent = point.parent;
|
198
|
+
}
|
199
|
+
if (parentList[parent] === undefined) {
|
200
|
+
parentList[parent] = [];
|
201
|
+
}
|
202
|
+
parentList[parent].push(i);
|
203
|
+
i = i + 1;
|
204
|
+
});
|
205
|
+
/*
|
206
|
+
* Quality check:
|
207
|
+
* - If parent does not exist, then set parent to tree root
|
208
|
+
* - Add node id to parents children list
|
209
|
+
*/
|
210
|
+
for (key in parentList) {
|
211
|
+
if (parentList.hasOwnProperty(key)) {
|
212
|
+
if (key !== "") {
|
213
|
+
if (HighchartsAdapter.inArray(key, allIds) === -1) {
|
214
|
+
insertItem(key);
|
215
|
+
delete parentList[key];
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
220
|
+
tree = getNodeTree("", -1, 0, parentList, this.points, null);
|
221
|
+
return tree;
|
222
|
+
},
|
223
|
+
calculateArea: function (node, area) {
|
224
|
+
var childrenValues = [],
|
225
|
+
childValues,
|
226
|
+
series = this,
|
227
|
+
options = series.options,
|
228
|
+
algorithm = options.layoutAlgorithm,
|
229
|
+
alternate = options.alternateStartingDirection,
|
230
|
+
levelRoot = this.nodeMap[this.rootNode].level,
|
231
|
+
i = 0,
|
232
|
+
level,
|
233
|
+
levelNr = options.levelIsConstant ? node.level : (node.level - levelRoot),
|
234
|
+
point;
|
235
|
+
node.isVisible = (node.id === this.rootNode) || !!(this.nodeMap[node.parent] && this.nodeMap[node.parent].isVisible);
|
236
|
+
levelNr = (levelNr > 0) ? levelNr : 0;
|
237
|
+
// If layoutAlgorithm is set for the level of the children, then default is overwritten
|
238
|
+
if (this.levelMap[levelNr + 1]) {
|
239
|
+
level = this.levelMap[levelNr + 1];
|
240
|
+
if (level.layoutAlgorithm && series[level.layoutAlgorithm]) {
|
241
|
+
algorithm = level.layoutAlgorithm;
|
242
|
+
}
|
243
|
+
if (level.layoutStartingDirection) {
|
244
|
+
area.direction = level.layoutStartingDirection === 'vertical' ? 0 : 1;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
childrenValues = series[algorithm](area, node.children);
|
248
|
+
each(node.children, function (child) {
|
249
|
+
levelNr = options.levelIsConstant ? child.level : (child.level - levelRoot);
|
250
|
+
point = series.points[child.i];
|
251
|
+
point.level = levelNr;
|
252
|
+
childValues = childrenValues[i];
|
253
|
+
childValues.val = child.childrenTotal;
|
254
|
+
childValues.direction = area.direction;
|
255
|
+
if (alternate) {
|
256
|
+
childValues.direction = 1 - childValues.direction;
|
257
|
+
}
|
258
|
+
child.values = childValues;
|
259
|
+
child.isVisible = node.isVisible;
|
260
|
+
point.node = child;
|
261
|
+
point.value = child.val;
|
262
|
+
point.isLeaf = true;
|
263
|
+
// If node has children, then call method recursively
|
264
|
+
if (child.children.length) {
|
265
|
+
point.isLeaf = false;
|
266
|
+
series.calculateArea(child, childValues);
|
267
|
+
}
|
268
|
+
i = i + 1;
|
269
|
+
});
|
270
|
+
},
|
271
|
+
setPointValues: function () {
|
272
|
+
var series = this,
|
273
|
+
xAxis = series.xAxis,
|
274
|
+
yAxis = series.yAxis;
|
275
|
+
series.nodeMap[""].values = {
|
276
|
+
x: 0,
|
277
|
+
y: 0,
|
278
|
+
width: 100,
|
279
|
+
height: 100
|
280
|
+
};
|
281
|
+
each(series.points, function (point) {
|
282
|
+
var node = point.node,
|
283
|
+
values = node.values,
|
284
|
+
x1,
|
285
|
+
x2,
|
286
|
+
y1,
|
287
|
+
y2;
|
288
|
+
values.x = values.x / series.axisRatio;
|
289
|
+
values.width = values.width / series.axisRatio;
|
290
|
+
x1 = Math.round(xAxis.translate(values.x, 0, 0, 0, 1));
|
291
|
+
x2 = Math.round(xAxis.translate(values.x + values.width, 0, 0, 0, 1));
|
292
|
+
y1 = Math.round(yAxis.translate(values.y, 0, 0, 0, 1));
|
293
|
+
y2 = Math.round(yAxis.translate(values.y + values.height, 0, 0, 0, 1));
|
294
|
+
if (point.value > 0) {
|
295
|
+
// Set point values
|
296
|
+
point.shapeType = 'rect';
|
297
|
+
point.shapeArgs = {
|
298
|
+
x: Math.min(x1, x2),
|
299
|
+
y: Math.min(y1, y2),
|
300
|
+
width: Math.abs(x2 - x1),
|
301
|
+
height: Math.abs(y2 - y1)
|
302
|
+
};
|
303
|
+
point.plotX = point.shapeArgs.x + (point.shapeArgs.width / 2);
|
304
|
+
point.plotY = point.shapeArgs.y + (point.shapeArgs.height / 2);
|
305
|
+
}
|
306
|
+
});
|
307
|
+
},
|
308
|
+
getSeriesArea: function (val) {
|
309
|
+
var x = 0,
|
310
|
+
y = 0,
|
311
|
+
h = 100,
|
312
|
+
r = this.axisRatio = (this.xAxis.len / this.yAxis.len),
|
313
|
+
w = 100 * r,
|
314
|
+
d = this.options.layoutStartingDirection === 'vertical' ? 0 : 1,
|
315
|
+
seriesArea = {
|
316
|
+
x: x,
|
317
|
+
y: y,
|
318
|
+
width: w,
|
319
|
+
height: h,
|
320
|
+
direction: d,
|
321
|
+
val: val
|
322
|
+
};
|
323
|
+
return seriesArea;
|
324
|
+
},
|
325
|
+
getLevels: function () {
|
326
|
+
var map = [],
|
327
|
+
levels = this.options.levels;
|
328
|
+
if (levels) {
|
329
|
+
each(levels, function (level) {
|
330
|
+
if (level.level !== undefined) {
|
331
|
+
map[level.level] = level;
|
332
|
+
}
|
333
|
+
});
|
334
|
+
}
|
335
|
+
return map;
|
336
|
+
},
|
337
|
+
setColorRecursive: function (node, color) {
|
338
|
+
var series = this,
|
339
|
+
point,
|
340
|
+
level;
|
341
|
+
if (node) {
|
342
|
+
point = series.points[node.i];
|
343
|
+
level = series.levelMap[node.level];
|
344
|
+
// Select either point color, level color or inherited color.
|
345
|
+
color = pick(point && point.options.color, level && level.color, color);
|
346
|
+
if (point) {
|
347
|
+
point.color = color;
|
348
|
+
}
|
349
|
+
// Do it all again with the children
|
350
|
+
if (node.children.length) {
|
351
|
+
each(node.children, function (child) {
|
352
|
+
series.setColorRecursive(child, color);
|
353
|
+
});
|
354
|
+
}
|
355
|
+
}
|
356
|
+
},
|
357
|
+
alg_func_group: function (h, w, d, p) {
|
358
|
+
this.height = h;
|
359
|
+
this.width = w;
|
360
|
+
this.plot = p;
|
361
|
+
this.direction = d;
|
362
|
+
this.startDirection = d;
|
363
|
+
this.total = 0;
|
364
|
+
this.nW = 0;
|
365
|
+
this.lW = 0;
|
366
|
+
this.nH = 0;
|
367
|
+
this.lH = 0;
|
368
|
+
this.elArr = [];
|
369
|
+
this.lP = {
|
370
|
+
total: 0,
|
371
|
+
lH: 0,
|
372
|
+
nH: 0,
|
373
|
+
lW: 0,
|
374
|
+
nW: 0,
|
375
|
+
nR: 0,
|
376
|
+
lR: 0,
|
377
|
+
aspectRatio: function (w, h) {
|
378
|
+
return Math.max((w / h), (h / w));
|
379
|
+
}
|
380
|
+
};
|
381
|
+
this.addElement = function (el) {
|
382
|
+
this.lP.total = this.elArr[this.elArr.length - 1];
|
383
|
+
this.total = this.total + el;
|
384
|
+
if (this.direction === 0) {
|
385
|
+
// Calculate last point old aspect ratio
|
386
|
+
this.lW = this.nW;
|
387
|
+
this.lP.lH = this.lP.total / this.lW;
|
388
|
+
this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH);
|
389
|
+
// Calculate last point new aspect ratio
|
390
|
+
this.nW = this.total / this.height;
|
391
|
+
this.lP.nH = this.lP.total / this.nW;
|
392
|
+
this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH);
|
393
|
+
} else {
|
394
|
+
// Calculate last point old aspect ratio
|
395
|
+
this.lH = this.nH;
|
396
|
+
this.lP.lW = this.lP.total / this.lH;
|
397
|
+
this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH);
|
398
|
+
// Calculate last point new aspect ratio
|
399
|
+
this.nH = this.total / this.width;
|
400
|
+
this.lP.nW = this.lP.total / this.nH;
|
401
|
+
this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH);
|
402
|
+
}
|
403
|
+
this.elArr.push(el);
|
404
|
+
};
|
405
|
+
this.reset = function () {
|
406
|
+
this.nW = 0;
|
407
|
+
this.lW = 0;
|
408
|
+
this.elArr = [];
|
409
|
+
this.total = 0;
|
410
|
+
};
|
411
|
+
},
|
412
|
+
alg_func_calcPoints: function (directionChange, last, group, childrenArea) {
|
413
|
+
var pX,
|
414
|
+
pY,
|
415
|
+
pW,
|
416
|
+
pH,
|
417
|
+
gW = group.lW,
|
418
|
+
gH = group.lH,
|
419
|
+
plot = group.plot,
|
420
|
+
keep,
|
421
|
+
i = 0,
|
422
|
+
end = group.elArr.length - 1;
|
423
|
+
if (last) {
|
424
|
+
gW = group.nW;
|
425
|
+
gH = group.nH;
|
426
|
+
} else {
|
427
|
+
keep = group.elArr[group.elArr.length - 1];
|
428
|
+
}
|
429
|
+
each(group.elArr, function (p) {
|
430
|
+
if (last || (i < end)) {
|
431
|
+
if (group.direction === 0) {
|
432
|
+
pX = plot.x;
|
433
|
+
pY = plot.y;
|
434
|
+
pW = gW;
|
435
|
+
pH = p / pW;
|
436
|
+
} else {
|
437
|
+
pX = plot.x;
|
438
|
+
pY = plot.y;
|
439
|
+
pH = gH;
|
440
|
+
pW = p / pH;
|
441
|
+
}
|
442
|
+
childrenArea.push({
|
443
|
+
x: pX,
|
444
|
+
y: pY,
|
445
|
+
width: pW,
|
446
|
+
height: pH
|
447
|
+
});
|
448
|
+
if (group.direction === 0) {
|
449
|
+
plot.y = plot.y + pH;
|
450
|
+
} else {
|
451
|
+
plot.x = plot.x + pW;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
i = i + 1;
|
455
|
+
});
|
456
|
+
// Reset variables
|
457
|
+
group.reset();
|
458
|
+
if (group.direction === 0) {
|
459
|
+
group.width = group.width - gW;
|
460
|
+
} else {
|
461
|
+
group.height = group.height - gH;
|
462
|
+
}
|
463
|
+
plot.y = plot.parent.y + (plot.parent.height - group.height);
|
464
|
+
plot.x = plot.parent.x + (plot.parent.width - group.width);
|
465
|
+
if (directionChange) {
|
466
|
+
group.direction = 1 - group.direction;
|
467
|
+
}
|
468
|
+
// If not last, then add uncalculated element
|
469
|
+
if (!last) {
|
470
|
+
group.addElement(keep);
|
471
|
+
}
|
472
|
+
},
|
473
|
+
alg_func_lowAspectRatio: function (directionChange, parent, children) {
|
474
|
+
var childrenArea = [],
|
475
|
+
series = this,
|
476
|
+
pTot,
|
477
|
+
plot = {
|
478
|
+
x: parent.x,
|
479
|
+
y: parent.y,
|
480
|
+
parent: parent
|
481
|
+
},
|
482
|
+
direction = parent.direction,
|
483
|
+
i = 0,
|
484
|
+
end = children.length - 1,
|
485
|
+
group = new this.alg_func_group(parent.height, parent.width, direction, plot);
|
486
|
+
// Loop through and calculate all areas
|
487
|
+
each(children, function (child) {
|
488
|
+
pTot = (parent.width * parent.height) * (child.val / parent.val);
|
489
|
+
group.addElement(pTot);
|
490
|
+
if (group.lP.nR > group.lP.lR) {
|
491
|
+
series.alg_func_calcPoints(directionChange, false, group, childrenArea, plot);
|
492
|
+
}
|
493
|
+
// If last child, then calculate all remaining areas
|
494
|
+
if (i === end) {
|
495
|
+
series.alg_func_calcPoints(directionChange, true, group, childrenArea, plot);
|
496
|
+
}
|
497
|
+
i = i + 1;
|
498
|
+
});
|
499
|
+
return childrenArea;
|
500
|
+
},
|
501
|
+
alg_func_fill: function (directionChange, parent, children) {
|
502
|
+
var childrenArea = [],
|
503
|
+
pTot,
|
504
|
+
direction = parent.direction,
|
505
|
+
x = parent.x,
|
506
|
+
y = parent.y,
|
507
|
+
width = parent.width,
|
508
|
+
height = parent.height,
|
509
|
+
pX,
|
510
|
+
pY,
|
511
|
+
pW,
|
512
|
+
pH;
|
513
|
+
each(children, function (child) {
|
514
|
+
pTot = (parent.width * parent.height) * (child.val / parent.val);
|
515
|
+
pX = x;
|
516
|
+
pY = y;
|
517
|
+
if (direction === 0) {
|
518
|
+
pH = height;
|
519
|
+
pW = pTot / pH;
|
520
|
+
width = width - pW;
|
521
|
+
x = x + pW;
|
522
|
+
} else {
|
523
|
+
pW = width;
|
524
|
+
pH = pTot / pW;
|
525
|
+
height = height - pH;
|
526
|
+
y = y + pH;
|
527
|
+
}
|
528
|
+
childrenArea.push({
|
529
|
+
x: pX,
|
530
|
+
y: pY,
|
531
|
+
width: pW,
|
532
|
+
height: pH
|
533
|
+
});
|
534
|
+
if (directionChange) {
|
535
|
+
direction = 1 - direction;
|
536
|
+
}
|
537
|
+
});
|
538
|
+
return childrenArea;
|
539
|
+
},
|
540
|
+
strip: function (parent, children) {
|
541
|
+
return this.alg_func_lowAspectRatio(false, parent, children);
|
542
|
+
},
|
543
|
+
squarified: function (parent, children) {
|
544
|
+
return this.alg_func_lowAspectRatio(true, parent, children);
|
545
|
+
},
|
546
|
+
sliceAndDice: function (parent, children) {
|
547
|
+
return this.alg_func_fill(true, parent, children);
|
548
|
+
},
|
549
|
+
stripes: function (parent, children) {
|
550
|
+
return this.alg_func_fill(false, parent, children);
|
551
|
+
},
|
552
|
+
translate: function () {
|
553
|
+
// Call prototype function
|
554
|
+
Series.prototype.translate.call(this);
|
555
|
+
this.handleLayout();
|
556
|
+
|
557
|
+
// If a colorAxis is defined
|
558
|
+
if (this.colorAxis) {
|
559
|
+
this.translateColors();
|
560
|
+
} else {
|
561
|
+
this.setColorRecursive(this.tree, undefined);
|
562
|
+
}
|
563
|
+
},
|
564
|
+
/**
|
565
|
+
* Extend drawDataLabels with logic to handle the levels option
|
566
|
+
*/
|
567
|
+
drawDataLabels: function () {
|
568
|
+
var series = this,
|
569
|
+
points = series.points,
|
570
|
+
options,
|
571
|
+
level,
|
572
|
+
dataLabelsGroup = this.dataLabelsGroup,
|
573
|
+
dataLabels;
|
574
|
+
each(points, function (point) {
|
575
|
+
if (point.node.isVisible) {
|
576
|
+
level = series.levelMap[point.level];
|
577
|
+
if (!point.isLeaf || level) {
|
578
|
+
options = undefined;
|
579
|
+
// If not a leaf, then label should be disabled as default
|
580
|
+
if (!point.isLeaf) {
|
581
|
+
options = {enabled: false};
|
582
|
+
}
|
583
|
+
if (level) {
|
584
|
+
dataLabels = level.dataLabels;
|
585
|
+
if (dataLabels) {
|
586
|
+
options = merge(options, dataLabels);
|
587
|
+
series._hasPointLabels = true;
|
588
|
+
}
|
589
|
+
}
|
590
|
+
options = merge(options, point.options.dataLabels);
|
591
|
+
point.dlOptions = options;
|
592
|
+
} else {
|
593
|
+
delete point.dlOptions;
|
594
|
+
}
|
595
|
+
}
|
596
|
+
});
|
597
|
+
this.dataLabelsGroup = this.group;
|
598
|
+
Series.prototype.drawDataLabels.call(this);
|
599
|
+
this.dataLabelsGroup = dataLabelsGroup;
|
600
|
+
},
|
601
|
+
alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
|
602
|
+
/**
|
603
|
+
* Extending ColumnSeries drawPoints
|
604
|
+
*/
|
605
|
+
drawPoints: function () {
|
606
|
+
var series = this,
|
607
|
+
points = series.points,
|
608
|
+
seriesOptions = series.options,
|
609
|
+
attr,
|
610
|
+
hover,
|
611
|
+
level;
|
612
|
+
each(points, function (point) {
|
613
|
+
if (point.node.isVisible) {
|
614
|
+
level = series.levelMap[point.level];
|
615
|
+
attr = {
|
616
|
+
stroke: seriesOptions.borderColor,
|
617
|
+
'stroke-width': seriesOptions.borderWidth,
|
618
|
+
dashstyle: seriesOptions.borderDashStyle,
|
619
|
+
r: 0, // borderRadius gives wrong size relations and should always be disabled
|
620
|
+
fill: pick(point.color, series.color)
|
621
|
+
};
|
622
|
+
// Overwrite standard series options with level options
|
623
|
+
if (level) {
|
624
|
+
attr.stroke = level.borderColor || attr.stroke;
|
625
|
+
attr['stroke-width'] = level.borderWidth || attr['stroke-width'];
|
626
|
+
attr.dashstyle = level.borderDashStyle || attr.dashstyle;
|
627
|
+
}
|
628
|
+
// Merge with point attributes
|
629
|
+
attr.stroke = point.borderColor || attr.stroke;
|
630
|
+
attr['stroke-width'] = point.borderWidth || attr['stroke-width'];
|
631
|
+
attr.dashstyle = point.borderDashStyle || attr.dashstyle;
|
632
|
+
attr.zIndex = (1000 - (point.level * 2));
|
633
|
+
|
634
|
+
// Make a copy to prevent overwriting individual props
|
635
|
+
point.pointAttr = merge(point.pointAttr);
|
636
|
+
hover = point.pointAttr.hover;
|
637
|
+
hover.zIndex = 1001;
|
638
|
+
hover.fill = Color(attr.fill).brighten(seriesOptions.states.hover.brightness).get();
|
639
|
+
// If not a leaf, then remove fill
|
640
|
+
if (!point.isLeaf) {
|
641
|
+
if (seriesOptions.allowDrillToNode) {
|
642
|
+
// TODO: let users set the opacity
|
643
|
+
attr.fill = Color(attr.fill).setOpacity(0.15).get();
|
644
|
+
hover.fill = Color(hover.fill).setOpacity(0.75).get();
|
645
|
+
} else {
|
646
|
+
attr.fill = 'none';
|
647
|
+
delete hover.fill;
|
648
|
+
}
|
649
|
+
}
|
650
|
+
if (point.node.level <= series.nodeMap[series.rootNode].level) {
|
651
|
+
attr.fill = 'none';
|
652
|
+
attr.zIndex = 0;
|
653
|
+
delete hover.fill;
|
654
|
+
}
|
655
|
+
point.pointAttr[''] = H.extend(point.pointAttr[''], attr);
|
656
|
+
if (point.dataLabel) {
|
657
|
+
point.dataLabel.attr({ zIndex: (point.pointAttr[''].zIndex + 1) });
|
658
|
+
}
|
659
|
+
}
|
660
|
+
});
|
661
|
+
// Call standard drawPoints
|
662
|
+
seriesTypes.column.prototype.drawPoints.call(this);
|
663
|
+
|
664
|
+
each(points, function (point) {
|
665
|
+
if (point.graphic) {
|
666
|
+
point.graphic.attr(point.pointAttr['']);
|
667
|
+
}
|
668
|
+
});
|
669
|
+
|
670
|
+
// Set click events on points
|
671
|
+
if (seriesOptions.allowDrillToNode) {
|
672
|
+
series.drillCloser();
|
673
|
+
}
|
674
|
+
},
|
675
|
+
/**
|
676
|
+
* Add drilling on the suitable points
|
677
|
+
* TODO: review and better naming
|
678
|
+
*/
|
679
|
+
drillCloser: function () {
|
680
|
+
var series = this,
|
681
|
+
points = series.points,
|
682
|
+
nodeParent;
|
683
|
+
each(points, function (point) {
|
684
|
+
var nodeParentName;
|
685
|
+
if (point.node.isVisible) {
|
686
|
+
H.removeEvent(point, 'click');
|
687
|
+
if (point.graphic) {
|
688
|
+
point.graphic.css({ cursor: 'default' });
|
689
|
+
}
|
690
|
+
if ((point.node.level - series.nodeMap[series.rootNode].level) === 1 && !point.isLeaf) {
|
691
|
+
nodeParent = series.nodeMap[series.nodeMap[point.id].parent];
|
692
|
+
nodeParentName = nodeParent.name || nodeParent.id;
|
693
|
+
if (point.graphic) {
|
694
|
+
point.graphic.css({ cursor: 'pointer' });
|
695
|
+
}
|
696
|
+
H.addEvent(point, 'click', function () {
|
697
|
+
// Remove hover
|
698
|
+
point.setState('');
|
699
|
+
series.drillToNode(point.id);
|
700
|
+
series.showDrillUpButton(nodeParentName);
|
701
|
+
});
|
702
|
+
}
|
703
|
+
}
|
704
|
+
});
|
705
|
+
},
|
706
|
+
drillUp: function () {
|
707
|
+
var drillPoint = null,
|
708
|
+
node,
|
709
|
+
parent;
|
710
|
+
if (this.rootNode) {
|
711
|
+
node = this.nodeMap[this.rootNode];
|
712
|
+
if (node.parent !== null) {
|
713
|
+
drillPoint = this.nodeMap[node.parent];
|
714
|
+
} else {
|
715
|
+
drillPoint = this.nodeMap[""];
|
716
|
+
}
|
717
|
+
}
|
718
|
+
|
719
|
+
if (drillPoint !== null) {
|
720
|
+
this.drillToNode(drillPoint.id);
|
721
|
+
if (drillPoint.id === "") {
|
722
|
+
this.drillUpButton = this.drillUpButton.destroy();
|
723
|
+
} else {
|
724
|
+
parent = this.nodeMap[drillPoint.parent];
|
725
|
+
this.showDrillUpButton((parent.name || parent.id));
|
726
|
+
}
|
727
|
+
}
|
728
|
+
},
|
729
|
+
drillToNode: function (id) {
|
730
|
+
var node = this.nodeMap[id],
|
731
|
+
val = node.values;
|
732
|
+
this.rootNode = id;
|
733
|
+
this.xAxis.setExtremes(val.x, val.x + val.width, false);
|
734
|
+
this.yAxis.setExtremes(val.y, val.y + val.height, false);
|
735
|
+
this.chart.redraw();
|
736
|
+
},
|
737
|
+
showDrillUpButton: function (name) {
|
738
|
+
var series = this,
|
739
|
+
backText = (name || '< Back'),
|
740
|
+
buttonOptions = series.options.drillUpButton,
|
741
|
+
attr,
|
742
|
+
states;
|
743
|
+
|
744
|
+
if (buttonOptions.text) {
|
745
|
+
backText = buttonOptions.text;
|
746
|
+
}
|
747
|
+
if (!this.drillUpButton) {
|
748
|
+
attr = buttonOptions.theme;
|
749
|
+
states = attr && attr.states;
|
750
|
+
|
751
|
+
this.drillUpButton = this.chart.renderer.button(
|
752
|
+
backText,
|
753
|
+
null,
|
754
|
+
null,
|
755
|
+
function () {
|
756
|
+
series.drillUp();
|
757
|
+
},
|
758
|
+
attr,
|
759
|
+
states && states.hover,
|
760
|
+
states && states.select
|
761
|
+
)
|
762
|
+
.attr({
|
763
|
+
align: buttonOptions.position.align,
|
764
|
+
zIndex: 9
|
765
|
+
})
|
766
|
+
.add()
|
767
|
+
.align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
|
768
|
+
} else {
|
769
|
+
this.drillUpButton.attr({
|
770
|
+
text: backText
|
771
|
+
})
|
772
|
+
.align();
|
773
|
+
}
|
774
|
+
},
|
775
|
+
buildKDTree: noop,
|
776
|
+
drawLegendSymbol: H.LegendSymbolMixin.drawRectangle,
|
777
|
+
getExtremes: function () {
|
778
|
+
// Get the extremes from the value data
|
779
|
+
Series.prototype.getExtremes.call(this, this.colorValueData);
|
780
|
+
this.valueMin = this.dataMin;
|
781
|
+
this.valueMax = this.dataMax;
|
782
|
+
|
783
|
+
// Get the extremes from the y data
|
784
|
+
Series.prototype.getExtremes.call(this);
|
785
|
+
},
|
786
|
+
bindAxes: function () {
|
787
|
+
var treeAxis = {
|
788
|
+
endOnTick: false,
|
789
|
+
gridLineWidth: 0,
|
790
|
+
lineWidth: 0,
|
791
|
+
min: 0,
|
792
|
+
dataMin: 0,
|
793
|
+
minPadding: 0,
|
794
|
+
max: 100,
|
795
|
+
dataMax: 100,
|
796
|
+
maxPadding: 0,
|
797
|
+
startOnTick: false,
|
798
|
+
title: null,
|
799
|
+
tickPositions: []
|
800
|
+
};
|
801
|
+
Series.prototype.bindAxes.call(this);
|
802
|
+
H.extend(this.yAxis.options, treeAxis);
|
803
|
+
H.extend(this.xAxis.options, treeAxis);
|
804
|
+
}
|
805
|
+
}));
|
806
|
+
}(Highcharts));
|