jqtree 1.5.2 → 1.6.2
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 +1 -0
- package/.github/workflows/ci.yml +54 -0
- package/.github/workflows/codeql-analysis.yml +28 -0
- package/README.md +1 -1
- package/_config.yml +1 -1
- package/_entries/10_changelog.md +20 -0
- package/_entries/{36_showemptynode.md → 36_showemptyfolder.md} +5 -5
- package/_entries/38_start_dnd_delay.md +13 -0
- package/_entries/{38_tabindex.md → 39_tabindex.md} +0 -0
- package/_entries/{39_usecontextmenu.md → 40_usecontextmenu.md} +0 -0
- package/_entries/{40_functions.md → 41_functions.md} +0 -0
- package/_entries/{41_addparentnode.md → 42_addparentnode.md} +0 -0
- package/_entries/{42_addnodeafter.md → 43_addnodeafter.md} +0 -0
- package/_entries/{43_addnodebefore.md → 44_addnodebefore.md} +0 -0
- package/_entries/{44_appendnode.md → 45_appendnode.md} +0 -0
- package/_entries/{45_closenode.md → 46_closenode.md} +0 -0
- package/_entries/{46_destroy.md → 47_destroy.md} +0 -0
- package/_entries/{47_getnodebycallback.md → 48_getnodebycallback.md} +0 -0
- package/_entries/{48_getnodebyid.md → 49_getnodebyid.md} +0 -0
- package/_entries/{49_getnodebyhtmlelement.md → 50_getnodebyhtmlelement.md} +0 -0
- package/_entries/{50_getselectednode.md → 51_getselectednode.md} +0 -0
- package/_entries/{51_getstate.md → 52_getstate.md} +0 -0
- package/_entries/{52_gettree.md → 53_gettree.md} +0 -0
- package/_entries/{53_isdragging.md → 54_isdragging.md} +0 -0
- package/_entries/{54_loaddata.md → 55_loaddata.md} +0 -0
- package/_entries/{55_loaddatafromurl.md → 56_loaddatafromurl.md} +0 -0
- package/_entries/{56_movedown.md → 57_movedown.md} +0 -0
- package/_entries/{57_movenode.md → 58_movenode.md} +0 -0
- package/_entries/{58_moveup.md → 59_moveup.md} +0 -0
- package/_entries/{59_opennode.md → 60_opennode.md} +0 -0
- package/_entries/{60_prependnode.md → 61_prependnode.md} +0 -0
- package/_entries/62_refresh.md +12 -0
- package/_entries/{61_reload.md → 63_reload.md} +0 -0
- package/_entries/{62_removenode.md → 64_removenode.md} +0 -0
- package/_entries/{63_selectnode.md → 65_selectnode.md} +0 -0
- package/_entries/{64_scrolltonode.md → 66_scrolltonode.md} +0 -0
- package/_entries/{65_setoption.md → 67_setoption.md} +0 -0
- package/_entries/{66_setstate.md → 68_setstate.md} +0 -0
- package/_entries/{67_toggle.md → 69_toggle.md} +0 -0
- package/_entries/{68_tojson.md → 70_tojson.md} +0 -0
- package/_entries/{69_updatenode.md → 71_updatenode.md} +0 -0
- package/_entries/{70_events.md → 72_events.md} +0 -0
- package/_entries/{71_tree-click.md → 73_tree-click.md} +0 -0
- package/_entries/{72_tree-close.md → 74_tree-close.md} +0 -0
- package/_entries/{73_tree-contextmenu.md → 75_tree-contextmenu.md} +0 -0
- package/_entries/{74_tree-dblclick.md → 76_tree-dblclick.md} +0 -0
- package/_entries/{75_tree-init.md → 77_tree-init.md} +0 -0
- package/_entries/{76_tree-load-data.md → 78_tree-load-data.md} +0 -0
- package/_entries/{77_tree-loading-data.md → 79_tree-loading-data.md} +0 -0
- package/_entries/{78_tree-move.md → 80_tree-move.md} +0 -0
- package/_entries/{79_tree-refresh.md → 81_tree-refresh.md} +0 -0
- package/_entries/{80_tree-open.md → 82_tree-open.md} +0 -0
- package/_entries/{81_tree-select.md → 83_tree-select.md} +0 -0
- package/_entries/{82_multiple-selection.md → 84_multiple-selection.md} +0 -0
- package/_entries/{83_add-to-selection.md → 85_add-to-selection.md} +0 -0
- package/_entries/{84_get-selected-nodes.md → 86_get-selected-nodes.md} +0 -0
- package/_entries/{85_is-node-selected.md → 87_is-node-selected.md} +0 -0
- package/_entries/{86_remove-from-selection.md → 88_remove-from-selection.md} +0 -0
- package/_entries/{87_node-functions.md → 89_node-functions.md} +0 -0
- package/_entries/{88_children.md → 90_children.md} +0 -0
- package/_entries/{89_getdata.md → 91_getdata.md} +0 -0
- package/_entries/{90_getlevel.md → 92_getlevel.md} +0 -0
- package/_entries/{91_getnextnode.md → 93_getnextnode.md} +0 -0
- package/_entries/{92_getnextsibling.md → 94_getnextsibling.md} +0 -0
- package/_entries/{93_getpreviousnode.md → 95_getpreviousnode.md} +0 -0
- package/_entries/{94_getprevioussibling.md → 96_getprevioussibling.md} +0 -0
- package/_entries/{95_parent.md → 97_parent.md} +0 -0
- package/_examples/13_drag_outside.html +2 -1
- package/_examples/14_filter.html +113 -0
- package/_layouts/base.html +1 -23
- package/babel.config.json +11 -0
- package/babel.coverage.config.json +4 -0
- package/bower.json +1 -1
- package/jest-browser.config.js +0 -3
- package/jest-jsdom.config.js +1 -2
- package/jqtree.css +4 -1
- package/jqtree.postcss +3 -0
- package/lib/dataLoader.js +146 -98
- package/lib/dragAndDropHandler.js +668 -470
- package/lib/elementsRenderer.js +282 -197
- package/lib/jqtreeOptions.js +1 -2
- package/lib/keyHandler.js +134 -87
- package/lib/mouse.widget.js +288 -165
- package/lib/node.js +693 -505
- package/lib/nodeElement.js +329 -205
- package/lib/playwright/playwright.test.js +216 -189
- package/lib/playwright/testUtil.js +437 -192
- package/lib/playwright/visualRegression.js +183 -117
- package/lib/saveStateHandler.js +311 -204
- package/lib/scrollHandler.js +293 -199
- package/lib/selectNodeHandler.js +140 -105
- package/lib/simple.widget.js +184 -109
- package/lib/test/global.d.js +3 -0
- package/lib/test/jqTree/create.test.js +44 -40
- package/lib/test/jqTree/events.test.js +185 -138
- package/lib/test/jqTree/keyboard.test.js +216 -199
- package/lib/test/jqTree/loadOnDemand.test.js +233 -157
- package/lib/test/jqTree/methods.test.js +1269 -1000
- package/lib/test/jqTree/options.test.js +467 -398
- package/lib/test/node.test.js +1036 -873
- package/lib/test/nodeUtil.test.js +21 -20
- package/lib/test/support/exampleData.js +35 -23
- package/lib/test/support/jqTreeMatchers.js +72 -54
- package/lib/test/support/matchers.d.js +1 -0
- package/lib/test/support/setupTests.js +9 -3
- package/lib/test/support/testUtil.js +38 -15
- package/lib/test/support/treeStructure.js +41 -32
- package/lib/test/util.test.js +21 -20
- package/lib/tree.jquery.d.js +1 -0
- package/lib/tree.jquery.js +1264 -883
- package/lib/types.js +1 -2
- package/lib/typings.d.js +2 -0
- package/lib/util.js +21 -7
- package/lib/version.js +8 -3
- package/package.json +43 -36
- package/production +4 -4
- package/rollup.config.js +16 -11
- package/src/dataLoader.ts +6 -6
- package/src/dragAndDropHandler.ts +0 -4
- package/src/elementsRenderer.ts +4 -0
- package/src/jqtreeOptions.ts +33 -32
- package/src/mouse.widget.ts +58 -29
- package/src/node.ts +32 -46
- package/src/nodeElement.ts +17 -9
- package/src/playwright/.eslintrc +5 -0
- package/src/playwright/playwright.test.ts +30 -30
- package/src/playwright/testUtil.ts +36 -37
- package/src/saveStateHandler.ts +11 -6
- package/src/selectNodeHandler.ts +14 -21
- package/src/simple.widget.ts +1 -1
- package/src/test/.eslintrc +4 -0
- package/src/test/jqTree/create.test.ts +0 -1
- package/src/test/jqTree/events.test.ts +12 -13
- package/src/test/jqTree/keyboard.test.ts +0 -1
- package/src/test/jqTree/loadOnDemand.test.ts +46 -1
- package/src/test/jqTree/methods.test.ts +67 -18
- package/src/test/jqTree/options.test.ts +5 -6
- package/src/test/node.test.ts +2 -2
- package/src/test/support/jqTreeMatchers.ts +8 -9
- package/src/test/support/matchers.d.ts +2 -4
- package/src/test/support/setupTests.ts +2 -1
- package/src/tree.jquery.d.ts +19 -13
- package/src/tree.jquery.ts +63 -57
- package/src/version.ts +1 -1
- package/static/bower.json +3 -3
- package/static/bower_components/fontawesome/css/all.min.css +2 -2
- package/static/bower_components/fontawesome/webfonts/fa-brands-400.eot +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-brands-400.svg +774 -627
- package/static/bower_components/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-brands-400.woff +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-regular-400.eot +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-regular-400.svg +93 -95
- package/static/bower_components/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-regular-400.woff +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-solid-900.eot +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-solid-900.svg +1164 -1074
- package/static/bower_components/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-solid-900.woff +0 -0
- package/static/bower_components/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- package/static/bower_components/jquery/dist/jquery.js +118 -109
- package/static/bower_components/jquery/dist/jquery.min.js +2 -2
- package/static/bower_components/jquery-mockjax/dist/jquery.mockjax.js +15 -9
- package/static/example.css +13 -0
- package/static/example.postcss +13 -0
- package/static/example_data.js +33 -36
- package/static/examples/filter.js +63 -0
- package/tree.jquery.debug.js +4809 -3305
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +3 -3
- package/tree.jquery.js.map +1 -1
- package/tsconfig.json +1 -0
- package/.travis.yml +0 -18
package/src/node.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export type NodeData = string | DefaultRecord;
|
|
1
|
+
interface NodeRecordWithChildren extends NodeRecord {
|
|
2
|
+
children: NodeData[];
|
|
3
|
+
}
|
|
5
4
|
|
|
6
5
|
export enum Position {
|
|
7
6
|
Before = 1,
|
|
@@ -34,12 +33,19 @@ export const getPositionName = (position: Position): string => {
|
|
|
34
33
|
export const getPosition = (name: string): Position | undefined =>
|
|
35
34
|
positionNames[name];
|
|
36
35
|
|
|
36
|
+
const isNodeRecordWithChildren = (
|
|
37
|
+
data: NodeData
|
|
38
|
+
): data is NodeRecordWithChildren =>
|
|
39
|
+
typeof data === "object" &&
|
|
40
|
+
"children" in data &&
|
|
41
|
+
data["children"] instanceof Array;
|
|
42
|
+
|
|
37
43
|
export class Node implements INode {
|
|
38
44
|
public id?: NodeId;
|
|
39
45
|
public name: string;
|
|
40
46
|
public children: Node[];
|
|
41
47
|
public parent: Node | null;
|
|
42
|
-
public idMapping:
|
|
48
|
+
public idMapping: Map<NodeId, Node>;
|
|
43
49
|
public tree?: Node;
|
|
44
50
|
public nodeClass?: typeof Node;
|
|
45
51
|
public load_on_demand: boolean;
|
|
@@ -61,7 +67,7 @@ export class Node implements INode {
|
|
|
61
67
|
this.parent = null;
|
|
62
68
|
|
|
63
69
|
if (isRoot) {
|
|
64
|
-
this.idMapping =
|
|
70
|
+
this.idMapping = new Map<NodeId, Node>();
|
|
65
71
|
this.tree = this;
|
|
66
72
|
this.nodeClass = nodeClass;
|
|
67
73
|
}
|
|
@@ -131,15 +137,11 @@ export class Node implements INode {
|
|
|
131
137
|
const node = this.createNode(o);
|
|
132
138
|
this.addChild(node);
|
|
133
139
|
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
o["children"] &&
|
|
137
|
-
o["children"] instanceof Array
|
|
138
|
-
) {
|
|
139
|
-
if (o["children"].length === 0) {
|
|
140
|
+
if (isNodeRecordWithChildren(o)) {
|
|
141
|
+
if (o.children.length === 0) {
|
|
140
142
|
node.isEmptyFolder = true;
|
|
141
143
|
} else {
|
|
142
|
-
node.loadFromData(o
|
|
144
|
+
node.loadFromData(o.children);
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
}
|
|
@@ -299,7 +301,7 @@ export class Node implements INode {
|
|
|
299
301
|
/*
|
|
300
302
|
Get the tree as data.
|
|
301
303
|
*/
|
|
302
|
-
public getData(includeParent = false):
|
|
304
|
+
public getData(includeParent = false): NodeRecord[] {
|
|
303
305
|
const getDataFromNodes = (nodes: Node[]): Record<string, unknown>[] => {
|
|
304
306
|
return nodes.map((node) => {
|
|
305
307
|
const tmpNode: Record<string, unknown> = {};
|
|
@@ -379,12 +381,10 @@ export class Node implements INode {
|
|
|
379
381
|
this.parent.addChildAtPosition(node, childIndex + 1);
|
|
380
382
|
|
|
381
383
|
if (
|
|
382
|
-
|
|
383
|
-
nodeInfo
|
|
384
|
-
nodeInfo["children"] instanceof Array &&
|
|
385
|
-
nodeInfo["children"].length
|
|
384
|
+
isNodeRecordWithChildren(nodeInfo) &&
|
|
385
|
+
nodeInfo.children.length
|
|
386
386
|
) {
|
|
387
|
-
node.loadFromData(nodeInfo
|
|
387
|
+
node.loadFromData(nodeInfo.children);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
return node;
|
|
@@ -401,12 +401,10 @@ export class Node implements INode {
|
|
|
401
401
|
this.parent.addChildAtPosition(node, childIndex);
|
|
402
402
|
|
|
403
403
|
if (
|
|
404
|
-
|
|
405
|
-
nodeInfo
|
|
406
|
-
nodeInfo["children"] instanceof Array &&
|
|
407
|
-
nodeInfo["children"].length
|
|
404
|
+
isNodeRecordWithChildren(nodeInfo) &&
|
|
405
|
+
nodeInfo.children.length
|
|
408
406
|
) {
|
|
409
|
-
node.loadFromData(nodeInfo
|
|
407
|
+
node.loadFromData(nodeInfo.children);
|
|
410
408
|
}
|
|
411
409
|
|
|
412
410
|
return node;
|
|
@@ -445,13 +443,8 @@ export class Node implements INode {
|
|
|
445
443
|
const node = this.createNode(nodeInfo);
|
|
446
444
|
this.addChild(node);
|
|
447
445
|
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
nodeInfo["children"] &&
|
|
451
|
-
nodeInfo["children"] instanceof Array &&
|
|
452
|
-
nodeInfo["children"].length
|
|
453
|
-
) {
|
|
454
|
-
node.loadFromData(nodeInfo["children"]);
|
|
446
|
+
if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
|
|
447
|
+
node.loadFromData(nodeInfo.children);
|
|
455
448
|
}
|
|
456
449
|
|
|
457
450
|
return node;
|
|
@@ -461,13 +454,8 @@ export class Node implements INode {
|
|
|
461
454
|
const node = this.createNode(nodeInfo);
|
|
462
455
|
this.addChildAtPosition(node, 0);
|
|
463
456
|
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
nodeInfo["children"] &&
|
|
467
|
-
nodeInfo["children"] instanceof Array &&
|
|
468
|
-
nodeInfo["children"].length
|
|
469
|
-
) {
|
|
470
|
-
node.loadFromData(nodeInfo["children"]);
|
|
457
|
+
if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
|
|
458
|
+
node.loadFromData(nodeInfo.children);
|
|
471
459
|
}
|
|
472
460
|
|
|
473
461
|
return node;
|
|
@@ -500,18 +488,18 @@ export class Node implements INode {
|
|
|
500
488
|
}
|
|
501
489
|
|
|
502
490
|
public getNodeById(nodeId: NodeId): Node | null {
|
|
503
|
-
return this.idMapping
|
|
491
|
+
return this.idMapping.get(nodeId) || null;
|
|
504
492
|
}
|
|
505
493
|
|
|
506
494
|
public addNodeToIndex(node: Node): void {
|
|
507
495
|
if (node.id != null) {
|
|
508
|
-
this.idMapping
|
|
496
|
+
this.idMapping.set(node.id, node);
|
|
509
497
|
}
|
|
510
498
|
}
|
|
511
499
|
|
|
512
500
|
public removeNodeFromIndex(node: Node): void {
|
|
513
501
|
if (node.id != null) {
|
|
514
|
-
|
|
502
|
+
this.idMapping.delete(node.id);
|
|
515
503
|
}
|
|
516
504
|
}
|
|
517
505
|
|
|
@@ -641,12 +629,10 @@ export class Node implements INode {
|
|
|
641
629
|
this.setData(nodeData);
|
|
642
630
|
|
|
643
631
|
if (
|
|
644
|
-
|
|
645
|
-
nodeData
|
|
646
|
-
nodeData["children"] instanceof Array &&
|
|
647
|
-
nodeData["children"].length
|
|
632
|
+
isNodeRecordWithChildren(nodeData) &&
|
|
633
|
+
nodeData.children.length
|
|
648
634
|
) {
|
|
649
|
-
addChildren(nodeData
|
|
635
|
+
addChildren(nodeData.children);
|
|
650
636
|
}
|
|
651
637
|
};
|
|
652
638
|
|
package/src/nodeElement.ts
CHANGED
|
@@ -18,10 +18,16 @@ export class NodeElement {
|
|
|
18
18
|
this.treeWidget = treeWidget;
|
|
19
19
|
|
|
20
20
|
if (!node.element) {
|
|
21
|
-
|
|
21
|
+
const element = this.treeWidget.element.get(0);
|
|
22
|
+
|
|
23
|
+
if (element) {
|
|
24
|
+
node.element = element;
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
if (node.element) {
|
|
29
|
+
this.$element = jQuery(node.element);
|
|
30
|
+
}
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
public addDropHint(position: number): DropHint {
|
|
@@ -99,9 +105,8 @@ export class FolderElement extends NodeElement {
|
|
|
99
105
|
const buttonEl = $button.get(0);
|
|
100
106
|
|
|
101
107
|
if (buttonEl) {
|
|
102
|
-
const icon =
|
|
103
|
-
true
|
|
104
|
-
);
|
|
108
|
+
const icon =
|
|
109
|
+
this.treeWidget.renderer.openedIconElement.cloneNode(true);
|
|
105
110
|
|
|
106
111
|
buttonEl.appendChild(icon);
|
|
107
112
|
}
|
|
@@ -147,9 +152,8 @@ export class FolderElement extends NodeElement {
|
|
|
147
152
|
const buttonEl = $button.get(0);
|
|
148
153
|
|
|
149
154
|
if (buttonEl) {
|
|
150
|
-
const icon =
|
|
151
|
-
true
|
|
152
|
-
);
|
|
155
|
+
const icon =
|
|
156
|
+
this.treeWidget.renderer.closedIconElement.cloneNode(true);
|
|
153
157
|
|
|
154
158
|
buttonEl.appendChild(icon);
|
|
155
159
|
}
|
|
@@ -248,7 +252,11 @@ class GhostDropHint implements DropHint {
|
|
|
248
252
|
}
|
|
249
253
|
|
|
250
254
|
public moveInsideOpenFolder(): void {
|
|
251
|
-
|
|
255
|
+
const childElement = this.node.children[0].element;
|
|
256
|
+
|
|
257
|
+
if (childElement) {
|
|
258
|
+
jQuery(childElement).before(this.$ghost);
|
|
259
|
+
}
|
|
252
260
|
}
|
|
253
261
|
|
|
254
262
|
public moveInside(): void {
|
|
@@ -41,8 +41,8 @@ beforeEach(async () => {
|
|
|
41
41
|
autoOpen: 0,
|
|
42
42
|
data: ExampleData.exampleData,
|
|
43
43
|
dragAndDrop: ${given.dragAndDrop},
|
|
44
|
+
startDndDelay: 100,
|
|
44
45
|
});
|
|
45
|
-
$tree.tree("setMouseDelay", 100);
|
|
46
46
|
`);
|
|
47
47
|
});
|
|
48
48
|
|
|
@@ -51,15 +51,15 @@ afterEach(async () => {
|
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
it("displays a tree", async () => {
|
|
54
|
-
await expect(page).
|
|
55
|
-
await expect(page).
|
|
56
|
-
await expect(page).
|
|
54
|
+
await expect(page).toMatchText(/.*Saurischia.*/);
|
|
55
|
+
await expect(page).toMatchText(/.*Ornithischians.*/);
|
|
56
|
+
await expect(page).toMatchText(/.*Coelophysoids.*/);
|
|
57
57
|
|
|
58
58
|
await matchScreenshot("displays_a_tree");
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
it("selects a node", async () => {
|
|
62
|
-
await expect(page).
|
|
62
|
+
await expect(page).toMatchText(/.*Saurischia.*/);
|
|
63
63
|
const saurischia = await findNodeElement("Saurischia");
|
|
64
64
|
await selectNode(saurischia);
|
|
65
65
|
await expectToBeSelected(saurischia);
|
|
@@ -68,7 +68,7 @@ it("selects a node", async () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it("opens a node", async () => {
|
|
71
|
-
await expect(page).
|
|
71
|
+
await expect(page).toMatchText(/.*Saurischia.*/);
|
|
72
72
|
|
|
73
73
|
const theropods = await findNodeElement("Theropods");
|
|
74
74
|
await expectToBeClosed(theropods);
|
|
@@ -84,30 +84,30 @@ describe("dragAndDrop", () => {
|
|
|
84
84
|
it("moves a node", async () => {
|
|
85
85
|
await dragAndDrop("Herrerasaurians", "Ornithischians");
|
|
86
86
|
|
|
87
|
-
await getTreeStructure()
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
87
|
+
const structure = await getTreeStructure();
|
|
88
|
+
|
|
89
|
+
expect(structure).toEqual([
|
|
90
|
+
expect.objectContaining({
|
|
91
|
+
name: "Saurischia",
|
|
92
|
+
children: [
|
|
93
|
+
expect.objectContaining({ name: "Theropods" }),
|
|
94
|
+
expect.objectContaining({ name: "Sauropodomorphs" }),
|
|
95
|
+
],
|
|
96
|
+
}),
|
|
97
|
+
expect.objectContaining({
|
|
98
|
+
name: "Ornithischians",
|
|
99
|
+
children: [
|
|
100
|
+
expect.objectContaining({ name: "Herrerasaurians" }),
|
|
101
|
+
expect.objectContaining({ name: "Heterodontosaurids" }),
|
|
102
|
+
expect.objectContaining({ name: "Thyreophorans" }),
|
|
103
|
+
expect.objectContaining({ name: "Ornithopods" }),
|
|
104
|
+
expect.objectContaining({
|
|
105
|
+
name: "Pachycephalosaurians",
|
|
106
|
+
}),
|
|
107
|
+
expect.objectContaining({ name: "Ceratopsians" }),
|
|
108
|
+
],
|
|
109
|
+
}),
|
|
110
|
+
]);
|
|
111
111
|
|
|
112
112
|
await matchScreenshot("moves_a_node");
|
|
113
113
|
});
|
|
@@ -96,47 +96,46 @@ export const selectNode = async (
|
|
|
96
96
|
await titleHandle?.click();
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
export const getTreeStructure = async (): Promise<
|
|
100
|
-
JQTreeMatchers.TreeStructure
|
|
101
|
-
> =>
|
|
99
|
+
export const getTreeStructure = async (): Promise<JQTreeMatchers.TreeStructure> =>
|
|
102
100
|
await page
|
|
103
101
|
.evaluate(
|
|
104
102
|
`
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
103
|
+
;
|
|
104
|
+
function getTreeNode($li) {
|
|
105
|
+
const $div = $li.children("div.jqtree-element");
|
|
106
|
+
const $span = $div.children("span.jqtree-title");
|
|
107
|
+
const name = $span.text();
|
|
108
|
+
const selected = $li.hasClass("jqtree-selected");
|
|
109
|
+
|
|
110
|
+
if ($li.hasClass("jqtree-folder")) {
|
|
111
|
+
const $ul = $li.children("ul.jqtree_common");
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
nodeType: "folder",
|
|
115
|
+
children: getChildren($ul),
|
|
116
|
+
name,
|
|
117
|
+
open: !$li.hasClass("jqtree-closed"),
|
|
118
|
+
selected,
|
|
119
|
+
};
|
|
120
|
+
} else {
|
|
121
|
+
return {
|
|
122
|
+
nodeType: "child",
|
|
123
|
+
name,
|
|
124
|
+
selected,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
127
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
JSON.stringify(window.getChildren(jQuery("ul.jqtree-tree")))
|
|
128
|
+
|
|
129
|
+
function getChildren($ul) {
|
|
130
|
+
return $ul
|
|
131
|
+
.children("li.jqtree_common")
|
|
132
|
+
.map((_, li) => {
|
|
133
|
+
return getTreeNode(jQuery(li));
|
|
134
|
+
})
|
|
135
|
+
.get();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
JSON.stringify(window.getChildren(jQuery("ul.jqtree-tree")));
|
|
140
139
|
`
|
|
141
140
|
)
|
|
142
141
|
.then((s) => JSON.parse(s as string) as JQTreeMatchers.TreeStructure);
|
package/src/saveStateHandler.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { isInt } from "./util";
|
|
2
2
|
import { JqTreeWidget } from "./tree.jquery";
|
|
3
|
-
import { Node
|
|
3
|
+
import { Node } from "./node";
|
|
4
|
+
|
|
5
|
+
export interface SavedState {
|
|
6
|
+
open_nodes: NodeId[];
|
|
7
|
+
selected_node: NodeId[];
|
|
8
|
+
}
|
|
4
9
|
|
|
5
10
|
export default class SaveStateHandler {
|
|
6
11
|
private treeWidget: JqTreeWidget;
|
|
@@ -24,7 +29,7 @@ export default class SaveStateHandler {
|
|
|
24
29
|
const jsonData = this.loadFromStorage();
|
|
25
30
|
|
|
26
31
|
if (jsonData) {
|
|
27
|
-
return
|
|
32
|
+
return this.parseState(jsonData) as unknown as SavedState;
|
|
28
33
|
} else {
|
|
29
34
|
return null;
|
|
30
35
|
}
|
|
@@ -121,7 +126,7 @@ export default class SaveStateHandler {
|
|
|
121
126
|
state.selected_node = [state.selected_node];
|
|
122
127
|
}
|
|
123
128
|
|
|
124
|
-
return
|
|
129
|
+
return state as unknown as SavedState;
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
private loadFromStorage(): string | null {
|
|
@@ -134,11 +139,11 @@ export default class SaveStateHandler {
|
|
|
134
139
|
}
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
private openInitialNodes(nodeIds:
|
|
142
|
+
private openInitialNodes(nodeIds: NodeId[]): boolean {
|
|
138
143
|
let mustLoadOnDemand = false;
|
|
139
144
|
|
|
140
|
-
for (const
|
|
141
|
-
const node = this.treeWidget.getNodeById(
|
|
145
|
+
for (const nodeId of nodeIds) {
|
|
146
|
+
const node = this.treeWidget.getNodeById(nodeId);
|
|
142
147
|
|
|
143
148
|
if (node) {
|
|
144
149
|
if (!node.load_on_demand) {
|
package/src/selectNodeHandler.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { Node
|
|
1
|
+
import { Node } from "./node";
|
|
2
2
|
import { JqTreeWidget } from "./tree.jquery";
|
|
3
3
|
|
|
4
4
|
export default class SelectNodeHandler {
|
|
5
5
|
private treeWidget: JqTreeWidget;
|
|
6
|
-
private selectedNodes:
|
|
6
|
+
private selectedNodes: Set<NodeId>;
|
|
7
7
|
private selectedSingleNode: Node | null;
|
|
8
8
|
|
|
9
9
|
constructor(treeWidget: JqTreeWidget) {
|
|
10
10
|
this.treeWidget = treeWidget;
|
|
11
|
+
this.selectedNodes = new Set<NodeId>();
|
|
11
12
|
this.clear();
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -25,18 +26,14 @@ export default class SelectNodeHandler {
|
|
|
25
26
|
if (this.selectedSingleNode) {
|
|
26
27
|
return [this.selectedSingleNode];
|
|
27
28
|
} else {
|
|
28
|
-
const selectedNodes = [];
|
|
29
|
+
const selectedNodes: Node[] = [];
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const node = this.treeWidget.getNodeById(id);
|
|
35
|
-
if (node) {
|
|
36
|
-
selectedNodes.push(node);
|
|
37
|
-
}
|
|
31
|
+
this.selectedNodes.forEach((id) => {
|
|
32
|
+
const node = this.treeWidget.getNodeById(id);
|
|
33
|
+
if (node) {
|
|
34
|
+
selectedNodes.push(node);
|
|
38
35
|
}
|
|
39
|
-
}
|
|
36
|
+
});
|
|
40
37
|
|
|
41
38
|
return selectedNodes;
|
|
42
39
|
}
|
|
@@ -69,11 +66,7 @@ export default class SelectNodeHandler {
|
|
|
69
66
|
|
|
70
67
|
public isNodeSelected(node: Node): boolean {
|
|
71
68
|
if (node.id != null) {
|
|
72
|
-
|
|
73
|
-
return true;
|
|
74
|
-
} else {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
69
|
+
return this.selectedNodes.has(node.id);
|
|
77
70
|
} else if (this.selectedSingleNode) {
|
|
78
71
|
return this.selectedSingleNode.element === node.element;
|
|
79
72
|
} else {
|
|
@@ -82,7 +75,7 @@ export default class SelectNodeHandler {
|
|
|
82
75
|
}
|
|
83
76
|
|
|
84
77
|
public clear(): void {
|
|
85
|
-
this.selectedNodes
|
|
78
|
+
this.selectedNodes.clear();
|
|
86
79
|
this.selectedSingleNode = null;
|
|
87
80
|
}
|
|
88
81
|
|
|
@@ -95,12 +88,12 @@ export default class SelectNodeHandler {
|
|
|
95
88
|
this.selectedSingleNode = null;
|
|
96
89
|
}
|
|
97
90
|
} else {
|
|
98
|
-
|
|
91
|
+
this.selectedNodes.delete(node.id);
|
|
99
92
|
|
|
100
93
|
if (includeChildren) {
|
|
101
94
|
node.iterate(() => {
|
|
102
95
|
if (node.id != null) {
|
|
103
|
-
|
|
96
|
+
this.selectedNodes.delete(node.id);
|
|
104
97
|
}
|
|
105
98
|
return true;
|
|
106
99
|
});
|
|
@@ -110,7 +103,7 @@ export default class SelectNodeHandler {
|
|
|
110
103
|
|
|
111
104
|
public addToSelection(node: Node): void {
|
|
112
105
|
if (node.id != null) {
|
|
113
|
-
this.selectedNodes
|
|
106
|
+
this.selectedNodes.add(node.id);
|
|
114
107
|
} else {
|
|
115
108
|
this.selectedSingleNode = node;
|
|
116
109
|
}
|
package/src/simple.widget.ts
CHANGED
|
@@ -109,7 +109,7 @@ export default class SimpleWidget<WidgetOptions> {
|
|
|
109
109
|
|
|
110
110
|
public options: WidgetOptions;
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
public $el: JQuery<HTMLElement>;
|
|
113
113
|
|
|
114
114
|
constructor(el: HTMLElement, options: WidgetOptions) {
|
|
115
115
|
this.$el = jQuery(el);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as $ from "jquery";
|
|
2
1
|
import getGiven from "givens";
|
|
3
2
|
import { rest } from "msw";
|
|
4
3
|
import { setupServer } from "msw/node";
|
|
@@ -35,7 +34,7 @@ describe("tree.click", () => {
|
|
|
35
34
|
});
|
|
36
35
|
|
|
37
36
|
it("fires tree.click", () =>
|
|
38
|
-
new Promise((done) => {
|
|
37
|
+
new Promise<void>((done) => {
|
|
39
38
|
given.$tree.on("tree.click", (e: unknown) => {
|
|
40
39
|
const treeClickEvent = e as ClickNodeEvent;
|
|
41
40
|
|
|
@@ -43,7 +42,7 @@ describe("tree.click", () => {
|
|
|
43
42
|
done();
|
|
44
43
|
});
|
|
45
44
|
|
|
46
|
-
given.titleSpan.click
|
|
45
|
+
given.titleSpan.trigger("click");
|
|
47
46
|
}));
|
|
48
47
|
});
|
|
49
48
|
|
|
@@ -64,7 +63,7 @@ describe("tree.contextmenu", () => {
|
|
|
64
63
|
});
|
|
65
64
|
|
|
66
65
|
it("fires tree.contextmenu", () =>
|
|
67
|
-
new Promise((done) => {
|
|
66
|
+
new Promise<void>((done) => {
|
|
68
67
|
given.$tree.on("tree.contextmenu", (e: unknown) => {
|
|
69
68
|
const treeClickEvent = e as ClickNodeEvent;
|
|
70
69
|
|
|
@@ -93,7 +92,7 @@ describe("tree.dblclick", () => {
|
|
|
93
92
|
});
|
|
94
93
|
|
|
95
94
|
it("fires tree.dblclick", () =>
|
|
96
|
-
new Promise((done) => {
|
|
95
|
+
new Promise<void>((done) => {
|
|
97
96
|
given.$tree.on("tree.dblclick", (e: unknown) => {
|
|
98
97
|
const treeClickEvent = e as ClickNodeEvent;
|
|
99
98
|
|
|
@@ -101,7 +100,7 @@ describe("tree.dblclick", () => {
|
|
|
101
100
|
done();
|
|
102
101
|
});
|
|
103
102
|
|
|
104
|
-
given.titleSpan.dblclick
|
|
103
|
+
given.titleSpan.trigger("dblclick");
|
|
105
104
|
}));
|
|
106
105
|
});
|
|
107
106
|
|
|
@@ -114,7 +113,7 @@ describe("tree.init", () => {
|
|
|
114
113
|
|
|
115
114
|
context("with json data", () => {
|
|
116
115
|
it("is called", () =>
|
|
117
|
-
new Promise((done) => {
|
|
116
|
+
new Promise<void>((done) => {
|
|
118
117
|
given.$tree.on("tree.init", () => {
|
|
119
118
|
expect(
|
|
120
119
|
given.$tree.tree("getNodeByName", "node2")
|
|
@@ -148,7 +147,7 @@ describe("tree.init", () => {
|
|
|
148
147
|
});
|
|
149
148
|
|
|
150
149
|
it("is called", () =>
|
|
151
|
-
new Promise((done) => {
|
|
150
|
+
new Promise<void>((done) => {
|
|
152
151
|
given.$tree.on("tree.init", () => {
|
|
153
152
|
expect(
|
|
154
153
|
given.$tree.tree("getNodeByName", "node2")
|
|
@@ -173,7 +172,7 @@ describe("tree.load_data", () => {
|
|
|
173
172
|
|
|
174
173
|
context("when the tree is initialized with data", () => {
|
|
175
174
|
it("fires tree.load_data", () =>
|
|
176
|
-
new Promise((resolve) => {
|
|
175
|
+
new Promise<void>((resolve) => {
|
|
177
176
|
given.$tree.on("tree.load_data", (e: any) => {
|
|
178
177
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
179
178
|
expect(e.tree_data).toEqual(exampleData);
|
|
@@ -204,7 +203,7 @@ describe("tree.select", () => {
|
|
|
204
203
|
});
|
|
205
204
|
|
|
206
205
|
it("fires tree.click", () =>
|
|
207
|
-
new Promise((done) => {
|
|
206
|
+
new Promise<void>((done) => {
|
|
208
207
|
given.$tree.on("tree.select", (e: unknown) => {
|
|
209
208
|
const treeClickEvent = e as ClickNodeEvent;
|
|
210
209
|
|
|
@@ -213,7 +212,7 @@ describe("tree.select", () => {
|
|
|
213
212
|
done();
|
|
214
213
|
});
|
|
215
214
|
|
|
216
|
-
given.titleSpan.click
|
|
215
|
+
given.titleSpan.trigger("click");
|
|
217
216
|
}));
|
|
218
217
|
|
|
219
218
|
context("when the node was selected", () => {
|
|
@@ -222,7 +221,7 @@ describe("tree.select", () => {
|
|
|
222
221
|
});
|
|
223
222
|
|
|
224
223
|
it("fires tree.select with node is null", () =>
|
|
225
|
-
new Promise((done) => {
|
|
224
|
+
new Promise<void>((done) => {
|
|
226
225
|
given.$tree.on("tree.select", (e: unknown) => {
|
|
227
226
|
const treeClickEvent = e as ClickNodeEvent;
|
|
228
227
|
|
|
@@ -231,7 +230,7 @@ describe("tree.select", () => {
|
|
|
231
230
|
done();
|
|
232
231
|
});
|
|
233
232
|
|
|
234
|
-
given.titleSpan.click
|
|
233
|
+
given.titleSpan.trigger("click");
|
|
235
234
|
}));
|
|
236
235
|
});
|
|
237
236
|
});
|