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