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