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.
Files changed (90) hide show
  1. package/bower.json +1 -1
  2. package/config/babel.config.json +1 -1
  3. package/config/production +2 -0
  4. package/devserver/devserver_scroll.js +8 -0
  5. package/devserver/test_scroll.html +28 -0
  6. package/devserver/test_scroll_container.html +39 -0
  7. package/docs/_config.yml +1 -1
  8. package/docs/_entries/general/changelog.md +7 -0
  9. package/package.json +5 -1
  10. package/src/dataLoader.ts +44 -19
  11. package/src/dragAndDropHandler/dragElement.ts +42 -0
  12. package/src/dragAndDropHandler/hitAreasGenerator.ts +175 -0
  13. package/src/dragAndDropHandler/index.ts +470 -0
  14. package/src/dragAndDropHandler/types.ts +12 -0
  15. package/src/dragAndDropHandler/visibleNodeIterator.ts +97 -0
  16. package/src/elementsRenderer.ts +75 -40
  17. package/src/jqtreeMethodTypes.ts +40 -0
  18. package/src/jqtreeOptions.ts +43 -25
  19. package/src/keyHandler.ts +59 -30
  20. package/src/mouse.widget.ts +3 -3
  21. package/src/mouseWidgetTypes.ts +6 -0
  22. package/src/nodeElement/borderDropHint.ts +32 -0
  23. package/src/nodeElement/folderElement.ts +133 -0
  24. package/src/nodeElement/ghostDropHint.ts +68 -0
  25. package/src/nodeElement/index.ts +101 -0
  26. package/src/playwright/coverage.ts +1 -4
  27. package/src/playwright/playwright.test.ts +0 -4
  28. package/src/saveStateHandler.ts +75 -26
  29. package/src/scrollHandler.ts +13 -7
  30. package/src/selectNodeHandler.ts +10 -16
  31. package/src/test/jqTree/keyboard.test.ts +18 -23
  32. package/src/test/jqTree/methods.test.ts +32 -3
  33. package/src/test/jqTree/options.test.ts +15 -4
  34. package/src/test/node.test.ts +1 -1
  35. package/src/tree.jquery.ts +239 -57
  36. package/src/util.ts +3 -0
  37. package/src/version.ts +1 -1
  38. package/tree.jquery.debug.js +1728 -2576
  39. package/tree.jquery.debug.js.map +1 -1
  40. package/tree.jquery.js +2 -2
  41. package/tree.jquery.js.map +1 -1
  42. package/lib/dataLoader.js +0 -123
  43. package/lib/dragAndDropHandler.js +0 -588
  44. package/lib/elementsRenderer.js +0 -267
  45. package/lib/jqtreeOptions.js +0 -1
  46. package/lib/keyHandler.js +0 -111
  47. package/lib/mouse.widget.js +0 -255
  48. package/lib/node.js +0 -708
  49. package/lib/nodeElement.js +0 -274
  50. package/lib/nodeUtils.js +0 -10
  51. package/lib/playwright/coverage.js +0 -99
  52. package/lib/playwright/playwright.test.js +0 -606
  53. package/lib/playwright/testUtils.js +0 -210
  54. package/lib/saveStateHandler.js +0 -277
  55. package/lib/scrollHandler/containerScrollParent.js +0 -160
  56. package/lib/scrollHandler/createScrollParent.js +0 -57
  57. package/lib/scrollHandler/documentScrollParent.js +0 -169
  58. package/lib/scrollHandler/scrollParent.js +0 -58
  59. package/lib/scrollHandler/types.js +0 -1
  60. package/lib/scrollHandler.js +0 -71
  61. package/lib/selectNodeHandler.js +0 -128
  62. package/lib/simple.widget.js +0 -158
  63. package/lib/test/global.d.js +0 -3
  64. package/lib/test/jqTree/accessibility.test.js +0 -37
  65. package/lib/test/jqTree/create.test.js +0 -48
  66. package/lib/test/jqTree/events.test.js +0 -210
  67. package/lib/test/jqTree/keyboard.test.js +0 -225
  68. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  69. package/lib/test/jqTree/methods.test.js +0 -1348
  70. package/lib/test/jqTree/options.test.js +0 -548
  71. package/lib/test/jqTree/scrollHandler/containerScrollParent.test.js +0 -94
  72. package/lib/test/node.test.js +0 -1202
  73. package/lib/test/nodeUtil.test.js +0 -27
  74. package/lib/test/nodeUtils.test.js +0 -20
  75. package/lib/test/support/exampleData.js +0 -35
  76. package/lib/test/support/jqTreeMatchers.js +0 -70
  77. package/lib/test/support/matchers.d.js +0 -1
  78. package/lib/test/support/setupTests.js +0 -7
  79. package/lib/test/support/testUtil.js +0 -29
  80. package/lib/test/support/treeStructure.js +0 -38
  81. package/lib/test/util.test.js +0 -26
  82. package/lib/tree.jquery.d.js +0 -1
  83. package/lib/tree.jquery.js +0 -1105
  84. package/lib/types.js +0 -1
  85. package/lib/typings.d.js +0 -2
  86. package/lib/util.js +0 -15
  87. package/lib/version.js +0 -8
  88. package/src/dragAndDropHandler.ts +0 -713
  89. package/src/nodeElement.ts +0 -272
  90. package/src/types.ts +0 -19
@@ -1,23 +1,63 @@
1
1
  import { getBoolString } from "./util";
2
2
  import { Node } from "./node";
3
- import { JqTreeWidget } from "./tree.jquery";
4
-
5
- type IconElement = string | HTMLElement | JQuery<HTMLElement>;
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 treeWidget: JqTreeWidget;
11
-
12
- constructor(treeWidget: JqTreeWidget) {
13
- this.treeWidget = treeWidget;
14
-
15
- this.openedIconElement = this.createButtonElement(
16
- treeWidget.options.openedIcon || "+",
17
- );
18
- this.closedIconElement = this.createButtonElement(
19
- treeWidget.options.closedIcon || "-",
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
- const $element = this.treeWidget.element;
33
- $element.empty();
72
+ this.$element.empty();
34
73
 
35
- if ($element[0]) {
36
- this.createDomElements(
37
- $element[0],
38
- this.treeWidget.tree.children,
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.treeWidget.options.rtl) {
143
+ if (this.rtl) {
108
144
  classString += " jqtree-rtl";
109
145
  }
110
146
  }
111
147
 
112
- if (this.treeWidget.options.dragAndDrop) {
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.treeWidget.options.onCreateLi) {
138
- this.treeWidget.options.onCreateLi(node, jQuery(li), isSelected);
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.treeWidget.options.buttonLeft) {
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.treeWidget.options.buttonLeft) {
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.treeWidget.options.tabIndex;
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.treeWidget.options.autoEscape) {
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.treeWidget.options.buttonLeft) {
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;
@@ -1,16 +1,34 @@
1
1
  import { Node } from "./node";
2
2
 
3
- type CanMoveNodeTo = (
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
- type CreateLi = (node: Node, el: JQuery, isSelected: boolean) => void;
9
- type DataFilter = (data: unknown) => NodeData[];
10
- type DataUrlFunction = (node: Node | null) => JQuery.AjaxSettings;
11
- type DataUrl = string | JQuery.AjaxSettings | DataUrlFunction;
12
- type DragMethod = (node: Node, event: Event | Touch) => void;
13
- type HandleLoadingMethod = (
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?: string | HTMLElement | JQuery<HTMLElement>;
25
- data: NodeData[] | undefined;
26
- dataFilter: DataFilter | undefined;
27
- dataUrl: DataUrl | undefined;
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: ((node: Node) => boolean) | undefined;
32
- onCanMoveTo: CanMoveNodeTo | undefined;
33
- onCanSelectNode: ((node: Node) => boolean) | undefined;
34
- onCreateLi: CreateLi | undefined;
35
- onDragMove: DragMethod | undefined;
36
- onDragStop: DragMethod | undefined;
37
- onGetStateFromStorage: (() => string) | undefined;
38
- onIsMoveHandle: ((el: JQuery) => boolean) | undefined;
39
- onLoadFailed: ((response: JQuery.jqXHR) => void) | undefined;
40
- onLoading: HandleLoadingMethod | undefined;
41
- onSetStateFromStorage: ((data: string) => void) | undefined;
42
- openedIcon?: string | HTMLElement | JQuery<HTMLElement>;
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: boolean | undefined;
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: number;
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 { JqTreeWidget } from "./tree.jquery";
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 static LEFT = 37;
6
- private static UP = 38;
7
- private static RIGHT = 39;
8
- private static DOWN = 40;
9
-
10
- private treeWidget: JqTreeWidget;
11
-
12
- constructor(treeWidget: JqTreeWidget) {
13
- this.treeWidget = treeWidget;
14
-
15
- if (treeWidget.options.keyboardSupport) {
16
- jQuery(document).on("keydown.jqtree", this.handleKeyDown);
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
- jQuery(document).off("keydown.jqtree");
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.treeWidget.openNode(selectedNode);
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.treeWidget.closeNode(selectedNode);
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.treeWidget.selectNode(node);
97
+ this.originalSelectNode(node);
64
98
 
65
99
  return false;
66
100
  }
67
101
  }
68
102
 
69
- private handleKeyDown = (e: JQuery.Event): boolean => {
103
+ private handleKeyDown = (e: KeyboardEvent): boolean => {
70
104
  if (!this.canHandleKeyboard()) {
71
105
  return true;
72
106
  }
73
107
 
74
- const selectedNode = this.treeWidget.getSelectedNode();
108
+ const selectedNode = this.getSelectedNode();
75
109
  if (!selectedNode) {
76
110
  return true;
77
111
  }
78
112
 
79
- const key = e.which;
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 KeyHandler.UP:
117
+ case "ArrowUp":
86
118
  return this.moveUp(selectedNode);
87
119
 
88
- case KeyHandler.RIGHT:
120
+ case "ArrowRight":
89
121
  return this.moveRight(selectedNode);
90
122
 
91
- case KeyHandler.LEFT:
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
  }
@@ -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 "./types";
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,6 @@
1
+ export interface PositionInfo {
2
+ pageX: number | undefined;
3
+ pageY: number | undefined;
4
+ target: HTMLElement;
5
+ originalEvent: Event;
6
+ }
@@ -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;