jqtree 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +13 -3
- package/.github/workflows/ci.yml +6 -6
- package/.github/workflows/codeql-analysis.yml +4 -4
- package/.github/workflows/size.yml +3 -3
- package/.github/workflows/static.yml +1 -1
- package/bower.json +1 -1
- package/config/jest.config.js +4 -0
- package/config/jest.polyfills.js +14 -0
- package/devserver/test_index.html +9 -0
- package/docs/.ruby-version +1 -1
- package/docs/_config.yml +1 -1
- package/docs/_entries/general/changelog.md +4 -0
- package/docs/_entries/multiple_selection/get-selected-nodes.md +1 -1
- package/docs/_entries/node/getnextnode.md +3 -6
- package/docs/_entries/node/getnextsibling.md +1 -1
- package/docs/_entries/node/getnextvisiblenode.md +8 -5
- package/docs/_entries/node/getpreviousnode.md +12 -0
- package/docs/_entries/node/getprevioussibling.md +1 -1
- package/docs/_entries/node/getpreviousvisiblenode.md +6 -5
- package/package.json +32 -30
- package/src/dataLoader.ts +19 -21
- package/src/dragAndDropHandler/dragElement.ts +37 -25
- package/src/dragAndDropHandler/generateHitAreas.ts +176 -0
- package/src/dragAndDropHandler/index.ts +32 -48
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +91 -0
- package/src/dragAndDropHandler/types.ts +2 -1
- package/src/mouseHandler.ts +385 -0
- package/src/mouseUtils.ts +23 -0
- package/src/node.ts +1 -29
- package/src/nodeElement/folderElement.ts +1 -1
- package/src/nodeElement/ghostDropHint.ts +2 -1
- package/src/nodeElement/index.ts +2 -1
- package/src/playwright/coverage.ts +3 -3
- package/src/playwright/playwright.test.ts +150 -49
- package/src/playwright/testUtils.ts +28 -5
- package/src/position.ts +28 -0
- package/src/scrollHandler/containerScrollParent.ts +13 -23
- package/src/scrollHandler/createScrollParent.ts +22 -22
- package/src/scrollHandler/documentScrollParent.ts +16 -13
- package/src/scrollHandler.ts +6 -14
- package/src/test/jqTree/events.test.ts +97 -30
- package/src/test/jqTree/loadOnDemand.test.ts +22 -15
- package/src/test/jqTree/methods.test.ts +8 -11
- package/src/test/jqTree/mouse.test.ts +82 -0
- package/src/test/jqTree/options.test.ts +9 -8
- package/src/test/node.test.ts +2 -1
- package/src/test/{nodeUtil.test.ts → position.test.ts} +1 -1
- package/src/tree.jquery.ts +108 -184
- package/src/util.ts +10 -1
- package/src/version.ts +1 -1
- package/tree.jquery.debug.js +2158 -2135
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +3 -3
- package/tree.jquery.js.map +1 -1
- package/tsconfig.json +5 -3
- package/docs/_entries/functions/get-selected-nodes.md +0 -10
- package/src/dragAndDropHandler/hitAreasGenerator.ts +0 -175
- package/src/dragAndDropHandler/visibleNodeIterator.ts +0 -97
- package/src/mouse.widget.ts +0 -266
- package/src/mouseWidgetTypes.ts +0 -6
package/tree.jquery.debug.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
JqTree 1.8.
|
|
2
|
+
JqTree 1.8.1
|
|
3
3
|
|
|
4
|
-
Copyright
|
|
4
|
+
Copyright 2024 Marco Braak
|
|
5
5
|
|
|
6
6
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
you may not use this file except in compliance with the License.
|
|
@@ -20,9 +20,7 @@ limitations under the License.
|
|
|
20
20
|
var jqtree = (function (exports) {
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
|
-
const version = "1.8.
|
|
24
|
-
|
|
25
|
-
const isNodeRecordWithChildren = data => typeof data === "object" && "children" in data && data["children"] instanceof Array;
|
|
23
|
+
const version = "1.8.1";
|
|
26
24
|
|
|
27
25
|
let Position = /*#__PURE__*/function (Position) {
|
|
28
26
|
Position[Position["Before"] = 1] = "Before";
|
|
@@ -48,2360 +46,2442 @@ var jqtree = (function (exports) {
|
|
|
48
46
|
return "";
|
|
49
47
|
};
|
|
50
48
|
const getPosition = name => positionNames[name];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
let
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
49
|
+
|
|
50
|
+
class DragElement {
|
|
51
|
+
constructor(_ref) {
|
|
52
|
+
let {
|
|
53
|
+
autoEscape,
|
|
54
|
+
nodeName,
|
|
55
|
+
offsetX,
|
|
56
|
+
offsetY,
|
|
57
|
+
treeElement
|
|
58
|
+
} = _ref;
|
|
59
|
+
this.offsetX = offsetX;
|
|
60
|
+
this.offsetY = offsetY;
|
|
61
|
+
this.element = this.createElement(nodeName, autoEscape);
|
|
62
|
+
treeElement.appendChild(this.element);
|
|
63
|
+
}
|
|
64
|
+
move(pageX, pageY) {
|
|
65
|
+
this.element.style.left = `${pageX - this.offsetX}px`;
|
|
66
|
+
this.element.style.top = `${pageY - this.offsetY}px`;
|
|
67
|
+
}
|
|
68
|
+
remove() {
|
|
69
|
+
this.element.remove();
|
|
70
|
+
}
|
|
71
|
+
createElement(nodeName, autoEscape) {
|
|
72
|
+
const element = document.createElement("span");
|
|
73
|
+
element.classList.add("jqtree-title", "jqtree-dragging");
|
|
74
|
+
if (autoEscape) {
|
|
75
|
+
element.textContent = nodeName;
|
|
76
|
+
} else {
|
|
77
|
+
element.innerHTML = nodeName;
|
|
66
78
|
}
|
|
79
|
+
element.style.position = "absolute";
|
|
80
|
+
return element;
|
|
67
81
|
}
|
|
82
|
+
}
|
|
68
83
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
const isInt = n => typeof n === "number" && n % 1 === 0;
|
|
85
|
+
const isFunction = v => typeof v === "function";
|
|
86
|
+
const getBoolString = value => value ? "true" : "false";
|
|
87
|
+
const getOffsetTop = element => getElementPosition(element).top;
|
|
88
|
+
const getElementPosition = element => {
|
|
89
|
+
const rect = element.getBoundingClientRect();
|
|
90
|
+
return {
|
|
91
|
+
left: rect.x + window.scrollX,
|
|
92
|
+
top: rect.y + window.scrollY
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const iterateVisibleNodes = (tree, _ref) => {
|
|
97
|
+
let {
|
|
98
|
+
handleAfterOpenFolder,
|
|
99
|
+
handleClosedFolder,
|
|
100
|
+
handleFirstNode,
|
|
101
|
+
handleNode,
|
|
102
|
+
handleOpenFolder
|
|
103
|
+
} = _ref;
|
|
104
|
+
let isFirstNode = true;
|
|
105
|
+
const iterate = (node, nextNode) => {
|
|
106
|
+
let mustIterateInside = (node.is_open || !node.element) && node.hasChildren();
|
|
107
|
+
let element = null;
|
|
108
|
+
|
|
109
|
+
// Is the element visible?
|
|
110
|
+
if (node.element?.offsetParent) {
|
|
111
|
+
element = node.element;
|
|
112
|
+
if (isFirstNode) {
|
|
113
|
+
handleFirstNode(node);
|
|
114
|
+
isFirstNode = false;
|
|
115
|
+
}
|
|
116
|
+
if (!node.hasChildren()) {
|
|
117
|
+
handleNode(node, nextNode, node.element);
|
|
118
|
+
} else if (node.is_open) {
|
|
119
|
+
if (!handleOpenFolder(node, node.element)) {
|
|
120
|
+
mustIterateInside = false;
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
handleClosedFolder(node, nextNode, element);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (mustIterateInside) {
|
|
127
|
+
const childrenLength = node.children.length;
|
|
128
|
+
node.children.forEach((_, i) => {
|
|
129
|
+
const child = node.children[i];
|
|
130
|
+
if (child) {
|
|
131
|
+
if (i === childrenLength - 1) {
|
|
132
|
+
iterate(child, null);
|
|
133
|
+
} else {
|
|
134
|
+
const nextChild = node.children[i + 1];
|
|
135
|
+
if (nextChild) {
|
|
136
|
+
iterate(child, nextChild);
|
|
93
137
|
}
|
|
94
|
-
} else if (key !== "children" && key !== "parent") {
|
|
95
|
-
// You can't update the children or the parent using this function
|
|
96
|
-
this[key] = value;
|
|
97
138
|
}
|
|
98
139
|
}
|
|
140
|
+
});
|
|
141
|
+
if (node.is_open && element) {
|
|
142
|
+
handleAfterOpenFolder(node, nextNode);
|
|
99
143
|
}
|
|
100
144
|
}
|
|
101
|
-
}
|
|
145
|
+
};
|
|
146
|
+
iterate(tree, null);
|
|
147
|
+
};
|
|
102
148
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const node = this.createNode(childData);
|
|
123
|
-
this.addChild(node);
|
|
124
|
-
if (isNodeRecordWithChildren(childData)) {
|
|
125
|
-
node.loadFromData(childData.children);
|
|
126
|
-
}
|
|
149
|
+
const generatePositions = (tree, currentNode) => {
|
|
150
|
+
const positions = [];
|
|
151
|
+
let lastTop = 0;
|
|
152
|
+
const addPosition = (node, position, top) => {
|
|
153
|
+
const area = {
|
|
154
|
+
top,
|
|
155
|
+
bottom: 0,
|
|
156
|
+
node,
|
|
157
|
+
position
|
|
158
|
+
};
|
|
159
|
+
positions.push(area);
|
|
160
|
+
lastTop = top;
|
|
161
|
+
};
|
|
162
|
+
const handleAfterOpenFolder = (node, nextNode) => {
|
|
163
|
+
if (node === currentNode || nextNode === currentNode) {
|
|
164
|
+
// Cannot move before or after current item
|
|
165
|
+
addPosition(node, Position.None, lastTop);
|
|
166
|
+
} else {
|
|
167
|
+
addPosition(node, Position.After, lastTop);
|
|
127
168
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
*/
|
|
137
|
-
addChild(node) {
|
|
138
|
-
this.children.push(node);
|
|
139
|
-
node.setParent(this);
|
|
140
|
-
}
|
|
169
|
+
};
|
|
170
|
+
const handleClosedFolder = (node, nextNode, element) => {
|
|
171
|
+
const top = getOffsetTop(element);
|
|
172
|
+
if (node === currentNode) {
|
|
173
|
+
// Cannot move after current item
|
|
174
|
+
addPosition(node, Position.None, top);
|
|
175
|
+
} else {
|
|
176
|
+
addPosition(node, Position.Inside, top);
|
|
141
177
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
178
|
+
// Cannot move before current item
|
|
179
|
+
if (nextNode !== currentNode) {
|
|
180
|
+
addPosition(node, Position.After, top);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const handleFirstNode = node => {
|
|
185
|
+
if (node !== currentNode) {
|
|
186
|
+
addPosition(node, Position.Before, getOffsetTop(node.element));
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const handleNode = (node, nextNode, element) => {
|
|
190
|
+
const top = getOffsetTop(element);
|
|
191
|
+
if (node === currentNode) {
|
|
192
|
+
// Cannot move inside current item
|
|
193
|
+
addPosition(node, Position.None, top);
|
|
194
|
+
} else {
|
|
195
|
+
addPosition(node, Position.Inside, top);
|
|
196
|
+
}
|
|
197
|
+
if (nextNode === currentNode || node === currentNode) {
|
|
198
|
+
// Cannot move before or after current item
|
|
199
|
+
addPosition(node, Position.None, top);
|
|
200
|
+
} else {
|
|
201
|
+
addPosition(node, Position.After, top);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const handleOpenFolder = (node, element) => {
|
|
205
|
+
if (node === currentNode) {
|
|
206
|
+
// Cannot move inside current item
|
|
207
|
+
// Stop iterating
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
153
210
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
removeChild(node) {
|
|
159
|
-
// remove children from the index
|
|
160
|
-
node.removeChildren();
|
|
161
|
-
this.doRemoveChild(node);
|
|
162
|
-
}
|
|
211
|
+
// Cannot move before current item
|
|
212
|
+
if (node.children[0] !== currentNode) {
|
|
213
|
+
addPosition(node, Position.Inside, getOffsetTop(element));
|
|
214
|
+
}
|
|
163
215
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
216
|
+
// Continue iterating
|
|
217
|
+
return true;
|
|
218
|
+
};
|
|
219
|
+
iterateVisibleNodes(tree, {
|
|
220
|
+
handleAfterOpenFolder,
|
|
221
|
+
handleClosedFolder,
|
|
222
|
+
handleFirstNode,
|
|
223
|
+
handleNode,
|
|
224
|
+
handleOpenFolder
|
|
225
|
+
});
|
|
226
|
+
return positions;
|
|
227
|
+
};
|
|
228
|
+
const generateHitAreasForGroup = (hitAreas, positionsInGroup, top, bottom) => {
|
|
229
|
+
// limit positions in group
|
|
230
|
+
const positionCount = Math.min(positionsInGroup.length, 4);
|
|
231
|
+
const areaHeight = Math.round((bottom - top) / positionCount);
|
|
232
|
+
let areaTop = top;
|
|
233
|
+
let i = 0;
|
|
234
|
+
while (i < positionCount) {
|
|
235
|
+
const position = positionsInGroup[i];
|
|
236
|
+
if (position) {
|
|
237
|
+
hitAreas.push({
|
|
238
|
+
top: areaTop,
|
|
239
|
+
bottom: areaTop + areaHeight,
|
|
240
|
+
node: position.node,
|
|
241
|
+
position: position.position
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
areaTop += areaHeight;
|
|
245
|
+
i += 1;
|
|
170
246
|
}
|
|
247
|
+
};
|
|
248
|
+
const generateHitAreasFromPositions = (positions, treeBottom) => {
|
|
249
|
+
let previousTop = positions[0]?.top ?? 0;
|
|
250
|
+
let group = [];
|
|
251
|
+
const hitAreas = [];
|
|
252
|
+
for (const position of positions) {
|
|
253
|
+
if (position.top !== previousTop && group.length) {
|
|
254
|
+
generateHitAreasForGroup(hitAreas, group, previousTop, position.top);
|
|
255
|
+
previousTop = position.top;
|
|
256
|
+
group = [];
|
|
257
|
+
}
|
|
258
|
+
group.push(position);
|
|
259
|
+
}
|
|
260
|
+
generateHitAreasForGroup(hitAreas, group, previousTop, treeBottom);
|
|
261
|
+
return hitAreas;
|
|
262
|
+
};
|
|
263
|
+
const generateHitAreas = (tree, currentNode, treeBottom) => {
|
|
264
|
+
const positions = generatePositions(tree, currentNode);
|
|
265
|
+
return generateHitAreasFromPositions(positions, treeBottom);
|
|
266
|
+
};
|
|
171
267
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
268
|
+
class DragAndDropHandler {
|
|
269
|
+
constructor(_ref) {
|
|
270
|
+
let {
|
|
271
|
+
autoEscape,
|
|
272
|
+
getNodeElement,
|
|
273
|
+
getNodeElementForNode,
|
|
274
|
+
getScrollLeft,
|
|
275
|
+
getTree,
|
|
276
|
+
onCanMove,
|
|
277
|
+
onCanMoveTo,
|
|
278
|
+
onDragMove,
|
|
279
|
+
onDragStop,
|
|
280
|
+
onIsMoveHandle,
|
|
281
|
+
openNode,
|
|
282
|
+
refreshElements,
|
|
283
|
+
slide,
|
|
284
|
+
treeElement,
|
|
285
|
+
triggerEvent
|
|
286
|
+
} = _ref;
|
|
287
|
+
this.autoEscape = autoEscape;
|
|
288
|
+
this.getNodeElement = getNodeElement;
|
|
289
|
+
this.getNodeElementForNode = getNodeElementForNode;
|
|
290
|
+
this.getScrollLeft = getScrollLeft;
|
|
291
|
+
this.getTree = getTree;
|
|
292
|
+
this.onCanMove = onCanMove;
|
|
293
|
+
this.onCanMoveTo = onCanMoveTo;
|
|
294
|
+
this.onDragMove = onDragMove;
|
|
295
|
+
this.onDragStop = onDragStop;
|
|
296
|
+
this.onIsMoveHandle = onIsMoveHandle;
|
|
297
|
+
this.openNode = openNode;
|
|
298
|
+
this.refreshElements = refreshElements;
|
|
299
|
+
this.slide = slide;
|
|
300
|
+
this.treeElement = treeElement;
|
|
301
|
+
this.triggerEvent = triggerEvent;
|
|
302
|
+
this.hoveredArea = null;
|
|
303
|
+
this.hitAreas = [];
|
|
304
|
+
this.isDragging = false;
|
|
305
|
+
this.currentItem = null;
|
|
176
306
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
307
|
+
mouseCapture(positionInfo) {
|
|
308
|
+
const element = positionInfo.target;
|
|
309
|
+
if (!this.mustCaptureElement(element)) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
if (this.onIsMoveHandle && !this.onIsMoveHandle(jQuery(element))) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
let nodeElement = this.getNodeElement(element);
|
|
316
|
+
if (nodeElement && this.onCanMove) {
|
|
317
|
+
if (!this.onCanMove(nodeElement.node)) {
|
|
318
|
+
nodeElement = null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
this.currentItem = nodeElement;
|
|
322
|
+
return this.currentItem != null;
|
|
180
323
|
}
|
|
181
|
-
|
|
182
|
-
|
|
324
|
+
mouseStart(positionInfo) {
|
|
325
|
+
if (!this.currentItem) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
this.refresh();
|
|
329
|
+
const {
|
|
330
|
+
left,
|
|
331
|
+
top
|
|
332
|
+
} = getElementPosition(positionInfo.target);
|
|
333
|
+
const node = this.currentItem.node;
|
|
334
|
+
this.dragElement = new DragElement({
|
|
335
|
+
autoEscape: this.autoEscape ?? true,
|
|
336
|
+
nodeName: node.name,
|
|
337
|
+
offsetX: positionInfo.pageX - left,
|
|
338
|
+
offsetY: positionInfo.pageY - top,
|
|
339
|
+
treeElement: this.treeElement
|
|
340
|
+
});
|
|
341
|
+
this.isDragging = true;
|
|
342
|
+
this.currentItem.element.classList.add("jqtree-moving");
|
|
343
|
+
return true;
|
|
183
344
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return (level <= 2);
|
|
345
|
+
mouseDrag(positionInfo) {
|
|
346
|
+
if (!this.currentItem || !this.dragElement) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
this.dragElement.move(positionInfo.pageX, positionInfo.pageY);
|
|
350
|
+
const area = this.findHoveredArea(positionInfo.pageX, positionInfo.pageY);
|
|
351
|
+
if (area && this.canMoveToArea(area)) {
|
|
352
|
+
if (!area.node.isFolder()) {
|
|
353
|
+
this.stopOpenFolderTimer();
|
|
194
354
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
_iterate(child, level + 1);
|
|
204
|
-
}
|
|
355
|
+
if (this.hoveredArea !== area) {
|
|
356
|
+
this.hoveredArea = area;
|
|
357
|
+
|
|
358
|
+
// If this is a closed folder, start timer to open it
|
|
359
|
+
if (this.mustOpenFolderTimer(area)) {
|
|
360
|
+
this.startOpenFolderTimer(area.node);
|
|
361
|
+
} else {
|
|
362
|
+
this.stopOpenFolderTimer();
|
|
205
363
|
}
|
|
364
|
+
this.updateDropHint();
|
|
206
365
|
}
|
|
207
|
-
};
|
|
208
|
-
_iterate(this, 0);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/*
|
|
212
|
-
Move node relative to another node.
|
|
213
|
-
Argument position: Position.BEFORE, Position.AFTER or Position.Inside
|
|
214
|
-
// move node1 after node2
|
|
215
|
-
tree.moveNode(node1, node2, Position.AFTER);
|
|
216
|
-
*/
|
|
217
|
-
moveNode(movedNode, targetNode, position) {
|
|
218
|
-
if (!movedNode.parent || movedNode.isParentOf(targetNode)) {
|
|
219
|
-
// - Node is parent of target node
|
|
220
|
-
// - Or, parent is empty
|
|
221
|
-
return false;
|
|
222
366
|
} else {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
case Position.Before:
|
|
234
|
-
{
|
|
235
|
-
if (targetNode.parent) {
|
|
236
|
-
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode));
|
|
237
|
-
return true;
|
|
238
|
-
}
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
case Position.Inside:
|
|
242
|
-
{
|
|
243
|
-
// move inside as first child
|
|
244
|
-
targetNode.addChildAtPosition(movedNode, 0);
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
default:
|
|
248
|
-
return false;
|
|
367
|
+
this.removeDropHint();
|
|
368
|
+
this.stopOpenFolderTimer();
|
|
369
|
+
this.hoveredArea = area;
|
|
370
|
+
}
|
|
371
|
+
if (!area) {
|
|
372
|
+
if (this.onDragMove) {
|
|
373
|
+
this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
|
|
249
374
|
}
|
|
250
375
|
}
|
|
376
|
+
return true;
|
|
251
377
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (["parent", "children", "element", "idMapping", "load_on_demand", "nodeClass", "tree", "isEmptyFolder"].indexOf(k) === -1 && Object.prototype.hasOwnProperty.call(node, k)) {
|
|
263
|
-
const v = node[k];
|
|
264
|
-
tmpNode[k] = v;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
if (node.hasChildren()) {
|
|
268
|
-
tmpNode["children"] = getDataFromNodes(node.children);
|
|
269
|
-
}
|
|
270
|
-
return tmpNode;
|
|
271
|
-
});
|
|
272
|
-
};
|
|
273
|
-
if (includeParent) {
|
|
274
|
-
return getDataFromNodes([this]);
|
|
275
|
-
} else {
|
|
276
|
-
return getDataFromNodes(this.children);
|
|
378
|
+
mouseStop(positionInfo) {
|
|
379
|
+
this.moveItem(positionInfo);
|
|
380
|
+
this.clear();
|
|
381
|
+
this.removeHover();
|
|
382
|
+
this.removeDropHint();
|
|
383
|
+
this.removeHitAreas();
|
|
384
|
+
const currentItem = this.currentItem;
|
|
385
|
+
if (this.currentItem) {
|
|
386
|
+
this.currentItem.element.classList.remove("jqtree-moving");
|
|
387
|
+
this.currentItem = null;
|
|
277
388
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const node = this.getNodeByCallback(n => n.name === name);
|
|
284
|
-
if (!node) {
|
|
285
|
-
throw `Node with name ${name} not found`;
|
|
389
|
+
this.isDragging = false;
|
|
390
|
+
if (!this.hoveredArea && currentItem) {
|
|
391
|
+
if (this.onDragStop) {
|
|
392
|
+
this.onDragStop(currentItem.node, positionInfo.originalEvent);
|
|
393
|
+
}
|
|
286
394
|
}
|
|
287
|
-
return
|
|
395
|
+
return false;
|
|
288
396
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return false;
|
|
297
|
-
} else {
|
|
298
|
-
return true;
|
|
397
|
+
refresh() {
|
|
398
|
+
this.removeHitAreas();
|
|
399
|
+
if (this.currentItem) {
|
|
400
|
+
this.generateHitAreas();
|
|
401
|
+
this.currentItem = this.getNodeElementForNode(this.currentItem.node);
|
|
402
|
+
if (this.isDragging) {
|
|
403
|
+
this.currentItem.element.classList.add("jqtree-moving");
|
|
299
404
|
}
|
|
300
|
-
});
|
|
301
|
-
return result;
|
|
302
|
-
}
|
|
303
|
-
addAfter(nodeInfo) {
|
|
304
|
-
if (!this.parent) {
|
|
305
|
-
return null;
|
|
306
|
-
} else {
|
|
307
|
-
const node = this.createNode(nodeInfo);
|
|
308
|
-
const childIndex = this.parent.getChildIndex(this);
|
|
309
|
-
this.parent.addChildAtPosition(node, childIndex + 1);
|
|
310
|
-
node.loadChildrenFromData(nodeInfo);
|
|
311
|
-
return node;
|
|
312
405
|
}
|
|
313
406
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
407
|
+
generateHitAreas() {
|
|
408
|
+
const tree = this.getTree();
|
|
409
|
+
if (!this.currentItem || !tree) {
|
|
410
|
+
this.hitAreas = [];
|
|
317
411
|
} else {
|
|
318
|
-
|
|
319
|
-
const childIndex = this.parent.getChildIndex(this);
|
|
320
|
-
this.parent.addChildAtPosition(node, childIndex);
|
|
321
|
-
node.loadChildrenFromData(nodeInfo);
|
|
322
|
-
return node;
|
|
412
|
+
this.hitAreas = generateHitAreas(tree, this.currentItem.node, this.getTreeDimensions().bottom);
|
|
323
413
|
}
|
|
324
414
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
} else {
|
|
329
|
-
const newParent = this.createNode(nodeInfo);
|
|
330
|
-
if (this.tree) {
|
|
331
|
-
newParent.setParent(this.tree);
|
|
332
|
-
}
|
|
333
|
-
const originalParent = this.parent;
|
|
334
|
-
for (const child of originalParent.children) {
|
|
335
|
-
newParent.addChild(child);
|
|
336
|
-
}
|
|
337
|
-
originalParent.children = [];
|
|
338
|
-
originalParent.addChild(newParent);
|
|
339
|
-
return newParent;
|
|
340
|
-
}
|
|
415
|
+
mustCaptureElement(element) {
|
|
416
|
+
const nodeName = element.nodeName;
|
|
417
|
+
return nodeName !== "INPUT" && nodeName !== "SELECT" && nodeName !== "TEXTAREA";
|
|
341
418
|
}
|
|
342
|
-
|
|
343
|
-
if (this.
|
|
344
|
-
|
|
345
|
-
this.parent = null;
|
|
419
|
+
canMoveToArea(area) {
|
|
420
|
+
if (!this.onCanMoveTo) {
|
|
421
|
+
return true;
|
|
346
422
|
}
|
|
423
|
+
if (!this.currentItem) {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
const positionName = getPositionName(area.position);
|
|
427
|
+
return this.onCanMoveTo(this.currentItem.node, area.node, positionName);
|
|
347
428
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
this.addChild(node);
|
|
351
|
-
node.loadChildrenFromData(nodeInfo);
|
|
352
|
-
return node;
|
|
353
|
-
}
|
|
354
|
-
prepend(nodeInfo) {
|
|
355
|
-
const node = this.createNode(nodeInfo);
|
|
356
|
-
this.addChildAtPosition(node, 0);
|
|
357
|
-
node.loadChildrenFromData(nodeInfo);
|
|
358
|
-
return node;
|
|
429
|
+
removeHitAreas() {
|
|
430
|
+
this.hitAreas = [];
|
|
359
431
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
|
-
parent = parent.parent;
|
|
432
|
+
clear() {
|
|
433
|
+
if (this.dragElement) {
|
|
434
|
+
this.dragElement.remove();
|
|
435
|
+
this.dragElement = null;
|
|
367
436
|
}
|
|
368
|
-
return false;
|
|
369
437
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
while (node.parent) {
|
|
375
|
-
level += 1;
|
|
376
|
-
node = node.parent;
|
|
438
|
+
removeDropHint() {
|
|
439
|
+
if (this.previousGhost) {
|
|
440
|
+
this.previousGhost.remove();
|
|
377
441
|
}
|
|
378
|
-
return level;
|
|
379
442
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
addNodeToIndex(node) {
|
|
384
|
-
if (node.id != null) {
|
|
385
|
-
this.idMapping.set(node.id, node);
|
|
386
|
-
}
|
|
443
|
+
removeHover() {
|
|
444
|
+
this.hoveredArea = null;
|
|
387
445
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
446
|
+
findHoveredArea(x, y) {
|
|
447
|
+
const dimensions = this.getTreeDimensions();
|
|
448
|
+
if (x < dimensions.left || y < dimensions.top || x > dimensions.right || y > dimensions.bottom) {
|
|
449
|
+
return null;
|
|
391
450
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
this.children = [];
|
|
399
|
-
}
|
|
400
|
-
getPreviousSibling() {
|
|
401
|
-
if (!this.parent) {
|
|
402
|
-
return null;
|
|
403
|
-
} else {
|
|
404
|
-
const previousIndex = this.parent.getChildIndex(this) - 1;
|
|
405
|
-
if (previousIndex >= 0) {
|
|
406
|
-
return this.parent.children[previousIndex] || null;
|
|
407
|
-
} else {
|
|
451
|
+
let low = 0;
|
|
452
|
+
let high = this.hitAreas.length;
|
|
453
|
+
while (low < high) {
|
|
454
|
+
const mid = low + high >> 1;
|
|
455
|
+
const area = this.hitAreas[mid];
|
|
456
|
+
if (!area) {
|
|
408
457
|
return null;
|
|
409
458
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
return null;
|
|
415
|
-
} else {
|
|
416
|
-
const nextIndex = this.parent.getChildIndex(this) + 1;
|
|
417
|
-
if (nextIndex < this.parent.children.length) {
|
|
418
|
-
return this.parent.children[nextIndex] || null;
|
|
459
|
+
if (y < area.top) {
|
|
460
|
+
high = mid;
|
|
461
|
+
} else if (y > area.bottom) {
|
|
462
|
+
low = mid + 1;
|
|
419
463
|
} else {
|
|
420
|
-
return
|
|
464
|
+
return area;
|
|
421
465
|
}
|
|
422
466
|
}
|
|
467
|
+
return null;
|
|
423
468
|
}
|
|
424
|
-
|
|
425
|
-
|
|
469
|
+
mustOpenFolderTimer(area) {
|
|
470
|
+
const node = area.node;
|
|
471
|
+
return node.isFolder() && !node.is_open && area.position === Position.Inside;
|
|
426
472
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
473
|
+
updateDropHint() {
|
|
474
|
+
if (!this.hoveredArea) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// remove previous drop hint
|
|
479
|
+
this.removeDropHint();
|
|
480
|
+
|
|
481
|
+
// add new drop hint
|
|
482
|
+
const nodeElement = this.getNodeElementForNode(this.hoveredArea.node);
|
|
483
|
+
this.previousGhost = nodeElement.addDropHint(this.hoveredArea.position);
|
|
436
484
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
return this.parent.getNextNode(false);
|
|
449
|
-
}
|
|
485
|
+
startOpenFolderTimer(folder) {
|
|
486
|
+
const openFolder = () => {
|
|
487
|
+
this.openNode(folder, this.slide, () => {
|
|
488
|
+
this.refresh();
|
|
489
|
+
this.updateDropHint();
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
this.stopOpenFolderTimer();
|
|
493
|
+
const openFolderDelay = this.openFolderDelay;
|
|
494
|
+
if (openFolderDelay !== false) {
|
|
495
|
+
this.openFolderTimer = window.setTimeout(openFolder, openFolderDelay);
|
|
450
496
|
}
|
|
451
497
|
}
|
|
452
|
-
|
|
453
|
-
if (this.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
498
|
+
stopOpenFolderTimer() {
|
|
499
|
+
if (this.openFolderTimer) {
|
|
500
|
+
clearTimeout(this.openFolderTimer);
|
|
501
|
+
this.openFolderTimer = null;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
moveItem(positionInfo) {
|
|
505
|
+
if (this.currentItem && this.hoveredArea && this.hoveredArea.position !== Position.None && this.canMoveToArea(this.hoveredArea)) {
|
|
506
|
+
const movedNode = this.currentItem.node;
|
|
507
|
+
const targetNode = this.hoveredArea.node;
|
|
508
|
+
const position = this.hoveredArea.position;
|
|
509
|
+
const previousParent = movedNode.parent;
|
|
510
|
+
if (position === Position.Inside) {
|
|
511
|
+
this.hoveredArea.node.is_open = true;
|
|
512
|
+
}
|
|
513
|
+
const doMove = () => {
|
|
514
|
+
const tree = this.getTree();
|
|
515
|
+
if (tree) {
|
|
516
|
+
tree.moveNode(movedNode, targetNode, position);
|
|
517
|
+
this.treeElement.textContent = "";
|
|
518
|
+
this.refreshElements(null);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
const event = this.triggerEvent("tree.move", {
|
|
522
|
+
move_info: {
|
|
523
|
+
moved_node: movedNode,
|
|
524
|
+
target_node: targetNode,
|
|
525
|
+
position: getPositionName(position),
|
|
526
|
+
previous_parent: previousParent,
|
|
527
|
+
do_move: doMove,
|
|
528
|
+
original_event: positionInfo.originalEvent
|
|
467
529
|
}
|
|
530
|
+
});
|
|
531
|
+
if (!event.isDefaultPrevented()) {
|
|
532
|
+
doMove();
|
|
468
533
|
}
|
|
469
534
|
}
|
|
470
535
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
536
|
+
getTreeDimensions() {
|
|
537
|
+
// Return the dimensions of the tree. Add a margin to the bottom to allow
|
|
538
|
+
// to drag-and-drop after the last element.
|
|
539
|
+
const treePosition = getElementPosition(this.treeElement);
|
|
540
|
+
const left = treePosition.left + this.getScrollLeft();
|
|
541
|
+
const top = treePosition.top;
|
|
542
|
+
return {
|
|
543
|
+
left,
|
|
544
|
+
top,
|
|
545
|
+
right: left + this.treeElement.clientWidth,
|
|
546
|
+
bottom: top + this.treeElement.clientHeight + 16
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
class ElementsRenderer {
|
|
552
|
+
constructor(_ref) {
|
|
553
|
+
let {
|
|
554
|
+
autoEscape,
|
|
555
|
+
buttonLeft,
|
|
556
|
+
closedIcon,
|
|
557
|
+
onCreateLi,
|
|
558
|
+
dragAndDrop,
|
|
559
|
+
$element,
|
|
560
|
+
getTree,
|
|
561
|
+
isNodeSelected,
|
|
562
|
+
openedIcon,
|
|
563
|
+
rtl,
|
|
564
|
+
showEmptyFolder,
|
|
565
|
+
tabIndex
|
|
566
|
+
} = _ref;
|
|
567
|
+
this.autoEscape = autoEscape;
|
|
568
|
+
this.buttonLeft = buttonLeft;
|
|
569
|
+
this.dragAndDrop = dragAndDrop;
|
|
570
|
+
this.$element = $element;
|
|
571
|
+
this.getTree = getTree;
|
|
572
|
+
this.isNodeSelected = isNodeSelected;
|
|
573
|
+
this.onCreateLi = onCreateLi;
|
|
574
|
+
this.rtl = rtl;
|
|
575
|
+
this.showEmptyFolder = showEmptyFolder;
|
|
576
|
+
this.tabIndex = tabIndex;
|
|
577
|
+
this.openedIconElement = this.createButtonElement(openedIcon || "+");
|
|
578
|
+
this.closedIconElement = this.createButtonElement(closedIcon || "-");
|
|
579
|
+
}
|
|
580
|
+
render(fromNode) {
|
|
581
|
+
if (fromNode && fromNode.parent) {
|
|
582
|
+
this.renderFromNode(fromNode);
|
|
474
583
|
} else {
|
|
475
|
-
|
|
476
|
-
if (!previousSibling) {
|
|
477
|
-
return this.getParent();
|
|
478
|
-
} else if (previousSibling.hasChildren()) {
|
|
479
|
-
return previousSibling.getLastChild();
|
|
480
|
-
} else {
|
|
481
|
-
return previousSibling;
|
|
482
|
-
}
|
|
584
|
+
this.renderFromRoot();
|
|
483
585
|
}
|
|
484
586
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (!previousSibling) {
|
|
491
|
-
return this.getParent();
|
|
492
|
-
} else if (!previousSibling.hasChildren() || !previousSibling.is_open) {
|
|
493
|
-
// Previous sibling
|
|
494
|
-
return previousSibling;
|
|
495
|
-
} else {
|
|
496
|
-
// Last child of previous sibling
|
|
497
|
-
return previousSibling.getLastChild();
|
|
498
|
-
}
|
|
587
|
+
renderFromRoot() {
|
|
588
|
+
this.$element.empty();
|
|
589
|
+
const tree = this.getTree();
|
|
590
|
+
if (this.$element[0] && tree) {
|
|
591
|
+
this.createDomElements(this.$element[0], tree.children, true, 1);
|
|
499
592
|
}
|
|
500
593
|
}
|
|
501
|
-
|
|
502
|
-
//
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
594
|
+
renderFromNode(node) {
|
|
595
|
+
// remember current li
|
|
596
|
+
const $previousLi = jQuery(node.element);
|
|
597
|
+
|
|
598
|
+
// create element
|
|
599
|
+
const li = this.createLi(node, node.getLevel());
|
|
600
|
+
this.attachNodeData(node, li);
|
|
601
|
+
|
|
602
|
+
// add element to dom
|
|
603
|
+
$previousLi.after(li);
|
|
604
|
+
|
|
605
|
+
// remove previous li
|
|
606
|
+
$previousLi.remove();
|
|
607
|
+
|
|
608
|
+
// create children
|
|
609
|
+
if (node.children) {
|
|
610
|
+
this.createDomElements(li, node.children, false, node.getLevel() + 1);
|
|
510
611
|
}
|
|
511
612
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
return lastChild;
|
|
522
|
-
} else {
|
|
523
|
-
return lastChild?.getLastChild();
|
|
613
|
+
createDomElements(element, children, isRootNode, level) {
|
|
614
|
+
const ul = this.createUl(isRootNode);
|
|
615
|
+
element.appendChild(ul);
|
|
616
|
+
for (const child of children) {
|
|
617
|
+
const li = this.createLi(child, level);
|
|
618
|
+
ul.appendChild(li);
|
|
619
|
+
this.attachNodeData(child, li);
|
|
620
|
+
if (child.hasChildren()) {
|
|
621
|
+
this.createDomElements(li, child.children, false, level + 1);
|
|
524
622
|
}
|
|
525
623
|
}
|
|
526
624
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const addNode = nodeData => {
|
|
531
|
-
this.setData(nodeData);
|
|
532
|
-
if (isNodeRecordWithChildren(nodeData) && nodeData.children.length) {
|
|
533
|
-
addChildren(nodeData.children);
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
const addChildren = childrenData => {
|
|
537
|
-
for (const child of childrenData) {
|
|
538
|
-
const node = this.createNode();
|
|
539
|
-
node.initFromData(child);
|
|
540
|
-
this.addChild(node);
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
addNode(data);
|
|
544
|
-
}
|
|
545
|
-
setParent(parent) {
|
|
546
|
-
this.parent = parent;
|
|
547
|
-
this.tree = parent.tree;
|
|
548
|
-
this.tree?.addNodeToIndex(this);
|
|
549
|
-
}
|
|
550
|
-
doRemoveChild(node) {
|
|
551
|
-
this.children.splice(this.getChildIndex(node), 1);
|
|
552
|
-
this.tree?.removeNodeFromIndex(node);
|
|
553
|
-
}
|
|
554
|
-
getNodeClass() {
|
|
555
|
-
return this.nodeClass || this?.tree?.nodeClass || Node;
|
|
556
|
-
}
|
|
557
|
-
createNode(nodeData) {
|
|
558
|
-
const nodeClass = this.getNodeClass();
|
|
559
|
-
return new nodeClass(nodeData);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Load children data from nodeInfo if it has children
|
|
563
|
-
loadChildrenFromData(nodeInfo) {
|
|
564
|
-
if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
|
|
565
|
-
this.loadFromData(nodeInfo.children);
|
|
566
|
-
}
|
|
625
|
+
attachNodeData(node, li) {
|
|
626
|
+
node.element = li;
|
|
627
|
+
jQuery(li).data("node", node);
|
|
567
628
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
this.$element = jQuery("<span>").addClass("jqtree-title jqtree-dragging");
|
|
575
|
-
if (autoEscape) {
|
|
576
|
-
this.$element.text(nodeName);
|
|
629
|
+
createUl(isRootNode) {
|
|
630
|
+
let classString;
|
|
631
|
+
let role;
|
|
632
|
+
if (!isRootNode) {
|
|
633
|
+
classString = "";
|
|
634
|
+
role = "group";
|
|
577
635
|
} else {
|
|
578
|
-
|
|
636
|
+
classString = "jqtree-tree";
|
|
637
|
+
role = "tree";
|
|
638
|
+
if (this.rtl) {
|
|
639
|
+
classString += " jqtree-rtl";
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (this.dragAndDrop) {
|
|
643
|
+
classString += " jqtree-dnd";
|
|
579
644
|
}
|
|
580
|
-
|
|
581
|
-
$
|
|
645
|
+
const ul = document.createElement("ul");
|
|
646
|
+
ul.className = `jqtree_common ${classString}`;
|
|
647
|
+
ul.setAttribute("role", role);
|
|
648
|
+
return ul;
|
|
582
649
|
}
|
|
583
|
-
|
|
584
|
-
this
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
650
|
+
createLi(node, level) {
|
|
651
|
+
const isSelected = Boolean(this.isNodeSelected(node));
|
|
652
|
+
const mustShowFolder = node.isFolder() || node.isEmptyFolder && this.showEmptyFolder;
|
|
653
|
+
const li = mustShowFolder ? this.createFolderLi(node, level, isSelected) : this.createNodeLi(node, level, isSelected);
|
|
654
|
+
if (this.onCreateLi) {
|
|
655
|
+
this.onCreateLi(node, jQuery(li), isSelected);
|
|
656
|
+
}
|
|
657
|
+
return li;
|
|
588
658
|
}
|
|
589
|
-
|
|
590
|
-
|
|
659
|
+
setTreeItemAriaAttributes(element, name, level, isSelected) {
|
|
660
|
+
element.setAttribute("aria-label", name);
|
|
661
|
+
element.setAttribute("aria-level", `${level}`);
|
|
662
|
+
element.setAttribute("aria-selected", getBoolString(isSelected));
|
|
663
|
+
element.setAttribute("role", "treeitem");
|
|
591
664
|
}
|
|
592
|
-
|
|
665
|
+
createFolderLi(node, level, isSelected) {
|
|
666
|
+
const buttonClasses = this.getButtonClasses(node);
|
|
667
|
+
const folderClasses = this.getFolderClasses(node, isSelected);
|
|
668
|
+
const iconElement = node.is_open ? this.openedIconElement : this.closedIconElement;
|
|
593
669
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
class VisibleNodeIterator {
|
|
600
|
-
constructor(tree) {
|
|
601
|
-
this.tree = tree;
|
|
602
|
-
}
|
|
603
|
-
iterate() {
|
|
604
|
-
let isFirstNode = true;
|
|
605
|
-
const _iterateNode = (node, nextNode) => {
|
|
606
|
-
let mustIterateInside = (node.is_open || !node.element) && node.hasChildren();
|
|
607
|
-
let element = null;
|
|
608
|
-
|
|
609
|
-
// Is the element visible?
|
|
610
|
-
if (node.element?.offsetParent) {
|
|
611
|
-
element = node.element;
|
|
612
|
-
if (isFirstNode) {
|
|
613
|
-
this.handleFirstNode(node);
|
|
614
|
-
isFirstNode = false;
|
|
615
|
-
}
|
|
616
|
-
if (!node.hasChildren()) {
|
|
617
|
-
this.handleNode(node, nextNode, node.element);
|
|
618
|
-
} else if (node.is_open) {
|
|
619
|
-
if (!this.handleOpenFolder(node, node.element)) {
|
|
620
|
-
mustIterateInside = false;
|
|
621
|
-
}
|
|
622
|
-
} else {
|
|
623
|
-
this.handleClosedFolder(node, nextNode, element);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
if (mustIterateInside) {
|
|
627
|
-
const childrenLength = node.children.length;
|
|
628
|
-
node.children.forEach((_, i) => {
|
|
629
|
-
const child = node.children[i];
|
|
630
|
-
if (child) {
|
|
631
|
-
if (i === childrenLength - 1) {
|
|
632
|
-
_iterateNode(child, null);
|
|
633
|
-
} else {
|
|
634
|
-
const nextChild = node.children[i + 1];
|
|
635
|
-
if (nextChild) {
|
|
636
|
-
_iterateNode(child, nextChild);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
if (node.is_open && element) {
|
|
642
|
-
this.handleAfterOpenFolder(node, nextNode);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
};
|
|
646
|
-
_iterateNode(this.tree, null);
|
|
647
|
-
}
|
|
670
|
+
// li
|
|
671
|
+
const li = document.createElement("li");
|
|
672
|
+
li.className = `jqtree_common ${folderClasses}`;
|
|
673
|
+
li.setAttribute("role", "none");
|
|
648
674
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
*/
|
|
655
|
-
}
|
|
675
|
+
// div
|
|
676
|
+
const div = document.createElement("div");
|
|
677
|
+
div.className = "jqtree-element jqtree_common";
|
|
678
|
+
div.setAttribute("role", "none");
|
|
679
|
+
li.appendChild(div);
|
|
656
680
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
generate() {
|
|
664
|
-
this.positions = [];
|
|
665
|
-
this.lastTop = 0;
|
|
666
|
-
this.iterate();
|
|
667
|
-
return this.generateHitAreas(this.positions);
|
|
668
|
-
}
|
|
669
|
-
generateHitAreas(positions) {
|
|
670
|
-
let previousTop = positions[0]?.top ?? 0;
|
|
671
|
-
let group = [];
|
|
672
|
-
const hitAreas = [];
|
|
673
|
-
for (const position of positions) {
|
|
674
|
-
if (position.top !== previousTop && group.length) {
|
|
675
|
-
this.generateHitAreasForGroup(hitAreas, group, previousTop, position.top);
|
|
676
|
-
previousTop = position.top;
|
|
677
|
-
group = [];
|
|
678
|
-
}
|
|
679
|
-
group.push(position);
|
|
680
|
-
}
|
|
681
|
-
this.generateHitAreasForGroup(hitAreas, group, previousTop, this.treeBottom);
|
|
682
|
-
return hitAreas;
|
|
683
|
-
}
|
|
684
|
-
handleOpenFolder(node, element) {
|
|
685
|
-
if (node === this.currentNode) {
|
|
686
|
-
// Cannot move inside current item
|
|
687
|
-
// Stop iterating
|
|
688
|
-
return false;
|
|
681
|
+
// button link
|
|
682
|
+
const buttonLink = document.createElement("a");
|
|
683
|
+
buttonLink.className = buttonClasses;
|
|
684
|
+
if (iconElement) {
|
|
685
|
+
buttonLink.appendChild(iconElement.cloneNode(true));
|
|
689
686
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
if (node.children[0] !== this.currentNode) {
|
|
693
|
-
this.addPosition(node, Position.Inside, getOffsetTop(element));
|
|
687
|
+
if (this.buttonLeft) {
|
|
688
|
+
div.appendChild(buttonLink);
|
|
694
689
|
}
|
|
695
690
|
|
|
696
|
-
//
|
|
697
|
-
|
|
691
|
+
// title span
|
|
692
|
+
const titleSpan = this.createTitleSpan(node.name, isSelected, true, level);
|
|
693
|
+
titleSpan.setAttribute("aria-expanded", getBoolString(node.is_open));
|
|
694
|
+
div.appendChild(titleSpan);
|
|
695
|
+
if (!this.buttonLeft) {
|
|
696
|
+
div.appendChild(buttonLink);
|
|
697
|
+
}
|
|
698
|
+
return li;
|
|
698
699
|
}
|
|
699
|
-
|
|
700
|
-
const
|
|
701
|
-
if (
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
this.addPosition(node, Position.Inside, top);
|
|
700
|
+
createNodeLi(node, level, isSelected) {
|
|
701
|
+
const liClasses = ["jqtree_common"];
|
|
702
|
+
if (isSelected) {
|
|
703
|
+
liClasses.push("jqtree-selected");
|
|
704
|
+
}
|
|
705
|
+
const classString = liClasses.join(" ");
|
|
706
706
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
707
|
+
// li
|
|
708
|
+
const li = document.createElement("li");
|
|
709
|
+
li.className = classString;
|
|
710
|
+
li.setAttribute("role", "none");
|
|
711
|
+
|
|
712
|
+
// div
|
|
713
|
+
const div = document.createElement("div");
|
|
714
|
+
div.className = "jqtree-element jqtree_common";
|
|
715
|
+
div.setAttribute("role", "none");
|
|
716
|
+
li.appendChild(div);
|
|
717
|
+
|
|
718
|
+
// title span
|
|
719
|
+
const titleSpan = this.createTitleSpan(node.name, isSelected, false, level);
|
|
720
|
+
div.appendChild(titleSpan);
|
|
721
|
+
return li;
|
|
722
|
+
}
|
|
723
|
+
createTitleSpan(nodeName, isSelected, isFolder, level) {
|
|
724
|
+
const titleSpan = document.createElement("span");
|
|
725
|
+
let classes = "jqtree-title jqtree_common";
|
|
726
|
+
if (isFolder) {
|
|
727
|
+
classes += " jqtree-title-folder";
|
|
728
|
+
}
|
|
729
|
+
classes += ` jqtree-title-button-${this.buttonLeft ? "left" : "right"}`;
|
|
730
|
+
titleSpan.className = classes;
|
|
731
|
+
if (isSelected) {
|
|
732
|
+
const tabIndex = this.tabIndex;
|
|
733
|
+
if (tabIndex !== undefined) {
|
|
734
|
+
titleSpan.setAttribute("tabindex", `${tabIndex}`);
|
|
710
735
|
}
|
|
711
736
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
737
|
+
this.setTreeItemAriaAttributes(titleSpan, nodeName, level, isSelected);
|
|
738
|
+
if (this.autoEscape) {
|
|
739
|
+
titleSpan.textContent = nodeName;
|
|
740
|
+
} else {
|
|
741
|
+
titleSpan.innerHTML = nodeName;
|
|
716
742
|
}
|
|
743
|
+
return titleSpan;
|
|
717
744
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
745
|
+
getButtonClasses(node) {
|
|
746
|
+
const classes = ["jqtree-toggler", "jqtree_common"];
|
|
747
|
+
if (!node.is_open) {
|
|
748
|
+
classes.push("jqtree-closed");
|
|
749
|
+
}
|
|
750
|
+
if (this.buttonLeft) {
|
|
751
|
+
classes.push("jqtree-toggler-left");
|
|
722
752
|
} else {
|
|
723
|
-
|
|
753
|
+
classes.push("jqtree-toggler-right");
|
|
724
754
|
}
|
|
755
|
+
return classes.join(" ");
|
|
725
756
|
}
|
|
726
|
-
|
|
727
|
-
const
|
|
728
|
-
if (node
|
|
729
|
-
|
|
730
|
-
this.addPosition(node, Position.None, top);
|
|
731
|
-
} else {
|
|
732
|
-
this.addPosition(node, Position.Inside, top);
|
|
757
|
+
getFolderClasses(node, isSelected) {
|
|
758
|
+
const classes = ["jqtree-folder"];
|
|
759
|
+
if (!node.is_open) {
|
|
760
|
+
classes.push("jqtree-closed");
|
|
733
761
|
}
|
|
734
|
-
if (
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
762
|
+
if (isSelected) {
|
|
763
|
+
classes.push("jqtree-selected");
|
|
764
|
+
}
|
|
765
|
+
if (node.is_loading) {
|
|
766
|
+
classes.push("jqtree-loading");
|
|
739
767
|
}
|
|
768
|
+
return classes.join(" ");
|
|
740
769
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const positionCount = Math.min(positionsInGroup.length, 4);
|
|
754
|
-
const areaHeight = Math.round((bottom - top) / positionCount);
|
|
755
|
-
let areaTop = top;
|
|
756
|
-
let i = 0;
|
|
757
|
-
while (i < positionCount) {
|
|
758
|
-
const position = positionsInGroup[i];
|
|
759
|
-
if (position) {
|
|
760
|
-
hitAreas.push({
|
|
761
|
-
top: areaTop,
|
|
762
|
-
bottom: areaTop + areaHeight,
|
|
763
|
-
node: position.node,
|
|
764
|
-
position: position.position
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
areaTop += areaHeight;
|
|
768
|
-
i += 1;
|
|
770
|
+
createButtonElement(value) {
|
|
771
|
+
if (typeof value === "string") {
|
|
772
|
+
// convert value to html
|
|
773
|
+
const div = document.createElement("div");
|
|
774
|
+
div.innerHTML = value;
|
|
775
|
+
return document.createTextNode(div.innerHTML);
|
|
776
|
+
} else if (value == null) {
|
|
777
|
+
return undefined;
|
|
778
|
+
} else if (value.nodeType) {
|
|
779
|
+
return value;
|
|
780
|
+
} else {
|
|
781
|
+
return jQuery(value)[0];
|
|
769
782
|
}
|
|
770
783
|
}
|
|
771
784
|
}
|
|
772
785
|
|
|
773
|
-
class
|
|
786
|
+
class DataLoader {
|
|
774
787
|
constructor(_ref) {
|
|
775
788
|
let {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
onCanMove,
|
|
782
|
-
onCanMoveTo,
|
|
783
|
-
onDragMove,
|
|
784
|
-
onDragStop,
|
|
785
|
-
onIsMoveHandle,
|
|
786
|
-
openNode,
|
|
787
|
-
refreshElements,
|
|
788
|
-
slide,
|
|
789
|
-
$treeElement,
|
|
789
|
+
dataFilter,
|
|
790
|
+
loadData,
|
|
791
|
+
onLoadFailed,
|
|
792
|
+
onLoading,
|
|
793
|
+
treeElement,
|
|
790
794
|
triggerEvent
|
|
791
795
|
} = _ref;
|
|
792
|
-
this.
|
|
793
|
-
this.
|
|
794
|
-
this.
|
|
795
|
-
this.
|
|
796
|
-
this.
|
|
797
|
-
this.onCanMove = onCanMove;
|
|
798
|
-
this.onCanMoveTo = onCanMoveTo;
|
|
799
|
-
this.onDragMove = onDragMove;
|
|
800
|
-
this.onDragStop = onDragStop;
|
|
801
|
-
this.onIsMoveHandle = onIsMoveHandle;
|
|
802
|
-
this.openNode = openNode;
|
|
803
|
-
this.refreshElements = refreshElements;
|
|
804
|
-
this.slide = slide;
|
|
805
|
-
this.$treeElement = $treeElement;
|
|
796
|
+
this.dataFilter = dataFilter;
|
|
797
|
+
this.loadData = loadData;
|
|
798
|
+
this.onLoadFailed = onLoadFailed;
|
|
799
|
+
this.onLoading = onLoading;
|
|
800
|
+
this.treeElement = treeElement;
|
|
806
801
|
this.triggerEvent = triggerEvent;
|
|
807
|
-
this.hoveredArea = null;
|
|
808
|
-
this.hitAreas = [];
|
|
809
|
-
this.isDragging = false;
|
|
810
|
-
this.currentItem = null;
|
|
811
802
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
|
-
if (this.onIsMoveHandle && !this.onIsMoveHandle(jQuery(element))) {
|
|
818
|
-
return null;
|
|
803
|
+
loadFromUrl(urlInfo, parentNode, onFinished) {
|
|
804
|
+
if (!urlInfo) {
|
|
805
|
+
return;
|
|
819
806
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
807
|
+
const element = this.getDomElement(parentNode);
|
|
808
|
+
this.addLoadingClass(element);
|
|
809
|
+
this.notifyLoading(true, parentNode, element);
|
|
810
|
+
const stopLoading = () => {
|
|
811
|
+
this.removeLoadingClass(element);
|
|
812
|
+
this.notifyLoading(false, parentNode, element);
|
|
813
|
+
};
|
|
814
|
+
const handleSuccess = data => {
|
|
815
|
+
stopLoading();
|
|
816
|
+
this.loadData(this.parseData(data), parentNode);
|
|
817
|
+
if (onFinished && typeof onFinished === "function") {
|
|
818
|
+
onFinished();
|
|
824
819
|
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
820
|
+
};
|
|
821
|
+
const handleError = jqXHR => {
|
|
822
|
+
stopLoading();
|
|
823
|
+
if (this.onLoadFailed) {
|
|
824
|
+
this.onLoadFailed(jqXHR);
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
this.submitRequest(urlInfo, handleSuccess, handleError);
|
|
828
828
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
829
|
+
addLoadingClass(element) {
|
|
830
|
+
element.classList.add("jqtree-loading");
|
|
831
|
+
}
|
|
832
|
+
removeLoadingClass(element) {
|
|
833
|
+
element.classList.remove("jqtree-loading");
|
|
834
|
+
}
|
|
835
|
+
getDomElement(parentNode) {
|
|
836
|
+
if (parentNode) {
|
|
837
|
+
return parentNode.element;
|
|
838
|
+
} else {
|
|
839
|
+
return this.treeElement;
|
|
832
840
|
}
|
|
833
|
-
this.refresh();
|
|
834
|
-
const offset = jQuery(positionInfo.target).offset();
|
|
835
|
-
const left = offset ? offset.left : 0;
|
|
836
|
-
const top = offset ? offset.top : 0;
|
|
837
|
-
const node = this.currentItem.node;
|
|
838
|
-
this.dragElement = new DragElement(node.name, positionInfo.pageX - left, positionInfo.pageY - top, this.$treeElement, this.autoEscape ?? true);
|
|
839
|
-
this.isDragging = true;
|
|
840
|
-
this.currentItem.element.classList.add("jqtree-moving");
|
|
841
|
-
return true;
|
|
842
841
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
842
|
+
notifyLoading(isLoading, node, element) {
|
|
843
|
+
const $el = jQuery(element);
|
|
844
|
+
if (this.onLoading) {
|
|
845
|
+
this.onLoading(isLoading, node, $el);
|
|
846
846
|
}
|
|
847
|
-
this.
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
847
|
+
this.triggerEvent("tree.loading_data", {
|
|
848
|
+
isLoading,
|
|
849
|
+
node,
|
|
850
|
+
$el
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
submitRequest(urlInfoInput, handleSuccess, handleError) {
|
|
854
|
+
const urlInfo = typeof urlInfoInput === "string" ? {
|
|
855
|
+
url: urlInfoInput
|
|
856
|
+
} : urlInfoInput;
|
|
857
|
+
const ajaxSettings = {
|
|
858
|
+
method: "GET",
|
|
859
|
+
cache: false,
|
|
860
|
+
dataType: "json",
|
|
861
|
+
success: handleSuccess,
|
|
862
|
+
error: handleError,
|
|
863
|
+
...urlInfo
|
|
864
|
+
};
|
|
865
|
+
ajaxSettings.method = ajaxSettings.method?.toUpperCase() || "GET";
|
|
866
|
+
void jQuery.ajax(ajaxSettings);
|
|
867
|
+
}
|
|
868
|
+
parseData(data) {
|
|
869
|
+
const getParsedData = () => {
|
|
870
|
+
if (typeof data === "string") {
|
|
871
|
+
return JSON.parse(data);
|
|
872
|
+
} else {
|
|
873
|
+
return data;
|
|
863
874
|
}
|
|
875
|
+
};
|
|
876
|
+
const parsedData = getParsedData();
|
|
877
|
+
if (this.dataFilter) {
|
|
878
|
+
return this.dataFilter(parsedData);
|
|
864
879
|
} else {
|
|
865
|
-
|
|
866
|
-
this.stopOpenFolderTimer();
|
|
867
|
-
this.hoveredArea = area;
|
|
868
|
-
}
|
|
869
|
-
if (!area) {
|
|
870
|
-
if (this.onDragMove) {
|
|
871
|
-
this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
|
|
872
|
-
}
|
|
880
|
+
return parsedData;
|
|
873
881
|
}
|
|
874
|
-
return true;
|
|
875
882
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
class KeyHandler {
|
|
886
|
+
constructor(_ref) {
|
|
887
|
+
let {
|
|
888
|
+
closeNode,
|
|
889
|
+
getSelectedNode,
|
|
890
|
+
isFocusOnTree,
|
|
891
|
+
keyboardSupport,
|
|
892
|
+
openNode,
|
|
893
|
+
selectNode
|
|
894
|
+
} = _ref;
|
|
895
|
+
this.closeNode = closeNode;
|
|
896
|
+
this.getSelectedNode = getSelectedNode;
|
|
897
|
+
this.isFocusOnTree = isFocusOnTree;
|
|
898
|
+
this.keyboardSupport = keyboardSupport;
|
|
899
|
+
this.openNode = openNode;
|
|
900
|
+
this.originalSelectNode = selectNode;
|
|
901
|
+
if (keyboardSupport) {
|
|
902
|
+
this.handleKeyDownHandler = this.handleKeyDown.bind(this);
|
|
903
|
+
document.addEventListener("keydown", this.handleKeyDownHandler);
|
|
886
904
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
}
|
|
905
|
+
}
|
|
906
|
+
deinit() {
|
|
907
|
+
if (this.handleKeyDownHandler) {
|
|
908
|
+
document.removeEventListener("keydown", this.handleKeyDownHandler);
|
|
892
909
|
}
|
|
893
|
-
return false;
|
|
894
910
|
}
|
|
895
|
-
|
|
896
|
-
this.
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
911
|
+
moveDown(selectedNode) {
|
|
912
|
+
return this.selectNode(selectedNode.getNextVisibleNode());
|
|
913
|
+
}
|
|
914
|
+
moveUp(selectedNode) {
|
|
915
|
+
return this.selectNode(selectedNode.getPreviousVisibleNode());
|
|
916
|
+
}
|
|
917
|
+
moveRight(selectedNode) {
|
|
918
|
+
if (!selectedNode.isFolder()) {
|
|
919
|
+
return true;
|
|
920
|
+
} else {
|
|
921
|
+
// folder node
|
|
922
|
+
if (selectedNode.is_open) {
|
|
923
|
+
// Right moves to the first child of an open node
|
|
924
|
+
return this.selectNode(selectedNode.getNextVisibleNode());
|
|
925
|
+
} else {
|
|
926
|
+
// Right expands a closed node
|
|
927
|
+
this.openNode(selectedNode);
|
|
928
|
+
return false;
|
|
902
929
|
}
|
|
903
930
|
}
|
|
904
931
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
this.
|
|
932
|
+
moveLeft(selectedNode) {
|
|
933
|
+
if (selectedNode.isFolder() && selectedNode.is_open) {
|
|
934
|
+
// Left on an open node closes the node
|
|
935
|
+
this.closeNode(selectedNode);
|
|
936
|
+
return false;
|
|
909
937
|
} else {
|
|
910
|
-
|
|
911
|
-
this.
|
|
938
|
+
// Left on a closed or end node moves focus to the node's parent
|
|
939
|
+
return this.selectNode(selectedNode.getParent());
|
|
912
940
|
}
|
|
913
941
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
return nodeName !== "INPUT" && nodeName !== "SELECT" && nodeName !== "TEXTAREA";
|
|
917
|
-
}
|
|
918
|
-
canMoveToArea(area) {
|
|
919
|
-
if (!this.onCanMoveTo) {
|
|
942
|
+
selectNode(node) {
|
|
943
|
+
if (!node) {
|
|
920
944
|
return true;
|
|
921
|
-
}
|
|
922
|
-
|
|
945
|
+
} else {
|
|
946
|
+
this.originalSelectNode(node);
|
|
923
947
|
return false;
|
|
924
948
|
}
|
|
925
|
-
const positionName = getPositionName(area.position);
|
|
926
|
-
return this.onCanMoveTo(this.currentItem.node, area.node, positionName);
|
|
927
949
|
}
|
|
928
|
-
|
|
929
|
-
this.
|
|
930
|
-
|
|
931
|
-
clear() {
|
|
932
|
-
if (this.dragElement) {
|
|
933
|
-
this.dragElement.remove();
|
|
934
|
-
this.dragElement = null;
|
|
950
|
+
handleKeyDown = e => {
|
|
951
|
+
if (!this.canHandleKeyboard()) {
|
|
952
|
+
return true;
|
|
935
953
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
this.previousGhost.remove();
|
|
954
|
+
const selectedNode = this.getSelectedNode();
|
|
955
|
+
if (!selectedNode) {
|
|
956
|
+
return true;
|
|
940
957
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
958
|
+
switch (e.key) {
|
|
959
|
+
case "ArrowDown":
|
|
960
|
+
return this.moveDown(selectedNode);
|
|
961
|
+
case "ArrowUp":
|
|
962
|
+
return this.moveUp(selectedNode);
|
|
963
|
+
case "ArrowRight":
|
|
964
|
+
return this.moveRight(selectedNode);
|
|
965
|
+
case "ArrowLeft":
|
|
966
|
+
return this.moveLeft(selectedNode);
|
|
967
|
+
default:
|
|
968
|
+
return true;
|
|
949
969
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
970
|
+
};
|
|
971
|
+
canHandleKeyboard() {
|
|
972
|
+
return this.keyboardSupport && this.isFocusOnTree();
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const getPositionInfoFromMouseEvent = e => ({
|
|
977
|
+
originalEvent: e,
|
|
978
|
+
pageX: e.pageX,
|
|
979
|
+
pageY: e.pageY,
|
|
980
|
+
target: e.target
|
|
981
|
+
});
|
|
982
|
+
const getPositionInfoFromTouch = (touch, e) => ({
|
|
983
|
+
originalEvent: e,
|
|
984
|
+
pageX: touch.pageX,
|
|
985
|
+
pageY: touch.pageY,
|
|
986
|
+
target: touch.target
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
class MouseHandler {
|
|
990
|
+
constructor(_ref) {
|
|
991
|
+
let {
|
|
992
|
+
element,
|
|
993
|
+
getMouseDelay,
|
|
994
|
+
getNode,
|
|
995
|
+
onClickButton,
|
|
996
|
+
onClickTitle,
|
|
997
|
+
onMouseCapture,
|
|
998
|
+
onMouseDrag,
|
|
999
|
+
onMouseStart,
|
|
1000
|
+
onMouseStop,
|
|
1001
|
+
triggerEvent,
|
|
1002
|
+
useContextMenu
|
|
1003
|
+
} = _ref;
|
|
1004
|
+
this.element = element;
|
|
1005
|
+
this.getMouseDelay = getMouseDelay;
|
|
1006
|
+
this.getNode = getNode;
|
|
1007
|
+
this.onClickButton = onClickButton;
|
|
1008
|
+
this.onClickTitle = onClickTitle;
|
|
1009
|
+
this.onMouseCapture = onMouseCapture;
|
|
1010
|
+
this.onMouseDrag = onMouseDrag;
|
|
1011
|
+
this.onMouseStart = onMouseStart;
|
|
1012
|
+
this.onMouseStop = onMouseStop;
|
|
1013
|
+
this.triggerEvent = triggerEvent;
|
|
1014
|
+
this.useContextMenu = useContextMenu;
|
|
1015
|
+
element.addEventListener("click", this.handleClick);
|
|
1016
|
+
element.addEventListener("dblclick", this.handleDblclick);
|
|
1017
|
+
element.addEventListener("mousedown", this.mouseDown, {
|
|
1018
|
+
passive: false
|
|
1019
|
+
});
|
|
1020
|
+
element.addEventListener("touchstart", this.touchStart, {
|
|
1021
|
+
passive: false
|
|
1022
|
+
});
|
|
1023
|
+
if (useContextMenu) {
|
|
1024
|
+
element.addEventListener("contextmenu", this.handleContextmenu);
|
|
965
1025
|
}
|
|
966
|
-
|
|
1026
|
+
this.isMouseStarted = false;
|
|
1027
|
+
this.mouseDelayTimer = null;
|
|
1028
|
+
this.isMouseDelayMet = false;
|
|
1029
|
+
this.mouseDownInfo = null;
|
|
967
1030
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1031
|
+
deinit() {
|
|
1032
|
+
this.element.removeEventListener("click", this.handleClick);
|
|
1033
|
+
this.element.removeEventListener("dblclick", this.handleDblclick);
|
|
1034
|
+
if (this.useContextMenu) {
|
|
1035
|
+
this.element.removeEventListener("contextmenu", this.handleContextmenu);
|
|
1036
|
+
}
|
|
1037
|
+
this.element.removeEventListener("mousedown", this.mouseDown);
|
|
1038
|
+
this.element.removeEventListener("touchstart", this.touchStart);
|
|
1039
|
+
this.removeMouseMoveEventListeners();
|
|
971
1040
|
}
|
|
972
|
-
|
|
973
|
-
|
|
1041
|
+
mouseDown = e => {
|
|
1042
|
+
// Left mouse button?
|
|
1043
|
+
if (e.button !== 0) {
|
|
974
1044
|
return;
|
|
975
1045
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1046
|
+
const result = this.handleMouseDown(getPositionInfoFromMouseEvent(e));
|
|
1047
|
+
if (result && e.cancelable) {
|
|
1048
|
+
e.preventDefault();
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
handleMouseDown(positionInfo) {
|
|
1052
|
+
// We may have missed mouseup (out of window)
|
|
1053
|
+
if (this.isMouseStarted) {
|
|
1054
|
+
this.handleMouseUp(positionInfo);
|
|
1055
|
+
}
|
|
1056
|
+
this.mouseDownInfo = positionInfo;
|
|
1057
|
+
if (!this.onMouseCapture(positionInfo)) {
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
this.handleStartMouse();
|
|
1061
|
+
return true;
|
|
983
1062
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
};
|
|
991
|
-
this.
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1063
|
+
handleStartMouse() {
|
|
1064
|
+
document.addEventListener("mousemove", this.mouseMove, {
|
|
1065
|
+
passive: false
|
|
1066
|
+
});
|
|
1067
|
+
document.addEventListener("touchmove", this.touchMove, {
|
|
1068
|
+
passive: false
|
|
1069
|
+
});
|
|
1070
|
+
document.addEventListener("mouseup", this.mouseUp, {
|
|
1071
|
+
passive: false
|
|
1072
|
+
});
|
|
1073
|
+
document.addEventListener("touchend", this.touchEnd, {
|
|
1074
|
+
passive: false
|
|
1075
|
+
});
|
|
1076
|
+
const mouseDelay = this.getMouseDelay();
|
|
1077
|
+
if (mouseDelay) {
|
|
1078
|
+
this.startMouseDelayTimer(mouseDelay);
|
|
1079
|
+
} else {
|
|
1080
|
+
this.isMouseDelayMet = true;
|
|
995
1081
|
}
|
|
996
1082
|
}
|
|
997
|
-
|
|
998
|
-
if (this.
|
|
999
|
-
clearTimeout(this.
|
|
1000
|
-
this.openFolderTimer = null;
|
|
1083
|
+
startMouseDelayTimer(mouseDelay) {
|
|
1084
|
+
if (this.mouseDelayTimer) {
|
|
1085
|
+
clearTimeout(this.mouseDelayTimer);
|
|
1001
1086
|
}
|
|
1087
|
+
this.mouseDelayTimer = window.setTimeout(() => {
|
|
1088
|
+
if (this.mouseDownInfo) {
|
|
1089
|
+
this.isMouseDelayMet = true;
|
|
1090
|
+
}
|
|
1091
|
+
}, mouseDelay);
|
|
1092
|
+
this.isMouseDelayMet = false;
|
|
1002
1093
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (
|
|
1010
|
-
|
|
1094
|
+
mouseMove = e => {
|
|
1095
|
+
this.handleMouseMove(e, getPositionInfoFromMouseEvent(e));
|
|
1096
|
+
};
|
|
1097
|
+
handleMouseMove(e, positionInfo) {
|
|
1098
|
+
if (this.isMouseStarted) {
|
|
1099
|
+
this.onMouseDrag(positionInfo);
|
|
1100
|
+
if (e.cancelable) {
|
|
1101
|
+
e.preventDefault();
|
|
1011
1102
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
position: getPositionName(position),
|
|
1025
|
-
previous_parent: previousParent,
|
|
1026
|
-
do_move: doMove,
|
|
1027
|
-
original_event: positionInfo.originalEvent
|
|
1028
|
-
}
|
|
1029
|
-
});
|
|
1030
|
-
if (!event.isDefaultPrevented()) {
|
|
1031
|
-
doMove();
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
if (!this.isMouseDelayMet) {
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
if (this.mouseDownInfo) {
|
|
1109
|
+
this.isMouseStarted = this.onMouseStart(this.mouseDownInfo) !== false;
|
|
1110
|
+
}
|
|
1111
|
+
if (this.isMouseStarted) {
|
|
1112
|
+
this.onMouseDrag(positionInfo);
|
|
1113
|
+
if (e.cancelable) {
|
|
1114
|
+
e.preventDefault();
|
|
1032
1115
|
}
|
|
1116
|
+
} else {
|
|
1117
|
+
this.handleMouseUp(positionInfo);
|
|
1033
1118
|
}
|
|
1034
1119
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
};
|
|
1046
|
-
} else {
|
|
1047
|
-
const el = this.$treeElement;
|
|
1048
|
-
const width = el.width() || 0;
|
|
1049
|
-
const height = el.height() || 0;
|
|
1050
|
-
const left = offset.left + this.getScrollLeft();
|
|
1051
|
-
return {
|
|
1052
|
-
left,
|
|
1053
|
-
top: offset.top,
|
|
1054
|
-
right: left + width,
|
|
1055
|
-
bottom: offset.top + height + 16
|
|
1056
|
-
};
|
|
1120
|
+
mouseUp = e => {
|
|
1121
|
+
this.handleMouseUp(getPositionInfoFromMouseEvent(e));
|
|
1122
|
+
};
|
|
1123
|
+
handleMouseUp(positionInfo) {
|
|
1124
|
+
this.removeMouseMoveEventListeners();
|
|
1125
|
+
this.isMouseDelayMet = false;
|
|
1126
|
+
this.mouseDownInfo = null;
|
|
1127
|
+
if (this.isMouseStarted) {
|
|
1128
|
+
this.isMouseStarted = false;
|
|
1129
|
+
this.onMouseStop(positionInfo);
|
|
1057
1130
|
}
|
|
1058
1131
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
autoEscape,
|
|
1065
|
-
buttonLeft,
|
|
1066
|
-
closedIcon,
|
|
1067
|
-
onCreateLi,
|
|
1068
|
-
dragAndDrop,
|
|
1069
|
-
$element,
|
|
1070
|
-
getTree,
|
|
1071
|
-
isNodeSelected,
|
|
1072
|
-
openedIcon,
|
|
1073
|
-
rtl,
|
|
1074
|
-
showEmptyFolder,
|
|
1075
|
-
tabIndex
|
|
1076
|
-
} = _ref;
|
|
1077
|
-
this.autoEscape = autoEscape;
|
|
1078
|
-
this.buttonLeft = buttonLeft;
|
|
1079
|
-
this.dragAndDrop = dragAndDrop;
|
|
1080
|
-
this.$element = $element;
|
|
1081
|
-
this.getTree = getTree;
|
|
1082
|
-
this.isNodeSelected = isNodeSelected;
|
|
1083
|
-
this.onCreateLi = onCreateLi;
|
|
1084
|
-
this.rtl = rtl;
|
|
1085
|
-
this.showEmptyFolder = showEmptyFolder;
|
|
1086
|
-
this.tabIndex = tabIndex;
|
|
1087
|
-
this.openedIconElement = this.createButtonElement(openedIcon || "+");
|
|
1088
|
-
this.closedIconElement = this.createButtonElement(closedIcon || "-");
|
|
1132
|
+
removeMouseMoveEventListeners() {
|
|
1133
|
+
document.removeEventListener("mousemove", this.mouseMove);
|
|
1134
|
+
document.removeEventListener("touchmove", this.touchMove);
|
|
1135
|
+
document.removeEventListener("mouseup", this.mouseUp);
|
|
1136
|
+
document.removeEventListener("touchend", this.touchEnd);
|
|
1089
1137
|
}
|
|
1090
|
-
|
|
1091
|
-
if (
|
|
1092
|
-
|
|
1093
|
-
} else {
|
|
1094
|
-
this.renderFromRoot();
|
|
1138
|
+
touchStart = e => {
|
|
1139
|
+
if (!e) {
|
|
1140
|
+
return;
|
|
1095
1141
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
this.$element.empty();
|
|
1099
|
-
const tree = this.getTree();
|
|
1100
|
-
if (this.$element[0] && tree) {
|
|
1101
|
-
this.createDomElements(this.$element[0], tree.children, true, 1);
|
|
1142
|
+
if (e.touches.length > 1) {
|
|
1143
|
+
return;
|
|
1102
1144
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
const $previousLi = jQuery(node.element);
|
|
1107
|
-
|
|
1108
|
-
// create element
|
|
1109
|
-
const li = this.createLi(node, node.getLevel());
|
|
1110
|
-
this.attachNodeData(node, li);
|
|
1111
|
-
|
|
1112
|
-
// add element to dom
|
|
1113
|
-
$previousLi.after(li);
|
|
1114
|
-
|
|
1115
|
-
// remove previous li
|
|
1116
|
-
$previousLi.remove();
|
|
1117
|
-
|
|
1118
|
-
// create children
|
|
1119
|
-
if (node.children) {
|
|
1120
|
-
this.createDomElements(li, node.children, false, node.getLevel() + 1);
|
|
1145
|
+
const touch = e.touches[0];
|
|
1146
|
+
if (!touch) {
|
|
1147
|
+
return;
|
|
1121
1148
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
const li = this.createLi(child, level);
|
|
1128
|
-
ul.appendChild(li);
|
|
1129
|
-
this.attachNodeData(child, li);
|
|
1130
|
-
if (child.hasChildren()) {
|
|
1131
|
-
this.createDomElements(li, child.children, false, level + 1);
|
|
1132
|
-
}
|
|
1149
|
+
this.handleMouseDown(getPositionInfoFromTouch(touch, e));
|
|
1150
|
+
};
|
|
1151
|
+
touchMove = e => {
|
|
1152
|
+
if (!e) {
|
|
1153
|
+
return;
|
|
1133
1154
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
node.element = li;
|
|
1137
|
-
jQuery(li).data("node", node);
|
|
1138
|
-
}
|
|
1139
|
-
createUl(isRootNode) {
|
|
1140
|
-
let classString;
|
|
1141
|
-
let role;
|
|
1142
|
-
if (!isRootNode) {
|
|
1143
|
-
classString = "";
|
|
1144
|
-
role = "group";
|
|
1145
|
-
} else {
|
|
1146
|
-
classString = "jqtree-tree";
|
|
1147
|
-
role = "tree";
|
|
1148
|
-
if (this.rtl) {
|
|
1149
|
-
classString += " jqtree-rtl";
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
if (this.dragAndDrop) {
|
|
1153
|
-
classString += " jqtree-dnd";
|
|
1155
|
+
if (e.touches.length > 1) {
|
|
1156
|
+
return;
|
|
1154
1157
|
}
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
return ul;
|
|
1159
|
-
}
|
|
1160
|
-
createLi(node, level) {
|
|
1161
|
-
const isSelected = Boolean(this.isNodeSelected(node));
|
|
1162
|
-
const mustShowFolder = node.isFolder() || node.isEmptyFolder && this.showEmptyFolder;
|
|
1163
|
-
const li = mustShowFolder ? this.createFolderLi(node, level, isSelected) : this.createNodeLi(node, level, isSelected);
|
|
1164
|
-
if (this.onCreateLi) {
|
|
1165
|
-
this.onCreateLi(node, jQuery(li), isSelected);
|
|
1158
|
+
const touch = e.touches[0];
|
|
1159
|
+
if (!touch) {
|
|
1160
|
+
return;
|
|
1166
1161
|
}
|
|
1167
|
-
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
element.setAttribute("aria-selected", getBoolString(isSelected));
|
|
1173
|
-
element.setAttribute("role", "treeitem");
|
|
1174
|
-
}
|
|
1175
|
-
createFolderLi(node, level, isSelected) {
|
|
1176
|
-
const buttonClasses = this.getButtonClasses(node);
|
|
1177
|
-
const folderClasses = this.getFolderClasses(node, isSelected);
|
|
1178
|
-
const iconElement = node.is_open ? this.openedIconElement : this.closedIconElement;
|
|
1179
|
-
|
|
1180
|
-
// li
|
|
1181
|
-
const li = document.createElement("li");
|
|
1182
|
-
li.className = `jqtree_common ${folderClasses}`;
|
|
1183
|
-
li.setAttribute("role", "none");
|
|
1184
|
-
|
|
1185
|
-
// div
|
|
1186
|
-
const div = document.createElement("div");
|
|
1187
|
-
div.className = "jqtree-element jqtree_common";
|
|
1188
|
-
div.setAttribute("role", "none");
|
|
1189
|
-
li.appendChild(div);
|
|
1190
|
-
|
|
1191
|
-
// button link
|
|
1192
|
-
const buttonLink = document.createElement("a");
|
|
1193
|
-
buttonLink.className = buttonClasses;
|
|
1194
|
-
if (iconElement) {
|
|
1195
|
-
buttonLink.appendChild(iconElement.cloneNode(true));
|
|
1162
|
+
this.handleMouseMove(e, getPositionInfoFromTouch(touch, e));
|
|
1163
|
+
};
|
|
1164
|
+
touchEnd = e => {
|
|
1165
|
+
if (!e) {
|
|
1166
|
+
return;
|
|
1196
1167
|
}
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1168
|
+
if (e.touches.length > 1) {
|
|
1169
|
+
return;
|
|
1199
1170
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
titleSpan.setAttribute("aria-expanded", getBoolString(node.is_open));
|
|
1204
|
-
div.appendChild(titleSpan);
|
|
1205
|
-
if (!this.buttonLeft) {
|
|
1206
|
-
div.appendChild(buttonLink);
|
|
1171
|
+
const touch = e.touches[0];
|
|
1172
|
+
if (!touch) {
|
|
1173
|
+
return;
|
|
1207
1174
|
}
|
|
1208
|
-
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
liClasses.push("jqtree-selected");
|
|
1175
|
+
this.handleMouseUp(getPositionInfoFromTouch(touch, e));
|
|
1176
|
+
};
|
|
1177
|
+
handleClick = e => {
|
|
1178
|
+
if (!e.target) {
|
|
1179
|
+
return;
|
|
1214
1180
|
}
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
const li = document.createElement("li");
|
|
1219
|
-
li.className = classString;
|
|
1220
|
-
li.setAttribute("role", "none");
|
|
1221
|
-
|
|
1222
|
-
// div
|
|
1223
|
-
const div = document.createElement("div");
|
|
1224
|
-
div.className = "jqtree-element jqtree_common";
|
|
1225
|
-
div.setAttribute("role", "none");
|
|
1226
|
-
li.appendChild(div);
|
|
1227
|
-
|
|
1228
|
-
// title span
|
|
1229
|
-
const titleSpan = this.createTitleSpan(node.name, isSelected, false, level);
|
|
1230
|
-
div.appendChild(titleSpan);
|
|
1231
|
-
return li;
|
|
1232
|
-
}
|
|
1233
|
-
createTitleSpan(nodeName, isSelected, isFolder, level) {
|
|
1234
|
-
const titleSpan = document.createElement("span");
|
|
1235
|
-
let classes = "jqtree-title jqtree_common";
|
|
1236
|
-
if (isFolder) {
|
|
1237
|
-
classes += " jqtree-title-folder";
|
|
1181
|
+
const clickTarget = this.getClickTarget(e.target);
|
|
1182
|
+
if (!clickTarget) {
|
|
1183
|
+
return;
|
|
1238
1184
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1185
|
+
if (clickTarget.type === "button") {
|
|
1186
|
+
this.onClickButton(clickTarget.node);
|
|
1187
|
+
e.preventDefault();
|
|
1188
|
+
e.stopPropagation();
|
|
1189
|
+
} else if (clickTarget.type === "label") {
|
|
1190
|
+
const event = this.triggerEvent("tree.click", {
|
|
1191
|
+
node: clickTarget.node,
|
|
1192
|
+
click_event: e
|
|
1193
|
+
});
|
|
1194
|
+
if (!event.isDefaultPrevented()) {
|
|
1195
|
+
this.onClickTitle(clickTarget.node);
|
|
1245
1196
|
}
|
|
1246
1197
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
titleSpan.innerHTML = nodeName;
|
|
1252
|
-
}
|
|
1253
|
-
return titleSpan;
|
|
1254
|
-
}
|
|
1255
|
-
getButtonClasses(node) {
|
|
1256
|
-
const classes = ["jqtree-toggler", "jqtree_common"];
|
|
1257
|
-
if (!node.is_open) {
|
|
1258
|
-
classes.push("jqtree-closed");
|
|
1259
|
-
}
|
|
1260
|
-
if (this.buttonLeft) {
|
|
1261
|
-
classes.push("jqtree-toggler-left");
|
|
1262
|
-
} else {
|
|
1263
|
-
classes.push("jqtree-toggler-right");
|
|
1198
|
+
};
|
|
1199
|
+
handleDblclick = e => {
|
|
1200
|
+
if (!e.target) {
|
|
1201
|
+
return;
|
|
1264
1202
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1203
|
+
const clickTarget = this.getClickTarget(e.target);
|
|
1204
|
+
if (clickTarget?.type === "label") {
|
|
1205
|
+
this.triggerEvent("tree.dblclick", {
|
|
1206
|
+
node: clickTarget.node,
|
|
1207
|
+
click_event: e
|
|
1208
|
+
});
|
|
1271
1209
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1210
|
+
};
|
|
1211
|
+
handleContextmenu = e => {
|
|
1212
|
+
if (!e.target) {
|
|
1213
|
+
return;
|
|
1274
1214
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1215
|
+
const div = e.target.closest("ul.jqtree-tree .jqtree-element");
|
|
1216
|
+
if (div) {
|
|
1217
|
+
const node = this.getNode(div);
|
|
1218
|
+
if (node) {
|
|
1219
|
+
e.preventDefault();
|
|
1220
|
+
e.stopPropagation();
|
|
1221
|
+
this.triggerEvent("tree.contextmenu", {
|
|
1222
|
+
node,
|
|
1223
|
+
click_event: e
|
|
1224
|
+
});
|
|
1225
|
+
return false;
|
|
1226
|
+
}
|
|
1277
1227
|
}
|
|
1278
|
-
return
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1228
|
+
return null;
|
|
1229
|
+
};
|
|
1230
|
+
getClickTarget(element) {
|
|
1231
|
+
const button = element.closest(".jqtree-toggler");
|
|
1232
|
+
if (button) {
|
|
1233
|
+
const node = this.getNode(button);
|
|
1234
|
+
if (node) {
|
|
1235
|
+
return {
|
|
1236
|
+
type: "button",
|
|
1237
|
+
node
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1290
1240
|
} else {
|
|
1291
|
-
|
|
1241
|
+
const jqTreeElement = element.closest(".jqtree-element");
|
|
1242
|
+
if (jqTreeElement) {
|
|
1243
|
+
const node = this.getNode(jqTreeElement);
|
|
1244
|
+
if (node) {
|
|
1245
|
+
return {
|
|
1246
|
+
type: "label",
|
|
1247
|
+
node
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1292
1251
|
}
|
|
1252
|
+
return null;
|
|
1293
1253
|
}
|
|
1294
1254
|
}
|
|
1295
1255
|
|
|
1296
|
-
class
|
|
1256
|
+
class SaveStateHandler {
|
|
1297
1257
|
constructor(_ref) {
|
|
1298
1258
|
let {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1259
|
+
addToSelection,
|
|
1260
|
+
getNodeById,
|
|
1261
|
+
getSelectedNodes,
|
|
1262
|
+
getTree,
|
|
1263
|
+
onGetStateFromStorage,
|
|
1264
|
+
onSetStateFromStorage,
|
|
1265
|
+
openNode,
|
|
1266
|
+
refreshElements,
|
|
1267
|
+
removeFromSelection,
|
|
1268
|
+
saveState
|
|
1305
1269
|
} = _ref;
|
|
1306
|
-
this.
|
|
1307
|
-
this.
|
|
1308
|
-
this.
|
|
1309
|
-
this.
|
|
1310
|
-
this
|
|
1311
|
-
this.
|
|
1270
|
+
this.addToSelection = addToSelection;
|
|
1271
|
+
this.getNodeById = getNodeById;
|
|
1272
|
+
this.getSelectedNodes = getSelectedNodes;
|
|
1273
|
+
this.getTree = getTree;
|
|
1274
|
+
this.onGetStateFromStorage = onGetStateFromStorage;
|
|
1275
|
+
this.onSetStateFromStorage = onSetStateFromStorage;
|
|
1276
|
+
this.openNode = openNode;
|
|
1277
|
+
this.refreshElements = refreshElements;
|
|
1278
|
+
this.removeFromSelection = removeFromSelection;
|
|
1279
|
+
this.saveStateOption = saveState;
|
|
1312
1280
|
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1281
|
+
saveState() {
|
|
1282
|
+
const state = JSON.stringify(this.getState());
|
|
1283
|
+
if (this.onSetStateFromStorage) {
|
|
1284
|
+
this.onSetStateFromStorage(state);
|
|
1285
|
+
} else if (this.supportsLocalStorage()) {
|
|
1286
|
+
localStorage.setItem(this.getKeyName(), state);
|
|
1316
1287
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
this.
|
|
1320
|
-
|
|
1321
|
-
this.
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1288
|
+
}
|
|
1289
|
+
getStateFromStorage() {
|
|
1290
|
+
const jsonData = this.loadFromStorage();
|
|
1291
|
+
if (jsonData) {
|
|
1292
|
+
return this.parseState(jsonData);
|
|
1293
|
+
} else {
|
|
1294
|
+
return null;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
getState() {
|
|
1298
|
+
const getOpenNodeIds = () => {
|
|
1299
|
+
const openNodes = [];
|
|
1300
|
+
this.getTree()?.iterate(node => {
|
|
1301
|
+
if (node.is_open && node.id && node.hasChildren()) {
|
|
1302
|
+
openNodes.push(node.id);
|
|
1303
|
+
}
|
|
1304
|
+
return true;
|
|
1305
|
+
});
|
|
1306
|
+
return openNodes;
|
|
1330
1307
|
};
|
|
1331
|
-
const
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1308
|
+
const getSelectedNodeIds = () => {
|
|
1309
|
+
const selectedNodeIds = [];
|
|
1310
|
+
this.getSelectedNodes().forEach(node => {
|
|
1311
|
+
if (node.id != null) {
|
|
1312
|
+
selectedNodeIds.push(node.id);
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
return selectedNodeIds;
|
|
1336
1316
|
};
|
|
1337
|
-
|
|
1317
|
+
return {
|
|
1318
|
+
open_nodes: getOpenNodeIds(),
|
|
1319
|
+
selected_node: getSelectedNodeIds()
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/*
|
|
1324
|
+
Set initial state
|
|
1325
|
+
Don't handle nodes that are loaded on demand
|
|
1326
|
+
result: must load on demand
|
|
1327
|
+
*/
|
|
1328
|
+
setInitialState(state) {
|
|
1329
|
+
if (!state) {
|
|
1330
|
+
return false;
|
|
1331
|
+
} else {
|
|
1332
|
+
let mustLoadOnDemand = false;
|
|
1333
|
+
if (state.open_nodes) {
|
|
1334
|
+
mustLoadOnDemand = this.openInitialNodes(state.open_nodes);
|
|
1335
|
+
}
|
|
1336
|
+
if (state.selected_node) {
|
|
1337
|
+
this.resetSelection();
|
|
1338
|
+
this.selectInitialNodes(state.selected_node);
|
|
1339
|
+
}
|
|
1340
|
+
return mustLoadOnDemand;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
setInitialStateOnDemand(state, cbFinished) {
|
|
1344
|
+
if (state) {
|
|
1345
|
+
this.doSetInitialStateOnDemand(state.open_nodes, state.selected_node, cbFinished);
|
|
1346
|
+
} else {
|
|
1347
|
+
cbFinished();
|
|
1348
|
+
}
|
|
1338
1349
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1350
|
+
getNodeIdToBeSelected() {
|
|
1351
|
+
const state = this.getStateFromStorage();
|
|
1352
|
+
if (state && state.selected_node) {
|
|
1353
|
+
return state.selected_node[0] || null;
|
|
1354
|
+
} else {
|
|
1355
|
+
return null;
|
|
1342
1356
|
}
|
|
1343
1357
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1358
|
+
parseState(jsonData) {
|
|
1359
|
+
const state = JSON.parse(jsonData);
|
|
1360
|
+
|
|
1361
|
+
// Check if selected_node is an int (instead of an array)
|
|
1362
|
+
if (state && state.selected_node && isInt(state.selected_node)) {
|
|
1363
|
+
// Convert to array
|
|
1364
|
+
state.selected_node = [state.selected_node];
|
|
1347
1365
|
}
|
|
1366
|
+
return state;
|
|
1348
1367
|
}
|
|
1349
|
-
|
|
1350
|
-
if (
|
|
1351
|
-
return
|
|
1368
|
+
loadFromStorage() {
|
|
1369
|
+
if (this.onGetStateFromStorage) {
|
|
1370
|
+
return this.onGetStateFromStorage();
|
|
1371
|
+
} else if (this.supportsLocalStorage()) {
|
|
1372
|
+
return localStorage.getItem(this.getKeyName());
|
|
1352
1373
|
} else {
|
|
1353
|
-
return
|
|
1374
|
+
return null;
|
|
1354
1375
|
}
|
|
1355
1376
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1377
|
+
openInitialNodes(nodeIds) {
|
|
1378
|
+
let mustLoadOnDemand = false;
|
|
1379
|
+
for (const nodeId of nodeIds) {
|
|
1380
|
+
const node = this.getNodeById(nodeId);
|
|
1381
|
+
if (node) {
|
|
1382
|
+
if (!node.load_on_demand) {
|
|
1383
|
+
node.is_open = true;
|
|
1384
|
+
} else {
|
|
1385
|
+
mustLoadOnDemand = true;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1359
1388
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1389
|
+
return mustLoadOnDemand;
|
|
1390
|
+
}
|
|
1391
|
+
selectInitialNodes(nodeIds) {
|
|
1392
|
+
let selectCount = 0;
|
|
1393
|
+
for (const nodeId of nodeIds) {
|
|
1394
|
+
const node = this.getNodeById(nodeId);
|
|
1395
|
+
if (node) {
|
|
1396
|
+
selectCount += 1;
|
|
1397
|
+
this.addToSelection(node);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return selectCount !== 0;
|
|
1401
|
+
}
|
|
1402
|
+
resetSelection() {
|
|
1403
|
+
const selectedNodes = this.getSelectedNodes();
|
|
1404
|
+
selectedNodes.forEach(node => {
|
|
1405
|
+
this.removeFromSelection(node);
|
|
1364
1406
|
});
|
|
1365
1407
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1408
|
+
doSetInitialStateOnDemand(nodeIdsParam, selectedNodes, cbFinished) {
|
|
1409
|
+
let loadingCount = 0;
|
|
1410
|
+
let nodeIds = nodeIdsParam;
|
|
1411
|
+
const openNodes = () => {
|
|
1412
|
+
const newNodesIds = [];
|
|
1413
|
+
for (const nodeId of nodeIds) {
|
|
1414
|
+
const node = this.getNodeById(nodeId);
|
|
1415
|
+
if (!node) {
|
|
1416
|
+
newNodesIds.push(nodeId);
|
|
1417
|
+
} else {
|
|
1418
|
+
if (!node.is_loading) {
|
|
1419
|
+
if (node.load_on_demand) {
|
|
1420
|
+
loadAndOpenNode(node);
|
|
1421
|
+
} else {
|
|
1422
|
+
this.openNode(node, false);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
nodeIds = newNodesIds;
|
|
1428
|
+
if (this.selectInitialNodes(selectedNodes)) {
|
|
1429
|
+
this.refreshElements(null);
|
|
1430
|
+
}
|
|
1431
|
+
if (loadingCount === 0) {
|
|
1432
|
+
cbFinished();
|
|
1433
|
+
}
|
|
1377
1434
|
};
|
|
1378
|
-
|
|
1379
|
-
|
|
1435
|
+
const loadAndOpenNode = node => {
|
|
1436
|
+
loadingCount += 1;
|
|
1437
|
+
this.openNode(node, false, () => {
|
|
1438
|
+
loadingCount -= 1;
|
|
1439
|
+
openNodes();
|
|
1440
|
+
});
|
|
1441
|
+
};
|
|
1442
|
+
openNodes();
|
|
1380
1443
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1444
|
+
getKeyName() {
|
|
1445
|
+
if (typeof this.saveStateOption === "string") {
|
|
1446
|
+
return this.saveStateOption;
|
|
1447
|
+
} else {
|
|
1448
|
+
return "tree";
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
supportsLocalStorage() {
|
|
1452
|
+
const testSupport = () => {
|
|
1453
|
+
// Is local storage supported?
|
|
1454
|
+
if (localStorage == null) {
|
|
1455
|
+
return false;
|
|
1385
1456
|
} else {
|
|
1386
|
-
|
|
1457
|
+
// Check if it's possible to store an item. Safari does not allow this in private browsing mode.
|
|
1458
|
+
try {
|
|
1459
|
+
const key = "_storage_test";
|
|
1460
|
+
sessionStorage.setItem(key, "value");
|
|
1461
|
+
sessionStorage.removeItem(key);
|
|
1462
|
+
} catch (error) {
|
|
1463
|
+
return false;
|
|
1464
|
+
}
|
|
1465
|
+
return true;
|
|
1387
1466
|
}
|
|
1388
1467
|
};
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
return this.dataFilter(parsedData);
|
|
1392
|
-
} else {
|
|
1393
|
-
return parsedData;
|
|
1468
|
+
if (this._supportsLocalStorage == null) {
|
|
1469
|
+
this._supportsLocalStorage = testSupport();
|
|
1394
1470
|
}
|
|
1471
|
+
return this._supportsLocalStorage;
|
|
1395
1472
|
}
|
|
1396
1473
|
}
|
|
1397
1474
|
|
|
1398
|
-
class
|
|
1475
|
+
class ContainerScrollParent {
|
|
1399
1476
|
constructor(_ref) {
|
|
1400
1477
|
let {
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
isFocusOnTree,
|
|
1404
|
-
keyboardSupport,
|
|
1405
|
-
openNode,
|
|
1406
|
-
selectNode
|
|
1478
|
+
container,
|
|
1479
|
+
refreshHitAreas
|
|
1407
1480
|
} = _ref;
|
|
1408
|
-
this.
|
|
1409
|
-
this.
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
this.
|
|
1414
|
-
|
|
1415
|
-
this.
|
|
1416
|
-
|
|
1481
|
+
this.container = container;
|
|
1482
|
+
this.refreshHitAreas = refreshHitAreas;
|
|
1483
|
+
}
|
|
1484
|
+
checkHorizontalScrolling(pageX) {
|
|
1485
|
+
const newHorizontalScrollDirection = this.getNewHorizontalScrollDirection(pageX);
|
|
1486
|
+
if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
|
|
1487
|
+
this.horizontalScrollDirection = newHorizontalScrollDirection;
|
|
1488
|
+
if (this.horizontalScrollTimeout != null) {
|
|
1489
|
+
window.clearTimeout(this.verticalScrollTimeout);
|
|
1490
|
+
}
|
|
1491
|
+
if (newHorizontalScrollDirection) {
|
|
1492
|
+
this.horizontalScrollTimeout = window.setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
1493
|
+
}
|
|
1417
1494
|
}
|
|
1418
1495
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1496
|
+
checkVerticalScrolling(pageY) {
|
|
1497
|
+
const newVerticalScrollDirection = this.getNewVerticalScrollDirection(pageY);
|
|
1498
|
+
if (this.verticalScrollDirection !== newVerticalScrollDirection) {
|
|
1499
|
+
this.verticalScrollDirection = newVerticalScrollDirection;
|
|
1500
|
+
if (this.verticalScrollTimeout != null) {
|
|
1501
|
+
window.clearTimeout(this.verticalScrollTimeout);
|
|
1502
|
+
this.verticalScrollTimeout = undefined;
|
|
1503
|
+
}
|
|
1504
|
+
if (newVerticalScrollDirection) {
|
|
1505
|
+
this.verticalScrollTimeout = window.setTimeout(this.scrollVertically.bind(this), 40);
|
|
1506
|
+
}
|
|
1422
1507
|
}
|
|
1423
1508
|
}
|
|
1424
|
-
|
|
1425
|
-
return this.
|
|
1509
|
+
getScrollLeft() {
|
|
1510
|
+
return this.container.scrollLeft;
|
|
1426
1511
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1512
|
+
scrollToY(top) {
|
|
1513
|
+
this.container.scrollTop = top;
|
|
1429
1514
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1515
|
+
stopScrolling() {
|
|
1516
|
+
this.horizontalScrollDirection = undefined;
|
|
1517
|
+
this.verticalScrollDirection = undefined;
|
|
1518
|
+
this.scrollParentTop = undefined;
|
|
1519
|
+
this.scrollParentBottom = undefined;
|
|
1520
|
+
}
|
|
1521
|
+
getNewHorizontalScrollDirection(pageX) {
|
|
1522
|
+
const scrollParentOffset = getElementPosition(this.container);
|
|
1523
|
+
const rightEdge = scrollParentOffset.left + this.container.clientWidth;
|
|
1524
|
+
const leftEdge = scrollParentOffset.left;
|
|
1525
|
+
const isNearRightEdge = pageX > rightEdge - 20;
|
|
1526
|
+
const isNearLeftEdge = pageX < leftEdge + 20;
|
|
1527
|
+
if (isNearRightEdge) {
|
|
1528
|
+
return "right";
|
|
1529
|
+
} else if (isNearLeftEdge) {
|
|
1530
|
+
return "left";
|
|
1443
1531
|
}
|
|
1532
|
+
return undefined;
|
|
1444
1533
|
}
|
|
1445
|
-
|
|
1446
|
-
if (
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
// Left on a closed or end node moves focus to the node's parent
|
|
1452
|
-
return this.selectNode(selectedNode.getParent());
|
|
1534
|
+
getNewVerticalScrollDirection(pageY) {
|
|
1535
|
+
if (pageY < this.getScrollParentTop()) {
|
|
1536
|
+
return "top";
|
|
1537
|
+
}
|
|
1538
|
+
if (pageY > this.getScrollParentBottom()) {
|
|
1539
|
+
return "bottom";
|
|
1453
1540
|
}
|
|
1541
|
+
return undefined;
|
|
1454
1542
|
}
|
|
1455
|
-
|
|
1456
|
-
if (!
|
|
1457
|
-
return
|
|
1458
|
-
} else {
|
|
1459
|
-
this.originalSelectNode(node);
|
|
1460
|
-
return false;
|
|
1543
|
+
scrollHorizontally() {
|
|
1544
|
+
if (!this.horizontalScrollDirection) {
|
|
1545
|
+
return;
|
|
1461
1546
|
}
|
|
1547
|
+
const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
|
|
1548
|
+
this.container.scrollBy({
|
|
1549
|
+
left: distance,
|
|
1550
|
+
top: 0,
|
|
1551
|
+
behavior: "instant"
|
|
1552
|
+
});
|
|
1553
|
+
this.refreshHitAreas();
|
|
1554
|
+
setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
1462
1555
|
}
|
|
1463
|
-
|
|
1464
|
-
if (!this.
|
|
1465
|
-
return
|
|
1556
|
+
scrollVertically() {
|
|
1557
|
+
if (!this.verticalScrollDirection) {
|
|
1558
|
+
return;
|
|
1466
1559
|
}
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1560
|
+
const distance = this.verticalScrollDirection === "top" ? -20 : 20;
|
|
1561
|
+
this.container.scrollBy({
|
|
1562
|
+
left: 0,
|
|
1563
|
+
top: distance,
|
|
1564
|
+
behavior: "instant"
|
|
1565
|
+
});
|
|
1566
|
+
this.refreshHitAreas();
|
|
1567
|
+
setTimeout(this.scrollVertically.bind(this), 40);
|
|
1568
|
+
}
|
|
1569
|
+
getScrollParentTop() {
|
|
1570
|
+
if (this.scrollParentTop == null) {
|
|
1571
|
+
this.scrollParentTop = getOffsetTop(this.container);
|
|
1470
1572
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
case "ArrowRight":
|
|
1477
|
-
return this.moveRight(selectedNode);
|
|
1478
|
-
case "ArrowLeft":
|
|
1479
|
-
return this.moveLeft(selectedNode);
|
|
1480
|
-
default:
|
|
1481
|
-
return true;
|
|
1573
|
+
return this.scrollParentTop;
|
|
1574
|
+
}
|
|
1575
|
+
getScrollParentBottom() {
|
|
1576
|
+
if (this.scrollParentBottom == null) {
|
|
1577
|
+
this.scrollParentBottom = this.getScrollParentTop() + this.container.clientHeight;
|
|
1482
1578
|
}
|
|
1483
|
-
|
|
1484
|
-
canHandleKeyboard() {
|
|
1485
|
-
return this.keyboardSupport && this.isFocusOnTree();
|
|
1579
|
+
return this.scrollParentBottom;
|
|
1486
1580
|
}
|
|
1487
1581
|
}
|
|
1488
1582
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
const simpleWidgetClass = widgetClass;
|
|
1505
|
-
const widget = new simpleWidgetClass(el, options);
|
|
1506
|
-
if (!jQuery.data(el, dataKey)) {
|
|
1507
|
-
jQuery.data(el, dataKey, widget);
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
// Call init after setting data, so we can call methods
|
|
1511
|
-
widget.init();
|
|
1583
|
+
class DocumentScrollParent {
|
|
1584
|
+
constructor(_ref) {
|
|
1585
|
+
let {
|
|
1586
|
+
refreshHitAreas,
|
|
1587
|
+
treeElement
|
|
1588
|
+
} = _ref;
|
|
1589
|
+
this.refreshHitAreas = refreshHitAreas;
|
|
1590
|
+
this.treeElement = treeElement;
|
|
1591
|
+
}
|
|
1592
|
+
checkHorizontalScrolling(pageX) {
|
|
1593
|
+
const newHorizontalScrollDirection = this.getNewHorizontalScrollDirection(pageX);
|
|
1594
|
+
if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
|
|
1595
|
+
this.horizontalScrollDirection = newHorizontalScrollDirection;
|
|
1596
|
+
if (this.horizontalScrollTimeout != null) {
|
|
1597
|
+
window.clearTimeout(this.horizontalScrollTimeout);
|
|
1512
1598
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
};
|
|
1516
|
-
const destroyWidget = $el => {
|
|
1517
|
-
const dataKey = getDataKey();
|
|
1518
|
-
for (const el of $el.get()) {
|
|
1519
|
-
const widget = getWidgetData(el, dataKey);
|
|
1520
|
-
if (widget) {
|
|
1521
|
-
widget.destroy();
|
|
1599
|
+
if (newHorizontalScrollDirection) {
|
|
1600
|
+
this.horizontalScrollTimeout = window.setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
1522
1601
|
}
|
|
1523
|
-
jQuery.removeData(el, dataKey);
|
|
1524
1602
|
}
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
if (
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
if (widgetFunction && typeof widgetFunction === "function") {
|
|
1534
|
-
result = widgetFunction.apply(widget, args);
|
|
1535
|
-
}
|
|
1603
|
+
}
|
|
1604
|
+
checkVerticalScrolling(pageY) {
|
|
1605
|
+
const newVerticalScrollDirection = this.getNewVerticalScrollDirection(pageY);
|
|
1606
|
+
if (this.verticalScrollDirection !== newVerticalScrollDirection) {
|
|
1607
|
+
this.verticalScrollDirection = newVerticalScrollDirection;
|
|
1608
|
+
if (this.verticalScrollTimeout != null) {
|
|
1609
|
+
window.clearTimeout(this.verticalScrollTimeout);
|
|
1610
|
+
this.verticalScrollTimeout = undefined;
|
|
1536
1611
|
}
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
};
|
|
1540
|
-
|
|
1541
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1542
|
-
jQuery.fn[widgetName] = function (argument1) {
|
|
1543
|
-
if (!argument1) {
|
|
1544
|
-
return createWidget(this, null);
|
|
1545
|
-
} else if (typeof argument1 === "object") {
|
|
1546
|
-
const options = argument1;
|
|
1547
|
-
return createWidget(this, options);
|
|
1548
|
-
} else if (typeof argument1 === "string" && argument1[0] !== "_") {
|
|
1549
|
-
const functionName = argument1;
|
|
1550
|
-
if (functionName === "destroy") {
|
|
1551
|
-
return destroyWidget(this);
|
|
1552
|
-
} else if (functionName === "get_widget_class") {
|
|
1553
|
-
return widgetClass;
|
|
1554
|
-
} else {
|
|
1555
|
-
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
1556
|
-
args[_key - 1] = arguments[_key];
|
|
1557
|
-
}
|
|
1558
|
-
return callFunction(this, functionName, args);
|
|
1612
|
+
if (newVerticalScrollDirection) {
|
|
1613
|
+
this.verticalScrollTimeout = window.setTimeout(this.scrollVertically.bind(this), 40);
|
|
1559
1614
|
}
|
|
1560
|
-
} else {
|
|
1561
|
-
return undefined;
|
|
1562
1615
|
}
|
|
1563
|
-
};
|
|
1564
|
-
};
|
|
1565
|
-
class SimpleWidget {
|
|
1566
|
-
static register(widgetClass, widgetName) {
|
|
1567
|
-
register(widgetClass, widgetName);
|
|
1568
|
-
}
|
|
1569
|
-
static defaults = {};
|
|
1570
|
-
constructor(el, options) {
|
|
1571
|
-
this.$el = jQuery(el);
|
|
1572
|
-
|
|
1573
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1574
|
-
const defaults = this.constructor["defaults"];
|
|
1575
|
-
this.options = {
|
|
1576
|
-
...defaults,
|
|
1577
|
-
...options
|
|
1578
|
-
};
|
|
1579
1616
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1617
|
+
getScrollLeft() {
|
|
1618
|
+
return document.documentElement.scrollLeft;
|
|
1582
1619
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1620
|
+
scrollToY(top) {
|
|
1621
|
+
const treeTop = getOffsetTop(this.treeElement);
|
|
1622
|
+
document.documentElement.scrollTop = top + treeTop;
|
|
1585
1623
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1624
|
+
stopScrolling() {
|
|
1625
|
+
this.horizontalScrollDirection = undefined;
|
|
1626
|
+
this.verticalScrollDirection = undefined;
|
|
1627
|
+
this.documentScrollHeight = undefined;
|
|
1628
|
+
this.documentScrollWidth = undefined;
|
|
1588
1629
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
pageY: e.pageY,
|
|
1597
|
-
target: e.target,
|
|
1598
|
-
originalEvent: e
|
|
1599
|
-
});
|
|
1600
|
-
const getPositionInfoFromTouch = (touch, e) => ({
|
|
1601
|
-
pageX: touch.pageX,
|
|
1602
|
-
pageY: touch.pageY,
|
|
1603
|
-
target: touch.target,
|
|
1604
|
-
originalEvent: e
|
|
1605
|
-
});
|
|
1606
|
-
class MouseWidget extends SimpleWidget {
|
|
1607
|
-
init() {
|
|
1608
|
-
const element = this.$el.get(0);
|
|
1609
|
-
if (element) {
|
|
1610
|
-
element.addEventListener("mousedown", this.mouseDown, {
|
|
1611
|
-
passive: false
|
|
1612
|
-
});
|
|
1613
|
-
element.addEventListener("touchstart", this.touchStart, {
|
|
1614
|
-
passive: false
|
|
1615
|
-
});
|
|
1630
|
+
getNewHorizontalScrollDirection(pageX) {
|
|
1631
|
+
const scrollLeft = document.documentElement.scrollLeft;
|
|
1632
|
+
const windowWidth = window.innerWidth;
|
|
1633
|
+
const isNearRightEdge = pageX > windowWidth - 20;
|
|
1634
|
+
const isNearLeftEdge = pageX - scrollLeft < 20;
|
|
1635
|
+
if (isNearRightEdge && this.canScrollRight()) {
|
|
1636
|
+
return "right";
|
|
1616
1637
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
this.isMouseDelayMet = false;
|
|
1620
|
-
this.mouseDownInfo = null;
|
|
1621
|
-
}
|
|
1622
|
-
deinit() {
|
|
1623
|
-
const el = this.$el.get(0);
|
|
1624
|
-
if (el) {
|
|
1625
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
1626
|
-
el.removeEventListener("mousedown", this.mouseDown, {
|
|
1627
|
-
passive: false
|
|
1628
|
-
});
|
|
1629
|
-
|
|
1630
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
1631
|
-
el.removeEventListener("touchstart", this.touchStart, {
|
|
1632
|
-
passive: false
|
|
1633
|
-
});
|
|
1638
|
+
if (isNearLeftEdge) {
|
|
1639
|
+
return "left";
|
|
1634
1640
|
}
|
|
1635
|
-
|
|
1641
|
+
return undefined;
|
|
1636
1642
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
if (this.isMouseStarted) {
|
|
1650
|
-
this.handleMouseUp(positionInfo);
|
|
1651
|
-
}
|
|
1652
|
-
this.mouseDownInfo = positionInfo;
|
|
1653
|
-
if (!this.mouseCapture(positionInfo)) {
|
|
1654
|
-
return false;
|
|
1643
|
+
canScrollRight() {
|
|
1644
|
+
const documentElement = document.documentElement;
|
|
1645
|
+
return documentElement.scrollLeft + documentElement.clientWidth < this.getDocumentScrollWidth();
|
|
1646
|
+
}
|
|
1647
|
+
canScrollDown() {
|
|
1648
|
+
const documentElement = document.documentElement;
|
|
1649
|
+
return documentElement.scrollTop + documentElement.clientHeight < this.getDocumentScrollHeight();
|
|
1650
|
+
}
|
|
1651
|
+
getDocumentScrollHeight() {
|
|
1652
|
+
// Store the original scroll height because the scroll height can increase when the drag element is moved beyond the scroll height.
|
|
1653
|
+
if (this.documentScrollHeight == null) {
|
|
1654
|
+
this.documentScrollHeight = document.documentElement.scrollHeight;
|
|
1655
1655
|
}
|
|
1656
|
-
this.
|
|
1657
|
-
return true;
|
|
1656
|
+
return this.documentScrollHeight;
|
|
1658
1657
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
document.addEventListener("touchmove", this.touchMove, {
|
|
1664
|
-
passive: false
|
|
1665
|
-
});
|
|
1666
|
-
document.addEventListener("mouseup", this.mouseUp, {
|
|
1667
|
-
passive: false
|
|
1668
|
-
});
|
|
1669
|
-
document.addEventListener("touchend", this.touchEnd, {
|
|
1670
|
-
passive: false
|
|
1671
|
-
});
|
|
1672
|
-
const mouseDelay = this.getMouseDelay();
|
|
1673
|
-
if (mouseDelay) {
|
|
1674
|
-
this.startMouseDelayTimer(mouseDelay);
|
|
1675
|
-
} else {
|
|
1676
|
-
this.isMouseDelayMet = true;
|
|
1658
|
+
getDocumentScrollWidth() {
|
|
1659
|
+
// Store the original scroll width because the scroll width can increase when the drag element is moved beyond the scroll width.
|
|
1660
|
+
if (this.documentScrollWidth == null) {
|
|
1661
|
+
this.documentScrollWidth = document.documentElement.scrollWidth;
|
|
1677
1662
|
}
|
|
1663
|
+
return this.documentScrollWidth;
|
|
1678
1664
|
}
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1665
|
+
getNewVerticalScrollDirection(pageY) {
|
|
1666
|
+
const scrollTop = jQuery(document).scrollTop() || 0;
|
|
1667
|
+
const distanceTop = pageY - scrollTop;
|
|
1668
|
+
if (distanceTop < 20) {
|
|
1669
|
+
return "top";
|
|
1682
1670
|
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
this.isMouseDelayMet = false;
|
|
1671
|
+
const windowHeight = window.innerHeight;
|
|
1672
|
+
if (windowHeight - (pageY - scrollTop) < 20 && this.canScrollDown()) {
|
|
1673
|
+
return "bottom";
|
|
1674
|
+
}
|
|
1675
|
+
return undefined;
|
|
1689
1676
|
}
|
|
1690
|
-
|
|
1691
|
-
this.
|
|
1692
|
-
};
|
|
1693
|
-
handleMouseMove(e, positionInfo) {
|
|
1694
|
-
if (this.isMouseStarted) {
|
|
1695
|
-
this.mouseDrag(positionInfo);
|
|
1696
|
-
if (e.cancelable) {
|
|
1697
|
-
e.preventDefault();
|
|
1698
|
-
}
|
|
1677
|
+
scrollHorizontally() {
|
|
1678
|
+
if (!this.horizontalScrollDirection) {
|
|
1699
1679
|
return;
|
|
1700
1680
|
}
|
|
1701
|
-
|
|
1681
|
+
const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
|
|
1682
|
+
window.scrollBy({
|
|
1683
|
+
left: distance,
|
|
1684
|
+
top: 0,
|
|
1685
|
+
behavior: "instant"
|
|
1686
|
+
});
|
|
1687
|
+
this.refreshHitAreas();
|
|
1688
|
+
setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
1689
|
+
}
|
|
1690
|
+
scrollVertically() {
|
|
1691
|
+
if (!this.verticalScrollDirection) {
|
|
1702
1692
|
return;
|
|
1703
1693
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
} else {
|
|
1713
|
-
this.handleMouseUp(positionInfo);
|
|
1714
|
-
}
|
|
1694
|
+
const distance = this.verticalScrollDirection === "top" ? -20 : 20;
|
|
1695
|
+
window.scrollBy({
|
|
1696
|
+
left: 0,
|
|
1697
|
+
top: distance,
|
|
1698
|
+
behavior: "instant"
|
|
1699
|
+
});
|
|
1700
|
+
this.refreshHitAreas();
|
|
1701
|
+
setTimeout(this.scrollVertically.bind(this), 40);
|
|
1715
1702
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
const isOverflow = overflowValue => overflowValue === "auto" || overflowValue === "scroll";
|
|
1706
|
+
const hasOverFlow = element => {
|
|
1707
|
+
const style = getComputedStyle(element);
|
|
1708
|
+
return isOverflow(style.overflowX) || isOverflow(style.overflowY);
|
|
1709
|
+
};
|
|
1710
|
+
const getParentWithOverflow = treeElement => {
|
|
1711
|
+
if (hasOverFlow(treeElement)) {
|
|
1712
|
+
return treeElement;
|
|
1713
|
+
}
|
|
1714
|
+
let parent = treeElement.parentElement;
|
|
1715
|
+
while (parent) {
|
|
1716
|
+
if (hasOverFlow(parent)) {
|
|
1717
|
+
return parent;
|
|
1726
1718
|
}
|
|
1719
|
+
parent = parent.parentElement;
|
|
1727
1720
|
}
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
});
|
|
1737
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
1738
|
-
document.removeEventListener("mouseup", this.mouseUp, {
|
|
1739
|
-
passive: false
|
|
1721
|
+
return null;
|
|
1722
|
+
};
|
|
1723
|
+
const createScrollParent = (treeElement, refreshHitAreas) => {
|
|
1724
|
+
const container = getParentWithOverflow(treeElement);
|
|
1725
|
+
if (container && container.tagName !== "HTML") {
|
|
1726
|
+
return new ContainerScrollParent({
|
|
1727
|
+
container,
|
|
1728
|
+
refreshHitAreas
|
|
1740
1729
|
});
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1730
|
+
} else {
|
|
1731
|
+
return new DocumentScrollParent({
|
|
1732
|
+
refreshHitAreas,
|
|
1733
|
+
treeElement
|
|
1744
1734
|
});
|
|
1745
1735
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
if (!touch) {
|
|
1781
|
-
return;
|
|
1736
|
+
};
|
|
1737
|
+
|
|
1738
|
+
class ScrollHandler {
|
|
1739
|
+
constructor(_ref) {
|
|
1740
|
+
let {
|
|
1741
|
+
refreshHitAreas,
|
|
1742
|
+
treeElement
|
|
1743
|
+
} = _ref;
|
|
1744
|
+
this.refreshHitAreas = refreshHitAreas;
|
|
1745
|
+
this.scrollParent = undefined;
|
|
1746
|
+
this.treeElement = treeElement;
|
|
1747
|
+
}
|
|
1748
|
+
checkScrolling(positionInfo) {
|
|
1749
|
+
this.checkVerticalScrolling(positionInfo);
|
|
1750
|
+
this.checkHorizontalScrolling(positionInfo);
|
|
1751
|
+
}
|
|
1752
|
+
stopScrolling() {
|
|
1753
|
+
this.getScrollParent().stopScrolling();
|
|
1754
|
+
}
|
|
1755
|
+
scrollToY(top) {
|
|
1756
|
+
this.getScrollParent().scrollToY(top);
|
|
1757
|
+
}
|
|
1758
|
+
getScrollLeft() {
|
|
1759
|
+
return this.getScrollParent().getScrollLeft();
|
|
1760
|
+
}
|
|
1761
|
+
checkVerticalScrolling(positionInfo) {
|
|
1762
|
+
this.getScrollParent().checkVerticalScrolling(positionInfo.pageY);
|
|
1763
|
+
}
|
|
1764
|
+
checkHorizontalScrolling(positionInfo) {
|
|
1765
|
+
this.getScrollParent().checkHorizontalScrolling(positionInfo.pageX);
|
|
1766
|
+
}
|
|
1767
|
+
getScrollParent() {
|
|
1768
|
+
if (!this.scrollParent) {
|
|
1769
|
+
this.scrollParent = createScrollParent(this.treeElement, this.refreshHitAreas);
|
|
1782
1770
|
}
|
|
1783
|
-
this.
|
|
1784
|
-
}
|
|
1771
|
+
return this.scrollParent;
|
|
1772
|
+
}
|
|
1785
1773
|
}
|
|
1786
1774
|
|
|
1787
|
-
class
|
|
1775
|
+
class SelectNodeHandler {
|
|
1788
1776
|
constructor(_ref) {
|
|
1789
1777
|
let {
|
|
1790
|
-
|
|
1791
|
-
getNodeById,
|
|
1792
|
-
getSelectedNodes,
|
|
1793
|
-
getTree,
|
|
1794
|
-
onGetStateFromStorage,
|
|
1795
|
-
onSetStateFromStorage,
|
|
1796
|
-
openNode,
|
|
1797
|
-
refreshElements,
|
|
1798
|
-
removeFromSelection,
|
|
1799
|
-
saveState
|
|
1778
|
+
getNodeById
|
|
1800
1779
|
} = _ref;
|
|
1801
|
-
this.addToSelection = addToSelection;
|
|
1802
1780
|
this.getNodeById = getNodeById;
|
|
1803
|
-
this.
|
|
1804
|
-
this.
|
|
1805
|
-
this.onGetStateFromStorage = onGetStateFromStorage;
|
|
1806
|
-
this.onSetStateFromStorage = onSetStateFromStorage;
|
|
1807
|
-
this.openNode = openNode;
|
|
1808
|
-
this.refreshElements = refreshElements;
|
|
1809
|
-
this.removeFromSelection = removeFromSelection;
|
|
1810
|
-
this.saveStateOption = saveState;
|
|
1781
|
+
this.selectedNodes = new Set();
|
|
1782
|
+
this.clear();
|
|
1811
1783
|
}
|
|
1812
|
-
|
|
1813
|
-
const
|
|
1814
|
-
if (
|
|
1815
|
-
|
|
1816
|
-
} else
|
|
1817
|
-
|
|
1784
|
+
getSelectedNode() {
|
|
1785
|
+
const selectedNodes = this.getSelectedNodes();
|
|
1786
|
+
if (selectedNodes.length) {
|
|
1787
|
+
return selectedNodes[0] || false;
|
|
1788
|
+
} else {
|
|
1789
|
+
return false;
|
|
1818
1790
|
}
|
|
1819
1791
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
return this.parseState(jsonData);
|
|
1792
|
+
getSelectedNodes() {
|
|
1793
|
+
if (this.selectedSingleNode) {
|
|
1794
|
+
return [this.selectedSingleNode];
|
|
1824
1795
|
} else {
|
|
1825
|
-
|
|
1796
|
+
const selectedNodes = [];
|
|
1797
|
+
this.selectedNodes.forEach(id => {
|
|
1798
|
+
const node = this.getNodeById(id);
|
|
1799
|
+
if (node) {
|
|
1800
|
+
selectedNodes.push(node);
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
return selectedNodes;
|
|
1826
1804
|
}
|
|
1827
1805
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
}
|
|
1835
|
-
return true;
|
|
1836
|
-
});
|
|
1837
|
-
return openNodes;
|
|
1838
|
-
};
|
|
1839
|
-
const getSelectedNodeIds = () => {
|
|
1840
|
-
const selectedNodeIds = [];
|
|
1841
|
-
this.getSelectedNodes().forEach(node => {
|
|
1842
|
-
if (node.id != null) {
|
|
1843
|
-
selectedNodeIds.push(node.id);
|
|
1844
|
-
}
|
|
1845
|
-
});
|
|
1846
|
-
return selectedNodeIds;
|
|
1847
|
-
};
|
|
1848
|
-
return {
|
|
1849
|
-
open_nodes: getOpenNodeIds(),
|
|
1850
|
-
selected_node: getSelectedNodeIds()
|
|
1851
|
-
};
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
/*
|
|
1855
|
-
Set initial state
|
|
1856
|
-
Don't handle nodes that are loaded on demand
|
|
1857
|
-
result: must load on demand
|
|
1858
|
-
*/
|
|
1859
|
-
setInitialState(state) {
|
|
1860
|
-
if (!state) {
|
|
1861
|
-
return false;
|
|
1862
|
-
} else {
|
|
1863
|
-
let mustLoadOnDemand = false;
|
|
1864
|
-
if (state.open_nodes) {
|
|
1865
|
-
mustLoadOnDemand = this.openInitialNodes(state.open_nodes);
|
|
1806
|
+
getSelectedNodesUnder(parent) {
|
|
1807
|
+
if (this.selectedSingleNode) {
|
|
1808
|
+
if (parent.isParentOf(this.selectedSingleNode)) {
|
|
1809
|
+
return [this.selectedSingleNode];
|
|
1810
|
+
} else {
|
|
1811
|
+
return [];
|
|
1866
1812
|
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1813
|
+
} else {
|
|
1814
|
+
const selectedNodes = [];
|
|
1815
|
+
for (const id in this.selectedNodes) {
|
|
1816
|
+
if (Object.prototype.hasOwnProperty.call(this.selectedNodes, id)) {
|
|
1817
|
+
const node = this.getNodeById(id);
|
|
1818
|
+
if (node && parent.isParentOf(node)) {
|
|
1819
|
+
selectedNodes.push(node);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1870
1822
|
}
|
|
1871
|
-
return
|
|
1823
|
+
return selectedNodes;
|
|
1872
1824
|
}
|
|
1873
1825
|
}
|
|
1874
|
-
|
|
1875
|
-
if (
|
|
1876
|
-
this.
|
|
1826
|
+
isNodeSelected(node) {
|
|
1827
|
+
if (node.id != null) {
|
|
1828
|
+
return this.selectedNodes.has(node.id);
|
|
1829
|
+
} else if (this.selectedSingleNode) {
|
|
1830
|
+
return this.selectedSingleNode.element === node.element;
|
|
1877
1831
|
} else {
|
|
1878
|
-
|
|
1832
|
+
return false;
|
|
1879
1833
|
}
|
|
1880
1834
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1835
|
+
clear() {
|
|
1836
|
+
this.selectedNodes.clear();
|
|
1837
|
+
this.selectedSingleNode = null;
|
|
1838
|
+
}
|
|
1839
|
+
removeFromSelection(node) {
|
|
1840
|
+
let includeChildren = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1841
|
+
if (node.id == null) {
|
|
1842
|
+
if (this.selectedSingleNode && node.element === this.selectedSingleNode.element) {
|
|
1843
|
+
this.selectedSingleNode = null;
|
|
1844
|
+
}
|
|
1885
1845
|
} else {
|
|
1886
|
-
|
|
1846
|
+
this.selectedNodes.delete(node.id);
|
|
1847
|
+
if (includeChildren) {
|
|
1848
|
+
node.iterate(() => {
|
|
1849
|
+
if (node.id != null) {
|
|
1850
|
+
this.selectedNodes.delete(node.id);
|
|
1851
|
+
}
|
|
1852
|
+
return true;
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1887
1855
|
}
|
|
1888
1856
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
// Convert to array
|
|
1895
|
-
state.selected_node = [state.selected_node];
|
|
1857
|
+
addToSelection(node) {
|
|
1858
|
+
if (node.id != null) {
|
|
1859
|
+
this.selectedNodes.add(node.id);
|
|
1860
|
+
} else {
|
|
1861
|
+
this.selectedSingleNode = node;
|
|
1896
1862
|
}
|
|
1897
|
-
return state;
|
|
1898
1863
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
const register = (widgetClass, widgetName) => {
|
|
1867
|
+
const getDataKey = () => `simple_widget_${widgetName}`;
|
|
1868
|
+
const getWidgetData = (el, dataKey) => {
|
|
1869
|
+
const widget = jQuery.data(el, dataKey);
|
|
1870
|
+
if (widget && widget instanceof SimpleWidget) {
|
|
1871
|
+
return widget;
|
|
1904
1872
|
} else {
|
|
1905
1873
|
return null;
|
|
1906
1874
|
}
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
for (const
|
|
1911
|
-
const
|
|
1912
|
-
if (
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1875
|
+
};
|
|
1876
|
+
const createWidget = ($el, options) => {
|
|
1877
|
+
const dataKey = getDataKey();
|
|
1878
|
+
for (const el of $el.get()) {
|
|
1879
|
+
const existingWidget = getWidgetData(el, dataKey);
|
|
1880
|
+
if (!existingWidget) {
|
|
1881
|
+
const simpleWidgetClass = widgetClass;
|
|
1882
|
+
const widget = new simpleWidgetClass(el, options);
|
|
1883
|
+
if (!jQuery.data(el, dataKey)) {
|
|
1884
|
+
jQuery.data(el, dataKey, widget);
|
|
1917
1885
|
}
|
|
1886
|
+
|
|
1887
|
+
// Call init after setting data, so we can call methods
|
|
1888
|
+
widget.init();
|
|
1918
1889
|
}
|
|
1919
1890
|
}
|
|
1920
|
-
return
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
for (const
|
|
1925
|
-
const
|
|
1926
|
-
if (
|
|
1927
|
-
|
|
1928
|
-
this.addToSelection(node);
|
|
1891
|
+
return $el;
|
|
1892
|
+
};
|
|
1893
|
+
const destroyWidget = $el => {
|
|
1894
|
+
const dataKey = getDataKey();
|
|
1895
|
+
for (const el of $el.get()) {
|
|
1896
|
+
const widget = getWidgetData(el, dataKey);
|
|
1897
|
+
if (widget) {
|
|
1898
|
+
widget.destroy();
|
|
1929
1899
|
}
|
|
1900
|
+
jQuery.removeData(el, dataKey);
|
|
1930
1901
|
}
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
const
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
let nodeIds = nodeIdsParam;
|
|
1942
|
-
const openNodes = () => {
|
|
1943
|
-
const newNodesIds = [];
|
|
1944
|
-
for (const nodeId of nodeIds) {
|
|
1945
|
-
const node = this.getNodeById(nodeId);
|
|
1946
|
-
if (!node) {
|
|
1947
|
-
newNodesIds.push(nodeId);
|
|
1948
|
-
} else {
|
|
1949
|
-
if (!node.is_loading) {
|
|
1950
|
-
if (node.load_on_demand) {
|
|
1951
|
-
loadAndOpenNode(node);
|
|
1952
|
-
} else {
|
|
1953
|
-
this.openNode(node, false);
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1902
|
+
};
|
|
1903
|
+
const callFunction = ($el, functionName, args) => {
|
|
1904
|
+
let result = null;
|
|
1905
|
+
for (const el of $el.get()) {
|
|
1906
|
+
const widget = jQuery.data(el, getDataKey());
|
|
1907
|
+
if (widget && widget instanceof SimpleWidget) {
|
|
1908
|
+
const simpleWidget = widget;
|
|
1909
|
+
const widgetFunction = simpleWidget[functionName];
|
|
1910
|
+
if (widgetFunction && typeof widgetFunction === "function") {
|
|
1911
|
+
result = widgetFunction.apply(widget, args);
|
|
1956
1912
|
}
|
|
1957
1913
|
}
|
|
1958
|
-
nodeIds = newNodesIds;
|
|
1959
|
-
if (this.selectInitialNodes(selectedNodes)) {
|
|
1960
|
-
this.refreshElements(null);
|
|
1961
|
-
}
|
|
1962
|
-
if (loadingCount === 0) {
|
|
1963
|
-
cbFinished();
|
|
1964
|
-
}
|
|
1965
|
-
};
|
|
1966
|
-
const loadAndOpenNode = node => {
|
|
1967
|
-
loadingCount += 1;
|
|
1968
|
-
this.openNode(node, false, () => {
|
|
1969
|
-
loadingCount -= 1;
|
|
1970
|
-
openNodes();
|
|
1971
|
-
});
|
|
1972
|
-
};
|
|
1973
|
-
openNodes();
|
|
1974
|
-
}
|
|
1975
|
-
getKeyName() {
|
|
1976
|
-
if (typeof this.saveStateOption === "string") {
|
|
1977
|
-
return this.saveStateOption;
|
|
1978
|
-
} else {
|
|
1979
|
-
return "tree";
|
|
1980
1914
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1915
|
+
return result;
|
|
1916
|
+
};
|
|
1917
|
+
|
|
1918
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1919
|
+
jQuery.fn[widgetName] = function (argument1) {
|
|
1920
|
+
if (!argument1) {
|
|
1921
|
+
return createWidget(this, null);
|
|
1922
|
+
} else if (typeof argument1 === "object") {
|
|
1923
|
+
const options = argument1;
|
|
1924
|
+
return createWidget(this, options);
|
|
1925
|
+
} else if (typeof argument1 === "string" && argument1[0] !== "_") {
|
|
1926
|
+
const functionName = argument1;
|
|
1927
|
+
if (functionName === "destroy") {
|
|
1928
|
+
return destroyWidget(this);
|
|
1929
|
+
} else if (functionName === "get_widget_class") {
|
|
1930
|
+
return widgetClass;
|
|
1987
1931
|
} else {
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
const key = "_storage_test";
|
|
1991
|
-
sessionStorage.setItem(key, "value");
|
|
1992
|
-
sessionStorage.removeItem(key);
|
|
1993
|
-
} catch (error) {
|
|
1994
|
-
return false;
|
|
1932
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
1933
|
+
args[_key - 1] = arguments[_key];
|
|
1995
1934
|
}
|
|
1996
|
-
return
|
|
1935
|
+
return callFunction(this, functionName, args);
|
|
1997
1936
|
}
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
this._supportsLocalStorage = testSupport();
|
|
1937
|
+
} else {
|
|
1938
|
+
return undefined;
|
|
2001
1939
|
}
|
|
2002
|
-
|
|
1940
|
+
};
|
|
1941
|
+
};
|
|
1942
|
+
class SimpleWidget {
|
|
1943
|
+
static register(widgetClass, widgetName) {
|
|
1944
|
+
register(widgetClass, widgetName);
|
|
1945
|
+
}
|
|
1946
|
+
static defaults = {};
|
|
1947
|
+
constructor(el, options) {
|
|
1948
|
+
this.$el = jQuery(el);
|
|
1949
|
+
|
|
1950
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1951
|
+
const defaults = this.constructor["defaults"];
|
|
1952
|
+
this.options = {
|
|
1953
|
+
...defaults,
|
|
1954
|
+
...options
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
destroy() {
|
|
1958
|
+
this.deinit();
|
|
1959
|
+
}
|
|
1960
|
+
init() {
|
|
1961
|
+
//
|
|
1962
|
+
}
|
|
1963
|
+
deinit() {
|
|
1964
|
+
//
|
|
2003
1965
|
}
|
|
2004
1966
|
}
|
|
2005
1967
|
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
this.
|
|
1968
|
+
const isNodeRecordWithChildren = data => typeof data === "object" && "children" in data && data["children"] instanceof Array;
|
|
1969
|
+
|
|
1970
|
+
class Node {
|
|
1971
|
+
constructor() {
|
|
1972
|
+
let nodeData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
1973
|
+
let isRoot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1974
|
+
let nodeClass = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Node;
|
|
1975
|
+
this.name = "";
|
|
1976
|
+
this.load_on_demand = false;
|
|
1977
|
+
this.isEmptyFolder = nodeData != null && isNodeRecordWithChildren(nodeData) && nodeData.children.length === 0;
|
|
1978
|
+
this.setData(nodeData);
|
|
1979
|
+
this.children = [];
|
|
1980
|
+
this.parent = null;
|
|
1981
|
+
if (isRoot) {
|
|
1982
|
+
this.idMapping = new Map();
|
|
1983
|
+
this.tree = this;
|
|
1984
|
+
this.nodeClass = nodeClass;
|
|
1985
|
+
}
|
|
2014
1986
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
1987
|
+
|
|
1988
|
+
/*
|
|
1989
|
+
Set the data of this node.
|
|
1990
|
+
setData(string): set the name of the node
|
|
1991
|
+
setData(object): set attributes of the node
|
|
1992
|
+
Examples:
|
|
1993
|
+
setData('node1')
|
|
1994
|
+
setData({ name: 'node1', id: 1});
|
|
1995
|
+
setData({ name: 'node2', id: 2, color: 'green'});
|
|
1996
|
+
* This is an internal function; it is not in the docs
|
|
1997
|
+
* Does not remove existing node values
|
|
1998
|
+
*/
|
|
1999
|
+
setData(o) {
|
|
2000
|
+
if (!o) {
|
|
2001
|
+
return;
|
|
2002
|
+
} else if (typeof o === "string") {
|
|
2003
|
+
this.name = o;
|
|
2004
|
+
} else if (typeof o === "object") {
|
|
2005
|
+
for (const key in o) {
|
|
2006
|
+
if (Object.prototype.hasOwnProperty.call(o, key)) {
|
|
2007
|
+
const value = o[key];
|
|
2008
|
+
if (key === "label" || key === "name") {
|
|
2009
|
+
// You can use the 'label' key instead of 'name'; this is a legacy feature
|
|
2010
|
+
if (typeof value === "string") {
|
|
2011
|
+
this.name = value;
|
|
2012
|
+
}
|
|
2013
|
+
} else if (key !== "children" && key !== "parent") {
|
|
2014
|
+
// You can't update the children or the parent using this function
|
|
2015
|
+
this[key] = value;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2024
2018
|
}
|
|
2025
2019
|
}
|
|
2026
2020
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2021
|
+
|
|
2022
|
+
/*
|
|
2023
|
+
Create tree from data.
|
|
2024
|
+
Structure of data is:
|
|
2025
|
+
[
|
|
2026
|
+
{
|
|
2027
|
+
name: 'node1',
|
|
2028
|
+
children: [
|
|
2029
|
+
{ name: 'child1' },
|
|
2030
|
+
{ name: 'child2' }
|
|
2031
|
+
]
|
|
2032
|
+
},
|
|
2033
|
+
{
|
|
2034
|
+
name: 'node2'
|
|
2034
2035
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2036
|
+
]
|
|
2037
|
+
*/
|
|
2038
|
+
loadFromData(data) {
|
|
2039
|
+
this.removeChildren();
|
|
2040
|
+
for (const childData of data) {
|
|
2041
|
+
const node = this.createNode(childData);
|
|
2042
|
+
this.addChild(node);
|
|
2043
|
+
if (isNodeRecordWithChildren(childData)) {
|
|
2044
|
+
node.loadFromData(childData.children);
|
|
2037
2045
|
}
|
|
2038
2046
|
}
|
|
2047
|
+
return this;
|
|
2039
2048
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2049
|
+
|
|
2050
|
+
/*
|
|
2051
|
+
Add child.
|
|
2052
|
+
tree.addChild(
|
|
2053
|
+
new Node('child1')
|
|
2054
|
+
);
|
|
2055
|
+
*/
|
|
2056
|
+
addChild(node) {
|
|
2057
|
+
this.children.push(node);
|
|
2058
|
+
node.setParent(this);
|
|
2042
2059
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2060
|
+
|
|
2061
|
+
/*
|
|
2062
|
+
Add child at position. Index starts at 0.
|
|
2063
|
+
tree.addChildAtPosition(
|
|
2064
|
+
new Node('abc'),
|
|
2065
|
+
1
|
|
2066
|
+
);
|
|
2067
|
+
*/
|
|
2068
|
+
addChildAtPosition(node, index) {
|
|
2069
|
+
this.children.splice(index, 0, node);
|
|
2070
|
+
node.setParent(this);
|
|
2046
2071
|
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2072
|
+
|
|
2073
|
+
/*
|
|
2074
|
+
Remove child. This also removes the children of the node.
|
|
2075
|
+
tree.removeChild(tree.children[0]);
|
|
2076
|
+
*/
|
|
2077
|
+
removeChild(node) {
|
|
2078
|
+
// remove children from the index
|
|
2079
|
+
node.removeChildren();
|
|
2080
|
+
this.doRemoveChild(node);
|
|
2052
2081
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
const leftEdge = scrollParentOffset.left;
|
|
2061
|
-
const isNearRightEdge = pageX > rightEdge - 20;
|
|
2062
|
-
const isNearLeftEdge = pageX < leftEdge + 20;
|
|
2063
|
-
if (isNearRightEdge) {
|
|
2064
|
-
return "right";
|
|
2065
|
-
} else if (isNearLeftEdge) {
|
|
2066
|
-
return "left";
|
|
2067
|
-
}
|
|
2068
|
-
return undefined;
|
|
2082
|
+
|
|
2083
|
+
/*
|
|
2084
|
+
Get child index.
|
|
2085
|
+
var index = getChildIndex(node);
|
|
2086
|
+
*/
|
|
2087
|
+
getChildIndex(node) {
|
|
2088
|
+
return this.children.indexOf(node);
|
|
2069
2089
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
return "bottom";
|
|
2076
|
-
}
|
|
2077
|
-
return undefined;
|
|
2090
|
+
|
|
2091
|
+
/*
|
|
2092
|
+
Does the tree have children?
|
|
2093
|
+
if (tree.hasChildren()) {
|
|
2094
|
+
//
|
|
2078
2095
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2096
|
+
*/
|
|
2097
|
+
hasChildren() {
|
|
2098
|
+
return this.children.length !== 0;
|
|
2099
|
+
}
|
|
2100
|
+
isFolder() {
|
|
2101
|
+
return this.hasChildren() || this.load_on_demand;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
/*
|
|
2105
|
+
Iterate over all the nodes in the tree.
|
|
2106
|
+
Calls callback with (node, level).
|
|
2107
|
+
The callback must return true to continue the iteration on current node.
|
|
2108
|
+
tree.iterate(
|
|
2109
|
+
function(node, level) {
|
|
2110
|
+
console.log(node.name);
|
|
2111
|
+
// stop iteration after level 2
|
|
2112
|
+
return (level <= 2);
|
|
2113
|
+
}
|
|
2114
|
+
);
|
|
2115
|
+
*/
|
|
2116
|
+
iterate(callback) {
|
|
2117
|
+
const _iterate = (node, level) => {
|
|
2118
|
+
if (node.children) {
|
|
2119
|
+
for (const child of node.children) {
|
|
2120
|
+
const result = callback(child, level);
|
|
2121
|
+
if (result && child.hasChildren()) {
|
|
2122
|
+
_iterate(child, level + 1);
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
_iterate(this, 0);
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
/*
|
|
2131
|
+
Move node relative to another node.
|
|
2132
|
+
Argument position: Position.BEFORE, Position.AFTER or Position.Inside
|
|
2133
|
+
// move node1 after node2
|
|
2134
|
+
tree.moveNode(node1, node2, Position.AFTER);
|
|
2135
|
+
*/
|
|
2136
|
+
moveNode(movedNode, targetNode, position) {
|
|
2137
|
+
if (!movedNode.parent || movedNode.isParentOf(targetNode)) {
|
|
2138
|
+
// - Node is parent of target node
|
|
2139
|
+
// - Or, parent is empty
|
|
2140
|
+
return false;
|
|
2141
|
+
} else {
|
|
2142
|
+
movedNode.parent.doRemoveChild(movedNode);
|
|
2143
|
+
switch (position) {
|
|
2144
|
+
case Position.After:
|
|
2145
|
+
{
|
|
2146
|
+
if (targetNode.parent) {
|
|
2147
|
+
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode) + 1);
|
|
2148
|
+
return true;
|
|
2149
|
+
}
|
|
2150
|
+
return false;
|
|
2151
|
+
}
|
|
2152
|
+
case Position.Before:
|
|
2153
|
+
{
|
|
2154
|
+
if (targetNode.parent) {
|
|
2155
|
+
targetNode.parent.addChildAtPosition(movedNode, targetNode.parent.getChildIndex(targetNode));
|
|
2156
|
+
return true;
|
|
2157
|
+
}
|
|
2158
|
+
return false;
|
|
2159
|
+
}
|
|
2160
|
+
case Position.Inside:
|
|
2161
|
+
{
|
|
2162
|
+
// move inside as first child
|
|
2163
|
+
targetNode.addChildAtPosition(movedNode, 0);
|
|
2164
|
+
return true;
|
|
2165
|
+
}
|
|
2166
|
+
default:
|
|
2167
|
+
return false;
|
|
2168
|
+
}
|
|
2082
2169
|
}
|
|
2083
|
-
const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
|
|
2084
|
-
const container = this.$container.get(0);
|
|
2085
|
-
container.scrollBy({
|
|
2086
|
-
left: distance,
|
|
2087
|
-
top: 0,
|
|
2088
|
-
behavior: "instant"
|
|
2089
|
-
});
|
|
2090
|
-
this.refreshHitAreas();
|
|
2091
|
-
setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
2092
2170
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2171
|
+
|
|
2172
|
+
/*
|
|
2173
|
+
Get the tree as data.
|
|
2174
|
+
*/
|
|
2175
|
+
getData() {
|
|
2176
|
+
let includeParent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
2177
|
+
const getDataFromNodes = nodes => {
|
|
2178
|
+
return nodes.map(node => {
|
|
2179
|
+
const tmpNode = {};
|
|
2180
|
+
for (const k in node) {
|
|
2181
|
+
if (["parent", "children", "element", "idMapping", "load_on_demand", "nodeClass", "tree", "isEmptyFolder"].indexOf(k) === -1 && Object.prototype.hasOwnProperty.call(node, k)) {
|
|
2182
|
+
const v = node[k];
|
|
2183
|
+
tmpNode[k] = v;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
if (node.hasChildren()) {
|
|
2187
|
+
tmpNode["children"] = getDataFromNodes(node.children);
|
|
2188
|
+
}
|
|
2189
|
+
return tmpNode;
|
|
2190
|
+
});
|
|
2191
|
+
};
|
|
2192
|
+
if (includeParent) {
|
|
2193
|
+
return getDataFromNodes([this]);
|
|
2194
|
+
} else {
|
|
2195
|
+
return getDataFromNodes(this.children);
|
|
2096
2196
|
}
|
|
2097
|
-
const distance = this.verticalScrollDirection === "top" ? -20 : 20;
|
|
2098
|
-
const container = this.$container.get(0);
|
|
2099
|
-
container.scrollBy({
|
|
2100
|
-
left: 0,
|
|
2101
|
-
top: distance,
|
|
2102
|
-
behavior: "instant"
|
|
2103
|
-
});
|
|
2104
|
-
this.refreshHitAreas();
|
|
2105
|
-
setTimeout(this.scrollVertically.bind(this), 40);
|
|
2106
2197
|
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2198
|
+
getNodeByName(name) {
|
|
2199
|
+
return this.getNodeByCallback(node => node.name === name);
|
|
2200
|
+
}
|
|
2201
|
+
getNodeByNameMustExist(name) {
|
|
2202
|
+
const node = this.getNodeByCallback(n => n.name === name);
|
|
2203
|
+
if (!node) {
|
|
2204
|
+
throw `Node with name ${name} not found`;
|
|
2110
2205
|
}
|
|
2111
|
-
return
|
|
2206
|
+
return node;
|
|
2207
|
+
}
|
|
2208
|
+
getNodeByCallback(callback) {
|
|
2209
|
+
let result = null;
|
|
2210
|
+
this.iterate(node => {
|
|
2211
|
+
if (result) {
|
|
2212
|
+
return false;
|
|
2213
|
+
} else if (callback(node)) {
|
|
2214
|
+
result = node;
|
|
2215
|
+
return false;
|
|
2216
|
+
} else {
|
|
2217
|
+
return true;
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2220
|
+
return result;
|
|
2112
2221
|
}
|
|
2113
|
-
|
|
2114
|
-
if (this.
|
|
2115
|
-
|
|
2222
|
+
addAfter(nodeInfo) {
|
|
2223
|
+
if (!this.parent) {
|
|
2224
|
+
return null;
|
|
2225
|
+
} else {
|
|
2226
|
+
const node = this.createNode(nodeInfo);
|
|
2227
|
+
const childIndex = this.parent.getChildIndex(this);
|
|
2228
|
+
this.parent.addChildAtPosition(node, childIndex + 1);
|
|
2229
|
+
node.loadChildrenFromData(nodeInfo);
|
|
2230
|
+
return node;
|
|
2116
2231
|
}
|
|
2117
|
-
return this.scrollParentBottom;
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
class DocumentScrollParent {
|
|
2122
|
-
constructor($element, refreshHitAreas) {
|
|
2123
|
-
this.$element = $element;
|
|
2124
|
-
this.refreshHitAreas = refreshHitAreas;
|
|
2125
2232
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
}
|
|
2233
|
+
addBefore(nodeInfo) {
|
|
2234
|
+
if (!this.parent) {
|
|
2235
|
+
return null;
|
|
2236
|
+
} else {
|
|
2237
|
+
const node = this.createNode(nodeInfo);
|
|
2238
|
+
const childIndex = this.parent.getChildIndex(this);
|
|
2239
|
+
this.parent.addChildAtPosition(node, childIndex);
|
|
2240
|
+
node.loadChildrenFromData(nodeInfo);
|
|
2241
|
+
return node;
|
|
2136
2242
|
}
|
|
2137
2243
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
this.
|
|
2244
|
+
addParent(nodeInfo) {
|
|
2245
|
+
if (!this.parent) {
|
|
2246
|
+
return null;
|
|
2247
|
+
} else {
|
|
2248
|
+
const newParent = this.createNode(nodeInfo);
|
|
2249
|
+
if (this.tree) {
|
|
2250
|
+
newParent.setParent(this.tree);
|
|
2145
2251
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2252
|
+
const originalParent = this.parent;
|
|
2253
|
+
for (const child of originalParent.children) {
|
|
2254
|
+
newParent.addChild(child);
|
|
2148
2255
|
}
|
|
2256
|
+
originalParent.children = [];
|
|
2257
|
+
originalParent.addChild(newParent);
|
|
2258
|
+
return newParent;
|
|
2149
2259
|
}
|
|
2150
2260
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
const offset = this.$element.offset();
|
|
2156
|
-
const treeTop = offset ? offset.top : 0;
|
|
2157
|
-
jQuery(document).scrollTop(top + treeTop);
|
|
2158
|
-
}
|
|
2159
|
-
stopScrolling() {
|
|
2160
|
-
this.horizontalScrollDirection = undefined;
|
|
2161
|
-
this.verticalScrollDirection = undefined;
|
|
2162
|
-
this.documentScrollHeight = undefined;
|
|
2163
|
-
this.documentScrollWidth = undefined;
|
|
2164
|
-
}
|
|
2165
|
-
getNewHorizontalScrollDirection(pageX) {
|
|
2166
|
-
const $document = jQuery(document);
|
|
2167
|
-
const scrollLeft = $document.scrollLeft() || 0;
|
|
2168
|
-
const windowWidth = jQuery(window).width() || 0;
|
|
2169
|
-
const isNearRightEdge = pageX > windowWidth - 20;
|
|
2170
|
-
const isNearLeftEdge = pageX - scrollLeft < 20;
|
|
2171
|
-
if (isNearRightEdge && this.canScrollRight()) {
|
|
2172
|
-
return "right";
|
|
2173
|
-
}
|
|
2174
|
-
if (isNearLeftEdge) {
|
|
2175
|
-
return "left";
|
|
2261
|
+
remove() {
|
|
2262
|
+
if (this.parent) {
|
|
2263
|
+
this.parent.removeChild(this);
|
|
2264
|
+
this.parent = null;
|
|
2176
2265
|
}
|
|
2177
|
-
return undefined;
|
|
2178
2266
|
}
|
|
2179
|
-
|
|
2180
|
-
const
|
|
2181
|
-
|
|
2267
|
+
append(nodeInfo) {
|
|
2268
|
+
const node = this.createNode(nodeInfo);
|
|
2269
|
+
this.addChild(node);
|
|
2270
|
+
node.loadChildrenFromData(nodeInfo);
|
|
2271
|
+
return node;
|
|
2182
2272
|
}
|
|
2183
|
-
|
|
2184
|
-
const
|
|
2185
|
-
|
|
2273
|
+
prepend(nodeInfo) {
|
|
2274
|
+
const node = this.createNode(nodeInfo);
|
|
2275
|
+
this.addChildAtPosition(node, 0);
|
|
2276
|
+
node.loadChildrenFromData(nodeInfo);
|
|
2277
|
+
return node;
|
|
2186
2278
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
this
|
|
2279
|
+
isParentOf(node) {
|
|
2280
|
+
let parent = node.parent;
|
|
2281
|
+
while (parent) {
|
|
2282
|
+
if (parent === this) {
|
|
2283
|
+
return true;
|
|
2284
|
+
}
|
|
2285
|
+
parent = parent.parent;
|
|
2191
2286
|
}
|
|
2192
|
-
return
|
|
2287
|
+
return false;
|
|
2193
2288
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2289
|
+
getLevel() {
|
|
2290
|
+
let level = 0;
|
|
2291
|
+
let node = this; // eslint-disable-line @typescript-eslint/no-this-alias
|
|
2292
|
+
|
|
2293
|
+
while (node.parent) {
|
|
2294
|
+
level += 1;
|
|
2295
|
+
node = node.parent;
|
|
2198
2296
|
}
|
|
2199
|
-
return
|
|
2297
|
+
return level;
|
|
2200
2298
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
const distanceTop = pageY - scrollTop;
|
|
2204
|
-
if (distanceTop < 20) {
|
|
2205
|
-
return "top";
|
|
2206
|
-
}
|
|
2207
|
-
const windowHeight = jQuery(window).height() || 0;
|
|
2208
|
-
if (windowHeight - (pageY - scrollTop) < 20 && this.canScrollDown()) {
|
|
2209
|
-
return "bottom";
|
|
2210
|
-
}
|
|
2211
|
-
return undefined;
|
|
2299
|
+
getNodeById(nodeId) {
|
|
2300
|
+
return this.idMapping.get(nodeId) || null;
|
|
2212
2301
|
}
|
|
2213
|
-
|
|
2214
|
-
if (
|
|
2215
|
-
|
|
2302
|
+
addNodeToIndex(node) {
|
|
2303
|
+
if (node.id != null) {
|
|
2304
|
+
this.idMapping.set(node.id, node);
|
|
2216
2305
|
}
|
|
2217
|
-
const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
|
|
2218
|
-
window.scrollBy({
|
|
2219
|
-
left: distance,
|
|
2220
|
-
top: 0,
|
|
2221
|
-
behavior: "instant"
|
|
2222
|
-
});
|
|
2223
|
-
this.refreshHitAreas();
|
|
2224
|
-
setTimeout(this.scrollHorizontally.bind(this), 40);
|
|
2225
2306
|
}
|
|
2226
|
-
|
|
2227
|
-
if (
|
|
2228
|
-
|
|
2307
|
+
removeNodeFromIndex(node) {
|
|
2308
|
+
if (node.id != null) {
|
|
2309
|
+
this.idMapping.delete(node.id);
|
|
2229
2310
|
}
|
|
2230
|
-
const distance = this.verticalScrollDirection === "top" ? -20 : 20;
|
|
2231
|
-
window.scrollBy({
|
|
2232
|
-
left: 0,
|
|
2233
|
-
top: distance,
|
|
2234
|
-
behavior: "instant"
|
|
2235
|
-
});
|
|
2236
|
-
this.refreshHitAreas();
|
|
2237
|
-
setTimeout(this.scrollVertically.bind(this), 40);
|
|
2238
2311
|
}
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
for (const attr of ["overflow", "overflow-y"]) {
|
|
2243
|
-
const overflowValue = $element.css(attr);
|
|
2244
|
-
if (overflowValue === "auto" || overflowValue === "scroll") {
|
|
2312
|
+
removeChildren() {
|
|
2313
|
+
this.iterate(child => {
|
|
2314
|
+
this.tree?.removeNodeFromIndex(child);
|
|
2245
2315
|
return true;
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
return false;
|
|
2249
|
-
};
|
|
2250
|
-
const getParentWithOverflow = $treeElement => {
|
|
2251
|
-
if (hasOverFlow($treeElement)) {
|
|
2252
|
-
return $treeElement;
|
|
2253
|
-
}
|
|
2254
|
-
for (const element of $treeElement.parents().get()) {
|
|
2255
|
-
const $element = jQuery(element);
|
|
2256
|
-
if (hasOverFlow($element)) {
|
|
2257
|
-
return $element;
|
|
2258
|
-
}
|
|
2259
|
-
}
|
|
2260
|
-
return null;
|
|
2261
|
-
};
|
|
2262
|
-
const createScrollParent = ($treeElement, refreshHitAreas) => {
|
|
2263
|
-
const $container = getParentWithOverflow($treeElement);
|
|
2264
|
-
if ($container?.length && $container[0]?.tagName !== "HTML") {
|
|
2265
|
-
return new ContainerScrollParent({
|
|
2266
|
-
$container,
|
|
2267
|
-
refreshHitAreas,
|
|
2268
|
-
$treeElement
|
|
2269
2316
|
});
|
|
2270
|
-
|
|
2271
|
-
return new DocumentScrollParent($treeElement, refreshHitAreas);
|
|
2272
|
-
}
|
|
2273
|
-
};
|
|
2274
|
-
|
|
2275
|
-
class ScrollHandler {
|
|
2276
|
-
constructor(_ref) {
|
|
2277
|
-
let {
|
|
2278
|
-
refreshHitAreas,
|
|
2279
|
-
$treeElement
|
|
2280
|
-
} = _ref;
|
|
2281
|
-
this.refreshHitAreas = refreshHitAreas;
|
|
2282
|
-
this.scrollParent = undefined;
|
|
2283
|
-
this.$treeElement = $treeElement;
|
|
2284
|
-
}
|
|
2285
|
-
checkScrolling(positionInfo) {
|
|
2286
|
-
this.checkVerticalScrolling(positionInfo);
|
|
2287
|
-
this.checkHorizontalScrolling(positionInfo);
|
|
2288
|
-
}
|
|
2289
|
-
stopScrolling() {
|
|
2290
|
-
this.getScrollParent().stopScrolling();
|
|
2291
|
-
}
|
|
2292
|
-
scrollToY(top) {
|
|
2293
|
-
this.getScrollParent().scrollToY(top);
|
|
2294
|
-
}
|
|
2295
|
-
getScrollLeft() {
|
|
2296
|
-
return this.getScrollParent().getScrollLeft();
|
|
2317
|
+
this.children = [];
|
|
2297
2318
|
}
|
|
2298
|
-
|
|
2299
|
-
if (
|
|
2300
|
-
return;
|
|
2319
|
+
getPreviousSibling() {
|
|
2320
|
+
if (!this.parent) {
|
|
2321
|
+
return null;
|
|
2322
|
+
} else {
|
|
2323
|
+
const previousIndex = this.parent.getChildIndex(this) - 1;
|
|
2324
|
+
if (previousIndex >= 0) {
|
|
2325
|
+
return this.parent.children[previousIndex] || null;
|
|
2326
|
+
} else {
|
|
2327
|
+
return null;
|
|
2328
|
+
}
|
|
2301
2329
|
}
|
|
2302
|
-
this.getScrollParent().checkVerticalScrolling(positionInfo.pageY);
|
|
2303
2330
|
}
|
|
2304
|
-
|
|
2305
|
-
if (
|
|
2306
|
-
return;
|
|
2331
|
+
getNextSibling() {
|
|
2332
|
+
if (!this.parent) {
|
|
2333
|
+
return null;
|
|
2334
|
+
} else {
|
|
2335
|
+
const nextIndex = this.parent.getChildIndex(this) + 1;
|
|
2336
|
+
if (nextIndex < this.parent.children.length) {
|
|
2337
|
+
return this.parent.children[nextIndex] || null;
|
|
2338
|
+
} else {
|
|
2339
|
+
return null;
|
|
2340
|
+
}
|
|
2307
2341
|
}
|
|
2308
|
-
this.getScrollParent().checkHorizontalScrolling(positionInfo.pageX);
|
|
2309
2342
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
this.scrollParent = createScrollParent(this.$treeElement, this.refreshHitAreas);
|
|
2313
|
-
}
|
|
2314
|
-
return this.scrollParent;
|
|
2343
|
+
getNodesByProperty(key, value) {
|
|
2344
|
+
return this.filter(node => node[key] === value);
|
|
2315
2345
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
this.clear();
|
|
2346
|
+
filter(f) {
|
|
2347
|
+
const result = [];
|
|
2348
|
+
this.iterate(node => {
|
|
2349
|
+
if (f(node)) {
|
|
2350
|
+
result.push(node);
|
|
2351
|
+
}
|
|
2352
|
+
return true;
|
|
2353
|
+
});
|
|
2354
|
+
return result;
|
|
2326
2355
|
}
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
if (
|
|
2330
|
-
return
|
|
2356
|
+
getNextNode() {
|
|
2357
|
+
let includeChildren = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
2358
|
+
if (includeChildren && this.hasChildren()) {
|
|
2359
|
+
return this.children[0] || null;
|
|
2360
|
+
} else if (!this.parent) {
|
|
2361
|
+
return null;
|
|
2331
2362
|
} else {
|
|
2332
|
-
|
|
2363
|
+
const nextSibling = this.getNextSibling();
|
|
2364
|
+
if (nextSibling) {
|
|
2365
|
+
return nextSibling;
|
|
2366
|
+
} else {
|
|
2367
|
+
return this.parent.getNextNode(false);
|
|
2368
|
+
}
|
|
2333
2369
|
}
|
|
2334
2370
|
}
|
|
2335
|
-
|
|
2336
|
-
if (this.
|
|
2337
|
-
|
|
2371
|
+
getNextVisibleNode() {
|
|
2372
|
+
if (this.hasChildren() && this.is_open) {
|
|
2373
|
+
// First child
|
|
2374
|
+
return this.children[0] || null;
|
|
2338
2375
|
} else {
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2376
|
+
if (!this.parent) {
|
|
2377
|
+
return null;
|
|
2378
|
+
} else {
|
|
2379
|
+
const nextSibling = this.getNextSibling();
|
|
2380
|
+
if (nextSibling) {
|
|
2381
|
+
// Next sibling
|
|
2382
|
+
return nextSibling;
|
|
2383
|
+
} else {
|
|
2384
|
+
// Next node of parent
|
|
2385
|
+
return this.parent.getNextNode(false);
|
|
2344
2386
|
}
|
|
2345
|
-
}
|
|
2346
|
-
return selectedNodes;
|
|
2387
|
+
}
|
|
2347
2388
|
}
|
|
2348
2389
|
}
|
|
2349
|
-
|
|
2350
|
-
if (this.
|
|
2351
|
-
|
|
2352
|
-
|
|
2390
|
+
getPreviousNode() {
|
|
2391
|
+
if (!this.parent) {
|
|
2392
|
+
return null;
|
|
2393
|
+
} else {
|
|
2394
|
+
const previousSibling = this.getPreviousSibling();
|
|
2395
|
+
if (!previousSibling) {
|
|
2396
|
+
return this.getParent();
|
|
2397
|
+
} else if (previousSibling.hasChildren()) {
|
|
2398
|
+
return previousSibling.getLastChild();
|
|
2353
2399
|
} else {
|
|
2354
|
-
return
|
|
2400
|
+
return previousSibling;
|
|
2355
2401
|
}
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
getPreviousVisibleNode() {
|
|
2405
|
+
if (!this.parent) {
|
|
2406
|
+
return null;
|
|
2356
2407
|
} else {
|
|
2357
|
-
const
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2408
|
+
const previousSibling = this.getPreviousSibling();
|
|
2409
|
+
if (!previousSibling) {
|
|
2410
|
+
return this.getParent();
|
|
2411
|
+
} else if (!previousSibling.hasChildren() || !previousSibling.is_open) {
|
|
2412
|
+
// Previous sibling
|
|
2413
|
+
return previousSibling;
|
|
2414
|
+
} else {
|
|
2415
|
+
// Last child of previous sibling
|
|
2416
|
+
return previousSibling.getLastChild();
|
|
2365
2417
|
}
|
|
2366
|
-
return selectedNodes;
|
|
2367
2418
|
}
|
|
2368
2419
|
}
|
|
2369
|
-
|
|
2370
|
-
if
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2420
|
+
getParent() {
|
|
2421
|
+
// Return parent except if it is the root node
|
|
2422
|
+
if (!this.parent) {
|
|
2423
|
+
return null;
|
|
2424
|
+
} else if (!this.parent.parent) {
|
|
2425
|
+
// Root node -> null
|
|
2426
|
+
return null;
|
|
2374
2427
|
} else {
|
|
2375
|
-
return
|
|
2428
|
+
return this.parent;
|
|
2376
2429
|
}
|
|
2377
2430
|
}
|
|
2378
|
-
|
|
2379
|
-
this.
|
|
2380
|
-
|
|
2381
|
-
}
|
|
2382
|
-
removeFromSelection(node) {
|
|
2383
|
-
let includeChildren = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2384
|
-
if (node.id == null) {
|
|
2385
|
-
if (this.selectedSingleNode && node.element === this.selectedSingleNode.element) {
|
|
2386
|
-
this.selectedSingleNode = null;
|
|
2387
|
-
}
|
|
2431
|
+
getLastChild() {
|
|
2432
|
+
if (!this.hasChildren()) {
|
|
2433
|
+
return null;
|
|
2388
2434
|
} else {
|
|
2389
|
-
this.
|
|
2390
|
-
if (
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2435
|
+
const lastChild = this.children[this.children.length - 1];
|
|
2436
|
+
if (!lastChild) {
|
|
2437
|
+
return null;
|
|
2438
|
+
}
|
|
2439
|
+
if (!(lastChild.hasChildren() && lastChild.is_open)) {
|
|
2440
|
+
return lastChild;
|
|
2441
|
+
} else {
|
|
2442
|
+
return lastChild?.getLastChild();
|
|
2397
2443
|
}
|
|
2398
2444
|
}
|
|
2399
2445
|
}
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
this.
|
|
2446
|
+
|
|
2447
|
+
// Init Node from data without making it the root of the tree
|
|
2448
|
+
initFromData(data) {
|
|
2449
|
+
const addNode = nodeData => {
|
|
2450
|
+
this.setData(nodeData);
|
|
2451
|
+
if (isNodeRecordWithChildren(nodeData) && nodeData.children.length) {
|
|
2452
|
+
addChildren(nodeData.children);
|
|
2453
|
+
}
|
|
2454
|
+
};
|
|
2455
|
+
const addChildren = childrenData => {
|
|
2456
|
+
for (const child of childrenData) {
|
|
2457
|
+
const node = this.createNode();
|
|
2458
|
+
node.initFromData(child);
|
|
2459
|
+
this.addChild(node);
|
|
2460
|
+
}
|
|
2461
|
+
};
|
|
2462
|
+
addNode(data);
|
|
2463
|
+
}
|
|
2464
|
+
setParent(parent) {
|
|
2465
|
+
this.parent = parent;
|
|
2466
|
+
this.tree = parent.tree;
|
|
2467
|
+
this.tree?.addNodeToIndex(this);
|
|
2468
|
+
}
|
|
2469
|
+
doRemoveChild(node) {
|
|
2470
|
+
this.children.splice(this.getChildIndex(node), 1);
|
|
2471
|
+
this.tree?.removeNodeFromIndex(node);
|
|
2472
|
+
}
|
|
2473
|
+
getNodeClass() {
|
|
2474
|
+
return this.nodeClass || this?.tree?.nodeClass || Node;
|
|
2475
|
+
}
|
|
2476
|
+
createNode(nodeData) {
|
|
2477
|
+
const nodeClass = this.getNodeClass();
|
|
2478
|
+
return new nodeClass(nodeData);
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
// Load children data from nodeInfo if it has children
|
|
2482
|
+
loadChildrenFromData(nodeInfo) {
|
|
2483
|
+
if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
|
|
2484
|
+
this.loadFromData(nodeInfo.children);
|
|
2405
2485
|
}
|
|
2406
2486
|
}
|
|
2407
2487
|
}
|
|
@@ -2634,7 +2714,7 @@ var jqtree = (function (exports) {
|
|
|
2634
2714
|
|
|
2635
2715
|
const NODE_PARAM_IS_EMPTY = "Node parameter is empty";
|
|
2636
2716
|
const PARAM_IS_EMPTY = "Parameter is empty: ";
|
|
2637
|
-
class JqTreeWidget extends
|
|
2717
|
+
class JqTreeWidget extends SimpleWidget {
|
|
2638
2718
|
static defaults = {
|
|
2639
2719
|
animationSpeed: "fast",
|
|
2640
2720
|
autoEscape: true,
|
|
@@ -2740,7 +2820,7 @@ var jqtree = (function (exports) {
|
|
|
2740
2820
|
return this.element;
|
|
2741
2821
|
}
|
|
2742
2822
|
refresh() {
|
|
2743
|
-
this.
|
|
2823
|
+
this.refreshElements(null);
|
|
2744
2824
|
return this.element;
|
|
2745
2825
|
}
|
|
2746
2826
|
getNodeById(nodeId) {
|
|
@@ -2785,7 +2865,7 @@ var jqtree = (function (exports) {
|
|
|
2785
2865
|
return [slide, onFinished];
|
|
2786
2866
|
};
|
|
2787
2867
|
const [slide, onFinished] = parseParams();
|
|
2788
|
-
this.
|
|
2868
|
+
this.openNodeInternal(node, slide, onFinished);
|
|
2789
2869
|
return this.element;
|
|
2790
2870
|
}
|
|
2791
2871
|
closeNode(node, slideParam) {
|
|
@@ -2809,7 +2889,7 @@ var jqtree = (function (exports) {
|
|
|
2809
2889
|
addNodeAfter(newNodeInfo, existingNode) {
|
|
2810
2890
|
const newNode = existingNode.addAfter(newNodeInfo);
|
|
2811
2891
|
if (newNode) {
|
|
2812
|
-
this.
|
|
2892
|
+
this.refreshElements(existingNode.parent);
|
|
2813
2893
|
}
|
|
2814
2894
|
return newNode;
|
|
2815
2895
|
}
|
|
@@ -2819,7 +2899,7 @@ var jqtree = (function (exports) {
|
|
|
2819
2899
|
}
|
|
2820
2900
|
const newNode = existingNode.addBefore(newNodeInfo);
|
|
2821
2901
|
if (newNode) {
|
|
2822
|
-
this.
|
|
2902
|
+
this.refreshElements(existingNode.parent);
|
|
2823
2903
|
}
|
|
2824
2904
|
return newNode;
|
|
2825
2905
|
}
|
|
@@ -2829,7 +2909,7 @@ var jqtree = (function (exports) {
|
|
|
2829
2909
|
}
|
|
2830
2910
|
const newNode = existingNode.addParent(newNodeInfo);
|
|
2831
2911
|
if (newNode) {
|
|
2832
|
-
this.
|
|
2912
|
+
this.refreshElements(newNode.parent);
|
|
2833
2913
|
}
|
|
2834
2914
|
return newNode;
|
|
2835
2915
|
}
|
|
@@ -2844,19 +2924,19 @@ var jqtree = (function (exports) {
|
|
|
2844
2924
|
|
|
2845
2925
|
const parent = node.parent;
|
|
2846
2926
|
node.remove();
|
|
2847
|
-
this.
|
|
2927
|
+
this.refreshElements(parent);
|
|
2848
2928
|
return this.element;
|
|
2849
2929
|
}
|
|
2850
2930
|
appendNode(newNodeInfo, parentNodeParam) {
|
|
2851
2931
|
const parentNode = parentNodeParam || this.tree;
|
|
2852
2932
|
const node = parentNode.append(newNodeInfo);
|
|
2853
|
-
this.
|
|
2933
|
+
this.refreshElements(parentNode);
|
|
2854
2934
|
return node;
|
|
2855
2935
|
}
|
|
2856
2936
|
prependNode(newNodeInfo, parentNodeParam) {
|
|
2857
2937
|
const parentNode = parentNodeParam ?? this.tree;
|
|
2858
2938
|
const node = parentNode.prepend(newNodeInfo);
|
|
2859
|
-
this.
|
|
2939
|
+
this.refreshElements(parentNode);
|
|
2860
2940
|
return node;
|
|
2861
2941
|
}
|
|
2862
2942
|
updateNode(node, data) {
|
|
@@ -2877,7 +2957,7 @@ var jqtree = (function (exports) {
|
|
|
2877
2957
|
node.loadFromData(data.children);
|
|
2878
2958
|
}
|
|
2879
2959
|
}
|
|
2880
|
-
this.
|
|
2960
|
+
this.refreshElements(node);
|
|
2881
2961
|
return this.element;
|
|
2882
2962
|
}
|
|
2883
2963
|
isSelectedNodeInSubtree(subtree) {
|
|
@@ -2898,7 +2978,7 @@ var jqtree = (function (exports) {
|
|
|
2898
2978
|
const positionIndex = getPosition(position);
|
|
2899
2979
|
if (positionIndex !== undefined) {
|
|
2900
2980
|
this.tree.moveNode(node, targetNode, positionIndex);
|
|
2901
|
-
this.
|
|
2981
|
+
this.refreshElements(null);
|
|
2902
2982
|
}
|
|
2903
2983
|
return this.element;
|
|
2904
2984
|
}
|
|
@@ -2911,7 +2991,7 @@ var jqtree = (function (exports) {
|
|
|
2911
2991
|
}
|
|
2912
2992
|
this.selectNodeHandler.addToSelection(node);
|
|
2913
2993
|
this.openParents(node);
|
|
2914
|
-
this.
|
|
2994
|
+
this.getNodeElementForNode(node).select(mustSetFocus === undefined ? true : mustSetFocus);
|
|
2915
2995
|
this.saveState();
|
|
2916
2996
|
return this.element;
|
|
2917
2997
|
}
|
|
@@ -2929,7 +3009,7 @@ var jqtree = (function (exports) {
|
|
|
2929
3009
|
throw Error(NODE_PARAM_IS_EMPTY);
|
|
2930
3010
|
}
|
|
2931
3011
|
this.selectNodeHandler.removeFromSelection(node);
|
|
2932
|
-
this.
|
|
3012
|
+
this.getNodeElementForNode(node).deselect();
|
|
2933
3013
|
this.saveState();
|
|
2934
3014
|
return this.element;
|
|
2935
3015
|
}
|
|
@@ -2937,9 +3017,7 @@ var jqtree = (function (exports) {
|
|
|
2937
3017
|
if (!node) {
|
|
2938
3018
|
throw Error(NODE_PARAM_IS_EMPTY);
|
|
2939
3019
|
}
|
|
2940
|
-
const
|
|
2941
|
-
const treeTop = this.$el.offset()?.top ?? 0;
|
|
2942
|
-
const top = nodeTop - treeTop;
|
|
3020
|
+
const top = getOffsetTop(node.element) - getOffsetTop(this.$el.get(0));
|
|
2943
3021
|
this.scrollHandler.scrollToY(top);
|
|
2944
3022
|
return this.element;
|
|
2945
3023
|
}
|
|
@@ -2948,7 +3026,7 @@ var jqtree = (function (exports) {
|
|
|
2948
3026
|
}
|
|
2949
3027
|
setState(state) {
|
|
2950
3028
|
this.saveStateHandler.setInitialState(state);
|
|
2951
|
-
this.
|
|
3029
|
+
this.refreshElements(null);
|
|
2952
3030
|
return this.element;
|
|
2953
3031
|
}
|
|
2954
3032
|
setOption(option, value) {
|
|
@@ -2972,12 +3050,7 @@ var jqtree = (function (exports) {
|
|
|
2972
3050
|
getVersion() {
|
|
2973
3051
|
return version;
|
|
2974
3052
|
}
|
|
2975
|
-
|
|
2976
|
-
const event = jQuery.Event(eventName, values);
|
|
2977
|
-
this.element.trigger(event);
|
|
2978
|
-
return event;
|
|
2979
|
-
}
|
|
2980
|
-
_openNode(node) {
|
|
3053
|
+
openNodeInternal(node) {
|
|
2981
3054
|
let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
2982
3055
|
let onFinished = arguments.length > 2 ? arguments[2] : undefined;
|
|
2983
3056
|
const doOpenNode = (_node, _slide, _onFinished) => {
|
|
@@ -3006,33 +3079,30 @@ var jqtree = (function (exports) {
|
|
|
3006
3079
|
Redraw the tree or part of the tree.
|
|
3007
3080
|
from_node: redraw this subtree
|
|
3008
3081
|
*/
|
|
3009
|
-
|
|
3082
|
+
refreshElements(fromNode) {
|
|
3010
3083
|
const mustSetFocus = this.isFocusOnTree();
|
|
3011
3084
|
const mustSelect = fromNode ? this.isSelectedNodeInSubtree(fromNode) : false;
|
|
3012
3085
|
this.renderer.render(fromNode);
|
|
3013
3086
|
if (mustSelect) {
|
|
3014
3087
|
this.selectCurrentNode(mustSetFocus);
|
|
3015
3088
|
}
|
|
3016
|
-
this.
|
|
3089
|
+
this.triggerEvent("tree.refresh");
|
|
3017
3090
|
}
|
|
3018
|
-
|
|
3091
|
+
getNodeElementForNode(node) {
|
|
3019
3092
|
if (node.isFolder()) {
|
|
3020
3093
|
return this.createFolderElement(node);
|
|
3021
3094
|
} else {
|
|
3022
3095
|
return this.createNodeElement(node);
|
|
3023
3096
|
}
|
|
3024
3097
|
}
|
|
3025
|
-
|
|
3098
|
+
getNodeElement(element) {
|
|
3026
3099
|
const node = this.getNode(element);
|
|
3027
3100
|
if (node) {
|
|
3028
|
-
return this.
|
|
3101
|
+
return this.getNodeElementForNode(node);
|
|
3029
3102
|
} else {
|
|
3030
3103
|
return null;
|
|
3031
3104
|
}
|
|
3032
3105
|
}
|
|
3033
|
-
_getScrollLeft() {
|
|
3034
|
-
return this.scrollHandler.getScrollLeft();
|
|
3035
|
-
}
|
|
3036
3106
|
init() {
|
|
3037
3107
|
super.init();
|
|
3038
3108
|
this.element = this.$el;
|
|
@@ -3043,19 +3113,20 @@ var jqtree = (function (exports) {
|
|
|
3043
3113
|
}
|
|
3044
3114
|
this.connectHandlers();
|
|
3045
3115
|
this.initData();
|
|
3046
|
-
this.element.on("click", this.handleClick);
|
|
3047
|
-
this.element.on("dblclick", this.handleDblclick);
|
|
3048
|
-
if (this.options.useContextMenu) {
|
|
3049
|
-
this.element.on("contextmenu", this.handleContextmenu);
|
|
3050
|
-
}
|
|
3051
3116
|
}
|
|
3052
3117
|
deinit() {
|
|
3053
3118
|
this.element.empty();
|
|
3054
3119
|
this.element.off();
|
|
3055
3120
|
this.keyHandler.deinit();
|
|
3121
|
+
this.mouseHandler.deinit();
|
|
3056
3122
|
this.tree = new Node({}, true);
|
|
3057
3123
|
super.deinit();
|
|
3058
3124
|
}
|
|
3125
|
+
triggerEvent(eventName, values) {
|
|
3126
|
+
const event = jQuery.Event(eventName, values);
|
|
3127
|
+
this.element.trigger(event);
|
|
3128
|
+
return event;
|
|
3129
|
+
}
|
|
3059
3130
|
mouseCapture(positionInfo) {
|
|
3060
3131
|
if (this.options.dragAndDrop) {
|
|
3061
3132
|
return this.dndHandler.mouseCapture(positionInfo);
|
|
@@ -3087,9 +3158,6 @@ var jqtree = (function (exports) {
|
|
|
3087
3158
|
return false;
|
|
3088
3159
|
}
|
|
3089
3160
|
}
|
|
3090
|
-
getMouseDelay() {
|
|
3091
|
-
return this.options.startDndDelay ?? 0;
|
|
3092
|
-
}
|
|
3093
3161
|
initData() {
|
|
3094
3162
|
if (this.options.data) {
|
|
3095
3163
|
this.doLoadData(this.options.data, null);
|
|
@@ -3151,7 +3219,7 @@ var jqtree = (function (exports) {
|
|
|
3151
3219
|
const doInit = () => {
|
|
3152
3220
|
if (!this.isInitialized) {
|
|
3153
3221
|
this.isInitialized = true;
|
|
3154
|
-
this.
|
|
3222
|
+
this.triggerEvent("tree.init");
|
|
3155
3223
|
}
|
|
3156
3224
|
};
|
|
3157
3225
|
if (!this.options.nodeClass) {
|
|
@@ -3161,7 +3229,7 @@ var jqtree = (function (exports) {
|
|
|
3161
3229
|
this.selectNodeHandler.clear();
|
|
3162
3230
|
this.tree.loadFromData(data);
|
|
3163
3231
|
const mustLoadOnDemand = this.setInitialState();
|
|
3164
|
-
this.
|
|
3232
|
+
this.refreshElements(null);
|
|
3165
3233
|
if (!mustLoadOnDemand) {
|
|
3166
3234
|
doInit();
|
|
3167
3235
|
} else {
|
|
@@ -3238,7 +3306,7 @@ var jqtree = (function (exports) {
|
|
|
3238
3306
|
let loadingCount = 0;
|
|
3239
3307
|
const loadAndOpenNode = node => {
|
|
3240
3308
|
loadingCount += 1;
|
|
3241
|
-
this.
|
|
3309
|
+
this.openNodeInternal(node, false, () => {
|
|
3242
3310
|
loadingCount -= 1;
|
|
3243
3311
|
openNodes();
|
|
3244
3312
|
});
|
|
@@ -3251,7 +3319,7 @@ var jqtree = (function (exports) {
|
|
|
3251
3319
|
}
|
|
3252
3320
|
return false;
|
|
3253
3321
|
} else {
|
|
3254
|
-
this.
|
|
3322
|
+
this.openNodeInternal(node, false);
|
|
3255
3323
|
return level !== maxLevel;
|
|
3256
3324
|
}
|
|
3257
3325
|
});
|
|
@@ -3276,58 +3344,6 @@ var jqtree = (function (exports) {
|
|
|
3276
3344
|
return 0;
|
|
3277
3345
|
}
|
|
3278
3346
|
}
|
|
3279
|
-
handleClick = e => {
|
|
3280
|
-
const clickTarget = this.getClickTarget(e.target);
|
|
3281
|
-
if (clickTarget) {
|
|
3282
|
-
if (clickTarget.type === "button") {
|
|
3283
|
-
this.toggle(clickTarget.node, this.options.slide);
|
|
3284
|
-
e.preventDefault();
|
|
3285
|
-
e.stopPropagation();
|
|
3286
|
-
} else if (clickTarget.type === "label") {
|
|
3287
|
-
const node = clickTarget.node;
|
|
3288
|
-
const event = this._triggerEvent("tree.click", {
|
|
3289
|
-
node,
|
|
3290
|
-
click_event: e
|
|
3291
|
-
});
|
|
3292
|
-
if (!event.isDefaultPrevented()) {
|
|
3293
|
-
this.doSelectNode(node);
|
|
3294
|
-
}
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
};
|
|
3298
|
-
handleDblclick = e => {
|
|
3299
|
-
const clickTarget = this.getClickTarget(e.target);
|
|
3300
|
-
if (clickTarget?.type === "label") {
|
|
3301
|
-
this._triggerEvent("tree.dblclick", {
|
|
3302
|
-
node: clickTarget.node,
|
|
3303
|
-
click_event: e
|
|
3304
|
-
});
|
|
3305
|
-
}
|
|
3306
|
-
};
|
|
3307
|
-
getClickTarget(element) {
|
|
3308
|
-
const button = element.closest(".jqtree-toggler");
|
|
3309
|
-
if (button) {
|
|
3310
|
-
const node = this.getNode(button);
|
|
3311
|
-
if (node) {
|
|
3312
|
-
return {
|
|
3313
|
-
type: "button",
|
|
3314
|
-
node
|
|
3315
|
-
};
|
|
3316
|
-
}
|
|
3317
|
-
} else {
|
|
3318
|
-
const jqTreeElement = element.closest(".jqtree-element");
|
|
3319
|
-
if (jqTreeElement) {
|
|
3320
|
-
const node = this.getNode(jqTreeElement);
|
|
3321
|
-
if (node) {
|
|
3322
|
-
return {
|
|
3323
|
-
type: "label",
|
|
3324
|
-
node
|
|
3325
|
-
};
|
|
3326
|
-
}
|
|
3327
|
-
}
|
|
3328
|
-
}
|
|
3329
|
-
return null;
|
|
3330
|
-
}
|
|
3331
3347
|
getNode(element) {
|
|
3332
3348
|
const liElement = element.closest("li.jqtree_common");
|
|
3333
3349
|
if (liElement) {
|
|
@@ -3336,22 +3352,6 @@ var jqtree = (function (exports) {
|
|
|
3336
3352
|
return null;
|
|
3337
3353
|
}
|
|
3338
3354
|
}
|
|
3339
|
-
handleContextmenu = e => {
|
|
3340
|
-
const div = e.target.closest("ul.jqtree-tree .jqtree-element");
|
|
3341
|
-
if (div) {
|
|
3342
|
-
const node = this.getNode(div);
|
|
3343
|
-
if (node) {
|
|
3344
|
-
e.preventDefault();
|
|
3345
|
-
e.stopPropagation();
|
|
3346
|
-
this._triggerEvent("tree.contextmenu", {
|
|
3347
|
-
node,
|
|
3348
|
-
click_event: e
|
|
3349
|
-
});
|
|
3350
|
-
return false;
|
|
3351
|
-
}
|
|
3352
|
-
}
|
|
3353
|
-
return null;
|
|
3354
|
-
};
|
|
3355
3355
|
saveState() {
|
|
3356
3356
|
if (this.options.saveState) {
|
|
3357
3357
|
this.saveStateHandler.saveState();
|
|
@@ -3360,7 +3360,7 @@ var jqtree = (function (exports) {
|
|
|
3360
3360
|
selectCurrentNode(mustSetFocus) {
|
|
3361
3361
|
const node = this.getSelectedNode();
|
|
3362
3362
|
if (node) {
|
|
3363
|
-
const nodeElement = this.
|
|
3363
|
+
const nodeElement = this.getNodeElementForNode(node);
|
|
3364
3364
|
if (nodeElement) {
|
|
3365
3365
|
nodeElement.select(mustSetFocus);
|
|
3366
3366
|
}
|
|
@@ -3426,7 +3426,7 @@ var jqtree = (function (exports) {
|
|
|
3426
3426
|
if (this.selectNodeHandler.isNodeSelected(node)) {
|
|
3427
3427
|
if (selectOptions.mustToggle) {
|
|
3428
3428
|
this.deselectCurrentNode();
|
|
3429
|
-
this.
|
|
3429
|
+
this.triggerEvent("tree.select", {
|
|
3430
3430
|
node: null,
|
|
3431
3431
|
previous_node: node
|
|
3432
3432
|
});
|
|
@@ -3435,7 +3435,7 @@ var jqtree = (function (exports) {
|
|
|
3435
3435
|
const deselectedNode = this.getSelectedNode() || null;
|
|
3436
3436
|
this.deselectCurrentNode();
|
|
3437
3437
|
this.addToSelection(node, selectOptions.mustSetFocus);
|
|
3438
|
-
this.
|
|
3438
|
+
this.triggerEvent("tree.select", {
|
|
3439
3439
|
node,
|
|
3440
3440
|
deselected_node: deselectedNode
|
|
3441
3441
|
});
|
|
@@ -3455,7 +3455,7 @@ var jqtree = (function (exports) {
|
|
|
3455
3455
|
this.dndHandler.refresh();
|
|
3456
3456
|
}
|
|
3457
3457
|
}
|
|
3458
|
-
this.
|
|
3458
|
+
this.triggerEvent("tree.load_data", {
|
|
3459
3459
|
tree_data: data,
|
|
3460
3460
|
parent_node: parentNode
|
|
3461
3461
|
});
|
|
@@ -3470,7 +3470,7 @@ var jqtree = (function (exports) {
|
|
|
3470
3470
|
parentNode.loadFromData(data);
|
|
3471
3471
|
parentNode.load_on_demand = false;
|
|
3472
3472
|
parentNode.is_loading = false;
|
|
3473
|
-
this.
|
|
3473
|
+
this.refreshElements(parentNode);
|
|
3474
3474
|
}
|
|
3475
3475
|
doLoadDataFromUrl(urlInfoParam, parentNode, onFinished) {
|
|
3476
3476
|
const urlInfo = urlInfoParam || this.getDataUrlInfo(parentNode);
|
|
@@ -3481,7 +3481,7 @@ var jqtree = (function (exports) {
|
|
|
3481
3481
|
let onFinished = arguments.length > 2 ? arguments[2] : undefined;
|
|
3482
3482
|
node.is_loading = true;
|
|
3483
3483
|
this.doLoadDataFromUrl(null, node, () => {
|
|
3484
|
-
this.
|
|
3484
|
+
this.openNodeInternal(node, slide, onFinished);
|
|
3485
3485
|
});
|
|
3486
3486
|
}
|
|
3487
3487
|
containsElement(element) {
|
|
@@ -3501,6 +3501,7 @@ var jqtree = (function (exports) {
|
|
|
3501
3501
|
dragAndDrop,
|
|
3502
3502
|
keyboardSupport,
|
|
3503
3503
|
onCanMove,
|
|
3504
|
+
onCanMoveTo,
|
|
3504
3505
|
onCreateLi,
|
|
3505
3506
|
onDragMove,
|
|
3506
3507
|
onDragStop,
|
|
@@ -3518,20 +3519,20 @@ var jqtree = (function (exports) {
|
|
|
3518
3519
|
tabIndex
|
|
3519
3520
|
} = this.options;
|
|
3520
3521
|
const closeNode = this.closeNode.bind(this);
|
|
3521
|
-
const getNodeElement = this.
|
|
3522
|
-
const getNodeElementForNode = this.
|
|
3522
|
+
const getNodeElement = this.getNodeElement.bind(this);
|
|
3523
|
+
const getNodeElementForNode = this.getNodeElementForNode.bind(this);
|
|
3523
3524
|
const getNodeById = this.getNodeById.bind(this);
|
|
3524
|
-
const getScrollLeft = this._getScrollLeft.bind(this);
|
|
3525
3525
|
const getSelectedNode = this.getSelectedNode.bind(this);
|
|
3526
3526
|
const getTree = this.getTree.bind(this);
|
|
3527
3527
|
const isFocusOnTree = this.isFocusOnTree.bind(this);
|
|
3528
3528
|
const loadData = this.loadData.bind(this);
|
|
3529
|
-
const openNode = this.
|
|
3530
|
-
const refreshElements = this.
|
|
3529
|
+
const openNode = this.openNodeInternal.bind(this);
|
|
3530
|
+
const refreshElements = this.refreshElements.bind(this);
|
|
3531
3531
|
const refreshHitAreas = this.refreshHitAreas.bind(this);
|
|
3532
3532
|
const selectNode = this.selectNode.bind(this);
|
|
3533
3533
|
const $treeElement = this.element;
|
|
3534
|
-
const
|
|
3534
|
+
const treeElement = this.element.get(0);
|
|
3535
|
+
const triggerEvent = this.triggerEvent.bind(this);
|
|
3535
3536
|
const selectNodeHandler = new SelectNodeHandler({
|
|
3536
3537
|
getNodeById
|
|
3537
3538
|
});
|
|
@@ -3539,12 +3540,13 @@ var jqtree = (function (exports) {
|
|
|
3539
3540
|
const getSelectedNodes = selectNodeHandler.getSelectedNodes.bind(selectNodeHandler);
|
|
3540
3541
|
const isNodeSelected = selectNodeHandler.isNodeSelected.bind(selectNodeHandler);
|
|
3541
3542
|
const removeFromSelection = selectNodeHandler.removeFromSelection.bind(selectNodeHandler);
|
|
3543
|
+
const getMouseDelay = () => this.options.startDndDelay ?? 0;
|
|
3542
3544
|
const dataLoader = new DataLoader({
|
|
3543
3545
|
dataFilter,
|
|
3544
3546
|
loadData,
|
|
3545
3547
|
onLoadFailed,
|
|
3546
3548
|
onLoading,
|
|
3547
|
-
|
|
3549
|
+
treeElement,
|
|
3548
3550
|
triggerEvent
|
|
3549
3551
|
});
|
|
3550
3552
|
const saveStateHandler = new SaveStateHandler({
|
|
@@ -3559,6 +3561,11 @@ var jqtree = (function (exports) {
|
|
|
3559
3561
|
removeFromSelection,
|
|
3560
3562
|
saveState
|
|
3561
3563
|
});
|
|
3564
|
+
const scrollHandler = new ScrollHandler({
|
|
3565
|
+
refreshHitAreas,
|
|
3566
|
+
treeElement
|
|
3567
|
+
});
|
|
3568
|
+
const getScrollLeft = scrollHandler.getScrollLeft.bind(scrollHandler);
|
|
3562
3569
|
const dndHandler = new DragAndDropHandler({
|
|
3563
3570
|
autoEscape,
|
|
3564
3571
|
getNodeElement,
|
|
@@ -3566,6 +3573,7 @@ var jqtree = (function (exports) {
|
|
|
3566
3573
|
getScrollLeft,
|
|
3567
3574
|
getTree,
|
|
3568
3575
|
onCanMove,
|
|
3576
|
+
onCanMoveTo,
|
|
3569
3577
|
onDragMove,
|
|
3570
3578
|
onDragStop,
|
|
3571
3579
|
onIsMoveHandle,
|
|
@@ -3573,13 +3581,9 @@ var jqtree = (function (exports) {
|
|
|
3573
3581
|
openNode,
|
|
3574
3582
|
refreshElements,
|
|
3575
3583
|
slide,
|
|
3576
|
-
|
|
3584
|
+
treeElement,
|
|
3577
3585
|
triggerEvent
|
|
3578
3586
|
});
|
|
3579
|
-
const scrollHandler = new ScrollHandler({
|
|
3580
|
-
refreshHitAreas,
|
|
3581
|
-
$treeElement
|
|
3582
|
-
});
|
|
3583
3587
|
const keyHandler = new KeyHandler({
|
|
3584
3588
|
closeNode,
|
|
3585
3589
|
getSelectedNode,
|
|
@@ -3602,9 +3606,28 @@ var jqtree = (function (exports) {
|
|
|
3602
3606
|
showEmptyFolder,
|
|
3603
3607
|
tabIndex
|
|
3604
3608
|
});
|
|
3609
|
+
const getNode = this.getNode.bind(this);
|
|
3610
|
+
const onMouseCapture = this.mouseCapture.bind(this);
|
|
3611
|
+
const onMouseDrag = this.mouseDrag.bind(this);
|
|
3612
|
+
const onMouseStart = this.mouseStart.bind(this);
|
|
3613
|
+
const onMouseStop = this.mouseStop.bind(this);
|
|
3614
|
+
const mouseHandler = new MouseHandler({
|
|
3615
|
+
element: treeElement,
|
|
3616
|
+
getMouseDelay,
|
|
3617
|
+
getNode,
|
|
3618
|
+
onClickButton: this.toggle.bind(this),
|
|
3619
|
+
onClickTitle: this.doSelectNode.bind(this),
|
|
3620
|
+
onMouseCapture,
|
|
3621
|
+
onMouseDrag,
|
|
3622
|
+
onMouseStart,
|
|
3623
|
+
onMouseStop,
|
|
3624
|
+
triggerEvent,
|
|
3625
|
+
useContextMenu: this.options.useContextMenu
|
|
3626
|
+
});
|
|
3605
3627
|
this.dataLoader = dataLoader;
|
|
3606
3628
|
this.dndHandler = dndHandler;
|
|
3607
3629
|
this.keyHandler = keyHandler;
|
|
3630
|
+
this.mouseHandler = mouseHandler;
|
|
3608
3631
|
this.renderer = renderer;
|
|
3609
3632
|
this.saveStateHandler = saveStateHandler;
|
|
3610
3633
|
this.scrollHandler = scrollHandler;
|
|
@@ -3612,11 +3635,11 @@ var jqtree = (function (exports) {
|
|
|
3612
3635
|
}
|
|
3613
3636
|
createFolderElement(node) {
|
|
3614
3637
|
const closedIconElement = this.renderer.closedIconElement;
|
|
3615
|
-
const getScrollLeft = this.
|
|
3638
|
+
const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
|
|
3616
3639
|
const openedIconElement = this.renderer.openedIconElement;
|
|
3617
3640
|
const tabIndex = this.options.tabIndex;
|
|
3618
3641
|
const $treeElement = this.element;
|
|
3619
|
-
const triggerEvent = this.
|
|
3642
|
+
const triggerEvent = this.triggerEvent.bind(this);
|
|
3620
3643
|
return new FolderElement({
|
|
3621
3644
|
closedIconElement,
|
|
3622
3645
|
getScrollLeft,
|
|
@@ -3628,7 +3651,7 @@ var jqtree = (function (exports) {
|
|
|
3628
3651
|
});
|
|
3629
3652
|
}
|
|
3630
3653
|
createNodeElement(node) {
|
|
3631
|
-
const getScrollLeft = this.
|
|
3654
|
+
const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
|
|
3632
3655
|
const tabIndex = this.options.tabIndex;
|
|
3633
3656
|
const $treeElement = this.element;
|
|
3634
3657
|
return new NodeElement({
|