highcharts-rails 4.1.8 → 4.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +51 -0
- data/app/assets/javascripts/highcharts.js +340 -178
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +15 -8
- data/app/assets/javascripts/highcharts/highcharts-3d.js +78 -35
- data/app/assets/javascripts/highcharts/highcharts-more.js +43 -19
- data/app/assets/javascripts/highcharts/modules/boost.js +4 -4
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +1 -5
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +1 -1
- data/app/assets/javascripts/highcharts/modules/data.js +1 -1
- data/app/assets/javascripts/highcharts/modules/exporting.js +4 -3
- data/app/assets/javascripts/highcharts/modules/heatmap.js +18 -12
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +1 -1
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +3 -2
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +1 -1
- data/app/assets/javascripts/highcharts/modules/treemap.js +227 -236
- data/lib/highcharts/version.rb +1 -1
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.1.
|
2
|
+
* @license Highcharts JS v4.1.9 (2015-10-07)
|
3
3
|
* Exporting module
|
4
4
|
*
|
5
5
|
* (c) 2010-2014 Torstein Honsi
|
@@ -293,7 +293,8 @@ extend(Chart.prototype, {
|
|
293
293
|
extend(options.chart, {
|
294
294
|
animation: false,
|
295
295
|
renderTo: sandbox,
|
296
|
-
forExport:
|
296
|
+
forExport: true,
|
297
|
+
renderer: 'SVGRenderer',
|
297
298
|
width: sourceWidth,
|
298
299
|
height: sourceHeight
|
299
300
|
});
|
@@ -353,7 +354,7 @@ extend(Chart.prototype, {
|
|
353
354
|
if (allowHTML) {
|
354
355
|
html = svg.match(/<\/svg>(.*?$)/);
|
355
356
|
if (html) {
|
356
|
-
html = '<foreignObject x="0" y="0 width="200" height="200">' +
|
357
|
+
html = '<foreignObject x="0" y="0" width="200" height="200">' +
|
357
358
|
'<body xmlns="http://www.w3.org/1999/xhtml">' +
|
358
359
|
html[1] +
|
359
360
|
'</body>' +
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.1.
|
2
|
+
* @license Highcharts JS v4.1.9 (2015-10-07)
|
3
3
|
*
|
4
4
|
* (c) 2011-2014 Torstein Honsi
|
5
5
|
*
|
@@ -256,20 +256,23 @@ extend(ColorAxis.prototype, {
|
|
256
256
|
return color;
|
257
257
|
},
|
258
258
|
|
259
|
+
/**
|
260
|
+
* Override the getOffset method to add the whole axis groups inside the legend.
|
261
|
+
*/
|
259
262
|
getOffset: function () {
|
260
263
|
var group = this.legendGroup,
|
261
264
|
sideOffset = this.chart.axisOffset[this.side];
|
262
265
|
|
263
266
|
if (group) {
|
264
267
|
|
268
|
+
// Hook for the getOffset method to add groups to this parent group
|
269
|
+
this.axisParent = group;
|
270
|
+
|
271
|
+
// Call the base
|
265
272
|
Axis.prototype.getOffset.call(this);
|
266
|
-
|
267
|
-
if (!this.axisGroup.parentGroup) {
|
268
273
|
|
269
|
-
|
270
|
-
|
271
|
-
this.gridGroup.add(group);
|
272
|
-
this.labelGroup.add(group);
|
274
|
+
// First time only
|
275
|
+
if (!this.added) {
|
273
276
|
|
274
277
|
this.added = true;
|
275
278
|
|
@@ -644,17 +647,20 @@ seriesTypes.heatmap = extendClass(seriesTypes.scatter, merge(colorSeriesMixin, {
|
|
644
647
|
var series = this,
|
645
648
|
options = series.options,
|
646
649
|
xAxis = series.xAxis,
|
647
|
-
yAxis = series.yAxis
|
650
|
+
yAxis = series.yAxis,
|
651
|
+
between = function (x, a, b) {
|
652
|
+
return Math.min(Math.max(a, x), b);
|
653
|
+
};
|
648
654
|
|
649
655
|
series.generatePoints();
|
650
656
|
|
651
657
|
each(series.points, function (point) {
|
652
658
|
var xPad = (options.colsize || 1) / 2,
|
653
659
|
yPad = (options.rowsize || 1) / 2,
|
654
|
-
x1 = Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)),
|
655
|
-
x2 = Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)),
|
656
|
-
y1 = Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
|
657
|
-
y2 = Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1));
|
660
|
+
x1 = between(Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)), 0, xAxis.len),
|
661
|
+
x2 = between(Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)), 0, xAxis.len),
|
662
|
+
y1 = between(Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)), 0, yAxis.len),
|
663
|
+
y2 = between(Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1)), 0, yAxis.len);
|
658
664
|
|
659
665
|
// Set plotX and plotY for use in K-D-Tree and more
|
660
666
|
point.plotX = point.clientX = (x1 + x2) / 2;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.1.
|
2
|
+
* @license Highcharts JS v4.1.9 (2015-10-07)
|
3
3
|
* Client side exporting module
|
4
4
|
*
|
5
5
|
* (c) 2015 Torstein Honsi / Oystein Moseng
|
@@ -85,7 +85,8 @@ Highcharts.Chart.prototype.exportChartLocal = function (exportingOptions, chartO
|
|
85
85
|
svgToDataUrl = function (svg) {
|
86
86
|
try {
|
87
87
|
// Safari requires data URI since it doesn't allow navigation to blob URLs
|
88
|
-
|
88
|
+
// Firefox has an issue with Blobs and internal references, leading to gradients not working using Blobs (#4550)
|
89
|
+
if (!webKit && navigator.userAgent.toLowerCase().indexOf('firefox') < 0) {
|
89
90
|
return domurl.createObjectURL(new Blob([svg], { type: 'image/svg+xml;charset-utf-16'}));
|
90
91
|
}
|
91
92
|
} catch (e) {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.1.
|
2
|
+
* @license Highcharts JS v4.1.9 (2015-10-07)
|
3
3
|
*
|
4
4
|
* (c) 2014 Highsoft AS
|
5
5
|
* Authors: Jon Arild Nygard / Oystein Moseng
|
@@ -10,6 +10,7 @@
|
|
10
10
|
/*global HighchartsAdapter */
|
11
11
|
(function (H) {
|
12
12
|
var seriesTypes = H.seriesTypes,
|
13
|
+
map = H.map,
|
13
14
|
merge = H.merge,
|
14
15
|
extend = H.extend,
|
15
16
|
extendClass = H.extendClass,
|
@@ -20,7 +21,33 @@
|
|
20
21
|
grep = HighchartsAdapter.grep,
|
21
22
|
pick = H.pick,
|
22
23
|
Series = H.Series,
|
23
|
-
Color = H.Color
|
24
|
+
Color = H.Color,
|
25
|
+
eachObject = function (list, func, context) {
|
26
|
+
var key;
|
27
|
+
context = context || this;
|
28
|
+
for (key in list) {
|
29
|
+
if (list.hasOwnProperty(key)) {
|
30
|
+
func.call(context, list[key], key, list);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
},
|
34
|
+
reduce = function (arr, func, previous, context) {
|
35
|
+
context = context || this;
|
36
|
+
arr = arr || []; // @note should each be able to handle empty values automatically?
|
37
|
+
each(arr, function (current, i) {
|
38
|
+
previous = func.call(context, previous, current, i, arr);
|
39
|
+
});
|
40
|
+
return previous;
|
41
|
+
},
|
42
|
+
// @todo find correct name for this function.
|
43
|
+
recursive = function (item, func, context) {
|
44
|
+
var next;
|
45
|
+
context = context || this;
|
46
|
+
next = func.call(context, item);
|
47
|
+
if (next !== false) {
|
48
|
+
recursive(next, func, context);
|
49
|
+
}
|
50
|
+
};
|
24
51
|
|
25
52
|
// Define default options
|
26
53
|
plotOptions.treemap = merge(plotOptions.scatter, {
|
@@ -64,12 +91,7 @@
|
|
64
91
|
// Stolen from heatmap
|
65
92
|
var colorSeriesMixin = {
|
66
93
|
// mapping between SVG attributes and the corresponding options
|
67
|
-
pointAttrToOptions: {
|
68
|
-
stroke: 'borderColor',
|
69
|
-
'stroke-width': 'borderWidth',
|
70
|
-
fill: 'color',
|
71
|
-
dashstyle: 'borderDashStyle'
|
72
|
-
},
|
94
|
+
pointAttrToOptions: {},
|
73
95
|
pointArrayMap: ['value'],
|
74
96
|
axisTypes: seriesTypes.heatmap ? ['xAxis', 'yAxis', 'colorAxis'] : ['xAxis', 'yAxis'],
|
75
97
|
optionalAxis: 'colorAxis',
|
@@ -84,33 +106,35 @@
|
|
84
106
|
type: 'treemap',
|
85
107
|
trackerGroups: ['group', 'dataLabelsGroup'],
|
86
108
|
pointClass: extendClass(H.Point, {
|
87
|
-
setState: function (state, move) {
|
88
|
-
H.Point.prototype.setState.call(this, state, move);
|
89
|
-
if (state === 'hover') {
|
90
|
-
if (this.dataLabel) {
|
91
|
-
this.dataLabel.attr({ zIndex: 1002 });
|
92
|
-
}
|
93
|
-
} else {
|
94
|
-
if (this.dataLabel) {
|
95
|
-
this.dataLabel.attr({ zIndex: (this.pointAttr[''].zIndex + 1) });
|
96
|
-
}
|
97
|
-
}
|
98
|
-
},
|
99
109
|
setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible
|
100
110
|
}),
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
/**
|
112
|
+
* Creates an object map from parent id to childrens index.
|
113
|
+
* @param {Array} data List of points set in options.
|
114
|
+
* @param {string} data[].parent Parent id of point.
|
115
|
+
* @param {Array} ids List of all point ids.
|
116
|
+
* @return {Object} Map from parent id to children index in data.
|
117
|
+
*/
|
118
|
+
getListOfParents: function (data, ids) {
|
119
|
+
var listOfParents = reduce(data, function (prev, curr, i) {
|
120
|
+
var parent = pick(curr.parent, "");
|
121
|
+
if (prev[parent] === undefined) {
|
122
|
+
prev[parent] = [];
|
123
|
+
}
|
124
|
+
prev[parent].push(i);
|
125
|
+
return prev;
|
126
|
+
}, {});
|
127
|
+
|
128
|
+
// If parent does not exist, hoist parent to root of tree.
|
129
|
+
eachObject(listOfParents, function (children, parent, list) {
|
130
|
+
if ((parent !== "") && (HighchartsAdapter.inArray(parent, ids) === -1)) {
|
131
|
+
each(children, function (child) {
|
132
|
+
list[""].push(child);
|
133
|
+
});
|
134
|
+
delete list[parent];
|
135
|
+
}
|
136
|
+
});
|
137
|
+
return listOfParents;
|
114
138
|
},
|
115
139
|
/**
|
116
140
|
* Creates a tree structured object from the series points
|
@@ -118,51 +142,42 @@
|
|
118
142
|
getTree: function () {
|
119
143
|
var tree,
|
120
144
|
series = this,
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
});
|
128
|
-
};
|
129
|
-
// Actions
|
130
|
-
this.nodeMap = [];
|
131
|
-
|
132
|
-
// Map children to index
|
133
|
-
// @todo Use data instead of points
|
134
|
-
each(this.points, function (point, index) {
|
135
|
-
var parent = "";
|
136
|
-
allIds.push(point.id);
|
137
|
-
if (point.parent !== undefined) {
|
138
|
-
parent = point.parent;
|
139
|
-
}
|
140
|
-
if (parentList[parent] === undefined) {
|
141
|
-
parentList[parent] = [];
|
142
|
-
}
|
143
|
-
parentList[parent].push(index);
|
144
|
-
});
|
145
|
-
/*
|
146
|
-
* Quality check:
|
147
|
-
* - If parent does not exist, then set parent to tree root
|
148
|
-
* - Add node id to parents children list
|
149
|
-
*/
|
150
|
-
for (key in parentList) {
|
151
|
-
if ((parentList.hasOwnProperty(key)) && (key !== "") && (HighchartsAdapter.inArray(key, allIds) === -1)) {
|
152
|
-
insertItem(key);
|
153
|
-
delete parentList[key];
|
154
|
-
}
|
155
|
-
}
|
145
|
+
allIds = map(this.data, function (d) {
|
146
|
+
return d.id;
|
147
|
+
}),
|
148
|
+
parentList = series.getListOfParents(this.data, allIds);
|
149
|
+
|
150
|
+
series.nodeMap = [];
|
156
151
|
tree = series.buildNode("", -1, 0, parentList, null);
|
157
|
-
|
152
|
+
recursive(this.nodeMap[this.rootNode], function (node) {
|
153
|
+
var next = false,
|
154
|
+
p = node.parent;
|
158
155
|
node.visible = true;
|
156
|
+
if (p || p === "") {
|
157
|
+
next = series.nodeMap[p];
|
158
|
+
}
|
159
|
+
return next;
|
159
160
|
});
|
160
|
-
|
161
|
-
|
161
|
+
recursive(this.nodeMap[this.rootNode].children, function (children) {
|
162
|
+
var next = false;
|
163
|
+
each(children, function (child) {
|
164
|
+
child.visible = true;
|
165
|
+
if (child.children.length) {
|
166
|
+
next = (next || []).concat(child.children);
|
167
|
+
}
|
168
|
+
});
|
169
|
+
return next;
|
162
170
|
});
|
163
171
|
this.setTreeValues(tree);
|
164
172
|
return tree;
|
165
173
|
},
|
174
|
+
init: function (chart, options) {
|
175
|
+
var series = this;
|
176
|
+
Series.prototype.init.call(series, chart, options);
|
177
|
+
if (series.options.allowDrillToNode) {
|
178
|
+
series.drillTo();
|
179
|
+
}
|
180
|
+
},
|
166
181
|
buildNode: function (id, i, level, list, parent) {
|
167
182
|
var series = this,
|
168
183
|
children = [],
|
@@ -191,6 +206,7 @@
|
|
191
206
|
},
|
192
207
|
setTreeValues: function (tree) {
|
193
208
|
var series = this,
|
209
|
+
options = series.options,
|
194
210
|
childrenTotal = 0,
|
195
211
|
sorted = [],
|
196
212
|
val,
|
@@ -207,12 +223,19 @@
|
|
207
223
|
childrenTotal += child.val;
|
208
224
|
} else {
|
209
225
|
// @todo Add predicate to avoid looping already ignored children
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
226
|
+
recursive(child.children, function (children) {
|
227
|
+
var next = false;
|
228
|
+
each(children, function (node) {
|
229
|
+
extend(node, {
|
230
|
+
ignore: true,
|
231
|
+
isLeaf: false,
|
232
|
+
visible: false
|
233
|
+
});
|
234
|
+
if (node.children.length) {
|
235
|
+
next = (next || []).concat(node.children);
|
236
|
+
}
|
215
237
|
});
|
238
|
+
return next;
|
216
239
|
});
|
217
240
|
}
|
218
241
|
});
|
@@ -225,28 +248,12 @@
|
|
225
248
|
// Ignore this node if point is not visible
|
226
249
|
ignore: !(pick(point && point.visible, true) && (val > 0)),
|
227
250
|
isLeaf: tree.visible && !childrenTotal,
|
251
|
+
levelDynamic: (options.levelIsConstant ? tree.level : (tree.level - series.nodeMap[series.rootNode].level)),
|
228
252
|
name: pick(point && point.name, ""),
|
229
253
|
val: val
|
230
254
|
});
|
231
255
|
return tree;
|
232
256
|
},
|
233
|
-
eachChildren: function (node, callback) {
|
234
|
-
var series = this,
|
235
|
-
children = node.children;
|
236
|
-
callback(node);
|
237
|
-
if (children.length) {
|
238
|
-
each(children, function (child) {
|
239
|
-
series.eachChildren(child, callback);
|
240
|
-
});
|
241
|
-
}
|
242
|
-
},
|
243
|
-
eachParents: function (node, callback) {
|
244
|
-
var parent = this.nodeMap[node.parent];
|
245
|
-
callback(node);
|
246
|
-
if (parent) {
|
247
|
-
this.eachParents(parent, callback);
|
248
|
-
}
|
249
|
-
},
|
250
257
|
/**
|
251
258
|
* Recursive function which calculates the area for all children of a node.
|
252
259
|
* @param {Object} node The node which is parent to the children.
|
@@ -255,13 +262,11 @@
|
|
255
262
|
calculateChildrenAreas: function (parent, area) {
|
256
263
|
var series = this,
|
257
264
|
options = series.options,
|
258
|
-
|
259
|
-
level = this.levelMap[levelNumber + 1],
|
265
|
+
level = this.levelMap[parent.levelDynamic + 1],
|
260
266
|
algorithm = pick((series[level && level.layoutAlgorithm] && level.layoutAlgorithm), options.layoutAlgorithm),
|
261
267
|
alternate = options.alternateStartingDirection,
|
262
268
|
childrenValues = [],
|
263
|
-
children
|
264
|
-
point;
|
269
|
+
children;
|
265
270
|
|
266
271
|
// Collect all children which should be included
|
267
272
|
children = grep(parent.children, function (n) {
|
@@ -273,12 +278,15 @@
|
|
273
278
|
}
|
274
279
|
childrenValues = series[algorithm](area, children);
|
275
280
|
each(children, function (child, index) {
|
276
|
-
|
277
|
-
|
278
|
-
child.values = merge(childrenValues[index], {
|
281
|
+
var values = childrenValues[index];
|
282
|
+
child.values = merge(values, {
|
279
283
|
val: child.childrenTotal,
|
280
284
|
direction: (alternate ? 1 - area.direction : area.direction)
|
281
285
|
});
|
286
|
+
child.pointValues = merge(values, {
|
287
|
+
x: (values.x / series.axisRatio),
|
288
|
+
width: (values.width / series.axisRatio)
|
289
|
+
});
|
282
290
|
// If node has children, then call method recursively
|
283
291
|
if (child.children.length) {
|
284
292
|
series.calculateChildrenAreas(child, child.values);
|
@@ -289,23 +297,15 @@
|
|
289
297
|
var series = this,
|
290
298
|
xAxis = series.xAxis,
|
291
299
|
yAxis = series.yAxis;
|
292
|
-
series.nodeMap[""].values = {
|
293
|
-
x: 0,
|
294
|
-
y: 0,
|
295
|
-
width: 100,
|
296
|
-
height: 100
|
297
|
-
};
|
298
300
|
each(series.points, function (point) {
|
299
301
|
var node = point.node,
|
300
|
-
values = node.
|
302
|
+
values = node.pointValues,
|
301
303
|
x1,
|
302
304
|
x2,
|
303
305
|
y1,
|
304
306
|
y2;
|
305
307
|
// Points which is ignored, have no values.
|
306
308
|
if (values) {
|
307
|
-
values.x = values.x / series.axisRatio;
|
308
|
-
values.width = values.width / series.axisRatio;
|
309
309
|
x1 = Math.round(xAxis.translate(values.x, 0, 0, 0, 1));
|
310
310
|
x2 = Math.round(xAxis.translate(values.x + values.width, 0, 0, 0, 1));
|
311
311
|
y1 = Math.round(yAxis.translate(values.y, 0, 0, 0, 1));
|
@@ -327,43 +327,13 @@
|
|
327
327
|
}
|
328
328
|
});
|
329
329
|
},
|
330
|
-
getSeriesArea: function (val) {
|
331
|
-
var x = 0,
|
332
|
-
y = 0,
|
333
|
-
h = 100,
|
334
|
-
r = this.axisRatio = (this.xAxis.len / this.yAxis.len),
|
335
|
-
w = 100 * r,
|
336
|
-
d = this.options.layoutStartingDirection === 'vertical' ? 0 : 1,
|
337
|
-
seriesArea = {
|
338
|
-
x: x,
|
339
|
-
y: y,
|
340
|
-
width: w,
|
341
|
-
height: h,
|
342
|
-
direction: d,
|
343
|
-
val: val
|
344
|
-
};
|
345
|
-
this.nodeMap[""].values = seriesArea;
|
346
|
-
return seriesArea;
|
347
|
-
},
|
348
|
-
getLevels: function () {
|
349
|
-
var map = [],
|
350
|
-
levels = this.options.levels;
|
351
|
-
if (levels) {
|
352
|
-
each(levels, function (level) {
|
353
|
-
if (level.level !== undefined) {
|
354
|
-
map[level.level] = level;
|
355
|
-
}
|
356
|
-
});
|
357
|
-
}
|
358
|
-
return map;
|
359
|
-
},
|
360
330
|
setColorRecursive: function (node, color) {
|
361
331
|
var series = this,
|
362
332
|
point,
|
363
333
|
level;
|
364
334
|
if (node) {
|
365
335
|
point = series.points[node.i];
|
366
|
-
level = series.levelMap[node.
|
336
|
+
level = series.levelMap[node.levelDynamic];
|
367
337
|
// Select either point color, level color or inherited color.
|
368
338
|
color = pick(point && point.options.color, level && level.color, color);
|
369
339
|
if (point) {
|
@@ -573,16 +543,51 @@
|
|
573
543
|
return this.alg_func_fill(false, parent, children);
|
574
544
|
},
|
575
545
|
translate: function () {
|
546
|
+
var pointValues,
|
547
|
+
seriesArea,
|
548
|
+
tree,
|
549
|
+
val;
|
550
|
+
|
576
551
|
// Call prototype function
|
577
552
|
Series.prototype.translate.call(this);
|
578
|
-
this.handleLayout();
|
579
553
|
|
580
|
-
|
554
|
+
if (this.points.length) {
|
555
|
+
// Assign variables
|
556
|
+
this.rootNode = pick(this.options.rootId, "");
|
557
|
+
// Create a object map from level to options
|
558
|
+
this.levelMap = reduce(this.options.levels, function (arr, item) {
|
559
|
+
arr[item.level] = item;
|
560
|
+
return arr;
|
561
|
+
}, {});
|
562
|
+
tree = this.tree = this.getTree(); // @todo Only if series.isDirtyData is true
|
563
|
+
|
564
|
+
// Calculate plotting values.
|
565
|
+
this.axisRatio = (this.xAxis.len / this.yAxis.len);
|
566
|
+
this.nodeMap[""].pointValues = pointValues = {x: 0, y: 0, width: 100, height: 100 };
|
567
|
+
this.nodeMap[""].values = seriesArea = merge(pointValues, {
|
568
|
+
width: (pointValues.width * this.axisRatio),
|
569
|
+
direction: (this.options.layoutStartingDirection === 'vertical' ? 0 : 1),
|
570
|
+
val: tree.val
|
571
|
+
});
|
572
|
+
this.calculateChildrenAreas(tree, seriesArea);
|
573
|
+
}
|
574
|
+
|
575
|
+
// Logic for point colors
|
581
576
|
if (this.colorAxis) {
|
582
577
|
this.translateColors();
|
583
578
|
} else if (!this.options.colorByPoint) {
|
584
579
|
this.setColorRecursive(this.tree, undefined);
|
585
580
|
}
|
581
|
+
|
582
|
+
// Update axis extremes according to the root node.
|
583
|
+
val = this.nodeMap[this.rootNode].pointValues;
|
584
|
+
this.xAxis.setExtremes(val.x, val.x + val.width, false);
|
585
|
+
this.yAxis.setExtremes(val.y, val.y + val.height, false);
|
586
|
+
this.xAxis.setScale();
|
587
|
+
this.yAxis.setScale();
|
588
|
+
|
589
|
+
// Assign values to points.
|
590
|
+
this.setPointValues();
|
586
591
|
},
|
587
592
|
/**
|
588
593
|
* Extend drawDataLabels with logic to handle custom options related to the treemap series:
|
@@ -592,12 +597,13 @@
|
|
592
597
|
*/
|
593
598
|
drawDataLabels: function () {
|
594
599
|
var series = this,
|
595
|
-
|
596
|
-
|
600
|
+
points = grep(series.points, function (n) {
|
601
|
+
return n.node.visible;
|
602
|
+
}),
|
597
603
|
options,
|
598
604
|
level;
|
599
605
|
each(points, function (point) {
|
600
|
-
level = series.levelMap[point.
|
606
|
+
level = series.levelMap[point.node.levelDynamic];
|
601
607
|
// Set options to new object to avoid problems with scope
|
602
608
|
options = {style: {}};
|
603
609
|
|
@@ -620,82 +626,88 @@
|
|
620
626
|
// Merge custom options with point options
|
621
627
|
point.dlOptions = merge(options, point.options.dataLabels);
|
622
628
|
});
|
623
|
-
|
624
|
-
this.dataLabelsGroup = this.group; // Draw dataLabels in same group as points, because of z-index on hover
|
625
629
|
Series.prototype.drawDataLabels.call(this);
|
626
|
-
this.dataLabelsGroup = dataLabelsGroup;
|
627
630
|
},
|
628
631
|
alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
|
632
|
+
|
633
|
+
/**
|
634
|
+
* Get presentational attributes
|
635
|
+
*/
|
636
|
+
pointAttribs: function (point, state) {
|
637
|
+
var level = this.levelMap[point.node.levelDynamic] || {},
|
638
|
+
options = this.options,
|
639
|
+
attr,
|
640
|
+
stateOptions = (state && options.states[state]) || {};
|
641
|
+
|
642
|
+
// Set attributes by precedence. Point trumps level trumps series. Stroke width uses pick
|
643
|
+
// because it can be 0.
|
644
|
+
attr = {
|
645
|
+
'stroke': point.borderColor || level.borderColor || stateOptions.borderColor || options.borderColor,
|
646
|
+
'stroke-width': pick(point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth),
|
647
|
+
'dashstyle': point.borderDashStyle || level.borderDashStyle || stateOptions.borderDashStyle || options.borderDashStyle,
|
648
|
+
'fill': point.color || this.color
|
649
|
+
};
|
650
|
+
|
651
|
+
if (state === 'hover') {
|
652
|
+
attr.zIndex = 1;
|
653
|
+
}
|
654
|
+
|
655
|
+
if (point.node.level <= this.nodeMap[this.rootNode].level) {
|
656
|
+
// Hide levels above the current view
|
657
|
+
attr.fill = 'none';
|
658
|
+
attr["stroke-width"] = 0;
|
659
|
+
} else if (!point.node.isLeaf) {
|
660
|
+
// If not a leaf, then remove fill
|
661
|
+
// @todo let users set the opacity
|
662
|
+
attr.fill = pick(options.interactByLeaf, !options.allowDrillToNode) ? 'none' : Color(attr.fill).setOpacity(state === 'hover' ? 0.75 : 0.15).get();
|
663
|
+
} else if (state) {
|
664
|
+
// Brighten and hoist the hover nodes
|
665
|
+
attr.fill = Color(attr.fill).brighten(stateOptions.brightness).get();
|
666
|
+
}
|
667
|
+
|
668
|
+
return attr;
|
669
|
+
},
|
670
|
+
|
629
671
|
/**
|
630
672
|
* Extending ColumnSeries drawPoints
|
631
673
|
*/
|
632
674
|
drawPoints: function () {
|
633
675
|
var series = this,
|
634
|
-
points = series.points,
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
level;
|
676
|
+
points = grep(series.points, function (n) {
|
677
|
+
return n.node.visible;
|
678
|
+
});
|
679
|
+
|
639
680
|
each(points, function (point) {
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
};
|
648
|
-
// Overwrite standard series options with level options
|
649
|
-
if (level) {
|
650
|
-
attr.stroke = level.borderColor || attr.stroke;
|
651
|
-
attr['stroke-width'] = level.borderWidth || attr['stroke-width'];
|
652
|
-
attr.dashstyle = level.borderDashStyle || attr.dashstyle;
|
653
|
-
}
|
654
|
-
// Merge with point attributes
|
655
|
-
attr.stroke = point.borderColor || attr.stroke;
|
656
|
-
attr['stroke-width'] = point.borderWidth || attr['stroke-width'];
|
657
|
-
attr.dashstyle = point.borderDashStyle || attr.dashstyle;
|
658
|
-
attr.zIndex = (1000 - (point.level * 2));
|
659
|
-
|
660
|
-
// Make a copy to prevent overwriting individual props
|
661
|
-
point.pointAttr = merge(point.pointAttr);
|
662
|
-
hover = point.pointAttr.hover;
|
663
|
-
hover.zIndex = 1001;
|
664
|
-
hover.fill = Color(attr.fill).brighten(seriesOptions.states.hover.brightness).get();
|
665
|
-
// If not a leaf, then remove fill
|
666
|
-
if (!point.node.isLeaf) {
|
667
|
-
if (pick(seriesOptions.interactByLeaf, !seriesOptions.allowDrillToNode)) {
|
668
|
-
attr.fill = 'none';
|
669
|
-
delete hover.fill;
|
670
|
-
} else {
|
671
|
-
// TODO: let users set the opacity
|
672
|
-
attr.fill = Color(attr.fill).setOpacity(0.15).get();
|
673
|
-
hover.fill = Color(hover.fill).setOpacity(0.75).get();
|
674
|
-
}
|
675
|
-
}
|
676
|
-
if (point.node.level <= series.nodeMap[series.rootNode].level) {
|
677
|
-
attr.fill = 'none';
|
678
|
-
attr.zIndex = 0;
|
679
|
-
delete hover.fill;
|
680
|
-
}
|
681
|
-
point.pointAttr[''] = H.extend(point.pointAttr[''], attr);
|
682
|
-
// @todo Move this to drawDataLabels
|
683
|
-
if (point.dataLabel) {
|
684
|
-
point.dataLabel.attr({ zIndex: (point.pointAttr[''].zIndex + 1) });
|
681
|
+
var groupKey = "levelGroup-" + point.node.levelDynamic;
|
682
|
+
if (!series[groupKey]) {
|
683
|
+
series[groupKey] = series.chart.renderer.g(groupKey)
|
684
|
+
.attr({
|
685
|
+
zIndex: 1000 - point.node.levelDynamic // @todo Set the zIndex based upon the number of levels, instead of using 1000
|
686
|
+
})
|
687
|
+
.add(series.group);
|
685
688
|
}
|
689
|
+
point.group = series[groupKey];
|
690
|
+
// Preliminary code in prepraration for HC5 that uses pointAttribs for all series
|
691
|
+
point.pointAttr = {
|
692
|
+
'': series.pointAttribs(point),
|
693
|
+
'hover': series.pointAttribs(point, 'hover'),
|
694
|
+
'select': {}
|
695
|
+
};
|
686
696
|
});
|
687
697
|
// Call standard drawPoints
|
688
698
|
seriesTypes.column.prototype.drawPoints.call(this);
|
689
699
|
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
700
|
+
// If drillToNode is allowed, set a point cursor on clickables & add drillId to point
|
701
|
+
if (series.options.allowDrillToNode) {
|
702
|
+
each(points, function (point) {
|
703
|
+
var cursor,
|
704
|
+
drillId;
|
705
|
+
if (point.graphic) {
|
706
|
+
drillId = point.drillId = series.options.interactByLeaf ? series.drillToByLeaf(point) : series.drillToByGroup(point);
|
707
|
+
cursor = drillId ? "pointer" : "default";
|
708
|
+
point.graphic.css({ cursor: cursor });
|
709
|
+
}
|
710
|
+
});
|
699
711
|
}
|
700
712
|
},
|
701
713
|
/**
|
@@ -725,34 +737,17 @@
|
|
725
737
|
* Add drilling on the suitable points
|
726
738
|
*/
|
727
739
|
drillTo: function () {
|
728
|
-
var series = this
|
729
|
-
|
730
|
-
|
731
|
-
|
740
|
+
var series = this;
|
741
|
+
H.addEvent(series, 'click', function (event) {
|
742
|
+
var point = event.point,
|
743
|
+
drillId = point.drillId,
|
732
744
|
drillName;
|
733
|
-
H.removeEvent(point, 'click.drillTo');
|
734
|
-
if (point.graphic) {
|
735
|
-
point.graphic.css({ cursor: 'default' });
|
736
|
-
}
|
737
|
-
|
738
|
-
// Get the drill to id
|
739
|
-
if (series.options.interactByLeaf) {
|
740
|
-
drillId = series.drillToByLeaf(point);
|
741
|
-
} else {
|
742
|
-
drillId = series.drillToByGroup(point);
|
743
|
-
}
|
744
|
-
|
745
745
|
// If a drill id is returned, add click event and cursor.
|
746
746
|
if (drillId) {
|
747
747
|
drillName = series.nodeMap[series.rootNode].name || series.rootNode;
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
H.addEvent(point, 'click.drillTo', function () {
|
752
|
-
point.setState(''); // Remove hover
|
753
|
-
series.drillToNode(drillId);
|
754
|
-
series.showDrillUpButton(drillName);
|
755
|
-
});
|
748
|
+
point.setState(''); // Remove hover
|
749
|
+
series.drillToNode(drillId);
|
750
|
+
series.showDrillUpButton(drillName);
|
756
751
|
}
|
757
752
|
});
|
758
753
|
},
|
@@ -815,11 +810,7 @@
|
|
815
810
|
}
|
816
811
|
},
|
817
812
|
drillToNode: function (id) {
|
818
|
-
|
819
|
-
val = node.values;
|
820
|
-
this.rootNode = id;
|
821
|
-
this.xAxis.setExtremes(val.x, val.x + val.width, false);
|
822
|
-
this.yAxis.setExtremes(val.y, val.y + val.height, false);
|
813
|
+
this.options.rootId = id;
|
823
814
|
this.isDirty = true; // Force redraw
|
824
815
|
this.chart.redraw();
|
825
816
|
},
|