jqtree 1.8.7 → 1.8.9

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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- JqTree 1.8.7
2
+ JqTree 1.8.8
3
3
 
4
4
  Copyright 2024 Marco Braak
5
5
 
@@ -37,6 +37,32 @@ var jqtree = (function (exports) {
37
37
  this.treeElement = treeElement;
38
38
  this.triggerEvent = triggerEvent;
39
39
  }
40
+ loadFromUrl(urlInfo, parentNode, onFinished) {
41
+ if (!urlInfo) {
42
+ return;
43
+ }
44
+ const element = this.getDomElement(parentNode);
45
+ this.addLoadingClass(element);
46
+ this.notifyLoading(true, parentNode, element);
47
+ const stopLoading = () => {
48
+ this.removeLoadingClass(element);
49
+ this.notifyLoading(false, parentNode, element);
50
+ };
51
+ const handleSuccess = data => {
52
+ stopLoading();
53
+ this.loadData(this.parseData(data), parentNode);
54
+ if (onFinished && typeof onFinished === "function") {
55
+ onFinished();
56
+ }
57
+ };
58
+ const handleError = jqXHR => {
59
+ stopLoading();
60
+ if (this.onLoadFailed) {
61
+ this.onLoadFailed(jqXHR);
62
+ }
63
+ };
64
+ this.submitRequest(urlInfo, handleSuccess, handleError);
65
+ }
40
66
  addLoadingClass(element) {
41
67
  element.classList.add("jqtree-loading");
42
68
  }
@@ -91,32 +117,6 @@ var jqtree = (function (exports) {
91
117
  ajaxSettings.method = ajaxSettings.method?.toUpperCase() ?? "GET";
92
118
  void jQuery.ajax(ajaxSettings);
93
119
  }
94
- loadFromUrl(urlInfo, parentNode, onFinished) {
95
- if (!urlInfo) {
96
- return;
97
- }
98
- const element = this.getDomElement(parentNode);
99
- this.addLoadingClass(element);
100
- this.notifyLoading(true, parentNode, element);
101
- const stopLoading = () => {
102
- this.removeLoadingClass(element);
103
- this.notifyLoading(false, parentNode, element);
104
- };
105
- const handleSuccess = data => {
106
- stopLoading();
107
- this.loadData(this.parseData(data), parentNode);
108
- if (onFinished && typeof onFinished === "function") {
109
- onFinished();
110
- }
111
- };
112
- const handleError = jqXHR => {
113
- stopLoading();
114
- if (this.onLoadFailed) {
115
- this.onLoadFailed(jqXHR);
116
- }
117
- };
118
- this.submitRequest(urlInfo, handleSuccess, handleError);
119
- }
120
120
  }
121
121
 
122
122
  let Position = /*#__PURE__*/function (Position) {
@@ -156,6 +156,27 @@ var jqtree = (function (exports) {
156
156
  };
157
157
  };
158
158
 
159
+ function binarySearch(items, compareFn) {
160
+ let low = 0;
161
+ let high = items.length;
162
+ while (low < high) {
163
+ const mid = low + high >> 1;
164
+ const item = items[mid];
165
+ if (item === undefined) {
166
+ return null;
167
+ }
168
+ const compareResult = compareFn(item);
169
+ if (compareResult > 0) {
170
+ high = mid;
171
+ } else if (compareResult < 0) {
172
+ low = mid + 1;
173
+ } else {
174
+ return item;
175
+ }
176
+ }
177
+ return null;
178
+ }
179
+
159
180
  class DragElement {
160
181
  constructor(_ref) {
161
182
  let {
@@ -170,6 +191,13 @@ var jqtree = (function (exports) {
170
191
  this.element = this.createElement(nodeName, autoEscape);
171
192
  treeElement.appendChild(this.element);
172
193
  }
194
+ move(pageX, pageY) {
195
+ this.element.style.left = `${pageX - this.offsetX}px`;
196
+ this.element.style.top = `${pageY - this.offsetY}px`;
197
+ }
198
+ remove() {
199
+ this.element.remove();
200
+ }
173
201
  createElement(nodeName, autoEscape) {
174
202
  const element = document.createElement("span");
175
203
  element.classList.add("jqtree-title", "jqtree-dragging");
@@ -181,13 +209,6 @@ var jqtree = (function (exports) {
181
209
  element.style.position = "absolute";
182
210
  return element;
183
211
  }
184
- move(pageX, pageY) {
185
- this.element.style.left = `${pageX - this.offsetX}px`;
186
- this.element.style.top = `${pageY - this.offsetY}px`;
187
- }
188
- remove() {
189
- this.element.remove();
190
- }
191
212
  }
192
213
 
193
214
  const iterateVisibleNodes = (tree, _ref) => {
@@ -407,15 +428,113 @@ var jqtree = (function (exports) {
407
428
  this.isDragging = false;
408
429
  this.currentItem = null;
409
430
  }
410
- canMoveToArea(area) {
411
- if (!this.onCanMoveTo) {
412
- return true;
431
+ mouseCapture(positionInfo) {
432
+ const element = positionInfo.target;
433
+ if (!this.mustCaptureElement(element)) {
434
+ return null;
435
+ }
436
+ if (this.onIsMoveHandle && !this.onIsMoveHandle(jQuery(element))) {
437
+ return null;
438
+ }
439
+ let nodeElement = this.getNodeElement(element);
440
+ if (nodeElement && this.onCanMove) {
441
+ if (!this.onCanMove(nodeElement.node)) {
442
+ nodeElement = null;
443
+ }
444
+ }
445
+ this.currentItem = nodeElement;
446
+ return this.currentItem != null;
447
+ }
448
+ mouseDrag(positionInfo) {
449
+ if (!this.currentItem || !this.dragElement) {
450
+ return false;
413
451
  }
452
+ this.dragElement.move(positionInfo.pageX, positionInfo.pageY);
453
+ const area = this.findHoveredArea(positionInfo.pageX, positionInfo.pageY);
454
+ if (area && this.canMoveToArea(area, this.currentItem)) {
455
+ if (!area.node.isFolder()) {
456
+ this.stopOpenFolderTimer();
457
+ }
458
+ if (this.hoveredArea !== area) {
459
+ this.hoveredArea = area;
460
+
461
+ // If this is a closed folder, start timer to open it
462
+ if (this.mustOpenFolderTimer(area)) {
463
+ this.startOpenFolderTimer(area.node);
464
+ } else {
465
+ this.stopOpenFolderTimer();
466
+ }
467
+ this.updateDropHint();
468
+ }
469
+ } else {
470
+ this.removeDropHint();
471
+ this.stopOpenFolderTimer();
472
+ this.hoveredArea = area;
473
+ }
474
+ if (!area) {
475
+ if (this.onDragMove) {
476
+ this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
477
+ }
478
+ }
479
+ return true;
480
+ }
481
+ mouseStart(positionInfo) {
414
482
  if (!this.currentItem) {
415
483
  return false;
416
484
  }
485
+ this.refresh();
486
+ const {
487
+ left,
488
+ top
489
+ } = getElementPosition(positionInfo.target);
490
+ const node = this.currentItem.node;
491
+ this.dragElement = new DragElement({
492
+ autoEscape: this.autoEscape ?? true,
493
+ nodeName: node.name,
494
+ offsetX: positionInfo.pageX - left,
495
+ offsetY: positionInfo.pageY - top,
496
+ treeElement: this.treeElement
497
+ });
498
+ this.isDragging = true;
499
+ this.currentItem.element.classList.add("jqtree-moving");
500
+ return true;
501
+ }
502
+ mouseStop(positionInfo) {
503
+ this.moveItem(positionInfo);
504
+ this.clear();
505
+ this.removeHover();
506
+ this.removeDropHint();
507
+ this.removeHitAreas();
508
+ const currentItem = this.currentItem;
509
+ if (this.currentItem) {
510
+ this.currentItem.element.classList.remove("jqtree-moving");
511
+ this.currentItem = null;
512
+ }
513
+ this.isDragging = false;
514
+ if (!this.hoveredArea && currentItem) {
515
+ if (this.onDragStop) {
516
+ this.onDragStop(currentItem.node, positionInfo.originalEvent);
517
+ }
518
+ }
519
+ return false;
520
+ }
521
+ refresh() {
522
+ this.removeHitAreas();
523
+ if (this.currentItem) {
524
+ const currentNode = this.currentItem.node;
525
+ this.generateHitAreas(currentNode);
526
+ this.currentItem = this.getNodeElementForNode(currentNode);
527
+ if (this.isDragging) {
528
+ this.currentItem.element.classList.add("jqtree-moving");
529
+ }
530
+ }
531
+ }
532
+ canMoveToArea(area, currentItem) {
533
+ if (!this.onCanMoveTo) {
534
+ return true;
535
+ }
417
536
  const positionName = getPositionName(area.position);
418
- return this.onCanMoveTo(this.currentItem.node, area.node, positionName);
537
+ return this.onCanMoveTo(currentItem.node, area.node, positionName);
419
538
  }
420
539
  clear() {
421
540
  if (this.dragElement) {
@@ -428,30 +547,22 @@ var jqtree = (function (exports) {
428
547
  if (x < dimensions.left || y < dimensions.top || x > dimensions.right || y > dimensions.bottom) {
429
548
  return null;
430
549
  }
431
- let low = 0;
432
- let high = this.hitAreas.length;
433
- while (low < high) {
434
- const mid = low + high >> 1;
435
- const area = this.hitAreas[mid];
436
- if (!area) {
437
- return null;
438
- }
550
+ return binarySearch(this.hitAreas, area => {
439
551
  if (y < area.top) {
440
- high = mid;
552
+ return 1;
441
553
  } else if (y > area.bottom) {
442
- low = mid + 1;
554
+ return -1;
443
555
  } else {
444
- return area;
556
+ return 0;
445
557
  }
446
- }
447
- return null;
558
+ });
448
559
  }
449
- generateHitAreas() {
560
+ generateHitAreas(currentNode) {
450
561
  const tree = this.getTree();
451
- if (!this.currentItem || !tree) {
562
+ if (!tree) {
452
563
  this.hitAreas = [];
453
564
  } else {
454
- this.hitAreas = generateHitAreas(tree, this.currentItem.node, this.getTreeDimensions().bottom);
565
+ this.hitAreas = generateHitAreas(tree, currentNode, this.getTreeDimensions().bottom);
455
566
  }
456
567
  }
457
568
  getTreeDimensions() {
@@ -467,8 +578,10 @@ var jqtree = (function (exports) {
467
578
  top
468
579
  };
469
580
  }
581
+
582
+ /* Move the dragged node to the selected position in the tree. */
470
583
  moveItem(positionInfo) {
471
- if (this.currentItem && this.hoveredArea && this.hoveredArea.position !== Position.None && this.canMoveToArea(this.hoveredArea)) {
584
+ if (this.currentItem && this.hoveredArea && this.hoveredArea.position !== Position.None && this.canMoveToArea(this.hoveredArea, this.currentItem)) {
472
585
  const movedNode = this.currentItem.node;
473
586
  const targetNode = this.hoveredArea.node;
474
587
  const position = this.hoveredArea.position;
@@ -549,137 +662,71 @@ var jqtree = (function (exports) {
549
662
  const nodeElement = this.getNodeElementForNode(this.hoveredArea.node);
550
663
  this.previousGhost = nodeElement.addDropHint(this.hoveredArea.position);
551
664
  }
552
- mouseCapture(positionInfo) {
553
- const element = positionInfo.target;
554
- if (!this.mustCaptureElement(element)) {
555
- return null;
556
- }
557
- if (this.onIsMoveHandle && !this.onIsMoveHandle(jQuery(element))) {
558
- return null;
559
- }
560
- let nodeElement = this.getNodeElement(element);
561
- if (nodeElement && this.onCanMove) {
562
- if (!this.onCanMove(nodeElement.node)) {
563
- nodeElement = null;
564
- }
665
+ }
666
+
667
+ class ElementsRenderer {
668
+ constructor(_ref) {
669
+ let {
670
+ $element,
671
+ autoEscape,
672
+ buttonLeft,
673
+ closedIcon,
674
+ dragAndDrop,
675
+ getTree,
676
+ isNodeSelected,
677
+ onCreateLi,
678
+ openedIcon,
679
+ rtl,
680
+ showEmptyFolder,
681
+ tabIndex
682
+ } = _ref;
683
+ this.autoEscape = autoEscape;
684
+ this.buttonLeft = buttonLeft;
685
+ this.dragAndDrop = dragAndDrop;
686
+ this.$element = $element;
687
+ this.getTree = getTree;
688
+ this.isNodeSelected = isNodeSelected;
689
+ this.onCreateLi = onCreateLi;
690
+ this.rtl = rtl;
691
+ this.showEmptyFolder = showEmptyFolder;
692
+ this.tabIndex = tabIndex;
693
+ this.openedIconElement = this.createButtonElement(openedIcon ?? "+");
694
+ this.closedIconElement = this.createButtonElement(closedIcon ?? "-");
695
+ }
696
+ render(fromNode) {
697
+ if (fromNode?.parent) {
698
+ this.renderFromNode(fromNode);
699
+ } else {
700
+ this.renderFromRoot();
565
701
  }
566
- this.currentItem = nodeElement;
567
- return this.currentItem != null;
568
702
  }
569
- mouseDrag(positionInfo) {
570
- if (!this.currentItem || !this.dragElement) {
571
- return false;
703
+ renderFromNode(node) {
704
+ if (!node.element) {
705
+ return;
572
706
  }
573
- this.dragElement.move(positionInfo.pageX, positionInfo.pageY);
574
- const area = this.findHoveredArea(positionInfo.pageX, positionInfo.pageY);
575
- if (area && this.canMoveToArea(area)) {
576
- if (!area.node.isFolder()) {
577
- this.stopOpenFolderTimer();
578
- }
579
- if (this.hoveredArea !== area) {
580
- this.hoveredArea = area;
581
707
 
582
- // If this is a closed folder, start timer to open it
583
- if (this.mustOpenFolderTimer(area)) {
584
- this.startOpenFolderTimer(area.node);
585
- } else {
586
- this.stopOpenFolderTimer();
587
- }
588
- this.updateDropHint();
589
- }
590
- } else {
591
- this.removeDropHint();
592
- this.stopOpenFolderTimer();
593
- this.hoveredArea = area;
594
- }
595
- if (!area) {
596
- if (this.onDragMove) {
597
- this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
598
- }
599
- }
600
- return true;
601
- }
602
- mouseStart(positionInfo) {
603
- if (!this.currentItem) {
604
- return false;
605
- }
606
- this.refresh();
607
- const {
608
- left,
609
- top
610
- } = getElementPosition(positionInfo.target);
611
- const node = this.currentItem.node;
612
- this.dragElement = new DragElement({
613
- autoEscape: this.autoEscape ?? true,
614
- nodeName: node.name,
615
- offsetX: positionInfo.pageX - left,
616
- offsetY: positionInfo.pageY - top,
617
- treeElement: this.treeElement
618
- });
619
- this.isDragging = true;
620
- this.currentItem.element.classList.add("jqtree-moving");
621
- return true;
622
- }
623
- mouseStop(positionInfo) {
624
- this.moveItem(positionInfo);
625
- this.clear();
626
- this.removeHover();
627
- this.removeDropHint();
628
- this.removeHitAreas();
629
- const currentItem = this.currentItem;
630
- if (this.currentItem) {
631
- this.currentItem.element.classList.remove("jqtree-moving");
632
- this.currentItem = null;
633
- }
634
- this.isDragging = false;
635
- if (!this.hoveredArea && currentItem) {
636
- if (this.onDragStop) {
637
- this.onDragStop(currentItem.node, positionInfo.originalEvent);
638
- }
639
- }
640
- return false;
708
+ // remember current li
709
+ const $previousLi = jQuery(node.element);
710
+
711
+ // create element
712
+ const li = this.createLi(node, node.getLevel());
713
+
714
+ // add element to dom
715
+ $previousLi.after(li);
716
+
717
+ // remove previous li
718
+ $previousLi.remove();
719
+
720
+ // create children
721
+ this.createDomElements(li, node.children, false, node.getLevel() + 1);
641
722
  }
642
- refresh() {
643
- this.removeHitAreas();
644
- if (this.currentItem) {
645
- this.generateHitAreas();
646
- this.currentItem = this.getNodeElementForNode(this.currentItem.node);
647
- if (this.isDragging) {
648
- this.currentItem.element.classList.add("jqtree-moving");
649
- }
723
+ renderFromRoot() {
724
+ this.$element.empty();
725
+ const tree = this.getTree();
726
+ if (this.$element[0] && tree) {
727
+ this.createDomElements(this.$element[0], tree.children, true, 1);
650
728
  }
651
729
  }
652
- }
653
-
654
- class ElementsRenderer {
655
- constructor(_ref) {
656
- let {
657
- $element,
658
- autoEscape,
659
- buttonLeft,
660
- closedIcon,
661
- dragAndDrop,
662
- getTree,
663
- isNodeSelected,
664
- onCreateLi,
665
- openedIcon,
666
- rtl,
667
- showEmptyFolder,
668
- tabIndex
669
- } = _ref;
670
- this.autoEscape = autoEscape;
671
- this.buttonLeft = buttonLeft;
672
- this.dragAndDrop = dragAndDrop;
673
- this.$element = $element;
674
- this.getTree = getTree;
675
- this.isNodeSelected = isNodeSelected;
676
- this.onCreateLi = onCreateLi;
677
- this.rtl = rtl;
678
- this.showEmptyFolder = showEmptyFolder;
679
- this.tabIndex = tabIndex;
680
- this.openedIconElement = this.createButtonElement(openedIcon ?? "+");
681
- this.closedIconElement = this.createButtonElement(closedIcon ?? "-");
682
- }
683
730
  attachNodeData(node, li) {
684
731
  node.element = li;
685
732
  jQuery(li).data("node", node);
@@ -854,43 +901,42 @@ var jqtree = (function (exports) {
854
901
  element.setAttribute("aria-selected", getBoolString(isSelected));
855
902
  element.setAttribute("role", "treeitem");
856
903
  }
857
- render(fromNode) {
858
- if (fromNode?.parent) {
859
- this.renderFromNode(fromNode);
860
- } else {
861
- this.renderFromRoot();
904
+ }
905
+
906
+ class KeyHandler {
907
+ constructor(_ref) {
908
+ let {
909
+ closeNode,
910
+ getSelectedNode,
911
+ isFocusOnTree,
912
+ keyboardSupport,
913
+ openNode,
914
+ selectNode
915
+ } = _ref;
916
+ this.closeNode = closeNode;
917
+ this.getSelectedNode = getSelectedNode;
918
+ this.isFocusOnTree = isFocusOnTree;
919
+ this.keyboardSupport = keyboardSupport;
920
+ this.openNode = openNode;
921
+ this.originalSelectNode = selectNode;
922
+ if (keyboardSupport) {
923
+ document.addEventListener("keydown", this.handleKeyDown);
862
924
  }
863
925
  }
864
- renderFromNode(node) {
865
- if (!node.element) {
866
- return;
926
+ deinit() {
927
+ if (this.keyboardSupport) {
928
+ document.removeEventListener("keydown", this.handleKeyDown);
867
929
  }
868
-
869
- // remember current li
870
- const $previousLi = jQuery(node.element);
871
-
872
- // create element
873
- const li = this.createLi(node, node.getLevel());
874
-
875
- // add element to dom
876
- $previousLi.after(li);
877
-
878
- // remove previous li
879
- $previousLi.remove();
880
-
881
- // create children
882
- this.createDomElements(li, node.children, false, node.getLevel() + 1);
883
930
  }
884
- renderFromRoot() {
885
- this.$element.empty();
886
- const tree = this.getTree();
887
- if (this.$element[0] && tree) {
888
- this.createDomElements(this.$element[0], tree.children, true, 1);
889
- }
931
+ moveDown(selectedNode) {
932
+ return this.selectNode(selectedNode.getNextVisibleNode());
933
+ }
934
+ moveUp(selectedNode) {
935
+ return this.selectNode(selectedNode.getPreviousVisibleNode());
936
+ }
937
+ canHandleKeyboard() {
938
+ return this.keyboardSupport && this.isFocusOnTree();
890
939
  }
891
- }
892
-
893
- class KeyHandler {
894
940
  handleKeyDown = e => {
895
941
  if (!this.canHandleKeyboard()) {
896
942
  return;
@@ -902,14 +948,14 @@ var jqtree = (function (exports) {
902
948
  case "ArrowDown":
903
949
  isKeyHandled = this.moveDown(selectedNode);
904
950
  break;
905
- case "ArrowUp":
906
- isKeyHandled = this.moveUp(selectedNode);
951
+ case "ArrowLeft":
952
+ isKeyHandled = this.moveLeft(selectedNode);
907
953
  break;
908
954
  case "ArrowRight":
909
955
  isKeyHandled = this.moveRight(selectedNode);
910
956
  break;
911
- case "ArrowLeft":
912
- isKeyHandled = this.moveLeft(selectedNode);
957
+ case "ArrowUp":
958
+ isKeyHandled = this.moveUp(selectedNode);
913
959
  break;
914
960
  }
915
961
  }
@@ -917,28 +963,6 @@ var jqtree = (function (exports) {
917
963
  e.preventDefault();
918
964
  }
919
965
  };
920
- constructor(_ref) {
921
- let {
922
- closeNode,
923
- getSelectedNode,
924
- isFocusOnTree,
925
- keyboardSupport,
926
- openNode,
927
- selectNode
928
- } = _ref;
929
- this.closeNode = closeNode;
930
- this.getSelectedNode = getSelectedNode;
931
- this.isFocusOnTree = isFocusOnTree;
932
- this.keyboardSupport = keyboardSupport;
933
- this.openNode = openNode;
934
- this.originalSelectNode = selectNode;
935
- if (keyboardSupport) {
936
- document.addEventListener("keydown", this.handleKeyDown);
937
- }
938
- }
939
- canHandleKeyboard() {
940
- return this.keyboardSupport && this.isFocusOnTree();
941
- }
942
966
  moveLeft(selectedNode) {
943
967
  if (selectedNode.isFolder() && selectedNode.is_open) {
944
968
  // Left on an open node closes the node
@@ -977,17 +1001,6 @@ var jqtree = (function (exports) {
977
1001
  return true;
978
1002
  }
979
1003
  }
980
- deinit() {
981
- if (this.handleKeyDownHandler) {
982
- document.removeEventListener("keydown", this.handleKeyDownHandler);
983
- }
984
- }
985
- moveDown(selectedNode) {
986
- return this.selectNode(selectedNode.getNextVisibleNode());
987
- }
988
- moveUp(selectedNode) {
989
- return this.selectNode(selectedNode.getPreviousVisibleNode());
990
- }
991
1004
  }
992
1005
 
993
1006
  const getPositionInfoFromMouseEvent = e => ({
@@ -1004,18 +1017,93 @@ var jqtree = (function (exports) {
1004
1017
  });
1005
1018
 
1006
1019
  class MouseHandler {
1007
- handleClick = e => {
1008
- if (!e.target) {
1009
- return;
1020
+ constructor(_ref) {
1021
+ let {
1022
+ element,
1023
+ getMouseDelay,
1024
+ getNode,
1025
+ onClickButton,
1026
+ onClickTitle,
1027
+ onMouseCapture,
1028
+ onMouseDrag,
1029
+ onMouseStart,
1030
+ onMouseStop,
1031
+ triggerEvent,
1032
+ useContextMenu
1033
+ } = _ref;
1034
+ this.element = element;
1035
+ this.getMouseDelay = getMouseDelay;
1036
+ this.getNode = getNode;
1037
+ this.onClickButton = onClickButton;
1038
+ this.onClickTitle = onClickTitle;
1039
+ this.onMouseCapture = onMouseCapture;
1040
+ this.onMouseDrag = onMouseDrag;
1041
+ this.onMouseStart = onMouseStart;
1042
+ this.onMouseStop = onMouseStop;
1043
+ this.triggerEvent = triggerEvent;
1044
+ this.useContextMenu = useContextMenu;
1045
+ element.addEventListener("click", this.handleClick);
1046
+ element.addEventListener("dblclick", this.handleDblclick);
1047
+ element.addEventListener("mousedown", this.mouseDown, {
1048
+ passive: false
1049
+ });
1050
+ element.addEventListener("touchstart", this.touchStart, {
1051
+ passive: false
1052
+ });
1053
+ if (useContextMenu) {
1054
+ element.addEventListener("contextmenu", this.handleContextmenu);
1010
1055
  }
1011
- const clickTarget = this.getClickTarget(e.target);
1012
- if (!clickTarget) {
1013
- return;
1056
+ this.isMouseStarted = false;
1057
+ this.mouseDelayTimer = null;
1058
+ this.isMouseDelayMet = false;
1059
+ this.mouseDownInfo = null;
1060
+ }
1061
+ deinit() {
1062
+ this.element.removeEventListener("click", this.handleClick);
1063
+ this.element.removeEventListener("dblclick", this.handleDblclick);
1064
+ if (this.useContextMenu) {
1065
+ this.element.removeEventListener("contextmenu", this.handleContextmenu);
1014
1066
  }
1015
- switch (clickTarget.type) {
1016
- case "button":
1017
- this.onClickButton(clickTarget.node);
1018
- e.preventDefault();
1067
+ this.element.removeEventListener("mousedown", this.mouseDown);
1068
+ this.element.removeEventListener("touchstart", this.touchStart);
1069
+ this.removeMouseMoveEventListeners();
1070
+ }
1071
+ getClickTarget(element) {
1072
+ const button = element.closest(".jqtree-toggler");
1073
+ if (button) {
1074
+ const node = this.getNode(button);
1075
+ if (node) {
1076
+ return {
1077
+ node,
1078
+ type: "button"
1079
+ };
1080
+ }
1081
+ } else {
1082
+ const jqTreeElement = element.closest(".jqtree-element");
1083
+ if (jqTreeElement) {
1084
+ const node = this.getNode(jqTreeElement);
1085
+ if (node) {
1086
+ return {
1087
+ node,
1088
+ type: "label"
1089
+ };
1090
+ }
1091
+ }
1092
+ }
1093
+ return null;
1094
+ }
1095
+ handleClick = e => {
1096
+ if (!e.target) {
1097
+ return;
1098
+ }
1099
+ const clickTarget = this.getClickTarget(e.target);
1100
+ if (!clickTarget) {
1101
+ return;
1102
+ }
1103
+ switch (clickTarget.type) {
1104
+ case "button":
1105
+ this.onClickButton(clickTarget.node);
1106
+ e.preventDefault();
1019
1107
  e.stopPropagation();
1020
1108
  break;
1021
1109
  case "label":
@@ -1062,117 +1150,6 @@ var jqtree = (function (exports) {
1062
1150
  });
1063
1151
  }
1064
1152
  };
1065
- mouseDown = e => {
1066
- // Left mouse button?
1067
- if (e.button !== 0) {
1068
- return;
1069
- }
1070
- const result = this.handleMouseDown(getPositionInfoFromMouseEvent(e));
1071
- if (result && e.cancelable) {
1072
- e.preventDefault();
1073
- }
1074
- };
1075
- mouseMove = e => {
1076
- this.handleMouseMove(e, getPositionInfoFromMouseEvent(e));
1077
- };
1078
- mouseUp = e => {
1079
- this.handleMouseUp(getPositionInfoFromMouseEvent(e));
1080
- };
1081
- touchEnd = e => {
1082
- if (e.touches.length > 1) {
1083
- return;
1084
- }
1085
- const touch = e.touches[0];
1086
- if (!touch) {
1087
- return;
1088
- }
1089
- this.handleMouseUp(getPositionInfoFromTouch(touch, e));
1090
- };
1091
- touchMove = e => {
1092
- if (e.touches.length > 1) {
1093
- return;
1094
- }
1095
- const touch = e.touches[0];
1096
- if (!touch) {
1097
- return;
1098
- }
1099
- this.handleMouseMove(e, getPositionInfoFromTouch(touch, e));
1100
- };
1101
- touchStart = e => {
1102
- if (e.touches.length > 1) {
1103
- return;
1104
- }
1105
- const touch = e.touches[0];
1106
- if (!touch) {
1107
- return;
1108
- }
1109
- this.handleMouseDown(getPositionInfoFromTouch(touch, e));
1110
- };
1111
- constructor(_ref) {
1112
- let {
1113
- element,
1114
- getMouseDelay,
1115
- getNode,
1116
- onClickButton,
1117
- onClickTitle,
1118
- onMouseCapture,
1119
- onMouseDrag,
1120
- onMouseStart,
1121
- onMouseStop,
1122
- triggerEvent,
1123
- useContextMenu
1124
- } = _ref;
1125
- this.element = element;
1126
- this.getMouseDelay = getMouseDelay;
1127
- this.getNode = getNode;
1128
- this.onClickButton = onClickButton;
1129
- this.onClickTitle = onClickTitle;
1130
- this.onMouseCapture = onMouseCapture;
1131
- this.onMouseDrag = onMouseDrag;
1132
- this.onMouseStart = onMouseStart;
1133
- this.onMouseStop = onMouseStop;
1134
- this.triggerEvent = triggerEvent;
1135
- this.useContextMenu = useContextMenu;
1136
- element.addEventListener("click", this.handleClick);
1137
- element.addEventListener("dblclick", this.handleDblclick);
1138
- element.addEventListener("mousedown", this.mouseDown, {
1139
- passive: false
1140
- });
1141
- element.addEventListener("touchstart", this.touchStart, {
1142
- passive: false
1143
- });
1144
- if (useContextMenu) {
1145
- element.addEventListener("contextmenu", this.handleContextmenu);
1146
- }
1147
- this.isMouseStarted = false;
1148
- this.mouseDelayTimer = null;
1149
- this.isMouseDelayMet = false;
1150
- this.mouseDownInfo = null;
1151
- }
1152
- getClickTarget(element) {
1153
- const button = element.closest(".jqtree-toggler");
1154
- if (button) {
1155
- const node = this.getNode(button);
1156
- if (node) {
1157
- return {
1158
- node,
1159
- type: "button"
1160
- };
1161
- }
1162
- } else {
1163
- const jqTreeElement = element.closest(".jqtree-element");
1164
- if (jqTreeElement) {
1165
- const node = this.getNode(jqTreeElement);
1166
- if (node) {
1167
- return {
1168
- node,
1169
- type: "label"
1170
- };
1171
- }
1172
- }
1173
- }
1174
- return null;
1175
- }
1176
1153
  handleMouseDown(positionInfo) {
1177
1154
  // We may have missed mouseup (out of window)
1178
1155
  if (this.isMouseStarted) {
@@ -1237,6 +1214,22 @@ var jqtree = (function (exports) {
1237
1214
  this.isMouseDelayMet = true;
1238
1215
  }
1239
1216
  }
1217
+ mouseDown = e => {
1218
+ // Left mouse button?
1219
+ if (e.button !== 0) {
1220
+ return;
1221
+ }
1222
+ const result = this.handleMouseDown(getPositionInfoFromMouseEvent(e));
1223
+ if (result && e.cancelable) {
1224
+ e.preventDefault();
1225
+ }
1226
+ };
1227
+ mouseMove = e => {
1228
+ this.handleMouseMove(e, getPositionInfoFromMouseEvent(e));
1229
+ };
1230
+ mouseUp = e => {
1231
+ this.handleMouseUp(getPositionInfoFromMouseEvent(e));
1232
+ };
1240
1233
  removeMouseMoveEventListeners() {
1241
1234
  document.removeEventListener("mousemove", this.mouseMove);
1242
1235
  document.removeEventListener("touchmove", this.touchMove);
@@ -1254,16 +1247,36 @@ var jqtree = (function (exports) {
1254
1247
  }, mouseDelay);
1255
1248
  this.isMouseDelayMet = false;
1256
1249
  }
1257
- deinit() {
1258
- this.element.removeEventListener("click", this.handleClick);
1259
- this.element.removeEventListener("dblclick", this.handleDblclick);
1260
- if (this.useContextMenu) {
1261
- this.element.removeEventListener("contextmenu", this.handleContextmenu);
1250
+ touchEnd = e => {
1251
+ if (e.touches.length > 1) {
1252
+ return;
1262
1253
  }
1263
- this.element.removeEventListener("mousedown", this.mouseDown);
1264
- this.element.removeEventListener("touchstart", this.touchStart);
1265
- this.removeMouseMoveEventListeners();
1266
- }
1254
+ const touch = e.touches[0];
1255
+ if (!touch) {
1256
+ return;
1257
+ }
1258
+ this.handleMouseUp(getPositionInfoFromTouch(touch, e));
1259
+ };
1260
+ touchMove = e => {
1261
+ if (e.touches.length > 1) {
1262
+ return;
1263
+ }
1264
+ const touch = e.touches[0];
1265
+ if (!touch) {
1266
+ return;
1267
+ }
1268
+ this.handleMouseMove(e, getPositionInfoFromTouch(touch, e));
1269
+ };
1270
+ touchStart = e => {
1271
+ if (e.touches.length > 1) {
1272
+ return;
1273
+ }
1274
+ const touch = e.touches[0];
1275
+ if (!touch) {
1276
+ return;
1277
+ }
1278
+ this.handleMouseDown(getPositionInfoFromTouch(touch, e));
1279
+ };
1267
1280
  }
1268
1281
 
1269
1282
  const isNodeRecordWithChildren = data => typeof data === "object" && "children" in data && data.children instanceof Array;
@@ -1285,29 +1298,6 @@ var jqtree = (function (exports) {
1285
1298
  this.nodeClass = nodeClass;
1286
1299
  }
1287
1300
  }
1288
- createNode(nodeData) {
1289
- const nodeClass = this.getNodeClass();
1290
- return new nodeClass(nodeData);
1291
- }
1292
- doRemoveChild(node) {
1293
- this.children.splice(this.getChildIndex(node), 1);
1294
- this.tree?.removeNodeFromIndex(node);
1295
- }
1296
- getNodeClass() {
1297
- return this.nodeClass ?? this.tree?.nodeClass ?? Node;
1298
- }
1299
-
1300
- // Load children data from nodeInfo if it has children
1301
- loadChildrenFromData(nodeInfo) {
1302
- if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
1303
- this.loadFromData(nodeInfo.children);
1304
- }
1305
- }
1306
- setParent(parent) {
1307
- this.parent = parent;
1308
- this.tree = parent.tree;
1309
- this.tree?.addNodeToIndex(this);
1310
- }
1311
1301
  addAfter(nodeInfo) {
1312
1302
  if (!this.parent) {
1313
1303
  return null;
@@ -1783,6 +1773,29 @@ var jqtree = (function (exports) {
1783
1773
  }
1784
1774
  }
1785
1775
  }
1776
+ createNode(nodeData) {
1777
+ const nodeClass = this.getNodeClass();
1778
+ return new nodeClass(nodeData);
1779
+ }
1780
+ doRemoveChild(node) {
1781
+ this.children.splice(this.getChildIndex(node), 1);
1782
+ this.tree?.removeNodeFromIndex(node);
1783
+ }
1784
+ getNodeClass() {
1785
+ return this.nodeClass ?? this.tree?.nodeClass ?? Node;
1786
+ }
1787
+
1788
+ // Load children data from nodeInfo if it has children
1789
+ loadChildrenFromData(nodeInfo) {
1790
+ if (isNodeRecordWithChildren(nodeInfo) && nodeInfo.children.length) {
1791
+ this.loadFromData(nodeInfo.children);
1792
+ }
1793
+ }
1794
+ setParent(parent) {
1795
+ this.parent = parent;
1796
+ this.tree = parent.tree;
1797
+ this.tree?.addNodeToIndex(this);
1798
+ }
1786
1799
  }
1787
1800
 
1788
1801
  class BorderDropHint {
@@ -1828,6 +1841,9 @@ var jqtree = (function (exports) {
1828
1841
  }
1829
1842
  }
1830
1843
  }
1844
+ remove() {
1845
+ this.ghost.remove();
1846
+ }
1831
1847
  createGhostElement() {
1832
1848
  const ghost = document.createElement("li");
1833
1849
  ghost.className = "jqtree_common jqtree-ghost";
@@ -1855,33 +1871,21 @@ var jqtree = (function (exports) {
1855
1871
  childElement.before(this.ghost);
1856
1872
  }
1857
1873
  }
1858
- remove() {
1859
- this.ghost.remove();
1860
- }
1861
1874
  }
1862
1875
 
1863
1876
  class NodeElement {
1864
1877
  constructor(_ref) {
1865
1878
  let {
1866
- $treeElement,
1867
1879
  getScrollLeft,
1868
1880
  node,
1869
- tabIndex
1881
+ tabIndex,
1882
+ treeElement
1870
1883
  } = _ref;
1871
1884
  this.getScrollLeft = getScrollLeft;
1872
1885
  this.tabIndex = tabIndex;
1873
- this.$treeElement = $treeElement;
1886
+ this.treeElement = treeElement;
1874
1887
  this.init(node);
1875
1888
  }
1876
- getTitleSpan() {
1877
- return this.element.querySelector(":scope > .jqtree-element > span.jqtree-title");
1878
- }
1879
- getUl() {
1880
- return this.element.querySelector(":scope > ul");
1881
- }
1882
- mustShowBorderDropHint(position) {
1883
- return position === Position.Inside;
1884
- }
1885
1889
  addDropHint(position) {
1886
1890
  if (this.mustShowBorderDropHint(position)) {
1887
1891
  return new BorderDropHint(this.element, this.getScrollLeft());
@@ -1899,14 +1903,9 @@ var jqtree = (function (exports) {
1899
1903
  init(node) {
1900
1904
  this.node = node;
1901
1905
  if (!node.element) {
1902
- const element = this.$treeElement.get(0);
1903
- if (element) {
1904
- node.element = element;
1905
- }
1906
- }
1907
- if (node.element) {
1908
- this.element = node.element;
1906
+ node.element = this.treeElement;
1909
1907
  }
1908
+ this.element = node.element;
1910
1909
  }
1911
1910
  select(mustSetFocus) {
1912
1911
  this.element.classList.add("jqtree-selected");
@@ -1922,38 +1921,39 @@ var jqtree = (function (exports) {
1922
1921
  titleSpan.focus();
1923
1922
  }
1924
1923
  }
1924
+ getTitleSpan() {
1925
+ return this.element.querySelector(":scope > .jqtree-element > span.jqtree-title");
1926
+ }
1927
+ getUl() {
1928
+ return this.element.querySelector(":scope > ul");
1929
+ }
1930
+ mustShowBorderDropHint(position) {
1931
+ return position === Position.Inside;
1932
+ }
1925
1933
  }
1926
1934
 
1927
1935
  class FolderElement extends NodeElement {
1928
1936
  constructor(_ref) {
1929
1937
  let {
1930
- $treeElement,
1931
1938
  closedIconElement,
1932
1939
  getScrollLeft,
1933
1940
  node,
1934
1941
  openedIconElement,
1935
1942
  tabIndex,
1943
+ treeElement,
1936
1944
  triggerEvent
1937
1945
  } = _ref;
1938
1946
  super({
1939
- $treeElement,
1940
1947
  getScrollLeft,
1941
1948
  node,
1942
- tabIndex
1949
+ tabIndex,
1950
+ treeElement
1943
1951
  });
1944
1952
  this.closedIconElement = closedIconElement;
1945
1953
  this.openedIconElement = openedIconElement;
1946
1954
  this.triggerEvent = triggerEvent;
1947
1955
  }
1948
- mustShowBorderDropHint(position) {
1949
- return !this.node.is_open && position === Position.Inside;
1950
- }
1951
- getButton() {
1952
- return this.element.querySelector(":scope > .jqtree-element > a.jqtree-toggler");
1953
- }
1954
- close() {
1955
- let slide = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1956
- let animationSpeed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "fast";
1956
+ close(slide, animationSpeed) {
1957
1957
  if (!this.node.is_open) {
1958
1958
  return;
1959
1959
  }
@@ -1981,9 +1981,7 @@ var jqtree = (function (exports) {
1981
1981
  doClose();
1982
1982
  }
1983
1983
  }
1984
- open(onFinished) {
1985
- let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1986
- let animationSpeed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "fast";
1984
+ open(onFinished, slide, animationSpeed) {
1987
1985
  if (this.node.is_open) {
1988
1986
  return;
1989
1987
  }
@@ -2014,6 +2012,12 @@ var jqtree = (function (exports) {
2014
2012
  doOpen();
2015
2013
  }
2016
2014
  }
2015
+ mustShowBorderDropHint(position) {
2016
+ return !this.node.is_open && position === Position.Inside;
2017
+ }
2018
+ getButton() {
2019
+ return this.element.querySelector(":scope > .jqtree-element > a.jqtree-toggler");
2020
+ }
2017
2021
  }
2018
2022
 
2019
2023
  class SaveStateHandler {
@@ -2041,80 +2045,6 @@ var jqtree = (function (exports) {
2041
2045
  this.removeFromSelection = removeFromSelection;
2042
2046
  this.saveStateOption = saveState;
2043
2047
  }
2044
- getKeyName() {
2045
- if (typeof this.saveStateOption === "string") {
2046
- return this.saveStateOption;
2047
- } else {
2048
- return "tree";
2049
- }
2050
- }
2051
- loadFromStorage() {
2052
- if (this.onGetStateFromStorage) {
2053
- return this.onGetStateFromStorage();
2054
- } else if (this.supportsLocalStorage()) {
2055
- return localStorage.getItem(this.getKeyName());
2056
- } else {
2057
- return null;
2058
- }
2059
- }
2060
- openInitialNodes(nodeIds) {
2061
- let mustLoadOnDemand = false;
2062
- for (const nodeId of nodeIds) {
2063
- const node = this.getNodeById(nodeId);
2064
- if (node) {
2065
- if (!node.load_on_demand) {
2066
- node.is_open = true;
2067
- } else {
2068
- mustLoadOnDemand = true;
2069
- }
2070
- }
2071
- }
2072
- return mustLoadOnDemand;
2073
- }
2074
- parseState(jsonData) {
2075
- const state = JSON.parse(jsonData);
2076
-
2077
- // Check if selected_node is an int (instead of an array)
2078
- if (state.selected_node && isInt(state.selected_node)) {
2079
- // Convert to array
2080
- state.selected_node = [state.selected_node];
2081
- }
2082
- return state;
2083
- }
2084
- resetSelection() {
2085
- const selectedNodes = this.getSelectedNodes();
2086
- selectedNodes.forEach(node => {
2087
- this.removeFromSelection(node);
2088
- });
2089
- }
2090
- selectInitialNodes(nodeIds) {
2091
- let selectCount = 0;
2092
- for (const nodeId of nodeIds) {
2093
- const node = this.getNodeById(nodeId);
2094
- if (node) {
2095
- selectCount += 1;
2096
- this.addToSelection(node);
2097
- }
2098
- }
2099
- return selectCount !== 0;
2100
- }
2101
- supportsLocalStorage() {
2102
- const testSupport = () => {
2103
- // Check if it's possible to store an item. Safari does not allow this in private browsing mode.
2104
- try {
2105
- const key = "_storage_test";
2106
- sessionStorage.setItem(key, "value");
2107
- sessionStorage.removeItem(key);
2108
- } catch {
2109
- return false;
2110
- }
2111
- return true;
2112
- };
2113
- if (this._supportsLocalStorage == null) {
2114
- this._supportsLocalStorage = testSupport();
2115
- }
2116
- return this._supportsLocalStorage;
2117
- }
2118
2048
  getNodeIdToBeSelected() {
2119
2049
  const state = this.getStateFromStorage();
2120
2050
  if (state?.selected_node) {
@@ -2160,7 +2090,7 @@ var jqtree = (function (exports) {
2160
2090
  const state = JSON.stringify(this.getState());
2161
2091
  if (this.onSetStateFromStorage) {
2162
2092
  this.onSetStateFromStorage(state);
2163
- } else if (this.supportsLocalStorage()) {
2093
+ } else {
2164
2094
  localStorage.setItem(this.getKeyName(), state);
2165
2095
  }
2166
2096
  }
@@ -2168,7 +2098,7 @@ var jqtree = (function (exports) {
2168
2098
  /*
2169
2099
  Set initial state
2170
2100
  Don't handle nodes that are loaded on demand
2171
- result: must load on demand
2101
+ result: must load on demand (boolean)
2172
2102
  */
2173
2103
  setInitialState(state) {
2174
2104
  let mustLoadOnDemand = false;
@@ -2222,6 +2152,61 @@ var jqtree = (function (exports) {
2222
2152
  };
2223
2153
  openNodes();
2224
2154
  }
2155
+ getKeyName() {
2156
+ if (typeof this.saveStateOption === "string") {
2157
+ return this.saveStateOption;
2158
+ } else {
2159
+ return "tree";
2160
+ }
2161
+ }
2162
+ loadFromStorage() {
2163
+ if (this.onGetStateFromStorage) {
2164
+ return this.onGetStateFromStorage();
2165
+ } else {
2166
+ return localStorage.getItem(this.getKeyName());
2167
+ }
2168
+ }
2169
+ openInitialNodes(nodeIds) {
2170
+ let mustLoadOnDemand = false;
2171
+ for (const nodeId of nodeIds) {
2172
+ const node = this.getNodeById(nodeId);
2173
+ if (node) {
2174
+ if (!node.load_on_demand) {
2175
+ node.is_open = true;
2176
+ } else {
2177
+ mustLoadOnDemand = true;
2178
+ }
2179
+ }
2180
+ }
2181
+ return mustLoadOnDemand;
2182
+ }
2183
+ parseState(jsonData) {
2184
+ const state = JSON.parse(jsonData);
2185
+
2186
+ // Check if selected_node is an int (instead of an array)
2187
+ if (state.selected_node && isInt(state.selected_node)) {
2188
+ // Convert to array
2189
+ state.selected_node = [state.selected_node];
2190
+ }
2191
+ return state;
2192
+ }
2193
+ resetSelection() {
2194
+ const selectedNodes = this.getSelectedNodes();
2195
+ selectedNodes.forEach(node => {
2196
+ this.removeFromSelection(node);
2197
+ });
2198
+ }
2199
+ selectInitialNodes(nodeIds) {
2200
+ let selectCount = 0;
2201
+ for (const nodeId of nodeIds) {
2202
+ const node = this.getNodeById(nodeId);
2203
+ if (node) {
2204
+ selectCount += 1;
2205
+ this.addToSelection(node);
2206
+ }
2207
+ }
2208
+ return selectCount !== 0;
2209
+ }
2225
2210
  }
2226
2211
 
2227
2212
  class ContainerScrollParent {
@@ -2233,6 +2218,43 @@ var jqtree = (function (exports) {
2233
2218
  this.container = container;
2234
2219
  this.refreshHitAreas = refreshHitAreas;
2235
2220
  }
2221
+ checkHorizontalScrolling(pageX) {
2222
+ const newHorizontalScrollDirection = this.getNewHorizontalScrollDirection(pageX);
2223
+ if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
2224
+ this.horizontalScrollDirection = newHorizontalScrollDirection;
2225
+ if (this.horizontalScrollTimeout != null) {
2226
+ window.clearTimeout(this.verticalScrollTimeout);
2227
+ }
2228
+ if (newHorizontalScrollDirection) {
2229
+ this.horizontalScrollTimeout = window.setTimeout(this.scrollHorizontally.bind(this), 40);
2230
+ }
2231
+ }
2232
+ }
2233
+ checkVerticalScrolling(pageY) {
2234
+ const newVerticalScrollDirection = this.getNewVerticalScrollDirection(pageY);
2235
+ if (this.verticalScrollDirection !== newVerticalScrollDirection) {
2236
+ this.verticalScrollDirection = newVerticalScrollDirection;
2237
+ if (this.verticalScrollTimeout != null) {
2238
+ window.clearTimeout(this.verticalScrollTimeout);
2239
+ this.verticalScrollTimeout = undefined;
2240
+ }
2241
+ if (newVerticalScrollDirection) {
2242
+ this.verticalScrollTimeout = window.setTimeout(this.scrollVertically.bind(this), 40);
2243
+ }
2244
+ }
2245
+ }
2246
+ getScrollLeft() {
2247
+ return this.container.scrollLeft;
2248
+ }
2249
+ scrollToY(top) {
2250
+ this.container.scrollTop = top;
2251
+ }
2252
+ stopScrolling() {
2253
+ this.horizontalScrollDirection = undefined;
2254
+ this.verticalScrollDirection = undefined;
2255
+ this.scrollParentTop = undefined;
2256
+ this.scrollParentBottom = undefined;
2257
+ }
2236
2258
  getNewHorizontalScrollDirection(pageX) {
2237
2259
  const scrollParentOffset = getElementPosition(this.container);
2238
2260
  const rightEdge = scrollParentOffset.left + this.container.clientWidth;
@@ -2293,12 +2315,23 @@ var jqtree = (function (exports) {
2293
2315
  this.refreshHitAreas();
2294
2316
  setTimeout(this.scrollVertically.bind(this), 40);
2295
2317
  }
2318
+ }
2319
+
2320
+ class DocumentScrollParent {
2321
+ constructor(_ref) {
2322
+ let {
2323
+ refreshHitAreas,
2324
+ treeElement
2325
+ } = _ref;
2326
+ this.refreshHitAreas = refreshHitAreas;
2327
+ this.treeElement = treeElement;
2328
+ }
2296
2329
  checkHorizontalScrolling(pageX) {
2297
2330
  const newHorizontalScrollDirection = this.getNewHorizontalScrollDirection(pageX);
2298
2331
  if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
2299
2332
  this.horizontalScrollDirection = newHorizontalScrollDirection;
2300
2333
  if (this.horizontalScrollTimeout != null) {
2301
- window.clearTimeout(this.verticalScrollTimeout);
2334
+ window.clearTimeout(this.horizontalScrollTimeout);
2302
2335
  }
2303
2336
  if (newHorizontalScrollDirection) {
2304
2337
  this.horizontalScrollTimeout = window.setTimeout(this.scrollHorizontally.bind(this), 40);
@@ -2319,27 +2352,17 @@ var jqtree = (function (exports) {
2319
2352
  }
2320
2353
  }
2321
2354
  getScrollLeft() {
2322
- return this.container.scrollLeft;
2355
+ return document.documentElement.scrollLeft;
2323
2356
  }
2324
2357
  scrollToY(top) {
2325
- this.container.scrollTop = top;
2358
+ const treeTop = getOffsetTop(this.treeElement);
2359
+ document.documentElement.scrollTop = top + treeTop;
2326
2360
  }
2327
2361
  stopScrolling() {
2328
2362
  this.horizontalScrollDirection = undefined;
2329
2363
  this.verticalScrollDirection = undefined;
2330
- this.scrollParentTop = undefined;
2331
- this.scrollParentBottom = undefined;
2332
- }
2333
- }
2334
-
2335
- class DocumentScrollParent {
2336
- constructor(_ref) {
2337
- let {
2338
- refreshHitAreas,
2339
- treeElement
2340
- } = _ref;
2341
- this.refreshHitAreas = refreshHitAreas;
2342
- this.treeElement = treeElement;
2364
+ this.documentScrollHeight = undefined;
2365
+ this.documentScrollWidth = undefined;
2343
2366
  }
2344
2367
  canScrollDown() {
2345
2368
  const documentElement = document.documentElement;
@@ -2414,61 +2437,23 @@ var jqtree = (function (exports) {
2414
2437
  this.refreshHitAreas();
2415
2438
  setTimeout(this.scrollVertically.bind(this), 40);
2416
2439
  }
2417
- checkHorizontalScrolling(pageX) {
2418
- const newHorizontalScrollDirection = this.getNewHorizontalScrollDirection(pageX);
2419
- if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
2420
- this.horizontalScrollDirection = newHorizontalScrollDirection;
2421
- if (this.horizontalScrollTimeout != null) {
2422
- window.clearTimeout(this.horizontalScrollTimeout);
2423
- }
2424
- if (newHorizontalScrollDirection) {
2425
- this.horizontalScrollTimeout = window.setTimeout(this.scrollHorizontally.bind(this), 40);
2426
- }
2440
+ }
2441
+
2442
+ const isOverflow = overflowValue => overflowValue === "auto" || overflowValue === "scroll";
2443
+ const hasOverFlow = element => {
2444
+ const style = getComputedStyle(element);
2445
+ return isOverflow(style.overflowX) || isOverflow(style.overflowY);
2446
+ };
2447
+ const getParentWithOverflow = treeElement => {
2448
+ if (hasOverFlow(treeElement)) {
2449
+ return treeElement;
2450
+ }
2451
+ let parent = treeElement.parentElement;
2452
+ while (parent) {
2453
+ if (hasOverFlow(parent)) {
2454
+ return parent;
2427
2455
  }
2428
- }
2429
- checkVerticalScrolling(pageY) {
2430
- const newVerticalScrollDirection = this.getNewVerticalScrollDirection(pageY);
2431
- if (this.verticalScrollDirection !== newVerticalScrollDirection) {
2432
- this.verticalScrollDirection = newVerticalScrollDirection;
2433
- if (this.verticalScrollTimeout != null) {
2434
- window.clearTimeout(this.verticalScrollTimeout);
2435
- this.verticalScrollTimeout = undefined;
2436
- }
2437
- if (newVerticalScrollDirection) {
2438
- this.verticalScrollTimeout = window.setTimeout(this.scrollVertically.bind(this), 40);
2439
- }
2440
- }
2441
- }
2442
- getScrollLeft() {
2443
- return document.documentElement.scrollLeft;
2444
- }
2445
- scrollToY(top) {
2446
- const treeTop = getOffsetTop(this.treeElement);
2447
- document.documentElement.scrollTop = top + treeTop;
2448
- }
2449
- stopScrolling() {
2450
- this.horizontalScrollDirection = undefined;
2451
- this.verticalScrollDirection = undefined;
2452
- this.documentScrollHeight = undefined;
2453
- this.documentScrollWidth = undefined;
2454
- }
2455
- }
2456
-
2457
- const isOverflow = overflowValue => overflowValue === "auto" || overflowValue === "scroll";
2458
- const hasOverFlow = element => {
2459
- const style = getComputedStyle(element);
2460
- return isOverflow(style.overflowX) || isOverflow(style.overflowY);
2461
- };
2462
- const getParentWithOverflow = treeElement => {
2463
- if (hasOverFlow(treeElement)) {
2464
- return treeElement;
2465
- }
2466
- let parent = treeElement.parentElement;
2467
- while (parent) {
2468
- if (hasOverFlow(parent)) {
2469
- return parent;
2470
- }
2471
- parent = parent.parentElement;
2456
+ parent = parent.parentElement;
2472
2457
  }
2473
2458
  return null;
2474
2459
  };
@@ -2497,18 +2482,6 @@ var jqtree = (function (exports) {
2497
2482
  this.scrollParent = undefined;
2498
2483
  this.treeElement = treeElement;
2499
2484
  }
2500
- checkHorizontalScrolling(positionInfo) {
2501
- this.getScrollParent().checkHorizontalScrolling(positionInfo.pageX);
2502
- }
2503
- checkVerticalScrolling(positionInfo) {
2504
- this.getScrollParent().checkVerticalScrolling(positionInfo.pageY);
2505
- }
2506
- getScrollParent() {
2507
- if (!this.scrollParent) {
2508
- this.scrollParent = createScrollParent(this.treeElement, this.refreshHitAreas);
2509
- }
2510
- return this.scrollParent;
2511
- }
2512
2485
  checkScrolling(positionInfo) {
2513
2486
  this.checkVerticalScrolling(positionInfo);
2514
2487
  this.checkHorizontalScrolling(positionInfo);
@@ -2522,6 +2495,18 @@ var jqtree = (function (exports) {
2522
2495
  stopScrolling() {
2523
2496
  this.getScrollParent().stopScrolling();
2524
2497
  }
2498
+ checkHorizontalScrolling(positionInfo) {
2499
+ this.getScrollParent().checkHorizontalScrolling(positionInfo.pageX);
2500
+ }
2501
+ checkVerticalScrolling(positionInfo) {
2502
+ this.getScrollParent().checkVerticalScrolling(positionInfo.pageY);
2503
+ }
2504
+ getScrollParent() {
2505
+ if (!this.scrollParent) {
2506
+ this.scrollParent = createScrollParent(this.treeElement, this.refreshHitAreas);
2507
+ }
2508
+ return this.scrollParent;
2509
+ }
2525
2510
  }
2526
2511
 
2527
2512
  class SelectNodeHandler {
@@ -2575,14 +2560,12 @@ var jqtree = (function (exports) {
2575
2560
  }
2576
2561
  } else {
2577
2562
  const selectedNodes = [];
2578
- for (const id in this.selectedNodes) {
2579
- if (Object.prototype.hasOwnProperty.call(this.selectedNodes, id)) {
2580
- const node = this.getNodeById(id);
2581
- if (node && parent.isParentOf(node)) {
2582
- selectedNodes.push(node);
2583
- }
2563
+ this.selectedNodes.forEach(id => {
2564
+ const node = this.getNodeById(id);
2565
+ if (node && parent.isParentOf(node)) {
2566
+ selectedNodes.push(node);
2584
2567
  }
2585
- }
2568
+ });
2586
2569
  return selectedNodes;
2587
2570
  }
2588
2571
  }
@@ -2718,7 +2701,7 @@ var jqtree = (function (exports) {
2718
2701
  }
2719
2702
  }
2720
2703
 
2721
- const version = "1.8.7";
2704
+ const version = "1.8.8";
2722
2705
 
2723
2706
  const NODE_PARAM_IS_EMPTY = "Node parameter is empty";
2724
2707
  const PARAM_IS_EMPTY = "Parameter is empty: ";
@@ -2769,917 +2752,920 @@ var jqtree = (function (exports) {
2769
2752
  tabIndex: 0,
2770
2753
  useContextMenu: true
2771
2754
  }))();
2772
- connectHandlers() {
2773
- const {
2774
- autoEscape,
2775
- buttonLeft,
2776
- closedIcon,
2777
- dataFilter,
2778
- dragAndDrop,
2779
- keyboardSupport,
2780
- onCanMove,
2781
- onCanMoveTo,
2782
- onCreateLi,
2783
- onDragMove,
2784
- onDragStop,
2785
- onGetStateFromStorage,
2786
- onIsMoveHandle,
2787
- onLoadFailed,
2788
- onLoading,
2789
- onSetStateFromStorage,
2790
- openedIcon,
2791
- openFolderDelay,
2792
- rtl,
2793
- saveState,
2794
- showEmptyFolder,
2795
- slide,
2796
- tabIndex
2797
- } = this.options;
2798
- const closeNode = this.closeNode.bind(this);
2799
- const getNodeElement = this.getNodeElement.bind(this);
2800
- const getNodeElementForNode = this.getNodeElementForNode.bind(this);
2801
- const getNodeById = this.getNodeById.bind(this);
2802
- const getSelectedNode = this.getSelectedNode.bind(this);
2803
- const getTree = this.getTree.bind(this);
2804
- const isFocusOnTree = this.isFocusOnTree.bind(this);
2805
- const loadData = this.loadData.bind(this);
2806
- const openNode = this.openNodeInternal.bind(this);
2807
- const refreshElements = this.refreshElements.bind(this);
2808
- const refreshHitAreas = this.refreshHitAreas.bind(this);
2809
- const selectNode = this.selectNode.bind(this);
2810
- const $treeElement = this.element;
2811
- const treeElement = this.element.get(0);
2812
- const triggerEvent = this.triggerEvent.bind(this);
2813
- const selectNodeHandler = new SelectNodeHandler({
2814
- getNodeById
2815
- });
2816
- const addToSelection = selectNodeHandler.addToSelection.bind(selectNodeHandler);
2817
- const getSelectedNodes = selectNodeHandler.getSelectedNodes.bind(selectNodeHandler);
2818
- const isNodeSelected = selectNodeHandler.isNodeSelected.bind(selectNodeHandler);
2819
- const removeFromSelection = selectNodeHandler.removeFromSelection.bind(selectNodeHandler);
2820
- const getMouseDelay = () => this.options.startDndDelay ?? 0;
2821
- const dataLoader = new DataLoader({
2822
- dataFilter,
2823
- loadData,
2824
- onLoadFailed,
2825
- onLoading,
2826
- treeElement,
2827
- triggerEvent
2828
- });
2829
- const saveStateHandler = new SaveStateHandler({
2830
- addToSelection,
2831
- getNodeById,
2832
- getSelectedNodes,
2833
- getTree,
2834
- onGetStateFromStorage,
2835
- onSetStateFromStorage,
2836
- openNode,
2837
- refreshElements,
2838
- removeFromSelection,
2839
- saveState
2840
- });
2841
- const scrollHandler = new ScrollHandler({
2842
- refreshHitAreas,
2843
- treeElement
2844
- });
2845
- const getScrollLeft = scrollHandler.getScrollLeft.bind(scrollHandler);
2846
- const dndHandler = new DragAndDropHandler({
2847
- autoEscape,
2848
- getNodeElement,
2849
- getNodeElementForNode,
2850
- getScrollLeft,
2851
- getTree,
2852
- onCanMove,
2853
- onCanMoveTo,
2854
- onDragMove,
2855
- onDragStop,
2856
- onIsMoveHandle,
2857
- openFolderDelay,
2858
- openNode,
2859
- refreshElements,
2860
- slide,
2861
- treeElement,
2862
- triggerEvent
2863
- });
2864
- const keyHandler = new KeyHandler({
2865
- closeNode,
2866
- getSelectedNode,
2867
- isFocusOnTree,
2868
- keyboardSupport,
2869
- openNode,
2870
- selectNode
2871
- });
2872
- const renderer = new ElementsRenderer({
2873
- $element: $treeElement,
2874
- autoEscape,
2875
- buttonLeft,
2876
- closedIcon,
2877
- dragAndDrop,
2878
- getTree,
2879
- isNodeSelected,
2880
- onCreateLi,
2881
- openedIcon,
2882
- rtl,
2883
- showEmptyFolder,
2884
- tabIndex
2885
- });
2886
- const getNode = this.getNode.bind(this);
2887
- const onMouseCapture = this.mouseCapture.bind(this);
2888
- const onMouseDrag = this.mouseDrag.bind(this);
2889
- const onMouseStart = this.mouseStart.bind(this);
2890
- const onMouseStop = this.mouseStop.bind(this);
2891
- const mouseHandler = new MouseHandler({
2892
- element: treeElement,
2893
- getMouseDelay,
2894
- getNode,
2895
- onClickButton: this.toggle.bind(this),
2896
- onClickTitle: this.doSelectNode.bind(this),
2897
- onMouseCapture,
2898
- onMouseDrag,
2899
- onMouseStart,
2900
- onMouseStop,
2901
- triggerEvent,
2902
- useContextMenu: this.options.useContextMenu
2903
- });
2904
- this.dataLoader = dataLoader;
2905
- this.dndHandler = dndHandler;
2906
- this.keyHandler = keyHandler;
2907
- this.mouseHandler = mouseHandler;
2908
- this.renderer = renderer;
2909
- this.saveStateHandler = saveStateHandler;
2910
- this.scrollHandler = scrollHandler;
2911
- this.selectNodeHandler = selectNodeHandler;
2755
+ addNodeAfter(newNodeInfo, existingNode) {
2756
+ const newNode = existingNode.addAfter(newNodeInfo);
2757
+ if (newNode) {
2758
+ this.refreshElements(existingNode.parent);
2759
+ }
2760
+ return newNode;
2912
2761
  }
2913
- containsElement(element) {
2914
- const node = this.getNode(element);
2915
- return node != null && node.tree === this.tree;
2762
+ addNodeBefore(newNodeInfo, existingNode) {
2763
+ if (!existingNode) {
2764
+ throw Error(PARAM_IS_EMPTY + "existingNode");
2765
+ }
2766
+ const newNode = existingNode.addBefore(newNodeInfo);
2767
+ if (newNode) {
2768
+ this.refreshElements(existingNode.parent);
2769
+ }
2770
+ return newNode;
2916
2771
  }
2917
- createFolderElement(node) {
2918
- const closedIconElement = this.renderer.closedIconElement;
2919
- const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
2920
- const openedIconElement = this.renderer.openedIconElement;
2921
- const tabIndex = this.options.tabIndex;
2922
- const $treeElement = this.element;
2923
- const triggerEvent = this.triggerEvent.bind(this);
2924
- return new FolderElement({
2925
- $treeElement,
2926
- closedIconElement,
2927
- getScrollLeft,
2928
- node,
2929
- openedIconElement,
2930
- tabIndex,
2931
- triggerEvent
2932
- });
2772
+ addParentNode(newNodeInfo, existingNode) {
2773
+ if (!existingNode) {
2774
+ throw Error(PARAM_IS_EMPTY + "existingNode");
2775
+ }
2776
+ const newNode = existingNode.addParent(newNodeInfo);
2777
+ if (newNode) {
2778
+ this.refreshElements(newNode.parent);
2779
+ }
2780
+ return newNode;
2933
2781
  }
2934
- createNodeElement(node) {
2935
- const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
2936
- const tabIndex = this.options.tabIndex;
2937
- const $treeElement = this.element;
2938
- return new NodeElement({
2939
- $treeElement,
2940
- getScrollLeft,
2941
- node,
2942
- tabIndex
2943
- });
2944
- }
2945
- deselectCurrentNode() {
2946
- const node = this.getSelectedNode();
2947
- if (node) {
2948
- this.removeFromSelection(node);
2949
- }
2950
- }
2951
- deselectNodes(parentNode) {
2952
- const selectedNodesUnderParent = this.selectNodeHandler.getSelectedNodesUnder(parentNode);
2953
- for (const n of selectedNodesUnderParent) {
2954
- this.selectNodeHandler.removeFromSelection(n);
2955
- }
2956
- }
2957
- doLoadData(data, parentNode) {
2958
- if (data) {
2959
- if (parentNode) {
2960
- this.deselectNodes(parentNode);
2961
- this.loadSubtree(data, parentNode);
2962
- } else {
2963
- this.initTree(data);
2964
- }
2965
- if (this.isDragging()) {
2966
- this.dndHandler.refresh();
2967
- }
2782
+ addToSelection(node, mustSetFocus) {
2783
+ if (!node) {
2784
+ throw Error(NODE_PARAM_IS_EMPTY);
2968
2785
  }
2969
- this.triggerEvent("tree.load_data", {
2970
- parent_node: parentNode,
2971
- tree_data: data
2972
- });
2786
+ this.selectNodeHandler.addToSelection(node);
2787
+ this.openParents(node);
2788
+ this.getNodeElementForNode(node).select(mustSetFocus ?? true);
2789
+ this.saveState();
2790
+ return this.element;
2973
2791
  }
2974
- doLoadDataFromUrl(urlInfoParam, parentNode, onFinished) {
2975
- const urlInfo = urlInfoParam ?? this.getDataUrlInfo(parentNode);
2976
- this.dataLoader.loadFromUrl(urlInfo, parentNode, onFinished);
2792
+ appendNode(newNodeInfo, parentNodeParam) {
2793
+ const parentNode = parentNodeParam ?? this.tree;
2794
+ const node = parentNode.append(newNodeInfo);
2795
+ this.refreshElements(parentNode);
2796
+ return node;
2977
2797
  }
2978
- doSelectNode(node, optionsParam) {
2979
- const saveState = () => {
2980
- if (this.options.saveState) {
2981
- this.saveStateHandler.saveState();
2982
- }
2983
- };
2798
+ closeNode(node, slideParam) {
2984
2799
  if (!node) {
2985
- // Called with empty node -> deselect current node
2986
- this.deselectCurrentNode();
2987
- saveState();
2988
- return;
2989
- }
2990
- const defaultOptions = {
2991
- mustSetFocus: true,
2992
- mustToggle: true
2993
- };
2994
- const selectOptions = {
2995
- ...defaultOptions,
2996
- ...(optionsParam ?? {})
2997
- };
2998
- const canSelect = () => {
2999
- if (this.options.onCanSelectNode) {
3000
- return this.options.selectable && this.options.onCanSelectNode(node);
3001
- } else {
3002
- return this.options.selectable;
3003
- }
3004
- };
3005
- if (!canSelect()) {
3006
- return;
3007
- }
3008
- if (this.selectNodeHandler.isNodeSelected(node)) {
3009
- if (selectOptions.mustToggle) {
3010
- this.deselectCurrentNode();
3011
- this.triggerEvent("tree.select", {
3012
- node: null,
3013
- previous_node: node
3014
- });
3015
- }
3016
- } else {
3017
- const deselectedNode = this.getSelectedNode() || null;
3018
- this.deselectCurrentNode();
3019
- this.addToSelection(node, selectOptions.mustSetFocus);
3020
- this.triggerEvent("tree.select", {
3021
- deselected_node: deselectedNode,
3022
- node
3023
- });
3024
- this.openParents(node);
2800
+ throw Error(NODE_PARAM_IS_EMPTY);
3025
2801
  }
3026
- saveState();
3027
- }
3028
- getAutoOpenMaxLevel() {
3029
- if (this.options.autoOpen === true) {
3030
- return -1;
3031
- } else if (typeof this.options.autoOpen === "number") {
3032
- return this.options.autoOpen;
3033
- } else if (typeof this.options.autoOpen === "string") {
3034
- return parseInt(this.options.autoOpen, 10);
3035
- } else {
3036
- return 0;
2802
+ const slide = slideParam ?? this.options.slide;
2803
+ if (node.isFolder() || node.isEmptyFolder) {
2804
+ this.createFolderElement(node).close(slide, this.options.animationSpeed);
2805
+ this.saveState();
3037
2806
  }
2807
+ return this.element;
3038
2808
  }
3039
- getDataUrlInfo(node) {
3040
- const dataUrl = this.options.dataUrl ?? this.element.data("url");
3041
- const getUrlFromString = url => {
3042
- const urlInfo = {
3043
- url
3044
- };
3045
- setUrlInfoData(urlInfo);
3046
- return urlInfo;
3047
- };
3048
- const setUrlInfoData = urlInfo => {
3049
- if (node?.id) {
3050
- // Load on demand of a subtree; add node parameter
3051
- const data = {
3052
- node: node.id
3053
- };
3054
- urlInfo.data = data;
3055
- } else {
3056
- // Add selected_node parameter
3057
- const selectedNodeId = this.getNodeIdToBeSelected();
3058
- if (selectedNodeId) {
3059
- const data = {
3060
- selected_node: selectedNodeId
3061
- };
3062
- urlInfo.data = data;
3063
- }
3064
- }
3065
- };
3066
- if (typeof dataUrl === "function") {
3067
- return dataUrl(node);
3068
- } else if (typeof dataUrl === "string") {
3069
- return getUrlFromString(dataUrl);
3070
- } else if (dataUrl && typeof dataUrl === "object") {
3071
- setUrlInfoData(dataUrl);
3072
- return dataUrl;
3073
- } else {
3074
- return null;
3075
- }
2809
+ deinit() {
2810
+ this.element.empty();
2811
+ this.element.off();
2812
+ this.keyHandler.deinit();
2813
+ this.mouseHandler.deinit();
2814
+ this.tree = new Node({}, true);
2815
+ super.deinit();
3076
2816
  }
3077
- getDefaultClosedIcon() {
3078
- if (this.options.rtl) {
3079
- // triangle to the left
3080
- return "&#x25c0;";
3081
- } else {
3082
- // triangle to the right
3083
- return "&#x25ba;";
3084
- }
2817
+ getNodeByCallback(callback) {
2818
+ return this.tree.getNodeByCallback(callback);
3085
2819
  }
3086
- getNode(element) {
3087
- const liElement = element.closest("li.jqtree_common");
3088
- if (liElement) {
3089
- return jQuery(liElement).data("node");
3090
- } else {
2820
+ getNodeByHtmlElement(inputElement) {
2821
+ const element = inputElement instanceof HTMLElement ? inputElement : inputElement[0];
2822
+ if (!element) {
3091
2823
  return null;
3092
2824
  }
2825
+ return this.getNode(element);
3093
2826
  }
3094
- getNodeElement(element) {
3095
- const node = this.getNode(element);
3096
- if (node) {
3097
- return this.getNodeElementForNode(node);
3098
- } else {
3099
- return null;
3100
- }
2827
+ getNodeById(nodeId) {
2828
+ return this.tree.getNodeById(nodeId);
3101
2829
  }
3102
- getNodeElementForNode(node) {
3103
- if (node.isFolder()) {
3104
- return this.createFolderElement(node);
3105
- } else {
3106
- return this.createNodeElement(node);
3107
- }
2830
+ getNodeByName(name) {
2831
+ return this.tree.getNodeByName(name);
3108
2832
  }
3109
- getNodeIdToBeSelected() {
3110
- if (this.options.saveState) {
3111
- return this.saveStateHandler.getNodeIdToBeSelected();
3112
- } else {
3113
- return null;
3114
- }
2833
+ getNodeByNameMustExist(name) {
2834
+ return this.tree.getNodeByNameMustExist(name);
3115
2835
  }
3116
- getRtlOption() {
3117
- if (this.options.rtl != null) {
3118
- return this.options.rtl;
3119
- } else {
3120
- const dataRtl = this.element.data("rtl");
3121
- if (dataRtl !== null && dataRtl !== false && dataRtl !== undefined) {
3122
- return true;
3123
- } else {
3124
- return false;
3125
- }
3126
- }
2836
+ getNodesByProperty(key, value) {
2837
+ return this.tree.getNodesByProperty(key, value);
3127
2838
  }
3128
- initData() {
3129
- if (this.options.data) {
3130
- this.doLoadData(this.options.data, null);
3131
- } else {
3132
- const dataUrl = this.getDataUrlInfo(null);
3133
- if (dataUrl) {
3134
- this.doLoadDataFromUrl(null, null, null);
3135
- } else {
3136
- this.doLoadData([], null);
3137
- }
3138
- }
2839
+ getSelectedNode() {
2840
+ return this.selectNodeHandler.getSelectedNode();
3139
2841
  }
3140
- initTree(data) {
3141
- const doInit = () => {
3142
- if (!this.isInitialized) {
3143
- this.isInitialized = true;
3144
- this.triggerEvent("tree.init");
3145
- }
3146
- };
3147
- this.tree = new this.options.nodeClass(null, true, this.options.nodeClass);
3148
- this.selectNodeHandler.clear();
3149
- this.tree.loadFromData(data);
3150
- const mustLoadOnDemand = this.setInitialState();
3151
- this.refreshElements(null);
3152
- if (!mustLoadOnDemand) {
3153
- doInit();
3154
- } else {
3155
- // Load data on demand and then init the tree
3156
- this.setInitialStateOnDemand(doInit);
3157
- }
2842
+ getSelectedNodes() {
2843
+ return this.selectNodeHandler.getSelectedNodes();
3158
2844
  }
3159
- isFocusOnTree() {
3160
- const activeElement = document.activeElement;
3161
- return Boolean(activeElement && activeElement.tagName === "SPAN" && this.containsElement(activeElement));
2845
+ getState() {
2846
+ return this.saveStateHandler.getState();
3162
2847
  }
3163
- isSelectedNodeInSubtree(subtree) {
3164
- const selectedNode = this.getSelectedNode();
3165
- if (!selectedNode) {
3166
- return false;
3167
- } else {
3168
- return subtree === selectedNode || subtree.isParentOf(selectedNode);
3169
- }
2848
+ getStateFromStorage() {
2849
+ return this.saveStateHandler.getStateFromStorage();
3170
2850
  }
3171
- loadFolderOnDemand(node) {
3172
- let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
3173
- let onFinished = arguments.length > 2 ? arguments[2] : undefined;
3174
- node.is_loading = true;
3175
- this.doLoadDataFromUrl(null, node, () => {
3176
- this.openNodeInternal(node, slide, onFinished);
3177
- });
2851
+ getTree() {
2852
+ return this.tree;
3178
2853
  }
3179
- loadSubtree(data, parentNode) {
3180
- parentNode.loadFromData(data);
3181
- parentNode.load_on_demand = false;
3182
- parentNode.is_loading = false;
3183
- this.refreshElements(parentNode);
2854
+ getVersion() {
2855
+ return version;
3184
2856
  }
3185
- mouseCapture(positionInfo) {
3186
- if (this.options.dragAndDrop) {
3187
- return this.dndHandler.mouseCapture(positionInfo);
3188
- } else {
3189
- return false;
2857
+ init() {
2858
+ super.init();
2859
+ this.element = this.$el;
2860
+ this.isInitialized = false;
2861
+ this.options.rtl = this.getRtlOption();
2862
+ if (this.options.closedIcon == null) {
2863
+ this.options.closedIcon = this.getDefaultClosedIcon();
3190
2864
  }
2865
+ this.connectHandlers();
2866
+ this.initData();
3191
2867
  }
3192
- mouseDrag(positionInfo) {
3193
- if (this.options.dragAndDrop) {
3194
- const result = this.dndHandler.mouseDrag(positionInfo);
3195
- this.scrollHandler.checkScrolling(positionInfo);
3196
- return result;
3197
- } else {
3198
- return false;
3199
- }
2868
+ isDragging() {
2869
+ return this.dndHandler.isDragging;
3200
2870
  }
3201
- mouseStart(positionInfo) {
3202
- if (this.options.dragAndDrop) {
3203
- return this.dndHandler.mouseStart(positionInfo);
3204
- } else {
3205
- return false;
2871
+ isNodeSelected(node) {
2872
+ if (!node) {
2873
+ throw Error(NODE_PARAM_IS_EMPTY);
3206
2874
  }
2875
+ return this.selectNodeHandler.isNodeSelected(node);
3207
2876
  }
3208
- mouseStop(positionInfo) {
3209
- if (this.options.dragAndDrop) {
3210
- this.scrollHandler.stopScrolling();
3211
- return this.dndHandler.mouseStop(positionInfo);
2877
+ loadData(data, parentNode) {
2878
+ this.doLoadData(data, parentNode);
2879
+ return this.element;
2880
+ }
2881
+
2882
+ /*
2883
+ signatures:
2884
+ - loadDataFromUrl(url, parent_node=null, on_finished=null)
2885
+ loadDataFromUrl('/my_data');
2886
+ loadDataFromUrl('/my_data', node1);
2887
+ loadDataFromUrl('/my_data', node1, function() { console.log('finished'); });
2888
+ loadDataFromUrl('/my_data', null, function() { console.log('finished'); });
2889
+ - loadDataFromUrl(parent_node=null, on_finished=null)
2890
+ loadDataFromUrl();
2891
+ loadDataFromUrl(node1);
2892
+ loadDataFromUrl(null, function() { console.log('finished'); });
2893
+ loadDataFromUrl(node1, function() { console.log('finished'); });
2894
+ */
2895
+ loadDataFromUrl(param1, param2, param3) {
2896
+ if (typeof param1 === "string") {
2897
+ // first parameter is url
2898
+ this.doLoadDataFromUrl(param1, param2, param3 ?? null);
3212
2899
  } else {
3213
- return false;
2900
+ // first parameter is not url
2901
+ this.doLoadDataFromUrl(null, param1, param2);
3214
2902
  }
2903
+ return this.element;
3215
2904
  }
3216
- openNodeInternal(node) {
3217
- let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
3218
- let onFinished = arguments.length > 2 ? arguments[2] : undefined;
3219
- const doOpenNode = (_node, _slide, _onFinished) => {
3220
- const folderElement = this.createFolderElement(_node);
3221
- folderElement.open(_onFinished, _slide, this.options.animationSpeed);
3222
- };
3223
- if (node.isFolder() || node.isEmptyFolder) {
3224
- if (node.load_on_demand) {
3225
- this.loadFolderOnDemand(node, slide, onFinished);
3226
- } else {
3227
- let parent = node.parent;
3228
- while (parent) {
3229
- // nb: do not open root element
3230
- if (parent.parent) {
3231
- doOpenNode(parent, false);
3232
- }
3233
- parent = parent.parent;
3234
- }
3235
- doOpenNode(node, slide, onFinished);
3236
- this.saveState();
3237
- }
2905
+ moveDown() {
2906
+ const selectedNode = this.getSelectedNode();
2907
+ if (selectedNode) {
2908
+ this.keyHandler.moveDown(selectedNode);
3238
2909
  }
2910
+ return this.element;
3239
2911
  }
3240
- openParents(node) {
3241
- const parent = node.parent;
3242
- if (parent?.parent && !parent.is_open) {
3243
- this.openNode(parent, false);
2912
+ moveNode(node, targetNode, position) {
2913
+ if (!node) {
2914
+ throw Error(NODE_PARAM_IS_EMPTY);
3244
2915
  }
3245
- }
3246
-
3247
- /*
3248
- Redraw the tree or part of the tree.
3249
- from_node: redraw this subtree
3250
- */
3251
- refreshElements(fromNode) {
3252
- const mustSetFocus = this.isFocusOnTree();
3253
- const mustSelect = fromNode ? this.isSelectedNodeInSubtree(fromNode) : false;
3254
- this.renderer.render(fromNode);
3255
- if (mustSelect) {
3256
- this.selectCurrentNode(mustSetFocus);
2916
+ if (!targetNode) {
2917
+ throw Error(PARAM_IS_EMPTY + "targetNode");
3257
2918
  }
3258
- this.triggerEvent("tree.refresh");
3259
- }
3260
- saveState() {
3261
- if (this.options.saveState) {
3262
- this.saveStateHandler.saveState();
2919
+ if (!position) {
2920
+ throw Error(PARAM_IS_EMPTY + "position");
2921
+ }
2922
+ const positionIndex = getPosition(position);
2923
+ if (positionIndex !== undefined) {
2924
+ this.tree.moveNode(node, targetNode, positionIndex);
2925
+ this.refreshElements(null);
3263
2926
  }
2927
+ return this.element;
3264
2928
  }
3265
- selectCurrentNode(mustSetFocus) {
3266
- const node = this.getSelectedNode();
3267
- if (node) {
3268
- const nodeElement = this.getNodeElementForNode(node);
3269
- nodeElement.select(mustSetFocus);
2929
+ moveUp() {
2930
+ const selectedNode = this.getSelectedNode();
2931
+ if (selectedNode) {
2932
+ this.keyHandler.moveUp(selectedNode);
3270
2933
  }
2934
+ return this.element;
3271
2935
  }
3272
-
3273
- // Set initial state, either by restoring the state or auto-opening nodes
3274
- // result: must load nodes on demand?
3275
- setInitialState() {
3276
- const restoreState = () => {
3277
- // result: is state restored, must load on demand?
3278
- if (!this.options.saveState) {
3279
- return [false, false];
2936
+ openNode(node, param1, param2) {
2937
+ if (!node) {
2938
+ throw Error(NODE_PARAM_IS_EMPTY);
2939
+ }
2940
+ const parseParams = () => {
2941
+ let onFinished;
2942
+ let slide;
2943
+ if (isFunction(param1)) {
2944
+ onFinished = param1;
2945
+ slide = null;
3280
2946
  } else {
3281
- const state = this.saveStateHandler.getStateFromStorage();
3282
- if (!state) {
3283
- return [false, false];
3284
- } else {
3285
- const mustLoadOnDemand = this.saveStateHandler.setInitialState(state);
3286
-
3287
- // return true: the state is restored
3288
- return [true, mustLoadOnDemand];
3289
- }
2947
+ slide = param1;
2948
+ onFinished = param2;
3290
2949
  }
3291
- };
3292
- const autoOpenNodes = () => {
3293
- // result: must load on demand?
3294
- if (this.options.autoOpen === false) {
3295
- return false;
2950
+ if (slide == null) {
2951
+ slide = this.options.slide;
3296
2952
  }
3297
- const maxLevel = this.getAutoOpenMaxLevel();
3298
- let mustLoadOnDemand = false;
3299
- this.tree.iterate((node, level) => {
3300
- if (node.load_on_demand) {
3301
- mustLoadOnDemand = true;
3302
- return false;
3303
- } else if (!node.hasChildren()) {
3304
- return false;
3305
- } else {
3306
- node.is_open = true;
3307
- return level !== maxLevel;
3308
- }
3309
- });
3310
- return mustLoadOnDemand;
2953
+ return [slide, onFinished];
3311
2954
  };
3312
- let [isRestored, mustLoadOnDemand] = restoreState(); // eslint-disable-line prefer-const
3313
-
3314
- if (!isRestored) {
3315
- mustLoadOnDemand = autoOpenNodes();
2955
+ const [slide, onFinished] = parseParams();
2956
+ this.openNodeInternal(node, slide, onFinished);
2957
+ return this.element;
2958
+ }
2959
+ prependNode(newNodeInfo, parentNodeParam) {
2960
+ const parentNode = parentNodeParam ?? this.tree;
2961
+ const node = parentNode.prepend(newNodeInfo);
2962
+ this.refreshElements(parentNode);
2963
+ return node;
2964
+ }
2965
+ refresh() {
2966
+ this.refreshElements(null);
2967
+ return this.element;
2968
+ }
2969
+ refreshHitAreas() {
2970
+ this.dndHandler.refresh();
2971
+ return this.element;
2972
+ }
2973
+ reload(onFinished) {
2974
+ this.doLoadDataFromUrl(null, null, onFinished);
2975
+ return this.element;
2976
+ }
2977
+ removeFromSelection(node) {
2978
+ if (!node) {
2979
+ throw Error(NODE_PARAM_IS_EMPTY);
3316
2980
  }
3317
- return mustLoadOnDemand;
2981
+ this.selectNodeHandler.removeFromSelection(node);
2982
+ this.getNodeElementForNode(node).deselect();
2983
+ this.saveState();
2984
+ return this.element;
3318
2985
  }
2986
+ removeNode(node) {
2987
+ if (!node) {
2988
+ throw Error(NODE_PARAM_IS_EMPTY);
2989
+ }
2990
+ if (!node.parent) {
2991
+ throw Error("Node has no parent");
2992
+ }
2993
+ this.selectNodeHandler.removeFromSelection(node, true); // including children
3319
2994
 
3320
- // Set the initial state for nodes that are loaded on demand
3321
- // Call cb_finished when done
3322
- setInitialStateOnDemand(cbFinished) {
3323
- const restoreState = () => {
3324
- if (!this.options.saveState) {
3325
- return false;
3326
- } else {
3327
- const state = this.saveStateHandler.getStateFromStorage();
3328
- if (!state) {
3329
- return false;
3330
- } else {
3331
- this.saveStateHandler.setInitialStateOnDemand(state, cbFinished);
3332
- return true;
3333
- }
3334
- }
3335
- };
3336
- const autoOpenNodes = () => {
3337
- const maxLevel = this.getAutoOpenMaxLevel();
3338
- let loadingCount = 0;
3339
- const loadAndOpenNode = node => {
3340
- loadingCount += 1;
3341
- this.openNodeInternal(node, false, () => {
3342
- loadingCount -= 1;
3343
- openNodes();
3344
- });
3345
- };
3346
- const openNodes = () => {
3347
- this.tree.iterate((node, level) => {
3348
- if (node.load_on_demand) {
3349
- if (!node.is_loading) {
3350
- loadAndOpenNode(node);
3351
- }
3352
- return false;
3353
- } else {
3354
- this.openNodeInternal(node, false);
3355
- return level !== maxLevel;
3356
- }
3357
- });
3358
- if (loadingCount === 0) {
3359
- cbFinished();
3360
- }
3361
- };
3362
- openNodes();
3363
- };
3364
- if (!restoreState()) {
3365
- autoOpenNodes();
3366
- }
3367
- }
3368
- triggerEvent(eventName, values) {
3369
- const event = jQuery.Event(eventName, values);
3370
- this.element.trigger(event);
3371
- return event;
3372
- }
3373
- addNodeAfter(newNodeInfo, existingNode) {
3374
- const newNode = existingNode.addAfter(newNodeInfo);
3375
- if (newNode) {
3376
- this.refreshElements(existingNode.parent);
3377
- }
3378
- return newNode;
2995
+ const parent = node.parent;
2996
+ node.remove();
2997
+ this.refreshElements(parent);
2998
+ return this.element;
3379
2999
  }
3380
- addNodeBefore(newNodeInfo, existingNode) {
3381
- if (!existingNode) {
3382
- throw Error(PARAM_IS_EMPTY + "existingNode");
3000
+ scrollToNode(node) {
3001
+ if (!node) {
3002
+ throw Error(NODE_PARAM_IS_EMPTY);
3383
3003
  }
3384
- const newNode = existingNode.addBefore(newNodeInfo);
3385
- if (newNode) {
3386
- this.refreshElements(existingNode.parent);
3004
+ if (!node.element) {
3005
+ return this.element;
3387
3006
  }
3388
- return newNode;
3007
+ const top = getOffsetTop(node.element) - getOffsetTop(this.$el.get(0));
3008
+ this.scrollHandler.scrollToY(top);
3009
+ return this.element;
3389
3010
  }
3390
- addParentNode(newNodeInfo, existingNode) {
3391
- if (!existingNode) {
3392
- throw Error(PARAM_IS_EMPTY + "existingNode");
3393
- }
3394
- const newNode = existingNode.addParent(newNodeInfo);
3395
- if (newNode) {
3396
- this.refreshElements(newNode.parent);
3011
+ selectNode(node, optionsParam) {
3012
+ this.doSelectNode(node, optionsParam);
3013
+ return this.element;
3014
+ }
3015
+ setOption(option, value) {
3016
+ this.options[option] = value;
3017
+ return this.element;
3018
+ }
3019
+ setState(state) {
3020
+ if (state) {
3021
+ this.saveStateHandler.setInitialState(state);
3022
+ this.refreshElements(null);
3397
3023
  }
3398
- return newNode;
3024
+ return this.element;
3399
3025
  }
3400
- addToSelection(node, mustSetFocus) {
3026
+ toggle(node) {
3027
+ let slideParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
3401
3028
  if (!node) {
3402
3029
  throw Error(NODE_PARAM_IS_EMPTY);
3403
3030
  }
3404
- this.selectNodeHandler.addToSelection(node);
3405
- this.openParents(node);
3406
- this.getNodeElementForNode(node).select(mustSetFocus ?? true);
3407
- this.saveState();
3031
+ const slide = slideParam ?? this.options.slide;
3032
+ if (node.is_open) {
3033
+ this.closeNode(node, slide);
3034
+ } else {
3035
+ this.openNode(node, slide);
3036
+ }
3408
3037
  return this.element;
3409
3038
  }
3410
- appendNode(newNodeInfo, parentNodeParam) {
3411
- const parentNode = parentNodeParam ?? this.tree;
3412
- const node = parentNode.append(newNodeInfo);
3413
- this.refreshElements(parentNode);
3414
- return node;
3039
+ toJson() {
3040
+ return JSON.stringify(this.tree.getData());
3415
3041
  }
3416
- closeNode(node, slideParam) {
3042
+ updateNode(node, data) {
3417
3043
  if (!node) {
3418
3044
  throw Error(NODE_PARAM_IS_EMPTY);
3419
3045
  }
3420
- const slide = slideParam ?? this.options.slide;
3421
- if (node.isFolder() || node.isEmptyFolder) {
3422
- this.createFolderElement(node).close(slide, this.options.animationSpeed);
3423
- this.saveState();
3046
+ if (!data) {
3047
+ return this.element;
3048
+ }
3049
+ const idIsChanged = typeof data === "object" && data.id && data.id !== node.id;
3050
+ if (idIsChanged) {
3051
+ this.tree.removeNodeFromIndex(node);
3424
3052
  }
3053
+ node.setData(data);
3054
+ if (idIsChanged) {
3055
+ this.tree.addNodeToIndex(node);
3056
+ }
3057
+ if (typeof data === "object" && data.children && data.children instanceof Array) {
3058
+ node.removeChildren();
3059
+ if (data.children.length) {
3060
+ node.loadFromData(data.children);
3061
+ }
3062
+ }
3063
+ this.refreshElements(node);
3425
3064
  return this.element;
3426
3065
  }
3427
- deinit() {
3428
- this.element.empty();
3429
- this.element.off();
3430
- this.keyHandler.deinit();
3431
- this.mouseHandler.deinit();
3432
- this.tree = new Node({}, true);
3433
- super.deinit();
3066
+ connectHandlers() {
3067
+ const {
3068
+ autoEscape,
3069
+ buttonLeft,
3070
+ closedIcon,
3071
+ dataFilter,
3072
+ dragAndDrop,
3073
+ keyboardSupport,
3074
+ onCanMove,
3075
+ onCanMoveTo,
3076
+ onCreateLi,
3077
+ onDragMove,
3078
+ onDragStop,
3079
+ onGetStateFromStorage,
3080
+ onIsMoveHandle,
3081
+ onLoadFailed,
3082
+ onLoading,
3083
+ onSetStateFromStorage,
3084
+ openedIcon,
3085
+ openFolderDelay,
3086
+ rtl,
3087
+ saveState,
3088
+ showEmptyFolder,
3089
+ slide,
3090
+ tabIndex
3091
+ } = this.options;
3092
+ const closeNode = this.closeNode.bind(this);
3093
+ const getNodeElement = this.getNodeElement.bind(this);
3094
+ const getNodeElementForNode = this.getNodeElementForNode.bind(this);
3095
+ const getNodeById = this.getNodeById.bind(this);
3096
+ const getSelectedNode = this.getSelectedNode.bind(this);
3097
+ const getTree = this.getTree.bind(this);
3098
+ const isFocusOnTree = this.isFocusOnTree.bind(this);
3099
+ const loadData = this.loadData.bind(this);
3100
+ const openNode = this.openNodeInternal.bind(this);
3101
+ const refreshElements = this.refreshElements.bind(this);
3102
+ const refreshHitAreas = this.refreshHitAreas.bind(this);
3103
+ const selectNode = this.selectNode.bind(this);
3104
+ const $treeElement = this.element;
3105
+ const treeElement = this.element.get(0);
3106
+ const triggerEvent = this.triggerEvent.bind(this);
3107
+ const selectNodeHandler = new SelectNodeHandler({
3108
+ getNodeById
3109
+ });
3110
+ const addToSelection = selectNodeHandler.addToSelection.bind(selectNodeHandler);
3111
+ const getSelectedNodes = selectNodeHandler.getSelectedNodes.bind(selectNodeHandler);
3112
+ const isNodeSelected = selectNodeHandler.isNodeSelected.bind(selectNodeHandler);
3113
+ const removeFromSelection = selectNodeHandler.removeFromSelection.bind(selectNodeHandler);
3114
+ const getMouseDelay = () => this.options.startDndDelay ?? 0;
3115
+ const dataLoader = new DataLoader({
3116
+ dataFilter,
3117
+ loadData,
3118
+ onLoadFailed,
3119
+ onLoading,
3120
+ treeElement,
3121
+ triggerEvent
3122
+ });
3123
+ const saveStateHandler = new SaveStateHandler({
3124
+ addToSelection,
3125
+ getNodeById,
3126
+ getSelectedNodes,
3127
+ getTree,
3128
+ onGetStateFromStorage,
3129
+ onSetStateFromStorage,
3130
+ openNode,
3131
+ refreshElements,
3132
+ removeFromSelection,
3133
+ saveState
3134
+ });
3135
+ const scrollHandler = new ScrollHandler({
3136
+ refreshHitAreas,
3137
+ treeElement
3138
+ });
3139
+ const getScrollLeft = scrollHandler.getScrollLeft.bind(scrollHandler);
3140
+ const dndHandler = new DragAndDropHandler({
3141
+ autoEscape,
3142
+ getNodeElement,
3143
+ getNodeElementForNode,
3144
+ getScrollLeft,
3145
+ getTree,
3146
+ onCanMove,
3147
+ onCanMoveTo,
3148
+ onDragMove,
3149
+ onDragStop,
3150
+ onIsMoveHandle,
3151
+ openFolderDelay,
3152
+ openNode,
3153
+ refreshElements,
3154
+ slide,
3155
+ treeElement,
3156
+ triggerEvent
3157
+ });
3158
+ const keyHandler = new KeyHandler({
3159
+ closeNode,
3160
+ getSelectedNode,
3161
+ isFocusOnTree,
3162
+ keyboardSupport,
3163
+ openNode,
3164
+ selectNode
3165
+ });
3166
+ const renderer = new ElementsRenderer({
3167
+ $element: $treeElement,
3168
+ autoEscape,
3169
+ buttonLeft,
3170
+ closedIcon,
3171
+ dragAndDrop,
3172
+ getTree,
3173
+ isNodeSelected,
3174
+ onCreateLi,
3175
+ openedIcon,
3176
+ rtl,
3177
+ showEmptyFolder,
3178
+ tabIndex
3179
+ });
3180
+ const getNode = this.getNode.bind(this);
3181
+ const onMouseCapture = this.mouseCapture.bind(this);
3182
+ const onMouseDrag = this.mouseDrag.bind(this);
3183
+ const onMouseStart = this.mouseStart.bind(this);
3184
+ const onMouseStop = this.mouseStop.bind(this);
3185
+ const mouseHandler = new MouseHandler({
3186
+ element: treeElement,
3187
+ getMouseDelay,
3188
+ getNode,
3189
+ onClickButton: this.toggle.bind(this),
3190
+ onClickTitle: this.doSelectNode.bind(this),
3191
+ onMouseCapture,
3192
+ onMouseDrag,
3193
+ onMouseStart,
3194
+ onMouseStop,
3195
+ triggerEvent,
3196
+ useContextMenu: this.options.useContextMenu
3197
+ });
3198
+ this.dataLoader = dataLoader;
3199
+ this.dndHandler = dndHandler;
3200
+ this.keyHandler = keyHandler;
3201
+ this.mouseHandler = mouseHandler;
3202
+ this.renderer = renderer;
3203
+ this.saveStateHandler = saveStateHandler;
3204
+ this.scrollHandler = scrollHandler;
3205
+ this.selectNodeHandler = selectNodeHandler;
3206
+ }
3207
+ containsElement(element) {
3208
+ const node = this.getNode(element);
3209
+ return node != null && node.tree === this.tree;
3210
+ }
3211
+ createFolderElement(node) {
3212
+ const closedIconElement = this.renderer.closedIconElement;
3213
+ const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
3214
+ const openedIconElement = this.renderer.openedIconElement;
3215
+ const tabIndex = this.options.tabIndex;
3216
+ const treeElement = this.element.get(0);
3217
+ const triggerEvent = this.triggerEvent.bind(this);
3218
+ return new FolderElement({
3219
+ closedIconElement,
3220
+ getScrollLeft,
3221
+ node,
3222
+ openedIconElement,
3223
+ tabIndex,
3224
+ treeElement,
3225
+ triggerEvent
3226
+ });
3227
+ }
3228
+ createNodeElement(node) {
3229
+ const getScrollLeft = this.scrollHandler.getScrollLeft.bind(this.scrollHandler);
3230
+ const tabIndex = this.options.tabIndex;
3231
+ const treeElement = this.element.get(0);
3232
+ return new NodeElement({
3233
+ getScrollLeft,
3234
+ node,
3235
+ tabIndex,
3236
+ treeElement
3237
+ });
3238
+ }
3239
+ deselectCurrentNode() {
3240
+ const node = this.getSelectedNode();
3241
+ if (node) {
3242
+ this.removeFromSelection(node);
3243
+ }
3244
+ }
3245
+ deselectNodes(parentNode) {
3246
+ const selectedNodesUnderParent = this.selectNodeHandler.getSelectedNodesUnder(parentNode);
3247
+ for (const n of selectedNodesUnderParent) {
3248
+ this.selectNodeHandler.removeFromSelection(n);
3249
+ }
3250
+ }
3251
+ doLoadData(data, parentNode) {
3252
+ if (data) {
3253
+ if (parentNode) {
3254
+ this.deselectNodes(parentNode);
3255
+ this.loadSubtree(data, parentNode);
3256
+ } else {
3257
+ this.initTree(data);
3258
+ }
3259
+ if (this.isDragging()) {
3260
+ this.dndHandler.refresh();
3261
+ }
3262
+ }
3263
+ this.triggerEvent("tree.load_data", {
3264
+ parent_node: parentNode,
3265
+ tree_data: data
3266
+ });
3267
+ }
3268
+ doLoadDataFromUrl(urlInfoParam, parentNode, onFinished) {
3269
+ const urlInfo = urlInfoParam ?? this.getDataUrlInfo(parentNode);
3270
+ this.dataLoader.loadFromUrl(urlInfo, parentNode, onFinished);
3271
+ }
3272
+ doSelectNode(node, optionsParam) {
3273
+ const saveState = () => {
3274
+ if (this.options.saveState) {
3275
+ this.saveStateHandler.saveState();
3276
+ }
3277
+ };
3278
+ if (!node) {
3279
+ // Called with empty node -> deselect current node
3280
+ this.deselectCurrentNode();
3281
+ saveState();
3282
+ return;
3283
+ }
3284
+ const defaultOptions = {
3285
+ mustSetFocus: true,
3286
+ mustToggle: true
3287
+ };
3288
+ const selectOptions = {
3289
+ ...defaultOptions,
3290
+ ...(optionsParam ?? {})
3291
+ };
3292
+ const canSelect = () => {
3293
+ if (this.options.onCanSelectNode) {
3294
+ return this.options.selectable && this.options.onCanSelectNode(node);
3295
+ } else {
3296
+ return this.options.selectable;
3297
+ }
3298
+ };
3299
+ if (!canSelect()) {
3300
+ return;
3301
+ }
3302
+ if (this.selectNodeHandler.isNodeSelected(node)) {
3303
+ if (selectOptions.mustToggle) {
3304
+ this.deselectCurrentNode();
3305
+ this.triggerEvent("tree.select", {
3306
+ node: null,
3307
+ previous_node: node
3308
+ });
3309
+ }
3310
+ } else {
3311
+ const deselectedNode = this.getSelectedNode() || null;
3312
+ this.deselectCurrentNode();
3313
+ this.addToSelection(node, selectOptions.mustSetFocus);
3314
+ this.triggerEvent("tree.select", {
3315
+ deselected_node: deselectedNode,
3316
+ node
3317
+ });
3318
+ this.openParents(node);
3319
+ }
3320
+ saveState();
3434
3321
  }
3435
- getNodeByCallback(callback) {
3436
- return this.tree.getNodeByCallback(callback);
3322
+ getAutoOpenMaxLevel() {
3323
+ if (this.options.autoOpen === true) {
3324
+ return -1;
3325
+ } else if (typeof this.options.autoOpen === "number") {
3326
+ return this.options.autoOpen;
3327
+ } else if (typeof this.options.autoOpen === "string") {
3328
+ return parseInt(this.options.autoOpen, 10);
3329
+ } else {
3330
+ return 0;
3331
+ }
3437
3332
  }
3438
- getNodeByHtmlElement(inputElement) {
3439
- const element = inputElement instanceof HTMLElement ? inputElement : inputElement[0];
3440
- if (!element) {
3333
+ getDataUrlInfo(node) {
3334
+ const dataUrl = this.options.dataUrl ?? this.element.data("url");
3335
+ const getUrlFromString = url => {
3336
+ const urlInfo = {
3337
+ url
3338
+ };
3339
+ setUrlInfoData(urlInfo);
3340
+ return urlInfo;
3341
+ };
3342
+ const setUrlInfoData = urlInfo => {
3343
+ if (node?.id) {
3344
+ // Load on demand of a subtree; add node parameter
3345
+ const data = {
3346
+ node: node.id
3347
+ };
3348
+ urlInfo.data = data;
3349
+ } else {
3350
+ // Add selected_node parameter
3351
+ const selectedNodeId = this.getNodeIdToBeSelected();
3352
+ if (selectedNodeId) {
3353
+ const data = {
3354
+ selected_node: selectedNodeId
3355
+ };
3356
+ urlInfo.data = data;
3357
+ }
3358
+ }
3359
+ };
3360
+ if (typeof dataUrl === "function") {
3361
+ return dataUrl(node);
3362
+ } else if (typeof dataUrl === "string") {
3363
+ return getUrlFromString(dataUrl);
3364
+ } else if (dataUrl && typeof dataUrl === "object") {
3365
+ setUrlInfoData(dataUrl);
3366
+ return dataUrl;
3367
+ } else {
3441
3368
  return null;
3442
3369
  }
3443
- return this.getNode(element);
3444
- }
3445
- getNodeById(nodeId) {
3446
- return this.tree.getNodeById(nodeId);
3447
- }
3448
- getNodeByName(name) {
3449
- return this.tree.getNodeByName(name);
3450
- }
3451
- getNodeByNameMustExist(name) {
3452
- return this.tree.getNodeByNameMustExist(name);
3453
- }
3454
- getNodesByProperty(key, value) {
3455
- return this.tree.getNodesByProperty(key, value);
3456
- }
3457
- getSelectedNode() {
3458
- return this.selectNodeHandler.getSelectedNode();
3459
- }
3460
- getSelectedNodes() {
3461
- return this.selectNodeHandler.getSelectedNodes();
3462
- }
3463
- getState() {
3464
- return this.saveStateHandler.getState();
3465
- }
3466
- getStateFromStorage() {
3467
- return this.saveStateHandler.getStateFromStorage();
3468
- }
3469
- getTree() {
3470
- return this.tree;
3471
- }
3472
- getVersion() {
3473
- return version;
3474
3370
  }
3475
- init() {
3476
- super.init();
3477
- this.element = this.$el;
3478
- this.isInitialized = false;
3479
- this.options.rtl = this.getRtlOption();
3480
- if (this.options.closedIcon == null) {
3481
- this.options.closedIcon = this.getDefaultClosedIcon();
3371
+ getDefaultClosedIcon() {
3372
+ if (this.options.rtl) {
3373
+ // triangle to the left
3374
+ return "&#x25c0;";
3375
+ } else {
3376
+ // triangle to the right
3377
+ return "&#x25ba;";
3482
3378
  }
3483
- this.connectHandlers();
3484
- this.initData();
3485
- }
3486
- isDragging() {
3487
- return this.dndHandler.isDragging;
3488
3379
  }
3489
- isNodeSelected(node) {
3490
- if (!node) {
3491
- throw Error(NODE_PARAM_IS_EMPTY);
3380
+ getNode(element) {
3381
+ const liElement = element.closest("li.jqtree_common");
3382
+ if (liElement) {
3383
+ return jQuery(liElement).data("node");
3384
+ } else {
3385
+ return null;
3492
3386
  }
3493
- return this.selectNodeHandler.isNodeSelected(node);
3494
- }
3495
- loadData(data, parentNode) {
3496
- this.doLoadData(data, parentNode);
3497
- return this.element;
3498
3387
  }
3499
-
3500
- /*
3501
- signatures:
3502
- - loadDataFromUrl(url, parent_node=null, on_finished=null)
3503
- loadDataFromUrl('/my_data');
3504
- loadDataFromUrl('/my_data', node1);
3505
- loadDataFromUrl('/my_data', node1, function() { console.log('finished'); });
3506
- loadDataFromUrl('/my_data', null, function() { console.log('finished'); });
3507
- - loadDataFromUrl(parent_node=null, on_finished=null)
3508
- loadDataFromUrl();
3509
- loadDataFromUrl(node1);
3510
- loadDataFromUrl(null, function() { console.log('finished'); });
3511
- loadDataFromUrl(node1, function() { console.log('finished'); });
3512
- */
3513
- loadDataFromUrl(param1, param2, param3) {
3514
- if (typeof param1 === "string") {
3515
- // first parameter is url
3516
- this.doLoadDataFromUrl(param1, param2, param3 ?? null);
3388
+ getNodeElement(element) {
3389
+ const node = this.getNode(element);
3390
+ if (node) {
3391
+ return this.getNodeElementForNode(node);
3517
3392
  } else {
3518
- // first parameter is not url
3519
- this.doLoadDataFromUrl(null, param1, param2);
3393
+ return null;
3520
3394
  }
3521
- return this.element;
3522
3395
  }
3523
- moveDown() {
3524
- const selectedNode = this.getSelectedNode();
3525
- if (selectedNode) {
3526
- this.keyHandler.moveDown(selectedNode);
3396
+ getNodeElementForNode(node) {
3397
+ if (node.isFolder()) {
3398
+ return this.createFolderElement(node);
3399
+ } else {
3400
+ return this.createNodeElement(node);
3527
3401
  }
3528
- return this.element;
3529
3402
  }
3530
- moveNode(node, targetNode, position) {
3531
- if (!node) {
3532
- throw Error(NODE_PARAM_IS_EMPTY);
3533
- }
3534
- if (!targetNode) {
3535
- throw Error(PARAM_IS_EMPTY + "targetNode");
3536
- }
3537
- if (!position) {
3538
- throw Error(PARAM_IS_EMPTY + "position");
3539
- }
3540
- const positionIndex = getPosition(position);
3541
- if (positionIndex !== undefined) {
3542
- this.tree.moveNode(node, targetNode, positionIndex);
3543
- this.refreshElements(null);
3403
+ getNodeIdToBeSelected() {
3404
+ if (this.options.saveState) {
3405
+ return this.saveStateHandler.getNodeIdToBeSelected();
3406
+ } else {
3407
+ return null;
3544
3408
  }
3545
- return this.element;
3546
3409
  }
3547
- moveUp() {
3548
- const selectedNode = this.getSelectedNode();
3549
- if (selectedNode) {
3550
- this.keyHandler.moveUp(selectedNode);
3410
+ getRtlOption() {
3411
+ if (this.options.rtl != null) {
3412
+ return this.options.rtl;
3413
+ } else {
3414
+ const dataRtl = this.element.data("rtl");
3415
+ if (dataRtl !== null && dataRtl !== false && dataRtl !== undefined) {
3416
+ return true;
3417
+ } else {
3418
+ return false;
3419
+ }
3551
3420
  }
3552
- return this.element;
3553
3421
  }
3554
- openNode(node, param1, param2) {
3555
- if (!node) {
3556
- throw Error(NODE_PARAM_IS_EMPTY);
3557
- }
3558
- const parseParams = () => {
3559
- let onFinished;
3560
- let slide;
3561
- if (isFunction(param1)) {
3562
- onFinished = param1;
3563
- slide = null;
3422
+ initData() {
3423
+ if (this.options.data) {
3424
+ this.doLoadData(this.options.data, null);
3425
+ } else {
3426
+ const dataUrl = this.getDataUrlInfo(null);
3427
+ if (dataUrl) {
3428
+ this.doLoadDataFromUrl(null, null, null);
3564
3429
  } else {
3565
- slide = param1;
3566
- onFinished = param2;
3430
+ this.doLoadData([], null);
3567
3431
  }
3568
- if (slide == null) {
3569
- slide = this.options.slide;
3432
+ }
3433
+ }
3434
+ initTree(data) {
3435
+ const doInit = () => {
3436
+ if (!this.isInitialized) {
3437
+ this.isInitialized = true;
3438
+ this.triggerEvent("tree.init");
3570
3439
  }
3571
- return [slide, onFinished];
3572
3440
  };
3573
- const [slide, onFinished] = parseParams();
3574
- this.openNodeInternal(node, slide, onFinished);
3575
- return this.element;
3576
- }
3577
- prependNode(newNodeInfo, parentNodeParam) {
3578
- const parentNode = parentNodeParam ?? this.tree;
3579
- const node = parentNode.prepend(newNodeInfo);
3580
- this.refreshElements(parentNode);
3581
- return node;
3582
- }
3583
- refresh() {
3441
+ this.tree = new this.options.nodeClass(null, true, this.options.nodeClass);
3442
+ this.selectNodeHandler.clear();
3443
+ this.tree.loadFromData(data);
3444
+ const mustLoadOnDemand = this.setInitialState();
3584
3445
  this.refreshElements(null);
3585
- return this.element;
3586
- }
3587
- refreshHitAreas() {
3588
- this.dndHandler.refresh();
3589
- return this.element;
3590
- }
3591
- reload(onFinished) {
3592
- this.doLoadDataFromUrl(null, null, onFinished);
3593
- return this.element;
3594
- }
3595
- removeFromSelection(node) {
3596
- if (!node) {
3597
- throw Error(NODE_PARAM_IS_EMPTY);
3598
- }
3599
- this.selectNodeHandler.removeFromSelection(node);
3600
- this.getNodeElementForNode(node).deselect();
3601
- this.saveState();
3602
- return this.element;
3603
- }
3604
- removeNode(node) {
3605
- if (!node) {
3606
- throw Error(NODE_PARAM_IS_EMPTY);
3607
- }
3608
- if (!node.parent) {
3609
- throw Error("Node has no parent");
3446
+ if (!mustLoadOnDemand) {
3447
+ doInit();
3448
+ } else {
3449
+ // Load data on demand and then init the tree
3450
+ this.setInitialStateOnDemand(doInit);
3610
3451
  }
3611
- this.selectNodeHandler.removeFromSelection(node, true); // including children
3612
-
3613
- const parent = node.parent;
3614
- node.remove();
3615
- this.refreshElements(parent);
3616
- return this.element;
3617
3452
  }
3618
- scrollToNode(node) {
3619
- if (!node) {
3620
- throw Error(NODE_PARAM_IS_EMPTY);
3621
- }
3622
- if (!node.element) {
3623
- return this.element;
3453
+ isFocusOnTree() {
3454
+ const activeElement = document.activeElement;
3455
+ return Boolean(activeElement && activeElement.tagName === "SPAN" && this.containsElement(activeElement));
3456
+ }
3457
+ isSelectedNodeInSubtree(subtree) {
3458
+ const selectedNode = this.getSelectedNode();
3459
+ if (!selectedNode) {
3460
+ return false;
3461
+ } else {
3462
+ return subtree === selectedNode || subtree.isParentOf(selectedNode);
3624
3463
  }
3625
- const top = getOffsetTop(node.element) - getOffsetTop(this.$el.get(0));
3626
- this.scrollHandler.scrollToY(top);
3627
- return this.element;
3628
3464
  }
3629
- selectNode(node, optionsParam) {
3630
- this.doSelectNode(node, optionsParam);
3631
- return this.element;
3465
+ loadFolderOnDemand(node) {
3466
+ let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
3467
+ let onFinished = arguments.length > 2 ? arguments[2] : undefined;
3468
+ node.is_loading = true;
3469
+ this.doLoadDataFromUrl(null, node, () => {
3470
+ this.openNodeInternal(node, slide, onFinished);
3471
+ });
3632
3472
  }
3633
- setOption(option, value) {
3634
- this.options[option] = value;
3635
- return this.element;
3473
+ loadSubtree(data, parentNode) {
3474
+ parentNode.loadFromData(data);
3475
+ parentNode.load_on_demand = false;
3476
+ parentNode.is_loading = false;
3477
+ this.refreshElements(parentNode);
3636
3478
  }
3637
- setState(state) {
3638
- if (state) {
3639
- this.saveStateHandler.setInitialState(state);
3640
- this.refreshElements(null);
3479
+ mouseCapture(positionInfo) {
3480
+ if (this.options.dragAndDrop) {
3481
+ return this.dndHandler.mouseCapture(positionInfo);
3482
+ } else {
3483
+ return false;
3641
3484
  }
3642
- return this.element;
3643
3485
  }
3644
- toggle(node) {
3645
- let slideParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
3646
- if (!node) {
3647
- throw Error(NODE_PARAM_IS_EMPTY);
3486
+ mouseDrag(positionInfo) {
3487
+ if (this.options.dragAndDrop) {
3488
+ const result = this.dndHandler.mouseDrag(positionInfo);
3489
+ this.scrollHandler.checkScrolling(positionInfo);
3490
+ return result;
3491
+ } else {
3492
+ return false;
3648
3493
  }
3649
- const slide = slideParam ?? this.options.slide;
3650
- if (node.is_open) {
3651
- this.closeNode(node, slide);
3494
+ }
3495
+ mouseStart(positionInfo) {
3496
+ if (this.options.dragAndDrop) {
3497
+ return this.dndHandler.mouseStart(positionInfo);
3652
3498
  } else {
3653
- this.openNode(node, slide);
3499
+ return false;
3654
3500
  }
3655
- return this.element;
3656
3501
  }
3657
- toJson() {
3658
- return JSON.stringify(this.tree.getData());
3502
+ mouseStop(positionInfo) {
3503
+ if (this.options.dragAndDrop) {
3504
+ this.scrollHandler.stopScrolling();
3505
+ return this.dndHandler.mouseStop(positionInfo);
3506
+ } else {
3507
+ return false;
3508
+ }
3659
3509
  }
3660
- updateNode(node, data) {
3661
- if (!node) {
3662
- throw Error(NODE_PARAM_IS_EMPTY);
3510
+ openNodeInternal(node) {
3511
+ let slide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
3512
+ let onFinished = arguments.length > 2 ? arguments[2] : undefined;
3513
+ const doOpenNode = (_node, _slide, _onFinished) => {
3514
+ if (!node.children.length) {
3515
+ return;
3516
+ }
3517
+ const folderElement = this.createFolderElement(_node);
3518
+ folderElement.open(_onFinished, _slide, this.options.animationSpeed);
3519
+ };
3520
+ if (node.isFolder() || node.isEmptyFolder) {
3521
+ if (node.load_on_demand) {
3522
+ this.loadFolderOnDemand(node, slide, onFinished);
3523
+ } else {
3524
+ let parent = node.parent;
3525
+ while (parent) {
3526
+ // nb: do not open root element
3527
+ if (parent.parent) {
3528
+ doOpenNode(parent, false);
3529
+ }
3530
+ parent = parent.parent;
3531
+ }
3532
+ doOpenNode(node, slide, onFinished);
3533
+ this.saveState();
3534
+ }
3663
3535
  }
3664
- if (!data) {
3665
- return this.element;
3536
+ }
3537
+ openParents(node) {
3538
+ const parent = node.parent;
3539
+ if (parent?.parent && !parent.is_open) {
3540
+ this.openNode(parent, false);
3666
3541
  }
3667
- const idIsChanged = typeof data === "object" && data.id && data.id !== node.id;
3668
- if (idIsChanged) {
3669
- this.tree.removeNodeFromIndex(node);
3542
+ }
3543
+
3544
+ /*
3545
+ Redraw the tree or part of the tree.
3546
+ from_node: redraw this subtree
3547
+ */
3548
+ refreshElements(fromNode) {
3549
+ const mustSetFocus = this.isFocusOnTree();
3550
+ const mustSelect = fromNode ? this.isSelectedNodeInSubtree(fromNode) : false;
3551
+ this.renderer.render(fromNode);
3552
+ if (mustSelect) {
3553
+ this.selectCurrentNode(mustSetFocus);
3670
3554
  }
3671
- node.setData(data);
3672
- if (idIsChanged) {
3673
- this.tree.addNodeToIndex(node);
3555
+ this.triggerEvent("tree.refresh");
3556
+ }
3557
+ saveState() {
3558
+ if (this.options.saveState) {
3559
+ this.saveStateHandler.saveState();
3674
3560
  }
3675
- if (typeof data === "object" && data.children && data.children instanceof Array) {
3676
- node.removeChildren();
3677
- if (data.children.length) {
3678
- node.loadFromData(data.children);
3561
+ }
3562
+ selectCurrentNode(mustSetFocus) {
3563
+ const node = this.getSelectedNode();
3564
+ if (node) {
3565
+ const nodeElement = this.getNodeElementForNode(node);
3566
+ nodeElement.select(mustSetFocus);
3567
+ }
3568
+ }
3569
+
3570
+ // Set initial state, either by restoring the state or auto-opening nodes
3571
+ // result: must load nodes on demand?
3572
+ setInitialState() {
3573
+ const restoreState = () => {
3574
+ // result: is state restored, must load on demand?
3575
+ if (!this.options.saveState) {
3576
+ return [false, false];
3577
+ } else {
3578
+ const state = this.saveStateHandler.getStateFromStorage();
3579
+ if (!state) {
3580
+ return [false, false];
3581
+ } else {
3582
+ const mustLoadOnDemand = this.saveStateHandler.setInitialState(state);
3583
+
3584
+ // return true: the state is restored
3585
+ return [true, mustLoadOnDemand];
3586
+ }
3587
+ }
3588
+ };
3589
+ const autoOpenNodes = () => {
3590
+ // result: must load on demand?
3591
+ if (this.options.autoOpen === false) {
3592
+ return false;
3593
+ }
3594
+ const maxLevel = this.getAutoOpenMaxLevel();
3595
+ let mustLoadOnDemand = false;
3596
+ this.tree.iterate((node, level) => {
3597
+ if (node.load_on_demand) {
3598
+ mustLoadOnDemand = true;
3599
+ return false;
3600
+ } else if (!node.hasChildren()) {
3601
+ return false;
3602
+ } else {
3603
+ node.is_open = true;
3604
+ return level !== maxLevel;
3605
+ }
3606
+ });
3607
+ return mustLoadOnDemand;
3608
+ };
3609
+ let [isRestored, mustLoadOnDemand] = restoreState(); // eslint-disable-line prefer-const
3610
+
3611
+ if (!isRestored) {
3612
+ mustLoadOnDemand = autoOpenNodes();
3613
+ }
3614
+ return mustLoadOnDemand;
3615
+ }
3616
+
3617
+ // Set the initial state for nodes that are loaded on demand
3618
+ // Call cb_finished when done
3619
+ setInitialStateOnDemand(cbFinished) {
3620
+ const restoreState = () => {
3621
+ if (!this.options.saveState) {
3622
+ return false;
3623
+ } else {
3624
+ const state = this.saveStateHandler.getStateFromStorage();
3625
+ if (!state) {
3626
+ return false;
3627
+ } else {
3628
+ this.saveStateHandler.setInitialStateOnDemand(state, cbFinished);
3629
+ return true;
3630
+ }
3679
3631
  }
3632
+ };
3633
+ const autoOpenNodes = () => {
3634
+ const maxLevel = this.getAutoOpenMaxLevel();
3635
+ let loadingCount = 0;
3636
+ const loadAndOpenNode = node => {
3637
+ loadingCount += 1;
3638
+ this.openNodeInternal(node, false, () => {
3639
+ loadingCount -= 1;
3640
+ openNodes();
3641
+ });
3642
+ };
3643
+ const openNodes = () => {
3644
+ this.tree.iterate((node, level) => {
3645
+ if (node.load_on_demand) {
3646
+ if (!node.is_loading) {
3647
+ loadAndOpenNode(node);
3648
+ }
3649
+ return false;
3650
+ } else {
3651
+ this.openNodeInternal(node, false);
3652
+ return level !== maxLevel;
3653
+ }
3654
+ });
3655
+ if (loadingCount === 0) {
3656
+ cbFinished();
3657
+ }
3658
+ };
3659
+ openNodes();
3660
+ };
3661
+ if (!restoreState()) {
3662
+ autoOpenNodes();
3680
3663
  }
3681
- this.refreshElements(node);
3682
- return this.element;
3664
+ }
3665
+ triggerEvent(eventName, values) {
3666
+ const event = jQuery.Event(eventName, values);
3667
+ this.element.trigger(event);
3668
+ return event;
3683
3669
  }
3684
3670
  }
3685
3671
  SimpleWidget.register(JqTreeWidget, "tree");