jqtree 1.7.5 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/.eslintrc +13 -3
  2. package/.github/workflows/ci.yml +6 -6
  3. package/.github/workflows/codeql-analysis.yml +4 -4
  4. package/.github/workflows/size.yml +3 -3
  5. package/.github/workflows/static.yml +1 -1
  6. package/bower.json +1 -1
  7. package/config/babel.config.json +1 -1
  8. package/config/jest.config.js +4 -0
  9. package/config/jest.polyfills.js +14 -0
  10. package/config/production +2 -0
  11. package/devserver/devserver_scroll.js +8 -0
  12. package/devserver/test_index.html +9 -0
  13. package/devserver/test_scroll.html +28 -0
  14. package/devserver/test_scroll_container.html +39 -0
  15. package/docs/.ruby-version +1 -1
  16. package/docs/_config.yml +1 -1
  17. package/docs/_entries/general/changelog.md +11 -0
  18. package/docs/_entries/multiple_selection/get-selected-nodes.md +1 -1
  19. package/docs/_entries/node/getnextnode.md +3 -6
  20. package/docs/_entries/node/getnextsibling.md +1 -1
  21. package/docs/_entries/node/getnextvisiblenode.md +8 -5
  22. package/docs/_entries/node/getpreviousnode.md +12 -0
  23. package/docs/_entries/node/getprevioussibling.md +1 -1
  24. package/docs/_entries/node/getpreviousvisiblenode.md +6 -5
  25. package/package.json +35 -29
  26. package/src/dataLoader.ts +57 -34
  27. package/src/dragAndDropHandler/dragElement.ts +54 -0
  28. package/src/dragAndDropHandler/generateHitAreas.ts +176 -0
  29. package/src/dragAndDropHandler/index.ts +454 -0
  30. package/src/dragAndDropHandler/iterateVisibleNodes.ts +91 -0
  31. package/src/dragAndDropHandler/types.ts +13 -0
  32. package/src/elementsRenderer.ts +75 -40
  33. package/src/jqtreeMethodTypes.ts +40 -0
  34. package/src/jqtreeOptions.ts +43 -25
  35. package/src/keyHandler.ts +59 -30
  36. package/src/mouseHandler.ts +385 -0
  37. package/src/mouseUtils.ts +23 -0
  38. package/src/node.ts +1 -29
  39. package/src/nodeElement/borderDropHint.ts +32 -0
  40. package/src/nodeElement/folderElement.ts +133 -0
  41. package/src/nodeElement/ghostDropHint.ts +69 -0
  42. package/src/nodeElement/index.ts +102 -0
  43. package/src/playwright/coverage.ts +4 -7
  44. package/src/playwright/playwright.test.ts +150 -53
  45. package/src/playwright/testUtils.ts +28 -5
  46. package/src/position.ts +28 -0
  47. package/src/saveStateHandler.ts +75 -26
  48. package/src/scrollHandler/containerScrollParent.ts +13 -23
  49. package/src/scrollHandler/createScrollParent.ts +22 -22
  50. package/src/scrollHandler/documentScrollParent.ts +16 -13
  51. package/src/scrollHandler.ts +13 -15
  52. package/src/selectNodeHandler.ts +10 -16
  53. package/src/test/jqTree/events.test.ts +97 -30
  54. package/src/test/jqTree/keyboard.test.ts +18 -23
  55. package/src/test/jqTree/loadOnDemand.test.ts +22 -15
  56. package/src/test/jqTree/methods.test.ts +40 -14
  57. package/src/test/jqTree/mouse.test.ts +82 -0
  58. package/src/test/jqTree/options.test.ts +24 -12
  59. package/src/test/node.test.ts +3 -2
  60. package/src/test/{nodeUtil.test.ts → position.test.ts} +1 -1
  61. package/src/tree.jquery.ts +314 -208
  62. package/src/util.ts +12 -0
  63. package/src/version.ts +1 -1
  64. package/tree.jquery.debug.js +2594 -3419
  65. package/tree.jquery.debug.js.map +1 -1
  66. package/tree.jquery.js +3 -3
  67. package/tree.jquery.js.map +1 -1
  68. package/tsconfig.json +5 -3
  69. package/docs/_entries/functions/get-selected-nodes.md +0 -10
  70. package/lib/dataLoader.js +0 -123
  71. package/lib/dragAndDropHandler.js +0 -588
  72. package/lib/elementsRenderer.js +0 -267
  73. package/lib/jqtreeOptions.js +0 -1
  74. package/lib/keyHandler.js +0 -111
  75. package/lib/mouse.widget.js +0 -255
  76. package/lib/node.js +0 -708
  77. package/lib/nodeElement.js +0 -274
  78. package/lib/nodeUtils.js +0 -10
  79. package/lib/playwright/coverage.js +0 -99
  80. package/lib/playwright/playwright.test.js +0 -606
  81. package/lib/playwright/testUtils.js +0 -210
  82. package/lib/saveStateHandler.js +0 -277
  83. package/lib/scrollHandler/containerScrollParent.js +0 -160
  84. package/lib/scrollHandler/createScrollParent.js +0 -57
  85. package/lib/scrollHandler/documentScrollParent.js +0 -169
  86. package/lib/scrollHandler/scrollParent.js +0 -58
  87. package/lib/scrollHandler/types.js +0 -1
  88. package/lib/scrollHandler.js +0 -71
  89. package/lib/selectNodeHandler.js +0 -128
  90. package/lib/simple.widget.js +0 -158
  91. package/lib/test/global.d.js +0 -3
  92. package/lib/test/jqTree/accessibility.test.js +0 -37
  93. package/lib/test/jqTree/create.test.js +0 -48
  94. package/lib/test/jqTree/events.test.js +0 -210
  95. package/lib/test/jqTree/keyboard.test.js +0 -225
  96. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  97. package/lib/test/jqTree/methods.test.js +0 -1348
  98. package/lib/test/jqTree/options.test.js +0 -548
  99. package/lib/test/jqTree/scrollHandler/containerScrollParent.test.js +0 -94
  100. package/lib/test/node.test.js +0 -1202
  101. package/lib/test/nodeUtil.test.js +0 -27
  102. package/lib/test/nodeUtils.test.js +0 -20
  103. package/lib/test/support/exampleData.js +0 -35
  104. package/lib/test/support/jqTreeMatchers.js +0 -70
  105. package/lib/test/support/matchers.d.js +0 -1
  106. package/lib/test/support/setupTests.js +0 -7
  107. package/lib/test/support/testUtil.js +0 -29
  108. package/lib/test/support/treeStructure.js +0 -38
  109. package/lib/test/util.test.js +0 -26
  110. package/lib/tree.jquery.d.js +0 -1
  111. package/lib/tree.jquery.js +0 -1105
  112. package/lib/types.js +0 -1
  113. package/lib/typings.d.js +0 -2
  114. package/lib/util.js +0 -15
  115. package/lib/version.js +0 -8
  116. package/src/dragAndDropHandler.ts +0 -713
  117. package/src/mouse.widget.ts +0 -266
  118. package/src/nodeElement.ts +0 -272
  119. package/src/types.ts +0 -19
@@ -1,266 +0,0 @@
1
- /*
2
- This widget does the same a the mouse widget in jqueryui.
3
- */
4
- import SimpleWidget from "./simple.widget";
5
- import { PositionInfo } from "./types";
6
-
7
- const getPositionInfoFromMouseEvent = (e: MouseEvent): PositionInfo => ({
8
- pageX: e.pageX,
9
- pageY: e.pageY,
10
- target: e.target as HTMLElement,
11
- originalEvent: e,
12
- });
13
-
14
- const getPositionInfoFromTouch = (
15
- touch: Touch,
16
- e: TouchEvent
17
- ): PositionInfo => ({
18
- pageX: touch.pageX,
19
- pageY: touch.pageY,
20
- target: touch.target as HTMLElement,
21
- originalEvent: e,
22
- });
23
-
24
- abstract class MouseWidget<WidgetOptions> extends SimpleWidget<WidgetOptions> {
25
- protected isMouseStarted: boolean;
26
- protected mouseDownInfo: PositionInfo | null;
27
- private mouseDelayTimer: number | null;
28
- private isMouseDelayMet: boolean;
29
-
30
- public init(): void {
31
- const element = this.$el.get(0);
32
-
33
- if (element) {
34
- element.addEventListener("mousedown", this.mouseDown, {
35
- passive: false,
36
- });
37
- element.addEventListener("touchstart", this.touchStart, {
38
- passive: false,
39
- });
40
- }
41
-
42
- this.isMouseStarted = false;
43
- this.mouseDelayTimer = null;
44
- this.isMouseDelayMet = false;
45
- this.mouseDownInfo = null;
46
- }
47
-
48
- public deinit(): void {
49
- const el = this.$el.get(0);
50
-
51
- if (el) {
52
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
53
- (el as any).removeEventListener("mousedown", this.mouseDown, {
54
- passive: false,
55
- });
56
-
57
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
58
- (el as any).removeEventListener("touchstart", this.touchStart, {
59
- passive: false,
60
- });
61
- }
62
-
63
- this.removeMouseMoveEventListeners();
64
- }
65
-
66
- protected abstract mouseCapture(positionInfo: PositionInfo): boolean | null;
67
-
68
- protected abstract mouseStart(positionInfo: PositionInfo): boolean;
69
-
70
- protected abstract mouseDrag(positionInfo: PositionInfo): void;
71
-
72
- protected abstract mouseStop(positionInfo: PositionInfo): void;
73
-
74
- protected abstract getMouseDelay(): number;
75
-
76
- private mouseDown = (e: MouseEvent): void => {
77
- // Left mouse button?
78
- if (e.button !== 0) {
79
- return;
80
- }
81
-
82
- const result = this.handleMouseDown(getPositionInfoFromMouseEvent(e));
83
-
84
- if (result && e.cancelable) {
85
- e.preventDefault();
86
- }
87
- };
88
-
89
- private handleMouseDown(positionInfo: PositionInfo): boolean {
90
- // We may have missed mouseup (out of window)
91
- if (this.isMouseStarted) {
92
- this.handleMouseUp(positionInfo);
93
- }
94
-
95
- this.mouseDownInfo = positionInfo;
96
-
97
- if (!this.mouseCapture(positionInfo)) {
98
- return false;
99
- }
100
-
101
- this.handleStartMouse();
102
-
103
- return true;
104
- }
105
-
106
- private handleStartMouse(): void {
107
- document.addEventListener("mousemove", this.mouseMove, {
108
- passive: false,
109
- });
110
- document.addEventListener("touchmove", this.touchMove, {
111
- passive: false,
112
- });
113
- document.addEventListener("mouseup", this.mouseUp, { passive: false });
114
- document.addEventListener("touchend", this.touchEnd, {
115
- passive: false,
116
- });
117
-
118
- const mouseDelay = this.getMouseDelay();
119
-
120
- if (mouseDelay) {
121
- this.startMouseDelayTimer(mouseDelay);
122
- } else {
123
- this.isMouseDelayMet = true;
124
- }
125
- }
126
-
127
- private startMouseDelayTimer(mouseDelay: number): void {
128
- if (this.mouseDelayTimer) {
129
- clearTimeout(this.mouseDelayTimer);
130
- }
131
-
132
- this.mouseDelayTimer = window.setTimeout(() => {
133
- if (this.mouseDownInfo) {
134
- this.isMouseDelayMet = true;
135
- }
136
- }, mouseDelay);
137
-
138
- this.isMouseDelayMet = false;
139
- }
140
-
141
- private mouseMove = (e: MouseEvent): void => {
142
- this.handleMouseMove(e, getPositionInfoFromMouseEvent(e));
143
- };
144
-
145
- private handleMouseMove(
146
- e: MouseEvent | TouchEvent,
147
- positionInfo: PositionInfo
148
- ): void {
149
- if (this.isMouseStarted) {
150
- this.mouseDrag(positionInfo);
151
-
152
- if (e.cancelable) {
153
- e.preventDefault();
154
- }
155
- return;
156
- }
157
-
158
- if (!this.isMouseDelayMet) {
159
- return;
160
- }
161
-
162
- if (this.mouseDownInfo) {
163
- this.isMouseStarted = this.mouseStart(this.mouseDownInfo) !== false;
164
- }
165
-
166
- if (this.isMouseStarted) {
167
- this.mouseDrag(positionInfo);
168
-
169
- if (e.cancelable) {
170
- e.preventDefault();
171
- }
172
- } else {
173
- this.handleMouseUp(positionInfo);
174
- }
175
- }
176
-
177
- private mouseUp = (e: MouseEvent): void => {
178
- this.handleMouseUp(getPositionInfoFromMouseEvent(e));
179
- };
180
-
181
- private handleMouseUp(positionInfo: PositionInfo): void {
182
- this.removeMouseMoveEventListeners();
183
- this.isMouseDelayMet = false;
184
- this.mouseDownInfo = null;
185
-
186
- if (this.isMouseStarted) {
187
- this.isMouseStarted = false;
188
- this.mouseStop(positionInfo);
189
- }
190
- }
191
-
192
- private removeMouseMoveEventListeners() {
193
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
194
- (document as any).removeEventListener("mousemove", this.mouseMove, {
195
- passive: false,
196
- });
197
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
198
- (document as any).removeEventListener("touchmove", this.touchMove, {
199
- passive: false,
200
- });
201
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
202
- (document as any).removeEventListener("mouseup", this.mouseUp, {
203
- passive: false,
204
- });
205
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
206
- (document as any).removeEventListener("touchend", this.touchEnd, {
207
- passive: false,
208
- });
209
- }
210
-
211
- private touchStart = (e: TouchEvent): void => {
212
- if (!e) {
213
- return;
214
- }
215
-
216
- if (e.touches.length > 1) {
217
- return;
218
- }
219
-
220
- const touch = e.changedTouches[0];
221
-
222
- if (!touch) {
223
- return;
224
- }
225
-
226
- this.handleMouseDown(getPositionInfoFromTouch(touch, e));
227
- };
228
-
229
- private touchMove = (e: TouchEvent): void => {
230
- if (!e) {
231
- return;
232
- }
233
-
234
- if (e.touches.length > 1) {
235
- return;
236
- }
237
-
238
- const touch = e.changedTouches[0];
239
-
240
- if (!touch) {
241
- return;
242
- }
243
-
244
- this.handleMouseMove(e, getPositionInfoFromTouch(touch, e));
245
- };
246
-
247
- private touchEnd = (e: TouchEvent): void => {
248
- if (!e) {
249
- return;
250
- }
251
-
252
- if (e.touches.length > 1) {
253
- return;
254
- }
255
-
256
- const touch = e.changedTouches[0];
257
-
258
- if (!touch) {
259
- return;
260
- }
261
-
262
- this.handleMouseUp(getPositionInfoFromTouch(touch, e));
263
- };
264
- }
265
-
266
- export default MouseWidget;
@@ -1,272 +0,0 @@
1
- import { Position, Node } from "./node";
2
- import { JqTreeWidget } from "./tree.jquery";
3
- import { DropHint } from "./types";
4
-
5
- export type OnFinishOpenNode = (node: Node) => void;
6
-
7
- export class NodeElement {
8
- public node: Node;
9
- public $element: JQuery<HTMLElement>;
10
- protected treeWidget: JqTreeWidget;
11
-
12
- constructor(node: Node, treeWidget: JqTreeWidget) {
13
- this.init(node, treeWidget);
14
- }
15
-
16
- public init(node: Node, treeWidget: JqTreeWidget): void {
17
- this.node = node;
18
- this.treeWidget = treeWidget;
19
-
20
- if (!node.element) {
21
- const element = this.treeWidget.element.get(0);
22
-
23
- if (element) {
24
- node.element = element;
25
- }
26
- }
27
-
28
- if (node.element) {
29
- this.$element = jQuery(node.element);
30
- }
31
- }
32
-
33
- public addDropHint(position: number): DropHint {
34
- if (this.mustShowBorderDropHint(position)) {
35
- return new BorderDropHint(
36
- this.$element,
37
- this.treeWidget._getScrollLeft(),
38
- );
39
- } else {
40
- return new GhostDropHint(this.node, this.$element, position);
41
- }
42
- }
43
-
44
- public select(mustSetFocus: boolean): void {
45
- const $li = this.getLi();
46
-
47
- $li.addClass("jqtree-selected");
48
-
49
- const $span = this.getSpan();
50
- $span.attr("tabindex", this.treeWidget.options.tabIndex ?? null);
51
- $span.attr("aria-selected", "true");
52
-
53
- if (mustSetFocus) {
54
- $span.trigger("focus");
55
- }
56
- }
57
-
58
- public deselect(): void {
59
- const $li = this.getLi();
60
-
61
- $li.removeClass("jqtree-selected");
62
-
63
- const $span = this.getSpan();
64
- $span.removeAttr("tabindex");
65
- $span.attr("aria-selected", "false");
66
-
67
- $span.trigger("blur");
68
- }
69
-
70
- protected getUl(): JQuery<HTMLElement> {
71
- return this.$element.children("ul:first");
72
- }
73
-
74
- protected getSpan(): JQuery<HTMLElement> {
75
- return this.$element
76
- .children(".jqtree-element")
77
- .find("span.jqtree-title");
78
- }
79
-
80
- protected getLi(): JQuery<HTMLElement> {
81
- return this.$element;
82
- }
83
-
84
- protected mustShowBorderDropHint(position: Position): boolean {
85
- return position === Position.Inside;
86
- }
87
- }
88
-
89
- export class FolderElement extends NodeElement {
90
- public open(
91
- onFinished: OnFinishOpenNode | null,
92
- slide = true,
93
- animationSpeed: JQuery.Duration = "fast",
94
- ): void {
95
- if (this.node.is_open) {
96
- return;
97
- }
98
-
99
- this.node.is_open = true;
100
-
101
- const $button = this.getButton();
102
- $button.removeClass("jqtree-closed");
103
- $button.html("");
104
-
105
- const buttonEl = $button.get(0);
106
-
107
- if (buttonEl) {
108
- const openedIconElement =
109
- this.treeWidget.renderer.openedIconElement;
110
-
111
- if (openedIconElement) {
112
- const icon = openedIconElement.cloneNode(true);
113
- buttonEl.appendChild(icon);
114
- }
115
- }
116
-
117
- const doOpen = (): void => {
118
- const $li = this.getLi();
119
- $li.removeClass("jqtree-closed");
120
-
121
- const $titleSpan = this.getSpan();
122
- $titleSpan.attr("aria-expanded", "true");
123
-
124
- if (onFinished) {
125
- onFinished(this.node);
126
- }
127
-
128
- this.treeWidget._triggerEvent("tree.open", {
129
- node: this.node,
130
- });
131
- };
132
-
133
- if (slide) {
134
- this.getUl().slideDown(animationSpeed, doOpen);
135
- } else {
136
- this.getUl().show();
137
- doOpen();
138
- }
139
- }
140
-
141
- public close(
142
- slide = true,
143
- animationSpeed: JQuery.Duration | undefined = "fast",
144
- ): void {
145
- if (!this.node.is_open) {
146
- return;
147
- }
148
-
149
- this.node.is_open = false;
150
-
151
- const $button = this.getButton();
152
- $button.addClass("jqtree-closed");
153
- $button.html("");
154
-
155
- const buttonEl = $button.get(0);
156
-
157
- if (buttonEl) {
158
- const closedIconElement =
159
- this.treeWidget.renderer.closedIconElement;
160
-
161
- if (closedIconElement) {
162
- const icon = closedIconElement.cloneNode(true);
163
- buttonEl.appendChild(icon);
164
- }
165
- }
166
-
167
- const doClose = (): void => {
168
- const $li = this.getLi();
169
- $li.addClass("jqtree-closed");
170
-
171
- const $titleSpan = this.getSpan();
172
- $titleSpan.attr("aria-expanded", "false");
173
-
174
- this.treeWidget._triggerEvent("tree.close", {
175
- node: this.node,
176
- });
177
- };
178
-
179
- if (slide) {
180
- this.getUl().slideUp(animationSpeed, doClose);
181
- } else {
182
- this.getUl().hide();
183
- doClose();
184
- }
185
- }
186
-
187
- protected mustShowBorderDropHint(position: Position): boolean {
188
- return !this.node.is_open && position === Position.Inside;
189
- }
190
-
191
- private getButton(): JQuery {
192
- return this.$element
193
- .children(".jqtree-element")
194
- .find("a.jqtree-toggler");
195
- }
196
- }
197
-
198
- export class BorderDropHint implements DropHint {
199
- private $hint: JQuery<Element>;
200
-
201
- constructor($element: JQuery<Element>, scrollLeft: number) {
202
- const $div = $element.children(".jqtree-element");
203
-
204
- const elWidth = $element.width() || 0;
205
- const width = Math.max(elWidth + scrollLeft - 4, 0);
206
-
207
- const elHeight = $div.outerHeight() || 0;
208
- const height = Math.max(elHeight - 4, 0);
209
-
210
- this.$hint = jQuery('<span class="jqtree-border"></span>');
211
- $div.append(this.$hint);
212
-
213
- this.$hint.css({ width, height });
214
- }
215
-
216
- public remove(): void {
217
- this.$hint.remove();
218
- }
219
- }
220
-
221
- class GhostDropHint implements DropHint {
222
- private $element: JQuery<Element>;
223
- private node: Node;
224
- private $ghost: JQuery;
225
-
226
- constructor(node: Node, $element: JQuery<Element>, position: Position) {
227
- this.$element = $element;
228
-
229
- this.node = node;
230
- this.$ghost = jQuery(
231
- `<li class="jqtree_common jqtree-ghost"><span class="jqtree_common jqtree-circle"></span>
232
- <span class="jqtree_common jqtree-line"></span></li>`,
233
- );
234
-
235
- if (position === Position.After) {
236
- this.moveAfter();
237
- } else if (position === Position.Before) {
238
- this.moveBefore();
239
- } else if (position === Position.Inside) {
240
- if (node.isFolder() && node.is_open) {
241
- this.moveInsideOpenFolder();
242
- } else {
243
- this.moveInside();
244
- }
245
- }
246
- }
247
-
248
- public remove(): void {
249
- this.$ghost.remove();
250
- }
251
-
252
- public moveAfter(): void {
253
- this.$element.after(this.$ghost);
254
- }
255
-
256
- public moveBefore(): void {
257
- this.$element.before(this.$ghost);
258
- }
259
-
260
- public moveInsideOpenFolder(): void {
261
- const childElement = this.node.children[0]?.element;
262
-
263
- if (childElement) {
264
- jQuery(childElement).before(this.$ghost);
265
- }
266
- }
267
-
268
- public moveInside(): void {
269
- this.$element.after(this.$ghost);
270
- this.$ghost.addClass("jqtree-inside");
271
- }
272
- }
package/src/types.ts DELETED
@@ -1,19 +0,0 @@
1
- import { Node, Position } from "./node";
2
-
3
- export interface DropHint {
4
- remove: () => void;
5
- }
6
-
7
- export interface HitArea {
8
- top: number;
9
- bottom: number;
10
- node: Node;
11
- position: Position;
12
- }
13
-
14
- export interface PositionInfo {
15
- pageX: number | undefined;
16
- pageY: number | undefined;
17
- target: HTMLElement;
18
- originalEvent: Event;
19
- }