jqtree 1.7.5 → 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.
Files changed (119) hide show
  1. package/.eslintrc +13 -3
  2. package/.github/workflows/ci.yml +6 -6
  3. package/.github/workflows/codeql-analysis.yml +4 -4
  4. package/.github/workflows/size.yml +3 -3
  5. package/.github/workflows/static.yml +1 -1
  6. package/bower.json +1 -1
  7. package/config/babel.config.json +1 -1
  8. package/config/jest.config.js +4 -0
  9. package/config/jest.polyfills.js +14 -0
  10. package/config/production +2 -0
  11. package/devserver/devserver_scroll.js +8 -0
  12. package/devserver/test_index.html +9 -0
  13. package/devserver/test_scroll.html +28 -0
  14. package/devserver/test_scroll_container.html +39 -0
  15. package/docs/.ruby-version +1 -1
  16. package/docs/_config.yml +1 -1
  17. package/docs/_entries/general/changelog.md +11 -0
  18. package/docs/_entries/multiple_selection/get-selected-nodes.md +1 -1
  19. package/docs/_entries/node/getnextnode.md +3 -6
  20. package/docs/_entries/node/getnextsibling.md +1 -1
  21. package/docs/_entries/node/getnextvisiblenode.md +8 -5
  22. package/docs/_entries/node/getpreviousnode.md +12 -0
  23. package/docs/_entries/node/getprevioussibling.md +1 -1
  24. package/docs/_entries/node/getpreviousvisiblenode.md +6 -5
  25. package/package.json +35 -29
  26. package/src/dataLoader.ts +57 -34
  27. package/src/dragAndDropHandler/dragElement.ts +54 -0
  28. package/src/dragAndDropHandler/generateHitAreas.ts +176 -0
  29. package/src/dragAndDropHandler/index.ts +454 -0
  30. package/src/dragAndDropHandler/iterateVisibleNodes.ts +91 -0
  31. package/src/dragAndDropHandler/types.ts +13 -0
  32. package/src/elementsRenderer.ts +75 -40
  33. package/src/jqtreeMethodTypes.ts +40 -0
  34. package/src/jqtreeOptions.ts +43 -25
  35. package/src/keyHandler.ts +59 -30
  36. package/src/mouseHandler.ts +385 -0
  37. package/src/mouseUtils.ts +23 -0
  38. package/src/node.ts +1 -29
  39. package/src/nodeElement/borderDropHint.ts +32 -0
  40. package/src/nodeElement/folderElement.ts +133 -0
  41. package/src/nodeElement/ghostDropHint.ts +69 -0
  42. package/src/nodeElement/index.ts +102 -0
  43. package/src/playwright/coverage.ts +4 -7
  44. package/src/playwright/playwright.test.ts +150 -53
  45. package/src/playwright/testUtils.ts +28 -5
  46. package/src/position.ts +28 -0
  47. package/src/saveStateHandler.ts +75 -26
  48. package/src/scrollHandler/containerScrollParent.ts +13 -23
  49. package/src/scrollHandler/createScrollParent.ts +22 -22
  50. package/src/scrollHandler/documentScrollParent.ts +16 -13
  51. package/src/scrollHandler.ts +13 -15
  52. package/src/selectNodeHandler.ts +10 -16
  53. package/src/test/jqTree/events.test.ts +97 -30
  54. package/src/test/jqTree/keyboard.test.ts +18 -23
  55. package/src/test/jqTree/loadOnDemand.test.ts +22 -15
  56. package/src/test/jqTree/methods.test.ts +40 -14
  57. package/src/test/jqTree/mouse.test.ts +82 -0
  58. package/src/test/jqTree/options.test.ts +24 -12
  59. package/src/test/node.test.ts +3 -2
  60. package/src/test/{nodeUtil.test.ts → position.test.ts} +1 -1
  61. package/src/tree.jquery.ts +314 -208
  62. package/src/util.ts +12 -0
  63. package/src/version.ts +1 -1
  64. package/tree.jquery.debug.js +2594 -3419
  65. package/tree.jquery.debug.js.map +1 -1
  66. package/tree.jquery.js +3 -3
  67. package/tree.jquery.js.map +1 -1
  68. package/tsconfig.json +5 -3
  69. package/docs/_entries/functions/get-selected-nodes.md +0 -10
  70. package/lib/dataLoader.js +0 -123
  71. package/lib/dragAndDropHandler.js +0 -588
  72. package/lib/elementsRenderer.js +0 -267
  73. package/lib/jqtreeOptions.js +0 -1
  74. package/lib/keyHandler.js +0 -111
  75. package/lib/mouse.widget.js +0 -255
  76. package/lib/node.js +0 -708
  77. package/lib/nodeElement.js +0 -274
  78. package/lib/nodeUtils.js +0 -10
  79. package/lib/playwright/coverage.js +0 -99
  80. package/lib/playwright/playwright.test.js +0 -606
  81. package/lib/playwright/testUtils.js +0 -210
  82. package/lib/saveStateHandler.js +0 -277
  83. package/lib/scrollHandler/containerScrollParent.js +0 -160
  84. package/lib/scrollHandler/createScrollParent.js +0 -57
  85. package/lib/scrollHandler/documentScrollParent.js +0 -169
  86. package/lib/scrollHandler/scrollParent.js +0 -58
  87. package/lib/scrollHandler/types.js +0 -1
  88. package/lib/scrollHandler.js +0 -71
  89. package/lib/selectNodeHandler.js +0 -128
  90. package/lib/simple.widget.js +0 -158
  91. package/lib/test/global.d.js +0 -3
  92. package/lib/test/jqTree/accessibility.test.js +0 -37
  93. package/lib/test/jqTree/create.test.js +0 -48
  94. package/lib/test/jqTree/events.test.js +0 -210
  95. package/lib/test/jqTree/keyboard.test.js +0 -225
  96. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  97. package/lib/test/jqTree/methods.test.js +0 -1348
  98. package/lib/test/jqTree/options.test.js +0 -548
  99. package/lib/test/jqTree/scrollHandler/containerScrollParent.test.js +0 -94
  100. package/lib/test/node.test.js +0 -1202
  101. package/lib/test/nodeUtil.test.js +0 -27
  102. package/lib/test/nodeUtils.test.js +0 -20
  103. package/lib/test/support/exampleData.js +0 -35
  104. package/lib/test/support/jqTreeMatchers.js +0 -70
  105. package/lib/test/support/matchers.d.js +0 -1
  106. package/lib/test/support/setupTests.js +0 -7
  107. package/lib/test/support/testUtil.js +0 -29
  108. package/lib/test/support/treeStructure.js +0 -38
  109. package/lib/test/util.test.js +0 -26
  110. package/lib/tree.jquery.d.js +0 -1
  111. package/lib/tree.jquery.js +0 -1105
  112. package/lib/types.js +0 -1
  113. package/lib/typings.d.js +0 -2
  114. package/lib/util.js +0 -15
  115. package/lib/version.js +0 -8
  116. package/src/dragAndDropHandler.ts +0 -713
  117. package/src/mouse.widget.ts +0 -266
  118. package/src/nodeElement.ts +0 -272
  119. package/src/types.ts +0 -19
@@ -1,713 +0,0 @@
1
- import { getPositionName, Node, Position } from "./node";
2
- import { DropHint, HitArea, PositionInfo } from "./types";
3
- import { NodeElement } from "./nodeElement";
4
- import { JqTreeWidget } from "./tree.jquery";
5
-
6
- interface Dimensions {
7
- left: number;
8
- top: number;
9
- right: number;
10
- bottom: number;
11
- }
12
-
13
- export class DragAndDropHandler {
14
- public hitAreas: HitArea[];
15
- public isDragging: boolean;
16
- public currentItem: NodeElement | null;
17
- public hoveredArea: HitArea | null;
18
-
19
- private treeWidget: JqTreeWidget;
20
- private dragElement: DragElement | null;
21
- private previousGhost: DropHint | null;
22
- private openFolderTimer: number | null;
23
-
24
- constructor(treeWidget: JqTreeWidget) {
25
- this.treeWidget = treeWidget;
26
-
27
- this.hoveredArea = null;
28
- this.hitAreas = [];
29
- this.isDragging = false;
30
- this.currentItem = null;
31
- }
32
-
33
- public mouseCapture(positionInfo: PositionInfo): boolean | null {
34
- const $element = jQuery(positionInfo.target);
35
-
36
- if (!this.mustCaptureElement($element)) {
37
- return null;
38
- }
39
-
40
- if (
41
- this.treeWidget.options.onIsMoveHandle &&
42
- !this.treeWidget.options.onIsMoveHandle($element)
43
- ) {
44
- return null;
45
- }
46
-
47
- let nodeElement = this.treeWidget._getNodeElement($element);
48
-
49
- if (nodeElement && this.treeWidget.options.onCanMove) {
50
- if (!this.treeWidget.options.onCanMove(nodeElement.node)) {
51
- nodeElement = null;
52
- }
53
- }
54
-
55
- this.currentItem = nodeElement;
56
- return this.currentItem != null;
57
- }
58
-
59
- public mouseStart(positionInfo: PositionInfo): boolean {
60
- if (
61
- !this.currentItem ||
62
- positionInfo.pageX === undefined ||
63
- positionInfo.pageY === undefined
64
- ) {
65
- return false;
66
- }
67
-
68
- this.refresh();
69
-
70
- const offset = jQuery(positionInfo.target).offset();
71
- const left = offset ? offset.left : 0;
72
- const top = offset ? offset.top : 0;
73
-
74
- const node = this.currentItem.node;
75
-
76
- this.dragElement = new DragElement(
77
- node.name,
78
- positionInfo.pageX - left,
79
- positionInfo.pageY - top,
80
- this.treeWidget.element,
81
- this.treeWidget.options.autoEscape ?? true,
82
- );
83
-
84
- this.isDragging = true;
85
- this.currentItem.$element.addClass("jqtree-moving");
86
-
87
- return true;
88
- }
89
-
90
- public mouseDrag(positionInfo: PositionInfo): boolean {
91
- if (
92
- !this.currentItem ||
93
- !this.dragElement ||
94
- positionInfo.pageX === undefined ||
95
- positionInfo.pageY === undefined
96
- ) {
97
- return false;
98
- }
99
-
100
- this.dragElement.move(positionInfo.pageX, positionInfo.pageY);
101
-
102
- const area = this.findHoveredArea(
103
- positionInfo.pageX,
104
- positionInfo.pageY,
105
- );
106
-
107
- if (area && this.canMoveToArea(area)) {
108
- if (!area.node.isFolder()) {
109
- this.stopOpenFolderTimer();
110
- }
111
-
112
- if (this.hoveredArea !== area) {
113
- this.hoveredArea = area;
114
-
115
- // If this is a closed folder, start timer to open it
116
- if (this.mustOpenFolderTimer(area)) {
117
- this.startOpenFolderTimer(area.node);
118
- } else {
119
- this.stopOpenFolderTimer();
120
- }
121
-
122
- this.updateDropHint();
123
- }
124
- } else {
125
- this.removeDropHint();
126
- this.stopOpenFolderTimer();
127
- this.hoveredArea = area;
128
- }
129
-
130
- if (!area) {
131
- if (this.treeWidget.options.onDragMove) {
132
- this.treeWidget.options.onDragMove(
133
- this.currentItem.node,
134
- positionInfo.originalEvent,
135
- );
136
- }
137
- }
138
-
139
- return true;
140
- }
141
-
142
- public mouseStop(positionInfo: PositionInfo): boolean {
143
- this.moveItem(positionInfo);
144
- this.clear();
145
- this.removeHover();
146
- this.removeDropHint();
147
- this.removeHitAreas();
148
-
149
- const currentItem = this.currentItem;
150
-
151
- if (this.currentItem) {
152
- this.currentItem.$element.removeClass("jqtree-moving");
153
- this.currentItem = null;
154
- }
155
-
156
- this.isDragging = false;
157
-
158
- if (!this.hoveredArea && currentItem) {
159
- if (this.treeWidget.options.onDragStop) {
160
- this.treeWidget.options.onDragStop(
161
- currentItem.node,
162
- positionInfo.originalEvent,
163
- );
164
- }
165
- }
166
-
167
- return false;
168
- }
169
-
170
- public refresh(): void {
171
- this.removeHitAreas();
172
-
173
- if (this.currentItem) {
174
- this.generateHitAreas();
175
-
176
- this.currentItem = this.treeWidget._getNodeElementForNode(
177
- this.currentItem.node,
178
- );
179
-
180
- if (this.isDragging) {
181
- this.currentItem.$element.addClass("jqtree-moving");
182
- }
183
- }
184
- }
185
-
186
- private generateHitAreas(): void {
187
- if (!this.currentItem) {
188
- this.hitAreas = [];
189
- } else {
190
- const hitAreasGenerator = new HitAreasGenerator(
191
- this.treeWidget.tree,
192
- this.currentItem.node,
193
- this.getTreeDimensions().bottom,
194
- );
195
- this.hitAreas = hitAreasGenerator.generate();
196
- }
197
- }
198
-
199
- private mustCaptureElement($element: JQuery<HTMLElement>): boolean {
200
- return !$element.is("input,select,textarea");
201
- }
202
-
203
- private canMoveToArea(area: HitArea): boolean {
204
- if (!this.treeWidget.options.onCanMoveTo) {
205
- return true;
206
- }
207
-
208
- if (!this.currentItem) {
209
- return false;
210
- }
211
-
212
- const positionName = getPositionName(area.position);
213
-
214
- return this.treeWidget.options.onCanMoveTo(
215
- this.currentItem.node,
216
- area.node,
217
- positionName,
218
- );
219
- }
220
-
221
- private removeHitAreas(): void {
222
- this.hitAreas = [];
223
- }
224
-
225
- private clear(): void {
226
- if (this.dragElement) {
227
- this.dragElement.remove();
228
- this.dragElement = null;
229
- }
230
- }
231
-
232
- private removeDropHint(): void {
233
- if (this.previousGhost) {
234
- this.previousGhost.remove();
235
- }
236
- }
237
-
238
- private removeHover(): void {
239
- this.hoveredArea = null;
240
- }
241
-
242
- private findHoveredArea(x: number, y: number): HitArea | null {
243
- const dimensions = this.getTreeDimensions();
244
-
245
- if (
246
- x < dimensions.left ||
247
- y < dimensions.top ||
248
- x > dimensions.right ||
249
- y > dimensions.bottom
250
- ) {
251
- return null;
252
- }
253
-
254
- let low = 0;
255
- let high = this.hitAreas.length;
256
- while (low < high) {
257
- const mid = (low + high) >> 1;
258
- const area = this.hitAreas[mid];
259
-
260
- if (!area) {
261
- return null;
262
- }
263
-
264
- if (y < area.top) {
265
- high = mid;
266
- } else if (y > area.bottom) {
267
- low = mid + 1;
268
- } else {
269
- return area;
270
- }
271
- }
272
-
273
- return null;
274
- }
275
-
276
- private mustOpenFolderTimer(area: HitArea): boolean {
277
- const node = area.node;
278
-
279
- return (
280
- node.isFolder() &&
281
- !node.is_open &&
282
- area.position === Position.Inside
283
- );
284
- }
285
-
286
- private updateDropHint(): void {
287
- if (!this.hoveredArea) {
288
- return;
289
- }
290
-
291
- // remove previous drop hint
292
- this.removeDropHint();
293
-
294
- // add new drop hint
295
- const nodeElement = this.treeWidget._getNodeElementForNode(
296
- this.hoveredArea.node,
297
- );
298
- this.previousGhost = nodeElement.addDropHint(this.hoveredArea.position);
299
- }
300
-
301
- private startOpenFolderTimer(folder: Node): void {
302
- const openFolder = (): void => {
303
- this.treeWidget._openNode(
304
- folder,
305
- this.treeWidget.options.slide,
306
- () => {
307
- this.refresh();
308
- this.updateDropHint();
309
- },
310
- );
311
- };
312
-
313
- this.stopOpenFolderTimer();
314
-
315
- const openFolderDelay = this.treeWidget.options.openFolderDelay;
316
-
317
- if (openFolderDelay !== false) {
318
- this.openFolderTimer = window.setTimeout(
319
- openFolder,
320
- openFolderDelay,
321
- );
322
- }
323
- }
324
-
325
- private stopOpenFolderTimer(): void {
326
- if (this.openFolderTimer) {
327
- clearTimeout(this.openFolderTimer);
328
- this.openFolderTimer = null;
329
- }
330
- }
331
-
332
- private moveItem(positionInfo: PositionInfo): void {
333
- if (
334
- this.currentItem &&
335
- this.hoveredArea &&
336
- this.hoveredArea.position !== Position.None &&
337
- this.canMoveToArea(this.hoveredArea)
338
- ) {
339
- const movedNode = this.currentItem.node;
340
- const targetNode = this.hoveredArea.node;
341
- const position = this.hoveredArea.position;
342
- const previousParent = movedNode.parent;
343
-
344
- if (position === Position.Inside) {
345
- this.hoveredArea.node.is_open = true;
346
- }
347
-
348
- const doMove = (): void => {
349
- this.treeWidget.tree.moveNode(movedNode, targetNode, position);
350
- this.treeWidget.element.empty();
351
- this.treeWidget._refreshElements(null);
352
- };
353
-
354
- const event = this.treeWidget._triggerEvent("tree.move", {
355
- move_info: {
356
- moved_node: movedNode,
357
- target_node: targetNode,
358
- position: getPositionName(position),
359
- previous_parent: previousParent,
360
- do_move: doMove,
361
- original_event: positionInfo.originalEvent,
362
- },
363
- });
364
-
365
- if (!event.isDefaultPrevented()) {
366
- doMove();
367
- }
368
- }
369
- }
370
-
371
- private getTreeDimensions(): Dimensions {
372
- // Return the dimensions of the tree. Add a margin to the bottom to allow
373
- // to drag-and-drop after the last element.
374
- const offset = this.treeWidget.element.offset();
375
-
376
- if (!offset) {
377
- return { left: 0, top: 0, right: 0, bottom: 0 };
378
- } else {
379
- const el = this.treeWidget.element;
380
- const width = el.width() || 0;
381
- const height = el.height() || 0;
382
- const left = offset.left + this.treeWidget._getScrollLeft();
383
-
384
- return {
385
- left,
386
- top: offset.top,
387
- right: left + width,
388
- bottom: offset.top + height + 16,
389
- };
390
- }
391
- }
392
- }
393
-
394
- abstract class VisibleNodeIterator {
395
- private tree: Node;
396
-
397
- constructor(tree: Node) {
398
- this.tree = tree;
399
- }
400
-
401
- protected iterate(): void {
402
- let isFirstNode = true;
403
-
404
- const _iterateNode = (node: Node, nextNode: Node | null): void => {
405
- let mustIterateInside =
406
- (node.is_open || !node.element) && node.hasChildren();
407
-
408
- let $element: JQuery<HTMLElement> | null = null;
409
-
410
- if (node.element) {
411
- $element = jQuery(node.element);
412
-
413
- if (!$element.is(":visible")) {
414
- return;
415
- }
416
-
417
- if (isFirstNode) {
418
- this.handleFirstNode(node);
419
- isFirstNode = false;
420
- }
421
-
422
- if (!node.hasChildren()) {
423
- this.handleNode(node, nextNode, $element);
424
- } else if (node.is_open) {
425
- if (!this.handleOpenFolder(node, $element)) {
426
- mustIterateInside = false;
427
- }
428
- } else {
429
- this.handleClosedFolder(node, nextNode, $element);
430
- }
431
- }
432
-
433
- if (mustIterateInside) {
434
- const childrenLength = node.children.length;
435
- node.children.forEach((_, i) => {
436
- const child = node.children[i];
437
-
438
- if (child) {
439
- if (i === childrenLength - 1) {
440
- _iterateNode(child, null);
441
- } else {
442
- const nextChild = node.children[i + 1];
443
-
444
- if (nextChild) {
445
- _iterateNode(child, nextChild);
446
- }
447
- }
448
- }
449
- });
450
-
451
- if (node.is_open && $element) {
452
- this.handleAfterOpenFolder(node, nextNode);
453
- }
454
- }
455
- };
456
-
457
- _iterateNode(this.tree, null);
458
- }
459
-
460
- protected abstract handleNode(
461
- node: Node,
462
- nextNode: Node | null,
463
- $element: JQuery,
464
- ): void;
465
-
466
- /*
467
- override
468
- return
469
- - true: continue iterating
470
- - false: stop iterating
471
- */
472
- protected abstract handleOpenFolder(node: Node, $element: JQuery): boolean;
473
-
474
- protected abstract handleClosedFolder(
475
- node: Node,
476
- nextNode: Node | null,
477
- $element: JQuery,
478
- ): void;
479
-
480
- protected abstract handleAfterOpenFolder(
481
- node: Node,
482
- nextNode: Node | null,
483
- ): void;
484
-
485
- protected abstract handleFirstNode(node: Node): void;
486
- }
487
-
488
- export class HitAreasGenerator extends VisibleNodeIterator {
489
- private currentNode: Node;
490
- private treeBottom: number;
491
- private positions: HitArea[];
492
- private lastTop: number;
493
-
494
- constructor(tree: Node, currentNode: Node, treeBottom: number) {
495
- super(tree);
496
-
497
- this.currentNode = currentNode;
498
- this.treeBottom = treeBottom;
499
- }
500
-
501
- public generate(): HitArea[] {
502
- this.positions = [];
503
- this.lastTop = 0;
504
-
505
- this.iterate();
506
-
507
- return this.generateHitAreas(this.positions);
508
- }
509
-
510
- protected generateHitAreas(positions: HitArea[]): HitArea[] {
511
- let previousTop = positions[0]?.top ?? 0;
512
- let group = [];
513
- const hitAreas: HitArea[] = [];
514
-
515
- for (const position of positions) {
516
- if (position.top !== previousTop && group.length) {
517
- this.generateHitAreasForGroup(
518
- hitAreas,
519
- group,
520
- previousTop,
521
- position.top,
522
- );
523
-
524
- previousTop = position.top;
525
- group = [];
526
- }
527
-
528
- group.push(position);
529
- }
530
-
531
- this.generateHitAreasForGroup(
532
- hitAreas,
533
- group,
534
- previousTop,
535
- this.treeBottom,
536
- );
537
-
538
- return hitAreas;
539
- }
540
-
541
- protected handleOpenFolder(node: Node, $element: JQuery): boolean {
542
- if (node === this.currentNode) {
543
- // Cannot move inside current item
544
-
545
- // Dnd over the current element is not possible: add a position with type None for the top and the bottom.
546
- const top = this.getTop($element);
547
- const height = $element.height() || 0;
548
- this.addPosition(node, Position.None, top);
549
-
550
- if (height > 5) {
551
- // Subtract 5 pixels to allow more space for the next element.
552
- this.addPosition(node, Position.None, top + height - 5);
553
- }
554
-
555
- // Stop iterating
556
- return false;
557
- }
558
-
559
- // Cannot move before current item
560
- if (node.children[0] !== this.currentNode) {
561
- this.addPosition(node, Position.Inside, this.getTop($element));
562
- }
563
-
564
- // Continue iterating
565
- return true;
566
- }
567
-
568
- protected handleClosedFolder(
569
- node: Node,
570
- nextNode: Node,
571
- $element: JQuery,
572
- ): void {
573
- const top = this.getTop($element);
574
-
575
- if (node === this.currentNode) {
576
- // Cannot move after current item
577
- this.addPosition(node, Position.None, top);
578
- } else {
579
- this.addPosition(node, Position.Inside, top);
580
-
581
- // Cannot move before current item
582
- if (nextNode !== this.currentNode) {
583
- this.addPosition(node, Position.After, top);
584
- }
585
- }
586
- }
587
-
588
- protected handleFirstNode(node: Node): void {
589
- if (node !== this.currentNode) {
590
- this.addPosition(
591
- node,
592
- Position.Before,
593
- this.getTop(jQuery(node.element)),
594
- );
595
- }
596
- }
597
-
598
- protected handleAfterOpenFolder(node: Node, nextNode: Node): void {
599
- if (node === this.currentNode || nextNode === this.currentNode) {
600
- // Cannot move before or after current item
601
- this.addPosition(node, Position.None, this.lastTop);
602
- } else {
603
- this.addPosition(node, Position.After, this.lastTop);
604
- }
605
- }
606
-
607
- protected handleNode(node: Node, nextNode: Node, $element: JQuery): void {
608
- const top = this.getTop($element);
609
-
610
- if (node === this.currentNode) {
611
- // Cannot move inside current item
612
- this.addPosition(node, Position.None, top);
613
- } else {
614
- this.addPosition(node, Position.Inside, top);
615
- }
616
-
617
- if (nextNode === this.currentNode || node === this.currentNode) {
618
- // Cannot move before or after current item
619
- this.addPosition(node, Position.None, top);
620
- } else {
621
- this.addPosition(node, Position.After, top);
622
- }
623
- }
624
-
625
- private getTop($element: JQuery<HTMLElement>): number {
626
- const offset = $element.offset();
627
-
628
- return offset ? offset.top : 0;
629
- }
630
-
631
- private addPosition(node: Node, position: number, top: number): void {
632
- const area = {
633
- top,
634
- bottom: 0,
635
- node,
636
- position,
637
- };
638
-
639
- this.positions.push(area);
640
- this.lastTop = top;
641
- }
642
-
643
- private generateHitAreasForGroup(
644
- hitAreas: HitArea[],
645
- positionsInGroup: HitArea[],
646
- top: number,
647
- bottom: number,
648
- ): void {
649
- // limit positions in group
650
- const positionCount = Math.min(positionsInGroup.length, 4);
651
-
652
- const areaHeight = Math.round((bottom - top) / positionCount);
653
- let areaTop = top;
654
-
655
- let i = 0;
656
- while (i < positionCount) {
657
- const position = positionsInGroup[i];
658
-
659
- if (position && position.position !== Position.None) {
660
- hitAreas.push({
661
- top: areaTop,
662
- bottom: areaTop + areaHeight,
663
- node: position.node,
664
- position: position.position,
665
- });
666
- }
667
-
668
- areaTop += areaHeight;
669
- i += 1;
670
- }
671
- }
672
- }
673
-
674
- class DragElement {
675
- private offsetX: number;
676
- private offsetY: number;
677
- private $element: JQuery;
678
-
679
- constructor(
680
- nodeName: string,
681
- offsetX: number,
682
- offsetY: number,
683
- $tree: JQuery,
684
- autoEscape: boolean,
685
- ) {
686
- this.offsetX = offsetX;
687
- this.offsetY = offsetY;
688
-
689
- this.$element = jQuery("<span>").addClass(
690
- "jqtree-title jqtree-dragging",
691
- );
692
-
693
- if (autoEscape) {
694
- this.$element.text(nodeName);
695
- } else {
696
- this.$element.html(nodeName);
697
- }
698
-
699
- this.$element.css("position", "absolute");
700
- $tree.append(this.$element);
701
- }
702
-
703
- public move(pageX: number, pageY: number): void {
704
- this.$element.offset({
705
- left: pageX - this.offsetX,
706
- top: pageY - this.offsetY,
707
- });
708
- }
709
-
710
- public remove(): void {
711
- this.$element.remove();
712
- }
713
- }