corrade-nucleus-nucleons – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
20 office 1 /**
2 * @license Highcharts JS v5.0.12 (2017-05-24)
3 *
4 * (c) 2014 Highsoft AS
5 * Authors: Jon Arild Nygard / Oystein Moseng
6 *
7 * License: www.highcharts.com/license
8 */
9 'use strict';
10 (function(factory) {
11 if (typeof module === 'object' && module.exports) {
12 module.exports = factory;
13 } else {
14 factory(Highcharts);
15 }
16 }(function(Highcharts) {
17 (function(H) {
18 /**
19 * (c) 2014 Highsoft AS
20 * Authors: Jon Arild Nygard / Oystein Moseng
21 *
22 * License: www.highcharts.com/license
23 */
24  
25 var seriesType = H.seriesType,
26 seriesTypes = H.seriesTypes,
27 map = H.map,
28 merge = H.merge,
29 extend = H.extend,
30 noop = H.noop,
31 each = H.each,
32 grep = H.grep,
33 isNumber = H.isNumber,
34 isString = H.isString,
35 pick = H.pick,
36 Series = H.Series,
37 stableSort = H.stableSort,
38 color = H.Color,
39 eachObject = function(list, func, context) {
40 context = context || this;
41 H.objectEach(list, function(val, key) {
42 func.call(context, val, key, list);
43 });
44 },
45 reduce = function(arr, func, previous, context) {
46 context = context || this;
47 arr = arr || []; // @note should each be able to handle empty values automatically?
48 each(arr, function(current, i) {
49 previous = func.call(context, previous, current, i, arr);
50 });
51 return previous;
52 },
53 // @todo find correct name for this function.
54 // @todo Similar to reduce, this function is likely redundant
55 recursive = function(item, func, context) {
56 var next;
57 context = context || this;
58 next = func.call(context, item);
59 if (next !== false) {
60 recursive(next, func, context);
61 }
62 };
63  
64 // The Treemap series type
65 seriesType('treemap', 'scatter', {
66 showInLegend: false,
67 marker: false,
68 dataLabels: {
69 enabled: true,
70 defer: false,
71 verticalAlign: 'middle',
72 formatter: function() { // #2945
73 return this.point.name || this.point.id;
74 },
75 inside: true
76 },
77 tooltip: {
78 headerFormat: '',
79 pointFormat: '<b>{point.name}</b>: {point.value}</b><br/>'
80 },
81 ignoreHiddenPoint: true,
82 layoutAlgorithm: 'sliceAndDice',
83 layoutStartingDirection: 'vertical',
84 alternateStartingDirection: false,
85 levelIsConstant: true,
86 drillUpButton: {
87 position: {
88 align: 'right',
89 x: -10,
90 y: 10
91 }
92 },
93  
94 // Presentational options
95 borderColor: '#e6e6e6',
96 borderWidth: 1,
97 opacity: 0.15,
98 states: {
99 hover: {
100 borderColor: '#999999',
101 brightness: seriesTypes.heatmap ? 0 : 0.1,
102 opacity: 0.75,
103 shadow: false
104 }
105 }
106  
107  
108 // Prototype members
109 }, {
110 pointArrayMap: ['value'],
111 axisTypes: seriesTypes.heatmap ? ['xAxis', 'yAxis', 'colorAxis'] : ['xAxis', 'yAxis'],
112 optionalAxis: 'colorAxis',
113 getSymbol: noop,
114 parallelArrays: ['x', 'y', 'value', 'colorValue'],
115 colorKey: 'colorValue', // Point color option key
116 translateColors: seriesTypes.heatmap && seriesTypes.heatmap.prototype.translateColors,
117 trackerGroups: ['group', 'dataLabelsGroup'],
118 /**
119 * Creates an object map from parent id to childrens index.
120 * @param {Array} data List of points set in options.
121 * @param {string} data[].parent Parent id of point.
122 * @param {Array} ids List of all point ids.
123 * @return {Object} Map from parent id to children index in data.
124 */
125 getListOfParents: function(data, ids) {
126 var listOfParents = reduce(data, function(prev, curr, i) {
127 var parent = pick(curr.parent, '');
128 if (prev[parent] === undefined) {
129 prev[parent] = [];
130 }
131 prev[parent].push(i);
132 return prev;
133 }, {});
134  
135 // If parent does not exist, hoist parent to root of tree.
136 eachObject(listOfParents, function(children, parent, list) {
137 if ((parent !== '') && (H.inArray(parent, ids) === -1)) {
138 each(children, function(child) {
139 list[''].push(child);
140 });
141 delete list[parent];
142 }
143 });
144 return listOfParents;
145 },
146 /**
147 * Creates a tree structured object from the series points
148 */
149 getTree: function() {
150 var series = this,
151 allIds = map(this.data, function(d) {
152 return d.id;
153 }),
154 parentList = series.getListOfParents(this.data, allIds);
155  
156 series.nodeMap = [];
157 return series.buildNode('', -1, 0, parentList, null);
158 },
159 init: function(chart, options) {
160 var series = this;
161 Series.prototype.init.call(series, chart, options);
162 if (series.options.allowDrillToNode) {
163 H.addEvent(series, 'click', series.onClickDrillToNode);
164 }
165 },
166 buildNode: function(id, i, level, list, parent) {
167 var series = this,
168 children = [],
169 point = series.points[i],
170 node,
171 child;
172  
173 // Actions
174 each((list[id] || []), function(i) {
175 child = series.buildNode(series.points[i].id, i, (level + 1), list, id);
176 children.push(child);
177 });
178 node = {
179 id: id,
180 i: i,
181 children: children,
182 level: level,
183 parent: parent,
184 visible: false // @todo move this to better location
185 };
186 series.nodeMap[node.id] = node;
187 if (point) {
188 point.node = node;
189 }
190 return node;
191 },
192 setTreeValues: function(tree) {
193 var series = this,
194 options = series.options,
195 childrenTotal = 0,
196 children = [],
197 val,
198 point = series.points[tree.i];
199 // Parents of the root node is by default visible
200 recursive(series.nodeMap[series.rootNode], function(node) {
201 var next = false,
202 p = node.parent;
203 node.visible = true;
204 if (p || p === '') {
205 next = series.nodeMap[p];
206 }
207 return next;
208 });
209 // Children of the root node is by default visible
210 recursive(series.nodeMap[series.rootNode].children, function(children) {
211 var next = false;
212 each(children, function(child) {
213 child.visible = true;
214 if (child.children.length) {
215 next = (next || []).concat(child.children);
216 }
217 });
218 return next;
219 });
220  
221 // First give the children some values
222 each(tree.children, function(child) {
223 child = series.setTreeValues(child);
224 children.push(child);
225  
226 if (!child.ignore) {
227 childrenTotal += child.val;
228 } else {
229 // @todo Add predicate to avoid looping already ignored children
230 recursive(child.children, function(children) {
231 var next = false;
232 each(children, function(node) {
233 extend(node, {
234 ignore: true,
235 isLeaf: false,
236 visible: false
237 });
238 if (node.children.length) {
239 next = (next || []).concat(node.children);
240 }
241 });
242 return next;
243 });
244 }
245 });
246 // Sort the children
247 stableSort(children, function(a, b) {
248 return a.sortIndex - b.sortIndex;
249 });
250 // Set the values
251 val = pick(point && point.options.value, childrenTotal);
252 if (point) {
253 point.value = val;
254 }
255 extend(tree, {
256 children: children,
257 childrenTotal: childrenTotal,
258 // Ignore this node if point is not visible
259 ignore: !(pick(point && point.visible, true) && (val > 0)),
260 isLeaf: tree.visible && !childrenTotal,
261 levelDynamic: (options.levelIsConstant ? tree.level : (tree.level - series.nodeMap[series.rootNode].level)),
262 name: pick(point && point.name, ''),
263 sortIndex: pick(point && point.sortIndex, -val),
264 val: val
265 });
266 return tree;
267 },
268 /**
269 * Recursive function which calculates the area for all children of a node.
270 * @param {Object} node The node which is parent to the children.
271 * @param {Object} area The rectangular area of the parent.
272 */
273 calculateChildrenAreas: function(parent, area) {
274 var series = this,
275 options = series.options,
276 level = this.levelMap[parent.levelDynamic + 1],
277 algorithm = pick((series[level && level.layoutAlgorithm] && level.layoutAlgorithm), options.layoutAlgorithm),
278 alternate = options.alternateStartingDirection,
279 childrenValues = [],
280 children;
281  
282 // Collect all children which should be included
283 children = grep(parent.children, function(n) {
284 return !n.ignore;
285 });
286  
287 if (level && level.layoutStartingDirection) {
288 area.direction = level.layoutStartingDirection === 'vertical' ? 0 : 1;
289 }
290 childrenValues = series[algorithm](area, children);
291 each(children, function(child, index) {
292 var values = childrenValues[index];
293 child.values = merge(values, {
294 val: child.childrenTotal,
295 direction: (alternate ? 1 - area.direction : area.direction)
296 });
297 child.pointValues = merge(values, {
298 x: (values.x / series.axisRatio),
299 width: (values.width / series.axisRatio)
300 });
301 // If node has children, then call method recursively
302 if (child.children.length) {
303 series.calculateChildrenAreas(child, child.values);
304 }
305 });
306 },
307 setPointValues: function() {
308 var series = this,
309 xAxis = series.xAxis,
310 yAxis = series.yAxis;
311 each(series.points, function(point) {
312 var node = point.node,
313 values = node.pointValues,
314 x1,
315 x2,
316 y1,
317 y2,
318 crispCorr = 0;
319  
320  
321 // Get the crisp correction in classic mode. For this to work in
322 // styled mode, we would need to first add the shape (without x, y,
323 // width and height), then read the rendered stroke width using
324 // point.graphic.strokeWidth(), then modify and apply the shapeArgs.
325 // This applies also to column series, but the downside is
326 // performance and code complexity.
327 crispCorr = (
328 (series.pointAttribs(point)['stroke-width'] || 0) % 2
329 ) / 2;
330  
331  
332 // Points which is ignored, have no values.
333 if (values && node.visible) {
334 x1 = Math.round(xAxis.translate(values.x, 0, 0, 0, 1)) - crispCorr;
335 x2 = Math.round(xAxis.translate(values.x + values.width, 0, 0, 0, 1)) - crispCorr;
336 y1 = Math.round(yAxis.translate(values.y, 0, 0, 0, 1)) - crispCorr;
337 y2 = Math.round(yAxis.translate(values.y + values.height, 0, 0, 0, 1)) - crispCorr;
338 // Set point values
339 point.shapeType = 'rect';
340 point.shapeArgs = {
341 x: Math.min(x1, x2),
342 y: Math.min(y1, y2),
343 width: Math.abs(x2 - x1),
344 height: Math.abs(y2 - y1)
345 };
346 point.plotX = point.shapeArgs.x + (point.shapeArgs.width / 2);
347 point.plotY = point.shapeArgs.y + (point.shapeArgs.height / 2);
348 } else {
349 // Reset visibility
350 delete point.plotX;
351 delete point.plotY;
352 }
353 });
354 },
355 setColorRecursive: function(node, color, colorIndex) {
356 var series = this,
357 point,
358 level;
359 if (node) {
360 point = series.points[node.i];
361 level = series.levelMap[node.levelDynamic];
362 // Select either point color, level color or inherited color.
363 color = pick(
364 point && point.options.color,
365 level && level.color,
366 color,
367 series.color
368 );
369 colorIndex = pick(
370 point && point.options.colorIndex,
371 level && level.colorIndex,
372 colorIndex,
373 series.colorIndex
374 );
375  
376 if (point) {
377 point.color = color;
378 point.colorIndex = colorIndex;
379 }
380  
381 // Do it all again with the children
382 if (node.children.length) {
383 each(node.children, function(child) {
384 series.setColorRecursive(child, color, colorIndex);
385 });
386 }
387 }
388 },
389 algorithmGroup: function(h, w, d, p) {
390 this.height = h;
391 this.width = w;
392 this.plot = p;
393 this.direction = d;
394 this.startDirection = d;
395 this.total = 0;
396 this.nW = 0;
397 this.lW = 0;
398 this.nH = 0;
399 this.lH = 0;
400 this.elArr = [];
401 this.lP = {
402 total: 0,
403 lH: 0,
404 nH: 0,
405 lW: 0,
406 nW: 0,
407 nR: 0,
408 lR: 0,
409 aspectRatio: function(w, h) {
410 return Math.max((w / h), (h / w));
411 }
412 };
413 this.addElement = function(el) {
414 this.lP.total = this.elArr[this.elArr.length - 1];
415 this.total = this.total + el;
416 if (this.direction === 0) {
417 // Calculate last point old aspect ratio
418 this.lW = this.nW;
419 this.lP.lH = this.lP.total / this.lW;
420 this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH);
421 // Calculate last point new aspect ratio
422 this.nW = this.total / this.height;
423 this.lP.nH = this.lP.total / this.nW;
424 this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH);
425 } else {
426 // Calculate last point old aspect ratio
427 this.lH = this.nH;
428 this.lP.lW = this.lP.total / this.lH;
429 this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH);
430 // Calculate last point new aspect ratio
431 this.nH = this.total / this.width;
432 this.lP.nW = this.lP.total / this.nH;
433 this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH);
434 }
435 this.elArr.push(el);
436 };
437 this.reset = function() {
438 this.nW = 0;
439 this.lW = 0;
440 this.elArr = [];
441 this.total = 0;
442 };
443 },
444 algorithmCalcPoints: function(directionChange, last, group, childrenArea) {
445 var pX,
446 pY,
447 pW,
448 pH,
449 gW = group.lW,
450 gH = group.lH,
451 plot = group.plot,
452 keep,
453 i = 0,
454 end = group.elArr.length - 1;
455 if (last) {
456 gW = group.nW;
457 gH = group.nH;
458 } else {
459 keep = group.elArr[group.elArr.length - 1];
460 }
461 each(group.elArr, function(p) {
462 if (last || (i < end)) {
463 < end)) { if (group.direction === 0) {
464 < end)) { pX = plot.x;
465 < end)) { pY = plot.y;
466 < end)) { pW = gW;
467 < end)) { pH = p / pW;
468 < end)) { } else {
469 < end)) { pX = plot.x;
470 < end)) { pY = plot.y;
471 < end)) { pH = gH;
472 < end)) { pW = p / pH;
473 < end)) { }
474 < end)) { childrenArea.push({
475 < end)) { x: pX,
476 < end)) { y: pY,
477 < end)) { width: pW,
478 < end)) { height: pH
479 < end)) { });
480 < end)) { if (group.direction === 0) {
481 < end)) { plot.y = plot.y + pH;
482 < end)) { } else {
483 < end)) { plot.x = plot.x + pW;
484 < end)) { }
485 < end)) { }
486 < end)) { i = i + 1;
487 < end)) { });
488 < end)) { // Reset variables
489 < end)) { group.reset();
490 < end)) { if (group.direction === 0) {
491 < end)) { group.width = group.width - gW;
492 < end)) { } else {
493 < end)) { group.height = group.height - gH;
494 < end)) { }
495 < end)) { plot.y = plot.parent.y + (plot.parent.height - group.height);
496 < end)) { plot.x = plot.parent.x + (plot.parent.width - group.width);
497 < end)) { if (directionChange) {
498 < end)) { group.direction = 1 - group.direction;
499 < end)) { }
500 < end)) { // If not last, then add uncalculated element
501 < end)) { if (!last) {
502 < end)) { group.addElement(keep);
503 < end)) { }
504 < end)) { },
505 < end)) { algorithmLowAspectRatio: function(directionChange, parent, children) {
506 < end)) { var childrenArea = [],
507 < end)) { series = this,
508 < end)) { pTot,
509 < end)) { plot = {
510 < end)) { x: parent.x,
511 < end)) { y: parent.y,
512 < end)) { parent: parent
513 < end)) { },
514 < end)) { direction = parent.direction,
515 < end)) { i = 0,
516 < end)) { end = children.length - 1,
517 < end)) { group = new this.algorithmGroup(parent.height, parent.width, direction, plot); // eslint-disable-line new-cap
518 < end)) { // Loop through and calculate all areas
519 < end)) { each(children, function(child) {
520 < end)) { pTot = (parent.width * parent.height) * (child.val / parent.val);
521 < end)) { group.addElement(pTot);
522 < end)) { if (group.lP.nR > group.lP.lR) {
523 < end)) { series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot);
524 < end)) { }
525 < end)) { // If last child, then calculate all remaining areas
526 < end)) { if (i === end) {
527 < end)) { series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot);
528 < end)) { }
529 < end)) { i = i + 1;
530 < end)) { });
531 < end)) { return childrenArea;
532 < end)) { },
533 < end)) { algorithmFill: function(directionChange, parent, children) {
534 < end)) { var childrenArea = [],
535 < end)) { pTot,
536 < end)) { direction = parent.direction,
537 < end)) { x = parent.x,
538 < end)) { y = parent.y,
539 < end)) { width = parent.width,
540 < end)) { height = parent.height,
541 < end)) { pX,
542 < end)) { pY,
543 < end)) { pW,
544 < end)) { pH;
545 < end)) { each(children, function(child) {
546 < end)) { pTot = (parent.width * parent.height) * (child.val / parent.val);
547 < end)) { pX = x;
548 < end)) { pY = y;
549 < end)) { if (direction === 0) {
550 < end)) { pH = height;
551 < end)) { pW = pTot / pH;
552 < end)) { width = width - pW;
553 < end)) { x = x + pW;
554 < end)) { } else {
555 < end)) { pW = width;
556 < end)) { pH = pTot / pW;
557 < end)) { height = height - pH;
558 < end)) { y = y + pH;
559 < end)) { }
560 < end)) { childrenArea.push({
561 < end)) { x: pX,
562 < end)) { y: pY,
563 < end)) { width: pW,
564 < end)) { height: pH
565 < end)) { });
566 < end)) { if (directionChange) {
567 < end)) { direction = 1 - direction;
568 < end)) { }
569 < end)) { });
570 < end)) { return childrenArea;
571 < end)) { },
572 < end)) { strip: function(parent, children) {
573 < end)) { return this.algorithmLowAspectRatio(false, parent, children);
574 < end)) { },
575 < end)) { squarified: function(parent, children) {
576 < end)) { return this.algorithmLowAspectRatio(true, parent, children);
577 < end)) { },
578 < end)) { sliceAndDice: function(parent, children) {
579 < end)) { return this.algorithmFill(true, parent, children);
580 < end)) { },
581 < end)) { stripes: function(parent, children) {
582 < end)) { return this.algorithmFill(false, parent, children);
583 < end)) { },
584 < end)) { translate: function() {
585 < end)) { var series = this,
586 < end)) { rootId = series.rootNode = pick(series.rootNode, series.options.rootId, ''),
587 < end)) { rootNode,
588 < end)) { pointValues,
589 < end)) { seriesArea,
590 < end)) { tree,
591 < end)) { val;
592  
593 < end)) { // Call prototype function
594 < end)) { Series.prototype.translate.call(series);
595 < end)) { // Create a object map from level to options
596 < end)) { series.levelMap = reduce(series.options.levels, function(arr, item) {
597 < end)) { arr[item.level] = item;
598 < end)) { return arr;
599 < end)) { }, {});
600 < end)) { tree = series.tree = series.getTree(); // @todo Only if series.isDirtyData is true
601 < end)) { rootNode = series.nodeMap[rootId];
602 < end)) { if (
603 < end)) { rootId !== '' &&
604 < end)) { (!rootNode || !rootNode.children.length)
605 < end)) { ) {
606 < end)) { series.drillToNode('', false);
607 < end)) { rootId = series.rootNode;
608 < end)) { rootNode = series.nodeMap[rootId];
609 < end)) { }
610 < end)) { series.setTreeValues(tree);
611  
612 < end)) { // Calculate plotting values.
613 < end)) { series.axisRatio = (series.xAxis.len / series.yAxis.len);
614 < end)) { series.nodeMap[''].pointValues = pointValues = {
615 < end)) { x: 0,
616 < end)) { y: 0,
617 < end)) { width: 100,
618 < end)) { height: 100
619 < end)) { };
620 < end)) { series.nodeMap[''].values = seriesArea = merge(pointValues, {
621 < end)) { width: (pointValues.width * series.axisRatio),
622 < end)) { direction: (series.options.layoutStartingDirection === 'vertical' ? 0 : 1),
623 < end)) { val: tree.val
624 < end)) { });
625 < end)) { series.calculateChildrenAreas(tree, seriesArea);
626  
627 < end)) { // Logic for point colors
628 < end)) { if (series.colorAxis) {
629 < end)) { series.translateColors();
630 < end)) { } else if (!series.options.colorByPoint) {
631 < end)) { series.setColorRecursive(series.tree);
632 < end)) { }
633  
634 < end)) { // Update axis extremes according to the root node.
635 < end)) { if (series.options.allowDrillToNode) {
636 < end)) { val = rootNode.pointValues;
637 < end)) { series.xAxis.setExtremes(val.x, val.x + val.width, false);
638 < end)) { series.yAxis.setExtremes(val.y, val.y + val.height, false);
639 < end)) { series.xAxis.setScale();
640 < end)) { series.yAxis.setScale();
641 < end)) { }
642  
643 < end)) { // Assign values to points.
644 < end)) { series.setPointValues();
645 < end)) { },
646 < end)) { /**
647 < end)) { * Extend drawDataLabels with logic to handle custom options related to the treemap series:
648 < end)) { * - Points which is not a leaf node, has dataLabels disabled by default.
649 < end)) { * - Options set on series.levels is merged in.
650 < end)) { * - Width of the dataLabel is set to match the width of the point shape.
651 < end)) { */
652 < end)) { drawDataLabels: function() {
653 < end)) { var series = this,
654 < end)) { points = grep(series.points, function(n) {
655 < end)) { return n.node.visible;
656 < end)) { }),
657 < end)) { options,
658 < end)) { level;
659 < end)) { each(points, function(point) {
660 < end)) { level = series.levelMap[point.node.levelDynamic];
661 < end)) { // Set options to new object to avoid problems with scope
662 < end)) { options = {
663 < end)) { style: {}
664 < end)) { };
665  
666 < end)) { // If not a leaf, then label should be disabled as default
667 < end)) { if (!point.node.isLeaf) {
668 < end)) { options.enabled = false;
669 < end)) { }
670  
671 < end)) { // If options for level exists, include them as well
672 < end)) { if (level && level.dataLabels) {
673 < end)) { options = merge(options, level.dataLabels);
674 < end)) { series._hasPointLabels = true;
675 < end)) { }
676  
677 < end)) { // Set dataLabel width to the width of the point shape.
678 < end)) { if (point.shapeArgs) {
679 < end)) { options.style.width = point.shapeArgs.width;
680 < end)) { if (point.dataLabel) {
681 < end)) { point.dataLabel.css({
682 < end)) { width: point.shapeArgs.width + 'px'
683 < end)) { });
684 < end)) { }
685 < end)) { }
686  
687 < end)) { // Merge custom options with point options
688 < end)) { point.dlOptions = merge(options, point.options.dataLabels);
689 < end)) { });
690 < end)) { Series.prototype.drawDataLabels.call(this);
691 < end)) { },
692  
693 < end)) { /**
694 < end)) { * Over the alignment method by setting z index
695 < end)) { */
696 < end)) { alignDataLabel: function(point) {
697 < end)) { seriesTypes.column.prototype.alignDataLabel.apply(this, arguments);
698 < end)) { if (point.dataLabel) {
699 < end)) { point.dataLabel.attr({
700 < end)) { zIndex: point.node.zIndex + 1
701 < end)) { });
702 < end)) { }
703 < end)) { },
704  
705  
706 < end)) { /**
707 < end)) { * Get presentational attributes
708 < end)) { */
709 < end)) { pointAttribs: function(point, state) {
710 < end)) { var level = this.levelMap[point.node.levelDynamic] || {},
711 < end)) { options = this.options,
712 < end)) { attr,
713 < end)) { stateOptions = (state && options.states[state]) || {},
714 < end)) { className = point.getClassName(),
715 < end)) { opacity;
716  
717 < end)) { // Set attributes by precedence. Point trumps level trumps series. Stroke width uses pick
718 < end)) { // because it can be 0.
719 < end)) { attr = {
720 < end)) { 'stroke': point.borderColor || level.borderColor || stateOptions.borderColor || options.borderColor,
721 < end)) { 'stroke-width': pick(point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth),
722 < end)) { 'dashstyle': point.borderDashStyle || level.borderDashStyle || stateOptions.borderDashStyle || options.borderDashStyle,
723 < end)) { 'fill': point.color || this.color
724 < end)) { };
725  
726 < end)) { // Hide levels above the current view
727 < end)) { if (className.indexOf('highcharts-above-level') !== -1) {
728 < end)) { attr.fill = 'none';
729 < end)) { attr['stroke-width'] = 0;
730  
731 < end)) { // Nodes with children that accept interaction
732 < end)) { } else if (className.indexOf('highcharts-internal-node-interactive') !== -1) {
733 < end)) { opacity = pick(stateOptions.opacity, options.opacity);
734 < end)) { attr.fill = color(attr.fill).setOpacity(opacity).get();
735 < end)) { attr.cursor = 'pointer';
736 < end)) { // Hide nodes that have children
737 < end)) { } else if (className.indexOf('highcharts-internal-node') !== -1) {
738 < end)) { attr.fill = 'none';
739  
740 < end)) { } else if (state) {
741 < end)) { // Brighten and hoist the hover nodes
742 < end)) { attr.fill = color(attr.fill).brighten(stateOptions.brightness).get();
743 < end)) { }
744 < end)) { return attr;
745 < end)) { },
746  
747  
748 < end)) { /**
749 < end)) { * Extending ColumnSeries drawPoints
750 < end)) { */
751 < end)) { drawPoints: function() {
752 < end)) { var series = this,
753 < end)) { points = grep(series.points, function(n) {
754 < end)) { return n.node.visible;
755 < end)) { });
756  
757 < end)) { each(points, function(point) {
758 < end)) { var groupKey = 'levelGroup-' + point.node.levelDynamic;
759 < end)) { if (!series[groupKey]) {
760 < end)) { series[groupKey] = series.chart.renderer.g(groupKey)
761 < end)) { .attr({
762 < end)) { zIndex: 1000 - point.node.levelDynamic // @todo Set the zIndex based upon the number of levels, instead of using 1000
763 < end)) { })
764 < end)) { .add(series.group);
765 < end)) { }
766 < end)) { point.group = series[groupKey];
767  
768 < end)) { });
769 < end)) { // Call standard drawPoints
770 < end)) { seriesTypes.column.prototype.drawPoints.call(this);
771  
772 < end)) { // If drillToNode is allowed, set a point cursor on clickables & add drillId to point
773 < end)) { if (series.options.allowDrillToNode) {
774 < end)) { each(points, function(point) {
775 < end)) { if (point.graphic) {
776 < end)) { point.drillId = series.options.interactByLeaf ? series.drillToByLeaf(point) : series.drillToByGroup(point);
777 < end)) { }
778 < end)) { });
779 < end)) { }
780 < end)) { },
781 < end)) { /**
782 < end)) { * Add drilling on the suitable points
783 < end)) { */
784 < end)) { onClickDrillToNode: function(event) {
785 < end)) { var series = this,
786 < end)) { point = event.point,
787 < end)) { drillId = point && point.drillId;
788 < end)) { // If a drill id is returned, add click event and cursor.
789 < end)) { if (isString(drillId)) {
790 < end)) { point.setState(''); // Remove hover
791 < end)) { series.drillToNode(drillId);
792 < end)) { }
793 < end)) { },
794 < end)) { /**
795 < end)) { * Finds the drill id for a parent node.
796 < end)) { * Returns false if point should not have a click event
797 < end)) { * @param {Object} point
798 < end)) { * @return {string || boolean} Drill to id or false when point should not have a click event
799 < end)) { */
800 < end)) { drillToByGroup: function(point) {
801 < end)) { var series = this,
802 < end)) { drillId = false;
803 < end)) { if ((point.node.level - series.nodeMap[series.rootNode].level) === 1 && !point.node.isLeaf) {
804 < end)) { drillId = point.id;
805 < end)) { }
806 < end)) { return drillId;
807 < end)) { },
808 < end)) { /**
809 < end)) { * Finds the drill id for a leaf node.
810 < end)) { * Returns false if point should not have a click event
811 < end)) { * @param {Object} point
812 < end)) { * @return {string || boolean} Drill to id or false when point should not have a click event
813 < end)) { */
814 < end)) { drillToByLeaf: function(point) {
815 < end)) { var series = this,
816 < end)) { drillId = false,
817 < end)) { nodeParent;
818 < end)) { if ((point.node.parent !== series.rootNode) && (point.node.isLeaf)) {
819 < end)) { nodeParent = point.node;
820 < end)) { while (!drillId) {
821 < end)) { nodeParent = series.nodeMap[nodeParent.parent];
822 < end)) { if (nodeParent.parent === series.rootNode) {
823 < end)) { drillId = nodeParent.id;
824 < end)) { }
825 < end)) { }
826 < end)) { }
827 < end)) { return drillId;
828 < end)) { },
829 < end)) { drillUp: function() {
830 < end)) { var series = this,
831 < end)) { node = series.nodeMap[series.rootNode];
832 < end)) { if (node && isString(node.parent)) {
833 < end)) { series.drillToNode(node.parent);
834 < end)) { }
835 < end)) { },
836 < end)) { drillToNode: function(id, redraw) {
837 < end)) { var series = this,
838 < end)) { nodeMap = series.nodeMap,
839 < end)) { node = nodeMap[id];
840 < end)) { series.rootNode = id;
841 < end)) { if (id === '') {
842 < end)) { series.drillUpButton = series.drillUpButton.destroy();
843 < end)) { } else {
844 < end)) { series.showDrillUpButton((node && node.name || id));
845 < end)) { }
846 < end)) { this.isDirty = true; // Force redraw
847 < end)) { if (pick(redraw, true)) {
848 < end)) { this.chart.redraw();
849 < end)) { }
850 < end)) { },
851 < end)) { showDrillUpButton: function(name) {
852 < end)) { var series = this,
853 < end)) { backText = (name || '< Back'),
854 < end)) { buttonOptions = series.options.drillUpButton,
855 < end)) { attr,
856 < end)) { states;
857  
858 < end)) { if (buttonOptions.text) {
859 < end)) { backText = buttonOptions.text;
860 < end)) { }
861 < end)) { if (!this.drillUpButton) {
862 < end)) { attr = buttonOptions.theme;
863 < end)) { states = attr && attr.states;
864  
865 < end)) { this.drillUpButton = this.chart.renderer.button(
866 < end)) { backText,
867 < end)) { null,
868 < end)) { null,
869 < end)) { function() {
870 < end)) { series.drillUp();
871 < end)) { },
872 < end)) { attr,
873 < end)) { states && states.hover,
874 < end)) { states && states.select
875 < end)) { )
876 < end)) { .attr({
877 < end)) { align: buttonOptions.position.align,
878 < end)) { zIndex: 7
879 < end)) { })
880 < end)) { .add()
881 < end)) { .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
882 < end)) { } else {
883 < end)) { this.drillUpButton.attr({
884 < end)) { text: backText
885 < end)) { })
886 < end)) { .align();
887 < end)) { }
888 < end)) { },
889 < end)) { buildKDTree: noop,
890 < end)) { drawLegendSymbol: H.LegendSymbolMixin.drawRectangle,
891 < end)) { getExtremes: function() {
892 < end)) { // Get the extremes from the value data
893 < end)) { Series.prototype.getExtremes.call(this, this.colorValueData);
894 < end)) { this.valueMin = this.dataMin;
895 < end)) { this.valueMax = this.dataMax;
896  
897 < end)) { // Get the extremes from the y data
898 < end)) { Series.prototype.getExtremes.call(this);
899 < end)) { },
900 < end)) { getExtremesFromAll: true,
901 < end)) { bindAxes: function() {
902 < end)) { var treeAxis = {
903 < end)) { endOnTick: false,
904 < end)) { gridLineWidth: 0,
905 < end)) { lineWidth: 0,
906 < end)) { min: 0,
907 < end)) { dataMin: 0,
908 < end)) { minPadding: 0,
909 < end)) { max: 100,
910 < end)) { dataMax: 100,
911 < end)) { maxPadding: 0,
912 < end)) { startOnTick: false,
913 < end)) { title: null,
914 < end)) { tickPositions: []
915 < end)) { };
916 < end)) { Series.prototype.bindAxes.call(this);
917 < end)) { H.extend(this.yAxis.options, treeAxis);
918 < end)) { H.extend(this.xAxis.options, treeAxis);
919 < end)) { }
920  
921 < end)) { // Point class
922 < end)) { }, {
923 < end)) { getClassName: function() {
924 < end)) { var className = H.Point.prototype.getClassName.call(this),
925 < end)) { series = this.series,
926 < end)) { options = series.options;
927  
928 < end)) { // Above the current level
929 < end)) { if (this.node.level <= series.nodeMap[series.rootNode].level) {
930 < end)) { className += ' highcharts-above-level';
931  
932 < end)) { } else if (!this.node.isLeaf && !pick(options.interactByLeaf, !options.allowDrillToNode)) {
933 < end)) { className += ' highcharts-internal-node-interactive';
934  
935 < end)) { } else if (!this.node.isLeaf) {
936 < end)) { className += ' highcharts-internal-node';
937 < end)) { }
938 < end)) { return className;
939 < end)) { },
940 < end)) { isValid: function() {
941 < end)) { return isNumber(this.value);
942 < end)) { },
943 < end)) { setState: function(state) {
944 < end)) { H.Point.prototype.setState.call(this, state);
945  
946 < end)) { // Graphic does not exist when point is not visible.
947 < end)) { if (this.graphic) {
948 < end)) { this.graphic.attr({
949 < end)) { zIndex: state === 'hover' ? 1 : 0
950 < end)) { });
951 < end)) { }
952 < end)) { },
953 < end)) { setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible
954 < end)) { });
955  
956 < end)) { }(Highcharts));
957 < end)) {}));