corrade-nucleus-nucleons – Blame information for rev 31

Subversion Repositories:
Rev:
Rev Author Line No. Line
31 office 1 /**
2 * @license Highcharts JS v5.0.14 (2017-07-28)
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 /**
66 * @extends {plotOptions.scatter}
67 * @optionparent plotOptions.treemap
68 */
69 seriesType('treemap', 'scatter', {
70  
71 /**
72 * Whether to display this series type or specific series item in the
73 * legend.
74 *
75 * @type {Boolean}
76 * @default false
77 * @product highcharts
78 */
79 showInLegend: false,
80  
81 /**
82 */
83 marker: false,
84  
85 /**
86 * @extends plotOptions.heatmap.dataLabels
87 * @since 4.1.0
88 * @product highcharts
89 */
90 dataLabels: {
91  
92 /**
93 * Enable or disable the data labels.
94 *
95 * @type {Boolean}
96 * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/ Data labels enabled
97 * @default true
98 * @since 4.1.0
99 * @product highcharts
100 */
101 enabled: true,
102  
103 /**
104 * Whether to defer displaying the data labels until the initial series
105 * animation has finished.
106 *
107 * @type {Boolean}
108 * @default false
109 * @since 4.1.0
110 * @product highcharts
111 */
112 defer: false,
113  
114 /**
115 * The vertical alignment of a data label. Can be one of top, middle
116 * or bottom. The default value depends on the data, for instance
117 * in a column chart, the label is above positive values and below
118 * negative values.
119 *
120 * @type {String}
121 * @default middle
122 * @since 4.1.0
123 * @product highcharts
124 */
125 verticalAlign: 'middle',
126  
127 /**
128 */
129 formatter: function() { // #2945
130 return this.point.name || this.point.id;
131 },
132  
133 /**
134 * Whether to align the data label inside the box or to the actual
135 * value point.
136 *
137 * @type {Boolean}
138 * @default true
139 * @since 4.1.0
140 * @product highcharts
141 */
142 inside: true
143 },
144  
145 /**
146 * @extends plotOptions.heatmap.tooltip
147 * @since 4.1.0
148 * @product highcharts
149 */
150 tooltip: {
151  
152 /**
153 * The HTML of the tooltip header line. Variables are enclosed by
154 * curly brackets. Available variables are point.key, series.name,
155 * series.color and other members from the point and series objects.
156 * The point.key variable contains the category name, x value or
157 * datetime string depending on the type of axis. For datetime axes,
158 * the point.key date format can be set using tooltip.xDateFormat.
159 *
160 * @type {String}
161 * @sample {highcharts} highcharts/tooltip/footerformat/ A HTML table in the tooltip
162 * @default ""
163 * @since 4.1.0
164 * @product highcharts
165 */
166 headerFormat: '',
167  
168 /**
169 * The HTML of the point's line in the tooltip. Variables are enclosed
170 * by curly brackets. Available variables are point.x, point.y, series.
171 * name and series.color and other properties on the same form. Furthermore,
172 * point.y can be extended by the tooltip.yPrefix and tooltip.ySuffix
173 * variables. This can also be overridden for each series, which makes
174 * it a good hook for displaying units.
175 *
176 * @type {String}
177 * @sample {highcharts} highcharts/tooltip/pointformat/ A different point format with value suffix
178 * @default "<b>{point.name}</b>: {point.value}</b><br/>"
179 * @since 4.1.0
180 * @product highcharts
181 */
182 pointFormat: '<b>{point.name}</b>: {point.value}</b><br/>'
183 },
184  
185 /**
186 * Whether to ignore hidden points when the layout algorithm runs.
187 * If `false`, hidden points will leave open spaces.
188 *
189 * @type {Boolean}
190 * @default true
191 * @since 5.0.8
192 * @product highcharts
193 */
194 ignoreHiddenPoint: true,
195  
196 /**
197 * This option decides which algorithm is used for setting position
198 * and dimensions of the points. Can be one of `sliceAndDice`, `stripes`,
199 * `squarified` or `strip`.
200 *
201 * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"]
202 * @type {String}
203 * @see [How to write your own algorithm](http://www.highcharts.com/docs/chart-
204 * and-series-types/treemap)
205 * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-sliceanddice/ SliceAndDice by default
206 * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-stripes/ Stripes
207 * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-squarified/ Squarified
208 * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-strip/ Strip
209 * @default sliceAndDice
210 * @since 4.1.0
211 * @product highcharts
212 */
213 layoutAlgorithm: 'sliceAndDice',
214  
215 /**
216 * Defines which direction the layout algorithm will start drawing.
217 * Possible values are "vertical" and "horizontal".
218 *
219 * @validvalue ["vertical", "horizontal"]
220 * @type {String}
221 * @default vertical
222 * @since 4.1.0
223 * @product highcharts
224 */
225 layoutStartingDirection: 'vertical',
226  
227 /**
228 * Enabling this option will make the treemap alternate the drawing
229 * direction between vertical and horizontal. The next levels starting
230 * direction will always be the opposite of the previous.
231 *
232 * @type {Boolean}
233 * @sample {highcharts} highcharts/plotoptions/treemap-alternatestartingdirection-true/ Enabled
234 * @default false
235 * @since 4.1.0
236 * @product highcharts
237 */
238 alternateStartingDirection: false,
239  
240 /**
241 * Used together with the levels and allowDrillToNode options. When
242 * set to false the first level visible when drilling is considered
243 * to be level one. Otherwise the level will be the same as the tree
244 * structure.
245 *
246 * @validvalue [true, false]
247 * @type {Boolean}
248 * @default true
249 * @since 4.1.0
250 * @product highcharts
251 */
252 levelIsConstant: true,
253  
254 /**
255 */
256 drillUpButton: {
257  
258 /**
259 */
260 position: {
261  
262 /**
263 */
264 align: 'right',
265  
266 /**
267 */
268 x: -10,
269  
270 /**
271 */
272 y: 10
273 }
274 },
275  
276  
277 // Prototype members
278 }, {
279 pointArrayMap: ['value'],
280 axisTypes: seriesTypes.heatmap ? ['xAxis', 'yAxis', 'colorAxis'] : ['xAxis', 'yAxis'],
281 directTouch: true,
282 optionalAxis: 'colorAxis',
283 getSymbol: noop,
284 parallelArrays: ['x', 'y', 'value', 'colorValue'],
285 colorKey: 'colorValue', // Point color option key
286 translateColors: seriesTypes.heatmap && seriesTypes.heatmap.prototype.translateColors,
287 trackerGroups: ['group', 'dataLabelsGroup'],
288 /**
289 * Creates an object map from parent id to childrens index.
290 * @param {Array} data List of points set in options.
291 * @param {string} data[].parent Parent id of point.
292 * @param {Array} ids List of all point ids.
293 * @return {Object} Map from parent id to children index in data.
294 */
295 getListOfParents: function(data, ids) {
296 var listOfParents = reduce(data, function(prev, curr, i) {
297 var parent = pick(curr.parent, '');
298 if (prev[parent] === undefined) {
299 prev[parent] = [];
300 }
301 prev[parent].push(i);
302 return prev;
303 }, {});
304  
305 // If parent does not exist, hoist parent to root of tree.
306 eachObject(listOfParents, function(children, parent, list) {
307 if ((parent !== '') && (H.inArray(parent, ids) === -1)) {
308 each(children, function(child) {
309 list[''].push(child);
310 });
311 delete list[parent];
312 }
313 });
314 return listOfParents;
315 },
316 /**
317 * Creates a tree structured object from the series points
318 */
319 getTree: function() {
320 var series = this,
321 allIds = map(this.data, function(d) {
322 return d.id;
323 }),
324 parentList = series.getListOfParents(this.data, allIds);
325  
326 series.nodeMap = [];
327 return series.buildNode('', -1, 0, parentList, null);
328 },
329 init: function(chart, options) {
330 var series = this;
331 Series.prototype.init.call(series, chart, options);
332 if (series.options.allowDrillToNode) {
333 H.addEvent(series, 'click', series.onClickDrillToNode);
334 }
335 },
336 buildNode: function(id, i, level, list, parent) {
337 var series = this,
338 children = [],
339 point = series.points[i],
340 node,
341 child;
342  
343 // Actions
344 each((list[id] || []), function(i) {
345 child = series.buildNode(series.points[i].id, i, (level + 1), list, id);
346 children.push(child);
347 });
348 node = {
349 id: id,
350 i: i,
351 children: children,
352 level: level,
353 parent: parent,
354 visible: false // @todo move this to better location
355 };
356 series.nodeMap[node.id] = node;
357 if (point) {
358 point.node = node;
359 }
360 return node;
361 },
362 setTreeValues: function(tree) {
363 var series = this,
364 options = series.options,
365 childrenTotal = 0,
366 children = [],
367 val,
368 point = series.points[tree.i];
369  
370 // First give the children some values
371 each(tree.children, function(child) {
372 child = series.setTreeValues(child);
373 children.push(child);
374 if (!child.ignore) {
375 childrenTotal += child.val;
376 }
377 });
378 // Sort the children
379 stableSort(children, function(a, b) {
380 return a.sortIndex - b.sortIndex;
381 });
382 // Set the values
383 val = pick(point && point.options.value, childrenTotal);
384 if (point) {
385 point.value = val;
386 }
387 extend(tree, {
388 children: children,
389 childrenTotal: childrenTotal,
390 // Ignore this node if point is not visible
391 ignore: !(pick(point && point.visible, true) && (val > 0)),
392 isLeaf: tree.visible && !childrenTotal,
393 levelDynamic: tree.level - (options.levelIsConstant ? series.nodeMap[series.rootNode].level : 0),
394 name: pick(point && point.name, ''),
395 sortIndex: pick(point && point.sortIndex, -val),
396 val: val
397 });
398 return tree;
399 },
400 /**
401 * Recursive function which calculates the area for all children of a node.
402 * @param {Object} node The node which is parent to the children.
403 * @param {Object} area The rectangular area of the parent.
404 */
405 calculateChildrenAreas: function(parent, area) {
406 var series = this,
407 options = series.options,
408 level = this.levelMap[parent.levelDynamic + 1],
409 algorithm = pick((series[level && level.layoutAlgorithm] && level.layoutAlgorithm), options.layoutAlgorithm),
410 alternate = options.alternateStartingDirection,
411 childrenValues = [],
412 children;
413  
414 // Collect all children which should be included
415 children = grep(parent.children, function(n) {
416 return !n.ignore;
417 });
418  
419 if (level && level.layoutStartingDirection) {
420 area.direction = level.layoutStartingDirection === 'vertical' ? 0 : 1;
421 }
422 childrenValues = series[algorithm](area, children);
423 each(children, function(child, index) {
424 var values = childrenValues[index];
425 child.values = merge(values, {
426 val: child.childrenTotal,
427 direction: (alternate ? 1 - area.direction : area.direction)
428 });
429 child.pointValues = merge(values, {
430 x: (values.x / series.axisRatio),
431 width: (values.width / series.axisRatio)
432 });
433 // If node has children, then call method recursively
434 if (child.children.length) {
435 series.calculateChildrenAreas(child, child.values);
436 }
437 });
438 },
439 setPointValues: function() {
440 var series = this,
441 xAxis = series.xAxis,
442 yAxis = series.yAxis;
443 each(series.points, function(point) {
444 var node = point.node,
445 values = node.pointValues,
446 x1,
447 x2,
448 y1,
449 y2,
450 crispCorr = 0;
451  
452  
453  
454 // Points which is ignored, have no values.
455 if (values && node.visible) {
456 x1 = Math.round(xAxis.translate(values.x, 0, 0, 0, 1)) - crispCorr;
457 x2 = Math.round(xAxis.translate(values.x + values.width, 0, 0, 0, 1)) - crispCorr;
458 y1 = Math.round(yAxis.translate(values.y, 0, 0, 0, 1)) - crispCorr;
459 y2 = Math.round(yAxis.translate(values.y + values.height, 0, 0, 0, 1)) - crispCorr;
460 // Set point values
461 point.shapeType = 'rect';
462 point.shapeArgs = {
463 x: Math.min(x1, x2),
464 y: Math.min(y1, y2),
465 width: Math.abs(x2 - x1),
466 height: Math.abs(y2 - y1)
467 };
468 point.plotX = point.shapeArgs.x + (point.shapeArgs.width / 2);
469 point.plotY = point.shapeArgs.y + (point.shapeArgs.height / 2);
470 } else {
471 // Reset visibility
472 delete point.plotX;
473 delete point.plotY;
474 }
475 });
476 },
477 setColorRecursive: function(node, color, colorIndex) {
478 var series = this,
479 point,
480 level;
481 if (node) {
482 point = series.points[node.i];
483 level = series.levelMap[node.levelDynamic];
484 // Select either point color, level color or inherited color.
485 color = pick(
486 point && point.options.color,
487 level && level.color,
488 color,
489 series.color
490 );
491 colorIndex = pick(
492 point && point.options.colorIndex,
493 level && level.colorIndex,
494 colorIndex,
495 series.colorIndex
496 );
497  
498 if (point) {
499 point.color = color;
500 point.colorIndex = colorIndex;
501 }
502  
503 // Do it all again with the children
504 if (node.children.length) {
505 each(node.children, function(child) {
506 series.setColorRecursive(child, color, colorIndex);
507 });
508 }
509 }
510 },
511 algorithmGroup: function(h, w, d, p) {
512 this.height = h;
513 this.width = w;
514 this.plot = p;
515 this.direction = d;
516 this.startDirection = d;
517 this.total = 0;
518 this.nW = 0;
519 this.lW = 0;
520 this.nH = 0;
521 this.lH = 0;
522 this.elArr = [];
523 this.lP = {
524 total: 0,
525 lH: 0,
526 nH: 0,
527 lW: 0,
528 nW: 0,
529 nR: 0,
530 lR: 0,
531 aspectRatio: function(w, h) {
532 return Math.max((w / h), (h / w));
533 }
534 };
535 this.addElement = function(el) {
536 this.lP.total = this.elArr[this.elArr.length - 1];
537 this.total = this.total + el;
538 if (this.direction === 0) {
539 // Calculate last point old aspect ratio
540 this.lW = this.nW;
541 this.lP.lH = this.lP.total / this.lW;
542 this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH);
543 // Calculate last point new aspect ratio
544 this.nW = this.total / this.height;
545 this.lP.nH = this.lP.total / this.nW;
546 this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH);
547 } else {
548 // Calculate last point old aspect ratio
549 this.lH = this.nH;
550 this.lP.lW = this.lP.total / this.lH;
551 this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH);
552 // Calculate last point new aspect ratio
553 this.nH = this.total / this.width;
554 this.lP.nW = this.lP.total / this.nH;
555 this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH);
556 }
557 this.elArr.push(el);
558 };
559 this.reset = function() {
560 this.nW = 0;
561 this.lW = 0;
562 this.elArr = [];
563 this.total = 0;
564 };
565 },
566 algorithmCalcPoints: function(directionChange, last, group, childrenArea) {
567 var pX,
568 pY,
569 pW,
570 pH,
571 gW = group.lW,
572 gH = group.lH,
573 plot = group.plot,
574 keep,
575 i = 0,
576 end = group.elArr.length - 1;
577 if (last) {
578 gW = group.nW;
579 gH = group.nH;
580 } else {
581 keep = group.elArr[group.elArr.length - 1];
582 }
583 each(group.elArr, function(p) {
584 if (last || (i < end)) {
585 if (group.direction === 0) {
586 pX = plot.x;
587 pY = plot.y;
588 pW = gW;
589 pH = p / pW;
590 } else {
591 pX = plot.x;
592 pY = plot.y;
593 pH = gH;
594 pW = p / pH;
595 }
596 childrenArea.push({
597 x: pX,
598 y: pY,
599 width: pW,
600 height: pH
601 });
602 if (group.direction === 0) {
603 plot.y = plot.y + pH;
604 } else {
605 plot.x = plot.x + pW;
606 }
607 }
608 i = i + 1;
609 });
610 // Reset variables
611 group.reset();
612 if (group.direction === 0) {
613 group.width = group.width - gW;
614 } else {
615 group.height = group.height - gH;
616 }
617 plot.y = plot.parent.y + (plot.parent.height - group.height);
618 plot.x = plot.parent.x + (plot.parent.width - group.width);
619 if (directionChange) {
620 group.direction = 1 - group.direction;
621 }
622 // If not last, then add uncalculated element
623 if (!last) {
624 group.addElement(keep);
625 }
626 },
627 algorithmLowAspectRatio: function(directionChange, parent, children) {
628 var childrenArea = [],
629 series = this,
630 pTot,
631 plot = {
632 x: parent.x,
633 y: parent.y,
634 parent: parent
635 },
636 direction = parent.direction,
637 i = 0,
638 end = children.length - 1,
639 group = new this.algorithmGroup(parent.height, parent.width, direction, plot); // eslint-disable-line new-cap
640 // Loop through and calculate all areas
641 each(children, function(child) {
642 pTot = (parent.width * parent.height) * (child.val / parent.val);
643 group.addElement(pTot);
644 if (group.lP.nR > group.lP.lR) {
645 series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot);
646 }
647 // If last child, then calculate all remaining areas
648 if (i === end) {
649 series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot);
650 }
651 i = i + 1;
652 });
653 return childrenArea;
654 },
655 algorithmFill: function(directionChange, parent, children) {
656 var childrenArea = [],
657 pTot,
658 direction = parent.direction,
659 x = parent.x,
660 y = parent.y,
661 width = parent.width,
662 height = parent.height,
663 pX,
664 pY,
665 pW,
666 pH;
667 each(children, function(child) {
668 pTot = (parent.width * parent.height) * (child.val / parent.val);
669 pX = x;
670 pY = y;
671 if (direction === 0) {
672 pH = height;
673 pW = pTot / pH;
674 width = width - pW;
675 x = x + pW;
676 } else {
677 pW = width;
678 pH = pTot / pW;
679 height = height - pH;
680 y = y + pH;
681 }
682 childrenArea.push({
683 x: pX,
684 y: pY,
685 width: pW,
686 height: pH
687 });
688 if (directionChange) {
689 direction = 1 - direction;
690 }
691 });
692 return childrenArea;
693 },
694 strip: function(parent, children) {
695 return this.algorithmLowAspectRatio(false, parent, children);
696 },
697 squarified: function(parent, children) {
698 return this.algorithmLowAspectRatio(true, parent, children);
699 },
700 sliceAndDice: function(parent, children) {
701 return this.algorithmFill(true, parent, children);
702 },
703 stripes: function(parent, children) {
704 return this.algorithmFill(false, parent, children);
705 },
706 translate: function() {
707 var series = this,
708 rootId = series.rootNode = pick(series.rootNode, series.options.rootId, ''),
709 rootNode,
710 pointValues,
711 seriesArea,
712 tree,
713 val;
714  
715 // Call prototype function
716 Series.prototype.translate.call(series);
717 // Create a object map from level to options
718 series.levelMap = reduce(series.options.levels, function(arr, item) {
719 arr[item.level] = item;
720 return arr;
721 }, {});
722 tree = series.tree = series.getTree(); // @todo Only if series.isDirtyData is true
723 rootNode = series.nodeMap[rootId];
724 if (
725 rootId !== '' &&
726 (!rootNode || !rootNode.children.length)
727 ) {
728 series.drillToNode('', false);
729 rootId = series.rootNode;
730 rootNode = series.nodeMap[rootId];
731 }
732 // Parents of the root node is by default visible
733 recursive(series.nodeMap[series.rootNode], function(node) {
734 var next = false,
735 p = node.parent;
736 node.visible = true;
737 if (p || p === '') {
738 next = series.nodeMap[p];
739 }
740 return next;
741 });
742 // Children of the root node is by default visible
743 recursive(series.nodeMap[series.rootNode].children, function(children) {
744 var next = false;
745 each(children, function(child) {
746 child.visible = true;
747 if (child.children.length) {
748 next = (next || []).concat(child.children);
749 }
750 });
751 return next;
752 });
753 series.setTreeValues(tree);
754  
755 // Calculate plotting values.
756 series.axisRatio = (series.xAxis.len / series.yAxis.len);
757 series.nodeMap[''].pointValues = pointValues = {
758 x: 0,
759 y: 0,
760 width: 100,
761 height: 100
762 };
763 series.nodeMap[''].values = seriesArea = merge(pointValues, {
764 width: (pointValues.width * series.axisRatio),
765 direction: (series.options.layoutStartingDirection === 'vertical' ? 0 : 1),
766 val: tree.val
767 });
768 series.calculateChildrenAreas(tree, seriesArea);
769  
770 // Logic for point colors
771 if (series.colorAxis) {
772 series.translateColors();
773 } else if (!series.options.colorByPoint) {
774 series.setColorRecursive(series.tree);
775 }
776  
777 // Update axis extremes according to the root node.
778 if (series.options.allowDrillToNode) {
779 val = rootNode.pointValues;
780 series.xAxis.setExtremes(val.x, val.x + val.width, false);
781 series.yAxis.setExtremes(val.y, val.y + val.height, false);
782 series.xAxis.setScale();
783 series.yAxis.setScale();
784 }
785  
786 // Assign values to points.
787 series.setPointValues();
788 },
789 /**
790 * Extend drawDataLabels with logic to handle custom options related to the treemap series:
791 * - Points which is not a leaf node, has dataLabels disabled by default.
792 * - Options set on series.levels is merged in.
793 * - Width of the dataLabel is set to match the width of the point shape.
794 */
795 drawDataLabels: function() {
796 var series = this,
797 points = grep(series.points, function(n) {
798 return n.node.visible;
799 }),
800 options,
801 level;
802 each(points, function(point) {
803 level = series.levelMap[point.node.levelDynamic];
804 // Set options to new object to avoid problems with scope
805 options = {
806 style: {}
807 };
808  
809 // If not a leaf, then label should be disabled as default
810 if (!point.node.isLeaf) {
811 options.enabled = false;
812 }
813  
814 // If options for level exists, include them as well
815 if (level && level.dataLabels) {
816 options = merge(options, level.dataLabels);
817 series._hasPointLabels = true;
818 }
819  
820 // Set dataLabel width to the width of the point shape.
821 if (point.shapeArgs) {
822 options.style.width = point.shapeArgs.width;
823 if (point.dataLabel) {
824 point.dataLabel.css({
825 width: point.shapeArgs.width + 'px'
826 });
827 }
828 }
829  
830 // Merge custom options with point options
831 point.dlOptions = merge(options, point.options.dataLabels);
832 });
833 Series.prototype.drawDataLabels.call(this);
834 },
835  
836 /**
837 * Over the alignment method by setting z index
838 */
839 alignDataLabel: function(point) {
840 seriesTypes.column.prototype.alignDataLabel.apply(this, arguments);
841 if (point.dataLabel) {
842 // point.node.zIndex could be undefined (#6956)
843 point.dataLabel.attr({
844 zIndex: (point.node.zIndex || 0) + 1
845 });
846 }
847 },
848  
849  
850  
851 /**
852 * Extending ColumnSeries drawPoints
853 */
854 drawPoints: function() {
855 var series = this,
856 points = grep(series.points, function(n) {
857 return n.node.visible;
858 });
859  
860 each(points, function(point) {
861 var groupKey = 'levelGroup-' + point.node.levelDynamic;
862 if (!series[groupKey]) {
863 series[groupKey] = series.chart.renderer.g(groupKey)
864 .attr({
865 zIndex: 1000 - point.node.levelDynamic // @todo Set the zIndex based upon the number of levels, instead of using 1000
866 })
867 .add(series.group);
868 }
869 point.group = series[groupKey];
870  
871 });
872 // Call standard drawPoints
873 seriesTypes.column.prototype.drawPoints.call(this);
874  
875 // If drillToNode is allowed, set a point cursor on clickables & add drillId to point
876 if (series.options.allowDrillToNode) {
877 each(points, function(point) {
878 if (point.graphic) {
879 point.drillId = series.options.interactByLeaf ? series.drillToByLeaf(point) : series.drillToByGroup(point);
880 }
881 });
882 }
883 },
884 /**
885 * Add drilling on the suitable points
886 */
887 onClickDrillToNode: function(event) {
888 var series = this,
889 point = event.point,
890 drillId = point && point.drillId;
891 // If a drill id is returned, add click event and cursor.
892 if (isString(drillId)) {
893 point.setState(''); // Remove hover
894 series.drillToNode(drillId);
895 }
896 },
897 /**
898 * Finds the drill id for a parent node.
899 * Returns false if point should not have a click event
900 * @param {Object} point
901 * @return {String|Boolean} Drill to id or false when point should not have a click event
902 */
903 drillToByGroup: function(point) {
904 var series = this,
905 drillId = false;
906 if ((point.node.level - series.nodeMap[series.rootNode].level) === 1 && !point.node.isLeaf) {
907 drillId = point.id;
908 }
909 return drillId;
910 },
911 /**
912 * Finds the drill id for a leaf node.
913 * Returns false if point should not have a click event
914 * @param {Object} point
915 * @return {String|Boolean} Drill to id or false when point should not have a click event
916 */
917 drillToByLeaf: function(point) {
918 var series = this,
919 drillId = false,
920 nodeParent;
921 if ((point.node.parent !== series.rootNode) && (point.node.isLeaf)) {
922 nodeParent = point.node;
923 while (!drillId) {
924 nodeParent = series.nodeMap[nodeParent.parent];
925 if (nodeParent.parent === series.rootNode) {
926 drillId = nodeParent.id;
927 }
928 }
929 }
930 return drillId;
931 },
932 drillUp: function() {
933 var series = this,
934 node = series.nodeMap[series.rootNode];
935 if (node && isString(node.parent)) {
936 series.drillToNode(node.parent);
937 }
938 },
939 drillToNode: function(id, redraw) {
940 var series = this,
941 nodeMap = series.nodeMap,
942 node = nodeMap[id];
943 series.rootNode = id;
944 if (id === '') {
945 series.drillUpButton = series.drillUpButton.destroy();
946 } else {
947 series.showDrillUpButton((node && node.name || id));
948 }
949 this.isDirty = true; // Force redraw
950 if (pick(redraw, true)) {
951 this.chart.redraw();
952 }
953 },
954 showDrillUpButton: function(name) {
955 var series = this,
956 backText = (name || '< Back'),
957 < Back'), buttonOptions = series.options.drillUpButton,
958 < Back'), attr,
959 < Back'), states;
960  
961 < Back'), if (buttonOptions.text) {
962 < Back'), backText = buttonOptions.text;
963 < Back'), }
964 < Back'), if (!this.drillUpButton) {
965 < Back'), attr = buttonOptions.theme;
966 < Back'), states = attr && attr.states;
967  
968 < Back'), this.drillUpButton = this.chart.renderer.button(
969 < Back'), backText,
970 < Back'), null,
971 < Back'), null,
972 < Back'), function() {
973 < Back'), series.drillUp();
974 < Back'), },
975 < Back'), attr,
976 < Back'), states && states.hover,
977 < Back'), states && states.select
978 < Back'), )
979 < Back'), .attr({
980 < Back'), align: buttonOptions.position.align,
981 < Back'), zIndex: 7
982 < Back'), })
983 < Back'), .add()
984 < Back'), .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox');
985 < Back'), } else {
986 < Back'), this.drillUpButton.attr({
987 < Back'), text: backText
988 < Back'), })
989 < Back'), .align();
990 < Back'), }
991 < Back'), },
992 < Back'), buildKDTree: noop,
993 < Back'), drawLegendSymbol: H.LegendSymbolMixin.drawRectangle,
994 < Back'), getExtremes: function() {
995 < Back'), // Get the extremes from the value data
996 < Back'), Series.prototype.getExtremes.call(this, this.colorValueData);
997 < Back'), this.valueMin = this.dataMin;
998 < Back'), this.valueMax = this.dataMax;
999  
1000 < Back'), // Get the extremes from the y data
1001 < Back'), Series.prototype.getExtremes.call(this);
1002 < Back'), },
1003 < Back'), getExtremesFromAll: true,
1004 < Back'), bindAxes: function() {
1005 < Back'), var treeAxis = {
1006 < Back'), endOnTick: false,
1007 < Back'), gridLineWidth: 0,
1008 < Back'), lineWidth: 0,
1009 < Back'), min: 0,
1010 < Back'), dataMin: 0,
1011 < Back'), minPadding: 0,
1012 < Back'), max: 100,
1013 < Back'), dataMax: 100,
1014 < Back'), maxPadding: 0,
1015 < Back'), startOnTick: false,
1016 < Back'), title: null,
1017 < Back'), tickPositions: []
1018 < Back'), };
1019 < Back'), Series.prototype.bindAxes.call(this);
1020 < Back'), H.extend(this.yAxis.options, treeAxis);
1021 < Back'), H.extend(this.xAxis.options, treeAxis);
1022 < Back'), }
1023  
1024 < Back'), // Point class
1025 < Back'), }, {
1026 < Back'), getClassName: function() {
1027 < Back'), var className = H.Point.prototype.getClassName.call(this),
1028 < Back'), series = this.series,
1029 < Back'), options = series.options;
1030  
1031 < Back'), // Above the current level
1032 < Back'), if (this.node.level <= series.nodeMap[series.rootNode].level) {
1033 < Back'),<= series.nodeMap[series.rootNode].level) { className += ' highcharts-above-level';
1034  
1035 < Back'),<= series.nodeMap[series.rootNode].level) { } else if (!this.node.isLeaf && !pick(options.interactByLeaf, !options.allowDrillToNode)) {
1036 < Back'),<= series.nodeMap[series.rootNode].level) { className += ' highcharts-internal-node-interactive';
1037  
1038 < Back'),<= series.nodeMap[series.rootNode].level) { } else if (!this.node.isLeaf) {
1039 < Back'),<= series.nodeMap[series.rootNode].level) { className += ' highcharts-internal-node';
1040 < Back'),<= series.nodeMap[series.rootNode].level) { }
1041 < Back'),<= series.nodeMap[series.rootNode].level) { return className;
1042 < Back'),<= series.nodeMap[series.rootNode].level) { },
1043 < Back'),<= series.nodeMap[series.rootNode].level) { isValid: function() {
1044 < Back'),<= series.nodeMap[series.rootNode].level) { return isNumber(this.value);
1045 < Back'),<= series.nodeMap[series.rootNode].level) { },
1046 < Back'),<= series.nodeMap[series.rootNode].level) { setState: function(state) {
1047 < Back'),<= series.nodeMap[series.rootNode].level) { H.Point.prototype.setState.call(this, state);
1048  
1049 < Back'),<= series.nodeMap[series.rootNode].level) { // Graphic does not exist when point is not visible.
1050 < Back'),<= series.nodeMap[series.rootNode].level) { if (this.graphic) {
1051 < Back'),<= series.nodeMap[series.rootNode].level) { this.graphic.attr({
1052 < Back'),<= series.nodeMap[series.rootNode].level) { zIndex: state === 'hover' ? 1 : 0
1053 < Back'),<= series.nodeMap[series.rootNode].level) { });
1054 < Back'),<= series.nodeMap[series.rootNode].level) { }
1055 < Back'),<= series.nodeMap[series.rootNode].level) { },
1056 < Back'),<= series.nodeMap[series.rootNode].level) { setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible
1057 < Back'),<= series.nodeMap[series.rootNode].level) { });
1058  
1059 < Back'),<= series.nodeMap[series.rootNode].level) { }(Highcharts));
1060 < Back'),<= series.nodeMap[series.rootNode].level) {}));