jqtree 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.eslintrc +5 -1
  2. package/bower.json +1 -1
  3. package/config/babel.config.json +1 -1
  4. package/config/production +2 -0
  5. package/devserver/devserver_scroll.js +8 -0
  6. package/devserver/test_scroll.html +28 -0
  7. package/devserver/test_scroll_container.html +39 -0
  8. package/docs/_config.yml +1 -1
  9. package/docs/_entries/general/changelog.md +12 -0
  10. package/docs/package.json +1 -1
  11. package/docs/pnpm-lock.yaml +30 -30
  12. package/package.json +31 -27
  13. package/src/dataLoader.ts +44 -19
  14. package/src/dragAndDropHandler/dragElement.ts +42 -0
  15. package/src/dragAndDropHandler/hitAreasGenerator.ts +175 -0
  16. package/src/dragAndDropHandler/index.ts +470 -0
  17. package/src/dragAndDropHandler/types.ts +12 -0
  18. package/src/dragAndDropHandler/visibleNodeIterator.ts +97 -0
  19. package/src/elementsRenderer.ts +75 -40
  20. package/src/jqtreeMethodTypes.ts +40 -0
  21. package/src/jqtreeOptions.ts +43 -25
  22. package/src/keyHandler.ts +59 -38
  23. package/src/mouse.widget.ts +3 -3
  24. package/src/mouseWidgetTypes.ts +6 -0
  25. package/src/node.ts +32 -48
  26. package/src/nodeElement/borderDropHint.ts +32 -0
  27. package/src/nodeElement/folderElement.ts +133 -0
  28. package/src/nodeElement/ghostDropHint.ts +68 -0
  29. package/src/nodeElement/index.ts +101 -0
  30. package/src/nodeUtils.ts +10 -0
  31. package/src/playwright/coverage.ts +1 -4
  32. package/src/playwright/playwright.test.ts +203 -15
  33. package/src/playwright/testUtils.ts +23 -15
  34. package/src/saveStateHandler.ts +75 -26
  35. package/src/scrollHandler/containerScrollParent.ts +177 -0
  36. package/src/scrollHandler/createScrollParent.ts +50 -0
  37. package/src/scrollHandler/documentScrollParent.ts +182 -0
  38. package/src/scrollHandler/types.ts +7 -0
  39. package/src/scrollHandler.ts +36 -248
  40. package/src/selectNodeHandler.ts +10 -16
  41. package/src/test/jqTree/keyboard.test.ts +18 -23
  42. package/src/test/jqTree/loadOnDemand.test.ts +2 -3
  43. package/src/test/jqTree/methods.test.ts +33 -4
  44. package/src/test/jqTree/options.test.ts +15 -4
  45. package/src/test/node.test.ts +85 -26
  46. package/src/test/nodeUtils.test.ts +21 -0
  47. package/src/tree.jquery.ts +262 -83
  48. package/src/util.ts +3 -0
  49. package/src/version.ts +1 -1
  50. package/tree.jquery.debug.js +1922 -2608
  51. package/tree.jquery.debug.js.map +1 -1
  52. package/tree.jquery.js +2 -2
  53. package/tree.jquery.js.map +1 -1
  54. package/lib/dataLoader.js +0 -124
  55. package/lib/dragAndDropHandler.js +0 -596
  56. package/lib/elementsRenderer.js +0 -268
  57. package/lib/jqtreeOptions.js +0 -1
  58. package/lib/keyHandler.js +0 -115
  59. package/lib/mouse.widget.js +0 -256
  60. package/lib/node.js +0 -717
  61. package/lib/nodeElement.js +0 -277
  62. package/lib/playwright/coverage.js +0 -96
  63. package/lib/playwright/playwright.test.js +0 -228
  64. package/lib/playwright/testUtils.js +0 -184
  65. package/lib/saveStateHandler.js +0 -278
  66. package/lib/scrollHandler.js +0 -250
  67. package/lib/selectNodeHandler.js +0 -129
  68. package/lib/simple.widget.js +0 -159
  69. package/lib/test/global.d.js +0 -3
  70. package/lib/test/jqTree/accessibility.test.js +0 -37
  71. package/lib/test/jqTree/create.test.js +0 -48
  72. package/lib/test/jqTree/events.test.js +0 -210
  73. package/lib/test/jqTree/keyboard.test.js +0 -225
  74. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  75. package/lib/test/jqTree/methods.test.js +0 -1347
  76. package/lib/test/jqTree/options.test.js +0 -548
  77. package/lib/test/node.test.js +0 -1160
  78. package/lib/test/nodeUtil.test.js +0 -27
  79. package/lib/test/support/exampleData.js +0 -36
  80. package/lib/test/support/jqTreeMatchers.js +0 -70
  81. package/lib/test/support/matchers.d.js +0 -1
  82. package/lib/test/support/setupTests.js +0 -7
  83. package/lib/test/support/testUtil.js +0 -32
  84. package/lib/test/support/treeStructure.js +0 -39
  85. package/lib/test/util.test.js +0 -26
  86. package/lib/tree.jquery.d.js +0 -1
  87. package/lib/tree.jquery.js +0 -1106
  88. package/lib/types.js +0 -1
  89. package/lib/typings.d.js +0 -2
  90. package/lib/util.js +0 -18
  91. package/lib/version.js +0 -9
  92. package/src/dragAndDropHandler.ts +0 -719
  93. package/src/nodeElement.ts +0 -272
  94. package/src/types.ts +0 -19
@@ -0,0 +1,177 @@
1
+ import type { ScrollParent } from "./types";
2
+
3
+ type HorizontalScrollDirection = "left" | "right";
4
+ type VerticalScrollDirection = "bottom" | "top";
5
+
6
+ interface Params {
7
+ $container: JQuery<HTMLElement>;
8
+ refreshHitAreas: () => void;
9
+ $treeElement: JQuery<HTMLElement>;
10
+ }
11
+
12
+ export default class ContainerScrollParent implements ScrollParent {
13
+ private $container: JQuery<HTMLElement>;
14
+ private horizontalScrollDirection?: HorizontalScrollDirection;
15
+ private horizontalScrollTimeout?: number;
16
+ private refreshHitAreas: () => void;
17
+ private scrollParentBottom?: number;
18
+ private scrollParentTop?: number;
19
+ private verticalScrollTimeout?: number;
20
+ private verticalScrollDirection?: VerticalScrollDirection;
21
+
22
+ constructor({ $container, refreshHitAreas }: Params) {
23
+ this.$container = $container;
24
+ this.refreshHitAreas = refreshHitAreas;
25
+ }
26
+
27
+ public checkHorizontalScrolling(pageX: number): void {
28
+ const newHorizontalScrollDirection =
29
+ this.getNewHorizontalScrollDirection(pageX);
30
+
31
+ if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
32
+ this.horizontalScrollDirection = newHorizontalScrollDirection;
33
+
34
+ if (this.horizontalScrollTimeout != null) {
35
+ window.clearTimeout(this.verticalScrollTimeout);
36
+ }
37
+
38
+ if (newHorizontalScrollDirection) {
39
+ this.horizontalScrollTimeout = window.setTimeout(
40
+ this.scrollHorizontally.bind(this),
41
+ 40,
42
+ );
43
+ }
44
+ }
45
+ }
46
+
47
+ public checkVerticalScrolling(pageY: number) {
48
+ const newVerticalScrollDirection =
49
+ this.getNewVerticalScrollDirection(pageY);
50
+
51
+ if (this.verticalScrollDirection !== newVerticalScrollDirection) {
52
+ this.verticalScrollDirection = newVerticalScrollDirection;
53
+
54
+ if (this.verticalScrollTimeout != null) {
55
+ window.clearTimeout(this.verticalScrollTimeout);
56
+ this.verticalScrollTimeout = undefined;
57
+ }
58
+
59
+ if (newVerticalScrollDirection) {
60
+ this.verticalScrollTimeout = window.setTimeout(
61
+ this.scrollVertically.bind(this),
62
+ 40,
63
+ );
64
+ }
65
+ }
66
+ }
67
+
68
+ public getScrollLeft(): number {
69
+ return this.$container.scrollLeft() || 0;
70
+ }
71
+
72
+ public scrollToY(top: number): void {
73
+ const container = this.$container.get(0) as HTMLElement;
74
+ container.scrollTop = top;
75
+ }
76
+
77
+ public stopScrolling() {
78
+ this.horizontalScrollDirection = undefined;
79
+ this.verticalScrollDirection = undefined;
80
+ this.scrollParentTop = undefined;
81
+ this.scrollParentBottom = undefined;
82
+ }
83
+
84
+ private getNewHorizontalScrollDirection(
85
+ pageX: number,
86
+ ): HorizontalScrollDirection | undefined {
87
+ const scrollParentOffset = this.$container.offset();
88
+ if (!scrollParentOffset) {
89
+ return undefined;
90
+ }
91
+
92
+ const container = this.$container.get(0) as HTMLElement;
93
+
94
+ const rightEdge = scrollParentOffset.left + container.clientWidth;
95
+ const leftEdge = scrollParentOffset.left;
96
+ const isNearRightEdge = pageX > rightEdge - 20;
97
+ const isNearLeftEdge = pageX < leftEdge + 20;
98
+
99
+ if (isNearRightEdge) {
100
+ return "right";
101
+ } else if (isNearLeftEdge) {
102
+ return "left";
103
+ }
104
+
105
+ return undefined;
106
+ }
107
+
108
+ private getNewVerticalScrollDirection(
109
+ pageY: number,
110
+ ): VerticalScrollDirection | undefined {
111
+ if (pageY < this.getScrollParentTop()) {
112
+ return "top";
113
+ }
114
+
115
+ if (pageY > this.getScrollParentBottom()) {
116
+ return "bottom";
117
+ }
118
+
119
+ return undefined;
120
+ }
121
+
122
+ private scrollHorizontally() {
123
+ if (!this.horizontalScrollDirection) {
124
+ return;
125
+ }
126
+
127
+ const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
128
+ const container = this.$container.get(0) as HTMLElement;
129
+
130
+ container.scrollBy({
131
+ left: distance,
132
+ top: 0,
133
+ behavior: "instant",
134
+ });
135
+
136
+ this.refreshHitAreas();
137
+
138
+ setTimeout(this.scrollHorizontally.bind(this), 40);
139
+ }
140
+
141
+ private scrollVertically() {
142
+ if (!this.verticalScrollDirection) {
143
+ return;
144
+ }
145
+
146
+ const distance = this.verticalScrollDirection === "top" ? -20 : 20;
147
+ const container = this.$container.get(0) as HTMLElement;
148
+
149
+ container.scrollBy({
150
+ left: 0,
151
+ top: distance,
152
+ behavior: "instant",
153
+ });
154
+
155
+ this.refreshHitAreas();
156
+
157
+ setTimeout(this.scrollVertically.bind(this), 40);
158
+ }
159
+
160
+ private getScrollParentTop() {
161
+ if (this.scrollParentTop == null) {
162
+ this.scrollParentTop = this.$container.offset()?.top || 0;
163
+ }
164
+
165
+ return this.scrollParentTop;
166
+ }
167
+
168
+ private getScrollParentBottom() {
169
+ if (this.scrollParentBottom == null) {
170
+ this.scrollParentBottom =
171
+ this.getScrollParentTop() +
172
+ (this.$container.innerHeight() ?? 0);
173
+ }
174
+
175
+ return this.scrollParentBottom;
176
+ }
177
+ }
@@ -0,0 +1,50 @@
1
+ import type { ScrollParent } from "./types";
2
+ import ContainerScrollParent from "./containerScrollParent";
3
+ import DocumentScrollParent from "./documentScrollParent";
4
+
5
+ const hasOverFlow = ($element: JQuery<HTMLElement>): boolean => {
6
+ for (const attr of ["overflow", "overflow-y"]) {
7
+ const overflowValue = $element.css(attr);
8
+ if (overflowValue === "auto" || overflowValue === "scroll") {
9
+ return true;
10
+ }
11
+ }
12
+
13
+ return false;
14
+ };
15
+
16
+ const getParentWithOverflow = (
17
+ $treeElement: JQuery<HTMLElement>,
18
+ ): JQuery<HTMLElement> | null => {
19
+ if (hasOverFlow($treeElement)) {
20
+ return $treeElement;
21
+ }
22
+
23
+ for (const element of $treeElement.parents().get()) {
24
+ const $element = jQuery(element);
25
+ if (hasOverFlow($element)) {
26
+ return $element;
27
+ }
28
+ }
29
+
30
+ return null;
31
+ };
32
+
33
+ const createScrollParent = (
34
+ $treeElement: JQuery<HTMLElement>,
35
+ refreshHitAreas: () => void,
36
+ ): ScrollParent => {
37
+ const $container = getParentWithOverflow($treeElement);
38
+
39
+ if ($container?.length && $container[0]?.tagName !== "HTML") {
40
+ return new ContainerScrollParent({
41
+ $container,
42
+ refreshHitAreas,
43
+ $treeElement,
44
+ });
45
+ } else {
46
+ return new DocumentScrollParent($treeElement, refreshHitAreas);
47
+ }
48
+ };
49
+
50
+ export default createScrollParent;
@@ -0,0 +1,182 @@
1
+ import type { ScrollParent } from "./types";
2
+
3
+ type HorizontalScrollDirection = "left" | "right";
4
+ type VerticalScrollDirection = "bottom" | "top";
5
+
6
+ export default class DocumentScrollParent implements ScrollParent {
7
+ private $element: JQuery<HTMLElement>;
8
+ private horizontalScrollDirection?: HorizontalScrollDirection;
9
+ private horizontalScrollTimeout?: number;
10
+ private refreshHitAreas: () => void;
11
+ private verticalScrollDirection?: VerticalScrollDirection;
12
+ private verticalScrollTimeout?: number;
13
+ private documentScrollHeight?: number;
14
+ private documentScrollWidth?: number;
15
+
16
+ constructor($element: JQuery<HTMLElement>, refreshHitAreas: () => void) {
17
+ this.$element = $element;
18
+ this.refreshHitAreas = refreshHitAreas;
19
+ }
20
+
21
+ public checkHorizontalScrolling(pageX: number): void {
22
+ const newHorizontalScrollDirection =
23
+ this.getNewHorizontalScrollDirection(pageX);
24
+
25
+ if (this.horizontalScrollDirection !== newHorizontalScrollDirection) {
26
+ this.horizontalScrollDirection = newHorizontalScrollDirection;
27
+
28
+ if (this.horizontalScrollTimeout != null) {
29
+ window.clearTimeout(this.horizontalScrollTimeout);
30
+ }
31
+
32
+ if (newHorizontalScrollDirection) {
33
+ this.horizontalScrollTimeout = window.setTimeout(
34
+ this.scrollHorizontally.bind(this),
35
+ 40,
36
+ );
37
+ }
38
+ }
39
+ }
40
+
41
+ public checkVerticalScrolling(pageY: number) {
42
+ const newVerticalScrollDirection =
43
+ this.getNewVerticalScrollDirection(pageY);
44
+
45
+ if (this.verticalScrollDirection !== newVerticalScrollDirection) {
46
+ this.verticalScrollDirection = newVerticalScrollDirection;
47
+
48
+ if (this.verticalScrollTimeout != null) {
49
+ window.clearTimeout(this.verticalScrollTimeout);
50
+ this.verticalScrollTimeout = undefined;
51
+ }
52
+
53
+ if (newVerticalScrollDirection) {
54
+ this.verticalScrollTimeout = window.setTimeout(
55
+ this.scrollVertically.bind(this),
56
+ 40,
57
+ );
58
+ }
59
+ }
60
+ }
61
+
62
+ public getScrollLeft(): number {
63
+ return document.documentElement.scrollLeft;
64
+ }
65
+
66
+ public scrollToY(top: number): void {
67
+ const offset = this.$element.offset();
68
+ const treeTop = offset ? offset.top : 0;
69
+
70
+ jQuery(document).scrollTop(top + treeTop);
71
+ }
72
+
73
+ public stopScrolling() {
74
+ this.horizontalScrollDirection = undefined;
75
+ this.verticalScrollDirection = undefined;
76
+ this.documentScrollHeight = undefined;
77
+ this.documentScrollWidth = undefined;
78
+ }
79
+
80
+ private getNewHorizontalScrollDirection(
81
+ pageX: number,
82
+ ): HorizontalScrollDirection | undefined {
83
+ const $document = jQuery(document);
84
+
85
+ const scrollLeft = $document.scrollLeft() || 0;
86
+ const windowWidth = jQuery(window).width() || 0;
87
+
88
+ const isNearRightEdge = pageX > windowWidth - 20;
89
+ const isNearLeftEdge = pageX - scrollLeft < 20;
90
+
91
+ if (isNearRightEdge && this.canScrollRight()) {
92
+ return "right";
93
+ }
94
+
95
+ if (isNearLeftEdge) {
96
+ return "left";
97
+ }
98
+
99
+ return undefined;
100
+ }
101
+
102
+ private canScrollRight() {
103
+ const documentElement = document.documentElement;
104
+
105
+ return (
106
+ documentElement.scrollLeft + documentElement.clientWidth <
107
+ this.getDocumentScrollWidth()
108
+ );
109
+ }
110
+
111
+ private canScrollDown() {
112
+ const documentElement = document.documentElement;
113
+
114
+ return (
115
+ documentElement.scrollTop + documentElement.clientHeight <
116
+ this.getDocumentScrollHeight()
117
+ );
118
+ }
119
+
120
+ private getDocumentScrollHeight() {
121
+ // Store the original scroll height because the scroll height can increase when the drag element is moved beyond the scroll height.
122
+ if (this.documentScrollHeight == null) {
123
+ this.documentScrollHeight = document.documentElement.scrollHeight;
124
+ }
125
+
126
+ return this.documentScrollHeight;
127
+ }
128
+
129
+ private getDocumentScrollWidth() {
130
+ // Store the original scroll width because the scroll width can increase when the drag element is moved beyond the scroll width.
131
+ if (this.documentScrollWidth == null) {
132
+ this.documentScrollWidth = document.documentElement.scrollWidth;
133
+ }
134
+
135
+ return this.documentScrollWidth;
136
+ }
137
+
138
+ private getNewVerticalScrollDirection(
139
+ pageY: number,
140
+ ): VerticalScrollDirection | undefined {
141
+ const scrollTop = jQuery(document).scrollTop() || 0;
142
+ const distanceTop = pageY - scrollTop;
143
+
144
+ if (distanceTop < 20) {
145
+ return "top";
146
+ }
147
+
148
+ const windowHeight = jQuery(window).height() || 0;
149
+
150
+ if (windowHeight - (pageY - scrollTop) < 20 && this.canScrollDown()) {
151
+ return "bottom";
152
+ }
153
+
154
+ return undefined;
155
+ }
156
+
157
+ private scrollHorizontally() {
158
+ if (!this.horizontalScrollDirection) {
159
+ return;
160
+ }
161
+
162
+ const distance = this.horizontalScrollDirection === "left" ? -20 : 20;
163
+ window.scrollBy({ left: distance, top: 0, behavior: "instant" });
164
+
165
+ this.refreshHitAreas();
166
+
167
+ setTimeout(this.scrollHorizontally.bind(this), 40);
168
+ }
169
+
170
+ private scrollVertically() {
171
+ if (!this.verticalScrollDirection) {
172
+ return;
173
+ }
174
+
175
+ const distance = this.verticalScrollDirection === "top" ? -20 : 20;
176
+ window.scrollBy({ left: 0, top: distance, behavior: "instant" });
177
+
178
+ this.refreshHitAreas();
179
+
180
+ setTimeout(this.scrollVertically.bind(this), 40);
181
+ }
182
+ }
@@ -0,0 +1,7 @@
1
+ export interface ScrollParent {
2
+ checkHorizontalScrolling(pageX: number): void;
3
+ checkVerticalScrolling(pageY: number): void;
4
+ getScrollLeft(): number;
5
+ scrollToY(top: number): void;
6
+ stopScrolling(): void;
7
+ }