jqtree 1.8.10 → 1.9.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 (39) hide show
  1. package/bower.json +3 -10
  2. package/eslint.config.mjs +47 -9
  3. package/package.json +50 -53
  4. package/pnpm-workspace.yaml +4 -0
  5. package/src/animation.ts +48 -0
  6. package/src/dataLoader.ts +38 -48
  7. package/src/dragAndDropHandler/dragElement.ts +11 -11
  8. package/src/dragAndDropHandler/generateHitAreas.ts +4 -3
  9. package/src/dragAndDropHandler/index.ts +119 -120
  10. package/src/dragAndDropHandler/iterateVisibleNodes.ts +1 -1
  11. package/src/dragAndDropHandler/types.ts +1 -1
  12. package/src/elementsRenderer.ts +71 -78
  13. package/src/jqtreeMethodTypes.ts +2 -2
  14. package/src/jqtreeOptions.ts +3 -2
  15. package/src/keyHandler.ts +34 -34
  16. package/src/mouseHandler.ts +125 -123
  17. package/src/node.ts +23 -27
  18. package/src/nodeElement/borderDropHint.ts +6 -6
  19. package/src/nodeElement/folderElement.ts +30 -22
  20. package/src/nodeElement/ghostDropHint.ts +24 -24
  21. package/src/nodeElement/index.ts +13 -14
  22. package/src/positionUtils.ts +18 -0
  23. package/src/saveStateHandler.ts +56 -55
  24. package/src/scrollHandler/containerScrollParent.ts +27 -124
  25. package/src/scrollHandler/createScrollParent.ts +1 -1
  26. package/src/scrollHandler/documentScrollParent.ts +43 -125
  27. package/src/scrollHandler/scrollParent.ts +117 -0
  28. package/src/scrollHandler.ts +24 -25
  29. package/src/selectNodeHandler.ts +28 -28
  30. package/src/simple.widget.ts +1 -3
  31. package/src/tree.jquery.ts +253 -279
  32. package/src/util.ts +0 -14
  33. package/src/version.ts +1 -1
  34. package/tree.jquery.debug.js +1044 -998
  35. package/tree.jquery.debug.js.map +1 -1
  36. package/tree.jquery.js +3 -3
  37. package/tree.jquery.js.map +1 -1
  38. package/.tool-versions +0 -2
  39. package/src/scrollHandler/types.ts +0 -7
@@ -1,15 +1,16 @@
1
- import { GetTree, IsNodeSelected } from "./jqtreeMethodTypes";
2
- import { IconElement, OnCreateLi } from "./jqtreeOptions";
3
- import { Node } from "./node";
1
+ import type { GetTree, IsNodeSelected } from "./jqtreeMethodTypes";
2
+ import type { IconElement, OnCreateLi } from "./jqtreeOptions";
3
+ import type { Node } from "./node";
4
+
4
5
  import { getBoolString } from "./util";
5
6
 
6
7
  interface ElementsRendererParams {
7
- $element: JQuery;
8
8
  autoEscape: boolean;
9
9
  buttonLeft: boolean;
10
10
  closedIcon?: IconElement;
11
11
  dragAndDrop: boolean;
12
12
  getTree: GetTree;
13
+ htmlElement: HTMLElement;
13
14
  isNodeSelected: IsNodeSelected;
14
15
  onCreateLi?: OnCreateLi;
15
16
  openedIcon?: IconElement;
@@ -21,25 +22,25 @@ interface ElementsRendererParams {
21
22
  export default class ElementsRenderer {
22
23
  public closedIconElement?: HTMLElement | Text;
23
24
  public openedIconElement?: HTMLElement | Text;
24
- private $element: JQuery;
25
- private autoEscape: boolean;
26
- private buttonLeft: boolean;
27
- private dragAndDrop: boolean;
28
- private getTree: GetTree;
29
- private isNodeSelected: IsNodeSelected;
30
- private onCreateLi?: OnCreateLi;
31
- private rtl?: boolean;
32
-
33
- private showEmptyFolder: boolean;
34
- private tabIndex?: number;
25
+ private _autoEscape: boolean;
26
+ private _buttonLeft: boolean;
27
+ private _dragAndDrop: boolean;
28
+ private _getTree: GetTree;
29
+ private _htmlElement: HTMLElement;
30
+ private _isNodeSelected: IsNodeSelected;
31
+ private _onCreateLi?: OnCreateLi;
32
+ private _rtl?: boolean;
33
+
34
+ private _showEmptyFolder: boolean;
35
+ private _tabIndex?: number;
35
36
 
36
37
  constructor({
37
- $element,
38
38
  autoEscape,
39
39
  buttonLeft,
40
40
  closedIcon,
41
41
  dragAndDrop,
42
42
  getTree,
43
+ htmlElement,
43
44
  isNodeSelected,
44
45
  onCreateLi,
45
46
  openedIcon,
@@ -47,18 +48,18 @@ export default class ElementsRenderer {
47
48
  showEmptyFolder,
48
49
  tabIndex,
49
50
  }: ElementsRendererParams) {
50
- this.autoEscape = autoEscape;
51
- this.buttonLeft = buttonLeft;
52
- this.dragAndDrop = dragAndDrop;
53
- this.$element = $element;
54
- this.getTree = getTree;
55
- this.isNodeSelected = isNodeSelected;
56
- this.onCreateLi = onCreateLi;
57
- this.rtl = rtl;
58
- this.showEmptyFolder = showEmptyFolder;
59
- this.tabIndex = tabIndex;
60
- this.openedIconElement = this.createButtonElement(openedIcon ?? "+");
61
- this.closedIconElement = this.createButtonElement(closedIcon ?? "-");
51
+ this._autoEscape = autoEscape;
52
+ this._buttonLeft = buttonLeft;
53
+ this._dragAndDrop = dragAndDrop;
54
+ this._getTree = getTree;
55
+ this._htmlElement = htmlElement;
56
+ this._isNodeSelected = isNodeSelected;
57
+ this._onCreateLi = onCreateLi;
58
+ this._rtl = rtl;
59
+ this._showEmptyFolder = showEmptyFolder;
60
+ this._tabIndex = tabIndex;
61
+ this.openedIconElement = this._createButtonElement(openedIcon ?? "+");
62
+ this.closedIconElement = this._createButtonElement(closedIcon ?? "-");
62
63
  }
63
64
 
64
65
  public render(fromNode: Node | null): void {
@@ -74,38 +75,30 @@ export default class ElementsRenderer {
74
75
  return;
75
76
  }
76
77
 
77
- // remember current li
78
- const $previousLi = jQuery(node.element);
79
-
80
- // create element
81
- const li = this.createLi(node, node.getLevel());
82
-
83
- // add element to dom
84
- $previousLi.after(li);
85
-
86
- // remove previous li
87
- $previousLi.remove();
78
+ const currentLi = node.element;
79
+ const newLi = this._createLi(node, node.getLevel());
80
+ currentLi.replaceWith(newLi);
88
81
 
89
82
  // create children
90
- this.createDomElements(li, node.children, false, node.getLevel() + 1);
83
+ this._createDomElements(newLi, node.children, false, node.getLevel() + 1);
91
84
  }
92
85
 
93
86
  public renderFromRoot(): void {
94
- this.$element.empty();
87
+ this._htmlElement.textContent = '';
95
88
 
96
- const tree = this.getTree();
89
+ const tree = this._getTree();
97
90
 
98
- if (this.$element[0] && tree) {
99
- this.createDomElements(this.$element[0], tree.children, true, 1);
91
+ if (tree) {
92
+ this._createDomElements(this._htmlElement, tree.children, true, 1);
100
93
  }
101
94
  }
102
95
 
103
- private attachNodeData(node: Node, li: HTMLElement): void {
96
+ private _attachNodeData(node: Node, li: HTMLElement): void {
104
97
  node.element = li;
105
98
  jQuery(li).data("node", node);
106
99
  }
107
100
 
108
- private createButtonElement(
101
+ private _createButtonElement(
109
102
  value: IconElement,
110
103
  ): HTMLElement | Text | undefined {
111
104
  if (typeof value === "string") {
@@ -121,32 +114,32 @@ export default class ElementsRenderer {
121
114
  }
122
115
  }
123
116
 
124
- private createDomElements(
117
+ private _createDomElements(
125
118
  element: Element,
126
119
  children: Node[],
127
120
  isRootNode: boolean,
128
121
  level: number,
129
122
  ): void {
130
- const ul = this.createUl(isRootNode);
123
+ const ul = this._createUl(isRootNode);
131
124
  element.appendChild(ul);
132
125
 
133
126
  for (const child of children) {
134
- const li = this.createLi(child, level);
127
+ const li = this._createLi(child, level);
135
128
  ul.appendChild(li);
136
129
 
137
130
  if (child.hasChildren()) {
138
- this.createDomElements(li, child.children, false, level + 1);
131
+ this._createDomElements(li, child.children, false, level + 1);
139
132
  }
140
133
  }
141
134
  }
142
135
 
143
- private createFolderLi(
136
+ private _createFolderLi(
144
137
  node: Node,
145
138
  level: number,
146
139
  isSelected: boolean,
147
140
  ): HTMLLIElement {
148
- const buttonClasses = this.getButtonClasses(node);
149
- const folderClasses = this.getFolderClasses(node, isSelected);
141
+ const buttonClasses = this._getButtonClasses(node);
142
+ const folderClasses = this._getFolderClasses(node, isSelected);
150
143
 
151
144
  const iconElement = node.is_open
152
145
  ? this.openedIconElement
@@ -172,12 +165,12 @@ export default class ElementsRenderer {
172
165
  buttonLink.appendChild(iconElement.cloneNode(true));
173
166
  }
174
167
 
175
- if (this.buttonLeft) {
168
+ if (this._buttonLeft) {
176
169
  div.appendChild(buttonLink);
177
170
  }
178
171
 
179
172
  // title span
180
- const titleSpan = this.createTitleSpan(
173
+ const titleSpan = this._createTitleSpan(
181
174
  node.name,
182
175
  isSelected,
183
176
  true,
@@ -186,7 +179,7 @@ export default class ElementsRenderer {
186
179
  titleSpan.setAttribute("aria-expanded", getBoolString(node.is_open));
187
180
  div.appendChild(titleSpan);
188
181
 
189
- if (!this.buttonLeft) {
182
+ if (!this._buttonLeft) {
190
183
  div.appendChild(buttonLink);
191
184
  }
192
185
 
@@ -197,26 +190,26 @@ export default class ElementsRenderer {
197
190
  * Attach it to node.element.
198
191
  * Call onCreateLi
199
192
  */
200
- private createLi(node: Node, level: number): HTMLLIElement {
201
- const isSelected = Boolean(this.isNodeSelected(node));
193
+ private _createLi(node: Node, level: number): HTMLLIElement {
194
+ const isSelected = this._isNodeSelected(node);
202
195
 
203
196
  const mustShowFolder =
204
- node.isFolder() || (node.isEmptyFolder && this.showEmptyFolder);
197
+ node.isFolder() || (node.isEmptyFolder && this._showEmptyFolder);
205
198
 
206
199
  const li = mustShowFolder
207
- ? this.createFolderLi(node, level, isSelected)
208
- : this.createNodeLi(node, level, isSelected);
200
+ ? this._createFolderLi(node, level, isSelected)
201
+ : this._createNodeLi(node, level, isSelected);
209
202
 
210
- this.attachNodeData(node, li);
203
+ this._attachNodeData(node, li);
211
204
 
212
- if (this.onCreateLi) {
213
- this.onCreateLi(node, jQuery(li), isSelected);
205
+ if (this._onCreateLi) {
206
+ this._onCreateLi(node, jQuery(li), isSelected);
214
207
  }
215
208
 
216
209
  return li;
217
210
  }
218
211
 
219
- private createNodeLi(
212
+ private _createNodeLi(
220
213
  node: Node,
221
214
  level: number,
222
215
  isSelected: boolean,
@@ -242,7 +235,7 @@ export default class ElementsRenderer {
242
235
  li.appendChild(div);
243
236
 
244
237
  // title span
245
- const titleSpan = this.createTitleSpan(
238
+ const titleSpan = this._createTitleSpan(
246
239
  node.name,
247
240
  isSelected,
248
241
  false,
@@ -253,7 +246,7 @@ export default class ElementsRenderer {
253
246
  return li;
254
247
  }
255
248
 
256
- private createTitleSpan(
249
+ private _createTitleSpan(
257
250
  nodeName: string,
258
251
  isSelected: boolean,
259
252
  isFolder: boolean,
@@ -267,21 +260,21 @@ export default class ElementsRenderer {
267
260
  classes += " jqtree-title-folder";
268
261
  }
269
262
 
270
- classes += ` jqtree-title-button-${this.buttonLeft ? "left" : "right"}`;
263
+ classes += ` jqtree-title-button-${this._buttonLeft ? "left" : "right"}`;
271
264
 
272
265
  titleSpan.className = classes;
273
266
 
274
267
  if (isSelected) {
275
- const tabIndex = this.tabIndex;
268
+ const tabIndex = this._tabIndex;
276
269
 
277
270
  if (tabIndex !== undefined) {
278
271
  titleSpan.setAttribute("tabindex", `${tabIndex}`);
279
272
  }
280
273
  }
281
274
 
282
- this.setTreeItemAriaAttributes(titleSpan, nodeName, level, isSelected);
275
+ this._setTreeItemAriaAttributes(titleSpan, nodeName, level, isSelected);
283
276
 
284
- if (this.autoEscape) {
277
+ if (this._autoEscape) {
285
278
  titleSpan.textContent = nodeName;
286
279
  } else {
287
280
  titleSpan.innerHTML = nodeName;
@@ -290,7 +283,7 @@ export default class ElementsRenderer {
290
283
  return titleSpan;
291
284
  }
292
285
 
293
- private createUl(isRootNode: boolean): HTMLUListElement {
286
+ private _createUl(isRootNode: boolean): HTMLUListElement {
294
287
  let classString;
295
288
  let role;
296
289
 
@@ -301,12 +294,12 @@ export default class ElementsRenderer {
301
294
  classString = "jqtree-tree";
302
295
  role = "tree";
303
296
 
304
- if (this.rtl) {
297
+ if (this._rtl) {
305
298
  classString += " jqtree-rtl";
306
299
  }
307
300
  }
308
301
 
309
- if (this.dragAndDrop) {
302
+ if (this._dragAndDrop) {
310
303
  classString += " jqtree-dnd";
311
304
  }
312
305
 
@@ -318,14 +311,14 @@ export default class ElementsRenderer {
318
311
  return ul;
319
312
  }
320
313
 
321
- private getButtonClasses(node: Node): string {
314
+ private _getButtonClasses(node: Node): string {
322
315
  const classes = ["jqtree-toggler", "jqtree_common"];
323
316
 
324
317
  if (!node.is_open) {
325
318
  classes.push("jqtree-closed");
326
319
  }
327
320
 
328
- if (this.buttonLeft) {
321
+ if (this._buttonLeft) {
329
322
  classes.push("jqtree-toggler-left");
330
323
  } else {
331
324
  classes.push("jqtree-toggler-right");
@@ -334,7 +327,7 @@ export default class ElementsRenderer {
334
327
  return classes.join(" ");
335
328
  }
336
329
 
337
- private getFolderClasses(node: Node, isSelected: boolean): string {
330
+ private _getFolderClasses(node: Node, isSelected: boolean): string {
338
331
  const classes = ["jqtree-folder"];
339
332
 
340
333
  if (!node.is_open) {
@@ -352,7 +345,7 @@ export default class ElementsRenderer {
352
345
  return classes.join(" ");
353
346
  }
354
347
 
355
- private setTreeItemAriaAttributes(
348
+ private _setTreeItemAriaAttributes(
356
349
  element: HTMLElement,
357
350
  name: string,
358
351
  level: number,
@@ -1,4 +1,4 @@
1
- import { Node } from "./node";
1
+ import type { Node } from "./node";
2
2
 
3
3
  export type AddToSelection = (node: Node) => void;
4
4
 
@@ -37,4 +37,4 @@ export type SelectNode = (node: Node) => void;
37
37
  export type TriggerEvent = (
38
38
  eventName: string,
39
39
  values?: Record<string, unknown>,
40
- ) => JQuery.Event;
40
+ ) => boolean;
@@ -1,4 +1,5 @@
1
- import { Node } from "./node";
1
+ import type { AnimationSpeed } from "./animation";
2
+ import type { Node } from "./node";
2
3
 
3
4
  export type DataFilter = (data: unknown) => NodeData[];
4
5
 
@@ -9,7 +10,7 @@ export type DragMethod = (node: Node, event: Event | Touch) => void;
9
10
  export type IconElement = HTMLElement | JQuery | string;
10
11
 
11
12
  export interface JQTreeOptions {
12
- animationSpeed: JQuery.Duration;
13
+ animationSpeed: AnimationSpeed;
13
14
  autoEscape: boolean;
14
15
  autoOpen: boolean | number;
15
16
  buttonLeft: boolean;
package/src/keyHandler.ts CHANGED
@@ -1,11 +1,11 @@
1
- import {
1
+ import type {
2
2
  CloseNode,
3
3
  GetSelectedNode,
4
4
  IsFocusOnTree,
5
5
  OpenNode,
6
6
  SelectNode,
7
7
  } from "./jqtreeMethodTypes";
8
- import { Node } from "./node";
8
+ import type { Node } from "./node";
9
9
 
10
10
  interface KeyHandlerParams {
11
11
  closeNode: CloseNode;
@@ -17,14 +17,14 @@ interface KeyHandlerParams {
17
17
  }
18
18
 
19
19
  export default class KeyHandler {
20
- private closeNode: CloseNode;
21
- private getSelectedNode: GetSelectedNode;
20
+ private _closeNode: CloseNode;
21
+ private _getSelectedNode: GetSelectedNode;
22
22
 
23
- private isFocusOnTree: IsFocusOnTree;
23
+ private _isFocusOnTree: IsFocusOnTree;
24
24
 
25
- private keyboardSupport: boolean;
26
- private openNode: OpenNode;
27
- private originalSelectNode: SelectNode;
25
+ private _keyboardSupport: boolean;
26
+ private _openNode: OpenNode;
27
+ private _originalSelectNode: SelectNode;
28
28
  constructor({
29
29
  closeNode,
30
30
  getSelectedNode,
@@ -33,44 +33,44 @@ export default class KeyHandler {
33
33
  openNode,
34
34
  selectNode,
35
35
  }: KeyHandlerParams) {
36
- this.closeNode = closeNode;
37
- this.getSelectedNode = getSelectedNode;
38
- this.isFocusOnTree = isFocusOnTree;
39
- this.keyboardSupport = keyboardSupport;
40
- this.openNode = openNode;
41
- this.originalSelectNode = selectNode;
36
+ this._closeNode = closeNode;
37
+ this._getSelectedNode = getSelectedNode;
38
+ this._isFocusOnTree = isFocusOnTree;
39
+ this._keyboardSupport = keyboardSupport;
40
+ this._openNode = openNode;
41
+ this._originalSelectNode = selectNode;
42
42
 
43
43
  if (keyboardSupport) {
44
- document.addEventListener("keydown", this.handleKeyDown);
44
+ document.addEventListener("keydown", this._handleKeyDown);
45
45
  }
46
46
  }
47
47
 
48
48
  public deinit(): void {
49
- if (this.keyboardSupport) {
50
- document.removeEventListener("keydown", this.handleKeyDown);
49
+ if (this._keyboardSupport) {
50
+ document.removeEventListener("keydown", this._handleKeyDown);
51
51
  }
52
52
  }
53
53
 
54
54
  public moveDown(selectedNode: Node): boolean {
55
- return this.selectNode(selectedNode.getNextVisibleNode());
55
+ return this._selectNode(selectedNode.getNextVisibleNode());
56
56
  }
57
57
 
58
58
  public moveUp(selectedNode: Node): boolean {
59
- return this.selectNode(selectedNode.getPreviousVisibleNode());
59
+ return this._selectNode(selectedNode.getPreviousVisibleNode());
60
60
  }
61
61
 
62
- private canHandleKeyboard(): boolean {
63
- return this.keyboardSupport && this.isFocusOnTree();
62
+ private _canHandleKeyboard(): boolean {
63
+ return this._keyboardSupport && this._isFocusOnTree();
64
64
  }
65
65
 
66
- private handleKeyDown = (e: KeyboardEvent): void => {
67
- if (!this.canHandleKeyboard()) {
66
+ private _handleKeyDown = (e: KeyboardEvent): void => {
67
+ if (!this._canHandleKeyboard()) {
68
68
  return;
69
69
  }
70
70
 
71
71
  let isKeyHandled = false;
72
72
 
73
- const selectedNode = this.getSelectedNode();
73
+ const selectedNode = this._getSelectedNode();
74
74
  if (selectedNode) {
75
75
  switch (e.key) {
76
76
  case "ArrowDown":
@@ -78,11 +78,11 @@ export default class KeyHandler {
78
78
  break;
79
79
 
80
80
  case "ArrowLeft":
81
- isKeyHandled = this.moveLeft(selectedNode);
81
+ isKeyHandled = this._moveLeft(selectedNode);
82
82
  break;
83
83
 
84
84
  case "ArrowRight":
85
- isKeyHandled = this.moveRight(selectedNode);
85
+ isKeyHandled = this._moveRight(selectedNode);
86
86
  break;
87
87
 
88
88
  case "ArrowUp":
@@ -96,28 +96,28 @@ export default class KeyHandler {
96
96
  }
97
97
  };
98
98
 
99
- private moveLeft(selectedNode: Node): boolean {
99
+ private _moveLeft(selectedNode: Node): boolean {
100
100
  if (selectedNode.isFolder() && selectedNode.is_open) {
101
101
  // Left on an open node closes the node
102
- this.closeNode(selectedNode);
102
+ this._closeNode(selectedNode);
103
103
  return true;
104
104
  } else {
105
105
  // Left on a closed or end node moves focus to the node's parent
106
- return this.selectNode(selectedNode.getParent());
106
+ return this._selectNode(selectedNode.getParent());
107
107
  }
108
108
  }
109
109
 
110
- private moveRight(selectedNode: Node): boolean {
110
+ private _moveRight(selectedNode: Node): boolean {
111
111
  if (!selectedNode.isFolder()) {
112
112
  return false;
113
113
  } else {
114
114
  // folder node
115
115
  if (selectedNode.is_open) {
116
116
  // Right moves to the first child of an open node
117
- return this.selectNode(selectedNode.getNextVisibleNode());
117
+ return this._selectNode(selectedNode.getNextVisibleNode());
118
118
  } else {
119
119
  // Right expands a closed node
120
- this.openNode(selectedNode);
120
+ this._openNode(selectedNode);
121
121
  return true;
122
122
  }
123
123
  }
@@ -127,11 +127,11 @@ export default class KeyHandler {
127
127
  * Don't do anything if the node is null.
128
128
  * Result: a different node was selected.
129
129
  */
130
- private selectNode(node: Node | null): boolean {
130
+ private _selectNode(node: Node | null): boolean {
131
131
  if (!node) {
132
132
  return false;
133
133
  } else {
134
- this.originalSelectNode(node);
134
+ this._originalSelectNode(node);
135
135
 
136
136
  return true;
137
137
  }