1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var fn_utils_1 = require("./utils/fn.utils");
|
4 | var Observable_1 = require("rxjs/Observable");
|
5 | var tree_types_1 = require("./tree.types");
|
6 | var uuidv4 = require("uuid/v4");
|
7 | var ChildrenLoadingState;
|
8 | (function (ChildrenLoadingState) {
|
9 | ChildrenLoadingState[ChildrenLoadingState["NotStarted"] = 0] = "NotStarted";
|
10 | ChildrenLoadingState[ChildrenLoadingState["Loading"] = 1] = "Loading";
|
11 | ChildrenLoadingState[ChildrenLoadingState["Completed"] = 2] = "Completed";
|
12 | })(ChildrenLoadingState || (ChildrenLoadingState = {}));
|
13 | var Tree = (function () {
|
14 | /**
|
15 | * Build an instance of Tree from an object implementing TreeModel interface.
|
16 | * @param {TreeModel} model - A model that is used to build a tree.
|
17 | * @param {Tree} [parent] - An optional parent if you want to build a tree from the model that should be a child of an existing Tree instance.
|
18 | * @param {boolean} [isBranch] - An option that makes a branch from created tree. Branch can have children.
|
19 | */
|
20 | function Tree(node, parent, isBranch) {
|
21 | if (parent === void 0) { parent = null; }
|
22 | if (isBranch === void 0) { isBranch = false; }
|
23 | var _this = this;
|
24 | this._childrenLoadingState = ChildrenLoadingState.NotStarted;
|
25 | this._childrenAsyncOnce = fn_utils_1.once(function () {
|
26 | return new Observable_1.Observable(function (observer) {
|
27 | setTimeout(function () {
|
28 | _this._childrenLoadingState = ChildrenLoadingState.Loading;
|
29 | _this._loadChildren(function (children) {
|
30 | _this._children = (children || []).map(function (child) { return new Tree(child, _this); });
|
31 | _this._childrenLoadingState = ChildrenLoadingState.Completed;
|
32 | observer.next(_this.children);
|
33 | observer.complete();
|
34 | });
|
35 | });
|
36 | });
|
37 | });
|
38 | this.buildTreeFromModel(node, parent, isBranch || Array.isArray(node.children));
|
39 | }
|
40 | // STATIC METHODS ----------------------------------------------------------------------------------------------------
|
41 | /**
|
42 | * Check that value passed is not empty (it doesn't consist of only whitespace symbols).
|
43 | * @param {string} value - A value that should be checked.
|
44 | * @returns {boolean} - A flag indicating that value is empty or not.
|
45 | * @static
|
46 | */
|
47 | // STATIC METHODS ----------------------------------------------------------------------------------------------------
|
48 | /**
|
49 | * Check that value passed is not empty (it doesn't consist of only whitespace symbols).
|
50 | * @param {string} value - A value that should be checked.
|
51 | * @returns {boolean} - A flag indicating that value is empty or not.
|
52 | * @static
|
53 | */
|
54 | Tree.isValueEmpty =
|
55 | // STATIC METHODS ----------------------------------------------------------------------------------------------------
|
56 | /**
|
57 | * Check that value passed is not empty (it doesn't consist of only whitespace symbols).
|
58 | * @param {string} value - A value that should be checked.
|
59 | * @returns {boolean} - A flag indicating that value is empty or not.
|
60 | * @static
|
61 | */
|
62 | function (value) {
|
63 | return fn_utils_1.isEmpty(fn_utils_1.trim(value));
|
64 | };
|
65 | /**
|
66 | * Check whether a given value can be considered RenamableNode.
|
67 | * @param {any} value - A value to check.
|
68 | * @returns {boolean} - A flag indicating whether given value is Renamable node or not.
|
69 | * @static
|
70 | */
|
71 | /**
|
72 | * Check whether a given value can be considered RenamableNode.
|
73 | * @param {any} value - A value to check.
|
74 | * @returns {boolean} - A flag indicating whether given value is Renamable node or not.
|
75 | * @static
|
76 | */
|
77 | Tree.isRenamable = /**
|
78 | * Check whether a given value can be considered RenamableNode.
|
79 | * @param {any} value - A value to check.
|
80 | * @returns {boolean} - A flag indicating whether given value is Renamable node or not.
|
81 | * @static
|
82 | */
|
83 | function (value) {
|
84 | return (fn_utils_1.has(value, 'setName') &&
|
85 | fn_utils_1.isFunction(value.setName) &&
|
86 | (fn_utils_1.has(value, 'toString') && fn_utils_1.isFunction(value.toString) && value.toString !== Object.toString));
|
87 | };
|
88 | Tree.cloneTreeShallow = function (origin) {
|
89 | var tree = new Tree(Object.assign({}, origin.node));
|
90 | tree._children = origin._children;
|
91 | return tree;
|
92 | };
|
93 | Tree.applyNewValueToRenamable = function (value, newValue) {
|
94 | var renamableValue = Object.assign({}, value);
|
95 | renamableValue.setName(newValue);
|
96 | return renamableValue;
|
97 | };
|
98 | Tree.prototype.buildTreeFromModel = function (model, parent, isBranch) {
|
99 | var _this = this;
|
100 | this.parent = parent;
|
101 | this.node = Object.assign(fn_utils_1.omit(model, 'children'), { settings: tree_types_1.TreeModelSettings.merge(model, fn_utils_1.get(parent, 'node')) }, { emitLoadNextLevel: model.emitLoadNextLevel === true });
|
102 | if (fn_utils_1.isFunction(this.node.loadChildren)) {
|
103 | this._loadChildren = this.node.loadChildren;
|
104 | }
|
105 | else {
|
106 | fn_utils_1.get(model, 'children', []).forEach(function (child, index) {
|
107 | _this._addChild(new Tree(child, _this), index);
|
108 | });
|
109 | }
|
110 | if (!Array.isArray(this._children)) {
|
111 | this._children = this.node.loadChildren || isBranch ? [] : null;
|
112 | }
|
113 | };
|
114 | Tree.prototype.hasDeferredChildren = function () {
|
115 | return typeof this._loadChildren === 'function';
|
116 | };
|
117 | /* Setting the children loading state to Loading since a request was dispatched to the client */
|
118 | /* Setting the children loading state to Loading since a request was dispatched to the client */
|
119 | Tree.prototype.loadingChildrenRequested = /* Setting the children loading state to Loading since a request was dispatched to the client */
|
120 | function () {
|
121 | this._childrenLoadingState = ChildrenLoadingState.Loading;
|
122 | };
|
123 | /**
|
124 | * Check whether children of the node are being loaded.
|
125 | * Makes sense only for nodes that define `loadChildren` function.
|
126 | * @returns {boolean} A flag indicating that children are being loaded.
|
127 | */
|
128 | /**
|
129 | * Check whether children of the node are being loaded.
|
130 | * Makes sense only for nodes that define `loadChildren` function.
|
131 | * @returns {boolean} A flag indicating that children are being loaded.
|
132 | */
|
133 | Tree.prototype.childrenAreBeingLoaded = /**
|
134 | * Check whether children of the node are being loaded.
|
135 | * Makes sense only for nodes that define `loadChildren` function.
|
136 | * @returns {boolean} A flag indicating that children are being loaded.
|
137 | */
|
138 | function () {
|
139 | return this._childrenLoadingState === ChildrenLoadingState.Loading;
|
140 | };
|
141 | /**
|
142 | * Check whether children of the node were loaded.
|
143 | * Makes sense only for nodes that define `loadChildren` function.
|
144 | * @returns {boolean} A flag indicating that children were loaded.
|
145 | */
|
146 | /**
|
147 | * Check whether children of the node were loaded.
|
148 | * Makes sense only for nodes that define `loadChildren` function.
|
149 | * @returns {boolean} A flag indicating that children were loaded.
|
150 | */
|
151 | Tree.prototype.childrenWereLoaded = /**
|
152 | * Check whether children of the node were loaded.
|
153 | * Makes sense only for nodes that define `loadChildren` function.
|
154 | * @returns {boolean} A flag indicating that children were loaded.
|
155 | */
|
156 | function () {
|
157 | return this._childrenLoadingState === ChildrenLoadingState.Completed;
|
158 | };
|
159 | Tree.prototype.canLoadChildren = function () {
|
160 | return (this._childrenLoadingState === ChildrenLoadingState.NotStarted &&
|
161 | this.foldingType === tree_types_1.FoldingType.Expanded &&
|
162 | !!this._loadChildren);
|
163 | };
|
164 | /**
|
165 | * Check whether children of the node should be loaded and not loaded yet.
|
166 | * Makes sense only for nodes that define `loadChildren` function.
|
167 | * @returns {boolean} A flag indicating that children should be loaded for the current node.
|
168 | */
|
169 | /**
|
170 | * Check whether children of the node should be loaded and not loaded yet.
|
171 | * Makes sense only for nodes that define `loadChildren` function.
|
172 | * @returns {boolean} A flag indicating that children should be loaded for the current node.
|
173 | */
|
174 | Tree.prototype.childrenShouldBeLoaded = /**
|
175 | * Check whether children of the node should be loaded and not loaded yet.
|
176 | * Makes sense only for nodes that define `loadChildren` function.
|
177 | * @returns {boolean} A flag indicating that children should be loaded for the current node.
|
178 | */
|
179 | function () {
|
180 | return !this.childrenWereLoaded() && (!!this._loadChildren || this.node.emitLoadNextLevel === true);
|
181 | };
|
182 | Object.defineProperty(Tree.prototype, "children", {
|
183 | /**
|
184 | * Get children of the current tree.
|
185 | * @returns {Tree[]} The children of the current tree.
|
186 | */
|
187 | get: /**
|
188 | * Get children of the current tree.
|
189 | * @returns {Tree[]} The children of the current tree.
|
190 | */
|
191 | function () {
|
192 | return this._children;
|
193 | },
|
194 | enumerable: true,
|
195 | configurable: true
|
196 | });
|
197 | Object.defineProperty(Tree.prototype, "childrenAsync", {
|
198 | /**
|
199 | * By getting value from this property you start process of loading node's children using `loadChildren` function.
|
200 | * Once children are loaded `loadChildren` function won't be called anymore and loaded for the first time children are emitted in case of subsequent calls.
|
201 | * @returns {Observable<Tree[]>} An observable which emits children once they are loaded.
|
202 | */
|
203 | get: /**
|
204 | * By getting value from this property you start process of loading node's children using `loadChildren` function.
|
205 | * Once children are loaded `loadChildren` function won't be called anymore and loaded for the first time children are emitted in case of subsequent calls.
|
206 | * @returns {Observable<Tree[]>} An observable which emits children once they are loaded.
|
207 | */
|
208 | function () {
|
209 | if (this.canLoadChildren()) {
|
210 | return this._childrenAsyncOnce();
|
211 | }
|
212 | return Observable_1.Observable.of(this.children);
|
213 | },
|
214 | enumerable: true,
|
215 | configurable: true
|
216 | });
|
217 | /**
|
218 | * By calling this method you start process of loading node's children using `loadChildren` function.
|
219 | */
|
220 | /**
|
221 | * By calling this method you start process of loading node's children using `loadChildren` function.
|
222 | */
|
223 | Tree.prototype.reloadChildren = /**
|
224 | * By calling this method you start process of loading node's children using `loadChildren` function.
|
225 | */
|
226 | function () {
|
227 | var _this = this;
|
228 | if (this.childrenShouldBeLoaded()) {
|
229 | this._childrenLoadingState = ChildrenLoadingState.Loading;
|
230 | this._loadChildren(function (children) {
|
231 | _this._children = children && children.map(function (child) { return new Tree(child, _this); });
|
232 | _this._childrenLoadingState = ChildrenLoadingState.Completed;
|
233 | });
|
234 | }
|
235 | };
|
236 | /**
|
237 | * By calling this method you will remove all current children of a treee and create new.
|
238 | */
|
239 | /**
|
240 | * By calling this method you will remove all current children of a treee and create new.
|
241 | */
|
242 | Tree.prototype.setChildren = /**
|
243 | * By calling this method you will remove all current children of a treee and create new.
|
244 | */
|
245 | function (children) {
|
246 | var _this = this;
|
247 | this._children = children && children.map(function (child) { return new Tree(child, _this); });
|
248 | if (this.childrenShouldBeLoaded()) {
|
249 | this._childrenLoadingState = ChildrenLoadingState.Completed;
|
250 | }
|
251 | };
|
252 | /**
|
253 | * Create a new node in the current tree.
|
254 | * @param {boolean} isBranch - A flag that indicates whether a new node should be a "Branch". "Leaf" node will be created by default
|
255 | * @param {TreeModel} model - Tree model of the new node which will be inserted. Empty node will be created by default and it will fire edit mode of this node
|
256 | * @returns {Tree} A newly created child node.
|
257 | */
|
258 | /**
|
259 | * Create a new node in the current tree.
|
260 | * @param {boolean} isBranch - A flag that indicates whether a new node should be a "Branch". "Leaf" node will be created by default
|
261 | * @param {TreeModel} model - Tree model of the new node which will be inserted. Empty node will be created by default and it will fire edit mode of this node
|
262 | * @returns {Tree} A newly created child node.
|
263 | */
|
264 | Tree.prototype.createNode = /**
|
265 | * Create a new node in the current tree.
|
266 | * @param {boolean} isBranch - A flag that indicates whether a new node should be a "Branch". "Leaf" node will be created by default
|
267 | * @param {TreeModel} model - Tree model of the new node which will be inserted. Empty node will be created by default and it will fire edit mode of this node
|
268 | * @returns {Tree} A newly created child node.
|
269 | */
|
270 | function (isBranch, model) {
|
271 | if (model === void 0) { model = { value: '' }; }
|
272 | var tree = new Tree(model, this, isBranch);
|
273 | if (!model.id) {
|
274 | tree.markAsNew();
|
275 | }
|
276 | tree.id = tree.id || uuidv4();
|
277 | if (this.childrenShouldBeLoaded() && !(this.childrenAreBeingLoaded() || this.childrenWereLoaded())) {
|
278 | return null;
|
279 | }
|
280 | if (this.isLeaf()) {
|
281 | return this.addSibling(tree);
|
282 | }
|
283 | else {
|
284 | return this.addChild(tree);
|
285 | }
|
286 | };
|
287 | Object.defineProperty(Tree.prototype, "value", {
|
288 | /**
|
289 | * Get the value of the current node
|
290 | * @returns {(string|RenamableNode)} The value of the node.
|
291 | */
|
292 | get: /**
|
293 | * Get the value of the current node
|
294 | * @returns {(string|RenamableNode)} The value of the node.
|
295 | */
|
296 | function () {
|
297 | return this.node.value;
|
298 | },
|
299 | /**
|
300 | * Set the value of the current node
|
301 | * @param {(string|RenamableNode)} value - The new value of the node.
|
302 | */
|
303 | set: /**
|
304 | * Set the value of the current node
|
305 | * @param {(string|RenamableNode)} value - The new value of the node.
|
306 | */
|
307 | function (value) {
|
308 | if (typeof value !== 'string' && !Tree.isRenamable(value)) {
|
309 | return;
|
310 | }
|
311 | var stringifiedValue = '' + value;
|
312 | if (Tree.isRenamable(this.value)) {
|
313 | this.node.value = Tree.applyNewValueToRenamable(this.value, stringifiedValue);
|
314 | }
|
315 | else {
|
316 | this.node.value = Tree.isValueEmpty(stringifiedValue) ? this.node.value : stringifiedValue;
|
317 | }
|
318 | },
|
319 | enumerable: true,
|
320 | configurable: true
|
321 | });
|
322 | Object.defineProperty(Tree.prototype, "checked", {
|
323 | get: function () {
|
324 | return !!fn_utils_1.get(this.node.settings, 'checked');
|
325 | },
|
326 | set: function (checked) {
|
327 | this.node.settings = Object.assign({}, this.node.settings, { checked: checked });
|
328 | },
|
329 | enumerable: true,
|
330 | configurable: true
|
331 | });
|
332 | Object.defineProperty(Tree.prototype, "checkedChildren", {
|
333 | get: function () {
|
334 | return this.hasLoadedChildern() ? this.children.filter(function (child) { return child.checked; }) : [];
|
335 | },
|
336 | enumerable: true,
|
337 | configurable: true
|
338 | });
|
339 | Object.defineProperty(Tree.prototype, "selectionAllowed", {
|
340 | get: function () {
|
341 | var value = fn_utils_1.get(this.node.settings, 'selectionAllowed');
|
342 | return fn_utils_1.isNil(value) ? true : !!value;
|
343 | },
|
344 | set: function (selectionAllowed) {
|
345 | this.node.settings = Object.assign({}, this.node.settings, { selectionAllowed: selectionAllowed });
|
346 | },
|
347 | enumerable: true,
|
348 | configurable: true
|
349 | });
|
350 | Tree.prototype.hasLoadedChildern = function () {
|
351 | return !fn_utils_1.isEmpty(this.children);
|
352 | };
|
353 | Tree.prototype.loadedChildrenAmount = function () {
|
354 | return fn_utils_1.size(this.children);
|
355 | };
|
356 | Tree.prototype.checkedChildrenAmount = function () {
|
357 | return fn_utils_1.size(this.checkedChildren);
|
358 | };
|
359 | /**
|
360 | * Add a sibling node for the current node. This won't work if the current node is a root.
|
361 | * @param {Tree} sibling - A node that should become a sibling.
|
362 | * @param [number] position - Position in which sibling will be inserted. By default it will be inserted at the last position in a parent.
|
363 | * @returns {Tree} A newly inserted sibling, or null if you are trying to make a sibling for the root.
|
364 | */
|
365 | /**
|
366 | * Add a sibling node for the current node. This won't work if the current node is a root.
|
367 | * @param {Tree} sibling - A node that should become a sibling.
|
368 | * @param [number] position - Position in which sibling will be inserted. By default it will be inserted at the last position in a parent.
|
369 | * @returns {Tree} A newly inserted sibling, or null if you are trying to make a sibling for the root.
|
370 | */
|
371 | Tree.prototype.addSibling = /**
|
372 | * Add a sibling node for the current node. This won't work if the current node is a root.
|
373 | * @param {Tree} sibling - A node that should become a sibling.
|
374 | * @param [number] position - Position in which sibling will be inserted. By default it will be inserted at the last position in a parent.
|
375 | * @returns {Tree} A newly inserted sibling, or null if you are trying to make a sibling for the root.
|
376 | */
|
377 | function (sibling, position) {
|
378 | if (Array.isArray(fn_utils_1.get(this.parent, 'children'))) {
|
379 | return this.parent.addChild(sibling, position);
|
380 | }
|
381 | return null;
|
382 | };
|
383 | /**
|
384 | * Add a child node for the current node.
|
385 | * @param {Tree} child - A node that should become a child.
|
386 | * @param [number] position - Position in which child will be inserted. By default it will be inserted at the last position in a parent.
|
387 | * @returns {Tree} A newly inserted child.
|
388 | */
|
389 | /**
|
390 | * Add a child node for the current node.
|
391 | * @param {Tree} child - A node that should become a child.
|
392 | * @param [number] position - Position in which child will be inserted. By default it will be inserted at the last position in a parent.
|
393 | * @returns {Tree} A newly inserted child.
|
394 | */
|
395 | Tree.prototype.addChild = /**
|
396 | * Add a child node for the current node.
|
397 | * @param {Tree} child - A node that should become a child.
|
398 | * @param [number] position - Position in which child will be inserted. By default it will be inserted at the last position in a parent.
|
399 | * @returns {Tree} A newly inserted child.
|
400 | */
|
401 | function (child, position) {
|
402 | var newborn = this._addChild(Tree.cloneTreeShallow(child), position);
|
403 | this._setFoldingType();
|
404 | if (this.isNodeCollapsed()) {
|
405 | this.switchFoldingType();
|
406 | }
|
407 | return newborn;
|
408 | };
|
409 | Tree.prototype._addChild = function (child, position) {
|
410 | if (position === void 0) { position = fn_utils_1.size(this._children) || 0; }
|
411 | child.parent = this;
|
412 | if (Array.isArray(this._children)) {
|
413 | this._children.splice(position, 0, child);
|
414 | }
|
415 | else {
|
416 | this._children = [child];
|
417 | }
|
418 | return child;
|
419 | };
|
420 | /**
|
421 | * Swap position of the current node with the given sibling. If node passed as a parameter is not a sibling - nothing happens.
|
422 | * @param {Tree} sibling - A sibling with which current node shold be swapped.
|
423 | */
|
424 | /**
|
425 | * Swap position of the current node with the given sibling. If node passed as a parameter is not a sibling - nothing happens.
|
426 | * @param {Tree} sibling - A sibling with which current node shold be swapped.
|
427 | */
|
428 | Tree.prototype.swapWithSibling = /**
|
429 | * Swap position of the current node with the given sibling. If node passed as a parameter is not a sibling - nothing happens.
|
430 | * @param {Tree} sibling - A sibling with which current node shold be swapped.
|
431 | */
|
432 | function (sibling) {
|
433 | if (!this.hasSibling(sibling)) {
|
434 | return;
|
435 | }
|
436 | var siblingIndex = sibling.positionInParent;
|
437 | var thisTreeIndex = this.positionInParent;
|
438 | this.parent._children[siblingIndex] = this;
|
439 | this.parent._children[thisTreeIndex] = sibling;
|
440 | };
|
441 | Object.defineProperty(Tree.prototype, "positionInParent", {
|
442 | /**
|
443 | * Get a node's position in its parent.
|
444 | * @returns {number} The position inside a parent.
|
445 | */
|
446 | get: /**
|
447 | * Get a node's position in its parent.
|
448 | * @returns {number} The position inside a parent.
|
449 | */
|
450 | function () {
|
451 | if (this.isRoot()) {
|
452 | return -1;
|
453 | }
|
454 | return this.parent.children ? this.parent.children.indexOf(this) : -1;
|
455 | },
|
456 | enumerable: true,
|
457 | configurable: true
|
458 | });
|
459 | /**
|
460 | * Check whether or not this tree is static.
|
461 | * @returns {boolean} A flag indicating whether or not this tree is static.
|
462 | */
|
463 | /**
|
464 | * Check whether or not this tree is static.
|
465 | * @returns {boolean} A flag indicating whether or not this tree is static.
|
466 | */
|
467 | Tree.prototype.isStatic = /**
|
468 | * Check whether or not this tree is static.
|
469 | * @returns {boolean} A flag indicating whether or not this tree is static.
|
470 | */
|
471 | function () {
|
472 | return fn_utils_1.get(this.node.settings, 'static', false);
|
473 | };
|
474 | /**
|
475 | * Check whether or not this tree has a left menu.
|
476 | * @returns {boolean} A flag indicating whether or not this tree has a left menu.
|
477 | */
|
478 | /**
|
479 | * Check whether or not this tree has a left menu.
|
480 | * @returns {boolean} A flag indicating whether or not this tree has a left menu.
|
481 | */
|
482 | Tree.prototype.hasLeftMenu = /**
|
483 | * Check whether or not this tree has a left menu.
|
484 | * @returns {boolean} A flag indicating whether or not this tree has a left menu.
|
485 | */
|
486 | function () {
|
487 | return !fn_utils_1.get(this.node.settings, 'static', false) && fn_utils_1.get(this.node.settings, 'leftMenu', false);
|
488 | };
|
489 | /**
|
490 | * Check whether or not this tree has a right menu.
|
491 | * @returns {boolean} A flag indicating whether or not this tree has a right menu.
|
492 | */
|
493 | /**
|
494 | * Check whether or not this tree has a right menu.
|
495 | * @returns {boolean} A flag indicating whether or not this tree has a right menu.
|
496 | */
|
497 | Tree.prototype.hasRightMenu = /**
|
498 | * Check whether or not this tree has a right menu.
|
499 | * @returns {boolean} A flag indicating whether or not this tree has a right menu.
|
500 | */
|
501 | function () {
|
502 | return !fn_utils_1.get(this.node.settings, 'static', false) && fn_utils_1.get(this.node.settings, 'rightMenu', false);
|
503 | };
|
504 | /**
|
505 | * Check whether this tree is "Leaf" or not.
|
506 | * @returns {boolean} A flag indicating whether or not this tree is a "Leaf".
|
507 | */
|
508 | /**
|
509 | * Check whether this tree is "Leaf" or not.
|
510 | * @returns {boolean} A flag indicating whether or not this tree is a "Leaf".
|
511 | */
|
512 | Tree.prototype.isLeaf = /**
|
513 | * Check whether this tree is "Leaf" or not.
|
514 | * @returns {boolean} A flag indicating whether or not this tree is a "Leaf".
|
515 | */
|
516 | function () {
|
517 | return !this.isBranch();
|
518 | };
|
519 | Object.defineProperty(Tree.prototype, "menuItems", {
|
520 | /**
|
521 | * Get menu items of the current tree.
|
522 | * @returns {NodeMenuItem[]} The menu items of the current tree.
|
523 | */
|
524 | get: /**
|
525 | * Get menu items of the current tree.
|
526 | * @returns {NodeMenuItem[]} The menu items of the current tree.
|
527 | */
|
528 | function () {
|
529 | return fn_utils_1.get(this.node.settings, 'menuItems');
|
530 | },
|
531 | enumerable: true,
|
532 | configurable: true
|
533 | });
|
534 | /**
|
535 | * Check whether or not this tree has a custom menu.
|
536 | * @returns {boolean} A flag indicating whether or not this tree has a custom menu.
|
537 | */
|
538 | /**
|
539 | * Check whether or not this tree has a custom menu.
|
540 | * @returns {boolean} A flag indicating whether or not this tree has a custom menu.
|
541 | */
|
542 | Tree.prototype.hasCustomMenu = /**
|
543 | * Check whether or not this tree has a custom menu.
|
544 | * @returns {boolean} A flag indicating whether or not this tree has a custom menu.
|
545 | */
|
546 | function () {
|
547 | return !this.isStatic() && !!fn_utils_1.get(this.node.settings, 'menuItems', false);
|
548 | };
|
549 | /**
|
550 | * Check whether this tree is "Branch" or not. "Branch" is a node that has children.
|
551 | * @returns {boolean} A flag indicating whether or not this tree is a "Branch".
|
552 | */
|
553 | /**
|
554 | * Check whether this tree is "Branch" or not. "Branch" is a node that has children.
|
555 | * @returns {boolean} A flag indicating whether or not this tree is a "Branch".
|
556 | */
|
557 | Tree.prototype.isBranch = /**
|
558 | * Check whether this tree is "Branch" or not. "Branch" is a node that has children.
|
559 | * @returns {boolean} A flag indicating whether or not this tree is a "Branch".
|
560 | */
|
561 | function () {
|
562 | return this.node.emitLoadNextLevel === true || Array.isArray(this._children);
|
563 | };
|
564 | /**
|
565 | * Check whether this tree has children.
|
566 | * @returns {boolean} A flag indicating whether or not this tree has children.
|
567 | */
|
568 | /**
|
569 | * Check whether this tree has children.
|
570 | * @returns {boolean} A flag indicating whether or not this tree has children.
|
571 | */
|
572 | Tree.prototype.hasChildren = /**
|
573 | * Check whether this tree has children.
|
574 | * @returns {boolean} A flag indicating whether or not this tree has children.
|
575 | */
|
576 | function () {
|
577 | return !fn_utils_1.isEmpty(this._children) || this.childrenShouldBeLoaded();
|
578 | };
|
579 | /**
|
580 | * Check whether this tree is a root or not. The root is the tree (node) that doesn't have parent (or technically its parent is null).
|
581 | * @returns {boolean} A flag indicating whether or not this tree is the root.
|
582 | */
|
583 | /**
|
584 | * Check whether this tree is a root or not. The root is the tree (node) that doesn't have parent (or technically its parent is null).
|
585 | * @returns {boolean} A flag indicating whether or not this tree is the root.
|
586 | */
|
587 | Tree.prototype.isRoot = /**
|
588 | * Check whether this tree is a root or not. The root is the tree (node) that doesn't have parent (or technically its parent is null).
|
589 | * @returns {boolean} A flag indicating whether or not this tree is the root.
|
590 | */
|
591 | function () {
|
592 | return fn_utils_1.isNil(this.parent);
|
593 | };
|
594 | /**
|
595 | * Check whether provided tree is a sibling of the current tree. Sibling trees (nodes) are the trees that have the same parent.
|
596 | * @param {Tree} tree - A tree that should be tested on a siblingness.
|
597 | * @returns {boolean} A flag indicating whether or not provided tree is the sibling of the current one.
|
598 | */
|
599 | /**
|
600 | * Check whether provided tree is a sibling of the current tree. Sibling trees (nodes) are the trees that have the same parent.
|
601 | * @param {Tree} tree - A tree that should be tested on a siblingness.
|
602 | * @returns {boolean} A flag indicating whether or not provided tree is the sibling of the current one.
|
603 | */
|
604 | Tree.prototype.hasSibling = /**
|
605 | * Check whether provided tree is a sibling of the current tree. Sibling trees (nodes) are the trees that have the same parent.
|
606 | * @param {Tree} tree - A tree that should be tested on a siblingness.
|
607 | * @returns {boolean} A flag indicating whether or not provided tree is the sibling of the current one.
|
608 | */
|
609 | function (tree) {
|
610 | return !this.isRoot() && fn_utils_1.includes(this.parent.children, tree);
|
611 | };
|
612 | /**
|
613 | * Check whether provided tree is a child of the current tree.
|
614 | * This method tests that provided tree is a <strong>direct</strong> child of the current tree.
|
615 | * @param {Tree} tree - A tree that should be tested (child candidate).
|
616 | * @returns {boolean} A flag indicating whether provided tree is a child or not.
|
617 | */
|
618 | /**
|
619 | * Check whether provided tree is a child of the current tree.
|
620 | * This method tests that provided tree is a <strong>direct</strong> child of the current tree.
|
621 | * @param {Tree} tree - A tree that should be tested (child candidate).
|
622 | * @returns {boolean} A flag indicating whether provided tree is a child or not.
|
623 | */
|
624 | Tree.prototype.hasChild = /**
|
625 | * Check whether provided tree is a child of the current tree.
|
626 | * This method tests that provided tree is a <strong>direct</strong> child of the current tree.
|
627 | * @param {Tree} tree - A tree that should be tested (child candidate).
|
628 | * @returns {boolean} A flag indicating whether provided tree is a child or not.
|
629 | */
|
630 | function (tree) {
|
631 | return fn_utils_1.includes(this._children, tree);
|
632 | };
|
633 | /**
|
634 | * Remove given tree from the current tree.
|
635 | * The given tree will be removed only in case it is a direct child of the current tree (@see {@link hasChild}).
|
636 | * @param {Tree} tree - A tree that should be removed.
|
637 | */
|
638 | /**
|
639 | * Remove given tree from the current tree.
|
640 | * The given tree will be removed only in case it is a direct child of the current tree (@see {@link hasChild}).
|
641 | * @param {Tree} tree - A tree that should be removed.
|
642 | */
|
643 | Tree.prototype.removeChild = /**
|
644 | * Remove given tree from the current tree.
|
645 | * The given tree will be removed only in case it is a direct child of the current tree (@see {@link hasChild}).
|
646 | * @param {Tree} tree - A tree that should be removed.
|
647 | */
|
648 | function (tree) {
|
649 | if (!this.hasChildren()) {
|
650 | return;
|
651 | }
|
652 | var childIndex = this._children.findIndex(function (child) { return child === tree; });
|
653 | if (childIndex >= 0) {
|
654 | this._children.splice(childIndex, 1);
|
655 | }
|
656 | this._setFoldingType();
|
657 | };
|
658 | /**
|
659 | * Remove current tree from its parent.
|
660 | */
|
661 | /**
|
662 | * Remove current tree from its parent.
|
663 | */
|
664 | Tree.prototype.removeItselfFromParent = /**
|
665 | * Remove current tree from its parent.
|
666 | */
|
667 | function () {
|
668 | if (!this.parent) {
|
669 | return;
|
670 | }
|
671 | this.parent.removeChild(this);
|
672 | };
|
673 | /**
|
674 | * Switch folding type of the current tree. "Leaf" node cannot switch its folding type cause it doesn't have children, hence nothing to fold.
|
675 | * If node is a "Branch" and it is expanded, then by invoking current method state of the tree should be switched to "collapsed" and vice versa.
|
676 | */
|
677 | /**
|
678 | * Switch folding type of the current tree. "Leaf" node cannot switch its folding type cause it doesn't have children, hence nothing to fold.
|
679 | * If node is a "Branch" and it is expanded, then by invoking current method state of the tree should be switched to "collapsed" and vice versa.
|
680 | */
|
681 | Tree.prototype.switchFoldingType = /**
|
682 | * Switch folding type of the current tree. "Leaf" node cannot switch its folding type cause it doesn't have children, hence nothing to fold.
|
683 | * If node is a "Branch" and it is expanded, then by invoking current method state of the tree should be switched to "collapsed" and vice versa.
|
684 | */
|
685 | function () {
|
686 | if (this.isLeaf() || !this.hasChildren()) {
|
687 | return;
|
688 | }
|
689 | this.disableCollapseOnInit();
|
690 | this.node._foldingType = this.isNodeExpanded() ? tree_types_1.FoldingType.Collapsed : tree_types_1.FoldingType.Expanded;
|
691 | };
|
692 | /**
|
693 | * Check that tree is expanded.
|
694 | * @returns {boolean} A flag indicating whether current tree is expanded. Always returns false for the "Leaf" tree and for an empty tree.
|
695 | */
|
696 | /**
|
697 | * Check that tree is expanded.
|
698 | * @returns {boolean} A flag indicating whether current tree is expanded. Always returns false for the "Leaf" tree and for an empty tree.
|
699 | */
|
700 | Tree.prototype.isNodeExpanded = /**
|
701 | * Check that tree is expanded.
|
702 | * @returns {boolean} A flag indicating whether current tree is expanded. Always returns false for the "Leaf" tree and for an empty tree.
|
703 | */
|
704 | function () {
|
705 | return this.foldingType === tree_types_1.FoldingType.Expanded;
|
706 | };
|
707 | /**
|
708 | * Check that tree is collapsed.
|
709 | * @returns {boolean} A flag indicating whether current tree is collapsed. Always returns false for the "Leaf" tree and for an empty tree.
|
710 | */
|
711 | /**
|
712 | * Check that tree is collapsed.
|
713 | * @returns {boolean} A flag indicating whether current tree is collapsed. Always returns false for the "Leaf" tree and for an empty tree.
|
714 | */
|
715 | Tree.prototype.isNodeCollapsed = /**
|
716 | * Check that tree is collapsed.
|
717 | * @returns {boolean} A flag indicating whether current tree is collapsed. Always returns false for the "Leaf" tree and for an empty tree.
|
718 | */
|
719 | function () {
|
720 | return this.foldingType === tree_types_1.FoldingType.Collapsed;
|
721 | };
|
722 | /**
|
723 | * Set a current folding type: expanded, collapsed or leaf.
|
724 | */
|
725 | /**
|
726 | * Set a current folding type: expanded, collapsed or leaf.
|
727 | */
|
728 | Tree.prototype._setFoldingType = /**
|
729 | * Set a current folding type: expanded, collapsed or leaf.
|
730 | */
|
731 | function () {
|
732 | if (this.childrenShouldBeLoaded()) {
|
733 | this.node._foldingType = tree_types_1.FoldingType.Collapsed;
|
734 | }
|
735 | else if (this._children && !fn_utils_1.isEmpty(this._children)) {
|
736 | this.node._foldingType = this.isCollapsedOnInit() ? tree_types_1.FoldingType.Collapsed : tree_types_1.FoldingType.Expanded;
|
737 | }
|
738 | else if (Array.isArray(this._children)) {
|
739 | this.node._foldingType = tree_types_1.FoldingType.Empty;
|
740 | }
|
741 | else {
|
742 | this.node._foldingType = tree_types_1.FoldingType.Leaf;
|
743 | }
|
744 | };
|
745 | Object.defineProperty(Tree.prototype, "foldingType", {
|
746 | /**
|
747 | * Get a current folding type: expanded, collapsed or leaf.
|
748 | * @returns {FoldingType} A folding type of the current tree.
|
749 | */
|
750 | get: /**
|
751 | * Get a current folding type: expanded, collapsed or leaf.
|
752 | * @returns {FoldingType} A folding type of the current tree.
|
753 | */
|
754 | function () {
|
755 | if (!this.node._foldingType) {
|
756 | this._setFoldingType();
|
757 | }
|
758 | return this.node._foldingType;
|
759 | },
|
760 | enumerable: true,
|
761 | configurable: true
|
762 | });
|
763 | Object.defineProperty(Tree.prototype, "foldingCssClass", {
|
764 | /**
|
765 | * Get a css class for element which displayes folding state - expanded, collapsed or leaf
|
766 | * @returns {string} A string icontaining css class (classes)
|
767 | */
|
768 | get: /**
|
769 | * Get a css class for element which displayes folding state - expanded, collapsed or leaf
|
770 | * @returns {string} A string icontaining css class (classes)
|
771 | */
|
772 | function () {
|
773 | return this.getCssClassesFromSettings() || this.foldingType.cssClass;
|
774 | },
|
775 | enumerable: true,
|
776 | configurable: true
|
777 | });
|
778 | Tree.prototype.getCssClassesFromSettings = function () {
|
779 | if (!this.node._foldingType) {
|
780 | this._setFoldingType();
|
781 | }
|
782 | if (this.node._foldingType === tree_types_1.FoldingType.Collapsed) {
|
783 | return fn_utils_1.get(this.node.settings, 'cssClasses.collapsed', null);
|
784 | }
|
785 | else if (this.node._foldingType === tree_types_1.FoldingType.Expanded) {
|
786 | return fn_utils_1.get(this.node.settings, 'cssClasses.expanded', null);
|
787 | }
|
788 | else if (this.node._foldingType === tree_types_1.FoldingType.Empty) {
|
789 | return fn_utils_1.get(this.node.settings, 'cssClasses.empty', null);
|
790 | }
|
791 | return fn_utils_1.get(this.node.settings, 'cssClasses.leaf', null);
|
792 | };
|
793 | Object.defineProperty(Tree.prototype, "nodeTemplate", {
|
794 | /**
|
795 | * Get a html template to render before every node's name.
|
796 | * @returns {string} A string representing a html template.
|
797 | */
|
798 | get: /**
|
799 | * Get a html template to render before every node's name.
|
800 | * @returns {string} A string representing a html template.
|
801 | */
|
802 | function () {
|
803 | return this.getTemplateFromSettings();
|
804 | },
|
805 | enumerable: true,
|
806 | configurable: true
|
807 | });
|
808 | Tree.prototype.getTemplateFromSettings = function () {
|
809 | if (this.isLeaf()) {
|
810 | return fn_utils_1.get(this.node.settings, 'templates.leaf', '');
|
811 | }
|
812 | else {
|
813 | return fn_utils_1.get(this.node.settings, 'templates.node', '');
|
814 | }
|
815 | };
|
816 | Object.defineProperty(Tree.prototype, "leftMenuTemplate", {
|
817 | /**
|
818 | * Get a html template to render for an element activatin left menu of a node.
|
819 | * @returns {string} A string representing a html template.
|
820 | */
|
821 | get: /**
|
822 | * Get a html template to render for an element activatin left menu of a node.
|
823 | * @returns {string} A string representing a html template.
|
824 | */
|
825 | function () {
|
826 | if (this.hasLeftMenu()) {
|
827 | return fn_utils_1.get(this.node.settings, 'templates.leftMenu', '<span></span>');
|
828 | }
|
829 | return '';
|
830 | },
|
831 | enumerable: true,
|
832 | configurable: true
|
833 | });
|
834 | Tree.prototype.disableCollapseOnInit = function () {
|
835 | if (this.node.settings) {
|
836 | this.node.settings.isCollapsedOnInit = false;
|
837 | }
|
838 | };
|
839 | Tree.prototype.isCollapsedOnInit = function () {
|
840 | return !!fn_utils_1.get(this.node.settings, 'isCollapsedOnInit');
|
841 | };
|
842 | Tree.prototype.keepNodesInDOM = function () {
|
843 | return fn_utils_1.get(this.node.settings, 'keepNodesInDOM');
|
844 | };
|
845 | /**
|
846 | * Check that current tree is newly created (added by user via menu for example). Tree that was built from the TreeModel is not marked as new.
|
847 | * @returns {boolean} A flag whether the tree is new.
|
848 | */
|
849 | /**
|
850 | * Check that current tree is newly created (added by user via menu for example). Tree that was built from the TreeModel is not marked as new.
|
851 | * @returns {boolean} A flag whether the tree is new.
|
852 | */
|
853 | Tree.prototype.isNew = /**
|
854 | * Check that current tree is newly created (added by user via menu for example). Tree that was built from the TreeModel is not marked as new.
|
855 | * @returns {boolean} A flag whether the tree is new.
|
856 | */
|
857 | function () {
|
858 | return this.node._status === tree_types_1.TreeStatus.New;
|
859 | };
|
860 | Object.defineProperty(Tree.prototype, "id", {
|
861 | get: function () {
|
862 | return fn_utils_1.get(this.node, 'id');
|
863 | },
|
864 | set: function (id) {
|
865 | this.node.id = id;
|
866 | },
|
867 | enumerable: true,
|
868 | configurable: true
|
869 | });
|
870 | /**
|
871 | * Mark current tree as new (@see {@link isNew}).
|
872 | */
|
873 | /**
|
874 | * Mark current tree as new (@see {@link isNew}).
|
875 | */
|
876 | Tree.prototype.markAsNew = /**
|
877 | * Mark current tree as new (@see {@link isNew}).
|
878 | */
|
879 | function () {
|
880 | this.node._status = tree_types_1.TreeStatus.New;
|
881 | };
|
882 | /**
|
883 | * Check that current tree is being renamed (it is in the process of its value renaming initiated by a user).
|
884 | * @returns {boolean} A flag whether the tree is being renamed.
|
885 | */
|
886 | /**
|
887 | * Check that current tree is being renamed (it is in the process of its value renaming initiated by a user).
|
888 | * @returns {boolean} A flag whether the tree is being renamed.
|
889 | */
|
890 | Tree.prototype.isBeingRenamed = /**
|
891 | * Check that current tree is being renamed (it is in the process of its value renaming initiated by a user).
|
892 | * @returns {boolean} A flag whether the tree is being renamed.
|
893 | */
|
894 | function () {
|
895 | return this.node._status === tree_types_1.TreeStatus.IsBeingRenamed;
|
896 | };
|
897 | /**
|
898 | * Mark current tree as being renamed (@see {@link isBeingRenamed}).
|
899 | */
|
900 | /**
|
901 | * Mark current tree as being renamed (@see {@link isBeingRenamed}).
|
902 | */
|
903 | Tree.prototype.markAsBeingRenamed = /**
|
904 | * Mark current tree as being renamed (@see {@link isBeingRenamed}).
|
905 | */
|
906 | function () {
|
907 | this.node._status = tree_types_1.TreeStatus.IsBeingRenamed;
|
908 | };
|
909 | /**
|
910 | * Check that current tree is modified (for example it was renamed).
|
911 | * @returns {boolean} A flag whether the tree is modified.
|
912 | */
|
913 | /**
|
914 | * Check that current tree is modified (for example it was renamed).
|
915 | * @returns {boolean} A flag whether the tree is modified.
|
916 | */
|
917 | Tree.prototype.isModified = /**
|
918 | * Check that current tree is modified (for example it was renamed).
|
919 | * @returns {boolean} A flag whether the tree is modified.
|
920 | */
|
921 | function () {
|
922 | return this.node._status === tree_types_1.TreeStatus.Modified;
|
923 | };
|
924 | /**
|
925 | * Mark current tree as modified (@see {@link isModified}).
|
926 | */
|
927 | /**
|
928 | * Mark current tree as modified (@see {@link isModified}).
|
929 | */
|
930 | Tree.prototype.markAsModified = /**
|
931 | * Mark current tree as modified (@see {@link isModified}).
|
932 | */
|
933 | function () {
|
934 | this.node._status = tree_types_1.TreeStatus.Modified;
|
935 | };
|
936 | /**
|
937 | * Makes a clone of an underlying TreeModel instance
|
938 | * @returns {TreeModel} a clone of an underlying TreeModel instance
|
939 | */
|
940 | /**
|
941 | * Makes a clone of an underlying TreeModel instance
|
942 | * @returns {TreeModel} a clone of an underlying TreeModel instance
|
943 | */
|
944 | Tree.prototype.toTreeModel = /**
|
945 | * Makes a clone of an underlying TreeModel instance
|
946 | * @returns {TreeModel} a clone of an underlying TreeModel instance
|
947 | */
|
948 | function () {
|
949 | var model = fn_utils_1.defaultsDeep(this.isLeaf() ? {} : { children: [] }, this.node);
|
950 | if (this.children) {
|
951 | this.children.forEach(function (child) {
|
952 | model.children.push(child.toTreeModel());
|
953 | });
|
954 | }
|
955 | return model;
|
956 | };
|
957 | return Tree;
|
958 | }());
|
959 | exports.Tree = Tree;
|
960 | //# sourceMappingURL=tree.js.map |
\ | No newline at end of file |