jqtree 1.9.0 → 2.0.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 (49) hide show
  1. package/bower.json +1 -1
  2. package/js-coverage/coverage-final.json +13 -0
  3. package/lib/jqtreeOptions.js +1 -0
  4. package/lib/tree.jquery.d.js +0 -0
  5. package/lib/tree.jquery.js +394 -0
  6. package/lib/triggerJQueryEvent.js +68 -0
  7. package/lib/typings.d.js +1 -0
  8. package/lib/version.js +2 -0
  9. package/package.json +34 -29
  10. package/pnpm-workspace.yaml +3 -3
  11. package/src/jqtreeOptions.ts +20 -62
  12. package/src/tree.jquery.d.ts +81 -92
  13. package/src/tree.jquery.ts +234 -938
  14. package/src/triggerJQueryEvent.ts +97 -0
  15. package/src/version.ts +2 -2
  16. package/tree.jquery.debug.js +4226 -3281
  17. package/tree.jquery.debug.js.map +1 -1
  18. package/tree.jquery.js +22 -2
  19. package/tree.jquery.js.map +1 -1
  20. package/eslint.config.mjs +0 -112
  21. package/src/animation.ts +0 -48
  22. package/src/dataLoader.ts +0 -143
  23. package/src/dragAndDropHandler/binarySearch.ts +0 -27
  24. package/src/dragAndDropHandler/dragElement.ts +0 -54
  25. package/src/dragAndDropHandler/generateHitAreas.ts +0 -195
  26. package/src/dragAndDropHandler/index.ts +0 -432
  27. package/src/dragAndDropHandler/iterateVisibleNodes.ts +0 -91
  28. package/src/dragAndDropHandler/types.ts +0 -12
  29. package/src/elementsRenderer.ts +0 -359
  30. package/src/jqtreeMethodTypes.ts +0 -40
  31. package/src/keyHandler.ts +0 -139
  32. package/src/mouseHandler.ts +0 -383
  33. package/src/mouseUtils.ts +0 -23
  34. package/src/node.ts +0 -653
  35. package/src/nodeElement/borderDropHint.ts +0 -32
  36. package/src/nodeElement/folderElement.ts +0 -138
  37. package/src/nodeElement/ghostDropHint.ts +0 -74
  38. package/src/nodeElement/index.ts +0 -94
  39. package/src/nodeUtils.ts +0 -10
  40. package/src/positionUtils.ts +0 -18
  41. package/src/saveStateHandler.ts +0 -276
  42. package/src/scrollHandler/containerScrollParent.ts +0 -71
  43. package/src/scrollHandler/createScrollParent.ts +0 -51
  44. package/src/scrollHandler/documentScrollParent.ts +0 -104
  45. package/src/scrollHandler/scrollParent.ts +0 -117
  46. package/src/scrollHandler.ts +0 -55
  47. package/src/selectNodeHandler.ts +0 -111
  48. package/src/simple.widget.ts +0 -134
  49. package/src/util.ts +0 -5
package/eslint.config.mjs DELETED
@@ -1,112 +0,0 @@
1
- import cspellESLintPluginRecommended from "@cspell/eslint-plugin/recommended";
2
- import eslint from "@eslint/js";
3
- import tseslint from "typescript-eslint";
4
- import importPlugin from "eslint-plugin-import-x";
5
- import jestDomPlugin from "eslint-plugin-jest-dom";
6
- import jestExtendedPlugin from "eslint-plugin-jest-extended";
7
- import perfectionistPlugin from "eslint-plugin-perfectionist";
8
- import playwrightPlugin from "eslint-plugin-playwright";
9
- import testingLibraryPlugin from "eslint-plugin-testing-library";
10
- import vitestPlugin from "@vitest/eslint-plugin";
11
-
12
- export default [
13
- eslint.configs.recommended,
14
- ...tseslint.configs.strictTypeChecked,
15
- ...tseslint.configs.stylisticTypeChecked,
16
- importPlugin.flatConfigs.recommended,
17
- importPlugin.flatConfigs.typescript,
18
- perfectionistPlugin.configs["recommended-natural"],
19
- cspellESLintPluginRecommended,
20
- {
21
- languageOptions: {
22
- parserOptions: {
23
- projectService: true,
24
- tsconfigRootDir: import.meta.dirname,
25
- },
26
- },
27
- rules: {
28
- "@typescript-eslint/consistent-type-imports": "error",
29
- "@typescript-eslint/explicit-function-return-type": "off",
30
- "@typescript-eslint/interface-name-prefix": "off",
31
- "@typescript-eslint/no-empty-object-type": "off",
32
- "@typescript-eslint/no-explicit-any": "off",
33
- "@typescript-eslint/no-use-before-define": "off",
34
- "@typescript-eslint/no-unused-vars": [
35
- "error",
36
- {
37
- argsIgnorePattern: "^_",
38
- varsIgnorePattern: "^_",
39
- },
40
- ],
41
- "@typescript-eslint/non-nullable-type-assertion-style": "off",
42
- "@typescript-eslint/prefer-includes": "off",
43
- "@typescript-eslint/triple-slash-reference": "off",
44
- "@typescript-eslint/prefer-string-starts-ends-with": "off",
45
- "@typescript-eslint/restrict-template-expressions": [
46
- "error",
47
- {
48
- allowNumber: true,
49
- allowBoolean: true,
50
- allowAny: false,
51
- allowNullish: false,
52
- },
53
- ],
54
- "@typescript-eslint/unified-signatures": "off",
55
- "@cspell/spellchecker": [
56
- "error",
57
- {
58
- configFile: "./config/cspell.json",
59
- },
60
- ],
61
- },
62
- },
63
- {
64
- files: ["test/**/*.ts"],
65
- ...vitestPlugin.configs.all,
66
- },
67
- {
68
- files: ["test/**/*.ts"],
69
- rules: {
70
- "import-x/no-named-as-default": "off",
71
- "import-x/no-named-as-default-member": "off",
72
- "vitest/no-duplicate-hooks": "off",
73
- "vitest/no-hooks": "off",
74
- "vitest/no-identical-title": "off",
75
- "vitest/prefer-called-times": "off",
76
- "vitest/prefer-describe-function-title": "off",
77
- "vitest/prefer-expect-assertions": "off",
78
- "vitest/prefer-importing-vitest-globals": "off",
79
- "vitest/prefer-lowercase-title": "off",
80
- "vitest/prefer-strict-boolean-matchers": "off",
81
- "vitest/require-hook": "off",
82
- "vitest/require-mock-type-parameters": "off",
83
- },
84
- },
85
- {
86
- files: ["test/**/*.ts"],
87
- ...testingLibraryPlugin.configs["flat/dom"],
88
- },
89
- {
90
- files: ["test/**/*.ts"],
91
- ...jestDomPlugin.configs["flat/recommended"],
92
- },
93
- {
94
- files: ["test/**/*.ts"],
95
- ...jestExtendedPlugin.configs["flat/all"],
96
- },
97
- {
98
- files: ["test/**/*.ts"],
99
- rules: {
100
- "perfectionist/sort-imports": [
101
- "error",
102
- {
103
- internalPattern: ["^app"],
104
- },
105
- ],
106
- },
107
- },
108
- {
109
- files: ["playwright/**/*.ts"],
110
- ...playwrightPlugin.configs["flat/recommended"],
111
- },
112
- ];
package/src/animation.ts DELETED
@@ -1,48 +0,0 @@
1
- export type AnimationSpeed = "fast" | "slow" | number;
2
-
3
- export const getAnimationDuration = (duration: AnimationSpeed): number => {
4
- if (typeof duration === "number") {
5
- return duration;
6
- }
7
-
8
- return duration === "slow" ? 600 : 200;
9
- };
10
-
11
- export const slideDown = (
12
- element: HTMLElement,
13
- animationSpeed: AnimationSpeed,
14
- onFinished: () => void,
15
- ): void => {
16
- element.style.display = "block";
17
-
18
- const animation = element.animate(
19
- [
20
- { height: "0", overflow: "hidden" },
21
- { height: `${element.scrollHeight}px`, overflow: "hidden" },
22
- ],
23
- { duration: getAnimationDuration(animationSpeed) },
24
- );
25
-
26
- animation.onfinish = () => {
27
- onFinished();
28
- };
29
- };
30
-
31
- export const slideUp = (
32
- element: HTMLElement,
33
- animationSpeed: AnimationSpeed,
34
- onFinished: () => void,
35
- ): void => {
36
- const animation = element.animate(
37
- [
38
- { height: `${element.scrollHeight}px`, overflow: "hidden" },
39
- { height: "0", overflow: "hidden" },
40
- ],
41
- { duration: getAnimationDuration(animationSpeed) },
42
- );
43
-
44
- animation.onfinish = () => {
45
- element.style.display = "none";
46
- onFinished();
47
- };
48
- };
package/src/dataLoader.ts DELETED
@@ -1,143 +0,0 @@
1
- import type { LoadData, TriggerEvent } from "./jqtreeMethodTypes";
2
- import type { DataFilter, OnLoadFailed, OnLoading } from "./jqtreeOptions";
3
- import type { Node } from "./node";
4
-
5
- export type HandleFinishedLoading = () => void;
6
-
7
- interface DataLoaderParams {
8
- dataFilter?: DataFilter;
9
- loadData: LoadData;
10
- onLoadFailed?: OnLoadFailed;
11
- onLoading?: OnLoading;
12
- treeElement: HTMLElement;
13
- triggerEvent: TriggerEvent;
14
- }
15
-
16
- export default class DataLoader {
17
- private _dataFilter?: DataFilter;
18
- private _loadData: LoadData;
19
- private _onLoadFailed?: OnLoadFailed;
20
- private _onLoading?: OnLoading;
21
- private _treeElement: HTMLElement;
22
- private _triggerEvent: TriggerEvent;
23
-
24
- constructor({
25
- dataFilter,
26
- loadData,
27
- onLoadFailed,
28
- onLoading,
29
- treeElement,
30
- triggerEvent,
31
- }: DataLoaderParams) {
32
- this._dataFilter = dataFilter;
33
- this._loadData = loadData;
34
- this._onLoadFailed = onLoadFailed;
35
- this._onLoading = onLoading;
36
- this._treeElement = treeElement;
37
- this._triggerEvent = triggerEvent;
38
- }
39
-
40
- public loadFromUrl(
41
- urlInfo: JQuery.AjaxSettings | null | string,
42
- parentNode: Node | null,
43
- onFinished: HandleFinishedLoading | null,
44
- ): void {
45
- if (!urlInfo) {
46
- return;
47
- }
48
-
49
- const element = this._getDomElement(parentNode);
50
- this._addLoadingClass(element);
51
- this._notifyLoading(true, parentNode, element);
52
-
53
- const stopLoading = (): void => {
54
- this._removeLoadingClass(element);
55
- this._notifyLoading(false, parentNode, element);
56
- };
57
-
58
- const handleSuccess = (data: NodeData[]): void => {
59
- stopLoading();
60
- this._loadData(this._parseData(data), parentNode);
61
-
62
- if (onFinished && typeof onFinished === "function") {
63
- onFinished();
64
- }
65
- };
66
-
67
- const handleError = (jqXHR: JQuery.jqXHR): void => {
68
- stopLoading();
69
-
70
- if (this._onLoadFailed) {
71
- this._onLoadFailed(jqXHR);
72
- }
73
- };
74
-
75
- this._submitRequest(urlInfo, handleSuccess, handleError);
76
- }
77
-
78
- private _addLoadingClass(element: HTMLElement): void {
79
- element.classList.add("jqtree-loading");
80
- }
81
-
82
- private _getDomElement(parentNode: Node | null): HTMLElement {
83
- if (parentNode?.element) {
84
- return parentNode.element;
85
- } else {
86
- return this._treeElement;
87
- }
88
- }
89
-
90
- private _notifyLoading(
91
- isLoading: boolean,
92
- node: Node | null,
93
- element: HTMLElement,
94
- ): void {
95
- const $el = jQuery(element);
96
-
97
- if (this._onLoading) {
98
- this._onLoading(isLoading, node, $el);
99
- }
100
-
101
- this._triggerEvent("tree.loading_data", {
102
- $el,
103
- isLoading,
104
- node,
105
- });
106
- }
107
-
108
- private _parseData(data: NodeData[]): NodeData[] {
109
- if (this._dataFilter) {
110
- return this._dataFilter(data);
111
- } else {
112
- return data;
113
- }
114
- }
115
-
116
- private _removeLoadingClass(element: HTMLElement): void {
117
- element.classList.remove("jqtree-loading");
118
- }
119
-
120
- private _submitRequest(
121
- urlInfoInput: JQuery.AjaxSettings | string,
122
- handleSuccess: JQuery.Ajax.SuccessCallback<any>,
123
- handleError: JQuery.Ajax.ErrorCallback<any>,
124
- ): void {
125
- const urlInfo =
126
- typeof urlInfoInput === "string"
127
- ? { url: urlInfoInput }
128
- : urlInfoInput;
129
-
130
- const ajaxSettings: JQuery.AjaxSettings = {
131
- cache: false,
132
- dataType: "json",
133
- error: handleError,
134
- method: "GET",
135
- success: handleSuccess,
136
- ...urlInfo,
137
- };
138
-
139
- ajaxSettings.method = ajaxSettings.method?.toUpperCase() ?? "GET";
140
-
141
- void jQuery.ajax(ajaxSettings);
142
- }
143
- }
@@ -1,27 +0,0 @@
1
- function binarySearch<T>(items: T[], compareFn: (a: T) => number): null | T {
2
- let low = 0;
3
- let high = items.length;
4
-
5
- while (low < high) {
6
- const mid = (low + high) >> 1;
7
- const item = items[mid];
8
-
9
- if (item === undefined) {
10
- return null;
11
- }
12
-
13
- const compareResult = compareFn(item);
14
-
15
- if (compareResult > 0) {
16
- high = mid;
17
- } else if (compareResult < 0) {
18
- low = mid + 1;
19
- } else {
20
- return item;
21
- }
22
- }
23
-
24
- return null;
25
- }
26
-
27
- export default binarySearch;
@@ -1,54 +0,0 @@
1
- interface DragElementParams {
2
- autoEscape: boolean;
3
- nodeName: string;
4
- offsetX: number;
5
- offsetY: number;
6
- treeElement: HTMLElement;
7
- }
8
-
9
- class DragElement {
10
- private _element: HTMLElement;
11
- private _offsetX: number;
12
- private _offsetY: number;
13
-
14
- constructor({
15
- autoEscape,
16
- nodeName,
17
- offsetX,
18
- offsetY,
19
- treeElement,
20
- }: DragElementParams) {
21
- this._offsetX = offsetX;
22
- this._offsetY = offsetY;
23
-
24
- this._element = this._createElement(nodeName, autoEscape);
25
-
26
- treeElement.appendChild(this._element);
27
- }
28
-
29
- public move(pageX: number, pageY: number): void {
30
- this._element.style.left = `${pageX - this._offsetX}px`;
31
- this._element.style.top = `${pageY - this._offsetY}px`;
32
- }
33
-
34
- public remove(): void {
35
- this._element.remove();
36
- }
37
-
38
- private _createElement(nodeName: string, autoEscape: boolean) {
39
- const element = document.createElement("span");
40
- element.classList.add("jqtree-title", "jqtree-dragging");
41
-
42
- if (autoEscape) {
43
- element.textContent = nodeName;
44
- } else {
45
- element.innerHTML = nodeName;
46
- }
47
-
48
- element.style.position = "absolute";
49
-
50
- return element;
51
- }
52
- }
53
-
54
- export default DragElement;
@@ -1,195 +0,0 @@
1
- import type { Node, Position } from "../node";
2
- import type { HitArea } from "./types";
3
-
4
- import { getOffsetTop } from "../positionUtils";
5
- import iterateVisibleNodes from "./iterateVisibleNodes";
6
-
7
- interface HitPosition {
8
- node: Node;
9
- position: null | Position;
10
- top: number;
11
- }
12
-
13
- export const generateHitPositions = (
14
- tree: Node,
15
- currentNode: Node,
16
- ): HitPosition[] => {
17
- const hitPositions: HitPosition[] = [];
18
- let lastTop = 0;
19
-
20
- const addHitPosition = (
21
- node: Node,
22
- position: null | Position,
23
- top: number,
24
- ) => {
25
- hitPositions.push({
26
- node,
27
- position,
28
- top,
29
- });
30
- lastTop = top;
31
- };
32
-
33
- const handleAfterOpenFolder = (node: Node, nextNode: Node | null) => {
34
- if (node === currentNode || nextNode === currentNode) {
35
- // Cannot move before or after current item
36
- addHitPosition(node, null, lastTop);
37
- } else {
38
- addHitPosition(node, "after", lastTop);
39
- }
40
- };
41
-
42
- const handleClosedFolder = (
43
- node: Node,
44
- nextNode: Node | null,
45
- element: HTMLElement,
46
- ) => {
47
- const top = getOffsetTop(element);
48
-
49
- if (node === currentNode) {
50
- // Cannot move after current item
51
- addHitPosition(node, null, top);
52
- } else {
53
- addHitPosition(node, "inside", top);
54
-
55
- // Cannot move before current item
56
- if (nextNode !== currentNode) {
57
- addHitPosition(node, "after", top);
58
- }
59
- }
60
- };
61
-
62
- const handleFirstNode = (node: Node) => {
63
- if (node !== currentNode && node.element) {
64
- addHitPosition(node, "before", getOffsetTop(node.element));
65
- }
66
- };
67
-
68
- const handleNode = (
69
- node: Node,
70
- nextNode: Node | null,
71
- element: HTMLElement,
72
- ) => {
73
- const top = getOffsetTop(element);
74
-
75
- if (node === currentNode) {
76
- // Cannot move inside current item
77
- addHitPosition(node, null, top);
78
- } else {
79
- addHitPosition(node, "inside", top);
80
- }
81
-
82
- if (nextNode === currentNode || node === currentNode) {
83
- // Cannot move before or after current item
84
- addHitPosition(node, null, top);
85
- } else {
86
- addHitPosition(node, "after", top);
87
- }
88
- };
89
-
90
- const handleOpenFolder = (node: Node, element: HTMLElement) => {
91
- if (node === currentNode) {
92
- // Cannot move inside current item
93
-
94
- // Dnd over the current element is not possible: add a position with type None for the top and the bottom.
95
- const top = getOffsetTop(element);
96
- const height = element.clientHeight;
97
- addHitPosition(node, null, top);
98
-
99
- if (height > 5) {
100
- // Subtract 5 pixels to allow more space for the next element.
101
- addHitPosition(node, null, top + height - 5);
102
- }
103
-
104
- // Stop iterating
105
- return false;
106
- }
107
-
108
- // Cannot move before current item
109
- if (node.children[0] !== currentNode) {
110
- addHitPosition(node, "inside", getOffsetTop(element));
111
- }
112
-
113
- // Continue iterating
114
- return true;
115
- };
116
-
117
- iterateVisibleNodes(tree, {
118
- handleAfterOpenFolder,
119
- handleClosedFolder,
120
- handleFirstNode,
121
- handleNode,
122
- handleOpenFolder,
123
- });
124
-
125
- return hitPositions;
126
- };
127
-
128
- export const generateHitAreasForGroup = (
129
- hitAreas: HitArea[],
130
- positionsInGroup: HitPosition[],
131
- top: number,
132
- bottom: number,
133
- ) => {
134
- // limit positions in group
135
- const positionCount = Math.min(positionsInGroup.length, 4);
136
-
137
- const areaHeight = Math.round((bottom - top) / positionCount);
138
- let areaTop = top;
139
-
140
- for (let i = 0; i < positionCount; i++) {
141
- const position = positionsInGroup[i] as HitPosition;
142
-
143
- if (position.position) {
144
- hitAreas.push({
145
- bottom: areaTop + areaHeight,
146
- node: position.node,
147
- position: position.position,
148
- top: areaTop,
149
- });
150
- }
151
-
152
- areaTop += areaHeight;
153
- }
154
- };
155
-
156
- export const generateHitAreasFromPositions = (
157
- hitPositions: HitPosition[],
158
- treeBottom: number,
159
- ): HitArea[] => {
160
- if (!hitPositions.length) {
161
- return [];
162
- }
163
-
164
- let previousTop = (hitPositions[0] as HitPosition).top;
165
- let group: HitPosition[] = [];
166
- const hitAreas: HitArea[] = [];
167
-
168
- for (const position of hitPositions) {
169
- if (position.top !== previousTop && group.length) {
170
- generateHitAreasForGroup(
171
- hitAreas,
172
- group,
173
- previousTop,
174
- position.top,
175
- );
176
-
177
- previousTop = position.top;
178
- group = [];
179
- }
180
-
181
- group.push(position);
182
- }
183
-
184
- generateHitAreasForGroup(hitAreas, group, previousTop, treeBottom);
185
-
186
- return hitAreas;
187
- };
188
-
189
- const generateHitAreas = (tree: Node, currentNode: Node, treeBottom: number) =>
190
- generateHitAreasFromPositions(
191
- generateHitPositions(tree, currentNode),
192
- treeBottom,
193
- );
194
-
195
- export default generateHitAreas;