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
package/src/elementsRenderer.ts
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
1
|
import { getBoolString } from "./util";
|
|
2
2
|
import { Node } from "./node";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { IconElement, OnCreateLi } from "./jqtreeOptions";
|
|
4
|
+
import { GetTree, IsNodeSelected } from "./jqtreeMethodTypes";
|
|
5
|
+
|
|
6
|
+
interface ElementsRendererParams {
|
|
7
|
+
autoEscape: boolean;
|
|
8
|
+
buttonLeft: boolean;
|
|
9
|
+
closedIcon?: IconElement;
|
|
10
|
+
dragAndDrop: boolean;
|
|
11
|
+
$element: JQuery<HTMLElement>;
|
|
12
|
+
getTree: GetTree;
|
|
13
|
+
isNodeSelected: IsNodeSelected;
|
|
14
|
+
onCreateLi?: OnCreateLi;
|
|
15
|
+
openedIcon?: IconElement;
|
|
16
|
+
rtl?: boolean;
|
|
17
|
+
showEmptyFolder: boolean;
|
|
18
|
+
tabIndex?: number;
|
|
19
|
+
}
|
|
6
20
|
|
|
7
21
|
export default class ElementsRenderer {
|
|
8
22
|
public openedIconElement?: HTMLElement | Text;
|
|
9
23
|
public closedIconElement?: HTMLElement | Text;
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
private autoEscape: boolean;
|
|
25
|
+
private buttonLeft: boolean;
|
|
26
|
+
private dragAndDrop: boolean;
|
|
27
|
+
private $element: JQuery<HTMLElement>;
|
|
28
|
+
private getTree: GetTree;
|
|
29
|
+
private isNodeSelected: IsNodeSelected;
|
|
30
|
+
private onCreateLi?: OnCreateLi;
|
|
31
|
+
private rtl?: boolean;
|
|
32
|
+
private showEmptyFolder: boolean;
|
|
33
|
+
private tabIndex?: number;
|
|
34
|
+
|
|
35
|
+
constructor({
|
|
36
|
+
autoEscape,
|
|
37
|
+
buttonLeft,
|
|
38
|
+
closedIcon,
|
|
39
|
+
onCreateLi,
|
|
40
|
+
dragAndDrop,
|
|
41
|
+
$element,
|
|
42
|
+
getTree,
|
|
43
|
+
isNodeSelected,
|
|
44
|
+
openedIcon,
|
|
45
|
+
rtl,
|
|
46
|
+
showEmptyFolder,
|
|
47
|
+
tabIndex,
|
|
48
|
+
}: ElementsRendererParams) {
|
|
49
|
+
this.autoEscape = autoEscape;
|
|
50
|
+
this.buttonLeft = buttonLeft;
|
|
51
|
+
this.dragAndDrop = dragAndDrop;
|
|
52
|
+
this.$element = $element;
|
|
53
|
+
this.getTree = getTree;
|
|
54
|
+
this.isNodeSelected = isNodeSelected;
|
|
55
|
+
this.onCreateLi = onCreateLi;
|
|
56
|
+
this.rtl = rtl;
|
|
57
|
+
this.showEmptyFolder = showEmptyFolder;
|
|
58
|
+
this.tabIndex = tabIndex;
|
|
59
|
+
this.openedIconElement = this.createButtonElement(openedIcon || "+");
|
|
60
|
+
this.closedIconElement = this.createButtonElement(closedIcon || "-");
|
|
21
61
|
}
|
|
22
62
|
|
|
23
63
|
public render(fromNode: Node | null): void {
|
|
@@ -29,16 +69,12 @@ export default class ElementsRenderer {
|
|
|
29
69
|
}
|
|
30
70
|
|
|
31
71
|
public renderFromRoot(): void {
|
|
32
|
-
|
|
33
|
-
$element.empty();
|
|
72
|
+
this.$element.empty();
|
|
34
73
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
true,
|
|
40
|
-
1,
|
|
41
|
-
);
|
|
74
|
+
const tree = this.getTree();
|
|
75
|
+
|
|
76
|
+
if (this.$element[0] && tree) {
|
|
77
|
+
this.createDomElements(this.$element[0], tree.children, true, 1);
|
|
42
78
|
}
|
|
43
79
|
}
|
|
44
80
|
|
|
@@ -104,12 +140,12 @@ export default class ElementsRenderer {
|
|
|
104
140
|
classString = "jqtree-tree";
|
|
105
141
|
role = "tree";
|
|
106
142
|
|
|
107
|
-
if (this.
|
|
143
|
+
if (this.rtl) {
|
|
108
144
|
classString += " jqtree-rtl";
|
|
109
145
|
}
|
|
110
146
|
}
|
|
111
147
|
|
|
112
|
-
if (this.
|
|
148
|
+
if (this.dragAndDrop) {
|
|
113
149
|
classString += " jqtree-dnd";
|
|
114
150
|
}
|
|
115
151
|
|
|
@@ -122,20 +158,17 @@ export default class ElementsRenderer {
|
|
|
122
158
|
}
|
|
123
159
|
|
|
124
160
|
private createLi(node: Node, level: number): HTMLLIElement {
|
|
125
|
-
const isSelected = Boolean(
|
|
126
|
-
this.treeWidget.selectNodeHandler.isNodeSelected(node),
|
|
127
|
-
);
|
|
161
|
+
const isSelected = Boolean(this.isNodeSelected(node));
|
|
128
162
|
|
|
129
163
|
const mustShowFolder =
|
|
130
|
-
node.isFolder() ||
|
|
131
|
-
(node.isEmptyFolder && this.treeWidget.options.showEmptyFolder);
|
|
164
|
+
node.isFolder() || (node.isEmptyFolder && this.showEmptyFolder);
|
|
132
165
|
|
|
133
166
|
const li = mustShowFolder
|
|
134
167
|
? this.createFolderLi(node, level, isSelected)
|
|
135
168
|
: this.createNodeLi(node, level, isSelected);
|
|
136
169
|
|
|
137
|
-
if (this.
|
|
138
|
-
this.
|
|
170
|
+
if (this.onCreateLi) {
|
|
171
|
+
this.onCreateLi(node, jQuery(li), isSelected);
|
|
139
172
|
}
|
|
140
173
|
|
|
141
174
|
return li;
|
|
@@ -185,7 +218,7 @@ export default class ElementsRenderer {
|
|
|
185
218
|
buttonLink.appendChild(iconElement.cloneNode(true));
|
|
186
219
|
}
|
|
187
220
|
|
|
188
|
-
if (this.
|
|
221
|
+
if (this.buttonLeft) {
|
|
189
222
|
div.appendChild(buttonLink);
|
|
190
223
|
}
|
|
191
224
|
|
|
@@ -199,7 +232,7 @@ export default class ElementsRenderer {
|
|
|
199
232
|
titleSpan.setAttribute("aria-expanded", getBoolString(node.is_open));
|
|
200
233
|
div.appendChild(titleSpan);
|
|
201
234
|
|
|
202
|
-
if (!this.
|
|
235
|
+
if (!this.buttonLeft) {
|
|
203
236
|
div.appendChild(buttonLink);
|
|
204
237
|
}
|
|
205
238
|
|
|
@@ -257,14 +290,12 @@ export default class ElementsRenderer {
|
|
|
257
290
|
classes += " jqtree-title-folder";
|
|
258
291
|
}
|
|
259
292
|
|
|
260
|
-
classes += ` jqtree-title-button-${
|
|
261
|
-
this.treeWidget.options.buttonLeft ? "left" : "right"
|
|
262
|
-
}`;
|
|
293
|
+
classes += ` jqtree-title-button-${this.buttonLeft ? "left" : "right"}`;
|
|
263
294
|
|
|
264
295
|
titleSpan.className = classes;
|
|
265
296
|
|
|
266
297
|
if (isSelected) {
|
|
267
|
-
const tabIndex = this.
|
|
298
|
+
const tabIndex = this.tabIndex;
|
|
268
299
|
|
|
269
300
|
if (tabIndex !== undefined) {
|
|
270
301
|
titleSpan.setAttribute("tabindex", `${tabIndex}`);
|
|
@@ -273,7 +304,7 @@ export default class ElementsRenderer {
|
|
|
273
304
|
|
|
274
305
|
this.setTreeItemAriaAttributes(titleSpan, nodeName, level, isSelected);
|
|
275
306
|
|
|
276
|
-
if (this.
|
|
307
|
+
if (this.autoEscape) {
|
|
277
308
|
titleSpan.textContent = nodeName;
|
|
278
309
|
} else {
|
|
279
310
|
titleSpan.innerHTML = nodeName;
|
|
@@ -289,7 +320,7 @@ export default class ElementsRenderer {
|
|
|
289
320
|
classes.push("jqtree-closed");
|
|
290
321
|
}
|
|
291
322
|
|
|
292
|
-
if (this.
|
|
323
|
+
if (this.buttonLeft) {
|
|
293
324
|
classes.push("jqtree-toggler-left");
|
|
294
325
|
} else {
|
|
295
326
|
classes.push("jqtree-toggler-right");
|
|
@@ -325,6 +356,10 @@ export default class ElementsRenderer {
|
|
|
325
356
|
div.innerHTML = value;
|
|
326
357
|
|
|
327
358
|
return document.createTextNode(div.innerHTML);
|
|
359
|
+
} else if (value == null) {
|
|
360
|
+
return undefined;
|
|
361
|
+
} else if ((value as HTMLElement).nodeType) {
|
|
362
|
+
return value as HTMLElement;
|
|
328
363
|
} else {
|
|
329
364
|
return jQuery(value)[0];
|
|
330
365
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Node } from "./node";
|
|
2
|
+
|
|
3
|
+
export type AddToSelection = (node: Node) => void;
|
|
4
|
+
|
|
5
|
+
export type CloseNode = (node: Node) => void;
|
|
6
|
+
|
|
7
|
+
export type GetNodeById = (nodeId: NodeId) => Node | null;
|
|
8
|
+
|
|
9
|
+
export type GetScrollLeft = () => number;
|
|
10
|
+
|
|
11
|
+
export type GetSelectedNode = () => Node | false;
|
|
12
|
+
|
|
13
|
+
export type GetSelectedNodes = () => Node[];
|
|
14
|
+
|
|
15
|
+
export type GetTree = () => Node | null;
|
|
16
|
+
|
|
17
|
+
export type IsFocusOnTree = () => boolean;
|
|
18
|
+
|
|
19
|
+
export type IsNodeSelected = (node: Node) => boolean;
|
|
20
|
+
|
|
21
|
+
export type LoadData = (data: NodeData[], parentNode: Node | null) => void;
|
|
22
|
+
|
|
23
|
+
export type OnFinishOpenNode = (node: Node) => void;
|
|
24
|
+
|
|
25
|
+
export type OpenNode = (
|
|
26
|
+
node: Node,
|
|
27
|
+
slide?: boolean,
|
|
28
|
+
onFinished?: OnFinishOpenNode,
|
|
29
|
+
) => void;
|
|
30
|
+
|
|
31
|
+
export type RefreshElements = (fromNode: Node | null) => void;
|
|
32
|
+
|
|
33
|
+
export type RemoveFromSelection = (node: Node) => void;
|
|
34
|
+
|
|
35
|
+
export type SelectNode = (node: Node) => void;
|
|
36
|
+
|
|
37
|
+
export type TriggerEvent = (
|
|
38
|
+
eventName: string,
|
|
39
|
+
values?: Record<string, unknown>,
|
|
40
|
+
) => JQuery.Event;
|
package/src/jqtreeOptions.ts
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
import { Node } from "./node";
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
export type OnCanMove = ((node: Node) => boolean) | undefined;
|
|
4
|
+
|
|
5
|
+
type DataUrlFunction = (node: Node | null) => JQuery.AjaxSettings;
|
|
6
|
+
|
|
7
|
+
export type DataUrl = string | JQuery.AjaxSettings | DataUrlFunction;
|
|
8
|
+
|
|
9
|
+
export type DragMethod = (node: Node, event: Event | Touch) => void;
|
|
10
|
+
|
|
11
|
+
export type OnCanMoveTo = (
|
|
4
12
|
node: Node,
|
|
5
13
|
targetNode: Node,
|
|
6
14
|
positionName: string,
|
|
7
15
|
) => boolean;
|
|
8
|
-
|
|
9
|
-
type
|
|
10
|
-
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
type
|
|
16
|
+
|
|
17
|
+
export type OnGetStateFromStorage = (() => string) | undefined;
|
|
18
|
+
|
|
19
|
+
export type OnIsMoveHandle = (el: JQuery) => boolean;
|
|
20
|
+
|
|
21
|
+
export type OnLoadFailed = (response: JQuery.jqXHR) => void;
|
|
22
|
+
|
|
23
|
+
export type OnSetStateFromStorage = ((data: string) => void) | undefined;
|
|
24
|
+
|
|
25
|
+
export type DataFilter = (data: unknown) => NodeData[];
|
|
26
|
+
|
|
27
|
+
export type IconElement = string | HTMLElement | JQuery<HTMLElement>;
|
|
28
|
+
|
|
29
|
+
export type OnCreateLi = (node: Node, el: JQuery, isSelected: boolean) => void;
|
|
30
|
+
|
|
31
|
+
export type OnLoading = (
|
|
14
32
|
isLoading: boolean,
|
|
15
33
|
node: Node | null,
|
|
16
34
|
$el: JQuery,
|
|
@@ -21,32 +39,32 @@ export interface JQTreeOptions {
|
|
|
21
39
|
autoEscape: boolean;
|
|
22
40
|
autoOpen: boolean | number;
|
|
23
41
|
buttonLeft: boolean;
|
|
24
|
-
closedIcon?:
|
|
25
|
-
data
|
|
26
|
-
dataFilter
|
|
27
|
-
dataUrl
|
|
42
|
+
closedIcon?: IconElement;
|
|
43
|
+
data?: NodeData[];
|
|
44
|
+
dataFilter?: DataFilter;
|
|
45
|
+
dataUrl?: DataUrl;
|
|
28
46
|
dragAndDrop: boolean;
|
|
29
47
|
keyboardSupport: boolean;
|
|
30
48
|
nodeClass: typeof Node;
|
|
31
|
-
onCanMove
|
|
32
|
-
onCanMoveTo
|
|
33
|
-
onCanSelectNode
|
|
34
|
-
onCreateLi
|
|
35
|
-
onDragMove
|
|
36
|
-
onDragStop
|
|
37
|
-
onGetStateFromStorage
|
|
38
|
-
onIsMoveHandle
|
|
39
|
-
onLoadFailed
|
|
40
|
-
onLoading
|
|
41
|
-
onSetStateFromStorage
|
|
42
|
-
openedIcon?:
|
|
49
|
+
onCanMove?: OnCanMove;
|
|
50
|
+
onCanMoveTo?: OnCanMoveTo;
|
|
51
|
+
onCanSelectNode?: (node: Node) => boolean;
|
|
52
|
+
onCreateLi?: OnCreateLi;
|
|
53
|
+
onDragMove?: DragMethod;
|
|
54
|
+
onDragStop?: DragMethod;
|
|
55
|
+
onGetStateFromStorage?: OnGetStateFromStorage;
|
|
56
|
+
onIsMoveHandle?: OnIsMoveHandle;
|
|
57
|
+
onLoadFailed?: OnLoadFailed;
|
|
58
|
+
onLoading?: OnLoading;
|
|
59
|
+
onSetStateFromStorage?: OnSetStateFromStorage;
|
|
60
|
+
openedIcon?: IconElement;
|
|
43
61
|
openFolderDelay: number | false;
|
|
44
|
-
rtl
|
|
62
|
+
rtl?: boolean;
|
|
45
63
|
selectable: boolean;
|
|
46
64
|
saveState: boolean | string;
|
|
47
65
|
showEmptyFolder: boolean;
|
|
48
66
|
slide: boolean;
|
|
49
67
|
startDndDelay: number;
|
|
50
|
-
tabIndex
|
|
68
|
+
tabIndex?: number;
|
|
51
69
|
useContextMenu: boolean;
|
|
52
70
|
}
|
package/src/keyHandler.ts
CHANGED
|
@@ -1,24 +1,58 @@
|
|
|
1
1
|
import { Node } from "./node";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CloseNode,
|
|
4
|
+
GetSelectedNode,
|
|
5
|
+
IsFocusOnTree,
|
|
6
|
+
OpenNode,
|
|
7
|
+
SelectNode,
|
|
8
|
+
} from "./jqtreeMethodTypes";
|
|
9
|
+
|
|
10
|
+
type KeyboardEventHandler = (event: KeyboardEvent) => boolean;
|
|
11
|
+
|
|
12
|
+
interface KeyHandlerParams {
|
|
13
|
+
closeNode: CloseNode;
|
|
14
|
+
getSelectedNode: GetSelectedNode;
|
|
15
|
+
isFocusOnTree: IsFocusOnTree;
|
|
16
|
+
keyboardSupport: boolean;
|
|
17
|
+
openNode: OpenNode;
|
|
18
|
+
selectNode: SelectNode;
|
|
19
|
+
}
|
|
3
20
|
|
|
4
21
|
export default class KeyHandler {
|
|
5
|
-
private
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
private closeNode: CloseNode;
|
|
23
|
+
private getSelectedNode: GetSelectedNode;
|
|
24
|
+
private handleKeyDownHandler?: KeyboardEventHandler;
|
|
25
|
+
private isFocusOnTree: IsFocusOnTree;
|
|
26
|
+
private keyboardSupport: boolean;
|
|
27
|
+
private openNode: OpenNode;
|
|
28
|
+
private originalSelectNode: SelectNode;
|
|
29
|
+
|
|
30
|
+
constructor({
|
|
31
|
+
closeNode,
|
|
32
|
+
getSelectedNode,
|
|
33
|
+
isFocusOnTree,
|
|
34
|
+
keyboardSupport,
|
|
35
|
+
openNode,
|
|
36
|
+
selectNode,
|
|
37
|
+
}: KeyHandlerParams) {
|
|
38
|
+
this.closeNode = closeNode;
|
|
39
|
+
this.getSelectedNode = getSelectedNode;
|
|
40
|
+
this.isFocusOnTree = isFocusOnTree;
|
|
41
|
+
this.keyboardSupport = keyboardSupport;
|
|
42
|
+
this.openNode = openNode;
|
|
43
|
+
this.originalSelectNode = selectNode;
|
|
44
|
+
|
|
45
|
+
if (keyboardSupport) {
|
|
46
|
+
this.handleKeyDownHandler = this.handleKeyDown.bind(this);
|
|
47
|
+
|
|
48
|
+
document.addEventListener("keydown", this.handleKeyDownHandler);
|
|
17
49
|
}
|
|
18
50
|
}
|
|
19
51
|
|
|
20
52
|
public deinit(): void {
|
|
21
|
-
|
|
53
|
+
if (this.handleKeyDownHandler) {
|
|
54
|
+
document.removeEventListener("keydown", this.handleKeyDownHandler);
|
|
55
|
+
}
|
|
22
56
|
}
|
|
23
57
|
|
|
24
58
|
public moveDown(selectedNode: Node): boolean {
|
|
@@ -39,7 +73,7 @@ export default class KeyHandler {
|
|
|
39
73
|
return this.selectNode(selectedNode.getNextVisibleNode());
|
|
40
74
|
} else {
|
|
41
75
|
// Right expands a closed node
|
|
42
|
-
this.
|
|
76
|
+
this.openNode(selectedNode);
|
|
43
77
|
return false;
|
|
44
78
|
}
|
|
45
79
|
}
|
|
@@ -48,7 +82,7 @@ export default class KeyHandler {
|
|
|
48
82
|
public moveLeft(selectedNode: Node): boolean {
|
|
49
83
|
if (selectedNode.isFolder() && selectedNode.is_open) {
|
|
50
84
|
// Left on an open node closes the node
|
|
51
|
-
this.
|
|
85
|
+
this.closeNode(selectedNode);
|
|
52
86
|
return false;
|
|
53
87
|
} else {
|
|
54
88
|
// Left on a closed or end node moves focus to the node's parent
|
|
@@ -60,35 +94,33 @@ export default class KeyHandler {
|
|
|
60
94
|
if (!node) {
|
|
61
95
|
return true;
|
|
62
96
|
} else {
|
|
63
|
-
this.
|
|
97
|
+
this.originalSelectNode(node);
|
|
64
98
|
|
|
65
99
|
return false;
|
|
66
100
|
}
|
|
67
101
|
}
|
|
68
102
|
|
|
69
|
-
private handleKeyDown = (e:
|
|
103
|
+
private handleKeyDown = (e: KeyboardEvent): boolean => {
|
|
70
104
|
if (!this.canHandleKeyboard()) {
|
|
71
105
|
return true;
|
|
72
106
|
}
|
|
73
107
|
|
|
74
|
-
const selectedNode = this.
|
|
108
|
+
const selectedNode = this.getSelectedNode();
|
|
75
109
|
if (!selectedNode) {
|
|
76
110
|
return true;
|
|
77
111
|
}
|
|
78
112
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
switch (key) {
|
|
82
|
-
case KeyHandler.DOWN:
|
|
113
|
+
switch (e.key) {
|
|
114
|
+
case "ArrowDown":
|
|
83
115
|
return this.moveDown(selectedNode);
|
|
84
116
|
|
|
85
|
-
case
|
|
117
|
+
case "ArrowUp":
|
|
86
118
|
return this.moveUp(selectedNode);
|
|
87
119
|
|
|
88
|
-
case
|
|
120
|
+
case "ArrowRight":
|
|
89
121
|
return this.moveRight(selectedNode);
|
|
90
122
|
|
|
91
|
-
case
|
|
123
|
+
case "ArrowLeft":
|
|
92
124
|
return this.moveLeft(selectedNode);
|
|
93
125
|
|
|
94
126
|
default:
|
|
@@ -97,9 +129,6 @@ export default class KeyHandler {
|
|
|
97
129
|
};
|
|
98
130
|
|
|
99
131
|
private canHandleKeyboard(): boolean {
|
|
100
|
-
return (
|
|
101
|
-
(this.treeWidget.options.keyboardSupport || false) &&
|
|
102
|
-
this.treeWidget.selectNodeHandler.isFocusOnTree()
|
|
103
|
-
);
|
|
132
|
+
return this.keyboardSupport && this.isFocusOnTree();
|
|
104
133
|
}
|
|
105
134
|
}
|
package/src/mouse.widget.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
This widget does the same a the mouse widget in jqueryui.
|
|
3
3
|
*/
|
|
4
4
|
import SimpleWidget from "./simple.widget";
|
|
5
|
-
import { PositionInfo } from "./
|
|
5
|
+
import { PositionInfo } from "./mouseWidgetTypes";
|
|
6
6
|
|
|
7
7
|
const getPositionInfoFromMouseEvent = (e: MouseEvent): PositionInfo => ({
|
|
8
8
|
pageX: e.pageX,
|
|
@@ -13,7 +13,7 @@ const getPositionInfoFromMouseEvent = (e: MouseEvent): PositionInfo => ({
|
|
|
13
13
|
|
|
14
14
|
const getPositionInfoFromTouch = (
|
|
15
15
|
touch: Touch,
|
|
16
|
-
e: TouchEvent
|
|
16
|
+
e: TouchEvent,
|
|
17
17
|
): PositionInfo => ({
|
|
18
18
|
pageX: touch.pageX,
|
|
19
19
|
pageY: touch.pageY,
|
|
@@ -144,7 +144,7 @@ abstract class MouseWidget<WidgetOptions> extends SimpleWidget<WidgetOptions> {
|
|
|
144
144
|
|
|
145
145
|
private handleMouseMove(
|
|
146
146
|
e: MouseEvent | TouchEvent,
|
|
147
|
-
positionInfo: PositionInfo
|
|
147
|
+
positionInfo: PositionInfo,
|
|
148
148
|
): void {
|
|
149
149
|
if (this.isMouseStarted) {
|
|
150
150
|
this.mouseDrag(positionInfo);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DropHint } from "../dragAndDropHandler/types";
|
|
2
|
+
|
|
3
|
+
class BorderDropHint implements DropHint {
|
|
4
|
+
private hint?: HTMLElement;
|
|
5
|
+
|
|
6
|
+
constructor(element: HTMLElement, scrollLeft: number) {
|
|
7
|
+
const div = element.querySelector(":scope > .jqtree-element");
|
|
8
|
+
|
|
9
|
+
if (!div) {
|
|
10
|
+
this.hint = undefined;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const width = Math.max(element.offsetWidth + scrollLeft - 4, 0);
|
|
15
|
+
const height = Math.max(element.clientHeight - 4, 0);
|
|
16
|
+
|
|
17
|
+
const hint = document.createElement("span");
|
|
18
|
+
hint.className = "jqtree-border";
|
|
19
|
+
hint.style.width = `${width}px`;
|
|
20
|
+
hint.style.height = `${height}px`;
|
|
21
|
+
|
|
22
|
+
this.hint = hint;
|
|
23
|
+
|
|
24
|
+
div.append(this.hint);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public remove(): void {
|
|
28
|
+
this.hint?.remove();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default BorderDropHint;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Position } from "../node";
|
|
2
|
+
import NodeElement, { NodeElementParams } from "./index";
|
|
3
|
+
import { OnFinishOpenNode, TriggerEvent } from "../jqtreeMethodTypes";
|
|
4
|
+
|
|
5
|
+
interface FolderElementParams extends NodeElementParams {
|
|
6
|
+
closedIconElement?: HTMLElement | Text;
|
|
7
|
+
openedIconElement?: HTMLElement | Text;
|
|
8
|
+
triggerEvent: TriggerEvent;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class FolderElement extends NodeElement {
|
|
12
|
+
private closedIconElement?: HTMLElement | Text;
|
|
13
|
+
private openedIconElement?: HTMLElement | Text;
|
|
14
|
+
private triggerEvent: TriggerEvent;
|
|
15
|
+
|
|
16
|
+
constructor({
|
|
17
|
+
closedIconElement,
|
|
18
|
+
getScrollLeft,
|
|
19
|
+
node,
|
|
20
|
+
openedIconElement,
|
|
21
|
+
tabIndex,
|
|
22
|
+
$treeElement,
|
|
23
|
+
triggerEvent,
|
|
24
|
+
}: FolderElementParams) {
|
|
25
|
+
super({
|
|
26
|
+
getScrollLeft,
|
|
27
|
+
node,
|
|
28
|
+
tabIndex,
|
|
29
|
+
$treeElement,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.closedIconElement = closedIconElement;
|
|
33
|
+
this.openedIconElement = openedIconElement;
|
|
34
|
+
this.triggerEvent = triggerEvent;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public open(
|
|
38
|
+
onFinished: OnFinishOpenNode | undefined,
|
|
39
|
+
slide = true,
|
|
40
|
+
animationSpeed: JQuery.Duration = "fast",
|
|
41
|
+
): void {
|
|
42
|
+
if (this.node.is_open) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.node.is_open = true;
|
|
47
|
+
|
|
48
|
+
const button = this.getButton();
|
|
49
|
+
button.classList.remove("jqtree-closed");
|
|
50
|
+
button.innerHTML = "";
|
|
51
|
+
|
|
52
|
+
const openedIconElement = this.openedIconElement;
|
|
53
|
+
|
|
54
|
+
if (openedIconElement) {
|
|
55
|
+
const icon = openedIconElement.cloneNode(true);
|
|
56
|
+
button.appendChild(icon);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const doOpen = (): void => {
|
|
60
|
+
this.element.classList.remove("jqtree-closed");
|
|
61
|
+
|
|
62
|
+
const titleSpan = this.getTitleSpan();
|
|
63
|
+
titleSpan.setAttribute("aria-expanded", "true");
|
|
64
|
+
|
|
65
|
+
if (onFinished) {
|
|
66
|
+
onFinished(this.node);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.triggerEvent("tree.open", {
|
|
70
|
+
node: this.node,
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (slide) {
|
|
75
|
+
jQuery(this.getUl()).slideDown(animationSpeed, doOpen);
|
|
76
|
+
} else {
|
|
77
|
+
jQuery(this.getUl()).show();
|
|
78
|
+
doOpen();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public close(
|
|
83
|
+
slide = true,
|
|
84
|
+
animationSpeed: JQuery.Duration | undefined = "fast",
|
|
85
|
+
): void {
|
|
86
|
+
if (!this.node.is_open) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.node.is_open = false;
|
|
91
|
+
|
|
92
|
+
const button = this.getButton();
|
|
93
|
+
button.classList.add("jqtree-closed");
|
|
94
|
+
button.innerHTML = "";
|
|
95
|
+
|
|
96
|
+
const closedIconElement = this.closedIconElement;
|
|
97
|
+
|
|
98
|
+
if (closedIconElement) {
|
|
99
|
+
const icon = closedIconElement.cloneNode(true);
|
|
100
|
+
button.appendChild(icon);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const doClose = (): void => {
|
|
104
|
+
this.element.classList.add("jqtree-closed");
|
|
105
|
+
|
|
106
|
+
const titleSpan = this.getTitleSpan();
|
|
107
|
+
titleSpan.setAttribute("aria-expanded", "false");
|
|
108
|
+
|
|
109
|
+
this.triggerEvent("tree.close", {
|
|
110
|
+
node: this.node,
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if (slide) {
|
|
115
|
+
jQuery(this.getUl()).slideUp(animationSpeed, doClose);
|
|
116
|
+
} else {
|
|
117
|
+
jQuery(this.getUl()).hide();
|
|
118
|
+
doClose();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
protected mustShowBorderDropHint(position: Position): boolean {
|
|
123
|
+
return !this.node.is_open && position === Position.Inside;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private getButton(): HTMLLinkElement {
|
|
127
|
+
return this.element.querySelector(
|
|
128
|
+
":scope > .jqtree-element > a.jqtree-toggler",
|
|
129
|
+
) as HTMLLinkElement;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default FolderElement;
|