jqtree 1.9.0 → 2.0.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/bower.json +1 -1
- package/js-coverage/coverage-final.json +13 -0
- package/lib/jqtreeOptions.js +1 -0
- package/lib/tree.jquery.d.js +0 -0
- package/lib/tree.jquery.js +394 -0
- package/lib/triggerJQueryEvent.js +68 -0
- package/lib/typings.d.js +1 -0
- package/lib/version.js +2 -0
- package/package.json +34 -29
- package/pnpm-workspace.yaml +3 -3
- package/src/jqtreeOptions.ts +20 -62
- package/src/tree.jquery.d.ts +81 -92
- package/src/tree.jquery.ts +234 -938
- package/src/triggerJQueryEvent.ts +97 -0
- package/src/version.ts +2 -2
- package/tree.jquery.debug.js +4226 -3281
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +22 -2
- package/tree.jquery.js.map +1 -1
- package/eslint.config.mjs +0 -112
- package/src/animation.ts +0 -48
- package/src/dataLoader.ts +0 -143
- package/src/dragAndDropHandler/binarySearch.ts +0 -27
- package/src/dragAndDropHandler/dragElement.ts +0 -54
- package/src/dragAndDropHandler/generateHitAreas.ts +0 -195
- package/src/dragAndDropHandler/index.ts +0 -432
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +0 -91
- package/src/dragAndDropHandler/types.ts +0 -12
- package/src/elementsRenderer.ts +0 -359
- package/src/jqtreeMethodTypes.ts +0 -40
- package/src/keyHandler.ts +0 -139
- package/src/mouseHandler.ts +0 -383
- package/src/mouseUtils.ts +0 -23
- package/src/node.ts +0 -653
- package/src/nodeElement/borderDropHint.ts +0 -32
- package/src/nodeElement/folderElement.ts +0 -138
- package/src/nodeElement/ghostDropHint.ts +0 -74
- package/src/nodeElement/index.ts +0 -94
- package/src/nodeUtils.ts +0 -10
- package/src/positionUtils.ts +0 -18
- package/src/saveStateHandler.ts +0 -276
- package/src/scrollHandler/containerScrollParent.ts +0 -71
- package/src/scrollHandler/createScrollParent.ts +0 -51
- package/src/scrollHandler/documentScrollParent.ts +0 -104
- package/src/scrollHandler/scrollParent.ts +0 -117
- package/src/scrollHandler.ts +0 -55
- package/src/selectNodeHandler.ts +0 -111
- package/src/simple.widget.ts +0 -134
- package/src/util.ts +0 -5
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import type { AnimationSpeed } from "../animation";
|
|
2
|
-
import type { OnFinishOpenNode, TriggerEvent } from "../jqtreeMethodTypes";
|
|
3
|
-
import type { Position } from "../node";
|
|
4
|
-
import type { NodeElementParams } from "./index";
|
|
5
|
-
|
|
6
|
-
import { slideDown, slideUp } from "../animation";
|
|
7
|
-
import NodeElement from "./index";
|
|
8
|
-
|
|
9
|
-
interface FolderElementParams extends NodeElementParams {
|
|
10
|
-
closedIconElement?: HTMLElement | Text;
|
|
11
|
-
openedIconElement?: HTMLElement | Text;
|
|
12
|
-
triggerEvent: TriggerEvent;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class FolderElement extends NodeElement {
|
|
16
|
-
private _closedIconElement?: HTMLElement | Text;
|
|
17
|
-
private _openedIconElement?: HTMLElement | Text;
|
|
18
|
-
private _triggerEvent: TriggerEvent;
|
|
19
|
-
|
|
20
|
-
constructor({
|
|
21
|
-
closedIconElement,
|
|
22
|
-
getScrollLeft,
|
|
23
|
-
node,
|
|
24
|
-
openedIconElement,
|
|
25
|
-
tabIndex,
|
|
26
|
-
treeElement,
|
|
27
|
-
triggerEvent,
|
|
28
|
-
}: FolderElementParams) {
|
|
29
|
-
super({
|
|
30
|
-
getScrollLeft,
|
|
31
|
-
node,
|
|
32
|
-
tabIndex,
|
|
33
|
-
treeElement,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
this._closedIconElement = closedIconElement;
|
|
37
|
-
this._openedIconElement = openedIconElement;
|
|
38
|
-
this._triggerEvent = triggerEvent;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public close(slide: boolean, animationSpeed: AnimationSpeed): void {
|
|
42
|
-
if (!this.node.is_open) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
this.node.is_open = false;
|
|
47
|
-
|
|
48
|
-
const button = this._getButton();
|
|
49
|
-
button.classList.add("jqtree-closed");
|
|
50
|
-
button.innerHTML = "";
|
|
51
|
-
|
|
52
|
-
const closedIconElement = this._closedIconElement;
|
|
53
|
-
|
|
54
|
-
if (closedIconElement) {
|
|
55
|
-
const icon = closedIconElement.cloneNode(true);
|
|
56
|
-
button.appendChild(icon);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const doClose = (): void => {
|
|
60
|
-
this.element.classList.add("jqtree-closed");
|
|
61
|
-
|
|
62
|
-
const titleSpan = this.getTitleSpan();
|
|
63
|
-
titleSpan.setAttribute("aria-expanded", "false");
|
|
64
|
-
|
|
65
|
-
this._triggerEvent("tree.close", {
|
|
66
|
-
node: this.node,
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const ul = this.getUl();
|
|
71
|
-
|
|
72
|
-
if (slide) {
|
|
73
|
-
slideUp(ul, animationSpeed, doClose);
|
|
74
|
-
} else {
|
|
75
|
-
ul.style.display = "none";
|
|
76
|
-
doClose();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public open(
|
|
81
|
-
onFinished: OnFinishOpenNode | undefined,
|
|
82
|
-
slide: boolean,
|
|
83
|
-
animationSpeed: AnimationSpeed,
|
|
84
|
-
): void {
|
|
85
|
-
if (this.node.is_open) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.node.is_open = true;
|
|
90
|
-
|
|
91
|
-
const button = this._getButton();
|
|
92
|
-
button.classList.remove("jqtree-closed");
|
|
93
|
-
button.innerHTML = "";
|
|
94
|
-
|
|
95
|
-
const openedIconElement = this._openedIconElement;
|
|
96
|
-
|
|
97
|
-
if (openedIconElement) {
|
|
98
|
-
const icon = openedIconElement.cloneNode(true);
|
|
99
|
-
button.appendChild(icon);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const doOpen = (): void => {
|
|
103
|
-
this.element.classList.remove("jqtree-closed");
|
|
104
|
-
|
|
105
|
-
const titleSpan = this.getTitleSpan();
|
|
106
|
-
titleSpan.setAttribute("aria-expanded", "true");
|
|
107
|
-
|
|
108
|
-
if (onFinished) {
|
|
109
|
-
onFinished(this.node);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
this._triggerEvent("tree.open", {
|
|
113
|
-
node: this.node,
|
|
114
|
-
});
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const ul = this.getUl();
|
|
118
|
-
|
|
119
|
-
if (slide) {
|
|
120
|
-
slideDown(ul, animationSpeed, doOpen);
|
|
121
|
-
} else {
|
|
122
|
-
ul.style.display = "block";
|
|
123
|
-
doOpen();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
protected mustShowBorderDropHint(position: Position): boolean {
|
|
128
|
-
return !this.node.is_open && position === "inside";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
private _getButton(): HTMLLinkElement {
|
|
132
|
-
return this.element.querySelector(
|
|
133
|
-
":scope > .jqtree-element > a.jqtree-toggler",
|
|
134
|
-
) as HTMLLinkElement;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export default FolderElement;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { DropHint } from "../dragAndDropHandler/types";
|
|
2
|
-
import type { Node, Position } from "../node";
|
|
3
|
-
|
|
4
|
-
class GhostDropHint implements DropHint {
|
|
5
|
-
private _element: HTMLElement;
|
|
6
|
-
private _ghost: HTMLElement;
|
|
7
|
-
private _node: Node;
|
|
8
|
-
|
|
9
|
-
constructor(node: Node, element: HTMLElement, position: Position) {
|
|
10
|
-
this._element = element;
|
|
11
|
-
this._node = node;
|
|
12
|
-
this._ghost = this._createGhostElement();
|
|
13
|
-
|
|
14
|
-
switch (position) {
|
|
15
|
-
case "after":
|
|
16
|
-
this._moveAfter();
|
|
17
|
-
break;
|
|
18
|
-
|
|
19
|
-
case "before":
|
|
20
|
-
this._moveBefore();
|
|
21
|
-
break;
|
|
22
|
-
|
|
23
|
-
case "inside": {
|
|
24
|
-
if (node.isFolder() && node.is_open) {
|
|
25
|
-
this._moveInsideOpenFolder();
|
|
26
|
-
} else {
|
|
27
|
-
this._moveInside();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public remove(): void {
|
|
34
|
-
this._ghost.remove();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private _createGhostElement() {
|
|
38
|
-
const ghost = document.createElement("li");
|
|
39
|
-
ghost.className = "jqtree_common jqtree-ghost";
|
|
40
|
-
|
|
41
|
-
const circleSpan = document.createElement("span");
|
|
42
|
-
circleSpan.className = "jqtree_common jqtree-circle";
|
|
43
|
-
ghost.append(circleSpan);
|
|
44
|
-
|
|
45
|
-
const lineSpan = document.createElement("span");
|
|
46
|
-
lineSpan.className = "jqtree_common jqtree-line";
|
|
47
|
-
ghost.append(lineSpan);
|
|
48
|
-
|
|
49
|
-
return ghost;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private _moveAfter(): void {
|
|
53
|
-
this._element.after(this._ghost);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private _moveBefore(): void {
|
|
57
|
-
this._element.before(this._ghost);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private _moveInside(): void {
|
|
61
|
-
this._element.after(this._ghost);
|
|
62
|
-
this._ghost.classList.add("jqtree-inside");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private _moveInsideOpenFolder(): void {
|
|
66
|
-
const childElement = this._node.children[0]?.element;
|
|
67
|
-
|
|
68
|
-
if (childElement) {
|
|
69
|
-
childElement.before(this._ghost);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export default GhostDropHint;
|
package/src/nodeElement/index.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import type { DropHint } from "../dragAndDropHandler/types";
|
|
2
|
-
import type { GetScrollLeft } from "../jqtreeMethodTypes";
|
|
3
|
-
import type { Node, Position } from "../node";
|
|
4
|
-
|
|
5
|
-
import BorderDropHint from "./borderDropHint";
|
|
6
|
-
import GhostDropHint from "./ghostDropHint";
|
|
7
|
-
|
|
8
|
-
export interface NodeElementParams {
|
|
9
|
-
getScrollLeft: GetScrollLeft;
|
|
10
|
-
node: Node;
|
|
11
|
-
tabIndex?: number;
|
|
12
|
-
treeElement: HTMLElement;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class NodeElement {
|
|
16
|
-
public element: HTMLElement;
|
|
17
|
-
public node: Node;
|
|
18
|
-
private _getScrollLeft: GetScrollLeft;
|
|
19
|
-
private _tabIndex?: number;
|
|
20
|
-
private _treeElement: HTMLElement;
|
|
21
|
-
|
|
22
|
-
constructor({
|
|
23
|
-
getScrollLeft,
|
|
24
|
-
node,
|
|
25
|
-
tabIndex,
|
|
26
|
-
treeElement,
|
|
27
|
-
}: NodeElementParams) {
|
|
28
|
-
this._getScrollLeft = getScrollLeft;
|
|
29
|
-
this._tabIndex = tabIndex;
|
|
30
|
-
this._treeElement = treeElement;
|
|
31
|
-
|
|
32
|
-
this.init(node);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public addDropHint(position: Position): DropHint {
|
|
36
|
-
if (this.mustShowBorderDropHint(position)) {
|
|
37
|
-
return new BorderDropHint(this.element, this._getScrollLeft());
|
|
38
|
-
} else {
|
|
39
|
-
return new GhostDropHint(this.node, this.element, position);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public deselect(): void {
|
|
44
|
-
this.element.classList.remove("jqtree-selected");
|
|
45
|
-
|
|
46
|
-
const titleSpan = this.getTitleSpan();
|
|
47
|
-
titleSpan.removeAttribute("tabindex");
|
|
48
|
-
titleSpan.setAttribute("aria-selected", "false");
|
|
49
|
-
|
|
50
|
-
titleSpan.blur();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public init(node: Node): void {
|
|
54
|
-
this.node = node;
|
|
55
|
-
|
|
56
|
-
node.element ??= this._treeElement;
|
|
57
|
-
|
|
58
|
-
this.element = node.element;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public select(mustSetFocus: boolean): void {
|
|
62
|
-
this.element.classList.add("jqtree-selected");
|
|
63
|
-
|
|
64
|
-
const titleSpan = this.getTitleSpan();
|
|
65
|
-
const tabIndex = this._tabIndex;
|
|
66
|
-
|
|
67
|
-
// Check for null or undefined
|
|
68
|
-
if (tabIndex != null) {
|
|
69
|
-
titleSpan.setAttribute("tabindex", tabIndex.toString());
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
titleSpan.setAttribute("aria-selected", "true");
|
|
73
|
-
|
|
74
|
-
if (mustSetFocus) {
|
|
75
|
-
titleSpan.focus();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
protected getTitleSpan(): HTMLSpanElement {
|
|
80
|
-
return this.element.querySelector(
|
|
81
|
-
":scope > .jqtree-element > span.jqtree-title",
|
|
82
|
-
) as HTMLSpanElement;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
protected getUl(): HTMLUListElement {
|
|
86
|
-
return this.element.querySelector(":scope > ul") as HTMLUListElement;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
protected mustShowBorderDropHint(position: Position): boolean {
|
|
90
|
-
return position === "inside";
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export default NodeElement;
|
package/src/nodeUtils.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
interface NodeRecordWithChildren extends NodeRecord {
|
|
2
|
-
children: NodeData[];
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const isNodeRecordWithChildren = (
|
|
6
|
-
data: NodeData,
|
|
7
|
-
): data is NodeRecordWithChildren =>
|
|
8
|
-
typeof data === "object" &&
|
|
9
|
-
"children" in data &&
|
|
10
|
-
data.children instanceof Array;
|
package/src/positionUtils.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
interface TopLeftPosition {
|
|
2
|
-
left: number;
|
|
3
|
-
top: number;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// Get the top position of the HTML element.
|
|
7
|
-
export const getOffsetTop = (element: HTMLElement): number =>
|
|
8
|
-
getElementPosition(element).top;
|
|
9
|
-
|
|
10
|
-
// Get the top left position of the HTML element.
|
|
11
|
-
export const getElementPosition = (element: HTMLElement): TopLeftPosition => {
|
|
12
|
-
const rect = element.getBoundingClientRect();
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
left: rect.x + window.scrollX,
|
|
16
|
-
top: rect.y + window.scrollY,
|
|
17
|
-
};
|
|
18
|
-
};
|
package/src/saveStateHandler.ts
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AddToSelection,
|
|
3
|
-
GetNodeById,
|
|
4
|
-
GetSelectedNodes,
|
|
5
|
-
GetTree,
|
|
6
|
-
OpenNode,
|
|
7
|
-
RefreshElements,
|
|
8
|
-
RemoveFromSelection,
|
|
9
|
-
} from "./jqtreeMethodTypes";
|
|
10
|
-
import type { OnGetStateFromStorage, OnSetStateFromStorage } from "./jqtreeOptions";
|
|
11
|
-
import type { Node } from "./node";
|
|
12
|
-
|
|
13
|
-
import { isInt } from "./util";
|
|
14
|
-
|
|
15
|
-
export interface SavedState {
|
|
16
|
-
open_nodes?: NodeId[];
|
|
17
|
-
selected_node?: NodeId[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface SaveStateHandlerParams {
|
|
21
|
-
addToSelection: AddToSelection;
|
|
22
|
-
getNodeById: GetNodeById;
|
|
23
|
-
getSelectedNodes: GetSelectedNodes;
|
|
24
|
-
getTree: GetTree;
|
|
25
|
-
onGetStateFromStorage?: OnGetStateFromStorage;
|
|
26
|
-
onSetStateFromStorage?: OnSetStateFromStorage;
|
|
27
|
-
openNode: OpenNode;
|
|
28
|
-
refreshElements: RefreshElements;
|
|
29
|
-
removeFromSelection: RemoveFromSelection;
|
|
30
|
-
saveState: boolean | string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default class SaveStateHandler {
|
|
34
|
-
private _addToSelection: AddToSelection;
|
|
35
|
-
private _getNodeById: GetNodeById;
|
|
36
|
-
private _getSelectedNodes: GetSelectedNodes;
|
|
37
|
-
private _getTree: GetTree;
|
|
38
|
-
private _onGetStateFromStorage?: OnGetStateFromStorage;
|
|
39
|
-
private _onSetStateFromStorage?: OnSetStateFromStorage;
|
|
40
|
-
private _openNode: OpenNode;
|
|
41
|
-
private _refreshElements: RefreshElements;
|
|
42
|
-
private _removeFromSelection: RemoveFromSelection;
|
|
43
|
-
private _saveStateOption: boolean | string;
|
|
44
|
-
|
|
45
|
-
constructor({
|
|
46
|
-
addToSelection,
|
|
47
|
-
getNodeById,
|
|
48
|
-
getSelectedNodes,
|
|
49
|
-
getTree,
|
|
50
|
-
onGetStateFromStorage,
|
|
51
|
-
onSetStateFromStorage,
|
|
52
|
-
openNode,
|
|
53
|
-
refreshElements,
|
|
54
|
-
removeFromSelection,
|
|
55
|
-
saveState,
|
|
56
|
-
}: SaveStateHandlerParams) {
|
|
57
|
-
this._addToSelection = addToSelection;
|
|
58
|
-
this._getNodeById = getNodeById;
|
|
59
|
-
this._getSelectedNodes = getSelectedNodes;
|
|
60
|
-
this._getTree = getTree;
|
|
61
|
-
this._onGetStateFromStorage = onGetStateFromStorage;
|
|
62
|
-
this._onSetStateFromStorage = onSetStateFromStorage;
|
|
63
|
-
this._openNode = openNode;
|
|
64
|
-
this._refreshElements = refreshElements;
|
|
65
|
-
this._removeFromSelection = removeFromSelection;
|
|
66
|
-
this._saveStateOption = saveState;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public getNodeIdToBeSelected(): NodeId | null {
|
|
70
|
-
const state = this.getStateFromStorage();
|
|
71
|
-
|
|
72
|
-
if (state?.selected_node) {
|
|
73
|
-
return state.selected_node[0] ?? null;
|
|
74
|
-
} else {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public getState(): SavedState {
|
|
80
|
-
const getOpenNodeIds = (): NodeId[] => {
|
|
81
|
-
const openNodes: NodeId[] = [];
|
|
82
|
-
|
|
83
|
-
this._getTree()?.iterate((node: Node) => {
|
|
84
|
-
if (node.is_open && node.id && node.hasChildren()) {
|
|
85
|
-
openNodes.push(node.id);
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return openNodes;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const getSelectedNodeIds = (): NodeId[] => {
|
|
94
|
-
const selectedNodeIds: NodeId[] = [];
|
|
95
|
-
|
|
96
|
-
this._getSelectedNodes().forEach((node) => {
|
|
97
|
-
if (node.id != null) {
|
|
98
|
-
selectedNodeIds.push(node.id);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return selectedNodeIds;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
open_nodes: getOpenNodeIds(),
|
|
107
|
-
selected_node: getSelectedNodeIds(),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public getStateFromStorage(): null | SavedState {
|
|
112
|
-
const jsonData = this._loadFromStorage();
|
|
113
|
-
|
|
114
|
-
if (jsonData) {
|
|
115
|
-
return this._parseState(jsonData);
|
|
116
|
-
} else {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
public saveState(): void {
|
|
122
|
-
const state = JSON.stringify(this.getState());
|
|
123
|
-
|
|
124
|
-
if (this._onSetStateFromStorage) {
|
|
125
|
-
this._onSetStateFromStorage(state);
|
|
126
|
-
} else {
|
|
127
|
-
localStorage.setItem(this._getKeyName(), state);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/*
|
|
132
|
-
Set initial state
|
|
133
|
-
Don't handle nodes that are loaded on demand
|
|
134
|
-
|
|
135
|
-
result: must load on demand (boolean)
|
|
136
|
-
*/
|
|
137
|
-
public setInitialState(state: SavedState): boolean {
|
|
138
|
-
let mustLoadOnDemand = false;
|
|
139
|
-
|
|
140
|
-
if (state.open_nodes) {
|
|
141
|
-
mustLoadOnDemand = this._openInitialNodes(state.open_nodes);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
this._resetSelection();
|
|
145
|
-
|
|
146
|
-
if (state.selected_node) {
|
|
147
|
-
this._selectInitialNodes(state.selected_node);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return mustLoadOnDemand;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
public setInitialStateOnDemand(
|
|
154
|
-
state: SavedState,
|
|
155
|
-
cbFinished: () => void,
|
|
156
|
-
): void {
|
|
157
|
-
let loadingCount = 0;
|
|
158
|
-
let nodeIds = state.open_nodes;
|
|
159
|
-
|
|
160
|
-
const openNodes = (): void => {
|
|
161
|
-
if (!nodeIds) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const newNodesIds = [];
|
|
166
|
-
|
|
167
|
-
for (const nodeId of nodeIds) {
|
|
168
|
-
const node = this._getNodeById(nodeId);
|
|
169
|
-
|
|
170
|
-
if (!node) {
|
|
171
|
-
newNodesIds.push(nodeId);
|
|
172
|
-
} else {
|
|
173
|
-
if (!node.is_loading) {
|
|
174
|
-
if (node.load_on_demand) {
|
|
175
|
-
loadAndOpenNode(node);
|
|
176
|
-
} else {
|
|
177
|
-
this._openNode(node, false);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
nodeIds = newNodesIds;
|
|
184
|
-
|
|
185
|
-
if (state.selected_node) {
|
|
186
|
-
if (this._selectInitialNodes(state.selected_node)) {
|
|
187
|
-
this._refreshElements(null);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (loadingCount === 0) {
|
|
192
|
-
cbFinished();
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
const loadAndOpenNode = (node: Node): void => {
|
|
197
|
-
loadingCount += 1;
|
|
198
|
-
this._openNode(node, false, () => {
|
|
199
|
-
loadingCount -= 1;
|
|
200
|
-
openNodes();
|
|
201
|
-
});
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
openNodes();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
private _getKeyName(): string {
|
|
208
|
-
if (typeof this._saveStateOption === "string") {
|
|
209
|
-
return this._saveStateOption;
|
|
210
|
-
} else {
|
|
211
|
-
return "tree";
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private _loadFromStorage(): null | string {
|
|
216
|
-
if (this._onGetStateFromStorage) {
|
|
217
|
-
return this._onGetStateFromStorage();
|
|
218
|
-
} else {
|
|
219
|
-
return localStorage.getItem(this._getKeyName());
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
private _openInitialNodes(nodeIds: NodeId[]): boolean {
|
|
224
|
-
let mustLoadOnDemand = false;
|
|
225
|
-
|
|
226
|
-
for (const nodeId of nodeIds) {
|
|
227
|
-
const node = this._getNodeById(nodeId);
|
|
228
|
-
|
|
229
|
-
if (node) {
|
|
230
|
-
if (!node.load_on_demand) {
|
|
231
|
-
node.is_open = true;
|
|
232
|
-
} else {
|
|
233
|
-
mustLoadOnDemand = true;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return mustLoadOnDemand;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private _parseState(jsonData: string): SavedState {
|
|
242
|
-
const state = JSON.parse(jsonData) as Record<string, unknown>;
|
|
243
|
-
|
|
244
|
-
// Check if selected_node is an int (instead of an array)
|
|
245
|
-
if (state.selected_node && isInt(state.selected_node)) {
|
|
246
|
-
// Convert to array
|
|
247
|
-
state.selected_node = [state.selected_node];
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return state;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
private _resetSelection(): void {
|
|
254
|
-
const selectedNodes = this._getSelectedNodes();
|
|
255
|
-
|
|
256
|
-
selectedNodes.forEach((node) => {
|
|
257
|
-
this._removeFromSelection(node);
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
private _selectInitialNodes(nodeIds: NodeId[]): boolean {
|
|
262
|
-
let selectCount = 0;
|
|
263
|
-
|
|
264
|
-
for (const nodeId of nodeIds) {
|
|
265
|
-
const node = this._getNodeById(nodeId);
|
|
266
|
-
|
|
267
|
-
if (node) {
|
|
268
|
-
selectCount += 1;
|
|
269
|
-
|
|
270
|
-
this._addToSelection(node);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return selectCount !== 0;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
HorizontalScrollDirection,
|
|
3
|
-
VerticalScrollDirection,
|
|
4
|
-
} from "./scrollParent";
|
|
5
|
-
|
|
6
|
-
import { getElementPosition, getOffsetTop } from "../positionUtils";
|
|
7
|
-
import { ScrollParent } from "./scrollParent";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export default class ContainerScrollParent extends ScrollParent {
|
|
11
|
-
private _scrollParentBottom?: number;
|
|
12
|
-
private _scrollParentTop?: number;
|
|
13
|
-
|
|
14
|
-
public stopScrolling() {
|
|
15
|
-
super.stopScrolling();
|
|
16
|
-
|
|
17
|
-
this.horizontalScrollDirection = undefined;
|
|
18
|
-
this.verticalScrollDirection = undefined;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
protected getNewHorizontalScrollDirection(
|
|
22
|
-
pageX: number,
|
|
23
|
-
): HorizontalScrollDirection | undefined {
|
|
24
|
-
const scrollParentOffset = getElementPosition(this.container);
|
|
25
|
-
const containerWidth = this.container.getBoundingClientRect().width;
|
|
26
|
-
|
|
27
|
-
const rightEdge = scrollParentOffset.left + containerWidth;
|
|
28
|
-
const leftEdge = scrollParentOffset.left;
|
|
29
|
-
const isNearRightEdge = pageX > rightEdge - 20;
|
|
30
|
-
const isNearLeftEdge = pageX < leftEdge + 20;
|
|
31
|
-
|
|
32
|
-
if (isNearRightEdge) {
|
|
33
|
-
return "right";
|
|
34
|
-
} else if (isNearLeftEdge) {
|
|
35
|
-
return "left";
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return undefined;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
protected getNewVerticalScrollDirection(
|
|
42
|
-
pageY: number,
|
|
43
|
-
): undefined | VerticalScrollDirection {
|
|
44
|
-
if (pageY < this._getScrollParentTop()) {
|
|
45
|
-
return "top";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (pageY > this._getScrollParentBottom()) {
|
|
49
|
-
return "bottom";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private _getScrollParentBottom() {
|
|
56
|
-
if (this._scrollParentBottom == null) {
|
|
57
|
-
const containerHeight =
|
|
58
|
-
this.container.getBoundingClientRect().height;
|
|
59
|
-
this._scrollParentBottom =
|
|
60
|
-
this._getScrollParentTop() + containerHeight;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return this._scrollParentBottom;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private _getScrollParentTop() {
|
|
67
|
-
this._scrollParentTop ??= getOffsetTop(this.container);
|
|
68
|
-
|
|
69
|
-
return this._scrollParentTop;
|
|
70
|
-
}
|
|
71
|
-
}
|