UNPKG

42.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var fn_utils_1 = require("./utils/fn.utils");
4var Observable_1 = require("rxjs/Observable");
5var tree_types_1 = require("./tree.types");
6var uuidv4 = require("uuid/v4");
7var 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 = {}));
13var 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}());
959exports.Tree = Tree;
960//# sourceMappingURL=tree.js.map
\No newline at end of file