jqtree 1.7.5 → 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 (90) hide show
  1. package/bower.json +1 -1
  2. package/config/babel.config.json +1 -1
  3. package/config/production +2 -0
  4. package/devserver/devserver_scroll.js +8 -0
  5. package/devserver/test_scroll.html +28 -0
  6. package/devserver/test_scroll_container.html +39 -0
  7. package/docs/_config.yml +1 -1
  8. package/docs/_entries/general/changelog.md +7 -0
  9. package/package.json +5 -1
  10. package/src/dataLoader.ts +44 -19
  11. package/src/dragAndDropHandler/dragElement.ts +42 -0
  12. package/src/dragAndDropHandler/hitAreasGenerator.ts +175 -0
  13. package/src/dragAndDropHandler/index.ts +470 -0
  14. package/src/dragAndDropHandler/types.ts +12 -0
  15. package/src/dragAndDropHandler/visibleNodeIterator.ts +97 -0
  16. package/src/elementsRenderer.ts +75 -40
  17. package/src/jqtreeMethodTypes.ts +40 -0
  18. package/src/jqtreeOptions.ts +43 -25
  19. package/src/keyHandler.ts +59 -30
  20. package/src/mouse.widget.ts +3 -3
  21. package/src/mouseWidgetTypes.ts +6 -0
  22. package/src/nodeElement/borderDropHint.ts +32 -0
  23. package/src/nodeElement/folderElement.ts +133 -0
  24. package/src/nodeElement/ghostDropHint.ts +68 -0
  25. package/src/nodeElement/index.ts +101 -0
  26. package/src/playwright/coverage.ts +1 -4
  27. package/src/playwright/playwright.test.ts +0 -4
  28. package/src/saveStateHandler.ts +75 -26
  29. package/src/scrollHandler.ts +13 -7
  30. package/src/selectNodeHandler.ts +10 -16
  31. package/src/test/jqTree/keyboard.test.ts +18 -23
  32. package/src/test/jqTree/methods.test.ts +32 -3
  33. package/src/test/jqTree/options.test.ts +15 -4
  34. package/src/test/node.test.ts +1 -1
  35. package/src/tree.jquery.ts +239 -57
  36. package/src/util.ts +3 -0
  37. package/src/version.ts +1 -1
  38. package/tree.jquery.debug.js +1728 -2576
  39. package/tree.jquery.debug.js.map +1 -1
  40. package/tree.jquery.js +2 -2
  41. package/tree.jquery.js.map +1 -1
  42. package/lib/dataLoader.js +0 -123
  43. package/lib/dragAndDropHandler.js +0 -588
  44. package/lib/elementsRenderer.js +0 -267
  45. package/lib/jqtreeOptions.js +0 -1
  46. package/lib/keyHandler.js +0 -111
  47. package/lib/mouse.widget.js +0 -255
  48. package/lib/node.js +0 -708
  49. package/lib/nodeElement.js +0 -274
  50. package/lib/nodeUtils.js +0 -10
  51. package/lib/playwright/coverage.js +0 -99
  52. package/lib/playwright/playwright.test.js +0 -606
  53. package/lib/playwright/testUtils.js +0 -210
  54. package/lib/saveStateHandler.js +0 -277
  55. package/lib/scrollHandler/containerScrollParent.js +0 -160
  56. package/lib/scrollHandler/createScrollParent.js +0 -57
  57. package/lib/scrollHandler/documentScrollParent.js +0 -169
  58. package/lib/scrollHandler/scrollParent.js +0 -58
  59. package/lib/scrollHandler/types.js +0 -1
  60. package/lib/scrollHandler.js +0 -71
  61. package/lib/selectNodeHandler.js +0 -128
  62. package/lib/simple.widget.js +0 -158
  63. package/lib/test/global.d.js +0 -3
  64. package/lib/test/jqTree/accessibility.test.js +0 -37
  65. package/lib/test/jqTree/create.test.js +0 -48
  66. package/lib/test/jqTree/events.test.js +0 -210
  67. package/lib/test/jqTree/keyboard.test.js +0 -225
  68. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  69. package/lib/test/jqTree/methods.test.js +0 -1348
  70. package/lib/test/jqTree/options.test.js +0 -548
  71. package/lib/test/jqTree/scrollHandler/containerScrollParent.test.js +0 -94
  72. package/lib/test/node.test.js +0 -1202
  73. package/lib/test/nodeUtil.test.js +0 -27
  74. package/lib/test/nodeUtils.test.js +0 -20
  75. package/lib/test/support/exampleData.js +0 -35
  76. package/lib/test/support/jqTreeMatchers.js +0 -70
  77. package/lib/test/support/matchers.d.js +0 -1
  78. package/lib/test/support/setupTests.js +0 -7
  79. package/lib/test/support/testUtil.js +0 -29
  80. package/lib/test/support/treeStructure.js +0 -38
  81. package/lib/test/util.test.js +0 -26
  82. package/lib/tree.jquery.d.js +0 -1
  83. package/lib/tree.jquery.js +0 -1105
  84. package/lib/types.js +0 -1
  85. package/lib/typings.d.js +0 -2
  86. package/lib/util.js +0 -15
  87. package/lib/version.js +0 -8
  88. package/src/dragAndDropHandler.ts +0 -713
  89. package/src/nodeElement.ts +0 -272
  90. package/src/types.ts +0 -19
package/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jqTree",
3
- "version": "1.7.5",
3
+ "version": "1.8.0",
4
4
  "main": [
5
5
  "jqtree.css",
6
6
  "jqtree-circle.png",
@@ -4,7 +4,7 @@
4
4
  "test": {
5
5
  "presets": [
6
6
  "@babel/preset-typescript",
7
- ["@babel/preset-env", { "targets": { "node": "current" } }]
7
+ "@babel/preset-env"
8
8
  ]
9
9
  }
10
10
  }
package/config/production CHANGED
@@ -1,3 +1,5 @@
1
+ rm -rf ./lib &&
2
+ mkdir lib &&
1
3
  rollup -c config/rollup.config.mjs &&
2
4
  DEBUG_BUILD=true rollup -c config/rollup.config.mjs &&
3
5
  babel src --config-file ./config/babel.config.json --out-dir lib --extensions .ts &&
@@ -0,0 +1,8 @@
1
+ const $tree = $("#tree1");
2
+
3
+ $tree.tree({
4
+ autoOpen: true,
5
+ data: ExampleData.exampleData,
6
+ dragAndDrop: true,
7
+ useContextMenu: false,
8
+ });
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>JqTree devserver</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta
8
+ name="description"
9
+ content="JqTree is a jQuery widget for displaying a tree structure in html"
10
+ />
11
+ <link rel="stylesheet" href="/jqtree.css" />
12
+ <style>
13
+ body {
14
+ font-size: 20px;
15
+ }
16
+ ul.jqtree-tree ul.jqtree_common {
17
+ margin-left: 128px;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <div id="tree1"></div>
23
+ </body>
24
+ <script src="/bower_components/jquery/dist/jquery.min.js"></script>
25
+ <script src="/tree.jquery.js"></script>
26
+ <script src="/example_data.js"></script>
27
+ <script src="/devserver_scroll.js"></script>
28
+ </html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>JqTree devserver</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta
8
+ name="description"
9
+ content="JqTree is a jQuery widget for displaying a tree structure in html"
10
+ />
11
+ <link rel="stylesheet" href="/jqtree.css" />
12
+ <style>
13
+ body {
14
+ font-size: 20px;
15
+ }
16
+ ul.jqtree-tree ul.jqtree_common {
17
+ margin-left: 128px;
18
+ }
19
+ #scroll-container {
20
+ height: 200px;
21
+ width: 400px;
22
+ overflow-y: scroll;
23
+ user-select: none;
24
+ background-color: #eee;
25
+ margin: 128px;
26
+ padding: 8px;
27
+ }
28
+ </style>
29
+ </head>
30
+ <body>
31
+ <div id="scroll-container">
32
+ <div id="tree1"></div>
33
+ </div>
34
+ </body>
35
+ <script src="/bower_components/jquery/dist/jquery.min.js"></script>
36
+ <script src="/tree.jquery.js"></script>
37
+ <script src="/example_data.js"></script>
38
+ <script src="/devserver_scroll.js"></script>
39
+ </html>
package/docs/_config.yml CHANGED
@@ -118,7 +118,7 @@ defaults:
118
118
  values:
119
119
  layout: "example"
120
120
 
121
- jqtree_version: 1.7.5
121
+ jqtree_version: 1.8.0
122
122
 
123
123
  # Build settings
124
124
  markdown: kramdown
@@ -3,6 +3,13 @@ title: Changelog
3
3
  name: changelog
4
4
  ---
5
5
 
6
+ #### 1.8.0 (november 26 2023)
7
+
8
+ This release drops support for very old browsers (like IE 11).
9
+
10
+ - Issue #735: compile to es6. This decreases the file size to 49K (from 62K). This is the minified (not gzipped) version.
11
+ - Issue #766: open parent nodes in the addToSelection method (thanks to Tmgarcia)
12
+
6
13
  #### 1.7.5 (october 21 2023)
7
14
 
8
15
  - Issue #734: fix autoscroll issue (thanks to WriterStat)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jqtree",
3
- "version": "1.7.5",
3
+ "version": "1.8.0",
4
4
  "description": "Tree widget for jQuery",
5
5
  "keywords": [
6
6
  "jquery-plugin",
@@ -28,6 +28,9 @@
28
28
  "playwright": "pnpm build-with-coverage && playwright test --config config/playwright.config.js",
29
29
  "test": "pnpm jest && pnpm playwright"
30
30
  },
31
+ "browserslist": [
32
+ "defaults"
33
+ ],
31
34
  "peerDependencies": {
32
35
  "jquery": "^3"
33
36
  },
@@ -41,6 +44,7 @@
41
44
  "@rollup/plugin-node-resolve": "^15.2.3",
42
45
  "@rollup/plugin-terser": "^0.4.4",
43
46
  "@testing-library/dom": "^9.3.3",
47
+ "@testing-library/user-event": "^14.5.1",
44
48
  "@types/debug": "^4.1.10",
45
49
  "@types/jest": "^29.5.6",
46
50
  "@types/jest-axe": "^3.5.7",
package/src/dataLoader.ts CHANGED
@@ -1,19 +1,46 @@
1
1
  import { Node } from "./node";
2
- import { JqTreeWidget } from "./tree.jquery";
2
+ import { DataFilter, OnLoadFailed, OnLoading } from "./jqtreeOptions";
3
+ import { LoadData, TriggerEvent } from "./jqtreeMethodTypes";
3
4
 
4
5
  export type HandleFinishedLoading = () => void;
5
6
 
6
- export default class DataLoader {
7
- private treeWidget: JqTreeWidget;
7
+ interface DataLoaderParams {
8
+ dataFilter?: DataFilter;
9
+ loadData: LoadData;
10
+ onLoadFailed?: OnLoadFailed;
11
+ onLoading?: OnLoading;
12
+ $treeElement: JQuery<HTMLElement>;
13
+ triggerEvent: TriggerEvent;
14
+ }
8
15
 
9
- constructor(treeWidget: JqTreeWidget) {
10
- this.treeWidget = treeWidget;
16
+ export default class DataLoader {
17
+ private dataFilter?: DataFilter;
18
+ private loadData: LoadData;
19
+ private onLoadFailed?: OnLoadFailed;
20
+ private onLoading?: OnLoading;
21
+ private $treeElement: JQuery<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;
11
38
  }
12
39
 
13
40
  public loadFromUrl(
14
41
  urlInfo: string | JQuery.AjaxSettings | null,
15
42
  parentNode: Node | null,
16
- onFinished: HandleFinishedLoading | null
43
+ onFinished: HandleFinishedLoading | null,
17
44
  ): void {
18
45
  if (!urlInfo) {
19
46
  return;
@@ -30,7 +57,7 @@ export default class DataLoader {
30
57
 
31
58
  const handleSuccess = (data: string | NodeData[]): void => {
32
59
  stopLoading();
33
- this.treeWidget.loadData(this.parseData(data), parentNode);
60
+ this.loadData(this.parseData(data), parentNode);
34
61
 
35
62
  if (onFinished && typeof onFinished === "function") {
36
63
  onFinished();
@@ -40,8 +67,8 @@ export default class DataLoader {
40
67
  const handleError = (jqXHR: JQuery.jqXHR): void => {
41
68
  stopLoading();
42
69
 
43
- if (this.treeWidget.options.onLoadFailed) {
44
- this.treeWidget.options.onLoadFailed(jqXHR);
70
+ if (this.onLoadFailed) {
71
+ this.onLoadFailed(jqXHR);
45
72
  }
46
73
  };
47
74
 
@@ -64,20 +91,20 @@ export default class DataLoader {
64
91
  if (parentNode) {
65
92
  return jQuery(parentNode.element);
66
93
  } else {
67
- return this.treeWidget.element;
94
+ return this.$treeElement;
68
95
  }
69
96
  }
70
97
 
71
98
  private notifyLoading(
72
99
  isLoading: boolean,
73
100
  node: Node | null,
74
- $el: JQuery
101
+ $el: JQuery,
75
102
  ): void {
76
- if (this.treeWidget.options.onLoading) {
77
- this.treeWidget.options.onLoading(isLoading, node, $el);
103
+ if (this.onLoading) {
104
+ this.onLoading(isLoading, node, $el);
78
105
  }
79
106
 
80
- this.treeWidget._triggerEvent("tree.loading_data", {
107
+ this.triggerEvent("tree.loading_data", {
81
108
  isLoading,
82
109
  node,
83
110
  $el,
@@ -87,7 +114,7 @@ export default class DataLoader {
87
114
  private submitRequest(
88
115
  urlInfoInput: string | JQuery.AjaxSettings,
89
116
  handleSuccess: JQuery.Ajax.SuccessCallback<any>,
90
- handleError: JQuery.Ajax.ErrorCallback<any>
117
+ handleError: JQuery.Ajax.ErrorCallback<any>,
91
118
  ): void {
92
119
  const urlInfo =
93
120
  typeof urlInfoInput === "string"
@@ -109,8 +136,6 @@ export default class DataLoader {
109
136
  }
110
137
 
111
138
  private parseData(data: string | NodeData[]): NodeData[] {
112
- const { dataFilter } = this.treeWidget.options;
113
-
114
139
  const getParsedData = () => {
115
140
  if (typeof data === "string") {
116
141
  return JSON.parse(data) as NodeData[];
@@ -121,8 +146,8 @@ export default class DataLoader {
121
146
 
122
147
  const parsedData = getParsedData();
123
148
 
124
- if (dataFilter) {
125
- return dataFilter(parsedData);
149
+ if (this.dataFilter) {
150
+ return this.dataFilter(parsedData);
126
151
  } else {
127
152
  return parsedData;
128
153
  }
@@ -0,0 +1,42 @@
1
+ class DragElement {
2
+ private offsetX: number;
3
+ private offsetY: number;
4
+ private $element: JQuery;
5
+
6
+ constructor(
7
+ nodeName: string,
8
+ offsetX: number,
9
+ offsetY: number,
10
+ $tree: JQuery,
11
+ autoEscape: boolean,
12
+ ) {
13
+ this.offsetX = offsetX;
14
+ this.offsetY = offsetY;
15
+
16
+ this.$element = jQuery("<span>").addClass(
17
+ "jqtree-title jqtree-dragging",
18
+ );
19
+
20
+ if (autoEscape) {
21
+ this.$element.text(nodeName);
22
+ } else {
23
+ this.$element.html(nodeName);
24
+ }
25
+
26
+ this.$element.css("position", "absolute");
27
+ $tree.append(this.$element);
28
+ }
29
+
30
+ public move(pageX: number, pageY: number): void {
31
+ this.$element.offset({
32
+ left: pageX - this.offsetX,
33
+ top: pageY - this.offsetY,
34
+ });
35
+ }
36
+
37
+ public remove(): void {
38
+ this.$element.remove();
39
+ }
40
+ }
41
+
42
+ export default DragElement;
@@ -0,0 +1,175 @@
1
+ import { HitArea } from "./types";
2
+ import { Node, Position } from "../node";
3
+ import { getOffsetTop } from "../util";
4
+ import VisibleNodeIterator from "./visibleNodeIterator";
5
+
6
+ class HitAreasGenerator extends VisibleNodeIterator {
7
+ private currentNode: Node;
8
+ private treeBottom: number;
9
+ private positions: HitArea[];
10
+ private lastTop: number;
11
+
12
+ constructor(tree: Node, currentNode: Node, treeBottom: number) {
13
+ super(tree);
14
+
15
+ this.currentNode = currentNode;
16
+ this.treeBottom = treeBottom;
17
+ }
18
+
19
+ public generate(): HitArea[] {
20
+ this.positions = [];
21
+ this.lastTop = 0;
22
+
23
+ this.iterate();
24
+
25
+ return this.generateHitAreas(this.positions);
26
+ }
27
+
28
+ protected generateHitAreas(positions: HitArea[]): HitArea[] {
29
+ let previousTop = positions[0]?.top ?? 0;
30
+ let group = [];
31
+ const hitAreas: HitArea[] = [];
32
+
33
+ for (const position of positions) {
34
+ if (position.top !== previousTop && group.length) {
35
+ this.generateHitAreasForGroup(
36
+ hitAreas,
37
+ group,
38
+ previousTop,
39
+ position.top,
40
+ );
41
+
42
+ previousTop = position.top;
43
+ group = [];
44
+ }
45
+
46
+ group.push(position);
47
+ }
48
+
49
+ this.generateHitAreasForGroup(
50
+ hitAreas,
51
+ group,
52
+ previousTop,
53
+ this.treeBottom,
54
+ );
55
+
56
+ return hitAreas;
57
+ }
58
+
59
+ protected handleOpenFolder(node: Node, element: HTMLElement): boolean {
60
+ if (node === this.currentNode) {
61
+ // Cannot move inside current item
62
+ // Stop iterating
63
+ return false;
64
+ }
65
+
66
+ // Cannot move before current item
67
+ if (node.children[0] !== this.currentNode) {
68
+ this.addPosition(node, Position.Inside, getOffsetTop(element));
69
+ }
70
+
71
+ // Continue iterating
72
+ return true;
73
+ }
74
+
75
+ protected handleClosedFolder(
76
+ node: Node,
77
+ nextNode: Node,
78
+ element: HTMLElement,
79
+ ): void {
80
+ const top = getOffsetTop(element);
81
+
82
+ if (node === this.currentNode) {
83
+ // Cannot move after current item
84
+ this.addPosition(node, Position.None, top);
85
+ } else {
86
+ this.addPosition(node, Position.Inside, top);
87
+
88
+ // Cannot move before current item
89
+ if (nextNode !== this.currentNode) {
90
+ this.addPosition(node, Position.After, top);
91
+ }
92
+ }
93
+ }
94
+
95
+ protected handleFirstNode(node: Node): void {
96
+ if (node !== this.currentNode) {
97
+ this.addPosition(node, Position.Before, getOffsetTop(node.element));
98
+ }
99
+ }
100
+
101
+ protected handleAfterOpenFolder(node: Node, nextNode: Node): void {
102
+ if (node === this.currentNode || nextNode === this.currentNode) {
103
+ // Cannot move before or after current item
104
+ this.addPosition(node, Position.None, this.lastTop);
105
+ } else {
106
+ this.addPosition(node, Position.After, this.lastTop);
107
+ }
108
+ }
109
+
110
+ protected handleNode(
111
+ node: Node,
112
+ nextNode: Node,
113
+ element: HTMLElement,
114
+ ): void {
115
+ const top = getOffsetTop(element);
116
+
117
+ if (node === this.currentNode) {
118
+ // Cannot move inside current item
119
+ this.addPosition(node, Position.None, top);
120
+ } else {
121
+ this.addPosition(node, Position.Inside, top);
122
+ }
123
+
124
+ if (nextNode === this.currentNode || node === this.currentNode) {
125
+ // Cannot move before or after current item
126
+ this.addPosition(node, Position.None, top);
127
+ } else {
128
+ this.addPosition(node, Position.After, top);
129
+ }
130
+ }
131
+
132
+ private addPosition(node: Node, position: number, top: number): void {
133
+ const area = {
134
+ top,
135
+ bottom: 0,
136
+ node,
137
+ position,
138
+ };
139
+
140
+ this.positions.push(area);
141
+ this.lastTop = top;
142
+ }
143
+
144
+ private generateHitAreasForGroup(
145
+ hitAreas: HitArea[],
146
+ positionsInGroup: HitArea[],
147
+ top: number,
148
+ bottom: number,
149
+ ): void {
150
+ // limit positions in group
151
+ const positionCount = Math.min(positionsInGroup.length, 4);
152
+
153
+ const areaHeight = Math.round((bottom - top) / positionCount);
154
+ let areaTop = top;
155
+
156
+ let i = 0;
157
+ while (i < positionCount) {
158
+ const position = positionsInGroup[i];
159
+
160
+ if (position) {
161
+ hitAreas.push({
162
+ top: areaTop,
163
+ bottom: areaTop + areaHeight,
164
+ node: position.node,
165
+ position: position.position,
166
+ });
167
+ }
168
+
169
+ areaTop += areaHeight;
170
+ i += 1;
171
+ }
172
+ }
173
+ }
174
+
175
+ export default HitAreasGenerator;