Tree.js
3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* *
*
* (c) 2016-2019 Highsoft AS
*
* Authors: Jon Arild Nygard
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
/* eslint no-console: 0 */
'use strict';
import H from '../parts/Globals.js';
import U from '../parts/Utilities.js';
var isNumber = U.isNumber;
var extend = H.extend, pick = H.pick, isFunction = function (x) {
return typeof x === 'function';
};
/**
* Creates an object map from parent id to childrens index.
*
* @private
* @function Highcharts.Tree#getListOfParents
*
* @param {Array<*>} data
* List of points set in options. `Array<*>.parent`is parent id of point.
*
* @param {Array<string>} ids
* List of all point ids.
*
* @return {Highcharts.Dictionary<Array<*>>}
* Map from parent id to children index in data
*/
var getListOfParents = function (data, ids) {
var listOfParents = data.reduce(function (prev, curr) {
var parent = pick(curr.parent, '');
if (prev[parent] === undefined) {
prev[parent] = [];
}
prev[parent].push(curr);
return prev;
}, {}), parents = Object.keys(listOfParents);
// If parent does not exist, hoist parent to root of tree.
parents.forEach(function (parent, list) {
var children = listOfParents[parent];
if ((parent !== '') && (ids.indexOf(parent) === -1)) {
children.forEach(function (child) {
list[''].push(child);
});
delete list[parent];
}
});
return listOfParents;
};
var getNode = function (id, parent, level, data, mapOfIdToChildren, options) {
var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = {
data: data,
depth: level - 1,
id: id,
level: level,
parent: parent
}, start, end, children;
// Allow custom logic before the children has been created.
if (isFunction(before)) {
before(node, options);
}
// Call getNode recursively on the children. Calulate the height of the
// node, and the number of descendants.
children = ((mapOfIdToChildren[id] || [])).map(function (child) {
var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ?
childStart :
child.end);
// Start should be the lowest child.start.
start = ((!isNumber(start) || childStart < start) ?
childStart :
start);
// End should be the largest child.end.
// If child is milestone, then use start as end.
end = ((!isNumber(end) || childEnd > end) ?
childEnd :
end);
descendants = descendants + 1 + node.descendants;
height = Math.max(node.height + 1, height);
return node;
});
// Calculate start and end for point if it is not already explicitly set.
if (data) {
data.start = pick(data.start, start);
data.end = pick(data.end, end);
}
extend(node, {
children: children,
descendants: descendants,
height: height
});
// Allow custom logic after the children has been created.
if (isFunction(after)) {
after(node, options);
}
return node;
};
var getTree = function (data, options) {
var ids = data.map(function (d) {
return d.id;
}), mapOfIdToChildren = getListOfParents(data, ids);
return getNode('', null, 1, null, mapOfIdToChildren, options);
};
var Tree = {
getListOfParents: getListOfParents,
getNode: getNode,
getTree: getTree
};
export default Tree;