jqtree 1.7.5 → 1.8.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/config/babel.config.json +1 -1
- package/config/production +2 -0
- package/devserver/devserver_scroll.js +8 -0
- package/devserver/test_scroll.html +28 -0
- package/devserver/test_scroll_container.html +39 -0
- package/docs/_config.yml +1 -1
- package/docs/_entries/general/changelog.md +7 -0
- package/package.json +5 -1
- package/src/dataLoader.ts +44 -19
- package/src/dragAndDropHandler/dragElement.ts +42 -0
- package/src/dragAndDropHandler/hitAreasGenerator.ts +175 -0
- package/src/dragAndDropHandler/index.ts +470 -0
- package/src/dragAndDropHandler/types.ts +12 -0
- package/src/dragAndDropHandler/visibleNodeIterator.ts +97 -0
- package/src/elementsRenderer.ts +75 -40
- package/src/jqtreeMethodTypes.ts +40 -0
- package/src/jqtreeOptions.ts +43 -25
- package/src/keyHandler.ts +59 -30
- package/src/mouse.widget.ts +3 -3
- package/src/mouseWidgetTypes.ts +6 -0
- package/src/nodeElement/borderDropHint.ts +32 -0
- package/src/nodeElement/folderElement.ts +133 -0
- package/src/nodeElement/ghostDropHint.ts +68 -0
- package/src/nodeElement/index.ts +101 -0
- package/src/playwright/coverage.ts +1 -4
- package/src/playwright/playwright.test.ts +0 -4
- package/src/saveStateHandler.ts +75 -26
- package/src/scrollHandler.ts +13 -7
- package/src/selectNodeHandler.ts +10 -16
- package/src/test/jqTree/keyboard.test.ts +18 -23
- package/src/test/jqTree/methods.test.ts +32 -3
- package/src/test/jqTree/options.test.ts +15 -4
- package/src/test/node.test.ts +1 -1
- package/src/tree.jquery.ts +239 -57
- package/src/util.ts +3 -0
- package/src/version.ts +1 -1
- package/tree.jquery.debug.js +1728 -2576
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +2 -2
- package/tree.jquery.js.map +1 -1
- package/lib/dataLoader.js +0 -123
- package/lib/dragAndDropHandler.js +0 -588
- package/lib/elementsRenderer.js +0 -267
- package/lib/jqtreeOptions.js +0 -1
- package/lib/keyHandler.js +0 -111
- package/lib/mouse.widget.js +0 -255
- package/lib/node.js +0 -708
- package/lib/nodeElement.js +0 -274
- package/lib/nodeUtils.js +0 -10
- package/lib/playwright/coverage.js +0 -99
- package/lib/playwright/playwright.test.js +0 -606
- package/lib/playwright/testUtils.js +0 -210
- package/lib/saveStateHandler.js +0 -277
- package/lib/scrollHandler/containerScrollParent.js +0 -160
- package/lib/scrollHandler/createScrollParent.js +0 -57
- package/lib/scrollHandler/documentScrollParent.js +0 -169
- package/lib/scrollHandler/scrollParent.js +0 -58
- package/lib/scrollHandler/types.js +0 -1
- package/lib/scrollHandler.js +0 -71
- package/lib/selectNodeHandler.js +0 -128
- package/lib/simple.widget.js +0 -158
- package/lib/test/global.d.js +0 -3
- package/lib/test/jqTree/accessibility.test.js +0 -37
- package/lib/test/jqTree/create.test.js +0 -48
- package/lib/test/jqTree/events.test.js +0 -210
- package/lib/test/jqTree/keyboard.test.js +0 -225
- package/lib/test/jqTree/loadOnDemand.test.js +0 -218
- package/lib/test/jqTree/methods.test.js +0 -1348
- package/lib/test/jqTree/options.test.js +0 -548
- package/lib/test/jqTree/scrollHandler/containerScrollParent.test.js +0 -94
- package/lib/test/node.test.js +0 -1202
- package/lib/test/nodeUtil.test.js +0 -27
- package/lib/test/nodeUtils.test.js +0 -20
- package/lib/test/support/exampleData.js +0 -35
- package/lib/test/support/jqTreeMatchers.js +0 -70
- package/lib/test/support/matchers.d.js +0 -1
- package/lib/test/support/setupTests.js +0 -7
- package/lib/test/support/testUtil.js +0 -29
- package/lib/test/support/treeStructure.js +0 -38
- package/lib/test/util.test.js +0 -26
- package/lib/tree.jquery.d.js +0 -1
- package/lib/tree.jquery.js +0 -1105
- package/lib/types.js +0 -1
- package/lib/typings.d.js +0 -2
- package/lib/util.js +0 -15
- package/lib/version.js +0 -8
- package/src/dragAndDropHandler.ts +0 -713
- package/src/nodeElement.ts +0 -272
- package/src/types.ts +0 -19
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Position, Node } from "../node";
|
|
2
|
+
import { DropHint } from "../dragAndDropHandler/types";
|
|
3
|
+
|
|
4
|
+
class GhostDropHint implements DropHint {
|
|
5
|
+
private element: HTMLElement;
|
|
6
|
+
private node: Node;
|
|
7
|
+
private ghost: HTMLElement;
|
|
8
|
+
|
|
9
|
+
constructor(node: Node, element: HTMLElement, position: Position) {
|
|
10
|
+
this.element = element;
|
|
11
|
+
this.node = node;
|
|
12
|
+
this.ghost = this.createGhostElement();
|
|
13
|
+
|
|
14
|
+
if (position === Position.After) {
|
|
15
|
+
this.moveAfter();
|
|
16
|
+
} else if (position === Position.Before) {
|
|
17
|
+
this.moveBefore();
|
|
18
|
+
} else if (position === Position.Inside) {
|
|
19
|
+
if (node.isFolder() && node.is_open) {
|
|
20
|
+
this.moveInsideOpenFolder();
|
|
21
|
+
} else {
|
|
22
|
+
this.moveInside();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public remove(): void {
|
|
28
|
+
this.ghost.remove();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private moveAfter(): void {
|
|
32
|
+
this.element.after(this.ghost);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private moveBefore(): void {
|
|
36
|
+
this.element.before(this.ghost);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private moveInsideOpenFolder(): void {
|
|
40
|
+
const childElement = this.node.children[0]?.element;
|
|
41
|
+
|
|
42
|
+
if (childElement) {
|
|
43
|
+
childElement.before(this.ghost);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private moveInside(): void {
|
|
48
|
+
this.element.after(this.ghost);
|
|
49
|
+
this.ghost.classList.add("jqtree-inside");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private createGhostElement() {
|
|
53
|
+
const ghost = document.createElement("li");
|
|
54
|
+
ghost.className = "jqtree_common jqtree-ghost";
|
|
55
|
+
|
|
56
|
+
const circleSpan = document.createElement("span");
|
|
57
|
+
circleSpan.className = "jqtree_common jqtree-circle";
|
|
58
|
+
ghost.append(circleSpan);
|
|
59
|
+
|
|
60
|
+
const lineSpan = document.createElement("span");
|
|
61
|
+
lineSpan.className = "jqtree_common jqtree-line";
|
|
62
|
+
ghost.append(lineSpan);
|
|
63
|
+
|
|
64
|
+
return ghost;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default GhostDropHint;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Position, Node } from "../node";
|
|
2
|
+
import { DropHint } from "../dragAndDropHandler/types";
|
|
3
|
+
import BorderDropHint from "./borderDropHint";
|
|
4
|
+
import GhostDropHint from "./ghostDropHint";
|
|
5
|
+
import { GetScrollLeft } from "../jqtreeMethodTypes";
|
|
6
|
+
|
|
7
|
+
export interface NodeElementParams {
|
|
8
|
+
getScrollLeft: GetScrollLeft;
|
|
9
|
+
node: Node;
|
|
10
|
+
tabIndex?: number;
|
|
11
|
+
$treeElement: JQuery<HTMLElement>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class NodeElement {
|
|
15
|
+
public node: Node;
|
|
16
|
+
public element: HTMLElement;
|
|
17
|
+
private getScrollLeft: GetScrollLeft;
|
|
18
|
+
private tabIndex?: number;
|
|
19
|
+
private $treeElement: JQuery<HTMLElement>;
|
|
20
|
+
|
|
21
|
+
constructor({
|
|
22
|
+
getScrollLeft,
|
|
23
|
+
node,
|
|
24
|
+
tabIndex,
|
|
25
|
+
$treeElement,
|
|
26
|
+
}: NodeElementParams) {
|
|
27
|
+
this.getScrollLeft = getScrollLeft;
|
|
28
|
+
this.tabIndex = tabIndex;
|
|
29
|
+
this.$treeElement = $treeElement;
|
|
30
|
+
|
|
31
|
+
this.init(node);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public init(node: Node): void {
|
|
35
|
+
this.node = node;
|
|
36
|
+
|
|
37
|
+
if (!node.element) {
|
|
38
|
+
const element = this.$treeElement.get(0);
|
|
39
|
+
|
|
40
|
+
if (element) {
|
|
41
|
+
node.element = element;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (node.element) {
|
|
46
|
+
this.element = node.element;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public addDropHint(position: number): DropHint {
|
|
51
|
+
if (this.mustShowBorderDropHint(position)) {
|
|
52
|
+
return new BorderDropHint(this.element, this.getScrollLeft());
|
|
53
|
+
} else {
|
|
54
|
+
return new GhostDropHint(this.node, this.element, position);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public select(mustSetFocus: boolean): void {
|
|
59
|
+
this.element.classList.add("jqtree-selected");
|
|
60
|
+
|
|
61
|
+
const titleSpan = this.getTitleSpan();
|
|
62
|
+
const tabIndex = this.tabIndex;
|
|
63
|
+
|
|
64
|
+
// Check for null or undefined
|
|
65
|
+
if (tabIndex != null) {
|
|
66
|
+
titleSpan.setAttribute("tabindex", tabIndex.toString());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
titleSpan.setAttribute("aria-selected", "true");
|
|
70
|
+
|
|
71
|
+
if (mustSetFocus) {
|
|
72
|
+
titleSpan.focus();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public deselect(): void {
|
|
77
|
+
this.element.classList.remove("jqtree-selected");
|
|
78
|
+
|
|
79
|
+
const titleSpan = this.getTitleSpan();
|
|
80
|
+
titleSpan.removeAttribute("tabindex");
|
|
81
|
+
titleSpan.setAttribute("aria-selected", "false");
|
|
82
|
+
|
|
83
|
+
titleSpan.blur();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
protected getUl(): HTMLUListElement {
|
|
87
|
+
return this.element.querySelector(":scope > ul") as HTMLUListElement;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
protected getTitleSpan(): HTMLSpanElement {
|
|
91
|
+
return this.element.querySelector(
|
|
92
|
+
":scope > .jqtree-element > span.jqtree-title",
|
|
93
|
+
) as HTMLSpanElement;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected mustShowBorderDropHint(position: Position): boolean {
|
|
97
|
+
return position === Position.Inside;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default NodeElement;
|
|
@@ -13,14 +13,11 @@ export const initCoverage = async (context: BrowserContext) => {
|
|
|
13
13
|
await context.exposeFunction(
|
|
14
14
|
"collectIstanbulCoverage",
|
|
15
15
|
(coverageJSON: string) => {
|
|
16
|
-
if (
|
|
17
|
-
console.log("No coverage");
|
|
18
|
-
} else {
|
|
16
|
+
if (coverageJSON) {
|
|
19
17
|
const filename = path.join(
|
|
20
18
|
istanbulCLIOutput,
|
|
21
19
|
`playwright_coverage_${generateUUID()}.json`
|
|
22
20
|
);
|
|
23
|
-
console.log(`Writing coverage to ${filename}`);
|
|
24
21
|
fs.writeFileSync(filename, coverageJSON);
|
|
25
22
|
}
|
|
26
23
|
}
|
|
@@ -17,10 +17,6 @@ const initPage = async (page: Page, baseURL: string | undefined) => {
|
|
|
17
17
|
await page.waitForLoadState("domcontentloaded");
|
|
18
18
|
|
|
19
19
|
page.on("console", (msg) => console.log(`console: ${msg.text()}`));
|
|
20
|
-
|
|
21
|
-
await page.evaluate(`
|
|
22
|
-
console.log(window.__coverage__ ? 'Coverage enabled' : 'Coverage not enabled');
|
|
23
|
-
`);
|
|
24
20
|
};
|
|
25
21
|
|
|
26
22
|
interface InitTreeOptions {
|
package/src/saveStateHandler.ts
CHANGED
|
@@ -1,25 +1,76 @@
|
|
|
1
1
|
import { isInt } from "./util";
|
|
2
|
-
import { JqTreeWidget } from "./tree.jquery";
|
|
3
2
|
import { Node } from "./node";
|
|
3
|
+
import { OnGetStateFromStorage, OnSetStateFromStorage } from "./jqtreeOptions";
|
|
4
|
+
import {
|
|
5
|
+
AddToSelection,
|
|
6
|
+
GetNodeById,
|
|
7
|
+
GetSelectedNodes,
|
|
8
|
+
GetTree,
|
|
9
|
+
OpenNode,
|
|
10
|
+
RefreshElements,
|
|
11
|
+
RemoveFromSelection,
|
|
12
|
+
} from "./jqtreeMethodTypes";
|
|
4
13
|
|
|
5
14
|
export interface SavedState {
|
|
6
15
|
open_nodes: NodeId[];
|
|
7
16
|
selected_node: NodeId[];
|
|
8
17
|
}
|
|
9
18
|
|
|
19
|
+
interface SaveStateHandlerParams {
|
|
20
|
+
addToSelection: AddToSelection;
|
|
21
|
+
getNodeById: GetNodeById;
|
|
22
|
+
getSelectedNodes: GetSelectedNodes;
|
|
23
|
+
getTree: GetTree;
|
|
24
|
+
onGetStateFromStorage?: OnGetStateFromStorage;
|
|
25
|
+
onSetStateFromStorage?: OnSetStateFromStorage;
|
|
26
|
+
openNode: OpenNode;
|
|
27
|
+
refreshElements: RefreshElements;
|
|
28
|
+
removeFromSelection: RemoveFromSelection;
|
|
29
|
+
saveState: boolean | string;
|
|
30
|
+
}
|
|
31
|
+
|
|
10
32
|
export default class SaveStateHandler {
|
|
11
|
-
private
|
|
33
|
+
private addToSelection: AddToSelection;
|
|
34
|
+
private getNodeById: GetNodeById;
|
|
35
|
+
private getSelectedNodes: GetSelectedNodes;
|
|
36
|
+
private getTree: GetTree;
|
|
37
|
+
private onGetStateFromStorage?: OnGetStateFromStorage;
|
|
38
|
+
private onSetStateFromStorage?: OnSetStateFromStorage;
|
|
39
|
+
private openNode: OpenNode;
|
|
40
|
+
private refreshElements: RefreshElements;
|
|
41
|
+
private removeFromSelection: RemoveFromSelection;
|
|
42
|
+
private saveStateOption: boolean | string;
|
|
12
43
|
private _supportsLocalStorage: boolean | null;
|
|
13
44
|
|
|
14
|
-
constructor(
|
|
15
|
-
|
|
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;
|
|
16
67
|
}
|
|
17
68
|
|
|
18
69
|
public saveState(): void {
|
|
19
70
|
const state = JSON.stringify(this.getState());
|
|
20
71
|
|
|
21
|
-
if (this.
|
|
22
|
-
this.
|
|
72
|
+
if (this.onSetStateFromStorage) {
|
|
73
|
+
this.onSetStateFromStorage(state);
|
|
23
74
|
} else if (this.supportsLocalStorage()) {
|
|
24
75
|
localStorage.setItem(this.getKeyName(), state);
|
|
25
76
|
}
|
|
@@ -39,7 +90,7 @@ export default class SaveStateHandler {
|
|
|
39
90
|
const getOpenNodeIds = (): NodeId[] => {
|
|
40
91
|
const openNodes: NodeId[] = [];
|
|
41
92
|
|
|
42
|
-
this.
|
|
93
|
+
this.getTree()?.iterate((node: Node) => {
|
|
43
94
|
if (node.is_open && node.id && node.hasChildren()) {
|
|
44
95
|
openNodes.push(node.id);
|
|
45
96
|
}
|
|
@@ -52,7 +103,7 @@ export default class SaveStateHandler {
|
|
|
52
103
|
const getSelectedNodeIds = (): NodeId[] => {
|
|
53
104
|
const selectedNodeIds: NodeId[] = [];
|
|
54
105
|
|
|
55
|
-
this.
|
|
106
|
+
this.getSelectedNodes().forEach((node) => {
|
|
56
107
|
if (node.id != null) {
|
|
57
108
|
selectedNodeIds.push(node.id);
|
|
58
109
|
}
|
|
@@ -94,13 +145,13 @@ export default class SaveStateHandler {
|
|
|
94
145
|
|
|
95
146
|
public setInitialStateOnDemand(
|
|
96
147
|
state: SavedState,
|
|
97
|
-
cbFinished: () => void
|
|
148
|
+
cbFinished: () => void,
|
|
98
149
|
): void {
|
|
99
150
|
if (state) {
|
|
100
151
|
this.doSetInitialStateOnDemand(
|
|
101
152
|
state.open_nodes,
|
|
102
153
|
state.selected_node,
|
|
103
|
-
cbFinished
|
|
154
|
+
cbFinished,
|
|
104
155
|
);
|
|
105
156
|
} else {
|
|
106
157
|
cbFinished();
|
|
@@ -130,8 +181,8 @@ export default class SaveStateHandler {
|
|
|
130
181
|
}
|
|
131
182
|
|
|
132
183
|
private loadFromStorage(): string | null {
|
|
133
|
-
if (this.
|
|
134
|
-
return this.
|
|
184
|
+
if (this.onGetStateFromStorage) {
|
|
185
|
+
return this.onGetStateFromStorage();
|
|
135
186
|
} else if (this.supportsLocalStorage()) {
|
|
136
187
|
return localStorage.getItem(this.getKeyName());
|
|
137
188
|
} else {
|
|
@@ -143,7 +194,7 @@ export default class SaveStateHandler {
|
|
|
143
194
|
let mustLoadOnDemand = false;
|
|
144
195
|
|
|
145
196
|
for (const nodeId of nodeIds) {
|
|
146
|
-
const node = this.
|
|
197
|
+
const node = this.getNodeById(nodeId);
|
|
147
198
|
|
|
148
199
|
if (node) {
|
|
149
200
|
if (!node.load_on_demand) {
|
|
@@ -161,12 +212,12 @@ export default class SaveStateHandler {
|
|
|
161
212
|
let selectCount = 0;
|
|
162
213
|
|
|
163
214
|
for (const nodeId of nodeIds) {
|
|
164
|
-
const node = this.
|
|
215
|
+
const node = this.getNodeById(nodeId);
|
|
165
216
|
|
|
166
217
|
if (node) {
|
|
167
218
|
selectCount += 1;
|
|
168
219
|
|
|
169
|
-
this.
|
|
220
|
+
this.addToSelection(node);
|
|
170
221
|
}
|
|
171
222
|
}
|
|
172
223
|
|
|
@@ -174,19 +225,17 @@ export default class SaveStateHandler {
|
|
|
174
225
|
}
|
|
175
226
|
|
|
176
227
|
private resetSelection(): void {
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
const selectedNodes = selectNodeHandler.getSelectedNodes();
|
|
228
|
+
const selectedNodes = this.getSelectedNodes();
|
|
180
229
|
|
|
181
230
|
selectedNodes.forEach((node) => {
|
|
182
|
-
|
|
231
|
+
this.removeFromSelection(node);
|
|
183
232
|
});
|
|
184
233
|
}
|
|
185
234
|
|
|
186
235
|
private doSetInitialStateOnDemand(
|
|
187
236
|
nodeIdsParam: NodeId[],
|
|
188
237
|
selectedNodes: NodeId[],
|
|
189
|
-
cbFinished: () => void
|
|
238
|
+
cbFinished: () => void,
|
|
190
239
|
): void {
|
|
191
240
|
let loadingCount = 0;
|
|
192
241
|
let nodeIds = nodeIdsParam;
|
|
@@ -195,7 +244,7 @@ export default class SaveStateHandler {
|
|
|
195
244
|
const newNodesIds = [];
|
|
196
245
|
|
|
197
246
|
for (const nodeId of nodeIds) {
|
|
198
|
-
const node = this.
|
|
247
|
+
const node = this.getNodeById(nodeId);
|
|
199
248
|
|
|
200
249
|
if (!node) {
|
|
201
250
|
newNodesIds.push(nodeId);
|
|
@@ -204,7 +253,7 @@ export default class SaveStateHandler {
|
|
|
204
253
|
if (node.load_on_demand) {
|
|
205
254
|
loadAndOpenNode(node);
|
|
206
255
|
} else {
|
|
207
|
-
this.
|
|
256
|
+
this.openNode(node, false);
|
|
208
257
|
}
|
|
209
258
|
}
|
|
210
259
|
}
|
|
@@ -213,7 +262,7 @@ export default class SaveStateHandler {
|
|
|
213
262
|
nodeIds = newNodesIds;
|
|
214
263
|
|
|
215
264
|
if (this.selectInitialNodes(selectedNodes)) {
|
|
216
|
-
this.
|
|
265
|
+
this.refreshElements(null);
|
|
217
266
|
}
|
|
218
267
|
|
|
219
268
|
if (loadingCount === 0) {
|
|
@@ -223,7 +272,7 @@ export default class SaveStateHandler {
|
|
|
223
272
|
|
|
224
273
|
const loadAndOpenNode = (node: Node): void => {
|
|
225
274
|
loadingCount += 1;
|
|
226
|
-
this.
|
|
275
|
+
this.openNode(node, false, () => {
|
|
227
276
|
loadingCount -= 1;
|
|
228
277
|
openNodes();
|
|
229
278
|
});
|
|
@@ -233,8 +282,8 @@ export default class SaveStateHandler {
|
|
|
233
282
|
}
|
|
234
283
|
|
|
235
284
|
private getKeyName(): string {
|
|
236
|
-
if (typeof this.
|
|
237
|
-
return this.
|
|
285
|
+
if (typeof this.saveStateOption === "string") {
|
|
286
|
+
return this.saveStateOption;
|
|
238
287
|
} else {
|
|
239
288
|
return "tree";
|
|
240
289
|
}
|
package/src/scrollHandler.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PositionInfo } from "./types";
|
|
1
|
+
import { PositionInfo } from "./mouseWidgetTypes";
|
|
3
2
|
import { ScrollParent } from "./scrollHandler/types";
|
|
4
3
|
import createScrollParent from "./scrollHandler/createScrollParent";
|
|
5
4
|
|
|
5
|
+
interface ScrollHandlerParams {
|
|
6
|
+
refreshHitAreas: () => void;
|
|
7
|
+
$treeElement: JQuery<HTMLElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
export default class ScrollHandler {
|
|
7
|
-
private
|
|
11
|
+
private refreshHitAreas: () => void;
|
|
8
12
|
private scrollParent?: ScrollParent;
|
|
13
|
+
private $treeElement: JQuery<HTMLElement>;
|
|
9
14
|
|
|
10
|
-
constructor(
|
|
11
|
-
this.
|
|
15
|
+
constructor({ refreshHitAreas, $treeElement }: ScrollHandlerParams) {
|
|
16
|
+
this.refreshHitAreas = refreshHitAreas;
|
|
12
17
|
this.scrollParent = undefined;
|
|
18
|
+
this.$treeElement = $treeElement;
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
public checkScrolling(positionInfo: PositionInfo): void {
|
|
@@ -48,8 +54,8 @@ export default class ScrollHandler {
|
|
|
48
54
|
private getScrollParent(): ScrollParent {
|
|
49
55
|
if (!this.scrollParent) {
|
|
50
56
|
this.scrollParent = createScrollParent(
|
|
51
|
-
this
|
|
52
|
-
this.
|
|
57
|
+
this.$treeElement,
|
|
58
|
+
this.refreshHitAreas,
|
|
53
59
|
);
|
|
54
60
|
}
|
|
55
61
|
|
package/src/selectNodeHandler.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Node } from "./node";
|
|
2
|
-
import {
|
|
2
|
+
import { GetNodeById } from "./jqtreeMethodTypes";
|
|
3
|
+
|
|
4
|
+
interface SelectNodeHandlerParameters {
|
|
5
|
+
getNodeById: GetNodeById;
|
|
6
|
+
}
|
|
3
7
|
|
|
4
8
|
export default class SelectNodeHandler {
|
|
5
|
-
private
|
|
9
|
+
private getNodeById: GetNodeById;
|
|
6
10
|
private selectedNodes: Set<NodeId>;
|
|
7
11
|
private selectedSingleNode: Node | null;
|
|
8
12
|
|
|
9
|
-
constructor(
|
|
10
|
-
this.
|
|
13
|
+
constructor({ getNodeById }: SelectNodeHandlerParameters) {
|
|
14
|
+
this.getNodeById = getNodeById;
|
|
11
15
|
this.selectedNodes = new Set<NodeId>();
|
|
12
16
|
this.clear();
|
|
13
17
|
}
|
|
@@ -29,7 +33,7 @@ export default class SelectNodeHandler {
|
|
|
29
33
|
const selectedNodes: Node[] = [];
|
|
30
34
|
|
|
31
35
|
this.selectedNodes.forEach((id) => {
|
|
32
|
-
const node = this.
|
|
36
|
+
const node = this.getNodeById(id);
|
|
33
37
|
if (node) {
|
|
34
38
|
selectedNodes.push(node);
|
|
35
39
|
}
|
|
@@ -53,7 +57,7 @@ export default class SelectNodeHandler {
|
|
|
53
57
|
if (
|
|
54
58
|
Object.prototype.hasOwnProperty.call(this.selectedNodes, id)
|
|
55
59
|
) {
|
|
56
|
-
const node = this.
|
|
60
|
+
const node = this.getNodeById(id);
|
|
57
61
|
if (node && parent.isParentOf(node)) {
|
|
58
62
|
selectedNodes.push(node);
|
|
59
63
|
}
|
|
@@ -108,14 +112,4 @@ export default class SelectNodeHandler {
|
|
|
108
112
|
this.selectedSingleNode = node;
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
|
-
|
|
112
|
-
public isFocusOnTree(): boolean {
|
|
113
|
-
const activeElement = document.activeElement;
|
|
114
|
-
|
|
115
|
-
return Boolean(
|
|
116
|
-
activeElement &&
|
|
117
|
-
activeElement.tagName === "SPAN" &&
|
|
118
|
-
this.treeWidget._containsElement(activeElement as HTMLElement)
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
115
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import getGiven from "givens";
|
|
2
|
+
import { userEvent } from "@testing-library/user-event";
|
|
2
3
|
import "../../tree.jquery";
|
|
3
4
|
import exampleData from "../support/exampleData";
|
|
4
5
|
|
|
@@ -18,22 +19,16 @@ describe("keyboard support", () => {
|
|
|
18
19
|
interface Vars {
|
|
19
20
|
autoOpen: boolean;
|
|
20
21
|
initialSelectedNode: INode | null;
|
|
21
|
-
pressedKey:
|
|
22
|
+
pressedKey: string;
|
|
22
23
|
$tree: JQuery<HTMLElement>;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
const KEY_DOWN = 40;
|
|
26
|
-
const KEY_LEFT = 37;
|
|
27
|
-
const KEY_RIGHT = 39;
|
|
28
|
-
const KEY_UP = 38;
|
|
29
|
-
const KEY_PAGE_UP = 33;
|
|
30
|
-
|
|
31
26
|
const given = getGiven<Vars>();
|
|
32
27
|
given("autoOpen", () => false);
|
|
33
28
|
given("initialSelectedNode", () => null);
|
|
34
29
|
given("$tree", () => $("#tree1"));
|
|
35
30
|
|
|
36
|
-
beforeEach(() => {
|
|
31
|
+
beforeEach(async () => {
|
|
37
32
|
given.$tree.tree({
|
|
38
33
|
animationSpeed: 0,
|
|
39
34
|
autoOpen: given.autoOpen,
|
|
@@ -44,15 +39,15 @@ describe("keyboard support", () => {
|
|
|
44
39
|
given.$tree.tree("selectNode", given.initialSelectedNode);
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
|
|
42
|
+
await userEvent.keyboard(`{${given.pressedKey}}`);
|
|
48
43
|
});
|
|
49
44
|
|
|
50
45
|
context("with key down", () => {
|
|
51
|
-
given("pressedKey", () =>
|
|
46
|
+
given("pressedKey", () => "ArrowDown");
|
|
52
47
|
|
|
53
48
|
context("when a node is selected", () => {
|
|
54
49
|
given("initialSelectedNode", () =>
|
|
55
|
-
given.$tree.tree("getNodeByNameMustExist", "node1")
|
|
50
|
+
given.$tree.tree("getNodeByNameMustExist", "node1"),
|
|
56
51
|
);
|
|
57
52
|
|
|
58
53
|
it("selects the next node", () => {
|
|
@@ -71,7 +66,7 @@ describe("keyboard support", () => {
|
|
|
71
66
|
|
|
72
67
|
context("when the last node is selected", () => {
|
|
73
68
|
given("initialSelectedNode", () =>
|
|
74
|
-
given.$tree.tree("getNodeByNameMustExist", "node2")
|
|
69
|
+
given.$tree.tree("getNodeByNameMustExist", "node2"),
|
|
75
70
|
);
|
|
76
71
|
|
|
77
72
|
it("keeps the node selected", () => {
|
|
@@ -83,11 +78,11 @@ describe("keyboard support", () => {
|
|
|
83
78
|
});
|
|
84
79
|
|
|
85
80
|
context("with key up", () => {
|
|
86
|
-
given("pressedKey", () =>
|
|
81
|
+
given("pressedKey", () => "ArrowUp");
|
|
87
82
|
|
|
88
83
|
context("when a node is selected", () => {
|
|
89
84
|
given("initialSelectedNode", () =>
|
|
90
|
-
given.$tree.tree("getNodeByNameMustExist", "node2")
|
|
85
|
+
given.$tree.tree("getNodeByNameMustExist", "node2"),
|
|
91
86
|
);
|
|
92
87
|
|
|
93
88
|
it("selects the next node", () => {
|
|
@@ -106,11 +101,11 @@ describe("keyboard support", () => {
|
|
|
106
101
|
});
|
|
107
102
|
|
|
108
103
|
context("with key right", () => {
|
|
109
|
-
given("pressedKey", () =>
|
|
104
|
+
given("pressedKey", () => "ArrowRight");
|
|
110
105
|
|
|
111
106
|
context("when a closed folder is selected", () => {
|
|
112
107
|
given("initialSelectedNode", () =>
|
|
113
|
-
given.$tree.tree("getNodeByNameMustExist", "node1")
|
|
108
|
+
given.$tree.tree("getNodeByNameMustExist", "node1"),
|
|
114
109
|
);
|
|
115
110
|
|
|
116
111
|
it("opens the folder", () => {
|
|
@@ -132,7 +127,7 @@ describe("keyboard support", () => {
|
|
|
132
127
|
context("when an open folder is selected", () => {
|
|
133
128
|
given("autoOpen", () => true);
|
|
134
129
|
given("initialSelectedNode", () =>
|
|
135
|
-
given.$tree.tree("getNodeByNameMustExist", "node1")
|
|
130
|
+
given.$tree.tree("getNodeByNameMustExist", "node1"),
|
|
136
131
|
);
|
|
137
132
|
|
|
138
133
|
it("selects the first child", () => {
|
|
@@ -168,7 +163,7 @@ describe("keyboard support", () => {
|
|
|
168
163
|
|
|
169
164
|
context("when a child is selected", () => {
|
|
170
165
|
given("initialSelectedNode", () =>
|
|
171
|
-
given.$tree.tree("getNodeByNameMustExist", "child1")
|
|
166
|
+
given.$tree.tree("getNodeByNameMustExist", "child1"),
|
|
172
167
|
);
|
|
173
168
|
|
|
174
169
|
it("does nothing", () => {
|
|
@@ -179,11 +174,11 @@ describe("keyboard support", () => {
|
|
|
179
174
|
});
|
|
180
175
|
});
|
|
181
176
|
context("with key left", () => {
|
|
182
|
-
given("pressedKey", () =>
|
|
177
|
+
given("pressedKey", () => "ArrowLeft");
|
|
183
178
|
|
|
184
179
|
context("when a closed folder is selected", () => {
|
|
185
180
|
given("initialSelectedNode", () =>
|
|
186
|
-
given.$tree.tree("getNodeByNameMustExist", "node3")
|
|
181
|
+
given.$tree.tree("getNodeByNameMustExist", "node3"),
|
|
187
182
|
);
|
|
188
183
|
|
|
189
184
|
it("selects the previous node", () => {
|
|
@@ -210,7 +205,7 @@ describe("keyboard support", () => {
|
|
|
210
205
|
context("when an open folder is selected", () => {
|
|
211
206
|
given("autoOpen", () => true);
|
|
212
207
|
given("initialSelectedNode", () =>
|
|
213
|
-
given.$tree.tree("getNodeByNameMustExist", "node2")
|
|
208
|
+
given.$tree.tree("getNodeByNameMustExist", "node2"),
|
|
214
209
|
);
|
|
215
210
|
|
|
216
211
|
it("closes the folder", () => {
|
|
@@ -237,10 +232,10 @@ describe("keyboard support", () => {
|
|
|
237
232
|
});
|
|
238
233
|
|
|
239
234
|
context("with page up key", () => {
|
|
240
|
-
given("pressedKey", () =>
|
|
235
|
+
given("pressedKey", () => "PageUp");
|
|
241
236
|
|
|
242
237
|
given("initialSelectedNode", () =>
|
|
243
|
-
given.$tree.tree("getNodeByNameMustExist", "child1")
|
|
238
|
+
given.$tree.tree("getNodeByNameMustExist", "child1"),
|
|
244
239
|
);
|
|
245
240
|
|
|
246
241
|
it("does nothing", () => {
|