tree-element 0.1.1 → 0.2.0
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 +33 -29
- package/lib/animation.js +5 -5
- package/lib/animation.js.map +1 -1
- package/lib/classNames.d.ts.map +1 -1
- package/lib/classNames.js +2 -2
- package/lib/classNames.js.map +1 -1
- package/lib/dataLoader.d.ts.map +1 -1
- package/lib/dataLoader.js +14 -20
- package/lib/dataLoader.js.map +1 -1
- package/lib/dragAndDropHandler/binarySearch.js +3 -3
- package/lib/dragAndDropHandler/binarySearch.js.map +1 -1
- package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
- package/lib/dragAndDropHandler/dragElement.js +9 -12
- package/lib/dragAndDropHandler/dragElement.js.map +1 -1
- package/lib/dragAndDropHandler/generateHitAreas.d.ts.map +1 -1
- package/lib/dragAndDropHandler/generateHitAreas.js +25 -25
- package/lib/dragAndDropHandler/generateHitAreas.js.map +1 -1
- package/lib/dragAndDropHandler/index.d.ts.map +1 -1
- package/lib/dragAndDropHandler/index.js +90 -114
- package/lib/dragAndDropHandler/index.js.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.js +10 -10
- package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
- package/lib/dragAndDropHandler/types.d.ts.map +1 -1
- package/lib/elementsRenderer.d.ts +15 -6
- package/lib/elementsRenderer.d.ts.map +1 -1
- package/lib/elementsRenderer.js +157 -121
- package/lib/elementsRenderer.js.map +1 -1
- package/lib/events.d.ts.map +1 -1
- package/lib/index.d.ts +5 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +249 -252
- package/lib/index.js.map +1 -1
- package/lib/keyHandler.d.ts +2 -3
- package/lib/keyHandler.d.ts.map +1 -1
- package/lib/keyHandler.js +26 -25
- package/lib/keyHandler.js.map +1 -1
- package/lib/methodTypes.d.ts +1 -1
- package/lib/methodTypes.d.ts.map +1 -1
- package/lib/mouseHandler.d.ts.map +1 -1
- package/lib/mouseHandler.js +26 -42
- package/lib/mouseHandler.js.map +1 -1
- package/lib/mouseUtils.d.ts.map +1 -1
- package/lib/mouseUtils.js +2 -2
- package/lib/mouseUtils.js.map +1 -1
- package/lib/node.d.ts +2 -1
- package/lib/node.d.ts.map +1 -1
- package/lib/node.js +36 -35
- package/lib/node.js.map +1 -1
- package/lib/nodeElement/borderDropHint.d.ts.map +1 -1
- package/lib/nodeElement/borderDropHint.js +4 -5
- package/lib/nodeElement/borderDropHint.js.map +1 -1
- package/lib/nodeElement/folderElement.d.ts +7 -4
- package/lib/nodeElement/folderElement.d.ts.map +1 -1
- package/lib/nodeElement/folderElement.js +61 -42
- package/lib/nodeElement/folderElement.js.map +1 -1
- package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
- package/lib/nodeElement/ghostDropHint.js +5 -9
- package/lib/nodeElement/ghostDropHint.js.map +1 -1
- package/lib/nodeElement/index.d.ts +2 -1
- package/lib/nodeElement/index.d.ts.map +1 -1
- package/lib/nodeElement/index.js +34 -26
- 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.map +1 -1
- package/lib/positionUtils.js +3 -3
- package/lib/positionUtils.js.map +1 -1
- package/lib/requestUrl.d.ts +1 -1
- package/lib/requestUrl.d.ts.map +1 -1
- package/lib/requestUrl.js +4 -6
- package/lib/requestUrl.js.map +1 -1
- package/lib/saveStateHandler.d.ts.map +1 -1
- package/lib/saveStateHandler.js +38 -48
- package/lib/saveStateHandler.js.map +1 -1
- package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/containerScrollParent.js +9 -11
- package/lib/scrollHandler/containerScrollParent.js.map +1 -1
- package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/createScrollParent.js +10 -10
- package/lib/scrollHandler/createScrollParent.js.map +1 -1
- package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/documentScrollParent.js +16 -19
- package/lib/scrollHandler/documentScrollParent.js.map +1 -1
- package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/scrollParent.js +11 -17
- package/lib/scrollHandler/scrollParent.js.map +1 -1
- package/lib/scrollHandler.d.ts.map +1 -1
- package/lib/scrollHandler.js +11 -14
- package/lib/scrollHandler.js.map +1 -1
- package/lib/selectNodeHandler.d.ts +2 -2
- package/lib/selectNodeHandler.d.ts.map +1 -1
- package/lib/selectNodeHandler.js +45 -54
- package/lib/selectNodeHandler.js.map +1 -1
- package/lib/setDefaultOptions.d.ts.map +1 -1
- package/lib/setDefaultOptions.js +23 -28
- package/lib/setDefaultOptions.js.map +1 -1
- package/lib/triggerCustomEvent.d.ts.map +1 -1
- package/lib/triggerCustomEvent.js +2 -2
- package/lib/triggerCustomEvent.js.map +1 -1
- package/lib/util.d.ts.map +1 -1
- package/lib/util.js +2 -2
- 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 +5 -3
- package/src/animation.ts +1 -1
- package/src/classNames.ts +52 -52
- package/src/dataLoader.ts +68 -71
- package/src/dragAndDropHandler/binarySearch.ts +17 -17
- package/src/dragAndDropHandler/dragElement.ts +50 -50
- package/src/dragAndDropHandler/generateHitAreas.ts +156 -161
- package/src/dragAndDropHandler/index.ts +342 -351
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +59 -63
- package/src/dragAndDropHandler/types.ts +5 -5
- package/src/elementsRenderer.ts +351 -298
- package/src/events.ts +216 -216
- package/src/header.txt +1 -1
- package/src/index.ts +52 -82
- package/src/keyHandler.ts +125 -115
- package/src/methodTypes.ts +4 -7
- package/src/mouseHandler.ts +314 -317
- package/src/mouseUtils.ts +14 -14
- package/src/node.ts +761 -766
- package/src/nodeElement/borderDropHint.ts +25 -25
- package/src/nodeElement/folderElement.ts +135 -112
- package/src/nodeElement/ghostDropHint.ts +62 -62
- package/src/nodeElement/index.ts +88 -74
- package/src/nodeUtils.ts +5 -5
- package/src/options.ts +6 -2
- package/src/requestUrl.ts +3 -3
- package/src/saveStateHandler.ts +204 -206
- package/src/scrollHandler/containerScrollParent.ts +49 -52
- package/src/scrollHandler/createScrollParent.ts +27 -27
- package/src/scrollHandler/documentScrollParent.ts +70 -70
- package/src/scrollHandler/scrollParent.ts +98 -98
- package/src/scrollHandler.ts +45 -45
- package/src/selectNodeHandler.ts +176 -166
- package/src/setDefaultOptions.ts +25 -22
- package/src/triggerCustomEvent.ts +7 -3
- package/src/util.ts +2 -2
- package/src/version.ts +1 -1
- package/tree_element.debug.js +3752 -3784
- package/tree_element.debug.js.map +1 -1
- package/tree_element.js +2 -2
- package/tree_element.js.map +1 -1
package/src/index.ts
CHANGED
|
@@ -54,13 +54,10 @@ interface TreeElementParams extends Partial<TreeElementOptions> {
|
|
|
54
54
|
/** Replaces how events are dispatched. It must return whether the event
|
|
55
55
|
* was not cancelled. This exists for tests and for integrating with
|
|
56
56
|
* another event system. */
|
|
57
|
-
overrideTriggerEventProvider?: TriggerEventProvider
|
|
57
|
+
overrideTriggerEventProvider?: TriggerEventProvider;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export default class TreeElement {
|
|
61
|
-
/** @hidden */
|
|
62
|
-
public tree: Node;
|
|
63
|
-
|
|
64
61
|
private classNames: ClassNames;
|
|
65
62
|
private dataLoader: DataLoader;
|
|
66
63
|
private dndHandler: DragAndDropHandler;
|
|
@@ -74,14 +71,20 @@ export default class TreeElement {
|
|
|
74
71
|
private saveStateHandler: SaveStateHandler;
|
|
75
72
|
private scrollHandler: ScrollHandler;
|
|
76
73
|
private selectNodeHandler: SelectNodeHandler;
|
|
74
|
+
private tree: Node;
|
|
77
75
|
private triggerEventProvider: TriggerEventProvider;
|
|
78
76
|
|
|
79
77
|
/** @hidden */
|
|
80
|
-
constructor({
|
|
78
|
+
constructor({
|
|
79
|
+
htmlElement,
|
|
80
|
+
overrideTriggerEventProvider,
|
|
81
|
+
...options
|
|
82
|
+
}: TreeElementParams) {
|
|
81
83
|
this.htmlElement = htmlElement;
|
|
82
84
|
this.options = setDefaultOptions(htmlElement, options);
|
|
83
85
|
this.classNames = createClassNames(this.options);
|
|
84
|
-
this.triggerEventProvider =
|
|
86
|
+
this.triggerEventProvider =
|
|
87
|
+
overrideTriggerEventProvider ?? triggerCustomEvent;
|
|
85
88
|
|
|
86
89
|
this.isInitialized = false;
|
|
87
90
|
this.tree = new Node({}, true);
|
|
@@ -130,7 +133,7 @@ export default class TreeElement {
|
|
|
130
133
|
|
|
131
134
|
const saveState = () => {
|
|
132
135
|
saveStateHandler.saveState();
|
|
133
|
-
}
|
|
136
|
+
};
|
|
134
137
|
|
|
135
138
|
const selectNodeHandler = new SelectNodeHandler({
|
|
136
139
|
getNodeById,
|
|
@@ -139,7 +142,7 @@ export default class TreeElement {
|
|
|
139
142
|
getSelectable: () => this.options.selectable,
|
|
140
143
|
openParents,
|
|
141
144
|
saveState,
|
|
142
|
-
triggerEvent
|
|
145
|
+
triggerEvent,
|
|
143
146
|
});
|
|
144
147
|
|
|
145
148
|
const addToSelection =
|
|
@@ -150,7 +153,8 @@ export default class TreeElement {
|
|
|
150
153
|
selectNodeHandler.isNodeSelected.bind(selectNodeHandler);
|
|
151
154
|
const removeFromSelection =
|
|
152
155
|
selectNodeHandler.removeFromSelection.bind(selectNodeHandler);
|
|
153
|
-
const selectNode =
|
|
156
|
+
const selectNode =
|
|
157
|
+
selectNodeHandler.selectSingleNode.bind(selectNodeHandler);
|
|
154
158
|
|
|
155
159
|
const getMouseDelay = () => this.options.startDndDelay ?? 0;
|
|
156
160
|
|
|
@@ -267,10 +271,7 @@ export default class TreeElement {
|
|
|
267
271
|
* @returns The new node, or `null` when the node has no parent.
|
|
268
272
|
* @group Changing the tree
|
|
269
273
|
*/
|
|
270
|
-
public addNodeAfter(
|
|
271
|
-
nodeData: NodeData,
|
|
272
|
-
existingNode: Node,
|
|
273
|
-
): Node | null {
|
|
274
|
+
public addNodeAfter(nodeData: NodeData, existingNode: Node): Node | null {
|
|
274
275
|
const newNode = existingNode.addAfter(nodeData);
|
|
275
276
|
|
|
276
277
|
if (newNode) {
|
|
@@ -286,10 +287,7 @@ export default class TreeElement {
|
|
|
286
287
|
* @returns The new node, or `null` when the node has no parent.
|
|
287
288
|
* @group Changing the tree
|
|
288
289
|
*/
|
|
289
|
-
public addNodeBefore(
|
|
290
|
-
nodeData: NodeData,
|
|
291
|
-
existingNode: Node,
|
|
292
|
-
): Node | null {
|
|
290
|
+
public addNodeBefore(nodeData: NodeData, existingNode: Node): Node | null {
|
|
293
291
|
const newNode = existingNode.addBefore(nodeData);
|
|
294
292
|
|
|
295
293
|
if (newNode) {
|
|
@@ -306,10 +304,7 @@ export default class TreeElement {
|
|
|
306
304
|
* @returns The new node, or `null` when the node has no parent.
|
|
307
305
|
* @group Changing the tree
|
|
308
306
|
*/
|
|
309
|
-
public addParentNode(
|
|
310
|
-
nodeData: NodeData,
|
|
311
|
-
existingNode: Node,
|
|
312
|
-
): Node | null {
|
|
307
|
+
public addParentNode(nodeData: NodeData, existingNode: Node): Node | null {
|
|
313
308
|
const newNode = existingNode.addParent(nodeData);
|
|
314
309
|
|
|
315
310
|
if (newNode) {
|
|
@@ -377,7 +372,7 @@ export default class TreeElement {
|
|
|
377
372
|
* @group Other
|
|
378
373
|
*/
|
|
379
374
|
public deinit(): void {
|
|
380
|
-
this.htmlElement.textContent =
|
|
375
|
+
this.htmlElement.textContent = "";
|
|
381
376
|
|
|
382
377
|
this.dataLoader.deinit();
|
|
383
378
|
this.keyHandler.deinit();
|
|
@@ -465,11 +460,11 @@ export default class TreeElement {
|
|
|
465
460
|
}
|
|
466
461
|
|
|
467
462
|
/**
|
|
468
|
-
* Returns the selected node, or `
|
|
463
|
+
* Returns the selected node, or `null` when nothing is selected.
|
|
469
464
|
*
|
|
470
465
|
* @group Selection
|
|
471
466
|
*/
|
|
472
|
-
public getSelectedNode():
|
|
467
|
+
public getSelectedNode(): Node | null {
|
|
473
468
|
return this.selectNodeHandler.getSelectedNode();
|
|
474
469
|
}
|
|
475
470
|
|
|
@@ -571,11 +566,10 @@ export default class TreeElement {
|
|
|
571
566
|
* @param url - Defaults to the `dataUrl` option.
|
|
572
567
|
* @group Loading data
|
|
573
568
|
*/
|
|
574
|
-
public async loadDataFromUrl(
|
|
575
|
-
url
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
const requestUrl = url ? new RequestUrl(url) : this.createRequestUrl(parentNode);
|
|
569
|
+
public async loadDataFromUrl(url?: string, parentNode?: Node): Promise<void> {
|
|
570
|
+
const requestUrl = url
|
|
571
|
+
? new RequestUrl(url)
|
|
572
|
+
: this.createRequestUrl(parentNode);
|
|
579
573
|
|
|
580
574
|
if (requestUrl) {
|
|
581
575
|
await this.dataLoader.loadFromUrl(requestUrl, parentNode);
|
|
@@ -588,10 +582,7 @@ export default class TreeElement {
|
|
|
588
582
|
* @group Selection
|
|
589
583
|
*/
|
|
590
584
|
public moveDown() {
|
|
591
|
-
|
|
592
|
-
if (selectedNode) {
|
|
593
|
-
this.keyHandler.moveDown(selectedNode);
|
|
594
|
-
}
|
|
585
|
+
this.keyHandler.moveDown();
|
|
595
586
|
}
|
|
596
587
|
|
|
597
588
|
/**
|
|
@@ -605,11 +596,7 @@ export default class TreeElement {
|
|
|
605
596
|
* @param position - `"before"`, `"after"` or `"inside"`.
|
|
606
597
|
* @group Changing the tree
|
|
607
598
|
*/
|
|
608
|
-
public moveNode(
|
|
609
|
-
node: Node,
|
|
610
|
-
targetNode: Node,
|
|
611
|
-
position: Position,
|
|
612
|
-
): void {
|
|
599
|
+
public moveNode(node: Node, targetNode: Node, position: Position): void {
|
|
613
600
|
this.tree.moveNode(node, targetNode, position);
|
|
614
601
|
this.refreshElements(null);
|
|
615
602
|
}
|
|
@@ -620,10 +607,7 @@ export default class TreeElement {
|
|
|
620
607
|
* @group Selection
|
|
621
608
|
*/
|
|
622
609
|
public moveUp() {
|
|
623
|
-
|
|
624
|
-
if (selectedNode) {
|
|
625
|
-
this.keyHandler.moveUp(selectedNode);
|
|
626
|
-
}
|
|
610
|
+
this.keyHandler.moveUp();
|
|
627
611
|
}
|
|
628
612
|
|
|
629
613
|
/**
|
|
@@ -640,15 +624,12 @@ export default class TreeElement {
|
|
|
640
624
|
* @param slide - Override the `slide` option for this call.
|
|
641
625
|
* @group Opening and closing
|
|
642
626
|
*/
|
|
643
|
-
public async openNode(
|
|
644
|
-
node: Node,
|
|
645
|
-
slide?: boolean
|
|
646
|
-
): Promise<void> {
|
|
627
|
+
public async openNode(node: Node, slide?: boolean): Promise<void> {
|
|
647
628
|
const mustSlide = slide ?? this.options.slide;
|
|
648
629
|
|
|
649
630
|
const doOpenNode = async (
|
|
650
631
|
openedNode: Node,
|
|
651
|
-
slideOption: boolean
|
|
632
|
+
slideOption: boolean,
|
|
652
633
|
): Promise<void> => {
|
|
653
634
|
if (!node.children.length) {
|
|
654
635
|
return;
|
|
@@ -656,10 +637,7 @@ export default class TreeElement {
|
|
|
656
637
|
|
|
657
638
|
const folderElement = this.createFolderElement(openedNode);
|
|
658
639
|
|
|
659
|
-
await folderElement.open(
|
|
660
|
-
slideOption,
|
|
661
|
-
this.options.animationSpeed,
|
|
662
|
-
);
|
|
640
|
+
await folderElement.open(slideOption, this.options.animationSpeed);
|
|
663
641
|
};
|
|
664
642
|
|
|
665
643
|
if (node.isFolder() || node.isEmptyFolder) {
|
|
@@ -752,9 +730,7 @@ export default class TreeElement {
|
|
|
752
730
|
return;
|
|
753
731
|
}
|
|
754
732
|
|
|
755
|
-
const top =
|
|
756
|
-
getOffsetTop(node.element) -
|
|
757
|
-
getOffsetTop(this.htmlElement);
|
|
733
|
+
const top = getOffsetTop(node.element) - getOffsetTop(this.htmlElement);
|
|
758
734
|
|
|
759
735
|
this.scrollHandler.scrollToY(top);
|
|
760
736
|
}
|
|
@@ -768,10 +744,7 @@ export default class TreeElement {
|
|
|
768
744
|
* `false`.
|
|
769
745
|
* @group Selection
|
|
770
746
|
*/
|
|
771
|
-
public selectNode(
|
|
772
|
-
node: Node | null,
|
|
773
|
-
options?: SelectNodeOptions,
|
|
774
|
-
): void {
|
|
747
|
+
public selectNode(node: Node | null, options?: SelectNodeOptions): void {
|
|
775
748
|
if (!node) {
|
|
776
749
|
// Called with empty node -> deselect current node
|
|
777
750
|
this.deselectCurrentNode();
|
|
@@ -793,13 +766,15 @@ export default class TreeElement {
|
|
|
793
766
|
}
|
|
794
767
|
|
|
795
768
|
/**
|
|
796
|
-
* Applies a state to the tree
|
|
769
|
+
* Applies a state to the tree, and saves it to storage when `saveState` is
|
|
770
|
+
* enabled.
|
|
797
771
|
*
|
|
798
772
|
* @group State
|
|
799
773
|
*/
|
|
800
774
|
public setState(state: SavedState) {
|
|
801
775
|
this.saveStateHandler.setInitialState(state);
|
|
802
776
|
this.refreshElements(null);
|
|
777
|
+
this.saveState();
|
|
803
778
|
}
|
|
804
779
|
|
|
805
780
|
/**
|
|
@@ -879,6 +854,7 @@ export default class TreeElement {
|
|
|
879
854
|
this.scrollHandler,
|
|
880
855
|
);
|
|
881
856
|
const openedIconElement = this.renderer.openedIconElement;
|
|
857
|
+
const renderChildren = this.renderer.renderChildren.bind(this.renderer);
|
|
882
858
|
const tabIndex = this.options.tabIndex;
|
|
883
859
|
const treeElement = this.htmlElement;
|
|
884
860
|
const triggerEvent = this.triggerEvent.bind(this);
|
|
@@ -889,6 +865,7 @@ export default class TreeElement {
|
|
|
889
865
|
getScrollLeft,
|
|
890
866
|
node,
|
|
891
867
|
openedIconElement,
|
|
868
|
+
renderChildren,
|
|
892
869
|
tabIndex,
|
|
893
870
|
treeElement,
|
|
894
871
|
triggerEvent,
|
|
@@ -913,9 +890,9 @@ export default class TreeElement {
|
|
|
913
890
|
}
|
|
914
891
|
|
|
915
892
|
/* Create a RequestUrl based on the url in the options.
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
893
|
+
* Add a 'node' query parameter for loading on demand
|
|
894
|
+
* Add a 'selected_node' query parameter if a node is selected.
|
|
895
|
+
*/
|
|
919
896
|
private createRequestUrl(node?: Node): null | RequestUrl {
|
|
920
897
|
const dataUrl = this.options.dataUrl;
|
|
921
898
|
|
|
@@ -935,12 +912,12 @@ export default class TreeElement {
|
|
|
935
912
|
|
|
936
913
|
if (node?.id) {
|
|
937
914
|
// Load on demand of a subtree; add node parameter
|
|
938
|
-
requestUrl.setSearchParam(
|
|
915
|
+
requestUrl.setSearchParam("node", node.id.toString());
|
|
939
916
|
} else {
|
|
940
917
|
// Add selected_node parameter
|
|
941
918
|
const selectedNodeId = this.getNodeIdToBeSelected();
|
|
942
919
|
if (selectedNodeId) {
|
|
943
|
-
requestUrl.setSearchParam(
|
|
920
|
+
requestUrl.setSearchParam("selected_node", selectedNodeId.toString());
|
|
944
921
|
}
|
|
945
922
|
}
|
|
946
923
|
|
|
@@ -1020,11 +997,7 @@ export default class TreeElement {
|
|
|
1020
997
|
}
|
|
1021
998
|
};
|
|
1022
999
|
|
|
1023
|
-
this.tree = new this.options.nodeClass(
|
|
1024
|
-
null,
|
|
1025
|
-
true,
|
|
1026
|
-
this.options.nodeClass,
|
|
1027
|
-
);
|
|
1000
|
+
this.tree = new this.options.nodeClass(null, true, this.options.nodeClass);
|
|
1028
1001
|
|
|
1029
1002
|
this.selectNodeHandler.clear();
|
|
1030
1003
|
|
|
@@ -1071,10 +1044,7 @@ export default class TreeElement {
|
|
|
1071
1044
|
}
|
|
1072
1045
|
}
|
|
1073
1046
|
|
|
1074
|
-
private async loadFolderOnDemand(
|
|
1075
|
-
node: Node,
|
|
1076
|
-
slide: boolean,
|
|
1077
|
-
): Promise<void> {
|
|
1047
|
+
private async loadFolderOnDemand(node: Node, slide: boolean): Promise<void> {
|
|
1078
1048
|
node.is_loading = true;
|
|
1079
1049
|
|
|
1080
1050
|
await this.loadDataFromUrl(undefined, node);
|
|
@@ -1178,8 +1148,7 @@ export default class TreeElement {
|
|
|
1178
1148
|
if (!state) {
|
|
1179
1149
|
return [false, false];
|
|
1180
1150
|
} else {
|
|
1181
|
-
const mustLoadOnDemand =
|
|
1182
|
-
this.saveStateHandler.setInitialState(state);
|
|
1151
|
+
const mustLoadOnDemand = this.saveStateHandler.setInitialState(state);
|
|
1183
1152
|
|
|
1184
1153
|
// return true: the state is restored
|
|
1185
1154
|
return [true, mustLoadOnDemand];
|
|
@@ -1221,16 +1190,14 @@ export default class TreeElement {
|
|
|
1221
1190
|
|
|
1222
1191
|
// Set the initial state for nodes that are loaded on demand
|
|
1223
1192
|
private async setInitialStateOnDemand(): Promise<void> {
|
|
1224
|
-
return new Promise(resolve => {
|
|
1193
|
+
return new Promise((resolve) => {
|
|
1225
1194
|
const restoreState = (): boolean => {
|
|
1226
1195
|
const state = this.saveStateHandler.getStateFromStorage();
|
|
1227
1196
|
|
|
1228
1197
|
if (!state) {
|
|
1229
1198
|
return false;
|
|
1230
1199
|
} else {
|
|
1231
|
-
void this.saveStateHandler.setInitialStateOnDemand(
|
|
1232
|
-
state,
|
|
1233
|
-
).then(() => {
|
|
1200
|
+
void this.saveStateHandler.setInitialStateOnDemand(state).then(() => {
|
|
1234
1201
|
resolve();
|
|
1235
1202
|
});
|
|
1236
1203
|
|
|
@@ -1284,7 +1251,10 @@ export default class TreeElement {
|
|
|
1284
1251
|
this.nodeMap.set(element, node);
|
|
1285
1252
|
}
|
|
1286
1253
|
|
|
1287
|
-
private triggerEvent<Name extends TreeEventName>(
|
|
1288
|
-
|
|
1254
|
+
private triggerEvent<Name extends TreeEventName>(
|
|
1255
|
+
eventName: Name,
|
|
1256
|
+
values?: TreeEvents[Name],
|
|
1257
|
+
): boolean {
|
|
1258
|
+
return this.triggerEventProvider(this.htmlElement, eventName, values);
|
|
1289
1259
|
}
|
|
1290
|
-
}
|
|
1260
|
+
}
|
package/src/keyHandler.ts
CHANGED
|
@@ -1,139 +1,149 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
CloseNode,
|
|
3
|
+
GetSelectedNode,
|
|
4
|
+
IsFocusOnTree,
|
|
5
|
+
OpenNode,
|
|
6
|
+
SelectNode,
|
|
7
7
|
} from "./methodTypes";
|
|
8
8
|
import type { Node } from "./node";
|
|
9
9
|
|
|
10
10
|
interface KeyHandlerParams {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
closeNode: CloseNode;
|
|
12
|
+
getSelectedNode: GetSelectedNode;
|
|
13
|
+
isFocusOnTree: IsFocusOnTree;
|
|
14
|
+
keyboardSupport: boolean;
|
|
15
|
+
openNode: OpenNode;
|
|
16
|
+
selectNode: SelectNode;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export default class KeyHandler {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
20
|
+
private closeNode: CloseNode;
|
|
21
|
+
private getSelectedNode: GetSelectedNode;
|
|
22
|
+
|
|
23
|
+
private isFocusOnTree: IsFocusOnTree;
|
|
24
|
+
|
|
25
|
+
private keyboardSupport: boolean;
|
|
26
|
+
private openNode: OpenNode;
|
|
27
|
+
private originalSelectNode: SelectNode;
|
|
28
|
+
|
|
29
|
+
constructor({
|
|
30
|
+
closeNode,
|
|
31
|
+
getSelectedNode,
|
|
32
|
+
isFocusOnTree,
|
|
33
|
+
keyboardSupport,
|
|
34
|
+
openNode,
|
|
35
|
+
selectNode,
|
|
36
|
+
}: KeyHandlerParams) {
|
|
37
|
+
this.closeNode = closeNode;
|
|
38
|
+
this.getSelectedNode = getSelectedNode;
|
|
39
|
+
this.isFocusOnTree = isFocusOnTree;
|
|
40
|
+
this.keyboardSupport = keyboardSupport;
|
|
41
|
+
this.openNode = openNode;
|
|
42
|
+
this.originalSelectNode = selectNode;
|
|
43
|
+
|
|
44
|
+
if (keyboardSupport) {
|
|
45
|
+
document.addEventListener("keydown", this.handleKeyDown);
|
|
46
46
|
}
|
|
47
|
+
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
49
|
+
public deinit(): void {
|
|
50
|
+
if (this.keyboardSupport) {
|
|
51
|
+
document.removeEventListener("keydown", this.handleKeyDown);
|
|
52
52
|
}
|
|
53
|
+
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
public moveDown(): boolean {
|
|
56
|
+
return this.selectNode(this.getSelectedNode()?.getNextVisibleNode());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public moveUp(): boolean {
|
|
60
|
+
return this.selectNode(this.getSelectedNode()?.getPreviousVisibleNode());
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private canHandleKeyboard(): boolean {
|
|
64
|
+
return this.keyboardSupport && this.isFocusOnTree();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private handleKeyDown = (e: KeyboardEvent): void => {
|
|
68
|
+
if (!this.canHandleKeyboard()) {
|
|
69
|
+
return;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
|
-
|
|
59
|
-
|
|
72
|
+
let isKeyHandled = false;
|
|
73
|
+
|
|
74
|
+
const selectedNode = this.getSelectedNode();
|
|
75
|
+
if (selectedNode) {
|
|
76
|
+
switch (e.key) {
|
|
77
|
+
case "ArrowDown":
|
|
78
|
+
isKeyHandled = this.moveDown();
|
|
79
|
+
break;
|
|
80
|
+
|
|
81
|
+
case "ArrowLeft":
|
|
82
|
+
isKeyHandled = this.moveLeft();
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
case "ArrowRight":
|
|
86
|
+
isKeyHandled = this.moveRight();
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case "ArrowUp":
|
|
90
|
+
isKeyHandled = this.moveUp();
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
60
93
|
}
|
|
61
94
|
|
|
62
|
-
|
|
63
|
-
|
|
95
|
+
if (isKeyHandled) {
|
|
96
|
+
e.preventDefault();
|
|
64
97
|
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
private moveLeft(): boolean {
|
|
101
|
+
const selectedNode = this.getSelectedNode();
|
|
65
102
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let isKeyHandled = false;
|
|
72
|
-
|
|
73
|
-
const selectedNode = this.getSelectedNode();
|
|
74
|
-
if (selectedNode) {
|
|
75
|
-
switch (e.key) {
|
|
76
|
-
case "ArrowDown":
|
|
77
|
-
isKeyHandled = this.moveDown(selectedNode);
|
|
78
|
-
break;
|
|
79
|
-
|
|
80
|
-
case "ArrowLeft":
|
|
81
|
-
isKeyHandled = this.moveLeft(selectedNode);
|
|
82
|
-
break;
|
|
83
|
-
|
|
84
|
-
case "ArrowRight":
|
|
85
|
-
isKeyHandled = this.moveRight(selectedNode);
|
|
86
|
-
break;
|
|
87
|
-
|
|
88
|
-
case "ArrowUp":
|
|
89
|
-
isKeyHandled = this.moveUp(selectedNode);
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (isKeyHandled) {
|
|
95
|
-
e.preventDefault();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
private moveLeft(selectedNode: Node): boolean {
|
|
100
|
-
if (selectedNode.isFolder() && selectedNode.is_open) {
|
|
101
|
-
// Left on an open node closes the node
|
|
102
|
-
this.closeNode(selectedNode);
|
|
103
|
-
return true;
|
|
104
|
-
} else {
|
|
105
|
-
// Left on a closed or end node moves focus to the node's parent
|
|
106
|
-
return this.selectNode(selectedNode.getParent());
|
|
107
|
-
}
|
|
103
|
+
/* istanbul ignore if */
|
|
104
|
+
if (!selectedNode) {
|
|
105
|
+
return false;
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return this.selectNode(selectedNode.getNextVisibleNode());
|
|
118
|
-
} else {
|
|
119
|
-
// Right expands a closed node
|
|
120
|
-
void this.openNode(selectedNode);
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
108
|
+
if (selectedNode.isFolder() && selectedNode.is_open) {
|
|
109
|
+
// Left on an open node closes the node
|
|
110
|
+
this.closeNode(selectedNode);
|
|
111
|
+
return true;
|
|
112
|
+
} else {
|
|
113
|
+
// Left on a closed or end node moves focus to the node's parent
|
|
114
|
+
return this.selectNode(selectedNode.getParent());
|
|
124
115
|
}
|
|
116
|
+
}
|
|
125
117
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
private moveRight(): boolean {
|
|
119
|
+
const selectedNode = this.getSelectedNode();
|
|
120
|
+
|
|
121
|
+
if (!selectedNode?.isFolder()) {
|
|
122
|
+
return false;
|
|
123
|
+
} else {
|
|
124
|
+
// folder node
|
|
125
|
+
if (selectedNode.is_open) {
|
|
126
|
+
// Right moves to the first child of an open node
|
|
127
|
+
return this.selectNode(selectedNode.getNextVisibleNode());
|
|
128
|
+
} else {
|
|
129
|
+
// Right expands a closed node
|
|
130
|
+
void this.openNode(selectedNode);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Select the node.
|
|
137
|
+
* Don't do anything if the node is null.
|
|
138
|
+
* Result: a different node was selected.
|
|
139
|
+
*/
|
|
140
|
+
private selectNode(node?: Node | null): boolean {
|
|
141
|
+
if (!node) {
|
|
142
|
+
return false;
|
|
143
|
+
} else {
|
|
144
|
+
this.originalSelectNode(node);
|
|
145
|
+
|
|
146
|
+
return true;
|
|
138
147
|
}
|
|
148
|
+
}
|
|
139
149
|
}
|
package/src/methodTypes.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type GetNodeElementForNode = (node: Node) => NodeElement;
|
|
|
12
12
|
|
|
13
13
|
export type GetScrollLeft = () => number;
|
|
14
14
|
|
|
15
|
-
export type GetSelectedNode = () =>
|
|
15
|
+
export type GetSelectedNode = () => Node | null;
|
|
16
16
|
|
|
17
17
|
export type GetSelectedNodes = () => Node[];
|
|
18
18
|
|
|
@@ -24,10 +24,7 @@ export type IsNodeSelected = (node: Node) => boolean;
|
|
|
24
24
|
|
|
25
25
|
export type LoadData = (data: NodeData[], parentNode?: Node) => void;
|
|
26
26
|
|
|
27
|
-
export type OpenNode = (
|
|
28
|
-
node: Node,
|
|
29
|
-
slide?: boolean,
|
|
30
|
-
) => Promise<void>;
|
|
27
|
+
export type OpenNode = (node: Node, slide?: boolean) => Promise<void>;
|
|
31
28
|
|
|
32
29
|
export type OpenParents = (node: Node) => void;
|
|
33
30
|
|
|
@@ -39,6 +36,6 @@ export type SelectNode = (node: Node) => void;
|
|
|
39
36
|
|
|
40
37
|
// Trigger an event. Return if the event is processed (true) or cancelled (false).
|
|
41
38
|
export type TriggerEvent = <Name extends TreeEventName>(
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
eventName: Name,
|
|
40
|
+
values?: TreeEvents[Name],
|
|
44
41
|
) => boolean;
|