jqtree 1.9.1 → 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.
- package/bower.json +1 -1
- package/js-coverage/coverage-final.json +13 -0
- package/lib/jqtreeOptions.js +1 -0
- package/lib/tree.jquery.d.js +0 -0
- package/lib/tree.jquery.js +394 -0
- package/lib/triggerJQueryEvent.js +68 -0
- package/lib/typings.d.js +1 -0
- package/lib/version.js +2 -0
- package/package.json +20 -15
- package/pnpm-workspace.yaml +0 -1
- package/src/jqtreeOptions.ts +20 -62
- package/src/tree.jquery.d.ts +80 -92
- package/src/tree.jquery.ts +157 -967
- package/src/triggerJQueryEvent.ts +97 -0
- package/src/version.ts +2 -2
- package/tree.jquery.debug.js +4209 -3246
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +22 -2
- package/tree.jquery.js.map +1 -1
- package/src/animation.ts +0 -48
- package/src/dataLoader.ts +0 -143
- package/src/dragAndDropHandler/binarySearch.ts +0 -27
- package/src/dragAndDropHandler/dragElement.ts +0 -54
- package/src/dragAndDropHandler/generateHitAreas.ts +0 -195
- package/src/dragAndDropHandler/index.ts +0 -432
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +0 -91
- package/src/dragAndDropHandler/types.ts +0 -12
- package/src/elementsRenderer.ts +0 -359
- package/src/jqtreeMethodTypes.ts +0 -40
- package/src/keyHandler.ts +0 -139
- package/src/mouseHandler.ts +0 -383
- package/src/mouseUtils.ts +0 -23
- package/src/node.ts +0 -653
- package/src/nodeElement/borderDropHint.ts +0 -32
- package/src/nodeElement/folderElement.ts +0 -138
- package/src/nodeElement/ghostDropHint.ts +0 -74
- package/src/nodeElement/index.ts +0 -94
- package/src/nodeUtils.ts +0 -10
- package/src/positionUtils.ts +0 -18
- package/src/saveStateHandler.ts +0 -276
- package/src/scrollHandler/containerScrollParent.ts +0 -71
- package/src/scrollHandler/createScrollParent.ts +0 -51
- package/src/scrollHandler/documentScrollParent.ts +0 -104
- package/src/scrollHandler/scrollParent.ts +0 -117
- package/src/scrollHandler.ts +0 -55
- package/src/selectNodeHandler.ts +0 -111
- package/src/util.ts +0 -5
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;
|