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