UNPKG

13.5 kBJavaScriptView Raw
1import { a as __extends } from './tslib.es6-863e3717.js';
2import { U as Utils } from './Utils-5f9f1f09.js';
3import { select, event, selectAll, mouse } from 'd3';
4import { C as Component } from './Component-5b66527b.js';
5
6var HierarchyNode = /** @class */ (function () {
7 function HierarchyNode(name, level) {
8 this.children = [];
9 this.isExpanded = false;
10 this.isSelected = false;
11 this.isLeaf = false;
12 this.childrenInFilter = false;
13 this.selfInFilter = false;
14 this.color = function () { return null; };
15 this.click = function (n) { };
16 this.isLeafParent = false; // used in the event of context menut to denote that we should use a context menu for children
17 this.name = name;
18 this.level = level;
19 this.markedName = name;
20 }
21 HierarchyNode.prototype.filter = function (filterText) {
22 var regExp = new RegExp(filterText, 'i');
23 var isInFilter = function (node) {
24 var childrenInFilter = node.children.reduce(function (p, c) {
25 p = isInFilter(c) || p;
26 return p;
27 }, false);
28 var selfInFilter = regExp.test(node.name);
29 node.markedName = selfInFilter ? Utils.mark(filterText, node.name) : node.name;
30 if (node.parent != null)
31 node.parent.childrenInFilter = (selfInFilter || childrenInFilter) && filterText.length > 0;
32 node.selfInFilter = selfInFilter && filterText.length > 0;
33 node.childrenInFilter = childrenInFilter && filterText.length > 0;
34 return childrenInFilter || selfInFilter;
35 };
36 isInFilter(this);
37 };
38 HierarchyNode.prototype.traverse = function (condition) {
39 var traversal = [];
40 if (condition(this))
41 traversal.push(this);
42 this.children.forEach(function (n) {
43 traversal = traversal.concat(n.traverse(condition));
44 });
45 return traversal;
46 };
47 HierarchyNode.prototype.colorify = function (el) {
48 if (this.isLeaf && this.isSelected && this.color(this))
49 el.style('background-color', this.color(this));
50 if (!this.isSelected && this.isLeaf)
51 el.style('background-color', null);
52 };
53 return HierarchyNode;
54}());
55
56var Hierarchy = /** @class */ (function (_super) {
57 __extends(Hierarchy, _super);
58 function Hierarchy(renderTarget) {
59 var _this = _super.call(this, renderTarget) || this;
60 _this.filterText = '';
61 _this.withContextMenu = false;
62 _this.expandCollapseList = function (node, el, isFromClick) {
63 if (isFromClick === void 0) { isFromClick = false; }
64 _this.closeContextMenu();
65 if (el.classed('tsi-expanded') && !(_this.withContextMenu && node.isLeafParent)) {
66 el.selectAll('ul').remove();
67 el.classed('tsi-expanded', false);
68 node.isExpanded = false;
69 }
70 else {
71 if (_this.withContextMenu && node.isLeafParent) {
72 if (_this.clickedNode != el.node()) {
73 _this.clickedNode = el.node();
74 _this.contextMenu = _this.hierarchyList.append('div');
75 node.children.filter(function (n) { return n.name[0] !== '~'; }).forEach(function (n) {
76 _this.contextMenu.append('div').text("" + n.name).on('click', function () { return n.click(n); });
77 });
78 _this.contextMenu.append('div').classed('tsi-break', true);
79 node.children.filter(function (n) { return n.name[0] === '~'; }).forEach(function (n) {
80 var noTildeName = n.name.slice(1);
81 _this.contextMenu.append('div').text("" + noTildeName).on('click', function () { return n.click(n); });
82 });
83 _this.contextMenu.classed('tsi-hierarchyContextMenu', true);
84 var mouseWrapper_1 = mouse(_this.hierarchyList.node());
85 var mouseElt_1 = mouse(el.node());
86 _this.contextMenu.attr('style', function () { return "top: " + (mouseWrapper_1[1] - mouseElt_1[1]) + "px"; });
87 el.classed('tsi-resultSelected', true);
88 _this.hierarchyList.selectAll('.tsi-noPad').on('scroll', function () { _this.closeContextMenu(); });
89 }
90 else {
91 _this.clickedNode = null;
92 }
93 }
94 else {
95 var list = el.append('ul');
96 node.children.forEach(function (n) {
97 if (isFromClick || n.selfInFilter || n.childrenInFilter || (node.isExpanded && _this.filterText.length == 0)) {
98 var self = _this;
99 var clickMethod = function () {
100 if (n.isLeaf) {
101 var parent = n.parent;
102 while (parent != this.root) {
103 parent.isExpanded = true;
104 parent = parent.parent;
105 }
106 n.isSelected = !n.isSelected;
107 n.click(n);
108 var selector = select(this);
109 n.colorify(selector);
110 selector.classed('tsi-selected', n.isSelected);
111 }
112 else {
113 self.expandCollapseList(n, select(this), true);
114 }
115 event.stopPropagation();
116 };
117 var li = list.append('li').classed('tsi-leaf', n.isLeaf)
118 .classed('tsi-leafParent', n.isLeafParent && _this.withContextMenu)
119 .classed('tsi-selected', n.isSelected).on('click', clickMethod);
120 li.append('span').classed('tsi-caret', true).attr('style', "left: " + (n.level - 1) * 18 + "px");
121 li.append('span').classed('tsi-markedName', true).html(n.markedName) // known unsafe usage of .html
122 .attr('style', "padding-left: " + (40 + (n.level - 1) * 18 - (n.isLeafParent && _this.withContextMenu ? 16 : 0)) + "px")
123 .attr('title', n.isLeafParent && _this.withContextMenu ? n.name : '');
124 n.colorify(li);
125 if ((n.isExpanded || n.childrenInFilter) && !n.isLeaf) {
126 _this.expandCollapseList(n, li);
127 }
128 }
129 });
130 node.isExpanded = (node.isExpanded || isFromClick) || (node == _this.root);
131 el.classed('tsi-expanded', true);
132 }
133 }
134 };
135 return _this;
136 }
137 Hierarchy.prototype.render = function (data, options) {
138 var _this = this;
139 var self = this;
140 var targetElement = select(this.renderTarget).classed('tsi-hierarchy', true);
141 targetElement.html('');
142 this.chartOptions.setOptions(options);
143 _super.prototype.themify.call(this, targetElement, this.chartOptions.theme);
144 this.withContextMenu = this.chartOptions.withContextMenu;
145 this.root = this.buildTree(data);
146 this.root.isExpanded = true;
147 select("html").on("click." + Utils.guid(), function () {
148 if (_this.clickedNode && event.target != _this.clickedNode && _this.contextMenu) {
149 _this.closeContextMenu();
150 _this.clickedNode = null;
151 }
152 });
153 var inputDebounceTimeout;
154 var filter = targetElement.append('div').classed('tsi-filterWrapper', true).append('input').attr('placeholder', 'Search...').on('input', function () {
155 var _this = this;
156 clearTimeout(inputDebounceTimeout);
157 inputDebounceTimeout = setTimeout(function () {
158 self.filterText = _this.value.trim();
159 if (self.filterText.length == 1)
160 return; // quick return for small sets
161 var splitFilterText = self.filterText.split('/');
162 self.root.filter(splitFilterText[0]);
163 if (splitFilterText.length > 1) {
164 for (var i = 1; i < splitFilterText.length; i++) {
165 if (splitFilterText[i].length) {
166 var nodesInFilter = self.root.traverse(function (n) { return n.selfInFilter; });
167 nodesInFilter.forEach(function (n) {
168 var markedName = n.markedName;
169 n.filter(splitFilterText[i], false);
170 n.markedName = markedName;
171 });
172 nodesInFilter.forEach(function (n) {
173 if (!n.childrenInFilter)
174 n.selfInFilter = false;
175 });
176 }
177 }
178 }
179 list.selectAll('ul').remove();
180 list.classed('tsi-expanded', false);
181 self.root.childrenInFilter = self.root.childrenInFilter || self.filterText.length == 0;
182 if (self.root.childrenInFilter == false)
183 list.append('ul').append('div').text(self.getString('No filter results'));
184 else
185 self.expandCollapseList(self.root, list, false);
186 list.select('ul').classed('tsi-noPad', true);
187 }, 250);
188 });
189 var navTabs = targetElement.append('div').classed('tsi-navTabWrapper', true);
190 var allTab = navTabs.append('div').classed('tsi-navTab tsi-selected', true).text(this.getString('All hierarchies'));
191 var selectedTab = navTabs.append('div').classed('tsi-navTab', true).text(this.getString('Selected'));
192 var list = targetElement.append('div').classed('tsi-hierarchyList', true);
193 this.hierarchyList = list;
194 allTab.on('click', function () {
195 if (!allTab.classed('tsi-selected')) {
196 allTab.classed('tsi-selected', true);
197 selectedTab.classed('tsi-selected', false);
198 list.html('').classed('tsi-expanded', false);
199 _this.expandCollapseList(_this.root, list, true);
200 list.select('ul').classed('tsi-noPad', true);
201 filter.attr('disabled', null);
202 }
203 });
204 selectedTab.on('click', function () {
205 if (!selectedTab.classed('tsi-selected')) {
206 allTab.classed('tsi-selected', false);
207 selectedTab.classed('tsi-selected', true);
208 list.html('');
209 var ul = list.append('ul').classed('tsi-noPad', true);
210 var leafs = _this.root.traverse(function (n) { return n.isSelected; });
211 leafs.forEach(function (n) {
212 var li = ul.append('li').classed('tsi-leaf', n.isLeaf).classed('tsi-selected', n.isSelected).on('click', function () {
213 n.isSelected = !n.isSelected;
214 select(this).classed('tsi-selected', n.isSelected);
215 n.click(n);
216 n.colorify(select(this));
217 });
218 li.append('span').text(n.name).classed('tsi-markedName', true);
219 n.colorify(li);
220 });
221 filter.attr('disabled', true);
222 }
223 });
224 this.expandCollapseList(this.root, list, false);
225 list.select('ul').classed('tsi-noPad', true);
226 };
227 Hierarchy.prototype.buildTree = function (data) {
228 var traverse = function (data, key, level, parent) {
229 if (parent === void 0) { parent = null; }
230 var node = new HierarchyNode(key, level);
231 node.parent = parent;
232 if (data.hasOwnProperty('$leaf')) {
233 node.isLeaf = true;
234 if (data.hasOwnProperty('click'))
235 node.click = data.click;
236 if (data.hasOwnProperty('color'))
237 node.color = data.color;
238 node.parent.isLeafParent = true;
239 }
240 else {
241 Object.keys(data).sort().forEach(function (k) {
242 node.children.push(traverse(data[k], k, level + 1, node));
243 });
244 }
245 return node;
246 };
247 return traverse(data, '', 0);
248 };
249 Hierarchy.prototype.closeContextMenu = function () {
250 if (this.contextMenu) {
251 this.contextMenu.remove();
252 }
253 selectAll('.tsi-resultSelected').classed('tsi-resultSelected', false);
254 };
255 return Hierarchy;
256}(Component));
257
258export { Hierarchy as H };