tree-element 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -6
- package/lib/animation.d.ts +2 -2
- package/lib/animation.d.ts.map +1 -1
- package/lib/animation.js +13 -9
- package/lib/animation.js.map +1 -1
- package/lib/dataLoader.d.ts +1 -0
- package/lib/dataLoader.d.ts.map +1 -1
- package/lib/dataLoader.js +8 -0
- package/lib/dataLoader.js.map +1 -1
- package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
- package/lib/dragAndDropHandler/dragElement.js +2 -1
- package/lib/dragAndDropHandler/dragElement.js.map +1 -1
- package/lib/dragAndDropHandler/index.d.ts.map +1 -1
- package/lib/dragAndDropHandler/index.js +56 -65
- package/lib/dragAndDropHandler/index.js.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.js +16 -15
- package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
- package/lib/elementsRenderer.d.ts +5 -1
- package/lib/elementsRenderer.d.ts.map +1 -1
- package/lib/elementsRenderer.js +62 -39
- package/lib/elementsRenderer.js.map +1 -1
- package/lib/events.d.ts +44 -11
- package/lib/events.d.ts.map +1 -1
- package/lib/index.d.ts +31 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +162 -122
- package/lib/index.js.map +1 -1
- package/lib/keyHandler.d.ts +11 -5
- package/lib/keyHandler.d.ts.map +1 -1
- package/lib/keyHandler.js +87 -33
- package/lib/keyHandler.js.map +1 -1
- package/lib/methodTypes.d.ts +2 -2
- package/lib/methodTypes.d.ts.map +1 -1
- package/lib/mouseHandler.d.ts +1 -1
- package/lib/mouseHandler.d.ts.map +1 -1
- package/lib/mouseHandler.js +10 -7
- package/lib/mouseHandler.js.map +1 -1
- package/lib/node.d.ts +45 -15
- package/lib/node.d.ts.map +1 -1
- package/lib/node.js +136 -139
- package/lib/node.js.map +1 -1
- package/lib/nodeElement/folderElement.d.ts +1 -1
- package/lib/nodeElement/folderElement.d.ts.map +1 -1
- package/lib/nodeElement/folderElement.js +46 -57
- package/lib/nodeElement/folderElement.js.map +1 -1
- package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
- package/lib/nodeElement/ghostDropHint.js +8 -4
- package/lib/nodeElement/ghostDropHint.js.map +1 -1
- package/lib/nodeElement/index.d.ts.map +1 -1
- package/lib/nodeElement/index.js +6 -6
- package/lib/nodeElement/index.js.map +1 -1
- package/lib/nodeUtils.d.ts.map +1 -1
- package/lib/nodeUtils.js +1 -1
- package/lib/nodeUtils.js.map +1 -1
- package/lib/options.d.ts +23 -6
- package/lib/options.d.ts.map +1 -1
- package/lib/requestUrl.d.ts +0 -1
- package/lib/requestUrl.d.ts.map +1 -1
- package/lib/requestUrl.js +4 -22
- package/lib/requestUrl.js.map +1 -1
- package/lib/saveStateHandler.d.ts.map +1 -1
- package/lib/saveStateHandler.js +21 -41
- package/lib/saveStateHandler.js.map +1 -1
- package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/containerScrollParent.js +3 -8
- package/lib/scrollHandler/containerScrollParent.js.map +1 -1
- package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/createScrollParent.js +4 -5
- package/lib/scrollHandler/createScrollParent.js.map +1 -1
- package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/documentScrollParent.js +3 -9
- package/lib/scrollHandler/documentScrollParent.js.map +1 -1
- package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/scrollParent.js +19 -17
- package/lib/scrollHandler/scrollParent.js.map +1 -1
- package/lib/selectNodeHandler.d.ts +3 -1
- package/lib/selectNodeHandler.d.ts.map +1 -1
- package/lib/selectNodeHandler.js +27 -37
- package/lib/selectNodeHandler.js.map +1 -1
- package/lib/setDefaultOptions.d.ts +3 -0
- package/lib/setDefaultOptions.d.ts.map +1 -1
- package/lib/setDefaultOptions.js +21 -20
- package/lib/setDefaultOptions.js.map +1 -1
- package/lib/util.d.ts.map +1 -1
- package/lib/util.js +1 -1
- package/lib/util.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +44 -35
- package/src/animation.ts +13 -11
- package/src/dataLoader.ts +11 -0
- package/src/dragAndDropHandler/dragElement.ts +2 -1
- package/src/dragAndDropHandler/index.ts +70 -75
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +18 -16
- package/src/elementsRenderer.ts +76 -46
- package/src/events.ts +44 -11
- package/src/index.ts +210 -150
- package/src/keyHandler.ts +95 -41
- package/src/methodTypes.ts +3 -3
- package/src/mouseHandler.ts +10 -7
- package/src/node.ts +155 -148
- package/src/nodeElement/folderElement.ts +54 -63
- package/src/nodeElement/ghostDropHint.ts +4 -2
- package/src/nodeElement/index.ts +9 -15
- package/src/nodeUtils.ts +1 -1
- package/src/options.ts +23 -6
- package/src/requestUrl.ts +4 -25
- package/src/saveStateHandler.ts +29 -43
- package/src/scrollHandler/containerScrollParent.ts +3 -9
- package/src/scrollHandler/createScrollParent.ts +1 -2
- package/src/scrollHandler/documentScrollParent.ts +5 -11
- package/src/scrollHandler/scrollParent.ts +29 -25
- package/src/selectNodeHandler.ts +34 -38
- package/src/setDefaultOptions.ts +31 -19
- package/src/util.ts +1 -2
- package/src/version.ts +1 -1
- package/tree_element.css +87 -69
- package/tree_element.debug.js +717 -659
- package/tree_element.debug.js.map +1 -1
- package/tree_element.js +2 -2
- package/tree_element.js.map +1 -1
package/tree_element.debug.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Tree-element 0.
|
|
2
|
+
Tree-element 0.3.1
|
|
3
3
|
|
|
4
4
|
Copyright 2026 Marco Braak
|
|
5
5
|
|
|
@@ -78,12 +78,17 @@ var TreeElement = (function () {
|
|
|
78
78
|
async _loadFromUrl(url, node) {
|
|
79
79
|
let element = node?.element ?? this._treeElement;
|
|
80
80
|
element.classList.add(this._classNames.loading);
|
|
81
|
+
|
|
82
|
+
// Tell screen readers that the children of the folder are loading
|
|
83
|
+
let titleSpan = node ? this._getTitleSpan(element) : null;
|
|
84
|
+
titleSpan?.setAttribute("aria-busy", "true");
|
|
81
85
|
this._triggerEvent("tree.loading_data", {
|
|
82
86
|
element,
|
|
83
87
|
node
|
|
84
88
|
});
|
|
85
89
|
let stopLoading = () => {
|
|
86
90
|
element.classList.remove(this._classNames.loading);
|
|
91
|
+
titleSpan?.removeAttribute("aria-busy");
|
|
87
92
|
this._triggerEvent("tree.loaded_data", {
|
|
88
93
|
element,
|
|
89
94
|
node
|
|
@@ -119,6 +124,9 @@ var TreeElement = (function () {
|
|
|
119
124
|
});
|
|
120
125
|
});
|
|
121
126
|
}
|
|
127
|
+
_getTitleSpan(element) {
|
|
128
|
+
return element.querySelector(`:scope > .${this._classNames.element} > .${this._classNames.title}`);
|
|
129
|
+
}
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
// Get the top position of the HTML element.
|
|
@@ -166,7 +174,7 @@ var TreeElement = (function () {
|
|
|
166
174
|
this._offsetX = offsetX;
|
|
167
175
|
this._offsetY = offsetY;
|
|
168
176
|
this._element = this._createElement(nodeName, autoEscape, classNames);
|
|
169
|
-
treeElement.
|
|
177
|
+
treeElement.append(this._element);
|
|
170
178
|
}
|
|
171
179
|
_move(pageX, pageY) {
|
|
172
180
|
this._element.style.left = `${pageX - this._offsetX}px`;
|
|
@@ -181,6 +189,7 @@ var TreeElement = (function () {
|
|
|
181
189
|
if (autoEscape) {
|
|
182
190
|
element.textContent = nodeName;
|
|
183
191
|
} else {
|
|
192
|
+
// eslint-disable-next-line no-unsanitized/property -- the user opted out of escaping with autoEscape: false
|
|
184
193
|
element.innerHTML = nodeName;
|
|
185
194
|
}
|
|
186
195
|
element.style.position = "absolute";
|
|
@@ -217,25 +226,26 @@ var TreeElement = (function () {
|
|
|
217
226
|
handleClosedFolder(node, nextNode, element);
|
|
218
227
|
}
|
|
219
228
|
}
|
|
220
|
-
if (mustIterateInside) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
if (!mustIterateInside) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
let childrenLength = node.children.length;
|
|
233
|
+
for (let i of node.children.keys()) {
|
|
234
|
+
let child = node.children[i];
|
|
235
|
+
if (child) {
|
|
236
|
+
if (i === childrenLength - 1) {
|
|
237
|
+
iterate(child, null);
|
|
238
|
+
} else {
|
|
239
|
+
let nextChild = node.children[i + 1];
|
|
240
|
+
if (nextChild) {
|
|
241
|
+
iterate(child, nextChild);
|
|
232
242
|
}
|
|
233
243
|
}
|
|
234
|
-
});
|
|
235
|
-
if (node.is_open && element) {
|
|
236
|
-
handleAfterOpenFolder(node, nextNode);
|
|
237
244
|
}
|
|
238
245
|
}
|
|
246
|
+
if (node.is_open && element) {
|
|
247
|
+
handleAfterOpenFolder(node, nextNode);
|
|
248
|
+
}
|
|
239
249
|
};
|
|
240
250
|
iterate(tree, null);
|
|
241
251
|
};
|
|
@@ -419,10 +429,8 @@ var TreeElement = (function () {
|
|
|
419
429
|
return null;
|
|
420
430
|
}
|
|
421
431
|
let nodeElement = this._getNodeElement(element);
|
|
422
|
-
if (nodeElement && this._onCanMove) {
|
|
423
|
-
|
|
424
|
-
nodeElement = null;
|
|
425
|
-
}
|
|
432
|
+
if (nodeElement && this._onCanMove && !this._onCanMove(nodeElement._node)) {
|
|
433
|
+
nodeElement = null;
|
|
426
434
|
}
|
|
427
435
|
this._currentItem = nodeElement;
|
|
428
436
|
return this._currentItem != null;
|
|
@@ -453,10 +461,8 @@ var TreeElement = (function () {
|
|
|
453
461
|
this._stopOpenFolderTimer();
|
|
454
462
|
this._hoveredArea = area;
|
|
455
463
|
}
|
|
456
|
-
if (!area) {
|
|
457
|
-
|
|
458
|
-
this._onDragMove(this._currentItem._node, positionInfo.originalEvent);
|
|
459
|
-
}
|
|
464
|
+
if (!area && this._onDragMove) {
|
|
465
|
+
this._onDragMove(this._currentItem._node, positionInfo.originalEvent);
|
|
460
466
|
}
|
|
461
467
|
return true;
|
|
462
468
|
}
|
|
@@ -494,35 +500,32 @@ var TreeElement = (function () {
|
|
|
494
500
|
this._currentItem = null;
|
|
495
501
|
}
|
|
496
502
|
this._isDragging = false;
|
|
497
|
-
if (!this._hoveredArea && currentItem) {
|
|
498
|
-
|
|
499
|
-
this._onDragStop(currentItem._node, positionInfo.originalEvent);
|
|
500
|
-
}
|
|
503
|
+
if (!this._hoveredArea && currentItem && this._onDragStop) {
|
|
504
|
+
this._onDragStop(currentItem._node, positionInfo.originalEvent);
|
|
501
505
|
}
|
|
502
506
|
return false;
|
|
503
507
|
}
|
|
504
508
|
_refresh() {
|
|
505
509
|
this._removeHitAreas();
|
|
506
|
-
if (this._currentItem) {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
510
|
+
if (!this._currentItem) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
let currentNode = this._currentItem._node;
|
|
514
|
+
this._generateHitAreas(currentNode);
|
|
515
|
+
this._currentItem = this._getNodeElementForNode(currentNode);
|
|
516
|
+
if (this._isDragging) {
|
|
517
|
+
this._currentItem._element.classList.add(this._classNames.moving);
|
|
513
518
|
}
|
|
514
519
|
}
|
|
515
520
|
_canMoveToArea(area, currentItem) {
|
|
516
|
-
|
|
517
|
-
return true;
|
|
518
|
-
}
|
|
519
|
-
return this._onCanMoveTo(currentItem._node, area.node, area.position);
|
|
521
|
+
return this._onCanMoveTo ? this._onCanMoveTo(currentItem._node, area.node, area.position) : true;
|
|
520
522
|
}
|
|
521
523
|
_clear() {
|
|
522
|
-
if (this._dragElement) {
|
|
523
|
-
|
|
524
|
-
this._dragElement = null;
|
|
524
|
+
if (!this._dragElement) {
|
|
525
|
+
return;
|
|
525
526
|
}
|
|
527
|
+
this._dragElement._remove();
|
|
528
|
+
this._dragElement = null;
|
|
526
529
|
}
|
|
527
530
|
_findHoveredArea(x, y) {
|
|
528
531
|
let dimensions = this._getTreeDimensions();
|
|
@@ -532,20 +535,13 @@ var TreeElement = (function () {
|
|
|
532
535
|
return binarySearch(this._hitAreas, area => {
|
|
533
536
|
if (y < area.top) {
|
|
534
537
|
return 1;
|
|
535
|
-
} else if (y > area.bottom) {
|
|
536
|
-
return -1;
|
|
537
|
-
} else {
|
|
538
|
-
return 0;
|
|
539
538
|
}
|
|
539
|
+
return y > area.bottom ? -1 : 0;
|
|
540
540
|
});
|
|
541
541
|
}
|
|
542
542
|
_generateHitAreas(currentNode) {
|
|
543
543
|
let tree = this._getTree();
|
|
544
|
-
|
|
545
|
-
this._hitAreas = [];
|
|
546
|
-
} else {
|
|
547
|
-
this._hitAreas = generateHitAreas(tree, currentNode, this._getTreeDimensions().bottom);
|
|
548
|
-
}
|
|
544
|
+
this._hitAreas = tree ? generateHitAreas(tree, currentNode, this._getTreeDimensions().bottom) : [];
|
|
549
545
|
}
|
|
550
546
|
_getTreeDimensions() {
|
|
551
547
|
// Return the dimensions of the tree. Add a margin to the bottom to allow
|
|
@@ -561,36 +557,40 @@ var TreeElement = (function () {
|
|
|
561
557
|
};
|
|
562
558
|
}
|
|
563
559
|
|
|
564
|
-
/*
|
|
560
|
+
/*
|
|
561
|
+
Move the dragged node to the selected position in the tree.
|
|
562
|
+
*/
|
|
565
563
|
_moveItem(positionInfo) {
|
|
566
|
-
if (this._currentItem && this._hoveredArea?.position && this._canMoveToArea(this._hoveredArea, this._currentItem)) {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
564
|
+
if (!(this._currentItem && this._hoveredArea?.position && this._canMoveToArea(this._hoveredArea, this._currentItem))) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
let movedNode = this._currentItem._node;
|
|
568
|
+
let targetNode = this._hoveredArea.node;
|
|
569
|
+
let position = this._hoveredArea.position;
|
|
570
|
+
let previousParent = movedNode.parent;
|
|
571
|
+
if (position === "inside") {
|
|
572
|
+
this._hoveredArea.node.is_open = true;
|
|
573
|
+
}
|
|
574
|
+
let doMove = () => {
|
|
575
|
+
let tree = this._getTree();
|
|
576
|
+
if (!tree) {
|
|
577
|
+
return;
|
|
573
578
|
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
originalEvent: positionInfo.originalEvent,
|
|
587
|
-
position,
|
|
588
|
-
previousParent,
|
|
589
|
-
targetNode
|
|
590
|
-
}
|
|
591
|
-
})) {
|
|
592
|
-
doMove();
|
|
579
|
+
tree.moveNode(movedNode, targetNode, position);
|
|
580
|
+
this._treeElement.textContent = "";
|
|
581
|
+
this._refreshElements(null);
|
|
582
|
+
};
|
|
583
|
+
if (this._triggerEvent("tree.move", {
|
|
584
|
+
moveInfo: {
|
|
585
|
+
doMove,
|
|
586
|
+
movedNode,
|
|
587
|
+
originalEvent: positionInfo.originalEvent,
|
|
588
|
+
position,
|
|
589
|
+
previousParent,
|
|
590
|
+
targetNode
|
|
593
591
|
}
|
|
592
|
+
})) {
|
|
593
|
+
doMove();
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
596
|
_mustCaptureElement(element) {
|
|
@@ -626,10 +626,11 @@ var TreeElement = (function () {
|
|
|
626
626
|
}
|
|
627
627
|
}
|
|
628
628
|
_stopOpenFolderTimer() {
|
|
629
|
-
if (this._openFolderTimer) {
|
|
630
|
-
|
|
631
|
-
this._openFolderTimer = null;
|
|
629
|
+
if (!this._openFolderTimer) {
|
|
630
|
+
return;
|
|
632
631
|
}
|
|
632
|
+
clearTimeout(this._openFolderTimer);
|
|
633
|
+
this._openFolderTimer = null;
|
|
633
634
|
}
|
|
634
635
|
_updateDropHint() {
|
|
635
636
|
if (!this._hoveredArea) {
|
|
@@ -645,7 +646,7 @@ var TreeElement = (function () {
|
|
|
645
646
|
}
|
|
646
647
|
}
|
|
647
648
|
|
|
648
|
-
let isInt = n =>
|
|
649
|
+
let isInt = n => Number.isInteger(n);
|
|
649
650
|
let getBoolString = value => value ? "true" : "false";
|
|
650
651
|
|
|
651
652
|
/* Renders the tree to html.
|
|
@@ -661,21 +662,25 @@ var TreeElement = (function () {
|
|
|
661
662
|
*/
|
|
662
663
|
class ElementsRenderer {
|
|
663
664
|
constructor({
|
|
665
|
+
_ariaLabel: ariaLabel,
|
|
666
|
+
_ariaLabelledBy: ariaLabelledBy,
|
|
664
667
|
_autoEscape: autoEscape,
|
|
665
668
|
_buttonLeft: buttonLeft,
|
|
666
669
|
_classNames: classNames,
|
|
667
|
-
_closedIcon: closedIcon,
|
|
670
|
+
_closedIcon: closedIcon = "-",
|
|
668
671
|
_dragAndDrop: dragAndDrop,
|
|
669
672
|
_getTree: getTree,
|
|
670
673
|
_htmlElement: htmlElement,
|
|
671
674
|
_isNodeSelected: isNodeSelected,
|
|
672
675
|
_onCreateLi: onCreateLi,
|
|
673
|
-
_openedIcon: openedIcon,
|
|
676
|
+
_openedIcon: openedIcon = "+",
|
|
674
677
|
_rtl: rtl,
|
|
675
678
|
_setNodeElement: setNodeElement,
|
|
676
679
|
_showEmptyFolder: showEmptyFolder,
|
|
677
680
|
_tabIndex: tabIndex
|
|
678
681
|
}) {
|
|
682
|
+
this._ariaLabel = ariaLabel;
|
|
683
|
+
this._ariaLabelledBy = ariaLabelledBy;
|
|
679
684
|
this._autoEscape = autoEscape;
|
|
680
685
|
this._buttonLeft = buttonLeft;
|
|
681
686
|
this._classNames = classNames;
|
|
@@ -688,8 +693,8 @@ var TreeElement = (function () {
|
|
|
688
693
|
this._setNodeElement = setNodeElement;
|
|
689
694
|
this._showEmptyFolder = showEmptyFolder;
|
|
690
695
|
this._tabIndex = tabIndex;
|
|
691
|
-
this._openedIconElement = this._createButtonElement(openedIcon
|
|
692
|
-
this._closedIconElement = this._createButtonElement(closedIcon
|
|
696
|
+
this._openedIconElement = this._createButtonElement(openedIcon);
|
|
697
|
+
this._closedIconElement = this._createButtonElement(closedIcon);
|
|
693
698
|
this._rootUlTemplate = this._createUlTemplate(true);
|
|
694
699
|
this._groupUlTemplate = this._createUlTemplate(false);
|
|
695
700
|
this._nodeTemplate = this._createNodeTemplate();
|
|
@@ -708,10 +713,7 @@ var TreeElement = (function () {
|
|
|
708
713
|
* null when the folder is not rendered or has no children.
|
|
709
714
|
*/
|
|
710
715
|
_renderChildren(node) {
|
|
711
|
-
|
|
712
|
-
return null;
|
|
713
|
-
}
|
|
714
|
-
return this._createDomElements(node.element, node.children, false, node.getLevel() + 1);
|
|
716
|
+
return !node.element || !node.hasChildren() ? null : this._createDomElements(node.element, node.children, false, node.getLevel() + 1);
|
|
715
717
|
}
|
|
716
718
|
_renderFromNode(node) {
|
|
717
719
|
if (!node.element) {
|
|
@@ -743,21 +745,19 @@ var TreeElement = (function () {
|
|
|
743
745
|
_createButtonElement(value) {
|
|
744
746
|
if (typeof value === "string") {
|
|
745
747
|
let template = document.createElement("template");
|
|
748
|
+
// eslint-disable-next-line no-unsanitized/property -- icon options are documented to accept html
|
|
746
749
|
template.innerHTML = value;
|
|
747
750
|
return template.content;
|
|
748
|
-
} else if (value.nodeType) {
|
|
749
|
-
return value;
|
|
750
|
-
} else {
|
|
751
|
-
return undefined;
|
|
752
751
|
}
|
|
752
|
+
return value.nodeType ? value : undefined;
|
|
753
753
|
}
|
|
754
754
|
_createDomElements(element, children, isRootNode, level) {
|
|
755
755
|
let template = isRootNode ? this._rootUlTemplate : this._groupUlTemplate;
|
|
756
756
|
let ul = template.cloneNode();
|
|
757
|
-
element.
|
|
757
|
+
element.append(ul);
|
|
758
758
|
for (let child of children) {
|
|
759
759
|
let li = this._createLi(child, level);
|
|
760
|
-
ul.
|
|
760
|
+
ul.append(li);
|
|
761
761
|
if (this._mustRenderChildren(child)) {
|
|
762
762
|
this._createDomElements(li, child.children, false, level + 1);
|
|
763
763
|
}
|
|
@@ -770,19 +770,20 @@ var TreeElement = (function () {
|
|
|
770
770
|
if (isSelected) {
|
|
771
771
|
li.classList.add(this._classNames.selected);
|
|
772
772
|
}
|
|
773
|
-
if (node.is_loading) {
|
|
774
|
-
li.classList.add(this._classNames.loading);
|
|
775
|
-
}
|
|
776
773
|
|
|
777
|
-
// li > div > [
|
|
774
|
+
// li > div > [toggler], title span, [toggler]
|
|
778
775
|
let div = li.firstChild;
|
|
779
776
|
let titleSpan = div.childNodes[this._buttonLeft ? 1 : 0];
|
|
780
777
|
this._fillTitleSpan(titleSpan, node.name, isSelected, level);
|
|
778
|
+
if (node.is_loading) {
|
|
779
|
+
li.classList.add(this._classNames.loading);
|
|
780
|
+
titleSpan.setAttribute("aria-busy", "true");
|
|
781
|
+
}
|
|
781
782
|
return li;
|
|
782
783
|
}
|
|
783
784
|
|
|
784
785
|
/* Template for a folder <li>:
|
|
785
|
-
* li > div > [
|
|
786
|
+
* li > div > [toggler], title span, [toggler]
|
|
786
787
|
* The toggler icon and the aria-expanded attribute depend on the open
|
|
787
788
|
* state, so there is a template for each.
|
|
788
789
|
*/
|
|
@@ -794,23 +795,25 @@ var TreeElement = (function () {
|
|
|
794
795
|
let li = this._createLiTemplate(liClasses.join(" "));
|
|
795
796
|
let div = li.firstChild;
|
|
796
797
|
|
|
797
|
-
//
|
|
798
|
-
|
|
799
|
-
|
|
798
|
+
// The toggler is hidden from screen readers: the icon is decoration, and
|
|
799
|
+
// aria-expanded on the treeitem has the open state.
|
|
800
|
+
let toggler = document.createElement("span");
|
|
801
|
+
toggler.className = this._getButtonClasses(isOpen);
|
|
802
|
+
toggler.setAttribute("aria-hidden", "true");
|
|
800
803
|
let iconElement = isOpen ? this._openedIconElement : this._closedIconElement;
|
|
801
804
|
if (iconElement) {
|
|
802
|
-
|
|
805
|
+
toggler.append(iconElement.cloneNode(true));
|
|
803
806
|
}
|
|
804
807
|
if (this._buttonLeft) {
|
|
805
|
-
div.
|
|
808
|
+
div.append(toggler);
|
|
806
809
|
}
|
|
807
810
|
|
|
808
811
|
// title span
|
|
809
812
|
let titleSpan = this._createTitleSpanTemplate(true);
|
|
810
813
|
titleSpan.setAttribute("aria-expanded", getBoolString(isOpen));
|
|
811
|
-
div.
|
|
814
|
+
div.append(titleSpan);
|
|
812
815
|
if (!this._buttonLeft) {
|
|
813
|
-
div.
|
|
816
|
+
div.append(toggler);
|
|
814
817
|
}
|
|
815
818
|
return li;
|
|
816
819
|
}
|
|
@@ -830,7 +833,9 @@ var TreeElement = (function () {
|
|
|
830
833
|
return li;
|
|
831
834
|
}
|
|
832
835
|
|
|
833
|
-
/*
|
|
836
|
+
/*
|
|
837
|
+
Create the outer part of a <li> template: li > div
|
|
838
|
+
*/
|
|
834
839
|
_createLiTemplate(liClasses) {
|
|
835
840
|
let li = document.createElement("li");
|
|
836
841
|
li.className = liClasses;
|
|
@@ -838,7 +843,7 @@ var TreeElement = (function () {
|
|
|
838
843
|
let div = document.createElement("div");
|
|
839
844
|
div.className = `${this._classNames.element} ${this._classNames.common}`;
|
|
840
845
|
div.setAttribute("role", "none");
|
|
841
|
-
li.
|
|
846
|
+
li.append(div);
|
|
842
847
|
return li;
|
|
843
848
|
}
|
|
844
849
|
_createNodeLi(node, level, isSelected) {
|
|
@@ -854,11 +859,13 @@ var TreeElement = (function () {
|
|
|
854
859
|
return li;
|
|
855
860
|
}
|
|
856
861
|
|
|
857
|
-
/*
|
|
862
|
+
/*
|
|
863
|
+
Template for a <li> without children: li > div > title span
|
|
864
|
+
*/
|
|
858
865
|
_createNodeTemplate() {
|
|
859
866
|
let li = this._createLiTemplate(this._classNames.common);
|
|
860
867
|
let div = li.firstChild;
|
|
861
|
-
div.
|
|
868
|
+
div.append(this._createTitleSpanTemplate(false));
|
|
862
869
|
return li;
|
|
863
870
|
}
|
|
864
871
|
_createTitleSpanTemplate(isFolder) {
|
|
@@ -871,20 +878,25 @@ var TreeElement = (function () {
|
|
|
871
878
|
titleSpan.className = classes;
|
|
872
879
|
titleSpan.setAttribute("role", "treeitem");
|
|
873
880
|
titleSpan.setAttribute("aria-selected", "false");
|
|
881
|
+
|
|
882
|
+
// Every node is focusable, but only the tab stop is in the tab order
|
|
883
|
+
if (this._tabIndex !== undefined) {
|
|
884
|
+
titleSpan.setAttribute("tabindex", "-1");
|
|
885
|
+
}
|
|
874
886
|
return titleSpan;
|
|
875
887
|
}
|
|
876
888
|
_createUlTemplate(isRootNode) {
|
|
877
889
|
let classString;
|
|
878
890
|
let role;
|
|
879
|
-
if (
|
|
880
|
-
classString = "";
|
|
881
|
-
role = "group";
|
|
882
|
-
} else {
|
|
891
|
+
if (isRootNode) {
|
|
883
892
|
classString = this._classNames.tree;
|
|
884
893
|
role = "tree";
|
|
885
894
|
if (this._rtl) {
|
|
886
895
|
classString += ` ${this._classNames.rtl}`;
|
|
887
896
|
}
|
|
897
|
+
} else {
|
|
898
|
+
classString = "";
|
|
899
|
+
role = "group";
|
|
888
900
|
}
|
|
889
901
|
if (this._dragAndDrop) {
|
|
890
902
|
classString += ` ${this._classNames.dnd}`;
|
|
@@ -892,23 +904,33 @@ var TreeElement = (function () {
|
|
|
892
904
|
let ul = document.createElement("ul");
|
|
893
905
|
ul.className = `${this._classNames.common} ${classString}`;
|
|
894
906
|
ul.setAttribute("role", role);
|
|
907
|
+
if (isRootNode) {
|
|
908
|
+
if (this._ariaLabel !== undefined) {
|
|
909
|
+
ul.setAttribute("aria-label", this._ariaLabel);
|
|
910
|
+
}
|
|
911
|
+
if (this._ariaLabelledBy !== undefined) {
|
|
912
|
+
ul.setAttribute("aria-labelledby", this._ariaLabelledBy);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
895
915
|
return ul;
|
|
896
916
|
}
|
|
897
917
|
|
|
898
|
-
/*
|
|
918
|
+
/*
|
|
919
|
+
Set the parts of a cloned title span that differ per node
|
|
920
|
+
*/
|
|
899
921
|
_fillTitleSpan(titleSpan, nodeName, isSelected, level) {
|
|
900
|
-
titleSpan.setAttribute("aria-
|
|
901
|
-
titleSpan.setAttribute("aria-level", `${level}`);
|
|
922
|
+
titleSpan.setAttribute("aria-level", String(level));
|
|
902
923
|
if (isSelected) {
|
|
903
924
|
titleSpan.setAttribute("aria-selected", "true");
|
|
904
925
|
let tabIndex = this._tabIndex;
|
|
905
926
|
if (tabIndex !== undefined) {
|
|
906
|
-
titleSpan.setAttribute("tabindex",
|
|
927
|
+
titleSpan.setAttribute("tabindex", String(tabIndex));
|
|
907
928
|
}
|
|
908
929
|
}
|
|
909
930
|
if (this._autoEscape) {
|
|
910
931
|
titleSpan.textContent = nodeName;
|
|
911
932
|
} else {
|
|
933
|
+
// eslint-disable-next-line no-unsanitized/property -- the user opted out of escaping with autoEscape: false
|
|
912
934
|
titleSpan.innerHTML = nodeName;
|
|
913
935
|
}
|
|
914
936
|
}
|
|
@@ -925,7 +947,9 @@ var TreeElement = (function () {
|
|
|
925
947
|
return classes.join(" ");
|
|
926
948
|
}
|
|
927
949
|
|
|
928
|
-
/*
|
|
950
|
+
/*
|
|
951
|
+
The children of a closed folder are rendered when it is opened
|
|
952
|
+
*/
|
|
929
953
|
_mustRenderChildren(node) {
|
|
930
954
|
return node.hasChildren() && node.is_open === true;
|
|
931
955
|
}
|
|
@@ -934,18 +958,22 @@ var TreeElement = (function () {
|
|
|
934
958
|
class KeyHandler {
|
|
935
959
|
constructor({
|
|
936
960
|
_closeNode: closeNode,
|
|
961
|
+
_getFocusedNode: getFocusedNode,
|
|
937
962
|
_getSelectedNode: getSelectedNode,
|
|
938
|
-
|
|
963
|
+
_getTree: getTree,
|
|
939
964
|
_keyboardSupport: keyboardSupport,
|
|
940
965
|
_openNode: openNode,
|
|
941
|
-
_selectNode: selectNode
|
|
966
|
+
_selectNode: selectNode,
|
|
967
|
+
_triggerEvent: triggerEvent
|
|
942
968
|
}) {
|
|
943
969
|
this._closeNode = closeNode;
|
|
970
|
+
this._getFocusedNode = getFocusedNode;
|
|
944
971
|
this._getSelectedNode = getSelectedNode;
|
|
945
|
-
this.
|
|
972
|
+
this._getTree = getTree;
|
|
946
973
|
this._keyboardSupport = keyboardSupport;
|
|
947
974
|
this._openNode = openNode;
|
|
948
975
|
this._originalSelectNode = selectNode;
|
|
976
|
+
this._triggerEvent = triggerEvent;
|
|
949
977
|
if (keyboardSupport) {
|
|
950
978
|
document.addEventListener("keydown", this._handleKeyDown);
|
|
951
979
|
}
|
|
@@ -961,35 +989,89 @@ var TreeElement = (function () {
|
|
|
961
989
|
_moveUp() {
|
|
962
990
|
return this._selectNode(this._getSelectedNode()?.getPreviousVisibleNode());
|
|
963
991
|
}
|
|
964
|
-
|
|
965
|
-
|
|
992
|
+
|
|
993
|
+
// Activate the node, for example to open its edit page.
|
|
994
|
+
_activate(node, originalEvent) {
|
|
995
|
+
this._triggerEvent("tree.activate", {
|
|
996
|
+
node,
|
|
997
|
+
originalEvent
|
|
998
|
+
});
|
|
999
|
+
return true;
|
|
1000
|
+
}
|
|
1001
|
+
_handleArrowKey(key) {
|
|
1002
|
+
switch (key) {
|
|
1003
|
+
case "ArrowDown":
|
|
1004
|
+
{
|
|
1005
|
+
return this._moveDown();
|
|
1006
|
+
}
|
|
1007
|
+
case "ArrowLeft":
|
|
1008
|
+
{
|
|
1009
|
+
return this._moveLeft();
|
|
1010
|
+
}
|
|
1011
|
+
case "ArrowRight":
|
|
1012
|
+
{
|
|
1013
|
+
return this._moveRight();
|
|
1014
|
+
}
|
|
1015
|
+
case "ArrowUp":
|
|
1016
|
+
{
|
|
1017
|
+
return this._moveUp();
|
|
1018
|
+
}
|
|
1019
|
+
default:
|
|
1020
|
+
{
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
966
1024
|
}
|
|
967
1025
|
_handleKeyDown = e => {
|
|
968
|
-
|
|
1026
|
+
let focusedNode = this._getFocusedNode();
|
|
1027
|
+
if (!focusedNode) {
|
|
969
1028
|
return;
|
|
970
1029
|
}
|
|
971
|
-
let isKeyHandled
|
|
1030
|
+
let isKeyHandled;
|
|
972
1031
|
let selectedNode = this._getSelectedNode();
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
isKeyHandled = this.
|
|
977
|
-
break;
|
|
978
|
-
case "ArrowLeft":
|
|
979
|
-
isKeyHandled = this._moveLeft();
|
|
1032
|
+
switch (e.key) {
|
|
1033
|
+
case "End":
|
|
1034
|
+
{
|
|
1035
|
+
isKeyHandled = this._selectNode(this._getTree()?.getLastChild());
|
|
980
1036
|
break;
|
|
981
|
-
|
|
982
|
-
|
|
1037
|
+
}
|
|
1038
|
+
case "Enter":
|
|
1039
|
+
{
|
|
1040
|
+
// Without a selected node, activate the focused node
|
|
1041
|
+
isKeyHandled = this._activate(selectedNode ?? focusedNode, e);
|
|
983
1042
|
break;
|
|
984
|
-
|
|
985
|
-
|
|
1043
|
+
}
|
|
1044
|
+
case "Home":
|
|
1045
|
+
{
|
|
1046
|
+
isKeyHandled = this._selectNode(this._getTree()?.children[0]);
|
|
986
1047
|
break;
|
|
987
|
-
|
|
1048
|
+
}
|
|
1049
|
+
default:
|
|
1050
|
+
{
|
|
1051
|
+
isKeyHandled = selectedNode ? this._handleArrowKey(e.key) : this._handleKeyWithoutSelection(e.key, focusedNode);
|
|
1052
|
+
}
|
|
988
1053
|
}
|
|
989
1054
|
if (isKeyHandled) {
|
|
990
1055
|
e.preventDefault();
|
|
991
1056
|
}
|
|
992
1057
|
};
|
|
1058
|
+
|
|
1059
|
+
// No node is selected. These keys select the focused node, which is
|
|
1060
|
+
// usually the first node, see TreeElement.updateTabStop.
|
|
1061
|
+
_handleKeyWithoutSelection(key, focusedNode) {
|
|
1062
|
+
switch (key) {
|
|
1063
|
+
case " ":
|
|
1064
|
+
case "ArrowDown":
|
|
1065
|
+
case "ArrowRight":
|
|
1066
|
+
{
|
|
1067
|
+
return this._selectNode(focusedNode);
|
|
1068
|
+
}
|
|
1069
|
+
default:
|
|
1070
|
+
{
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
993
1075
|
_moveLeft() {
|
|
994
1076
|
let selectedNode = this._getSelectedNode();
|
|
995
1077
|
|
|
@@ -999,28 +1081,25 @@ var TreeElement = (function () {
|
|
|
999
1081
|
}
|
|
1000
1082
|
if (selectedNode.isFolder() && selectedNode.is_open) {
|
|
1001
1083
|
// Left on an open node closes the node
|
|
1002
|
-
this._closeNode(selectedNode);
|
|
1084
|
+
void this._closeNode(selectedNode);
|
|
1003
1085
|
return true;
|
|
1004
|
-
} else {
|
|
1005
|
-
// Left on a closed or end node moves focus to the node's parent
|
|
1006
|
-
return this._selectNode(selectedNode.getParent());
|
|
1007
1086
|
}
|
|
1087
|
+
// Left on a closed or end node moves focus to the node's parent
|
|
1088
|
+
return this._selectNode(selectedNode.getParent());
|
|
1008
1089
|
}
|
|
1009
1090
|
_moveRight() {
|
|
1010
1091
|
let selectedNode = this._getSelectedNode();
|
|
1011
|
-
if (
|
|
1012
|
-
return false;
|
|
1013
|
-
} else {
|
|
1092
|
+
if (selectedNode?.isFolder()) {
|
|
1014
1093
|
// folder node
|
|
1015
1094
|
if (selectedNode.is_open) {
|
|
1016
1095
|
// Right moves to the first child of an open node
|
|
1017
1096
|
return this._selectNode(selectedNode.getNextVisibleNode());
|
|
1018
|
-
} else {
|
|
1019
|
-
// Right expands a closed node
|
|
1020
|
-
void this._openNode(selectedNode);
|
|
1021
|
-
return true;
|
|
1022
1097
|
}
|
|
1098
|
+
// Right expands a closed node
|
|
1099
|
+
void this._openNode(selectedNode);
|
|
1100
|
+
return true;
|
|
1023
1101
|
}
|
|
1102
|
+
return false;
|
|
1024
1103
|
}
|
|
1025
1104
|
|
|
1026
1105
|
/* Select the node.
|
|
@@ -1028,12 +1107,11 @@ var TreeElement = (function () {
|
|
|
1028
1107
|
* Result: a different node was selected.
|
|
1029
1108
|
*/
|
|
1030
1109
|
_selectNode(node) {
|
|
1031
|
-
if (
|
|
1032
|
-
return false;
|
|
1033
|
-
} else {
|
|
1110
|
+
if (node) {
|
|
1034
1111
|
this._originalSelectNode(node);
|
|
1035
1112
|
return true;
|
|
1036
1113
|
}
|
|
1114
|
+
return false;
|
|
1037
1115
|
}
|
|
1038
1116
|
}
|
|
1039
1117
|
|
|
@@ -1137,10 +1215,12 @@ var TreeElement = (function () {
|
|
|
1137
1215
|
}
|
|
1138
1216
|
switch (clickTarget.type) {
|
|
1139
1217
|
case "button":
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1218
|
+
{
|
|
1219
|
+
void this._onClickButton(clickTarget.node);
|
|
1220
|
+
e.preventDefault();
|
|
1221
|
+
e.stopPropagation();
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1144
1224
|
case "label":
|
|
1145
1225
|
{
|
|
1146
1226
|
if (this._triggerEvent("tree.click", {
|
|
@@ -1223,10 +1303,11 @@ var TreeElement = (function () {
|
|
|
1223
1303
|
this._removeMouseMoveEventListeners();
|
|
1224
1304
|
this._isMouseDelayMet = false;
|
|
1225
1305
|
this._mouseDownInfo = null;
|
|
1226
|
-
if (this._isMouseStarted) {
|
|
1227
|
-
|
|
1228
|
-
this._onMouseStop(positionInfo);
|
|
1306
|
+
if (!this._isMouseStarted) {
|
|
1307
|
+
return;
|
|
1229
1308
|
}
|
|
1309
|
+
this._isMouseStarted = false;
|
|
1310
|
+
this._onMouseStop(positionInfo);
|
|
1230
1311
|
}
|
|
1231
1312
|
_handleStartMouse() {
|
|
1232
1313
|
document.addEventListener("mousemove", this._mouseMove, {
|
|
@@ -1313,7 +1394,7 @@ var TreeElement = (function () {
|
|
|
1313
1394
|
};
|
|
1314
1395
|
}
|
|
1315
1396
|
|
|
1316
|
-
let isNodeRecordWithChildren = data => typeof data === "object" && "children" in data && data.children
|
|
1397
|
+
let isNodeRecordWithChildren = data => typeof data === "object" && "children" in data && Array.isArray(data.children);
|
|
1317
1398
|
|
|
1318
1399
|
/*
|
|
1319
1400
|
A node reads and writes the private members of other nodes (node.setParent),
|
|
@@ -1341,38 +1422,62 @@ var TreeElement = (function () {
|
|
|
1341
1422
|
* :::
|
|
1342
1423
|
*/
|
|
1343
1424
|
class Node {
|
|
1344
|
-
/**
|
|
1425
|
+
/**
|
|
1426
|
+
@hidden
|
|
1427
|
+
*/
|
|
1345
1428
|
|
|
1346
|
-
/**
|
|
1429
|
+
/**
|
|
1430
|
+
The child nodes.
|
|
1431
|
+
*/
|
|
1347
1432
|
children;
|
|
1348
1433
|
/** The `li` element, once the node is rendered. Nodes inside a closed
|
|
1349
1434
|
* folder are rendered when the folder is opened. */
|
|
1350
1435
|
element;
|
|
1351
|
-
/**
|
|
1436
|
+
/**
|
|
1437
|
+
The id from the node data.
|
|
1438
|
+
*/
|
|
1352
1439
|
id;
|
|
1353
|
-
/**
|
|
1440
|
+
/**
|
|
1441
|
+
@hidden
|
|
1442
|
+
*/
|
|
1354
1443
|
idMapping;
|
|
1355
|
-
/**
|
|
1444
|
+
/**
|
|
1445
|
+
Whether the node's children are being fetched.
|
|
1446
|
+
*/
|
|
1356
1447
|
is_loading;
|
|
1357
|
-
/**
|
|
1448
|
+
/**
|
|
1449
|
+
Whether the folder is open.
|
|
1450
|
+
*/
|
|
1358
1451
|
is_open;
|
|
1359
|
-
/**
|
|
1452
|
+
/**
|
|
1453
|
+
Whether the node data had an empty `children` array.
|
|
1454
|
+
*/
|
|
1360
1455
|
isEmptyFolder;
|
|
1361
|
-
/**
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
/**
|
|
1456
|
+
/**
|
|
1457
|
+
Whether the children still have to be fetched.
|
|
1458
|
+
*/
|
|
1459
|
+
load_on_demand = false;
|
|
1460
|
+
/**
|
|
1461
|
+
The label. Also settable from the `label` key in node data.
|
|
1462
|
+
*/
|
|
1463
|
+
name = "";
|
|
1464
|
+
/**
|
|
1465
|
+
@hidden
|
|
1466
|
+
*/
|
|
1366
1467
|
nodeClass;
|
|
1367
|
-
/**
|
|
1468
|
+
/**
|
|
1469
|
+
The parent; `null` for the root node.
|
|
1470
|
+
*/
|
|
1368
1471
|
parent;
|
|
1369
|
-
/**
|
|
1472
|
+
/**
|
|
1473
|
+
The root node.
|
|
1474
|
+
*/
|
|
1370
1475
|
tree;
|
|
1371
1476
|
|
|
1372
|
-
/**
|
|
1477
|
+
/**
|
|
1478
|
+
@hidden
|
|
1479
|
+
*/
|
|
1373
1480
|
constructor(nodeData = null, isRoot = false, nodeClass = Node) {
|
|
1374
|
-
this.name = "";
|
|
1375
|
-
this.load_on_demand = false;
|
|
1376
1481
|
this.isEmptyFolder = nodeData != null && isNodeRecordWithChildren(nodeData) && nodeData.children.length === 0;
|
|
1377
1482
|
this.setData(nodeData);
|
|
1378
1483
|
this.children = [];
|
|
@@ -1395,15 +1500,14 @@ var TreeElement = (function () {
|
|
|
1395
1500
|
* @group Changing the tree
|
|
1396
1501
|
*/
|
|
1397
1502
|
addAfter(nodeInfo) {
|
|
1398
|
-
if (
|
|
1399
|
-
return null;
|
|
1400
|
-
} else {
|
|
1503
|
+
if (this.parent) {
|
|
1401
1504
|
let node = this._createNode(nodeInfo);
|
|
1402
1505
|
let childIndex = this.parent.getChildIndex(this);
|
|
1403
1506
|
this.parent.addChildAtPosition(node, childIndex + 1);
|
|
1404
1507
|
node._loadChildrenFromData(nodeInfo);
|
|
1405
1508
|
return node;
|
|
1406
1509
|
}
|
|
1510
|
+
return null;
|
|
1407
1511
|
}
|
|
1408
1512
|
|
|
1409
1513
|
/**
|
|
@@ -1413,15 +1517,14 @@ var TreeElement = (function () {
|
|
|
1413
1517
|
* @group Changing the tree
|
|
1414
1518
|
*/
|
|
1415
1519
|
addBefore(nodeInfo) {
|
|
1416
|
-
if (
|
|
1417
|
-
return null;
|
|
1418
|
-
} else {
|
|
1520
|
+
if (this.parent) {
|
|
1419
1521
|
let node = this._createNode(nodeInfo);
|
|
1420
1522
|
let childIndex = this.parent.getChildIndex(this);
|
|
1421
1523
|
this.parent.addChildAtPosition(node, childIndex);
|
|
1422
1524
|
node._loadChildrenFromData(nodeInfo);
|
|
1423
1525
|
return node;
|
|
1424
1526
|
}
|
|
1527
|
+
return null;
|
|
1425
1528
|
}
|
|
1426
1529
|
|
|
1427
1530
|
/**
|
|
@@ -1445,7 +1548,9 @@ var TreeElement = (function () {
|
|
|
1445
1548
|
node._setParent(this);
|
|
1446
1549
|
}
|
|
1447
1550
|
|
|
1448
|
-
/**
|
|
1551
|
+
/**
|
|
1552
|
+
@hidden
|
|
1553
|
+
*/
|
|
1449
1554
|
addNodeToIndex(node) {
|
|
1450
1555
|
if (node.id != null) {
|
|
1451
1556
|
this.idMapping?.set(node.id, node);
|
|
@@ -1459,9 +1564,7 @@ var TreeElement = (function () {
|
|
|
1459
1564
|
* @group Changing the tree
|
|
1460
1565
|
*/
|
|
1461
1566
|
addParent(nodeInfo) {
|
|
1462
|
-
if (
|
|
1463
|
-
return null;
|
|
1464
|
-
} else {
|
|
1567
|
+
if (this.parent) {
|
|
1465
1568
|
let newParent = this._createNode(nodeInfo);
|
|
1466
1569
|
if (this.tree) {
|
|
1467
1570
|
newParent._setParent(this.tree);
|
|
@@ -1474,6 +1577,7 @@ var TreeElement = (function () {
|
|
|
1474
1577
|
originalParent.addChild(newParent);
|
|
1475
1578
|
return newParent;
|
|
1476
1579
|
}
|
|
1580
|
+
return null;
|
|
1477
1581
|
}
|
|
1478
1582
|
|
|
1479
1583
|
/**
|
|
@@ -1540,10 +1644,11 @@ var TreeElement = (function () {
|
|
|
1540
1644
|
return nodes.map(node => {
|
|
1541
1645
|
let tmpNode = {};
|
|
1542
1646
|
for (let k in node) {
|
|
1543
|
-
if (["
|
|
1544
|
-
|
|
1545
|
-
tmpNode[k] = v;
|
|
1647
|
+
if (["children", "element", "idMapping", "isEmptyFolder", "load_on_demand", "nodeClass", "parent", "tree"].includes(k) || !Object.prototype.hasOwnProperty.call(node, k)) {
|
|
1648
|
+
continue;
|
|
1546
1649
|
}
|
|
1650
|
+
let v = node[k];
|
|
1651
|
+
tmpNode[k] = v;
|
|
1547
1652
|
}
|
|
1548
1653
|
if (node.hasChildren()) {
|
|
1549
1654
|
tmpNode.children = getDataFromNodes(node.children);
|
|
@@ -1551,11 +1656,7 @@ var TreeElement = (function () {
|
|
|
1551
1656
|
return tmpNode;
|
|
1552
1657
|
});
|
|
1553
1658
|
};
|
|
1554
|
-
|
|
1555
|
-
return getDataFromNodes([this]);
|
|
1556
|
-
} else {
|
|
1557
|
-
return getDataFromNodes(this.children);
|
|
1558
|
-
}
|
|
1659
|
+
return getDataFromNodes(includeParent ? [this] : this.children);
|
|
1559
1660
|
}
|
|
1560
1661
|
|
|
1561
1662
|
/**
|
|
@@ -1565,16 +1666,11 @@ var TreeElement = (function () {
|
|
|
1565
1666
|
* @group Moving around the tree
|
|
1566
1667
|
*/
|
|
1567
1668
|
getLastChild() {
|
|
1568
|
-
if (
|
|
1569
|
-
return null;
|
|
1570
|
-
} else {
|
|
1669
|
+
if (this.hasChildren()) {
|
|
1571
1670
|
let lastChild = this.children[this.children.length - 1];
|
|
1572
|
-
|
|
1573
|
-
return lastChild;
|
|
1574
|
-
} else {
|
|
1575
|
-
return lastChild.getLastChild();
|
|
1576
|
-
}
|
|
1671
|
+
return lastChild.hasChildren() && lastChild.is_open ? lastChild.getLastChild() : lastChild;
|
|
1577
1672
|
}
|
|
1673
|
+
return null;
|
|
1578
1674
|
}
|
|
1579
1675
|
|
|
1580
1676
|
/**
|
|
@@ -1584,7 +1680,7 @@ var TreeElement = (function () {
|
|
|
1584
1680
|
*/
|
|
1585
1681
|
getLevel() {
|
|
1586
1682
|
let level = 0;
|
|
1587
|
-
let node = this; // eslint-disable-line @typescript-eslint/no-this-alias
|
|
1683
|
+
let node = this; // eslint-disable-line @typescript-eslint/no-this-alias, unicorn/no-this-assignment
|
|
1588
1684
|
|
|
1589
1685
|
while (node.parent) {
|
|
1590
1686
|
level += 1;
|
|
@@ -1602,16 +1698,12 @@ var TreeElement = (function () {
|
|
|
1602
1698
|
getNextNode(includeChildren = true) {
|
|
1603
1699
|
if (includeChildren && this.hasChildren()) {
|
|
1604
1700
|
return this.children[0] ?? null;
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
} else {
|
|
1701
|
+
}
|
|
1702
|
+
if (this.parent) {
|
|
1608
1703
|
let nextSibling = this.getNextSibling();
|
|
1609
|
-
|
|
1610
|
-
return nextSibling;
|
|
1611
|
-
} else {
|
|
1612
|
-
return this.parent.getNextNode(false);
|
|
1613
|
-
}
|
|
1704
|
+
return nextSibling ?? this.parent.getNextNode(false);
|
|
1614
1705
|
}
|
|
1706
|
+
return null;
|
|
1615
1707
|
}
|
|
1616
1708
|
|
|
1617
1709
|
/**
|
|
@@ -1620,16 +1712,11 @@ var TreeElement = (function () {
|
|
|
1620
1712
|
* @group Moving around the tree
|
|
1621
1713
|
*/
|
|
1622
1714
|
getNextSibling() {
|
|
1623
|
-
if (
|
|
1624
|
-
return null;
|
|
1625
|
-
} else {
|
|
1715
|
+
if (this.parent) {
|
|
1626
1716
|
let nextIndex = this.parent.getChildIndex(this) + 1;
|
|
1627
|
-
|
|
1628
|
-
return this.parent.children[nextIndex] ?? null;
|
|
1629
|
-
} else {
|
|
1630
|
-
return null;
|
|
1631
|
-
}
|
|
1717
|
+
return nextIndex < this.parent.children.length ? this.parent.children[nextIndex] ?? null : null;
|
|
1632
1718
|
}
|
|
1719
|
+
return null;
|
|
1633
1720
|
}
|
|
1634
1721
|
|
|
1635
1722
|
/**
|
|
@@ -1642,20 +1729,17 @@ var TreeElement = (function () {
|
|
|
1642
1729
|
if (this.hasChildren() && this.is_open) {
|
|
1643
1730
|
// First child
|
|
1644
1731
|
return this.children[0] ?? null;
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
// Next sibling
|
|
1652
|
-
return nextSibling;
|
|
1653
|
-
} else {
|
|
1654
|
-
// Next node of parent
|
|
1655
|
-
return this.parent.getNextNode(false);
|
|
1656
|
-
}
|
|
1732
|
+
}
|
|
1733
|
+
if (this.parent) {
|
|
1734
|
+
let nextSibling = this.getNextSibling();
|
|
1735
|
+
if (nextSibling) {
|
|
1736
|
+
// Next sibling
|
|
1737
|
+
return nextSibling;
|
|
1657
1738
|
}
|
|
1739
|
+
// Next node of parent
|
|
1740
|
+
return this.parent.getNextNode(false);
|
|
1658
1741
|
}
|
|
1742
|
+
return null;
|
|
1659
1743
|
}
|
|
1660
1744
|
|
|
1661
1745
|
/**
|
|
@@ -1668,12 +1752,12 @@ var TreeElement = (function () {
|
|
|
1668
1752
|
this.iterate(node => {
|
|
1669
1753
|
if (result) {
|
|
1670
1754
|
return false;
|
|
1671
|
-
}
|
|
1755
|
+
}
|
|
1756
|
+
if (callback(node)) {
|
|
1672
1757
|
result = node;
|
|
1673
1758
|
return false;
|
|
1674
|
-
} else {
|
|
1675
|
-
return true;
|
|
1676
1759
|
}
|
|
1760
|
+
return true;
|
|
1677
1761
|
});
|
|
1678
1762
|
return result;
|
|
1679
1763
|
}
|
|
@@ -1729,12 +1813,12 @@ var TreeElement = (function () {
|
|
|
1729
1813
|
// Return parent except if it is the root node
|
|
1730
1814
|
if (!this.parent) {
|
|
1731
1815
|
return null;
|
|
1732
|
-
}
|
|
1733
|
-
|
|
1734
|
-
return null;
|
|
1735
|
-
} else {
|
|
1816
|
+
}
|
|
1817
|
+
if (this.parent.parent) {
|
|
1736
1818
|
return this.parent;
|
|
1737
1819
|
}
|
|
1820
|
+
// Root node -> null
|
|
1821
|
+
return null;
|
|
1738
1822
|
}
|
|
1739
1823
|
|
|
1740
1824
|
/**
|
|
@@ -1744,18 +1828,14 @@ var TreeElement = (function () {
|
|
|
1744
1828
|
* @group Moving around the tree
|
|
1745
1829
|
*/
|
|
1746
1830
|
getPreviousNode() {
|
|
1747
|
-
if (
|
|
1748
|
-
return null;
|
|
1749
|
-
} else {
|
|
1831
|
+
if (this.parent) {
|
|
1750
1832
|
let previousSibling = this.getPreviousSibling();
|
|
1751
1833
|
if (!previousSibling) {
|
|
1752
1834
|
return this.getParent();
|
|
1753
|
-
} else if (previousSibling.hasChildren()) {
|
|
1754
|
-
return previousSibling.getLastChild();
|
|
1755
|
-
} else {
|
|
1756
|
-
return previousSibling;
|
|
1757
1835
|
}
|
|
1836
|
+
return previousSibling.hasChildren() ? previousSibling.getLastChild() : previousSibling;
|
|
1758
1837
|
}
|
|
1838
|
+
return null;
|
|
1759
1839
|
}
|
|
1760
1840
|
|
|
1761
1841
|
/**
|
|
@@ -1764,16 +1844,11 @@ var TreeElement = (function () {
|
|
|
1764
1844
|
* @group Moving around the tree
|
|
1765
1845
|
*/
|
|
1766
1846
|
getPreviousSibling() {
|
|
1767
|
-
if (
|
|
1768
|
-
return null;
|
|
1769
|
-
} else {
|
|
1847
|
+
if (this.parent) {
|
|
1770
1848
|
let previousIndex = this.parent.getChildIndex(this) - 1;
|
|
1771
|
-
|
|
1772
|
-
return this.parent.children[previousIndex] ?? null;
|
|
1773
|
-
} else {
|
|
1774
|
-
return null;
|
|
1775
|
-
}
|
|
1849
|
+
return previousIndex >= 0 ? this.parent.children[previousIndex] ?? null : null;
|
|
1776
1850
|
}
|
|
1851
|
+
return null;
|
|
1777
1852
|
}
|
|
1778
1853
|
|
|
1779
1854
|
/**
|
|
@@ -1783,20 +1858,19 @@ var TreeElement = (function () {
|
|
|
1783
1858
|
* @group Moving around the tree
|
|
1784
1859
|
*/
|
|
1785
1860
|
getPreviousVisibleNode() {
|
|
1786
|
-
if (
|
|
1787
|
-
return null;
|
|
1788
|
-
} else {
|
|
1861
|
+
if (this.parent) {
|
|
1789
1862
|
let previousSibling = this.getPreviousSibling();
|
|
1790
1863
|
if (!previousSibling) {
|
|
1791
1864
|
return this.getParent();
|
|
1792
|
-
}
|
|
1865
|
+
}
|
|
1866
|
+
if (!previousSibling.hasChildren() || !previousSibling.is_open) {
|
|
1793
1867
|
// Previous sibling
|
|
1794
1868
|
return previousSibling;
|
|
1795
|
-
} else {
|
|
1796
|
-
// Last child of previous sibling
|
|
1797
|
-
return previousSibling.getLastChild();
|
|
1798
1869
|
}
|
|
1870
|
+
// Last child of previous sibling
|
|
1871
|
+
return previousSibling.getLastChild();
|
|
1799
1872
|
}
|
|
1873
|
+
return null;
|
|
1800
1874
|
}
|
|
1801
1875
|
|
|
1802
1876
|
/**
|
|
@@ -1910,32 +1984,31 @@ var TreeElement = (function () {
|
|
|
1910
1984
|
// - Node is parent of target node
|
|
1911
1985
|
// - Or, parent is empty
|
|
1912
1986
|
return false;
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
}
|
|
1922
|
-
return false;
|
|
1923
|
-
}
|
|
1924
|
-
case "before":
|
|
1925
|
-
{
|
|
1926
|
-
if (targetNode.parent) {
|
|
1927
|
-
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode));
|
|
1928
|
-
return true;
|
|
1929
|
-
}
|
|
1930
|
-
return false;
|
|
1987
|
+
}
|
|
1988
|
+
movedNode.parent._doRemoveChild(movedNode);
|
|
1989
|
+
switch (position) {
|
|
1990
|
+
case "after":
|
|
1991
|
+
{
|
|
1992
|
+
if (targetNode.parent) {
|
|
1993
|
+
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode) + 1);
|
|
1994
|
+
return true;
|
|
1931
1995
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1996
|
+
return false;
|
|
1997
|
+
}
|
|
1998
|
+
case "before":
|
|
1999
|
+
{
|
|
2000
|
+
if (targetNode.parent) {
|
|
2001
|
+
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode));
|
|
1936
2002
|
return true;
|
|
1937
2003
|
}
|
|
1938
|
-
|
|
2004
|
+
return false;
|
|
2005
|
+
}
|
|
2006
|
+
case "inside":
|
|
2007
|
+
{
|
|
2008
|
+
// move inside as first child
|
|
2009
|
+
targetNode.addChildAtPosition(movedNode, 0);
|
|
2010
|
+
return true;
|
|
2011
|
+
}
|
|
1939
2012
|
}
|
|
1940
2013
|
}
|
|
1941
2014
|
|
|
@@ -1958,10 +2031,11 @@ var TreeElement = (function () {
|
|
|
1958
2031
|
* @group Changing the tree
|
|
1959
2032
|
*/
|
|
1960
2033
|
remove() {
|
|
1961
|
-
if (this.parent) {
|
|
1962
|
-
|
|
1963
|
-
this.parent = null;
|
|
2034
|
+
if (!this.parent) {
|
|
2035
|
+
return;
|
|
1964
2036
|
}
|
|
2037
|
+
this.parent.removeChild(this);
|
|
2038
|
+
this.parent = null;
|
|
1965
2039
|
}
|
|
1966
2040
|
|
|
1967
2041
|
/**
|
|
@@ -1988,7 +2062,9 @@ var TreeElement = (function () {
|
|
|
1988
2062
|
this.children = [];
|
|
1989
2063
|
}
|
|
1990
2064
|
|
|
1991
|
-
/**
|
|
2065
|
+
/**
|
|
2066
|
+
@hidden
|
|
2067
|
+
*/
|
|
1992
2068
|
removeNodeFromIndex(node) {
|
|
1993
2069
|
if (node.id != null) {
|
|
1994
2070
|
this.idMapping?.delete(node.id);
|
|
@@ -2005,21 +2081,23 @@ var TreeElement = (function () {
|
|
|
2005
2081
|
setData(o) {
|
|
2006
2082
|
if (!o) {
|
|
2007
2083
|
return;
|
|
2008
|
-
}
|
|
2084
|
+
}
|
|
2085
|
+
if (typeof o === "string") {
|
|
2009
2086
|
this.name = o;
|
|
2010
2087
|
} else if (typeof o === "object") {
|
|
2011
2088
|
for (let key in o) {
|
|
2012
|
-
if (Object.prototype.hasOwnProperty.call(o, key)) {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
// You can't update the children or the parent using this function
|
|
2021
|
-
this[key] = value;
|
|
2089
|
+
if (!Object.prototype.hasOwnProperty.call(o, key)) {
|
|
2090
|
+
continue;
|
|
2091
|
+
}
|
|
2092
|
+
let value = o[key];
|
|
2093
|
+
if (key === "label" || key === "name") {
|
|
2094
|
+
// You can use the 'label' key instead of 'name'; this is a legacy feature
|
|
2095
|
+
if (typeof value === "string") {
|
|
2096
|
+
this.name = value;
|
|
2022
2097
|
}
|
|
2098
|
+
} else if (key !== "children" && key !== "parent") {
|
|
2099
|
+
// You can't update the children or the parent using this function
|
|
2100
|
+
this[key] = value;
|
|
2023
2101
|
}
|
|
2024
2102
|
}
|
|
2025
2103
|
}
|
|
@@ -2078,11 +2156,15 @@ var TreeElement = (function () {
|
|
|
2078
2156
|
this._ghost = this._createGhostElement();
|
|
2079
2157
|
switch (position) {
|
|
2080
2158
|
case "after":
|
|
2081
|
-
|
|
2082
|
-
|
|
2159
|
+
{
|
|
2160
|
+
this._moveAfter();
|
|
2161
|
+
break;
|
|
2162
|
+
}
|
|
2083
2163
|
case "before":
|
|
2084
|
-
|
|
2085
|
-
|
|
2164
|
+
{
|
|
2165
|
+
this._moveBefore();
|
|
2166
|
+
break;
|
|
2167
|
+
}
|
|
2086
2168
|
case "inside":
|
|
2087
2169
|
{
|
|
2088
2170
|
if (node.isFolder() && node.is_open) {
|
|
@@ -2149,11 +2231,7 @@ var TreeElement = (function () {
|
|
|
2149
2231
|
this._element = node.element ?? this._treeElement;
|
|
2150
2232
|
}
|
|
2151
2233
|
_addDropHint(position) {
|
|
2152
|
-
|
|
2153
|
-
return new BorderDropHint(this._element, this._getScrollLeft(), this._classNames);
|
|
2154
|
-
} else {
|
|
2155
|
-
return new GhostDropHint(this._node, this._element, position, this._classNames);
|
|
2156
|
-
}
|
|
2234
|
+
return this._mustShowBorderDropHint(position) ? new BorderDropHint(this._element, this._getScrollLeft(), this._classNames) : new GhostDropHint(this._node, this._element, position, this._classNames);
|
|
2157
2235
|
}
|
|
2158
2236
|
_deselect() {
|
|
2159
2237
|
if (!this._isRendered()) {
|
|
@@ -2161,7 +2239,11 @@ var TreeElement = (function () {
|
|
|
2161
2239
|
}
|
|
2162
2240
|
this._element.classList.remove(this._classNames.selected);
|
|
2163
2241
|
let titleSpan = this._getTitleSpan();
|
|
2164
|
-
|
|
2242
|
+
|
|
2243
|
+
// Check for null or undefined
|
|
2244
|
+
if (this._tabIndex != null) {
|
|
2245
|
+
titleSpan.setAttribute("tabindex", "-1");
|
|
2246
|
+
}
|
|
2165
2247
|
titleSpan.setAttribute("aria-selected", "false");
|
|
2166
2248
|
titleSpan.blur();
|
|
2167
2249
|
}
|
|
@@ -2206,7 +2288,7 @@ var TreeElement = (function () {
|
|
|
2206
2288
|
}
|
|
2207
2289
|
return duration === "slow" ? 600 : 200;
|
|
2208
2290
|
};
|
|
2209
|
-
let slideDown = (element, animationSpeed
|
|
2291
|
+
let slideDown = (element, animationSpeed) => {
|
|
2210
2292
|
element.style.display = "block";
|
|
2211
2293
|
let animation = element.animate([{
|
|
2212
2294
|
height: "0",
|
|
@@ -2217,11 +2299,13 @@ var TreeElement = (function () {
|
|
|
2217
2299
|
}], {
|
|
2218
2300
|
duration: getAnimationDuration(animationSpeed)
|
|
2219
2301
|
});
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2302
|
+
return new Promise(resolve => {
|
|
2303
|
+
animation.onfinish = () => {
|
|
2304
|
+
resolve();
|
|
2305
|
+
};
|
|
2306
|
+
});
|
|
2223
2307
|
};
|
|
2224
|
-
let slideUp = (element, animationSpeed
|
|
2308
|
+
let slideUp = (element, animationSpeed) => {
|
|
2225
2309
|
let animation = element.animate([{
|
|
2226
2310
|
height: `${element.scrollHeight}px`,
|
|
2227
2311
|
overflow: "hidden"
|
|
@@ -2231,10 +2315,12 @@ var TreeElement = (function () {
|
|
|
2231
2315
|
}], {
|
|
2232
2316
|
duration: getAnimationDuration(animationSpeed)
|
|
2233
2317
|
});
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2318
|
+
return new Promise(resolve => {
|
|
2319
|
+
animation.onfinish = () => {
|
|
2320
|
+
element.style.display = "none";
|
|
2321
|
+
resolve();
|
|
2322
|
+
};
|
|
2323
|
+
});
|
|
2238
2324
|
};
|
|
2239
2325
|
|
|
2240
2326
|
class FolderElement extends NodeElement {
|
|
@@ -2261,7 +2347,7 @@ var TreeElement = (function () {
|
|
|
2261
2347
|
this._renderChildren = renderChildren;
|
|
2262
2348
|
this._triggerEvent = triggerEvent;
|
|
2263
2349
|
}
|
|
2264
|
-
_close(slide, animationSpeed) {
|
|
2350
|
+
async _close(slide, animationSpeed) {
|
|
2265
2351
|
if (!this._node.is_open) {
|
|
2266
2352
|
return;
|
|
2267
2353
|
}
|
|
@@ -2274,113 +2360,84 @@ var TreeElement = (function () {
|
|
|
2274
2360
|
}
|
|
2275
2361
|
let button = this._getButton();
|
|
2276
2362
|
button.classList.add(this._classNames.closed);
|
|
2277
|
-
button.
|
|
2363
|
+
button.replaceChildren();
|
|
2278
2364
|
let closedIconElement = this._closedIconElement;
|
|
2279
2365
|
if (closedIconElement) {
|
|
2280
2366
|
let icon = closedIconElement.cloneNode(true);
|
|
2281
|
-
button.
|
|
2367
|
+
button.append(icon);
|
|
2282
2368
|
}
|
|
2283
|
-
let doClose = () => {
|
|
2284
|
-
this._element.classList.add(this._classNames.closed);
|
|
2285
|
-
let titleSpan = this._getTitleSpan();
|
|
2286
|
-
titleSpan.setAttribute("aria-expanded", "false");
|
|
2287
|
-
this._triggerEvent("tree.close", {
|
|
2288
|
-
node: this._node
|
|
2289
|
-
});
|
|
2290
|
-
};
|
|
2291
2369
|
let ul = this._getUl();
|
|
2292
|
-
if (
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
doClose();
|
|
2370
|
+
if (ul) {
|
|
2371
|
+
if (slide) {
|
|
2372
|
+
await slideUp(ul, animationSpeed);
|
|
2373
|
+
} else {
|
|
2374
|
+
ul.style.display = "none";
|
|
2375
|
+
}
|
|
2299
2376
|
}
|
|
2377
|
+
this._element.classList.add(this._classNames.closed);
|
|
2378
|
+
let titleSpan = this._getTitleSpan();
|
|
2379
|
+
titleSpan.setAttribute("aria-expanded", "false");
|
|
2380
|
+
this._triggerEvent("tree.close", {
|
|
2381
|
+
node: this._node
|
|
2382
|
+
});
|
|
2300
2383
|
}
|
|
2301
2384
|
async _open(slide, animationSpeed) {
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
titleSpan.setAttribute("aria-expanded", "true");
|
|
2328
|
-
this._triggerEvent("tree.open", {
|
|
2329
|
-
node: this._node
|
|
2330
|
-
});
|
|
2331
|
-
resolve();
|
|
2332
|
-
};
|
|
2333
|
-
|
|
2334
|
-
// The children are rendered the first time the folder is opened
|
|
2335
|
-
let ul = this._getUl() ?? this._renderChildren(this._node);
|
|
2336
|
-
if (!ul) {
|
|
2337
|
-
doOpen();
|
|
2338
|
-
} else if (slide) {
|
|
2339
|
-
slideDown(ul, animationSpeed, doOpen);
|
|
2385
|
+
if (this._node.is_open) {
|
|
2386
|
+
return;
|
|
2387
|
+
}
|
|
2388
|
+
this._node.is_open = true;
|
|
2389
|
+
if (!this._isRendered()) {
|
|
2390
|
+
// The folder is rendered open when its parent is opened
|
|
2391
|
+
this._triggerEvent("tree.open", {
|
|
2392
|
+
node: this._node
|
|
2393
|
+
});
|
|
2394
|
+
return;
|
|
2395
|
+
}
|
|
2396
|
+
let button = this._getButton();
|
|
2397
|
+
button.classList.remove(this._classNames.closed);
|
|
2398
|
+
button.replaceChildren();
|
|
2399
|
+
let openedIconElement = this._openedIconElement;
|
|
2400
|
+
if (openedIconElement) {
|
|
2401
|
+
let icon = openedIconElement.cloneNode(true);
|
|
2402
|
+
button.append(icon);
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
// The children are rendered the first time the folder is opened
|
|
2406
|
+
let ul = this._getUl() ?? this._renderChildren(this._node);
|
|
2407
|
+
if (ul) {
|
|
2408
|
+
if (slide) {
|
|
2409
|
+
await slideDown(ul, animationSpeed);
|
|
2340
2410
|
} else {
|
|
2341
2411
|
ul.style.display = "block";
|
|
2342
|
-
doOpen();
|
|
2343
2412
|
}
|
|
2413
|
+
}
|
|
2414
|
+
this._element.classList.remove(this._classNames.closed);
|
|
2415
|
+
let titleSpan = this._getTitleSpan();
|
|
2416
|
+
titleSpan.setAttribute("aria-expanded", "true");
|
|
2417
|
+
this._triggerEvent("tree.open", {
|
|
2418
|
+
node: this._node
|
|
2344
2419
|
});
|
|
2345
2420
|
}
|
|
2346
2421
|
_mustShowBorderDropHint(position) {
|
|
2347
2422
|
return !this._node.is_open && position === "inside";
|
|
2348
2423
|
}
|
|
2349
2424
|
_getButton() {
|
|
2350
|
-
return this._element.querySelector(`:scope > .${this._classNames.element} >
|
|
2425
|
+
return this._element.querySelector(`:scope > .${this._classNames.element} > .${this._classNames.toggler}`);
|
|
2351
2426
|
}
|
|
2352
2427
|
}
|
|
2353
2428
|
|
|
2354
|
-
// Url
|
|
2429
|
+
// Url of a request. A relative url is resolved against the page, like a link
|
|
2430
|
+
// or `fetch` would, so it also works when the page is in a subdirectory.
|
|
2355
2431
|
|
|
2356
|
-
let isAbsoluteUrl = inputUrl => {
|
|
2357
|
-
try {
|
|
2358
|
-
new URL(inputUrl);
|
|
2359
|
-
return true;
|
|
2360
|
-
} catch {
|
|
2361
|
-
return false;
|
|
2362
|
-
}
|
|
2363
|
-
};
|
|
2364
|
-
let LOCALHOST = "http://localhost";
|
|
2365
2432
|
class RequestUrl {
|
|
2366
2433
|
constructor(inputUrl) {
|
|
2367
|
-
|
|
2368
|
-
this._url = new URL(inputUrl);
|
|
2369
|
-
this._isAbsolute = true;
|
|
2370
|
-
} else {
|
|
2371
|
-
this._url = new URL(inputUrl, LOCALHOST);
|
|
2372
|
-
this._isAbsolute = false;
|
|
2373
|
-
}
|
|
2434
|
+
this._url = new URL(inputUrl, document.baseURI);
|
|
2374
2435
|
}
|
|
2375
2436
|
_setSearchParam(key, value) {
|
|
2376
2437
|
this._url.searchParams.set(key, value);
|
|
2377
2438
|
}
|
|
2378
2439
|
_value() {
|
|
2379
|
-
|
|
2380
|
-
return this._url.href;
|
|
2381
|
-
} else {
|
|
2382
|
-
return this._url.href.slice(LOCALHOST.length);
|
|
2383
|
-
}
|
|
2440
|
+
return this._url.href;
|
|
2384
2441
|
}
|
|
2385
2442
|
}
|
|
2386
2443
|
|
|
@@ -2413,11 +2470,7 @@ var TreeElement = (function () {
|
|
|
2413
2470
|
return null;
|
|
2414
2471
|
}
|
|
2415
2472
|
let state = this._getStateFromStorage();
|
|
2416
|
-
|
|
2417
|
-
return state.selected_node[0] ?? null;
|
|
2418
|
-
} else {
|
|
2419
|
-
return null;
|
|
2420
|
-
}
|
|
2473
|
+
return state?.selected_node ? state.selected_node[0] ?? null : null;
|
|
2421
2474
|
}
|
|
2422
2475
|
_getState() {
|
|
2423
2476
|
let getOpenNodeIds = () => {
|
|
@@ -2432,11 +2485,11 @@ var TreeElement = (function () {
|
|
|
2432
2485
|
};
|
|
2433
2486
|
let getSelectedNodeIds = () => {
|
|
2434
2487
|
let selectedNodeIds = [];
|
|
2435
|
-
this._getSelectedNodes()
|
|
2488
|
+
for (let node of this._getSelectedNodes()) {
|
|
2436
2489
|
if (node.id != null) {
|
|
2437
2490
|
selectedNodeIds.push(node.id);
|
|
2438
2491
|
}
|
|
2439
|
-
}
|
|
2492
|
+
}
|
|
2440
2493
|
return selectedNodeIds;
|
|
2441
2494
|
};
|
|
2442
2495
|
return {
|
|
@@ -2449,11 +2502,7 @@ var TreeElement = (function () {
|
|
|
2449
2502
|
return null;
|
|
2450
2503
|
}
|
|
2451
2504
|
let jsonData = this._loadFromStorage();
|
|
2452
|
-
|
|
2453
|
-
return this._parseState(jsonData);
|
|
2454
|
-
} else {
|
|
2455
|
-
return null;
|
|
2456
|
-
}
|
|
2505
|
+
return jsonData ? this._parseState(jsonData) : null;
|
|
2457
2506
|
}
|
|
2458
2507
|
_saveState() {
|
|
2459
2508
|
if (!this._saveStateOption) {
|
|
@@ -2473,10 +2522,7 @@ var TreeElement = (function () {
|
|
|
2473
2522
|
result: must load on demand (boolean)
|
|
2474
2523
|
*/
|
|
2475
2524
|
_setInitialState(state) {
|
|
2476
|
-
let mustLoadOnDemand = false;
|
|
2477
|
-
if (state.open_nodes) {
|
|
2478
|
-
mustLoadOnDemand = this._openInitialNodes(state.open_nodes);
|
|
2479
|
-
}
|
|
2525
|
+
let mustLoadOnDemand = state.open_nodes ? this._openInitialNodes(state.open_nodes) : false;
|
|
2480
2526
|
this._resetSelection();
|
|
2481
2527
|
if (state.selected_node) {
|
|
2482
2528
|
this._selectInitialNodes(state.selected_node);
|
|
@@ -2492,9 +2538,7 @@ var TreeElement = (function () {
|
|
|
2492
2538
|
let newNodesIds = [];
|
|
2493
2539
|
for (let nodeId of nodeIds) {
|
|
2494
2540
|
let node = this._getNodeById(nodeId);
|
|
2495
|
-
if (
|
|
2496
|
-
newNodesIds.push(nodeId);
|
|
2497
|
-
} else {
|
|
2541
|
+
if (node) {
|
|
2498
2542
|
if (!node.is_loading) {
|
|
2499
2543
|
if (node.load_on_demand) {
|
|
2500
2544
|
await loadAndOpenNode(node);
|
|
@@ -2502,13 +2546,13 @@ var TreeElement = (function () {
|
|
|
2502
2546
|
await this._openNode(node, false);
|
|
2503
2547
|
}
|
|
2504
2548
|
}
|
|
2549
|
+
} else {
|
|
2550
|
+
newNodesIds.push(nodeId);
|
|
2505
2551
|
}
|
|
2506
2552
|
}
|
|
2507
2553
|
nodeIds = newNodesIds;
|
|
2508
|
-
if (state.selected_node) {
|
|
2509
|
-
|
|
2510
|
-
this._refreshElements(null);
|
|
2511
|
-
}
|
|
2554
|
+
if (state.selected_node && this._selectInitialNodes(state.selected_node)) {
|
|
2555
|
+
this._refreshElements(null);
|
|
2512
2556
|
}
|
|
2513
2557
|
};
|
|
2514
2558
|
let loadAndOpenNode = async node => {
|
|
@@ -2518,28 +2562,20 @@ var TreeElement = (function () {
|
|
|
2518
2562
|
await openNodes();
|
|
2519
2563
|
}
|
|
2520
2564
|
_getKeyName() {
|
|
2521
|
-
|
|
2522
|
-
return this._saveStateOption;
|
|
2523
|
-
} else {
|
|
2524
|
-
return "tree";
|
|
2525
|
-
}
|
|
2565
|
+
return typeof this._saveStateOption === "string" ? this._saveStateOption : "tree";
|
|
2526
2566
|
}
|
|
2527
2567
|
_loadFromStorage() {
|
|
2528
|
-
|
|
2529
|
-
return this._onGetStateFromStorage();
|
|
2530
|
-
} else {
|
|
2531
|
-
return localStorage.getItem(this._getKeyName());
|
|
2532
|
-
}
|
|
2568
|
+
return this._onGetStateFromStorage ? this._onGetStateFromStorage() : localStorage.getItem(this._getKeyName());
|
|
2533
2569
|
}
|
|
2534
2570
|
_openInitialNodes(nodeIds) {
|
|
2535
2571
|
let mustLoadOnDemand = false;
|
|
2536
2572
|
for (let nodeId of nodeIds) {
|
|
2537
2573
|
let node = this._getNodeById(nodeId);
|
|
2538
2574
|
if (node) {
|
|
2539
|
-
if (
|
|
2540
|
-
node.is_open = true;
|
|
2541
|
-
} else {
|
|
2575
|
+
if (node.load_on_demand) {
|
|
2542
2576
|
mustLoadOnDemand = true;
|
|
2577
|
+
} else {
|
|
2578
|
+
node.is_open = true;
|
|
2543
2579
|
}
|
|
2544
2580
|
}
|
|
2545
2581
|
}
|
|
@@ -2557,18 +2593,19 @@ var TreeElement = (function () {
|
|
|
2557
2593
|
}
|
|
2558
2594
|
_resetSelection() {
|
|
2559
2595
|
let selectedNodes = this._getSelectedNodes();
|
|
2560
|
-
|
|
2596
|
+
for (let node of selectedNodes) {
|
|
2561
2597
|
this._removeFromSelection(node);
|
|
2562
|
-
}
|
|
2598
|
+
}
|
|
2563
2599
|
}
|
|
2564
2600
|
_selectInitialNodes(nodeIds) {
|
|
2565
2601
|
let selectCount = 0;
|
|
2566
2602
|
for (let nodeId of nodeIds) {
|
|
2567
2603
|
let node = this._getNodeById(nodeId);
|
|
2568
|
-
if (node) {
|
|
2569
|
-
|
|
2570
|
-
this._addToSelection(node);
|
|
2604
|
+
if (!node) {
|
|
2605
|
+
continue;
|
|
2571
2606
|
}
|
|
2607
|
+
selectCount += 1;
|
|
2608
|
+
this._addToSelection(node);
|
|
2572
2609
|
}
|
|
2573
2610
|
return selectCount !== 0;
|
|
2574
2611
|
}
|
|
@@ -2584,27 +2621,29 @@ var TreeElement = (function () {
|
|
|
2584
2621
|
}
|
|
2585
2622
|
_checkHorizontalScrolling(pageX) {
|
|
2586
2623
|
let newHorizontalScrollDirection = this._getNewHorizontalScrollDirection(pageX);
|
|
2587
|
-
if (this._horizontalScrollDirection
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2624
|
+
if (this._horizontalScrollDirection === newHorizontalScrollDirection) {
|
|
2625
|
+
return;
|
|
2626
|
+
}
|
|
2627
|
+
this._horizontalScrollDirection = newHorizontalScrollDirection;
|
|
2628
|
+
if (this._horizontalScrollTimeout != null) {
|
|
2629
|
+
window.clearTimeout(this._horizontalScrollTimeout);
|
|
2630
|
+
}
|
|
2631
|
+
if (newHorizontalScrollDirection) {
|
|
2632
|
+
this._horizontalScrollTimeout = window.setTimeout(this._scrollHorizontally.bind(this), 40);
|
|
2595
2633
|
}
|
|
2596
2634
|
}
|
|
2597
2635
|
_checkVerticalScrolling(pageY) {
|
|
2598
2636
|
let newVerticalScrollDirection = this._getNewVerticalScrollDirection(pageY);
|
|
2599
|
-
if (this._verticalScrollDirection
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2637
|
+
if (this._verticalScrollDirection === newVerticalScrollDirection) {
|
|
2638
|
+
return;
|
|
2639
|
+
}
|
|
2640
|
+
this._verticalScrollDirection = newVerticalScrollDirection;
|
|
2641
|
+
if (this._verticalScrollTimeout != null) {
|
|
2642
|
+
window.clearTimeout(this._verticalScrollTimeout);
|
|
2643
|
+
this._verticalScrollTimeout = undefined;
|
|
2644
|
+
}
|
|
2645
|
+
if (newVerticalScrollDirection) {
|
|
2646
|
+
this._verticalScrollTimeout = window.setTimeout(this._scrollVertically.bind(this), 40);
|
|
2608
2647
|
}
|
|
2609
2648
|
}
|
|
2610
2649
|
_getScrollLeft() {
|
|
@@ -2657,22 +2696,17 @@ var TreeElement = (function () {
|
|
|
2657
2696
|
let rightEdge = scrollParentOffset.left + containerWidth;
|
|
2658
2697
|
let leftEdge = scrollParentOffset.left;
|
|
2659
2698
|
let isNearRightEdge = pageX > rightEdge - 20;
|
|
2660
|
-
let isNearLeftEdge = pageX < leftEdge + 20;
|
|
2661
2699
|
if (isNearRightEdge) {
|
|
2662
2700
|
return "right";
|
|
2663
|
-
} else if (isNearLeftEdge) {
|
|
2664
|
-
return "left";
|
|
2665
2701
|
}
|
|
2666
|
-
|
|
2702
|
+
let isNearLeftEdge = pageX < leftEdge + 20;
|
|
2703
|
+
return isNearLeftEdge ? "left" : undefined;
|
|
2667
2704
|
}
|
|
2668
2705
|
_getNewVerticalScrollDirection(pageY) {
|
|
2669
2706
|
if (pageY < this._getScrollParentTop()) {
|
|
2670
2707
|
return "top";
|
|
2671
2708
|
}
|
|
2672
|
-
|
|
2673
|
-
return "bottom";
|
|
2674
|
-
}
|
|
2675
|
-
return undefined;
|
|
2709
|
+
return pageY > this._getScrollParentBottom() ? "bottom" : undefined;
|
|
2676
2710
|
}
|
|
2677
2711
|
_getScrollParentBottom() {
|
|
2678
2712
|
if (this._scrollParentBottom == null) {
|
|
@@ -2711,14 +2745,11 @@ var TreeElement = (function () {
|
|
|
2711
2745
|
let scrollLeft = this._container.scrollLeft;
|
|
2712
2746
|
let windowWidth = window.innerWidth;
|
|
2713
2747
|
let isNearRightEdge = pageX > windowWidth - 20;
|
|
2714
|
-
let isNearLeftEdge = pageX - scrollLeft < 20;
|
|
2715
2748
|
if (isNearRightEdge && this._canScrollRight()) {
|
|
2716
2749
|
return "right";
|
|
2717
2750
|
}
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
}
|
|
2721
|
-
return undefined;
|
|
2751
|
+
let isNearLeftEdge = pageX - scrollLeft < 20;
|
|
2752
|
+
return isNearLeftEdge ? "left" : undefined;
|
|
2722
2753
|
}
|
|
2723
2754
|
_getNewVerticalScrollDirection(pageY) {
|
|
2724
2755
|
let scrollTop = this._container.scrollTop;
|
|
@@ -2727,10 +2758,7 @@ var TreeElement = (function () {
|
|
|
2727
2758
|
return "top";
|
|
2728
2759
|
}
|
|
2729
2760
|
let windowHeight = window.innerHeight;
|
|
2730
|
-
|
|
2731
|
-
return "bottom";
|
|
2732
|
-
}
|
|
2733
|
-
return undefined;
|
|
2761
|
+
return windowHeight - (pageY - scrollTop) < 20 && this._canScrollDown() ? "bottom" : undefined;
|
|
2734
2762
|
}
|
|
2735
2763
|
_canScrollDown() {
|
|
2736
2764
|
return this._container.scrollTop + this._container.clientHeight < this._getDocumentScrollHeight();
|
|
@@ -2775,12 +2803,11 @@ var TreeElement = (function () {
|
|
|
2775
2803
|
_container: container,
|
|
2776
2804
|
_refreshHitAreas: refreshHitAreas
|
|
2777
2805
|
});
|
|
2778
|
-
} else {
|
|
2779
|
-
return new DocumentScrollParent({
|
|
2780
|
-
_refreshHitAreas: refreshHitAreas,
|
|
2781
|
-
_treeElement: treeElement
|
|
2782
|
-
});
|
|
2783
2806
|
}
|
|
2807
|
+
return new DocumentScrollParent({
|
|
2808
|
+
_refreshHitAreas: refreshHitAreas,
|
|
2809
|
+
_treeElement: treeElement
|
|
2810
|
+
});
|
|
2784
2811
|
};
|
|
2785
2812
|
|
|
2786
2813
|
class ScrollHandler {
|
|
@@ -2825,7 +2852,8 @@ var TreeElement = (function () {
|
|
|
2825
2852
|
_getSelectable: getSelectable,
|
|
2826
2853
|
_openParents: openParents,
|
|
2827
2854
|
_saveState: saveState,
|
|
2828
|
-
_triggerEvent: triggerEvent
|
|
2855
|
+
_triggerEvent: triggerEvent,
|
|
2856
|
+
_updateTabStop: updateTabStop
|
|
2829
2857
|
}) {
|
|
2830
2858
|
this._getNodeById = getNodeById;
|
|
2831
2859
|
this._getNodeElementForNode = getNodeElementForNode;
|
|
@@ -2836,12 +2864,13 @@ var TreeElement = (function () {
|
|
|
2836
2864
|
this._selectedNodes = new Set();
|
|
2837
2865
|
this._selectedSingleNode = null;
|
|
2838
2866
|
this._triggerEvent = triggerEvent;
|
|
2867
|
+
this._updateTabStop = updateTabStop;
|
|
2839
2868
|
}
|
|
2840
2869
|
_addToSelection(node) {
|
|
2841
|
-
if (node.id
|
|
2842
|
-
this._selectedNodes.add(node.id);
|
|
2843
|
-
} else {
|
|
2870
|
+
if (node.id == null) {
|
|
2844
2871
|
this._selectedSingleNode = node;
|
|
2872
|
+
} else {
|
|
2873
|
+
this._selectedNodes.add(node.id);
|
|
2845
2874
|
}
|
|
2846
2875
|
}
|
|
2847
2876
|
_clear() {
|
|
@@ -2850,52 +2879,39 @@ var TreeElement = (function () {
|
|
|
2850
2879
|
}
|
|
2851
2880
|
_getSelectedNode() {
|
|
2852
2881
|
let selectedNodes = this._getSelectedNodes();
|
|
2853
|
-
|
|
2854
|
-
return selectedNodes[0] ?? null;
|
|
2855
|
-
} else {
|
|
2856
|
-
return null;
|
|
2857
|
-
}
|
|
2882
|
+
return selectedNodes.length ? selectedNodes[0] ?? null : null;
|
|
2858
2883
|
}
|
|
2859
2884
|
_getSelectedNodes() {
|
|
2860
2885
|
if (this._selectedSingleNode) {
|
|
2861
2886
|
return [this._selectedSingleNode];
|
|
2862
|
-
} else {
|
|
2863
|
-
let selectedNodes = [];
|
|
2864
|
-
this._selectedNodes.forEach(id => {
|
|
2865
|
-
let node = this._getNodeById(id);
|
|
2866
|
-
if (node) {
|
|
2867
|
-
selectedNodes.push(node);
|
|
2868
|
-
}
|
|
2869
|
-
});
|
|
2870
|
-
return selectedNodes;
|
|
2871
2887
|
}
|
|
2888
|
+
let selectedNodes = [];
|
|
2889
|
+
this._selectedNodes.forEach(id => {
|
|
2890
|
+
let node = this._getNodeById(id);
|
|
2891
|
+
if (node) {
|
|
2892
|
+
selectedNodes.push(node);
|
|
2893
|
+
}
|
|
2894
|
+
});
|
|
2895
|
+
return selectedNodes;
|
|
2872
2896
|
}
|
|
2873
2897
|
_getSelectedNodesUnder(parent) {
|
|
2874
2898
|
if (this._selectedSingleNode) {
|
|
2875
|
-
|
|
2876
|
-
return [this._selectedSingleNode];
|
|
2877
|
-
} else {
|
|
2878
|
-
return [];
|
|
2879
|
-
}
|
|
2880
|
-
} else {
|
|
2881
|
-
let selectedNodes = [];
|
|
2882
|
-
this._selectedNodes.forEach(id => {
|
|
2883
|
-
let node = this._getNodeById(id);
|
|
2884
|
-
if (node && parent.isParentOf(node)) {
|
|
2885
|
-
selectedNodes.push(node);
|
|
2886
|
-
}
|
|
2887
|
-
});
|
|
2888
|
-
return selectedNodes;
|
|
2899
|
+
return parent.isParentOf(this._selectedSingleNode) ? [this._selectedSingleNode] : [];
|
|
2889
2900
|
}
|
|
2901
|
+
let selectedNodes = [];
|
|
2902
|
+
this._selectedNodes.forEach(id => {
|
|
2903
|
+
let node = this._getNodeById(id);
|
|
2904
|
+
if (node && parent.isParentOf(node)) {
|
|
2905
|
+
selectedNodes.push(node);
|
|
2906
|
+
}
|
|
2907
|
+
});
|
|
2908
|
+
return selectedNodes;
|
|
2890
2909
|
}
|
|
2891
2910
|
_isNodeSelected(node) {
|
|
2892
2911
|
if (node.id != null) {
|
|
2893
2912
|
return this._selectedNodes.has(node.id);
|
|
2894
|
-
} else if (this._selectedSingleNode) {
|
|
2895
|
-
return this._selectedSingleNode === node;
|
|
2896
|
-
} else {
|
|
2897
|
-
return false;
|
|
2898
2913
|
}
|
|
2914
|
+
return this._selectedSingleNode ? this._selectedSingleNode === node : false;
|
|
2899
2915
|
}
|
|
2900
2916
|
_removeFromSelection(node, includeChildren = false) {
|
|
2901
2917
|
if (node.id == null) {
|
|
@@ -2932,7 +2948,7 @@ var TreeElement = (function () {
|
|
|
2932
2948
|
};
|
|
2933
2949
|
let selectOptions = {
|
|
2934
2950
|
...defaultOptions,
|
|
2935
|
-
...
|
|
2951
|
+
...optionsParam
|
|
2936
2952
|
};
|
|
2937
2953
|
let canSelect = () => {
|
|
2938
2954
|
if (!this._getSelectable()) {
|
|
@@ -2968,10 +2984,20 @@ var TreeElement = (function () {
|
|
|
2968
2984
|
node
|
|
2969
2985
|
});
|
|
2970
2986
|
}
|
|
2987
|
+
this._updateTabStop();
|
|
2971
2988
|
this._saveState();
|
|
2972
2989
|
}
|
|
2973
2990
|
}
|
|
2974
2991
|
|
|
2992
|
+
/* The default icons are svg instead of text: the triangle characters come
|
|
2993
|
+
* from different fonts on each platform, so they differ in shape and size.
|
|
2994
|
+
* They are sized in em to follow the font size, and use currentColor to follow
|
|
2995
|
+
* --tree-element-toggler-color.
|
|
2996
|
+
*/
|
|
2997
|
+
let triangle = points => `<svg width="0.7em" height="0.7em" viewBox="0 0 10 10" focusable="false"><polygon points="${points}" fill="currentColor"/></svg>`;
|
|
2998
|
+
let triangleDown = triangle("0.5,1.5 9.5,1.5 5,9");
|
|
2999
|
+
let triangleLeft = triangle("9,0.5 9,9.5 1.5,5");
|
|
3000
|
+
let triangleRight = triangle("1,0.5 1,9.5 8.5,5");
|
|
2975
3001
|
let defaults = {
|
|
2976
3002
|
animationSpeed: "fast",
|
|
2977
3003
|
autoEscape: true,
|
|
@@ -2980,9 +3006,7 @@ var TreeElement = (function () {
|
|
|
2980
3006
|
buttonLeft: true,
|
|
2981
3007
|
classPrefix: DEFAULT_CLASS_PREFIX,
|
|
2982
3008
|
// the prefix of all css classes
|
|
2983
|
-
//
|
|
2984
|
-
// http://www.fileformat.info/info/unicode/char/25ba/index.htm
|
|
2985
|
-
// closedIcon: undefined,
|
|
3009
|
+
// closedIcon: undefined, // the default is a triangle; see getDefaultClosedIcon
|
|
2986
3010
|
// commonClassName: undefined, // the class of every element; the default is "<classPrefix>-common"
|
|
2987
3011
|
// data: undefined,
|
|
2988
3012
|
// dataFilter: undefined,
|
|
@@ -2999,11 +3023,9 @@ var TreeElement = (function () {
|
|
|
2999
3023
|
// onGetStateFromStorage: undefined,
|
|
3000
3024
|
// onIsMoveHandle: undefined,
|
|
3001
3025
|
// onSetStateFromStorage: undefined,
|
|
3002
|
-
// openedIcon: undefined,
|
|
3026
|
+
// openedIcon: undefined, // the default is a triangle pointing down
|
|
3003
3027
|
openFolderDelay: 500,
|
|
3004
3028
|
// The delay for opening a folder during drag and drop; the value is in milliseconds
|
|
3005
|
-
// The symbol to use for an open node - ▼ BLACK DOWN-POINTING TRIANGLE
|
|
3006
|
-
// http://www.fileformat.info/info/unicode/char/25bc/index.htm
|
|
3007
3029
|
// rtl: undefined, // right-to-left support; true / false (default)
|
|
3008
3030
|
saveState: false,
|
|
3009
3031
|
// true / false / string (local storage key; the default key is "tree")
|
|
@@ -3020,32 +3042,28 @@ var TreeElement = (function () {
|
|
|
3020
3042
|
let setDefaultOptions = (htmlElement, inputOptions) => {
|
|
3021
3043
|
let options = {
|
|
3022
3044
|
...defaults,
|
|
3023
|
-
...inputOptions
|
|
3045
|
+
...inputOptions,
|
|
3046
|
+
animationSpeed: inputOptions.animationSpeed ?? getDefaultAnimationSpeed()
|
|
3024
3047
|
};
|
|
3025
3048
|
options.dataUrl ??= htmlElement.dataset.url;
|
|
3026
3049
|
options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);
|
|
3027
3050
|
options.closedIcon ??= getDefaultClosedIcon(options);
|
|
3028
|
-
options.openedIcon ??=
|
|
3051
|
+
options.openedIcon ??= triangleDown;
|
|
3029
3052
|
return options;
|
|
3030
3053
|
};
|
|
3054
|
+
|
|
3055
|
+
// No animation when the user asked the system for reduced motion
|
|
3056
|
+
let getDefaultAnimationSpeed = () => prefersReducedMotion() ? 0 : defaults.animationSpeed;
|
|
3057
|
+
let prefersReducedMotion = () => typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3031
3058
|
let getDefaultClosedIcon = options => {
|
|
3032
|
-
|
|
3033
|
-
// triangle to the left
|
|
3034
|
-
return "◀";
|
|
3035
|
-
} else {
|
|
3036
|
-
// triangle to the right
|
|
3037
|
-
return "►";
|
|
3038
|
-
}
|
|
3059
|
+
return options.rtl ? triangleLeft : triangleRight;
|
|
3039
3060
|
};
|
|
3040
3061
|
let getRtlOptionFromHTMLElement = htmlElement => {
|
|
3041
3062
|
let dataRtl = htmlElement.dataset.rtl;
|
|
3042
3063
|
if (dataRtl == "") {
|
|
3043
3064
|
return true;
|
|
3044
|
-
} else if (dataRtl === "false") {
|
|
3045
|
-
return false;
|
|
3046
|
-
} else {
|
|
3047
|
-
return Boolean(dataRtl);
|
|
3048
3065
|
}
|
|
3066
|
+
return dataRtl === "false" ? false : Boolean(dataRtl);
|
|
3049
3067
|
};
|
|
3050
3068
|
|
|
3051
3069
|
// Trigger a CustomEvent. Return if the event is processed (true) or cancelled (false).
|
|
@@ -3060,7 +3078,7 @@ var TreeElement = (function () {
|
|
|
3060
3078
|
};
|
|
3061
3079
|
|
|
3062
3080
|
// Generated by config/generateVersion.mjs. Do not edit.
|
|
3063
|
-
let version = "0.
|
|
3081
|
+
let version = "0.3.1";
|
|
3064
3082
|
|
|
3065
3083
|
// The types that appear in the public api. Consumers cannot import them from
|
|
3066
3084
|
// the submodules directly, because those are not exposed in package.json.
|
|
@@ -3071,6 +3089,7 @@ var TreeElement = (function () {
|
|
|
3071
3089
|
_classNames;
|
|
3072
3090
|
_dataLoader;
|
|
3073
3091
|
_dndHandler;
|
|
3092
|
+
_fallbackTabStop;
|
|
3074
3093
|
_htmlElement;
|
|
3075
3094
|
_isInitialized;
|
|
3076
3095
|
_keyHandler;
|
|
@@ -3084,7 +3103,9 @@ var TreeElement = (function () {
|
|
|
3084
3103
|
_tree;
|
|
3085
3104
|
_triggerEventProvider;
|
|
3086
3105
|
|
|
3087
|
-
/**
|
|
3106
|
+
/**
|
|
3107
|
+
@hidden
|
|
3108
|
+
*/
|
|
3088
3109
|
constructor({
|
|
3089
3110
|
htmlElement,
|
|
3090
3111
|
overrideTriggerEventProvider,
|
|
@@ -3097,7 +3118,10 @@ var TreeElement = (function () {
|
|
|
3097
3118
|
this._isInitialized = false;
|
|
3098
3119
|
this._tree = new Node({}, true);
|
|
3099
3120
|
this._nodeMap = new WeakMap();
|
|
3121
|
+
this._fallbackTabStop = null;
|
|
3100
3122
|
let {
|
|
3123
|
+
ariaLabel,
|
|
3124
|
+
ariaLabelledBy,
|
|
3101
3125
|
autoEscape,
|
|
3102
3126
|
buttonLeft,
|
|
3103
3127
|
closedIcon,
|
|
@@ -3124,10 +3148,10 @@ var TreeElement = (function () {
|
|
|
3124
3148
|
let closeNode = this.closeNode.bind(this);
|
|
3125
3149
|
let getNodeElement = this._getNodeElement.bind(this);
|
|
3126
3150
|
let getNodeElementForNode = this._getNodeElementForNode.bind(this);
|
|
3151
|
+
let getFocusedNode = this._getFocusedNode.bind(this);
|
|
3127
3152
|
let getNodeById = this.getNodeById.bind(this);
|
|
3128
3153
|
let getSelectedNode = this.getSelectedNode.bind(this);
|
|
3129
3154
|
let getTree = this.getTree.bind(this);
|
|
3130
|
-
let isFocusOnTree = this._isFocusOnTree.bind(this);
|
|
3131
3155
|
let loadData = this.loadData.bind(this);
|
|
3132
3156
|
let openNode = this.openNode.bind(this);
|
|
3133
3157
|
let openParents = this._openParents.bind(this);
|
|
@@ -3136,6 +3160,7 @@ var TreeElement = (function () {
|
|
|
3136
3160
|
let setNodeElement = this._setNodeElement.bind(this);
|
|
3137
3161
|
let treeElement = this._htmlElement;
|
|
3138
3162
|
let triggerEvent = this._triggerEvent.bind(this);
|
|
3163
|
+
let updateTabStop = this._updateTabStop.bind(this);
|
|
3139
3164
|
let saveState = () => {
|
|
3140
3165
|
saveStateHandler._saveState();
|
|
3141
3166
|
};
|
|
@@ -3146,7 +3171,8 @@ var TreeElement = (function () {
|
|
|
3146
3171
|
_getSelectable: () => this._options.selectable,
|
|
3147
3172
|
_openParents: openParents,
|
|
3148
3173
|
_saveState: saveState,
|
|
3149
|
-
_triggerEvent: triggerEvent
|
|
3174
|
+
_triggerEvent: triggerEvent,
|
|
3175
|
+
_updateTabStop: updateTabStop
|
|
3150
3176
|
});
|
|
3151
3177
|
let addToSelection = selectNodeHandler._addToSelection.bind(selectNodeHandler);
|
|
3152
3178
|
let getSelectedNodes = selectNodeHandler._getSelectedNodes.bind(selectNodeHandler);
|
|
@@ -3199,13 +3225,17 @@ var TreeElement = (function () {
|
|
|
3199
3225
|
});
|
|
3200
3226
|
let keyHandler = new KeyHandler({
|
|
3201
3227
|
_closeNode: closeNode,
|
|
3228
|
+
_getFocusedNode: getFocusedNode,
|
|
3202
3229
|
_getSelectedNode: getSelectedNode,
|
|
3203
|
-
|
|
3230
|
+
_getTree: getTree,
|
|
3204
3231
|
_keyboardSupport: keyboardSupport,
|
|
3205
3232
|
_openNode: openNode,
|
|
3206
|
-
_selectNode: selectNode
|
|
3233
|
+
_selectNode: selectNode,
|
|
3234
|
+
_triggerEvent: triggerEvent
|
|
3207
3235
|
});
|
|
3208
3236
|
let renderer = new ElementsRenderer({
|
|
3237
|
+
_ariaLabel: ariaLabel,
|
|
3238
|
+
_ariaLabelledBy: ariaLabelledBy,
|
|
3209
3239
|
_autoEscape: autoEscape,
|
|
3210
3240
|
_buttonLeft: buttonLeft,
|
|
3211
3241
|
_classNames: classNames,
|
|
@@ -3300,10 +3330,11 @@ var TreeElement = (function () {
|
|
|
3300
3330
|
* @param mustSetFocus - Move the focus to the node. Default `true`.
|
|
3301
3331
|
* @group Selection
|
|
3302
3332
|
*/
|
|
3303
|
-
addToSelection(node, mustSetFocus) {
|
|
3333
|
+
addToSelection(node, mustSetFocus = true) {
|
|
3304
3334
|
this._selectNodeHandler._addToSelection(node);
|
|
3305
3335
|
this._openParents(node);
|
|
3306
|
-
this._getNodeElementForNode(node)._select(mustSetFocus
|
|
3336
|
+
this._getNodeElementForNode(node)._select(mustSetFocus);
|
|
3337
|
+
this._updateTabStop();
|
|
3307
3338
|
this._saveState();
|
|
3308
3339
|
}
|
|
3309
3340
|
|
|
@@ -3325,16 +3356,24 @@ var TreeElement = (function () {
|
|
|
3325
3356
|
}
|
|
3326
3357
|
|
|
3327
3358
|
/**
|
|
3328
|
-
* Closes a folder.
|
|
3359
|
+
* Closes a folder. Await the promise when you need to know the closing
|
|
3360
|
+
* animation has finished.
|
|
3361
|
+
*
|
|
3362
|
+
* @example
|
|
3363
|
+
* ```js
|
|
3364
|
+
* await tree.closeNode(node);
|
|
3365
|
+
* console.log("closed");
|
|
3366
|
+
* ```
|
|
3329
3367
|
*
|
|
3330
3368
|
* @param slide - Override the `slide` option for this call.
|
|
3331
3369
|
* @group Opening and closing
|
|
3332
3370
|
*/
|
|
3333
|
-
closeNode(node, slide) {
|
|
3334
|
-
if (node.isFolder() || node.isEmptyFolder) {
|
|
3335
|
-
|
|
3336
|
-
this._saveState();
|
|
3371
|
+
async closeNode(node, slide) {
|
|
3372
|
+
if (!(node.isFolder() || node.isEmptyFolder)) {
|
|
3373
|
+
return;
|
|
3337
3374
|
}
|
|
3375
|
+
await this._createFolderElement(node)._close(slide ?? this._options.slide, this._options.animationSpeed);
|
|
3376
|
+
this._saveState();
|
|
3338
3377
|
}
|
|
3339
3378
|
|
|
3340
3379
|
/**
|
|
@@ -3358,11 +3397,7 @@ var TreeElement = (function () {
|
|
|
3358
3397
|
*/
|
|
3359
3398
|
getNode(element) {
|
|
3360
3399
|
let liElement = element.closest(`li.${this._classNames.common}`);
|
|
3361
|
-
|
|
3362
|
-
return this._nodeMap.get(liElement) ?? null;
|
|
3363
|
-
} else {
|
|
3364
|
-
return null;
|
|
3365
|
-
}
|
|
3400
|
+
return liElement ? this._nodeMap.get(liElement) ?? null : null;
|
|
3366
3401
|
}
|
|
3367
3402
|
|
|
3368
3403
|
/**
|
|
@@ -3653,6 +3688,7 @@ var TreeElement = (function () {
|
|
|
3653
3688
|
removeFromSelection(node) {
|
|
3654
3689
|
this._selectNodeHandler._removeFromSelection(node);
|
|
3655
3690
|
this._getNodeElementForNode(node)._deselect();
|
|
3691
|
+
this._updateTabStop();
|
|
3656
3692
|
this._saveState();
|
|
3657
3693
|
}
|
|
3658
3694
|
|
|
@@ -3698,7 +3734,12 @@ var TreeElement = (function () {
|
|
|
3698
3734
|
this._saveStateHandler._saveState();
|
|
3699
3735
|
return;
|
|
3700
3736
|
}
|
|
3701
|
-
|
|
3737
|
+
|
|
3738
|
+
// Unlike a click, selecting the selected node again keeps it selected
|
|
3739
|
+
this._selectNodeHandler._selectSingleNode(node, {
|
|
3740
|
+
mustToggle: false,
|
|
3741
|
+
...options
|
|
3742
|
+
});
|
|
3702
3743
|
}
|
|
3703
3744
|
|
|
3704
3745
|
/**
|
|
@@ -3724,17 +3765,19 @@ var TreeElement = (function () {
|
|
|
3724
3765
|
}
|
|
3725
3766
|
|
|
3726
3767
|
/**
|
|
3727
|
-
* Closes an open node and opens a closed one.
|
|
3768
|
+
* Closes an open node and opens a closed one. Await the promise when you
|
|
3769
|
+
* need to know the node is really open or closed, like with `openNode` and
|
|
3770
|
+
* `closeNode`.
|
|
3728
3771
|
*
|
|
3729
3772
|
* @param slide - Override the `slide` option for this call.
|
|
3730
3773
|
* @group Opening and closing
|
|
3731
3774
|
*/
|
|
3732
|
-
toggle(node, slide = null) {
|
|
3775
|
+
async toggle(node, slide = null) {
|
|
3733
3776
|
let mustSlide = slide ?? this._options.slide;
|
|
3734
3777
|
if (node.is_open) {
|
|
3735
|
-
this.closeNode(node, mustSlide);
|
|
3778
|
+
await this.closeNode(node, mustSlide);
|
|
3736
3779
|
} else {
|
|
3737
|
-
|
|
3780
|
+
await this.openNode(node, mustSlide);
|
|
3738
3781
|
}
|
|
3739
3782
|
}
|
|
3740
3783
|
|
|
@@ -3772,7 +3815,7 @@ var TreeElement = (function () {
|
|
|
3772
3815
|
if (idIsChanged) {
|
|
3773
3816
|
this._tree.addNodeToIndex(node);
|
|
3774
3817
|
}
|
|
3775
|
-
if (typeof data === "object" && data.children && data.children
|
|
3818
|
+
if (typeof data === "object" && data.children && Array.isArray(data.children)) {
|
|
3776
3819
|
node.removeChildren();
|
|
3777
3820
|
if (data.children.length) {
|
|
3778
3821
|
node.loadFromData(data.children);
|
|
@@ -3780,15 +3823,45 @@ var TreeElement = (function () {
|
|
|
3780
3823
|
}
|
|
3781
3824
|
this._refreshElements(node);
|
|
3782
3825
|
}
|
|
3826
|
+
|
|
3827
|
+
// Open the nodes up to the autoOpen level. A folder that is loaded on
|
|
3828
|
+
// demand is fetched first, and its children are opened when the data has
|
|
3829
|
+
// arrived.
|
|
3830
|
+
async _autoOpenNodesOnDemand() {
|
|
3831
|
+
let maxLevel = this._getAutoOpenMaxLevel();
|
|
3832
|
+
let openNodes = async () => {
|
|
3833
|
+
let loading = [];
|
|
3834
|
+
this._tree.iterate((node, level) => {
|
|
3835
|
+
if (node.load_on_demand) {
|
|
3836
|
+
if (!node.is_loading) {
|
|
3837
|
+
loading.push(this.openNode(node, false).then(openNodes));
|
|
3838
|
+
}
|
|
3839
|
+
return false;
|
|
3840
|
+
}
|
|
3841
|
+
void this.openNode(node, false);
|
|
3842
|
+
return level !== maxLevel;
|
|
3843
|
+
});
|
|
3844
|
+
await Promise.all(loading);
|
|
3845
|
+
};
|
|
3846
|
+
await openNodes();
|
|
3847
|
+
}
|
|
3783
3848
|
_createFolderElement(node) {
|
|
3784
3849
|
let classNames = this._classNames;
|
|
3785
3850
|
let closedIconElement = this._renderer._closedIconElement;
|
|
3786
3851
|
let getScrollLeft = this._scrollHandler._getScrollLeft.bind(this._scrollHandler);
|
|
3787
3852
|
let openedIconElement = this._renderer._openedIconElement;
|
|
3788
|
-
let renderChildren = this._renderer._renderChildren.bind(this._renderer);
|
|
3789
3853
|
let tabIndex = this._options.tabIndex;
|
|
3790
3854
|
let treeElement = this._htmlElement;
|
|
3791
3855
|
let triggerEvent = this._triggerEvent.bind(this);
|
|
3856
|
+
|
|
3857
|
+
// A selected node in a closed folder is rendered when the folder is
|
|
3858
|
+
// opened, which can be after it was selected. It becomes the tab stop
|
|
3859
|
+
// then, so the fallback tab stop must go.
|
|
3860
|
+
let renderChildren = folder => {
|
|
3861
|
+
let ul = this._renderer._renderChildren(folder);
|
|
3862
|
+
this._updateTabStop();
|
|
3863
|
+
return ul;
|
|
3864
|
+
};
|
|
3792
3865
|
return new FolderElement({
|
|
3793
3866
|
_classNames: classNames,
|
|
3794
3867
|
_closedIconElement: closedIconElement,
|
|
@@ -3821,12 +3894,7 @@ var TreeElement = (function () {
|
|
|
3821
3894
|
*/
|
|
3822
3895
|
_createRequestUrl(node) {
|
|
3823
3896
|
let dataUrl = this._options.dataUrl;
|
|
3824
|
-
let url;
|
|
3825
|
-
if (typeof dataUrl === "function") {
|
|
3826
|
-
url = dataUrl(node);
|
|
3827
|
-
} else {
|
|
3828
|
-
url = dataUrl;
|
|
3829
|
-
}
|
|
3897
|
+
let url = typeof dataUrl === "function" ? dataUrl(node) : dataUrl;
|
|
3830
3898
|
if (!url) {
|
|
3831
3899
|
return null;
|
|
3832
3900
|
}
|
|
@@ -3862,33 +3930,54 @@ var TreeElement = (function () {
|
|
|
3862
3930
|
_getAutoOpenMaxLevel() {
|
|
3863
3931
|
if (this._options.autoOpen === true) {
|
|
3864
3932
|
return -1;
|
|
3865
|
-
}
|
|
3933
|
+
}
|
|
3934
|
+
if (typeof this._options.autoOpen === "number") {
|
|
3866
3935
|
return this._options.autoOpen;
|
|
3867
|
-
}
|
|
3936
|
+
}
|
|
3937
|
+
if (typeof this._options.autoOpen === "string") {
|
|
3868
3938
|
return parseInt(this._options.autoOpen, 10);
|
|
3869
3939
|
}
|
|
3870
3940
|
|
|
3871
3941
|
/* istanbul ignore next @preserve */
|
|
3872
3942
|
return 0;
|
|
3873
3943
|
}
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
}
|
|
3944
|
+
|
|
3945
|
+
// The title span of the first node, or null when the tree is empty
|
|
3946
|
+
_getFirstTitleSpan() {
|
|
3947
|
+
let firstElement = this._tree.children[0]?.element;
|
|
3948
|
+
return firstElement ? firstElement.querySelector(`:scope > .${this._classNames.element} > span.${this._classNames.title}`) : null;
|
|
3949
|
+
}
|
|
3950
|
+
|
|
3951
|
+
// The node of the HTML element that has the focus, if it is in this tree
|
|
3952
|
+
_getFocusedNode() {
|
|
3953
|
+
let activeElement = document.activeElement;
|
|
3954
|
+
|
|
3955
|
+
/* istanbul ignore if */
|
|
3956
|
+
if (!activeElement) {
|
|
3879
3957
|
return null;
|
|
3880
3958
|
}
|
|
3959
|
+
|
|
3960
|
+
// The keyboard must still work for input elements.
|
|
3961
|
+
let tagName = activeElement.tagName;
|
|
3962
|
+
if (tagName !== "A" && tagName !== "SPAN") {
|
|
3963
|
+
return null;
|
|
3964
|
+
}
|
|
3965
|
+
let node = this.getNode(activeElement);
|
|
3966
|
+
return node?.tree === this._tree ? node : null;
|
|
3967
|
+
}
|
|
3968
|
+
_getNodeElement(element) {
|
|
3969
|
+
let node = this.getNode(element);
|
|
3970
|
+
return node ? this._getNodeElementForNode(node) : null;
|
|
3881
3971
|
}
|
|
3882
3972
|
_getNodeElementForNode(node) {
|
|
3883
|
-
|
|
3884
|
-
return this._createFolderElement(node);
|
|
3885
|
-
} else {
|
|
3886
|
-
return this._createNodeElement(node);
|
|
3887
|
-
}
|
|
3973
|
+
return node.isFolder() ? this._createFolderElement(node) : this._createNodeElement(node);
|
|
3888
3974
|
}
|
|
3889
3975
|
_getNodeIdToBeSelected() {
|
|
3890
3976
|
return this._saveStateHandler._getNodeIdToBeSelected();
|
|
3891
3977
|
}
|
|
3978
|
+
_hasRenderedSelectedNode() {
|
|
3979
|
+
return this.getSelectedNodes().some(node => Boolean(node.element));
|
|
3980
|
+
}
|
|
3892
3981
|
_initData() {
|
|
3893
3982
|
if (this._options.data) {
|
|
3894
3983
|
this.loadData(this._options.data);
|
|
@@ -3903,10 +3992,11 @@ var TreeElement = (function () {
|
|
|
3903
3992
|
}
|
|
3904
3993
|
_initTree(data) {
|
|
3905
3994
|
let doInit = () => {
|
|
3906
|
-
if (
|
|
3907
|
-
|
|
3908
|
-
this._triggerEvent("tree.init");
|
|
3995
|
+
if (this._isInitialized) {
|
|
3996
|
+
return;
|
|
3909
3997
|
}
|
|
3998
|
+
this._isInitialized = true;
|
|
3999
|
+
this._triggerEvent("tree.init");
|
|
3910
4000
|
};
|
|
3911
4001
|
this._tree = new this._options.nodeClass(null, true, this._options.nodeClass);
|
|
3912
4002
|
this._selectNodeHandler._clear();
|
|
@@ -3923,32 +4013,22 @@ var TreeElement = (function () {
|
|
|
3923
4013
|
|
|
3924
4014
|
// Does an HTML element of the tree have the focus?
|
|
3925
4015
|
_isFocusOnTree() {
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
/* istanbul ignore if */
|
|
3929
|
-
if (!activeElement) {
|
|
3930
|
-
return false;
|
|
3931
|
-
}
|
|
3932
|
-
|
|
3933
|
-
// The keyboard must still work for input elements.
|
|
3934
|
-
let tagName = activeElement.tagName;
|
|
3935
|
-
if (tagName !== "A" && tagName !== "SPAN") {
|
|
3936
|
-
return false;
|
|
3937
|
-
}
|
|
3938
|
-
let node = this.getNode(activeElement);
|
|
3939
|
-
return node?.tree === this._tree;
|
|
4016
|
+
return this._getFocusedNode() !== null;
|
|
3940
4017
|
}
|
|
3941
4018
|
_isSelectedNodeInSubtree(subtree) {
|
|
3942
4019
|
let selectedNode = this.getSelectedNode();
|
|
3943
|
-
|
|
3944
|
-
return false;
|
|
3945
|
-
} else {
|
|
3946
|
-
return subtree === selectedNode || subtree.isParentOf(selectedNode);
|
|
3947
|
-
}
|
|
4020
|
+
return selectedNode ? subtree === selectedNode || subtree.isParentOf(selectedNode) : false;
|
|
3948
4021
|
}
|
|
3949
4022
|
async _loadFolderOnDemand(node, slide) {
|
|
3950
4023
|
node.is_loading = true;
|
|
3951
4024
|
await this.loadDataFromUrl(undefined, node);
|
|
4025
|
+
|
|
4026
|
+
// Loading failed, or there is no url. Opening the node now would load it
|
|
4027
|
+
// again, without end. Leave it closed so the user can try again.
|
|
4028
|
+
if (node.load_on_demand) {
|
|
4029
|
+
node.is_loading = false;
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
3952
4032
|
await this.openNode(node, slide);
|
|
3953
4033
|
}
|
|
3954
4034
|
_loadSubtree(data, parentNode) {
|
|
@@ -3958,10 +4038,7 @@ var TreeElement = (function () {
|
|
|
3958
4038
|
this._refreshElements(parentNode);
|
|
3959
4039
|
}
|
|
3960
4040
|
_mouseCapture(positionInfo) {
|
|
3961
|
-
|
|
3962
|
-
return false;
|
|
3963
|
-
}
|
|
3964
|
-
return this._dndHandler._mouseCapture(positionInfo);
|
|
4041
|
+
return this._options.dragAndDrop ? this._dndHandler._mouseCapture(positionInfo) : false;
|
|
3965
4042
|
}
|
|
3966
4043
|
_mouseDrag(positionInfo) {
|
|
3967
4044
|
/* istanbul ignore if */
|
|
@@ -3974,6 +4051,7 @@ var TreeElement = (function () {
|
|
|
3974
4051
|
}
|
|
3975
4052
|
_mouseStart(positionInfo) {
|
|
3976
4053
|
/* istanbul ignore if */
|
|
4054
|
+
// eslint-disable-next-line unicorn/prefer-ternary
|
|
3977
4055
|
if (!this._options.dragAndDrop) {
|
|
3978
4056
|
return false;
|
|
3979
4057
|
}
|
|
@@ -4005,6 +4083,7 @@ var TreeElement = (function () {
|
|
|
4005
4083
|
if (mustSelect) {
|
|
4006
4084
|
this._selectCurrentNode(mustSetFocus);
|
|
4007
4085
|
}
|
|
4086
|
+
this._updateTabStop();
|
|
4008
4087
|
this._triggerEvent("tree.refresh");
|
|
4009
4088
|
}
|
|
4010
4089
|
_saveState() {
|
|
@@ -4012,10 +4091,11 @@ var TreeElement = (function () {
|
|
|
4012
4091
|
}
|
|
4013
4092
|
_selectCurrentNode(mustSetFocus) {
|
|
4014
4093
|
let node = this.getSelectedNode();
|
|
4015
|
-
if (node) {
|
|
4016
|
-
|
|
4017
|
-
nodeElement._select(mustSetFocus);
|
|
4094
|
+
if (!node) {
|
|
4095
|
+
return;
|
|
4018
4096
|
}
|
|
4097
|
+
let nodeElement = this._getNodeElementForNode(node);
|
|
4098
|
+
nodeElement._select(mustSetFocus);
|
|
4019
4099
|
}
|
|
4020
4100
|
|
|
4021
4101
|
// Set initial state, either by restoring the state or auto-opening nodes
|
|
@@ -4024,14 +4104,13 @@ var TreeElement = (function () {
|
|
|
4024
4104
|
let restoreState = () => {
|
|
4025
4105
|
// result: is state restored, must load on demand?
|
|
4026
4106
|
let state = this._saveStateHandler._getStateFromStorage();
|
|
4027
|
-
if (
|
|
4028
|
-
return [false, false];
|
|
4029
|
-
} else {
|
|
4107
|
+
if (state) {
|
|
4030
4108
|
let mustLoadOnDemand = this._saveStateHandler._setInitialState(state);
|
|
4031
4109
|
|
|
4032
4110
|
// return true: the state is restored
|
|
4033
4111
|
return [true, mustLoadOnDemand];
|
|
4034
4112
|
}
|
|
4113
|
+
return [false, false];
|
|
4035
4114
|
};
|
|
4036
4115
|
let autoOpenNodes = () => {
|
|
4037
4116
|
// result: must load on demand?
|
|
@@ -4044,12 +4123,12 @@ var TreeElement = (function () {
|
|
|
4044
4123
|
if (node.load_on_demand) {
|
|
4045
4124
|
mustLoadOnDemand = true;
|
|
4046
4125
|
return false;
|
|
4047
|
-
}
|
|
4048
|
-
|
|
4049
|
-
} else {
|
|
4126
|
+
}
|
|
4127
|
+
if (node.hasChildren()) {
|
|
4050
4128
|
node.is_open = true;
|
|
4051
4129
|
return level !== maxLevel;
|
|
4052
4130
|
}
|
|
4131
|
+
return false;
|
|
4053
4132
|
});
|
|
4054
4133
|
return mustLoadOnDemand;
|
|
4055
4134
|
};
|
|
@@ -4063,50 +4142,12 @@ var TreeElement = (function () {
|
|
|
4063
4142
|
|
|
4064
4143
|
// Set the initial state for nodes that are loaded on demand
|
|
4065
4144
|
async _setInitialStateOnDemand() {
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
void this._saveStateHandler._setInitialStateOnDemand(state).then(() => {
|
|
4073
|
-
resolve();
|
|
4074
|
-
});
|
|
4075
|
-
return true;
|
|
4076
|
-
}
|
|
4077
|
-
};
|
|
4078
|
-
let autoOpenNodes = () => {
|
|
4079
|
-
let maxLevel = this._getAutoOpenMaxLevel();
|
|
4080
|
-
let loadingCount = 0;
|
|
4081
|
-
let loadAndOpenNode = node => {
|
|
4082
|
-
loadingCount += 1;
|
|
4083
|
-
void this.openNode(node, false).then(() => {
|
|
4084
|
-
loadingCount -= 1;
|
|
4085
|
-
openNodes();
|
|
4086
|
-
});
|
|
4087
|
-
};
|
|
4088
|
-
let openNodes = () => {
|
|
4089
|
-
this._tree.iterate((node, level) => {
|
|
4090
|
-
if (node.load_on_demand) {
|
|
4091
|
-
if (!node.is_loading) {
|
|
4092
|
-
loadAndOpenNode(node);
|
|
4093
|
-
}
|
|
4094
|
-
return false;
|
|
4095
|
-
} else {
|
|
4096
|
-
void this.openNode(node, false);
|
|
4097
|
-
return level !== maxLevel;
|
|
4098
|
-
}
|
|
4099
|
-
});
|
|
4100
|
-
if (loadingCount === 0) {
|
|
4101
|
-
resolve();
|
|
4102
|
-
}
|
|
4103
|
-
};
|
|
4104
|
-
openNodes();
|
|
4105
|
-
};
|
|
4106
|
-
if (!restoreState()) {
|
|
4107
|
-
autoOpenNodes();
|
|
4108
|
-
}
|
|
4109
|
-
});
|
|
4145
|
+
let state = this._saveStateHandler._getStateFromStorage();
|
|
4146
|
+
if (state) {
|
|
4147
|
+
await this._saveStateHandler._setInitialStateOnDemand(state);
|
|
4148
|
+
} else {
|
|
4149
|
+
await this._autoOpenNodesOnDemand();
|
|
4150
|
+
}
|
|
4110
4151
|
}
|
|
4111
4152
|
|
|
4112
4153
|
// Set this HTML element to this node in the node map.
|
|
@@ -4116,6 +4157,23 @@ var TreeElement = (function () {
|
|
|
4116
4157
|
_triggerEvent(eventName, values) {
|
|
4117
4158
|
return this._triggerEventProvider(this._htmlElement, eventName, values);
|
|
4118
4159
|
}
|
|
4160
|
+
|
|
4161
|
+
/* Keyboard users reach the tree through the tab stop. The selected node is
|
|
4162
|
+
* the tab stop, see NodeElement.select. Without a selected node, the first
|
|
4163
|
+
* node is the tab stop, so the tree can always be reached.
|
|
4164
|
+
*/
|
|
4165
|
+
_updateTabStop() {
|
|
4166
|
+
let tabIndex = this._options.tabIndex;
|
|
4167
|
+
let previousTabStop = this._fallbackTabStop;
|
|
4168
|
+
let tabStop = tabIndex == null || this._hasRenderedSelectedNode() ? null : this._getFirstTitleSpan();
|
|
4169
|
+
if (previousTabStop && previousTabStop !== tabStop && previousTabStop.getAttribute("aria-selected") !== "true") {
|
|
4170
|
+
previousTabStop.setAttribute("tabindex", "-1");
|
|
4171
|
+
}
|
|
4172
|
+
if (tabStop && tabIndex != null) {
|
|
4173
|
+
tabStop.setAttribute("tabindex", String(tabIndex));
|
|
4174
|
+
}
|
|
4175
|
+
this._fallbackTabStop = tabStop;
|
|
4176
|
+
}
|
|
4119
4177
|
}
|
|
4120
4178
|
|
|
4121
4179
|
return TreeElement;
|