jqtree 1.7.4 → 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/.eslintrc +5 -1
- 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 +12 -0
- package/docs/package.json +1 -1
- package/docs/pnpm-lock.yaml +30 -30
- package/package.json +31 -27
- 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 -38
- package/src/mouse.widget.ts +3 -3
- package/src/mouseWidgetTypes.ts +6 -0
- package/src/node.ts +32 -48
- 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/nodeUtils.ts +10 -0
- package/src/playwright/coverage.ts +1 -4
- package/src/playwright/playwright.test.ts +203 -15
- package/src/playwright/testUtils.ts +23 -15
- package/src/saveStateHandler.ts +75 -26
- package/src/scrollHandler/containerScrollParent.ts +177 -0
- package/src/scrollHandler/createScrollParent.ts +50 -0
- package/src/scrollHandler/documentScrollParent.ts +182 -0
- package/src/scrollHandler/types.ts +7 -0
- package/src/scrollHandler.ts +36 -248
- package/src/selectNodeHandler.ts +10 -16
- package/src/test/jqTree/keyboard.test.ts +18 -23
- package/src/test/jqTree/loadOnDemand.test.ts +2 -3
- package/src/test/jqTree/methods.test.ts +33 -4
- package/src/test/jqTree/options.test.ts +15 -4
- package/src/test/node.test.ts +85 -26
- package/src/test/nodeUtils.test.ts +21 -0
- package/src/tree.jquery.ts +262 -83
- package/src/util.ts +3 -0
- package/src/version.ts +1 -1
- package/tree.jquery.debug.js +1922 -2608
- 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 -124
- package/lib/dragAndDropHandler.js +0 -596
- package/lib/elementsRenderer.js +0 -268
- package/lib/jqtreeOptions.js +0 -1
- package/lib/keyHandler.js +0 -115
- package/lib/mouse.widget.js +0 -256
- package/lib/node.js +0 -717
- package/lib/nodeElement.js +0 -277
- package/lib/playwright/coverage.js +0 -96
- package/lib/playwright/playwright.test.js +0 -228
- package/lib/playwright/testUtils.js +0 -184
- package/lib/saveStateHandler.js +0 -278
- package/lib/scrollHandler.js +0 -250
- package/lib/selectNodeHandler.js +0 -129
- package/lib/simple.widget.js +0 -159
- 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 -1347
- package/lib/test/jqTree/options.test.js +0 -548
- package/lib/test/node.test.js +0 -1160
- package/lib/test/nodeUtil.test.js +0 -27
- package/lib/test/support/exampleData.js +0 -36
- 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 -32
- package/lib/test/support/treeStructure.js +0 -39
- package/lib/test/util.test.js +0 -26
- package/lib/tree.jquery.d.js +0 -1
- package/lib/tree.jquery.js +0 -1106
- package/lib/types.js +0 -1
- package/lib/typings.d.js +0 -2
- package/lib/util.js +0 -18
- package/lib/version.js +0 -9
- package/src/dragAndDropHandler.ts +0 -719
- package/src/nodeElement.ts +0 -272
- package/src/types.ts +0 -19
package/src/scrollHandler.ts
CHANGED
|
@@ -1,276 +1,64 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PositionInfo } from "./mouseWidgetTypes";
|
|
2
|
+
import { ScrollParent } from "./scrollHandler/types";
|
|
3
|
+
import createScrollParent from "./scrollHandler/createScrollParent";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
private $scrollParent: JQuery | null;
|
|
9
|
-
private scrollParentTop: number;
|
|
5
|
+
interface ScrollHandlerParams {
|
|
6
|
+
refreshHitAreas: () => void;
|
|
7
|
+
$treeElement: JQuery<HTMLElement>;
|
|
8
|
+
}
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
export default class ScrollHandler {
|
|
11
|
+
private refreshHitAreas: () => void;
|
|
12
|
+
private scrollParent?: ScrollParent;
|
|
13
|
+
private $treeElement: JQuery<HTMLElement>;
|
|
14
|
+
|
|
15
|
+
constructor({ refreshHitAreas, $treeElement }: ScrollHandlerParams) {
|
|
16
|
+
this.refreshHitAreas = refreshHitAreas;
|
|
17
|
+
this.scrollParent = undefined;
|
|
18
|
+
this.$treeElement = $treeElement;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
public checkScrolling(): void {
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
20
|
-
this.checkHorizontalScrolling();
|
|
21
|
+
public checkScrolling(positionInfo: PositionInfo): void {
|
|
22
|
+
this.checkVerticalScrolling(positionInfo);
|
|
23
|
+
this.checkHorizontalScrolling(positionInfo);
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
public
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
if (this.$scrollParent && this.$scrollParent[0]) {
|
|
27
|
-
this.$scrollParent[0].scrollTop = top;
|
|
28
|
-
} else {
|
|
29
|
-
const offset = this.treeWidget.$el.offset();
|
|
30
|
-
const treeTop = offset ? offset.top : 0;
|
|
31
|
-
|
|
32
|
-
jQuery(document).scrollTop(top + treeTop);
|
|
33
|
-
}
|
|
26
|
+
public stopScrolling() {
|
|
27
|
+
this.getScrollParent().stopScrolling();
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
public
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
let elementBottom: number;
|
|
40
|
-
let viewBottom: number;
|
|
41
|
-
let elementTop: number;
|
|
42
|
-
let viewTop: number;
|
|
43
|
-
|
|
44
|
-
const elHeight = $element.height() || 0;
|
|
45
|
-
|
|
46
|
-
if (this.$scrollParent) {
|
|
47
|
-
viewTop = 0;
|
|
48
|
-
viewBottom = this.$scrollParent.height() || 0;
|
|
49
|
-
|
|
50
|
-
const offset = $element.offset();
|
|
51
|
-
const originalTop = offset ? offset.top : 0;
|
|
52
|
-
|
|
53
|
-
elementTop = originalTop - this.scrollParentTop;
|
|
54
|
-
elementBottom = elementTop + elHeight;
|
|
55
|
-
} else {
|
|
56
|
-
viewTop = jQuery(window).scrollTop() || 0;
|
|
57
|
-
|
|
58
|
-
const windowHeight = jQuery(window).height() || 0;
|
|
59
|
-
viewBottom = viewTop + windowHeight;
|
|
60
|
-
|
|
61
|
-
const offset = $element.offset();
|
|
62
|
-
|
|
63
|
-
elementTop = offset ? offset.top : 0;
|
|
64
|
-
elementBottom = elementTop + elHeight;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return elementBottom <= viewBottom && elementTop >= viewTop;
|
|
30
|
+
public scrollToY(top: number): void {
|
|
31
|
+
this.getScrollParent().scrollToY(top);
|
|
68
32
|
}
|
|
69
33
|
|
|
70
34
|
public getScrollLeft(): number {
|
|
71
|
-
|
|
72
|
-
return 0;
|
|
73
|
-
} else {
|
|
74
|
-
return this.$scrollParent.scrollLeft() || 0;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private initScrollParent(): void {
|
|
79
|
-
const getParentWithOverflow = (): JQuery | null => {
|
|
80
|
-
const cssAttributes = ["overflow", "overflow-y"];
|
|
81
|
-
|
|
82
|
-
const hasOverFlow = ($el: JQuery): boolean => {
|
|
83
|
-
for (const attr of cssAttributes) {
|
|
84
|
-
const overflowValue = $el.css(attr);
|
|
85
|
-
if (
|
|
86
|
-
overflowValue === "auto" ||
|
|
87
|
-
overflowValue === "scroll"
|
|
88
|
-
) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return false;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
if (hasOverFlow(this.treeWidget.$el)) {
|
|
97
|
-
return this.treeWidget.$el;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
for (const el of this.treeWidget.$el.parents().get()) {
|
|
101
|
-
const $el = jQuery(el);
|
|
102
|
-
if (hasOverFlow($el)) {
|
|
103
|
-
return $el;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return null;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const setDocumentAsScrollParent = (): void => {
|
|
111
|
-
this.scrollParentTop = 0;
|
|
112
|
-
this.$scrollParent = null;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (this.treeWidget.$el.css("position") === "fixed") {
|
|
116
|
-
setDocumentAsScrollParent();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const $scrollParent = getParentWithOverflow();
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
$scrollParent &&
|
|
123
|
-
$scrollParent.length &&
|
|
124
|
-
$scrollParent[0]?.tagName !== "HTML"
|
|
125
|
-
) {
|
|
126
|
-
this.$scrollParent = $scrollParent;
|
|
127
|
-
|
|
128
|
-
const offset = this.$scrollParent.offset();
|
|
129
|
-
this.scrollParentTop = offset ? offset.top : 0;
|
|
130
|
-
} else {
|
|
131
|
-
setDocumentAsScrollParent();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
this.isInitialized = true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private ensureInit(): void {
|
|
138
|
-
if (!this.isInitialized) {
|
|
139
|
-
this.initScrollParent();
|
|
140
|
-
}
|
|
35
|
+
return this.getScrollParent().getScrollLeft();
|
|
141
36
|
}
|
|
142
37
|
|
|
143
|
-
private
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!scrollParent) {
|
|
38
|
+
private checkVerticalScrolling(positionInfo: PositionInfo): void {
|
|
39
|
+
if (positionInfo.pageY == null) {
|
|
147
40
|
return;
|
|
148
41
|
}
|
|
149
42
|
|
|
150
|
-
|
|
151
|
-
this.scrollParentTop + scrollParent.offsetHeight - area.bottom;
|
|
152
|
-
|
|
153
|
-
if (distanceBottom < 20) {
|
|
154
|
-
scrollParent.scrollTop += 20;
|
|
155
|
-
this.treeWidget.refreshHitAreas();
|
|
156
|
-
this.previousTop = -1;
|
|
157
|
-
} else if (area.top - this.scrollParentTop < 20) {
|
|
158
|
-
scrollParent.scrollTop -= 20;
|
|
159
|
-
this.treeWidget.refreshHitAreas();
|
|
160
|
-
this.previousTop = -1;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private handleVerticalScrollingWithDocument(area: HitArea): void {
|
|
165
|
-
const scrollTop = jQuery(document).scrollTop() || 0;
|
|
166
|
-
const distanceTop = area.top - scrollTop;
|
|
167
|
-
|
|
168
|
-
if (distanceTop < 20) {
|
|
169
|
-
jQuery(document).scrollTop(scrollTop - 20);
|
|
170
|
-
} else {
|
|
171
|
-
const windowHeight = jQuery(window).height() || 0;
|
|
172
|
-
|
|
173
|
-
if (windowHeight - (area.bottom - scrollTop) < 20) {
|
|
174
|
-
jQuery(document).scrollTop(scrollTop + 20);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
43
|
+
this.getScrollParent().checkVerticalScrolling(positionInfo.pageY);
|
|
177
44
|
}
|
|
178
45
|
|
|
179
|
-
private
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (hoveredArea && hoveredArea.top !== this.previousTop) {
|
|
183
|
-
this.previousTop = hoveredArea.top;
|
|
184
|
-
|
|
185
|
-
if (this.$scrollParent) {
|
|
186
|
-
this.handleVerticalScrollingWithScrollParent(hoveredArea);
|
|
187
|
-
} else {
|
|
188
|
-
this.handleVerticalScrollingWithDocument(hoveredArea);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private checkHorizontalScrolling(): void {
|
|
194
|
-
const positionInfo = this.treeWidget.dndHandler.positionInfo;
|
|
195
|
-
|
|
196
|
-
if (!positionInfo) {
|
|
46
|
+
private checkHorizontalScrolling(positionInfo: PositionInfo): void {
|
|
47
|
+
if (positionInfo.pageX == null) {
|
|
197
48
|
return;
|
|
198
49
|
}
|
|
199
50
|
|
|
200
|
-
|
|
201
|
-
this.handleHorizontalScrollingWithParent(positionInfo);
|
|
202
|
-
} else {
|
|
203
|
-
this.handleHorizontalScrollingWithDocument(positionInfo);
|
|
204
|
-
}
|
|
51
|
+
this.getScrollParent().checkHorizontalScrolling(positionInfo.pageX);
|
|
205
52
|
}
|
|
206
53
|
|
|
207
|
-
private
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
positionInfo.pageY === undefined
|
|
213
|
-
) {
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const $scrollParent = this.$scrollParent;
|
|
218
|
-
const scrollParentOffset = $scrollParent && $scrollParent.offset();
|
|
219
|
-
|
|
220
|
-
if (!($scrollParent && scrollParentOffset)) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const scrollParent = $scrollParent[0];
|
|
225
|
-
|
|
226
|
-
if (!scrollParent) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const canScrollRight =
|
|
231
|
-
scrollParent.scrollLeft + scrollParent.clientWidth <
|
|
232
|
-
scrollParent.scrollWidth;
|
|
233
|
-
const canScrollLeft = scrollParent.scrollLeft > 0;
|
|
234
|
-
|
|
235
|
-
const rightEdge = scrollParentOffset.left + scrollParent.clientWidth;
|
|
236
|
-
const leftEdge = scrollParentOffset.left;
|
|
237
|
-
const isNearRightEdge = positionInfo.pageX > rightEdge - 20;
|
|
238
|
-
const isNearLeftEdge = positionInfo.pageX < leftEdge + 20;
|
|
239
|
-
|
|
240
|
-
if (isNearRightEdge && canScrollRight) {
|
|
241
|
-
scrollParent.scrollLeft = Math.min(
|
|
242
|
-
scrollParent.scrollLeft + 20,
|
|
243
|
-
scrollParent.scrollWidth
|
|
54
|
+
private getScrollParent(): ScrollParent {
|
|
55
|
+
if (!this.scrollParent) {
|
|
56
|
+
this.scrollParent = createScrollParent(
|
|
57
|
+
this.$treeElement,
|
|
58
|
+
this.refreshHitAreas,
|
|
244
59
|
);
|
|
245
|
-
} else if (isNearLeftEdge && canScrollLeft) {
|
|
246
|
-
scrollParent.scrollLeft = Math.max(scrollParent.scrollLeft - 20, 0);
|
|
247
60
|
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
private handleHorizontalScrollingWithDocument(
|
|
251
|
-
positionInfo: PositionInfo
|
|
252
|
-
): void {
|
|
253
|
-
if (
|
|
254
|
-
positionInfo.pageX === undefined ||
|
|
255
|
-
positionInfo.pageY === undefined
|
|
256
|
-
) {
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const $document = jQuery(document);
|
|
261
61
|
|
|
262
|
-
|
|
263
|
-
const windowWidth = jQuery(window).width() || 0;
|
|
264
|
-
|
|
265
|
-
const canScrollLeft = scrollLeft > 0;
|
|
266
|
-
|
|
267
|
-
const isNearRightEdge = positionInfo.pageX > windowWidth - 20;
|
|
268
|
-
const isNearLeftEdge = positionInfo.pageX - scrollLeft < 20;
|
|
269
|
-
|
|
270
|
-
if (isNearRightEdge) {
|
|
271
|
-
$document.scrollLeft(scrollLeft + 20);
|
|
272
|
-
} else if (isNearLeftEdge && canScrollLeft) {
|
|
273
|
-
$document.scrollLeft(Math.max(scrollLeft - 20, 0));
|
|
274
|
-
}
|
|
62
|
+
return this.scrollParent;
|
|
275
63
|
}
|
|
276
64
|
}
|
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", () => {
|
|
@@ -136,9 +136,8 @@ context("when a node has load_on_demand in the data", () => {
|
|
|
136
136
|
|
|
137
137
|
context("when the node is selected and doesn't have the focus", () => {
|
|
138
138
|
beforeEach(() => {
|
|
139
|
-
given.$tree.tree("selectNode", given.node
|
|
140
|
-
|
|
141
|
-
});
|
|
139
|
+
given.$tree.tree("selectNode", given.node);
|
|
140
|
+
(document.activeElement as HTMLElement).blur(); // eslint-disable-line testing-library/no-node-access
|
|
142
141
|
});
|
|
143
142
|
|
|
144
143
|
it("keeps the node selected and not focused", async () => {
|
|
@@ -134,7 +134,7 @@ describe("addToSelection", () => {
|
|
|
134
134
|
given("child1", () => given.$tree.tree("getNodeByNameMustExist", "child1"));
|
|
135
135
|
given("child2", () => given.$tree.tree("getNodeByNameMustExist", "child2"));
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
it("selects the nodes", () => {
|
|
138
138
|
given.$tree.tree({
|
|
139
139
|
autoOpen: true,
|
|
140
140
|
data: exampleData,
|
|
@@ -142,15 +142,21 @@ describe("addToSelection", () => {
|
|
|
142
142
|
|
|
143
143
|
given.$tree.tree("addToSelection", given.child1);
|
|
144
144
|
given.$tree.tree("addToSelection", given.child2);
|
|
145
|
-
});
|
|
146
145
|
|
|
147
|
-
it("selects the nodes", () => {
|
|
148
146
|
expect(given.$tree.tree("getSelectedNodes")).toEqual(
|
|
149
147
|
expect.arrayContaining([given.child1, given.child2]),
|
|
150
148
|
);
|
|
151
149
|
});
|
|
152
150
|
|
|
153
151
|
it("renders the nodes correctly", () => {
|
|
152
|
+
given.$tree.tree({
|
|
153
|
+
autoOpen: true,
|
|
154
|
+
data: exampleData,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
given.$tree.tree("addToSelection", given.child1);
|
|
158
|
+
given.$tree.tree("addToSelection", given.child2);
|
|
159
|
+
|
|
154
160
|
expect(given.$tree).toHaveTreeStructure([
|
|
155
161
|
expect.objectContaining({
|
|
156
162
|
name: "node1",
|
|
@@ -172,6 +178,20 @@ describe("addToSelection", () => {
|
|
|
172
178
|
}),
|
|
173
179
|
]);
|
|
174
180
|
});
|
|
181
|
+
|
|
182
|
+
it("opens the parent node when it's closed", () => {
|
|
183
|
+
given.$tree.tree({
|
|
184
|
+
autoOpen: false,
|
|
185
|
+
data: exampleData,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const node1 = given.$tree.tree("getNodeByNameMustExist", "node1");
|
|
189
|
+
expect(node1.is_open).toBeFalsy();
|
|
190
|
+
|
|
191
|
+
given.$tree.tree("addToSelection", given.child1);
|
|
192
|
+
|
|
193
|
+
expect(node1.is_open).toBe(true);
|
|
194
|
+
});
|
|
175
195
|
});
|
|
176
196
|
|
|
177
197
|
describe("appendNode", () => {
|
|
@@ -984,7 +1004,7 @@ describe("refresh", () => {
|
|
|
984
1004
|
|
|
985
1005
|
it("rerenders the tree", () => {
|
|
986
1006
|
const tree = given.$tree.tree("getTree");
|
|
987
|
-
(tree.children[0] as INode).name = "node1a";
|
|
1007
|
+
(tree.children[0] as INode).name = "node1a"; // eslint-disable-line testing-library/no-node-access
|
|
988
1008
|
|
|
989
1009
|
expect(given.$tree).toHaveTreeStructure([
|
|
990
1010
|
expect.objectContaining({ name: "node1" }),
|
|
@@ -1207,6 +1227,15 @@ describe("selectNode", () => {
|
|
|
1207
1227
|
expect(given.$tree.tree("getSelectedNode")).toBeFalse();
|
|
1208
1228
|
});
|
|
1209
1229
|
});
|
|
1230
|
+
|
|
1231
|
+
it("opens the parent node when it's closed", () => {
|
|
1232
|
+
expect(given.node1.is_open).toBeFalsy();
|
|
1233
|
+
|
|
1234
|
+
const child1 = given.$tree.tree("getNodeByNameMustExist", "child1");
|
|
1235
|
+
given.$tree.tree("selectNode", child1);
|
|
1236
|
+
|
|
1237
|
+
expect(given.node1.is_open).toBe(true);
|
|
1238
|
+
});
|
|
1210
1239
|
});
|
|
1211
1240
|
|
|
1212
1241
|
describe("setOption", () => {
|
|
@@ -199,19 +199,30 @@ describe("closedIcon", () => {
|
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
it("renders a html element", () => {
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
const icon = document.createElement("span");
|
|
203
|
+
icon.className = "abc";
|
|
204
|
+
icon.textContent = "test";
|
|
205
205
|
|
|
206
206
|
const $tree = $("#tree1");
|
|
207
207
|
$tree.tree({
|
|
208
|
-
closedIcon,
|
|
208
|
+
closedIcon: icon,
|
|
209
209
|
data: exampleData,
|
|
210
210
|
});
|
|
211
211
|
|
|
212
212
|
const $span = $tree.find("a.jqtree-toggler:first span.abc");
|
|
213
213
|
expect($span.text()).toBe("test");
|
|
214
214
|
});
|
|
215
|
+
|
|
216
|
+
it("renders a default when the option is empty", () => {
|
|
217
|
+
const $tree = $("#tree1");
|
|
218
|
+
$tree.tree({
|
|
219
|
+
closedIcon: undefined,
|
|
220
|
+
data: exampleData,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const $span = $tree.find("a.jqtree-toggler:first");
|
|
224
|
+
expect($span.text()).toBe("►");
|
|
225
|
+
});
|
|
215
226
|
});
|
|
216
227
|
|
|
217
228
|
describe("dataUrl", () => {
|