jqtree 1.8.11 → 1.9.1

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 (37) hide show
  1. package/bower.json +1 -1
  2. package/package.json +45 -51
  3. package/pnpm-workspace.yaml +5 -0
  4. package/src/animation.ts +48 -0
  5. package/src/dataLoader.ts +38 -48
  6. package/src/dragAndDropHandler/dragElement.ts +11 -11
  7. package/src/dragAndDropHandler/generateHitAreas.ts +4 -3
  8. package/src/dragAndDropHandler/index.ts +119 -120
  9. package/src/dragAndDropHandler/iterateVisibleNodes.ts +1 -1
  10. package/src/dragAndDropHandler/types.ts +1 -1
  11. package/src/elementsRenderer.ts +71 -78
  12. package/src/jqtreeMethodTypes.ts +2 -2
  13. package/src/jqtreeOptions.ts +3 -2
  14. package/src/keyHandler.ts +34 -34
  15. package/src/mouseHandler.ts +118 -119
  16. package/src/node.ts +22 -22
  17. package/src/nodeElement/borderDropHint.ts +6 -6
  18. package/src/nodeElement/folderElement.ts +33 -25
  19. package/src/nodeElement/ghostDropHint.ts +24 -24
  20. package/src/nodeElement/index.ts +19 -18
  21. package/src/positionUtils.ts +18 -0
  22. package/src/saveStateHandler.ts +56 -55
  23. package/src/scrollHandler/containerScrollParent.ts +24 -22
  24. package/src/scrollHandler/documentScrollParent.ts +29 -28
  25. package/src/scrollHandler/scrollParent.ts +41 -41
  26. package/src/scrollHandler.ts +23 -22
  27. package/src/selectNodeHandler.ts +28 -28
  28. package/src/tree.jquery.d.ts +3 -2
  29. package/src/tree.jquery.ts +456 -368
  30. package/src/util.ts +0 -14
  31. package/src/version.ts +1 -1
  32. package/tree.jquery.debug.js +1094 -973
  33. package/tree.jquery.debug.js.map +1 -1
  34. package/tree.jquery.js +2 -2
  35. package/tree.jquery.js.map +1 -1
  36. package/eslint.config.mjs +0 -98
  37. package/src/simple.widget.ts +0 -134
@@ -1,19 +1,22 @@
1
- import DataLoader, { HandleFinishedLoading } from "./dataLoader";
1
+ import type { HandleFinishedLoading } from "./dataLoader";
2
+ import type { OnFinishOpenNode } from "./jqtreeMethodTypes";
3
+ import type { JQTreeOptions } from "./jqtreeOptions";
4
+ import type { PositionInfo } from "./mouseUtils";
5
+ import type { Position } from "./node";
6
+ import type { SavedState } from "./saveStateHandler";
7
+
8
+ import DataLoader from "./dataLoader";
2
9
  import { DragAndDropHandler } from "./dragAndDropHandler";
3
10
  import ElementsRenderer from "./elementsRenderer";
4
- import { OnFinishOpenNode } from "./jqtreeMethodTypes";
5
- import { JQTreeOptions } from "./jqtreeOptions";
6
11
  import KeyHandler from "./keyHandler";
7
12
  import MouseHandler from "./mouseHandler";
8
- import { PositionInfo } from "./mouseUtils";
9
- import { Node, Position } from "./node";
13
+ import { Node } from "./node";
10
14
  import NodeElement from "./nodeElement";
11
15
  import FolderElement from "./nodeElement/folderElement";
12
- import SaveStateHandler, { SavedState } from "./saveStateHandler";
16
+ import { getOffsetTop } from "./positionUtils";
17
+ import SaveStateHandler from "./saveStateHandler";
13
18
  import ScrollHandler from "./scrollHandler";
14
19
  import SelectNodeHandler from "./selectNodeHandler";
15
- import SimpleWidget from "./simple.widget";
16
- import { getOffsetTop, isFunction } from "./util";
17
20
  import __version__ from "./version";
18
21
 
19
22
  interface SelectNodeOptions {
@@ -21,61 +24,70 @@ interface SelectNodeOptions {
21
24
  mustToggle?: boolean;
22
25
  }
23
26
 
27
+ const defaults: JQTreeOptions = {
28
+ animationSpeed: "fast",
29
+ autoEscape: true,
30
+ autoOpen: false, // true / false / int (open n levels starting at 0)
31
+ buttonLeft: true,
32
+ // The symbol to use for a closed node - ► BLACK RIGHT-POINTING POINTER
33
+ // http://www.fileformat.info/info/unicode/char/25ba/index.htm
34
+ closedIcon: undefined,
35
+ data: undefined,
36
+ dataFilter: undefined,
37
+ dataUrl: undefined,
38
+ dragAndDrop: false,
39
+ keyboardSupport: true,
40
+ nodeClass: Node,
41
+ onCanMove: undefined, // Can this node be moved?
42
+ onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)
43
+ onCanSelectNode: undefined,
44
+ onCreateLi: undefined,
45
+ onDragMove: undefined,
46
+ onDragStop: undefined,
47
+ onGetStateFromStorage: undefined,
48
+ onIsMoveHandle: undefined,
49
+ onLoadFailed: undefined,
50
+ onLoading: undefined,
51
+ onSetStateFromStorage: undefined,
52
+ openedIcon: "▼",
53
+ openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds
54
+ // The symbol to use for an open node - ▼ BLACK DOWN-POINTING TRIANGLE
55
+ // http://www.fileformat.info/info/unicode/char/25bc/index.htm
56
+ rtl: undefined, // right-to-left support; true / false (default)
57
+ saveState: false, // true / false / string (cookie name)
58
+ selectable: true,
59
+ showEmptyFolder: false,
60
+ slide: true, // must display slide animation?
61
+ startDndDelay: 300, // The delay for starting dnd (in milliseconds)
62
+ tabIndex: 0,
63
+ useContextMenu: true,
64
+ };
65
+
24
66
  const NODE_PARAM_IS_EMPTY = "Node parameter is empty";
25
67
  const PARAM_IS_EMPTY = "Parameter is empty: ";
26
68
 
27
- export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
28
- protected static defaults: JQTreeOptions = {
29
- animationSpeed: "fast",
30
- autoEscape: true,
31
- autoOpen: false, // true / false / int (open n levels starting at 0)
32
- buttonLeft: true,
33
- // The symbol to use for a closed node - ► BLACK RIGHT-POINTING POINTER
34
- // http://www.fileformat.info/info/unicode/char/25ba/index.htm
35
- closedIcon: undefined,
36
- data: undefined,
37
- dataFilter: undefined,
38
- dataUrl: undefined,
39
- dragAndDrop: false,
40
- keyboardSupport: true,
41
- nodeClass: Node,
42
- onCanMove: undefined, // Can this node be moved?
43
- onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)
44
- onCanSelectNode: undefined,
45
- onCreateLi: undefined,
46
- onDragMove: undefined,
47
- onDragStop: undefined,
48
- onGetStateFromStorage: undefined,
49
- onIsMoveHandle: undefined,
50
- onLoadFailed: undefined,
51
- onLoading: undefined,
52
- onSetStateFromStorage: undefined,
53
- openedIcon: "&#x25bc;",
54
- openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds
55
- // The symbol to use for an open node - ▼ BLACK DOWN-POINTING TRIANGLE
56
- // http://www.fileformat.info/info/unicode/char/25bc/index.htm
57
- rtl: undefined, // right-to-left support; true / false (default)
58
- saveState: false, // true / false / string (cookie name)
59
- selectable: true,
60
- showEmptyFolder: false,
61
- slide: true, // must display slide animation?
62
- startDndDelay: 300, // The delay for starting dnd (in milliseconds)
63
- tabIndex: 0,
64
- useContextMenu: true,
65
- };
66
-
67
- private dataLoader: DataLoader;
68
- private dndHandler: DragAndDropHandler;
69
- private element: JQuery;
70
-
71
- private isInitialized: boolean;
72
- private keyHandler: KeyHandler;
73
- private mouseHandler: MouseHandler;
74
- private renderer: ElementsRenderer;
75
- private saveStateHandler: SaveStateHandler;
76
- private scrollHandler: ScrollHandler;
77
- private selectNodeHandler: SelectNodeHandler;
78
- private tree: Node;
69
+ export class JqTreeWidget {
70
+ [key: string]: unknown;
71
+
72
+ private _dataLoader: DataLoader;
73
+ private _dndHandler: DragAndDropHandler;
74
+ private _element: JQuery;
75
+ private _htmlElement: HTMLElement;
76
+ private _isInitialized: boolean;
77
+ private _keyHandler: KeyHandler;
78
+ private _mouseHandler: MouseHandler;
79
+ private _options: JQTreeOptions;
80
+ private _renderer: ElementsRenderer;
81
+ private _saveStateHandler: SaveStateHandler;
82
+ private _scrollHandler: ScrollHandler;
83
+ private _selectNodeHandler: SelectNodeHandler;
84
+ private _tree: Node;
85
+
86
+ constructor(el: HTMLElement, options: Partial<JQTreeOptions>) {
87
+ this._htmlElement = el;
88
+ this._element = jQuery(el);
89
+ this._options = { ...defaults, ...options };
90
+ }
79
91
 
80
92
  public addNodeAfter(
81
93
  newNodeInfo: NodeData,
@@ -84,7 +96,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
84
96
  const newNode = existingNode.addAfter(newNodeInfo);
85
97
 
86
98
  if (newNode) {
87
- this.refreshElements(existingNode.parent);
99
+ this._refreshElements(existingNode.parent);
88
100
  }
89
101
 
90
102
  return newNode;
@@ -101,7 +113,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
101
113
  const newNode = existingNode.addBefore(newNodeInfo);
102
114
 
103
115
  if (newNode) {
104
- this.refreshElements(existingNode.parent);
116
+ this._refreshElements(existingNode.parent);
105
117
  }
106
118
 
107
119
  return newNode;
@@ -118,7 +130,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
118
130
  const newNode = existingNode.addParent(newNodeInfo);
119
131
 
120
132
  if (newNode) {
121
- this.refreshElements(newNode.parent);
133
+ this._refreshElements(newNode.parent);
122
134
  }
123
135
 
124
136
  return newNode;
@@ -129,22 +141,22 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
129
141
  throw Error(NODE_PARAM_IS_EMPTY);
130
142
  }
131
143
 
132
- this.selectNodeHandler.addToSelection(node);
133
- this.openParents(node);
144
+ this._selectNodeHandler.addToSelection(node);
145
+ this._openParents(node);
134
146
 
135
- this.getNodeElementForNode(node).select(mustSetFocus ?? true);
147
+ this._getNodeElementForNode(node).select(mustSetFocus ?? true);
136
148
 
137
- this.saveState();
149
+ this._saveState();
138
150
 
139
- return this.element;
151
+ return this._element;
140
152
  }
141
153
 
142
154
  public appendNode(newNodeInfo: NodeData, parentNodeParam?: Node): Node {
143
- const parentNode = parentNodeParam ?? this.tree;
155
+ const parentNode = parentNodeParam ?? this._tree;
144
156
 
145
157
  const node = parentNode.append(newNodeInfo);
146
158
 
147
- this.refreshElements(parentNode);
159
+ this._refreshElements(parentNode);
148
160
 
149
161
  return node;
150
162
  }
@@ -154,34 +166,36 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
154
166
  throw Error(NODE_PARAM_IS_EMPTY);
155
167
  }
156
168
 
157
- const slide = slideParam ?? this.options.slide;
169
+ const slide = slideParam ?? this._options.slide;
158
170
 
159
171
  if (node.isFolder() || node.isEmptyFolder) {
160
- this.createFolderElement(node).close(
172
+ this._createFolderElement(node).close(
161
173
  slide,
162
- this.options.animationSpeed,
174
+ this._options.animationSpeed,
163
175
  );
164
176
 
165
- this.saveState();
177
+ this._saveState();
166
178
  }
167
179
 
168
- return this.element;
180
+ return this._element;
169
181
  }
170
182
 
171
183
  public deinit(): void {
172
- this.element.empty();
173
- this.element.off();
184
+ this._htmlElement.textContent = "";
185
+ this._element.off();
174
186
 
175
- this.keyHandler.deinit();
176
- this.mouseHandler.deinit();
187
+ this._keyHandler.deinit();
188
+ this._mouseHandler.deinit();
177
189
 
178
- this.tree = new Node({}, true);
190
+ this._tree = new Node({}, true);
191
+ }
179
192
 
180
- super.deinit();
193
+ public destroy(): void {
194
+ this.deinit();
181
195
  }
182
196
 
183
197
  public getNodeByCallback(callback: (node: Node) => boolean): Node | null {
184
- return this.tree.getNodeByCallback(callback);
198
+ return this._tree.getNodeByCallback(callback);
185
199
  }
186
200
 
187
201
  public getNodeByHtmlElement(
@@ -196,43 +210,43 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
196
210
  return null;
197
211
  }
198
212
 
199
- return this.getNode(element);
213
+ return this._getNode(element);
200
214
  }
201
215
 
202
216
  public getNodeById(nodeId: NodeId): Node | null {
203
- return this.tree.getNodeById(nodeId);
217
+ return this._tree.getNodeById(nodeId);
204
218
  }
205
219
 
206
220
  public getNodeByName(name: string): Node | null {
207
- return this.tree.getNodeByName(name);
221
+ return this._tree.getNodeByName(name);
208
222
  }
209
223
 
210
224
  public getNodeByNameMustExist(name: string): Node {
211
- return this.tree.getNodeByNameMustExist(name);
225
+ return this._tree.getNodeByNameMustExist(name);
212
226
  }
213
227
 
214
228
  public getNodesByProperty(key: string, value: unknown): Node[] {
215
- return this.tree.getNodesByProperty(key, value);
229
+ return this._tree.getNodesByProperty(key, value);
216
230
  }
217
231
 
218
232
  public getSelectedNode(): false | Node {
219
- return this.selectNodeHandler.getSelectedNode();
233
+ return this._selectNodeHandler.getSelectedNode();
220
234
  }
221
235
 
222
236
  public getSelectedNodes(): Node[] {
223
- return this.selectNodeHandler.getSelectedNodes();
237
+ return this._selectNodeHandler.getSelectedNodes();
224
238
  }
225
239
 
226
240
  public getState(): null | SavedState {
227
- return this.saveStateHandler.getState();
241
+ return this._saveStateHandler.getState();
228
242
  }
229
243
 
230
244
  public getStateFromStorage(): null | SavedState {
231
- return this.saveStateHandler.getStateFromStorage();
245
+ return this._saveStateHandler.getStateFromStorage();
232
246
  }
233
247
 
234
248
  public getTree(): Node {
235
- return this.tree;
249
+ return this._tree;
236
250
  }
237
251
 
238
252
  public getVersion(): string {
@@ -240,22 +254,23 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
240
254
  }
241
255
 
242
256
  public init(): void {
243
- super.init();
257
+ const htmlElement = this._element.get(0) as HTMLElement;
258
+ this._htmlElement = htmlElement;
259
+ this._isInitialized = false;
244
260
 
245
- this.element = this.$el;
246
- this.isInitialized = false;
261
+ this._options.dataUrl ??= this._element.data("url");
247
262
 
248
- this.options.rtl = this.getRtlOption();
263
+ const dataRtl = this._element.data("rtl") as unknown;
264
+ this._options.rtl ??= dataRtl === '' ? true : Boolean(dataRtl);
249
265
 
250
- this.options.closedIcon ??= this.getDefaultClosedIcon();
266
+ this._options.closedIcon ??= this._getDefaultClosedIcon();
251
267
 
252
- this.connectHandlers();
253
-
254
- this.initData();
268
+ this._connectHandlers();
269
+ this._initData();
255
270
  }
256
271
 
257
272
  public isDragging(): boolean {
258
- return this.dndHandler.isDragging;
273
+ return this._dndHandler.isDragging;
259
274
  }
260
275
 
261
276
  public isNodeSelected(node?: Node): boolean {
@@ -263,12 +278,12 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
263
278
  throw Error(NODE_PARAM_IS_EMPTY);
264
279
  }
265
280
 
266
- return this.selectNodeHandler.isNodeSelected(node);
281
+ return this._selectNodeHandler.isNodeSelected(node);
267
282
  }
268
283
 
269
284
  public loadData(data: NodeData[], parentNode: Node | null): JQuery {
270
- this.doLoadData(data, parentNode);
271
- return this.element;
285
+ this._doLoadData(data, parentNode);
286
+ return this._element;
272
287
  }
273
288
 
274
289
  /*
@@ -292,30 +307,30 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
292
307
  ): JQuery {
293
308
  if (typeof param1 === "string") {
294
309
  // first parameter is url
295
- this.doLoadDataFromUrl(
310
+ this._doLoadDataFromUrl(
296
311
  param1,
297
312
  param2 as Node | null,
298
313
  param3 ?? null,
299
314
  );
300
315
  } else {
301
316
  // first parameter is not url
302
- this.doLoadDataFromUrl(
317
+ this._doLoadDataFromUrl(
303
318
  null,
304
319
  param1,
305
320
  param2 as HandleFinishedLoading | null,
306
321
  );
307
322
  }
308
323
 
309
- return this.element;
324
+ return this._element;
310
325
  }
311
326
 
312
327
  public moveDown(): JQuery {
313
328
  const selectedNode = this.getSelectedNode();
314
329
  if (selectedNode) {
315
- this.keyHandler.moveDown(selectedNode);
330
+ this._keyHandler.moveDown(selectedNode);
316
331
  }
317
332
 
318
- return this.element;
333
+ return this._element;
319
334
  }
320
335
 
321
336
  public moveNode(
@@ -335,19 +350,19 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
335
350
  throw Error(PARAM_IS_EMPTY + "position");
336
351
  }
337
352
 
338
- this.tree.moveNode(node, targetNode, position);
339
- this.refreshElements(null);
353
+ this._tree.moveNode(node, targetNode, position);
354
+ this._refreshElements(null);
340
355
 
341
- return this.element;
356
+ return this._element;
342
357
  }
343
358
 
344
359
  public moveUp(): JQuery {
345
360
  const selectedNode = this.getSelectedNode();
346
361
  if (selectedNode) {
347
- this.keyHandler.moveUp(selectedNode);
362
+ this._keyHandler.moveUp(selectedNode);
348
363
  }
349
364
 
350
- return this.element;
365
+ return this._element;
351
366
  }
352
367
 
353
368
  public openNode(
@@ -363,48 +378,43 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
363
378
  let onFinished: null | OnFinishOpenNode;
364
379
  let slide: boolean | null;
365
380
 
366
- if (isFunction(param1)) {
367
- onFinished = param1 as OnFinishOpenNode;
381
+ if (typeof param1 === "function") {
382
+ onFinished = param1;
368
383
  slide = null;
369
384
  } else {
370
385
  slide = param1 as boolean;
371
386
  onFinished = param2 as OnFinishOpenNode;
372
387
  }
373
388
 
374
- slide ??= this.options.slide;
389
+ slide ??= this._options.slide;
375
390
 
376
391
  return [slide, onFinished];
377
392
  };
378
393
 
379
394
  const [slide, onFinished] = parseParams();
380
395
 
381
- this.openNodeInternal(node, slide, onFinished);
382
- return this.element;
396
+ this._openNodeInternal(node, slide, onFinished);
397
+ return this._element;
383
398
  }
384
399
 
385
400
  public prependNode(newNodeInfo: NodeData, parentNodeParam?: Node): Node {
386
- const parentNode = parentNodeParam ?? this.tree;
401
+ const parentNode = parentNodeParam ?? this._tree;
387
402
 
388
403
  const node = parentNode.prepend(newNodeInfo);
389
404
 
390
- this.refreshElements(parentNode);
405
+ this._refreshElements(parentNode);
391
406
 
392
407
  return node;
393
408
  }
394
409
 
395
410
  public refresh(): JQuery {
396
- this.refreshElements(null);
397
- return this.element;
398
- }
399
-
400
- public refreshHitAreas(): JQuery {
401
- this.dndHandler.refresh();
402
- return this.element;
411
+ this._refreshElements(null);
412
+ return this._element;
403
413
  }
404
414
 
405
415
  public reload(onFinished: HandleFinishedLoading | null): JQuery {
406
- this.doLoadDataFromUrl(null, null, onFinished);
407
- return this.element;
416
+ this._doLoadDataFromUrl(null, null, onFinished);
417
+ return this._element;
408
418
  }
409
419
 
410
420
  public removeFromSelection(node?: Node): JQuery {
@@ -412,12 +422,12 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
412
422
  throw Error(NODE_PARAM_IS_EMPTY);
413
423
  }
414
424
 
415
- this.selectNodeHandler.removeFromSelection(node);
425
+ this._selectNodeHandler.removeFromSelection(node);
416
426
 
417
- this.getNodeElementForNode(node).deselect();
418
- this.saveState();
427
+ this._getNodeElementForNode(node).deselect();
428
+ this._saveState();
419
429
 
420
- return this.element;
430
+ return this._element;
421
431
  }
422
432
 
423
433
  public removeNode(node?: Node): JQuery {
@@ -429,13 +439,13 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
429
439
  throw Error("Node has no parent");
430
440
  }
431
441
 
432
- this.selectNodeHandler.removeFromSelection(node, true); // including children
442
+ this._selectNodeHandler.removeFromSelection(node, true); // including children
433
443
 
434
444
  const parent = node.parent;
435
445
  node.remove();
436
- this.refreshElements(parent);
446
+ this._refreshElements(parent);
437
447
 
438
- return this.element;
448
+ return this._element;
439
449
  }
440
450
 
441
451
  public scrollToNode(node?: Node): JQuery {
@@ -444,38 +454,38 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
444
454
  }
445
455
 
446
456
  if (!node.element) {
447
- return this.element;
457
+ return this._element;
448
458
  }
449
459
 
450
460
  const top =
451
461
  getOffsetTop(node.element) -
452
- getOffsetTop(this.$el.get(0) as HTMLElement);
462
+ getOffsetTop(this._htmlElement);
453
463
 
454
- this.scrollHandler.scrollToY(top);
464
+ this._scrollHandler.scrollToY(top);
455
465
 
456
- return this.element;
466
+ return this._element;
457
467
  }
458
468
 
459
469
  public selectNode(
460
470
  node: Node | null,
461
471
  optionsParam?: SelectNodeOptions,
462
472
  ): JQuery {
463
- this.doSelectNode(node, optionsParam);
464
- return this.element;
473
+ this._doSelectNode(node, optionsParam);
474
+ return this._element;
465
475
  }
466
476
 
467
477
  public setOption(option: string, value: unknown): JQuery {
468
- (this.options as unknown as Record<string, unknown>)[option] = value;
469
- return this.element;
478
+ (this._options as unknown as Record<string, unknown>)[option] = value;
479
+ return this._element;
470
480
  }
471
481
 
472
482
  public setState(state?: SavedState): JQuery {
473
483
  if (state) {
474
- this.saveStateHandler.setInitialState(state);
475
- this.refreshElements(null);
484
+ this._saveStateHandler.setInitialState(state);
485
+ this._refreshElements(null);
476
486
  }
477
487
 
478
- return this.element;
488
+ return this._element;
479
489
  }
480
490
 
481
491
  public toggle(node?: Node, slideParam: boolean | null = null): JQuery {
@@ -483,7 +493,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
483
493
  throw Error(NODE_PARAM_IS_EMPTY);
484
494
  }
485
495
 
486
- const slide = slideParam ?? this.options.slide;
496
+ const slide = slideParam ?? this._options.slide;
487
497
 
488
498
  if (node.is_open) {
489
499
  this.closeNode(node, slide);
@@ -491,11 +501,11 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
491
501
  this.openNode(node, slide);
492
502
  }
493
503
 
494
- return this.element;
504
+ return this._element;
495
505
  }
496
506
 
497
507
  public toJson(): string {
498
- return JSON.stringify(this.tree.getData());
508
+ return JSON.stringify(this._tree.getData());
499
509
  }
500
510
 
501
511
  public updateNode(node?: Node, data?: NodeData): JQuery {
@@ -504,20 +514,20 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
504
514
  }
505
515
 
506
516
  if (!data) {
507
- return this.element;
517
+ return this._element;
508
518
  }
509
519
 
510
520
  const idIsChanged =
511
521
  typeof data === "object" && data.id && data.id !== node.id;
512
522
 
513
523
  if (idIsChanged) {
514
- this.tree.removeNodeFromIndex(node);
524
+ this._tree.removeNodeFromIndex(node);
515
525
  }
516
526
 
517
527
  node.setData(data);
518
528
 
519
529
  if (idIsChanged) {
520
- this.tree.addNodeToIndex(node);
530
+ this._tree.addNodeToIndex(node);
521
531
  }
522
532
 
523
533
  if (
@@ -528,16 +538,16 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
528
538
  node.removeChildren();
529
539
 
530
540
  if (data.children.length) {
531
- node.loadFromData(data.children as Node[]);
541
+ node.loadFromData(data.children);
532
542
  }
533
543
  }
534
544
 
535
- this.refreshElements(node);
545
+ this._refreshElements(node);
536
546
 
537
- return this.element;
547
+ return this._element;
538
548
  }
539
549
 
540
- private connectHandlers() {
550
+ private _connectHandlers() {
541
551
  const {
542
552
  autoEscape,
543
553
  buttonLeft,
@@ -562,23 +572,21 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
562
572
  showEmptyFolder,
563
573
  slide,
564
574
  tabIndex,
565
- } = this.options;
575
+ } = this._options;
566
576
 
567
577
  const closeNode = this.closeNode.bind(this);
568
- const getNodeElement = this.getNodeElement.bind(this);
569
- const getNodeElementForNode = this.getNodeElementForNode.bind(this);
578
+ const getNodeElement = this._getNodeElement.bind(this);
579
+ const getNodeElementForNode = this._getNodeElementForNode.bind(this);
570
580
  const getNodeById = this.getNodeById.bind(this);
571
581
  const getSelectedNode = this.getSelectedNode.bind(this);
572
582
  const getTree = this.getTree.bind(this);
573
- const isFocusOnTree = this.isFocusOnTree.bind(this);
583
+ const isFocusOnTree = this._isFocusOnTree.bind(this);
574
584
  const loadData = this.loadData.bind(this);
575
- const openNode = this.openNodeInternal.bind(this);
576
- const refreshElements = this.refreshElements.bind(this);
577
- const refreshHitAreas = this.refreshHitAreas.bind(this);
585
+ const openNode = this._openNodeInternal.bind(this);
586
+ const refreshElements = this._refreshElements.bind(this);
578
587
  const selectNode = this.selectNode.bind(this);
579
- const $treeElement = this.element;
580
- const treeElement = this.element.get(0) as HTMLElement;
581
- const triggerEvent = this.triggerEvent.bind(this);
588
+ const treeElement = this._htmlElement;
589
+ const triggerEvent = this._triggerEvent.bind(this);
582
590
 
583
591
  const selectNodeHandler = new SelectNodeHandler({
584
592
  getNodeById,
@@ -592,7 +600,11 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
592
600
  selectNodeHandler.isNodeSelected.bind(selectNodeHandler);
593
601
  const removeFromSelection =
594
602
  selectNodeHandler.removeFromSelection.bind(selectNodeHandler);
595
- const getMouseDelay = () => this.options.startDndDelay ?? 0;
603
+ const getMouseDelay = () => this._options.startDndDelay ?? 0;
604
+
605
+ const refreshHitAreas = () => {
606
+ dndHandler.refresh();
607
+ }
596
608
 
597
609
  const dataLoader = new DataLoader({
598
610
  dataFilter,
@@ -652,12 +664,12 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
652
664
  });
653
665
 
654
666
  const renderer = new ElementsRenderer({
655
- $element: $treeElement,
656
667
  autoEscape,
657
668
  buttonLeft,
658
669
  closedIcon,
659
670
  dragAndDrop,
660
671
  getTree,
672
+ htmlElement: treeElement,
661
673
  isNodeSelected,
662
674
  onCreateLi,
663
675
  openedIcon,
@@ -666,51 +678,44 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
666
678
  tabIndex,
667
679
  });
668
680
 
669
- const getNode = this.getNode.bind(this);
670
- const onMouseCapture = this.mouseCapture.bind(this);
671
- const onMouseDrag = this.mouseDrag.bind(this);
672
- const onMouseStart = this.mouseStart.bind(this);
673
- const onMouseStop = this.mouseStop.bind(this);
681
+ const getNode = this._getNode.bind(this);
682
+ const onMouseCapture = this._mouseCapture.bind(this);
683
+ const onMouseDrag = this._mouseDrag.bind(this);
684
+ const onMouseStart = this._mouseStart.bind(this);
685
+ const onMouseStop = this._mouseStop.bind(this);
674
686
 
675
687
  const mouseHandler = new MouseHandler({
676
688
  element: treeElement,
677
689
  getMouseDelay,
678
690
  getNode,
679
691
  onClickButton: this.toggle.bind(this),
680
- onClickTitle: this.doSelectNode.bind(this),
692
+ onClickTitle: this._doSelectNode.bind(this),
681
693
  onMouseCapture,
682
694
  onMouseDrag,
683
695
  onMouseStart,
684
696
  onMouseStop,
685
697
  triggerEvent,
686
- useContextMenu: this.options.useContextMenu,
698
+ useContextMenu: this._options.useContextMenu,
687
699
  });
688
700
 
689
- this.dataLoader = dataLoader;
690
- this.dndHandler = dndHandler;
691
- this.keyHandler = keyHandler;
692
- this.mouseHandler = mouseHandler;
693
- this.renderer = renderer;
694
- this.saveStateHandler = saveStateHandler;
695
- this.scrollHandler = scrollHandler;
696
- this.selectNodeHandler = selectNodeHandler;
701
+ this._dataLoader = dataLoader;
702
+ this._dndHandler = dndHandler;
703
+ this._keyHandler = keyHandler;
704
+ this._mouseHandler = mouseHandler;
705
+ this._renderer = renderer;
706
+ this._saveStateHandler = saveStateHandler;
707
+ this._scrollHandler = scrollHandler;
708
+ this._selectNodeHandler = selectNodeHandler;
697
709
  }
698
710
 
699
- private containsElement(element: HTMLElement): boolean {
700
- const node = this.getNode(element);
701
-
702
- return node?.tree === this.tree;
703
- }
704
-
705
- private createFolderElement(node: Node) {
706
- const closedIconElement = this.renderer.closedIconElement;
707
- const getScrollLeft = this.scrollHandler.getScrollLeft.bind(
708
- this.scrollHandler,
711
+ private _createFolderElement(node: Node) {
712
+ const closedIconElement = this._renderer.closedIconElement;
713
+ const getScrollLeft = this._scrollHandler.getScrollLeft.bind(
714
+ this._scrollHandler,
709
715
  );
710
- const openedIconElement = this.renderer.openedIconElement;
711
- const tabIndex = this.options.tabIndex;
712
- const treeElement = this.element.get(0) as HTMLElement;
713
- const triggerEvent = this.triggerEvent.bind(this);
716
+ const openedIconElement = this._renderer.openedIconElement;
717
+ const tabIndex = this._options.tabIndex;
718
+ const triggerEvent = this._triggerEvent.bind(this);
714
719
 
715
720
  return new FolderElement({
716
721
  closedIconElement,
@@ -718,84 +723,83 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
718
723
  node,
719
724
  openedIconElement,
720
725
  tabIndex,
721
- treeElement,
726
+ treeElement: this._htmlElement,
722
727
  triggerEvent,
723
728
  });
724
729
  }
725
730
 
726
- private createNodeElement(node: Node) {
727
- const getScrollLeft = this.scrollHandler.getScrollLeft.bind(
728
- this.scrollHandler,
731
+ private _createNodeElement(node: Node) {
732
+ const getScrollLeft = this._scrollHandler.getScrollLeft.bind(
733
+ this._scrollHandler,
729
734
  );
730
- const tabIndex = this.options.tabIndex;
731
- const treeElement = this.element.get(0) as HTMLElement;
735
+ const tabIndex = this._options.tabIndex;
732
736
 
733
737
  return new NodeElement({
734
738
  getScrollLeft,
735
739
  node,
736
740
  tabIndex,
737
- treeElement,
741
+ treeElement: this._htmlElement
738
742
  });
739
743
  }
740
744
 
741
- private deselectCurrentNode(): void {
745
+ private _deselectCurrentNode(): void {
742
746
  const node = this.getSelectedNode();
743
747
  if (node) {
744
748
  this.removeFromSelection(node);
745
749
  }
746
750
  }
747
751
 
748
- private deselectNodes(parentNode: Node): void {
752
+ private _deselectNodes(parentNode: Node): void {
749
753
  const selectedNodesUnderParent =
750
- this.selectNodeHandler.getSelectedNodesUnder(parentNode);
754
+ this._selectNodeHandler.getSelectedNodesUnder(parentNode);
751
755
  for (const n of selectedNodesUnderParent) {
752
- this.selectNodeHandler.removeFromSelection(n);
756
+ this._selectNodeHandler.removeFromSelection(n);
753
757
  }
754
758
  }
755
759
 
756
- private doLoadData(data: NodeData[] | null, parentNode: Node | null): void {
760
+ private _doLoadData(data: NodeData[] | null, parentNode: Node | null): void {
757
761
  if (data) {
758
762
  if (parentNode) {
759
- this.deselectNodes(parentNode);
760
- this.loadSubtree(data, parentNode);
763
+ this._deselectNodes(parentNode);
764
+ this._loadSubtree(data, parentNode);
761
765
  } else {
762
- this.initTree(data);
766
+ this._initTree(data);
763
767
  }
764
768
 
765
769
  if (this.isDragging()) {
766
- this.dndHandler.refresh();
770
+ this._dndHandler.refresh();
767
771
  }
768
772
  }
769
773
 
770
- this.triggerEvent("tree.load_data", {
774
+ this._triggerEvent("tree.load_data", {
771
775
  parent_node: parentNode,
772
776
  tree_data: data,
773
777
  });
774
778
  }
775
779
 
776
- private doLoadDataFromUrl(
780
+ private _doLoadDataFromUrl(
777
781
  urlInfoParam: JQuery.AjaxSettings | null | string,
778
782
  parentNode: Node | null,
779
783
  onFinished: HandleFinishedLoading | null,
780
784
  ): void {
781
- const urlInfo = urlInfoParam ?? this.getDataUrlInfo(parentNode);
785
+ const urlInfo = urlInfoParam ?? this._getDataUrlInfo(parentNode);
782
786
 
783
- this.dataLoader.loadFromUrl(urlInfo, parentNode, onFinished);
787
+ this._dataLoader.loadFromUrl(urlInfo, parentNode, onFinished);
784
788
  }
785
789
 
786
- private doSelectNode(
790
+ private _doSelectNode(
787
791
  node: Node | null,
788
792
  optionsParam?: SelectNodeOptions,
789
793
  ): void {
790
794
  const saveState = (): void => {
791
- if (this.options.saveState) {
792
- this.saveStateHandler.saveState();
795
+ if (this._options.saveState) {
796
+ this._saveStateHandler.saveState();
793
797
  }
794
798
  };
795
799
 
796
800
  if (!node) {
797
801
  // Called with empty node -> deselect current node
798
- this.deselectCurrentNode();
802
+ this._deselectCurrentNode();
799
803
  saveState();
800
804
  return;
801
805
  }
@@ -803,13 +807,13 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
803
807
  const selectOptions = { ...defaultOptions, ...(optionsParam ?? {}) };
804
808
 
805
809
  const canSelect = (): boolean => {
806
- if (this.options.onCanSelectNode) {
810
+ if (this._options.onCanSelectNode) {
807
811
  return (
808
- this.options.selectable &&
809
- this.options.onCanSelectNode(node)
812
+ this._options.selectable &&
813
+ this._options.onCanSelectNode(node)
810
814
  );
811
815
  } else {
812
- return this.options.selectable;
816
+ return this._options.selectable;
813
817
  }
814
818
  };
815
819
 
@@ -817,45 +821,42 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
817
821
  return;
818
822
  }
819
823
 
820
- if (this.selectNodeHandler.isNodeSelected(node)) {
824
+ if (this._selectNodeHandler.isNodeSelected(node)) {
821
825
  if (selectOptions.mustToggle) {
822
- this.deselectCurrentNode();
823
- this.triggerEvent("tree.select", {
826
+ this._deselectCurrentNode();
827
+ this._triggerEvent("tree.select", {
824
828
  node: null,
825
829
  previous_node: node,
826
830
  });
827
831
  }
828
832
  } else {
829
833
  const deselectedNode = this.getSelectedNode() || null;
830
- this.deselectCurrentNode();
834
+ this._deselectCurrentNode();
831
835
  this.addToSelection(node, selectOptions.mustSetFocus);
832
836
 
833
- this.triggerEvent("tree.select", {
837
+ this._triggerEvent("tree.select", {
834
838
  deselected_node: deselectedNode,
835
839
  node,
836
840
  });
837
- this.openParents(node);
841
+ this._openParents(node);
838
842
  }
839
843
 
840
844
  saveState();
841
845
  }
842
846
 
843
- private getAutoOpenMaxLevel(): number {
844
- if (this.options.autoOpen === true) {
847
+ private _getAutoOpenMaxLevel(): number {
848
+ if (this._options.autoOpen === true) {
845
849
  return -1;
846
- } else if (typeof this.options.autoOpen === "number") {
847
- return this.options.autoOpen;
848
- } else if (typeof this.options.autoOpen === "string") {
849
- return parseInt(this.options.autoOpen, 10);
850
+ } else if (typeof this._options.autoOpen === "number") {
851
+ return this._options.autoOpen;
852
+ } else if (typeof this._options.autoOpen === "string") {
853
+ return parseInt(this._options.autoOpen, 10);
850
854
  } else {
851
855
  return 0;
852
856
  }
853
857
  }
854
858
 
855
- private getDataUrlInfo(node: Node | null): JQuery.AjaxSettings | null {
856
- const dataUrl =
857
- this.options.dataUrl ?? (this.element.data("url") as null | string);
858
-
859
+ private _getDataUrlInfo(node: Node | null): JQuery.AjaxSettings | null {
859
860
  const getUrlFromString = (url: string): JQuery.AjaxSettings => {
860
861
  const urlInfo: JQuery.AjaxSettings = { url };
861
862
 
@@ -871,7 +872,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
871
872
  urlInfo.data = data;
872
873
  } else {
873
874
  // Add selected_node parameter
874
- const selectedNodeId = this.getNodeIdToBeSelected();
875
+ const selectedNodeId = this._getNodeIdToBeSelected();
875
876
  if (selectedNodeId) {
876
877
  const data = { selected_node: selectedNodeId };
877
878
  urlInfo.data = data;
@@ -879,6 +880,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
879
880
  }
880
881
  };
881
882
 
883
+ const dataUrl = this._options.dataUrl;
882
884
  if (typeof dataUrl === "function") {
883
885
  return dataUrl(node);
884
886
  } else if (typeof dataUrl === "string") {
@@ -891,8 +893,8 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
891
893
  }
892
894
  }
893
895
 
894
- private getDefaultClosedIcon(): string {
895
- if (this.options.rtl) {
896
+ private _getDefaultClosedIcon(): string {
897
+ if (this._options.rtl) {
896
898
  // triangle to the left
897
899
  return "&#x25c0;";
898
900
  } else {
@@ -901,7 +903,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
901
903
  }
902
904
  }
903
905
 
904
- private getNode(element: HTMLElement): Node | null {
906
+ private _getNode(element: HTMLElement): Node | null {
905
907
  const liElement = element.closest("li.jqtree_common");
906
908
 
907
909
  if (liElement) {
@@ -911,100 +913,95 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
911
913
  }
912
914
  }
913
915
 
914
- private getNodeElement(element: HTMLElement): NodeElement | null {
915
- const node = this.getNode(element);
916
+ private _getNodeElement(element: HTMLElement): NodeElement | null {
917
+ const node = this._getNode(element);
916
918
  if (node) {
917
- return this.getNodeElementForNode(node);
919
+ return this._getNodeElementForNode(node);
918
920
  } else {
919
921
  return null;
920
922
  }
921
923
  }
922
924
 
923
- private getNodeElementForNode(node: Node): NodeElement {
925
+ private _getNodeElementForNode(node: Node): NodeElement {
924
926
  if (node.isFolder()) {
925
- return this.createFolderElement(node);
927
+ return this._createFolderElement(node);
926
928
  } else {
927
- return this.createNodeElement(node);
929
+ return this._createNodeElement(node);
928
930
  }
929
931
  }
930
932
 
931
- private getNodeIdToBeSelected(): NodeId | null {
932
- if (this.options.saveState) {
933
- return this.saveStateHandler.getNodeIdToBeSelected();
933
+ private _getNodeIdToBeSelected(): NodeId | null {
934
+ if (this._options.saveState) {
935
+ return this._saveStateHandler.getNodeIdToBeSelected();
934
936
  } else {
935
937
  return null;
936
938
  }
937
939
  }
938
940
 
939
- private getRtlOption(): boolean {
940
- if (this.options.rtl != null) {
941
- return this.options.rtl;
941
+ private _initData(): void {
942
+ if (this._options.data) {
943
+ this._doLoadData(this._options.data, null);
942
944
  } else {
943
- const dataRtl = this.element.data("rtl") as unknown;
944
-
945
- if (
946
- dataRtl !== null &&
947
- dataRtl !== false &&
948
- dataRtl !== undefined
949
- ) {
950
- return true;
951
- } else {
952
- return false;
953
- }
954
- }
955
- }
956
-
957
- private initData(): void {
958
- if (this.options.data) {
959
- this.doLoadData(this.options.data, null);
960
- } else {
961
- const dataUrl = this.getDataUrlInfo(null);
945
+ const dataUrl = this._getDataUrlInfo(null);
962
946
 
963
947
  if (dataUrl) {
964
- this.doLoadDataFromUrl(null, null, null);
948
+ this._doLoadDataFromUrl(null, null, null);
965
949
  } else {
966
- this.doLoadData([], null);
950
+ this._doLoadData([], null);
967
951
  }
968
952
  }
969
953
  }
970
954
 
971
- private initTree(data: NodeData[]): void {
955
+ private _initTree(data: NodeData[]): void {
972
956
  const doInit = (): void => {
973
- if (!this.isInitialized) {
974
- this.isInitialized = true;
975
- this.triggerEvent("tree.init");
957
+ if (!this._isInitialized) {
958
+ this._isInitialized = true;
959
+ this._triggerEvent("tree.init");
976
960
  }
977
961
  };
978
962
 
979
- this.tree = new this.options.nodeClass(
963
+ this._tree = new this._options.nodeClass(
980
964
  null,
981
965
  true,
982
- this.options.nodeClass,
966
+ this._options.nodeClass,
983
967
  );
984
968
 
985
- this.selectNodeHandler.clear();
969
+ this._selectNodeHandler.clear();
986
970
 
987
- this.tree.loadFromData(data);
971
+ this._tree.loadFromData(data);
988
972
 
989
- const mustLoadOnDemand = this.setInitialState();
973
+ const mustLoadOnDemand = this._setInitialState();
990
974
 
991
- this.refreshElements(null);
975
+ this._refreshElements(null);
992
976
 
993
- if (!mustLoadOnDemand) {
994
- doInit();
995
- } else {
977
+ if (mustLoadOnDemand) {
996
978
  // Load data on demand and then init the tree
997
- this.setInitialStateOnDemand(doInit);
979
+ this._setInitialStateOnDemand(doInit);
980
+ } else {
981
+ doInit();
998
982
  }
999
983
  }
1000
984
 
1001
- private isFocusOnTree(): boolean {
985
+ // Does an element in the tree have the focus?
986
+ private _isFocusOnTree(): boolean {
1002
987
  const activeElement = document.activeElement;
1003
988
 
1004
- return activeElement?.tagName === "SPAN" && this.containsElement(activeElement as HTMLElement);
989
+ /* istanbul ignore if */
990
+ if (!activeElement) {
991
+ return false;
992
+ }
993
+
994
+ // The keyboard must still work for input elements.
995
+ const tagName = activeElement.tagName;
996
+ if (tagName !== "A" && tagName !== "SPAN") {
997
+ return false;
998
+ }
999
+
1000
+ const node = this._getNode(activeElement as HTMLElement);
1001
+ return node?.tree === this._tree;
1005
1002
  }
1006
1003
 
1007
- private isSelectedNodeInSubtree(subtree: Node): boolean {
1004
+ private _isSelectedNodeInSubtree(subtree: Node): boolean {
1008
1005
  const selectedNode = this.getSelectedNode();
1009
1006
 
1010
1007
  if (!selectedNode) {
@@ -1014,64 +1011,66 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1014
1011
  }
1015
1012
  }
1016
1013
 
1017
- private loadFolderOnDemand(
1014
+ private _loadFolderOnDemand(
1018
1015
  node: Node,
1019
1016
  slide = true,
1020
1017
  onFinished?: OnFinishOpenNode,
1021
1018
  ): void {
1022
1019
  node.is_loading = true;
1023
1020
 
1024
- this.doLoadDataFromUrl(null, node, () => {
1025
- this.openNodeInternal(node, slide, onFinished);
1021
+ this._doLoadDataFromUrl(null, node, () => {
1022
+ this._openNodeInternal(node, slide, onFinished);
1026
1023
  });
1027
1024
  }
1028
1025
 
1029
- private loadSubtree(data: NodeData[], parentNode: Node): void {
1026
+ private _loadSubtree(data: NodeData[], parentNode: Node): void {
1030
1027
  parentNode.loadFromData(data);
1031
1028
 
1032
1029
  parentNode.load_on_demand = false;
1033
1030
  parentNode.is_loading = false;
1034
1031
 
1035
- this.refreshElements(parentNode);
1032
+ this._refreshElements(parentNode);
1036
1033
  }
1037
1034
 
1038
- private mouseCapture(positionInfo: PositionInfo): boolean | null {
1039
- if (this.options.dragAndDrop) {
1040
- return this.dndHandler.mouseCapture(positionInfo);
1041
- } else {
1035
+ private _mouseCapture(positionInfo: PositionInfo): boolean | null {
1036
+ if (!this._options.dragAndDrop) {
1042
1037
  return false;
1043
1038
  }
1044
- }
1045
1039
 
1046
- private mouseDrag(positionInfo: PositionInfo): boolean {
1047
- if (this.options.dragAndDrop) {
1048
- const result = this.dndHandler.mouseDrag(positionInfo);
1040
+ return this._dndHandler.mouseCapture(positionInfo);
1041
+ }
1049
1042
 
1050
- this.scrollHandler.checkScrolling(positionInfo);
1051
- return result;
1052
- } else {
1043
+ private _mouseDrag(positionInfo: PositionInfo): boolean {
1044
+ /* istanbul ignore if */
1045
+ if (!this._options.dragAndDrop) {
1053
1046
  return false;
1054
1047
  }
1048
+
1049
+ const result = this._dndHandler.mouseDrag(positionInfo);
1050
+ this._scrollHandler.checkScrolling(positionInfo);
1051
+ return result;
1055
1052
  }
1056
1053
 
1057
- private mouseStart(positionInfo: PositionInfo): boolean {
1058
- if (this.options.dragAndDrop) {
1059
- return this.dndHandler.mouseStart(positionInfo);
1060
- } else {
1054
+ private _mouseStart(positionInfo: PositionInfo): boolean {
1055
+ /* istanbul ignore if */
1056
+ if (!this._options.dragAndDrop) {
1061
1057
  return false;
1062
1058
  }
1059
+
1060
+ return this._dndHandler.mouseStart(positionInfo);
1063
1061
  }
1064
1062
 
1065
- private mouseStop(positionInfo: PositionInfo): boolean {
1066
- if (this.options.dragAndDrop) {
1067
- this.scrollHandler.stopScrolling();
1068
- return this.dndHandler.mouseStop(positionInfo);
1069
- } else {
1063
+ private _mouseStop(positionInfo: PositionInfo): boolean {
1064
+ /* istanbul ignore if */
1065
+ if (!this._options.dragAndDrop) {
1070
1066
  return false;
1071
1067
  }
1068
+
1069
+ this._scrollHandler.stopScrolling();
1070
+ return this._dndHandler.mouseStop(positionInfo);
1072
1071
  }
1073
1072
 
1074
- private openNodeInternal(
1073
+ private _openNodeInternal(
1075
1074
  node: Node,
1076
1075
  slide = true,
1077
1076
  onFinished?: OnFinishOpenNode,
@@ -1085,17 +1084,17 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1085
1084
  return;
1086
1085
  }
1087
1086
 
1088
- const folderElement = this.createFolderElement(_node);
1087
+ const folderElement = this._createFolderElement(_node);
1089
1088
  folderElement.open(
1090
1089
  _onFinished,
1091
1090
  _slide,
1092
- this.options.animationSpeed,
1091
+ this._options.animationSpeed,
1093
1092
  );
1094
1093
  };
1095
1094
 
1096
1095
  if (node.isFolder() || node.isEmptyFolder) {
1097
1096
  if (node.load_on_demand) {
1098
- this.loadFolderOnDemand(node, slide, onFinished);
1097
+ this._loadFolderOnDemand(node, slide, onFinished);
1099
1098
  } else {
1100
1099
  let parent = node.parent;
1101
1100
 
@@ -1108,12 +1107,12 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1108
1107
  }
1109
1108
 
1110
1109
  doOpenNode(node, slide, onFinished);
1111
- this.saveState();
1110
+ this._saveState();
1112
1111
  }
1113
1112
  }
1114
1113
  }
1115
1114
 
1116
- private openParents(node: Node) {
1115
+ private _openParents(node: Node) {
1117
1116
  const parent = node.parent;
1118
1117
 
1119
1118
  if (parent?.parent && !parent.is_open) {
@@ -1125,50 +1124,50 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1125
1124
  Redraw the tree or part of the tree.
1126
1125
  from_node: redraw this subtree
1127
1126
  */
1128
- private refreshElements(fromNode: Node | null): void {
1129
- const mustSetFocus = this.isFocusOnTree();
1127
+ private _refreshElements(fromNode: Node | null): void {
1128
+ const mustSetFocus = this._isFocusOnTree();
1130
1129
  const mustSelect = fromNode
1131
- ? this.isSelectedNodeInSubtree(fromNode)
1130
+ ? this._isSelectedNodeInSubtree(fromNode)
1132
1131
  : false;
1133
1132
 
1134
- this.renderer.render(fromNode);
1133
+ this._renderer.render(fromNode);
1135
1134
 
1136
1135
  if (mustSelect) {
1137
- this.selectCurrentNode(mustSetFocus);
1136
+ this._selectCurrentNode(mustSetFocus);
1138
1137
  }
1139
1138
 
1140
- this.triggerEvent("tree.refresh");
1139
+ this._triggerEvent("tree.refresh");
1141
1140
  }
1142
1141
 
1143
- private saveState(): void {
1144
- if (this.options.saveState) {
1145
- this.saveStateHandler.saveState();
1142
+ private _saveState(): void {
1143
+ if (this._options.saveState) {
1144
+ this._saveStateHandler.saveState();
1146
1145
  }
1147
1146
  }
1148
1147
 
1149
- private selectCurrentNode(mustSetFocus: boolean): void {
1148
+ private _selectCurrentNode(mustSetFocus: boolean): void {
1150
1149
  const node = this.getSelectedNode();
1151
1150
  if (node) {
1152
- const nodeElement = this.getNodeElementForNode(node);
1151
+ const nodeElement = this._getNodeElementForNode(node);
1153
1152
  nodeElement.select(mustSetFocus);
1154
1153
  }
1155
1154
  }
1156
1155
 
1157
1156
  // Set initial state, either by restoring the state or auto-opening nodes
1158
1157
  // result: must load nodes on demand?
1159
- private setInitialState(): boolean {
1158
+ private _setInitialState(): boolean {
1160
1159
  const restoreState = (): [boolean, boolean] => {
1161
1160
  // result: is state restored, must load on demand?
1162
- if (!this.options.saveState) {
1161
+ if (!this._options.saveState) {
1163
1162
  return [false, false];
1164
1163
  } else {
1165
- const state = this.saveStateHandler.getStateFromStorage();
1164
+ const state = this._saveStateHandler.getStateFromStorage();
1166
1165
 
1167
1166
  if (!state) {
1168
1167
  return [false, false];
1169
1168
  } else {
1170
1169
  const mustLoadOnDemand =
1171
- this.saveStateHandler.setInitialState(state);
1170
+ this._saveStateHandler.setInitialState(state);
1172
1171
 
1173
1172
  // return true: the state is restored
1174
1173
  return [true, mustLoadOnDemand];
@@ -1178,14 +1177,14 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1178
1177
 
1179
1178
  const autoOpenNodes = (): boolean => {
1180
1179
  // result: must load on demand?
1181
- if (this.options.autoOpen === false) {
1180
+ if (this._options.autoOpen === false) {
1182
1181
  return false;
1183
1182
  }
1184
1183
 
1185
- const maxLevel = this.getAutoOpenMaxLevel();
1184
+ const maxLevel = this._getAutoOpenMaxLevel();
1186
1185
  let mustLoadOnDemand = false;
1187
1186
 
1188
- this.tree.iterate((node: Node, level: number) => {
1187
+ this._tree.iterate((node: Node, level: number) => {
1189
1188
  if (node.load_on_demand) {
1190
1189
  mustLoadOnDemand = true;
1191
1190
  return false;
@@ -1211,40 +1210,36 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1211
1210
 
1212
1211
  // Set the initial state for nodes that are loaded on demand
1213
1212
  // Call cb_finished when done
1214
- private setInitialStateOnDemand(cbFinished: () => void): void {
1213
+ private _setInitialStateOnDemand(cbFinished: () => void): void {
1215
1214
  const restoreState = (): boolean => {
1216
- if (!this.options.saveState) {
1215
+ const state = this._saveStateHandler.getStateFromStorage();
1216
+
1217
+ if (!state) {
1217
1218
  return false;
1218
1219
  } else {
1219
- const state = this.saveStateHandler.getStateFromStorage();
1220
-
1221
- if (!state) {
1222
- return false;
1223
- } else {
1224
- this.saveStateHandler.setInitialStateOnDemand(
1225
- state,
1226
- cbFinished,
1227
- );
1220
+ this._saveStateHandler.setInitialStateOnDemand(
1221
+ state,
1222
+ cbFinished,
1223
+ );
1228
1224
 
1229
- return true;
1230
- }
1225
+ return true;
1231
1226
  }
1232
1227
  };
1233
1228
 
1234
1229
  const autoOpenNodes = (): void => {
1235
- const maxLevel = this.getAutoOpenMaxLevel();
1230
+ const maxLevel = this._getAutoOpenMaxLevel();
1236
1231
  let loadingCount = 0;
1237
1232
 
1238
1233
  const loadAndOpenNode = (node: Node): void => {
1239
1234
  loadingCount += 1;
1240
- this.openNodeInternal(node, false, () => {
1235
+ this._openNodeInternal(node, false, () => {
1241
1236
  loadingCount -= 1;
1242
1237
  openNodes();
1243
1238
  });
1244
1239
  };
1245
1240
 
1246
1241
  const openNodes = (): void => {
1247
- this.tree.iterate((node: Node, level: number) => {
1242
+ this._tree.iterate((node: Node, level: number) => {
1248
1243
  if (node.load_on_demand) {
1249
1244
  if (!node.is_loading) {
1250
1245
  loadAndOpenNode(node);
@@ -1252,7 +1247,7 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1252
1247
 
1253
1248
  return false;
1254
1249
  } else {
1255
- this.openNodeInternal(node, false);
1250
+ this._openNodeInternal(node, false);
1256
1251
 
1257
1252
  return level !== maxLevel;
1258
1253
  }
@@ -1271,14 +1266,107 @@ export class JqTreeWidget extends SimpleWidget<JQTreeOptions> {
1271
1266
  }
1272
1267
  }
1273
1268
 
1274
- private triggerEvent(
1269
+ private _triggerEvent(
1275
1270
  eventName: string,
1276
1271
  values?: Record<string, unknown>,
1277
- ): JQuery.Event {
1272
+ ): boolean {
1278
1273
  const event = jQuery.Event(eventName, values);
1279
- this.element.trigger(event);
1280
- return event;
1274
+ this._element.trigger(event);
1275
+ return !event.isDefaultPrevented();
1281
1276
  }
1282
1277
  }
1283
1278
 
1284
- SimpleWidget.register(JqTreeWidget, "tree");
1279
+ const register = (): void => {
1280
+ const getWidgetData = (
1281
+ el: HTMLElement,
1282
+ dataKey: string,
1283
+ ): JqTreeWidget | null => {
1284
+ const widget = jQuery.data(el, dataKey) as unknown;
1285
+
1286
+ if (widget && widget instanceof JqTreeWidget) {
1287
+ return widget;
1288
+ } else {
1289
+ return null;
1290
+ }
1291
+ };
1292
+
1293
+ const createWidget = ($el: JQuery, options: null | Partial<JQTreeOptions>): JQuery => {
1294
+ for (const el of $el.get()) {
1295
+ const existingWidget = getWidgetData(el, "jqtree");
1296
+
1297
+ if (!existingWidget) {
1298
+ const widget = new JqTreeWidget(el, options ?? {});
1299
+
1300
+ if (!jQuery.data(el, "jqtree")) {
1301
+ jQuery.data(el, "jqtree", widget);
1302
+ }
1303
+
1304
+ // Call init after setting data, so we can call methods
1305
+ widget.init();
1306
+ }
1307
+ }
1308
+
1309
+ return $el;
1310
+ };
1311
+
1312
+ const destroyWidget = ($el: JQuery): void => {
1313
+ for (const el of $el.get()) {
1314
+ const widget = getWidgetData(el, "jqtree");
1315
+
1316
+ if (widget) {
1317
+ widget.destroy();
1318
+ }
1319
+
1320
+ jQuery.removeData(el, "jqtree");
1321
+ }
1322
+ };
1323
+
1324
+ const callFunction = (
1325
+ $el: JQuery,
1326
+ functionName: string,
1327
+ args: unknown[],
1328
+ ): unknown => {
1329
+ let result = null;
1330
+
1331
+ for (const el of $el.get()) {
1332
+ const widget = jQuery.data(el, "jqtree") as unknown;
1333
+
1334
+ if (widget && widget instanceof JqTreeWidget) {
1335
+ const widgetFunction = widget[functionName];
1336
+
1337
+ if (widgetFunction && typeof widgetFunction === "function") {
1338
+ result = widgetFunction.apply(widget, args) as unknown;
1339
+ }
1340
+ }
1341
+ }
1342
+
1343
+ return result;
1344
+ };
1345
+
1346
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1347
+ (jQuery.fn as any).tree = function (
1348
+ this: JQuery,
1349
+ argument1: unknown,
1350
+ ...args: unknown[]
1351
+ ) {
1352
+ if (!argument1) {
1353
+ return createWidget(this, null);
1354
+ } else if (typeof argument1 === "object") {
1355
+ const options = argument1 as unknown;
1356
+ return createWidget(this, options as JQTreeOptions);
1357
+ } else if (typeof argument1 === "string" && argument1[0] !== "_") {
1358
+ const functionName = argument1;
1359
+
1360
+ if (argument1 === "destroy") {
1361
+ destroyWidget(this);
1362
+ return undefined;
1363
+ } else {
1364
+ return callFunction(this, functionName, args);
1365
+ }
1366
+ } else {
1367
+ return undefined;
1368
+ }
1369
+ };
1370
+ };
1371
+
1372
+ register();