wunderbaum 0.13.0 → 0.14.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/LICENSE +1 -1
- package/dist/wunderbaum.css +31 -11
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +535 -296
- package/dist/wunderbaum.esm.js +619 -221
- package/dist/wunderbaum.esm.min.js +28 -28
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +619 -221
- package/dist/wunderbaum.umd.min.js +32 -32
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +3 -2
- package/src/common.ts +23 -4
- package/src/types.ts +86 -40
- package/src/util.ts +75 -2
- package/src/wb_ext_dnd.ts +21 -20
- package/src/wb_ext_edit.ts +1 -1
- package/src/wb_ext_filter.ts +6 -2
- package/src/wb_ext_grid.ts +1 -1
- package/src/wb_extension_base.ts +16 -1
- package/src/wb_node.ts +222 -106
- package/src/wb_options.ts +169 -108
- package/src/wunderbaum.ts +351 -127
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wunderbaum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"title": "A treegrid control.",
|
|
5
5
|
"description": "JavaScript tree/grid/treegrid control.",
|
|
6
6
|
"homepage": "https://github.com/mar10/wunderbaum",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@rollup/plugin-replace": "^6.0.2",
|
|
53
53
|
"@rollup/plugin-terser": "^0.4.4",
|
|
54
54
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
55
|
+
"@types/firebase": "^2.4.32",
|
|
55
56
|
"@types/jest": "^29.5.14",
|
|
56
57
|
"@typescript-eslint/eslint-plugin": "^8.24.0",
|
|
57
58
|
"@typescript-eslint/parser": "^8.24.0",
|
|
@@ -104,7 +105,7 @@
|
|
|
104
105
|
"scripts": {
|
|
105
106
|
"test": "npm run lint && npm run build:js && grunt ci --verbose",
|
|
106
107
|
"api_docs": "typedoc && touch docs/api/.nojekyll && rm docs/unittest/*.*; cp test/unit/*.* docs/unittest",
|
|
107
|
-
"format": "eslint src --fix && prettier src docs/demo -w && npm run lint",
|
|
108
|
+
"format": "eslint src docs/demo --fix && prettier src docs/demo -w && npm run lint",
|
|
108
109
|
"lint": "prettier src docs/demo --check && eslint src docs/demo && tsc -t esnext --moduleResolution node --noEmit src/wunderbaum.ts",
|
|
109
110
|
"build:minjs:umd": "terser build/wunderbaum.umd.js --compress --mangle --source-map \"base='build',url='wunderbaum.umd.min.js.map',filename='wunderbaum.umd.js'\" --output build/wunderbaum.umd.min.js",
|
|
110
111
|
"build:minjs:esm": "terser build/wunderbaum.esm.js --compress --mangle --source-map \"base='build',url='wunderbaum.esm.min.js.map',filename='wunderbaum.esm.js'\" --output build/wunderbaum.esm.min.js",
|
package/src/common.ts
CHANGED
|
@@ -35,13 +35,23 @@ export const RENDER_MAX_PREFETCH = 5;
|
|
|
35
35
|
export const RENDER_MIN_PREFETCH = 5;
|
|
36
36
|
/** Minimum column width if not set otherwise. */
|
|
37
37
|
export const DEFAULT_MIN_COL_WIDTH = 4;
|
|
38
|
+
/**
|
|
39
|
+
* A value for `node.type` that by convention may be used to mark a node as directory.
|
|
40
|
+
* It may be used to sort 'directories' to the top.
|
|
41
|
+
*/
|
|
42
|
+
export const NODE_TYPE_FOLDER = "folder";
|
|
38
43
|
/** Regular expression to detect if a string describes an image URL (in contrast
|
|
39
44
|
* to a class name). Strings are considered image urls if they contain '.' or '/'.
|
|
45
|
+
* `<` is ignored, because it is probably an html tag.
|
|
40
46
|
*/
|
|
41
|
-
export const
|
|
47
|
+
export const TEST_FILE_PATH = /^(?!.*<).*[/.]/;
|
|
48
|
+
/** Regular expression to detect if a string describes an HTML element. */
|
|
49
|
+
export const TEST_HTML = /</;
|
|
42
50
|
// export const RECURSIVE_REQUEST_ERROR = "$recursive_request";
|
|
43
51
|
// export const INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid";
|
|
44
52
|
|
|
53
|
+
/** Currently supported default icon maps. */
|
|
54
|
+
type IconLibrary = "bootstrap" | "fontawesome6";
|
|
45
55
|
/**
|
|
46
56
|
* Default node icons for icon libraries
|
|
47
57
|
*
|
|
@@ -49,7 +59,7 @@ export const TEST_IMG = new RegExp(/\.|\//);
|
|
|
49
59
|
* - 'fontawesome6' {@link https://fontawesome.com/icons}
|
|
50
60
|
*
|
|
51
61
|
*/
|
|
52
|
-
export const
|
|
62
|
+
export const defaultIconMaps: { [key in IconLibrary]: IconMapType } = {
|
|
53
63
|
bootstrap: {
|
|
54
64
|
error: "bi bi-exclamation-triangle",
|
|
55
65
|
// loading: "bi bi-hourglass-split wb-busy",
|
|
@@ -97,7 +107,7 @@ export const iconMaps: { [key: string]: IconMapType } = {
|
|
|
97
107
|
radioChecked: "fa-solid fa-circle",
|
|
98
108
|
radioUnchecked: "fa-regular fa-circle",
|
|
99
109
|
radioUnknown: "fa-regular fa-circle-question",
|
|
100
|
-
folder: "fa-
|
|
110
|
+
folder: "fa-regular fa-folder-closed",
|
|
101
111
|
folderOpen: "fa-regular fa-folder-open",
|
|
102
112
|
folderLazy: "fa-solid fa-folder-plus",
|
|
103
113
|
doc: "fa-regular fa-file",
|
|
@@ -221,7 +231,9 @@ export function makeNodeTitleStartMatcher(s: string): MatcherCallback {
|
|
|
221
231
|
};
|
|
222
232
|
}
|
|
223
233
|
|
|
224
|
-
/** Compare two nodes by title (case-insensitive).
|
|
234
|
+
/** Compare two nodes by title (case-insensitive).
|
|
235
|
+
* @deprecated Use `key` option instead of `cmp` in sort methods.
|
|
236
|
+
*/
|
|
225
237
|
export function nodeTitleSorter(a: WunderbaumNode, b: WunderbaumNode): number {
|
|
226
238
|
const x = a.title.toLowerCase();
|
|
227
239
|
const y = b.title.toLowerCase();
|
|
@@ -229,6 +241,13 @@ export function nodeTitleSorter(a: WunderbaumNode, b: WunderbaumNode): number {
|
|
|
229
241
|
return x === y ? 0 : x > y ? 1 : -1;
|
|
230
242
|
}
|
|
231
243
|
|
|
244
|
+
// /** Compare nodes by title (case-insensitive). */
|
|
245
|
+
// export function nodeTitleKeyGetter(
|
|
246
|
+
// node: WunderbaumNode
|
|
247
|
+
// ): string | number | Array<any> {
|
|
248
|
+
// return node.title.toLowerCase();
|
|
249
|
+
// }
|
|
250
|
+
|
|
232
251
|
/**
|
|
233
252
|
* Convert 'flat' to 'nested' format.
|
|
234
253
|
*
|
package/src/types.ts
CHANGED
|
@@ -60,8 +60,13 @@ export type MatcherCallback = (node: WunderbaumNode) => boolean;
|
|
|
60
60
|
export type WbIconBadgeCallback = (
|
|
61
61
|
e: WbIconBadgeEventType
|
|
62
62
|
) => WbIconBadgeEventResultType;
|
|
63
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* Passed to `sort()` methods. Should return -1, 0, or 1.
|
|
65
|
+
* @deprecated Use SortKeyCallback instead
|
|
66
|
+
*/
|
|
64
67
|
export type SortCallback = (a: WunderbaumNode, b: WunderbaumNode) => number;
|
|
68
|
+
/** Passed to `sort()` methods. Should return a representation that can be compared using `<`. */
|
|
69
|
+
export type SortKeyCallback = (node: WunderbaumNode) => string | number | any[];
|
|
65
70
|
/** When set as option, called when the value is needed (e.g. `colspan` type definition). */
|
|
66
71
|
export type BoolOptionResolver = (node: WunderbaumNode) => boolean;
|
|
67
72
|
/** When set as option, called when the value is needed (e.g. `icon` type definition). */
|
|
@@ -99,6 +104,12 @@ export type NodeToDictCallback = (
|
|
|
99
104
|
*/
|
|
100
105
|
export type NodeSelectCallback = (node: WunderbaumNode) => boolean | void;
|
|
101
106
|
|
|
107
|
+
/** @internal */
|
|
108
|
+
export type DeprecationOptions = {
|
|
109
|
+
since?: string;
|
|
110
|
+
hint?: string;
|
|
111
|
+
};
|
|
112
|
+
|
|
102
113
|
/**
|
|
103
114
|
* See also {@link WunderbaumNode.getOption|WunderbaumNode.getOption()}
|
|
104
115
|
* to evaluate `node.NAME` setting and `tree.types[node.type].NAME`.
|
|
@@ -163,7 +174,7 @@ export interface WbNodeData {
|
|
|
163
174
|
title: string;
|
|
164
175
|
/** Pass true to set node tooltip to the node's title. Defaults to {@link WunderbaumOptions.tooltip}. */
|
|
165
176
|
tooltip?: TooltipOption;
|
|
166
|
-
/** Inherit shared settings from the matching entry in
|
|
177
|
+
/** Inherit shared settings from the matching entry in `InitWunderbaumOptions.types`. */
|
|
167
178
|
type?: string;
|
|
168
179
|
/** Set to `true` to prevent selection. Defaults to {@link WunderbaumOptions.unselectable}. */
|
|
169
180
|
unselectable?: boolean;
|
|
@@ -203,7 +214,7 @@ export interface IconMapType {
|
|
|
203
214
|
* EVENT CALLBACK TYPES
|
|
204
215
|
* ---------------------------------------------------------------------------*/
|
|
205
216
|
|
|
206
|
-
/**
|
|
217
|
+
/** Retuen value of an event handler that can return `false` to prevent the default action. */
|
|
207
218
|
export type WbCancelableEventResultType = false | void;
|
|
208
219
|
|
|
209
220
|
export interface WbTreeEventType {
|
|
@@ -497,21 +508,6 @@ export interface ColumnDefinition {
|
|
|
497
508
|
|
|
498
509
|
export type ColumnDefinitionList = Array<ColumnDefinition>;
|
|
499
510
|
|
|
500
|
-
/**
|
|
501
|
-
* Used by {@link Wunderbaum.getState} and {@link Wunderbaum.setState}.
|
|
502
|
-
*/
|
|
503
|
-
export interface TreeStateDefinition {
|
|
504
|
-
/** The active node's key if any. */
|
|
505
|
-
activeKey: string | null;
|
|
506
|
-
/** The active column index if any. */
|
|
507
|
-
activeColIdx: number | null;
|
|
508
|
-
/** List of selected node's keys. */
|
|
509
|
-
selectedKeys: Array<string> | undefined;
|
|
510
|
-
/** List of expanded node's keys. */
|
|
511
|
-
expandedKeys: Array<string> | undefined;
|
|
512
|
-
/** List of checked node's keys. */
|
|
513
|
-
}
|
|
514
|
-
|
|
515
511
|
/**
|
|
516
512
|
* Column information (passed to the `render` event).
|
|
517
513
|
*/
|
|
@@ -753,8 +749,7 @@ export interface FilterNodesOptions {
|
|
|
753
749
|
/**Hide expanders if all child nodes are hidden by filter @default false */
|
|
754
750
|
hideExpanders?: boolean;
|
|
755
751
|
/** Highlight matches by wrapping inside `<mark>` tags.
|
|
756
|
-
* Does not work for filter callbacks.
|
|
757
|
-
* @default true
|
|
752
|
+
* Does not work for filter callbacks. @default true
|
|
758
753
|
*/
|
|
759
754
|
highlight?: boolean;
|
|
760
755
|
/** Match end nodes only @default false */
|
|
@@ -767,11 +762,11 @@ export interface FilterNodesOptions {
|
|
|
767
762
|
|
|
768
763
|
/** Possible values for {@link Wunderbaum.getState}. */
|
|
769
764
|
export interface GetStateOptions {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
/** Include the expanded keys. @default
|
|
765
|
+
/** Include the active node's key (and expand its parents). @default true */
|
|
766
|
+
activeKey?: boolean;
|
|
767
|
+
/** Include the expanded keys. @default false */
|
|
773
768
|
expandedKeys?: boolean;
|
|
774
|
-
/** Include the selected keys. @default
|
|
769
|
+
/** Include the selected keys. @default false */
|
|
775
770
|
selectedKeys?: boolean;
|
|
776
771
|
}
|
|
777
772
|
|
|
@@ -781,6 +776,28 @@ export interface SetStateOptions {
|
|
|
781
776
|
expandLazy?: boolean;
|
|
782
777
|
}
|
|
783
778
|
|
|
779
|
+
/** Used by {@link Wunderbaum.getState} and {@link Wunderbaum.setState}. */
|
|
780
|
+
export interface TreeStateDefinition {
|
|
781
|
+
/** List of expanded node's keys. */
|
|
782
|
+
expandedKeys: Array<string> | undefined;
|
|
783
|
+
/** The active node's key if any. */
|
|
784
|
+
activeKey: string | null;
|
|
785
|
+
/** The active column index if any. */
|
|
786
|
+
activeColIdx: number | null;
|
|
787
|
+
/** List of selected node's keys. */
|
|
788
|
+
selectedKeys: Array<string> | undefined;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/** Possible values for {@link Wunderbaum.loadLazyNodes} `options` argument. */
|
|
792
|
+
export interface LoadLazyNodesOptions {
|
|
793
|
+
/** Expand node (otherwise load, but keep collapsed). @default true */
|
|
794
|
+
expand?: boolean;
|
|
795
|
+
/** Force reloading even if already loaded. @default false */
|
|
796
|
+
force?: boolean;
|
|
797
|
+
/** Do not send events. @default false */
|
|
798
|
+
noEvents?: boolean;
|
|
799
|
+
}
|
|
800
|
+
|
|
784
801
|
/** Possible values for {@link WunderbaumNode.makeVisible}. */
|
|
785
802
|
export interface MakeVisibleOptions {
|
|
786
803
|
/** Do not animate expand (currently not implemented). @default false */
|
|
@@ -918,7 +935,17 @@ export interface SetStatusOptions {
|
|
|
918
935
|
}
|
|
919
936
|
|
|
920
937
|
/**
|
|
921
|
-
* Possible values for {@link
|
|
938
|
+
* Possible values for {@link Wunderbaum.reload} `options` argument.
|
|
939
|
+
*/
|
|
940
|
+
export interface ReloadOptions {
|
|
941
|
+
/** Load this source instead. @default initial source (if loaded via ajax) */
|
|
942
|
+
source?: SourceType;
|
|
943
|
+
/** Reactivate currently active node if any. @default true */
|
|
944
|
+
reactivate?: boolean;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Possible values for {@link WunderbaumNode.resetNativeChildOrder} `options` argument.
|
|
922
949
|
*/
|
|
923
950
|
export interface ResetOrderOptions {
|
|
924
951
|
/** Sort descendants recursively. @default true */
|
|
@@ -930,31 +957,37 @@ export interface ResetOrderOptions {
|
|
|
930
957
|
}
|
|
931
958
|
|
|
932
959
|
/**
|
|
933
|
-
* Possible values for {@link
|
|
960
|
+
* Possible values for {@link Wunderbaum.sort} and {@link WunderbaumNode.sort}
|
|
961
|
+
* `options` argument.
|
|
934
962
|
*/
|
|
935
|
-
export interface
|
|
936
|
-
/** Column ID as defined in `tree.columns` definition. Required if updateColInfo is true.*/
|
|
937
|
-
colId?: string;
|
|
963
|
+
export interface SortOptions {
|
|
938
964
|
/** The name of the node property that will be used for sorting.
|
|
939
|
-
* @
|
|
965
|
+
* Mandatory, unless {@link key} or {@link colId} are given.
|
|
940
966
|
*/
|
|
941
967
|
propName?: string;
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
968
|
+
/** Callback that determines a node representation for comparison.
|
|
969
|
+
* @default {@link common.nodeTitleKeyGetter} */
|
|
970
|
+
key?: SortKeyCallback;
|
|
971
|
+
/** Callback that determines the order. @default {@link common.nodeTitleSorter}
|
|
972
|
+
* @deprecated use {@link key} instead
|
|
973
|
+
*/
|
|
974
|
+
cmp?: SortCallback;
|
|
975
|
+
/** Sort order 'asc' or 'desc'.
|
|
976
|
+
* @default 'asc' (or if `updateColInfo` is true, the rotated status of the
|
|
977
|
+
* column definition.
|
|
978
|
+
* See also {@link WunderbaumOptions.sortFoldersFirst}.
|
|
979
|
+
*/
|
|
945
980
|
order?: SortOrderType;
|
|
981
|
+
/** Sort descendants recursively. @default true */
|
|
982
|
+
deep?: boolean;
|
|
983
|
+
/** Sort string values case insensitive. @default false */
|
|
984
|
+
caseInsensitive?: boolean;
|
|
946
985
|
/**
|
|
947
986
|
* Sort by this property if order is `undefined`.
|
|
948
987
|
* See also {@link WunderbaumNode.resetNativeChildOrder}.
|
|
949
988
|
* @default `_nativeIndex`.
|
|
950
989
|
*/
|
|
951
990
|
nativeOrderPropName?: string;
|
|
952
|
-
/** Sort string values case insensitive. @default false */
|
|
953
|
-
caseInsensitive?: boolean;
|
|
954
|
-
/** Sort descendants recursively. @default true */
|
|
955
|
-
deep?: boolean;
|
|
956
|
-
// /** Rotate sort order (asc -> desc -> none) before sorting. @default false */
|
|
957
|
-
// rotateOrder?: boolean;
|
|
958
991
|
/**
|
|
959
992
|
* Rotate sort order (asc -> desc -> none) before sorting.
|
|
960
993
|
* Update the sort icons in the column header
|
|
@@ -965,8 +998,16 @@ export interface SortByPropertyOptions {
|
|
|
965
998
|
* @default false
|
|
966
999
|
*/
|
|
967
1000
|
updateColInfo?: boolean;
|
|
1001
|
+
/** Column ID as defined in `tree.columns` definition. Required if updateColInfo is true.*/
|
|
1002
|
+
colId?: string;
|
|
968
1003
|
}
|
|
969
1004
|
|
|
1005
|
+
/**
|
|
1006
|
+
* Possible values for {@link WunderbaumNode.sortByProperty} `options` argument.
|
|
1007
|
+
* @deprecated
|
|
1008
|
+
*/
|
|
1009
|
+
export type SortByPropertyOptions = SortOptions;
|
|
1010
|
+
|
|
970
1011
|
/** Options passed to {@link Wunderbaum.visitRows}. */
|
|
971
1012
|
export interface VisitRowsOptions {
|
|
972
1013
|
/** Skip filtered nodes and children of collapsed nodes. @default false */
|
|
@@ -1122,6 +1163,7 @@ export type DropEffectAllowedType =
|
|
|
1122
1163
|
|
|
1123
1164
|
export type DropRegionType = "over" | "before" | "after";
|
|
1124
1165
|
export type DropRegionTypeSet = Set<DropRegionType>;
|
|
1166
|
+
export type DropRegionTypeList = Array<DropRegionType>;
|
|
1125
1167
|
// type AllowedDropRegionType =
|
|
1126
1168
|
// | "after"
|
|
1127
1169
|
// | "afterBefore"
|
|
@@ -1147,6 +1189,8 @@ export interface DropEventType extends WbNodeEventType {
|
|
|
1147
1189
|
node: WunderbaumNode;
|
|
1148
1190
|
/** The source node if any. */
|
|
1149
1191
|
sourceNode: WunderbaumNode;
|
|
1192
|
+
/** The DataTransfer object. */
|
|
1193
|
+
dataTransfer: DataTransfer;
|
|
1150
1194
|
}
|
|
1151
1195
|
|
|
1152
1196
|
export type DndOptionsType = {
|
|
@@ -1292,7 +1336,9 @@ export type DndOptionsType = {
|
|
|
1292
1336
|
*/
|
|
1293
1337
|
dragEnter?:
|
|
1294
1338
|
| null
|
|
1295
|
-
| ((
|
|
1339
|
+
| ((
|
|
1340
|
+
e: DropEventType
|
|
1341
|
+
) => DropRegionType | DropRegionTypeSet | DropRegionTypeList | boolean);
|
|
1296
1342
|
/**
|
|
1297
1343
|
* Callback(targetNode, data)
|
|
1298
1344
|
* @default null
|
package/src/util.ts
CHANGED
|
@@ -36,6 +36,8 @@ const ENTITY_MAP: { [key: string]: string } = {
|
|
|
36
36
|
"/": "/",
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
export type NotPromise<T> = T extends Promise<any> ? never : T;
|
|
40
|
+
|
|
39
41
|
export type FunctionType = (...args: any[]) => any;
|
|
40
42
|
export type EventCallbackType = (e: Event) => boolean | void;
|
|
41
43
|
type PromiseCallbackType = (val: any) => void;
|
|
@@ -175,7 +177,7 @@ export function each(
|
|
|
175
177
|
return obj;
|
|
176
178
|
}
|
|
177
179
|
|
|
178
|
-
/** Shortcut for `throw new Error(msg)
|
|
180
|
+
/** Shortcut for `throw new Error(msg)`. */
|
|
179
181
|
export function error(msg: string) {
|
|
180
182
|
throw new Error(msg);
|
|
181
183
|
}
|
|
@@ -783,6 +785,11 @@ export function toPixel(
|
|
|
783
785
|
throw new Error(`Expected a string like '123px': ${defaults}`);
|
|
784
786
|
}
|
|
785
787
|
|
|
788
|
+
/** Cast any value to <T>. */
|
|
789
|
+
export function unsafeCast<T>(value: any): T {
|
|
790
|
+
return value as T;
|
|
791
|
+
}
|
|
792
|
+
|
|
786
793
|
/** Return the the boolean value of the first non-null element.
|
|
787
794
|
* Example:
|
|
788
795
|
* ```js
|
|
@@ -874,7 +881,7 @@ export function adaptiveThrottle(
|
|
|
874
881
|
const throttledFn = (...args: any[]) => {
|
|
875
882
|
if (waiting) {
|
|
876
883
|
pendingArgs = args;
|
|
877
|
-
// console.log(`adaptiveThrottle()
|
|
884
|
+
// console.log(`adaptiveThrottle() queueing request #${waiting}...`, args);
|
|
878
885
|
waiting += 1;
|
|
879
886
|
} else {
|
|
880
887
|
// Prevent invocations while running or blocking
|
|
@@ -932,3 +939,69 @@ export function adaptiveThrottle(
|
|
|
932
939
|
};
|
|
933
940
|
return throttledFn;
|
|
934
941
|
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* MurmurHash3 implementation for strings.
|
|
945
|
+
* @param key The input string to hash.
|
|
946
|
+
* @param asString Optional convert result to zero-padded string of 8 characters.
|
|
947
|
+
* @param seed Optional seed value.
|
|
948
|
+
* @returns A 32-bit hash as a number or string.
|
|
949
|
+
*/
|
|
950
|
+
export function murmurHash3(
|
|
951
|
+
key: string,
|
|
952
|
+
asString = true,
|
|
953
|
+
seed: number = 0
|
|
954
|
+
): number | string {
|
|
955
|
+
let h1 = seed;
|
|
956
|
+
const remainder = key.length & 3; // key.length % 4
|
|
957
|
+
const bytes = key.length - remainder;
|
|
958
|
+
const c1 = 0xcc9e2d51;
|
|
959
|
+
const c2 = 0x1b873593;
|
|
960
|
+
|
|
961
|
+
let i = 0;
|
|
962
|
+
while (i < bytes) {
|
|
963
|
+
let k1 =
|
|
964
|
+
(key.charCodeAt(i) & 0xff) |
|
|
965
|
+
((key.charCodeAt(++i) & 0xff) << 8) |
|
|
966
|
+
((key.charCodeAt(++i) & 0xff) << 16) |
|
|
967
|
+
((key.charCodeAt(++i) & 0xff) << 24);
|
|
968
|
+
++i;
|
|
969
|
+
|
|
970
|
+
k1 = Math.imul(k1, c1);
|
|
971
|
+
k1 = (k1 << 15) | (k1 >>> 17);
|
|
972
|
+
k1 = Math.imul(k1, c2);
|
|
973
|
+
|
|
974
|
+
h1 ^= k1;
|
|
975
|
+
h1 = (h1 << 13) | (h1 >>> 19);
|
|
976
|
+
h1 = Math.imul(h1, 5) + 0xe6546b64;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
let k1 = 0;
|
|
980
|
+
switch (remainder) {
|
|
981
|
+
case 3:
|
|
982
|
+
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
|
|
983
|
+
// fall through
|
|
984
|
+
case 2:
|
|
985
|
+
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
|
|
986
|
+
// fall through
|
|
987
|
+
case 1:
|
|
988
|
+
k1 ^= key.charCodeAt(i) & 0xff;
|
|
989
|
+
k1 = Math.imul(k1, c1);
|
|
990
|
+
k1 = (k1 << 15) | (k1 >>> 17);
|
|
991
|
+
k1 = Math.imul(k1, c2);
|
|
992
|
+
h1 ^= k1;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
h1 ^= key.length;
|
|
996
|
+
h1 ^= h1 >>> 16;
|
|
997
|
+
h1 = Math.imul(h1, 0x85ebca6b);
|
|
998
|
+
h1 ^= h1 >>> 13;
|
|
999
|
+
h1 = Math.imul(h1, 0xc2b2ae35);
|
|
1000
|
+
h1 ^= h1 >>> 16;
|
|
1001
|
+
|
|
1002
|
+
if (asString) {
|
|
1003
|
+
// Convert to 8 digit hex string
|
|
1004
|
+
return (h1 >>> 0).toString(16).padStart(8, "0");
|
|
1005
|
+
}
|
|
1006
|
+
return h1 >>> 0; // Convert to unsigned 32-bit integer
|
|
1007
|
+
}
|
package/src/wb_ext_dnd.ts
CHANGED
|
@@ -78,7 +78,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
78
78
|
// this.$scrollParent = $temp.scrollParent();
|
|
79
79
|
// $temp.remove();
|
|
80
80
|
const tree = this.tree;
|
|
81
|
-
const dndOpts = tree.options.dnd
|
|
81
|
+
const dndOpts = tree.options.dnd;
|
|
82
82
|
|
|
83
83
|
// Enable drag support if dragStart() is specified:
|
|
84
84
|
if (dndOpts.dragStart) {
|
|
@@ -134,7 +134,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
134
134
|
e: DragEvent,
|
|
135
135
|
allowed: DropRegionTypeSet | null
|
|
136
136
|
): DropRegionType | false {
|
|
137
|
-
const rowHeight = this.tree.options.rowHeightPx
|
|
137
|
+
const rowHeight = this.tree.options.rowHeightPx;
|
|
138
138
|
const dy = e.offsetY;
|
|
139
139
|
|
|
140
140
|
if (!allowed) {
|
|
@@ -208,7 +208,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
208
208
|
// `_isVoidDrop: ${srcNode} -> ${dropRegion} ${targetNode}`
|
|
209
209
|
// );
|
|
210
210
|
// TODO: should be checked on move only
|
|
211
|
-
if (!this.treeOpts.dnd
|
|
211
|
+
if (!this.treeOpts.dnd!.preventVoidMoves || !srcNode) {
|
|
212
212
|
return false;
|
|
213
213
|
}
|
|
214
214
|
if (
|
|
@@ -225,7 +225,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
225
225
|
/* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
|
|
226
226
|
protected _applyScrollDir(): void {
|
|
227
227
|
if (this.isDragging() && this.currentScrollDir) {
|
|
228
|
-
const dndOpts = this.tree.options.dnd
|
|
228
|
+
const dndOpts = this.tree.options.dnd;
|
|
229
229
|
const sp = this.tree.element; // scroll parent
|
|
230
230
|
const scrollTop = sp.scrollTop;
|
|
231
231
|
if (this.currentScrollDir < 0) {
|
|
@@ -238,7 +238,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
238
238
|
/* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
|
|
239
239
|
protected _autoScroll(viewportY: number): number {
|
|
240
240
|
const tree = this.tree;
|
|
241
|
-
const dndOpts = tree.options.dnd
|
|
241
|
+
const dndOpts = tree.options.dnd;
|
|
242
242
|
const sensitivity = dndOpts.scrollSensitivity;
|
|
243
243
|
const sp = tree.element; // scroll parent
|
|
244
244
|
const headerHeight = tree.headerElement.clientHeight; // May be 0
|
|
@@ -284,7 +284,6 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
284
284
|
* Handle dragstart, drag and dragend events for the source node.
|
|
285
285
|
*/
|
|
286
286
|
protected onDragEvent(e: DragEvent) {
|
|
287
|
-
// const tree = this.tree;
|
|
288
287
|
const dndOpts: DndOptionsType = this.treeOpts.dnd;
|
|
289
288
|
const srcNode = Wunderbaum.getNode(e);
|
|
290
289
|
|
|
@@ -312,7 +311,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
312
311
|
return false;
|
|
313
312
|
}
|
|
314
313
|
const nodeData = srcNode.toDict(true, (n: any) => {
|
|
315
|
-
// We don't want to
|
|
314
|
+
// We don't want to reuse the key on drop:
|
|
316
315
|
n._orgKey = n.key;
|
|
317
316
|
delete n.key;
|
|
318
317
|
});
|
|
@@ -377,6 +376,7 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
377
376
|
};
|
|
378
377
|
if (!targetNode) {
|
|
379
378
|
this._leaveNode();
|
|
379
|
+
e.preventDefault(); // Don't open file in browser when dropped in empty area
|
|
380
380
|
return;
|
|
381
381
|
}
|
|
382
382
|
if (["drop"].includes(e.type)) {
|
|
@@ -518,19 +518,20 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
518
518
|
const srcNode = this.srcNode;
|
|
519
519
|
const lastDropEffect = this.lastDropEffect;
|
|
520
520
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
521
|
+
/* Before v0.14.0, we decoupled `_callEvent` like so:
|
|
522
|
+
Decouple this call, because drop actions may prevent the dragend
|
|
523
|
+
event from being fired on some browsers.
|
|
524
|
+
setTimeout(() => {...}, 10);
|
|
525
|
+
however this made e.dataTransfer.items inaccessible */
|
|
526
|
+
targetNode._callEvent("dnd.drop", {
|
|
527
|
+
event: e,
|
|
528
|
+
region: region,
|
|
529
|
+
suggestedDropMode: region === "over" ? "appendChild" : region,
|
|
530
|
+
suggestedDropEffect: lastDropEffect,
|
|
531
|
+
sourceNode: srcNode,
|
|
532
|
+
sourceNodeData: nodeData,
|
|
533
|
+
dataTransfer: e.dataTransfer,
|
|
534
|
+
});
|
|
534
535
|
}
|
|
535
536
|
return false;
|
|
536
537
|
}
|
package/src/wb_ext_edit.ts
CHANGED
|
@@ -286,7 +286,7 @@ export class EditExtension extends WunderbaumExtension<EditOptionsType> {
|
|
|
286
286
|
newValue = newValue.trim();
|
|
287
287
|
}
|
|
288
288
|
if (!node) {
|
|
289
|
-
this.tree.logDebug("stopEditTitle: not in edit mode.");
|
|
289
|
+
// this.tree.logDebug("stopEditTitle: not in edit mode.");
|
|
290
290
|
return;
|
|
291
291
|
}
|
|
292
292
|
node.logDebug(`stopEditTitle(${apply})`, options, focusElem, newValue);
|
package/src/wb_ext_filter.ts
CHANGED
|
@@ -75,7 +75,7 @@ export class FilterExtension extends WunderbaumExtension<FilterOptionsType> {
|
|
|
75
75
|
const filterActive = this.tree.filterMode !== null;
|
|
76
76
|
const activeNode = this.tree.getActiveNode();
|
|
77
77
|
const matchCount = filterActive ? this.countMatches() : 0;
|
|
78
|
-
const strings = this.treeOpts.strings
|
|
78
|
+
const strings = this.treeOpts.strings;
|
|
79
79
|
let matchIdx: string | number = "?";
|
|
80
80
|
|
|
81
81
|
if (this.matchInfoElem) {
|
|
@@ -363,6 +363,10 @@ export class FilterExtension extends WunderbaumExtension<FilterOptionsType> {
|
|
|
363
363
|
options.matchBranch === undefined,
|
|
364
364
|
"filterBranches() is deprecated."
|
|
365
365
|
);
|
|
366
|
+
this.tree.logDeprecate("filterBranches()", {
|
|
367
|
+
since: "0.9.0",
|
|
368
|
+
hint: "Use `filterNodes` instead and set `options.matchBranch: true`",
|
|
369
|
+
});
|
|
366
370
|
options.matchBranch = true;
|
|
367
371
|
return this._applyFilterNoUpdate(filter, options);
|
|
368
372
|
}
|
|
@@ -436,7 +440,7 @@ export class FilterExtension extends WunderbaumExtension<FilterOptionsType> {
|
|
|
436
440
|
}
|
|
437
441
|
|
|
438
442
|
/**
|
|
439
|
-
* @description Marks the matching
|
|
443
|
+
* @description Marks the matching characters of `text` either by `mark` or
|
|
440
444
|
* by exotic*Chars (if `escapeTitles` is `true`) based on `matches`
|
|
441
445
|
* which is an array of matching groups.
|
|
442
446
|
* @param {string} text
|
package/src/wb_ext_grid.ts
CHANGED
|
@@ -77,7 +77,7 @@ export class GridExtension extends WunderbaumExtension<GridOptionsType> {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
*
|
|
80
|
+
* Handles drag and sragstop events for column resizing.
|
|
81
81
|
*/
|
|
82
82
|
protected handleDrag(e: DragCallbackArgType): void {
|
|
83
83
|
const custom = e.customData;
|
package/src/wb_extension_base.ts
CHANGED
|
@@ -5,10 +5,25 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as util from "./util";
|
|
8
|
+
import { DndExtension } from "./wb_ext_dnd";
|
|
9
|
+
import { EditExtension } from "./wb_ext_edit";
|
|
10
|
+
import { FilterExtension } from "./wb_ext_filter";
|
|
11
|
+
import { GridExtension } from "./wb_ext_grid";
|
|
12
|
+
import { KeynavExtension } from "./wb_ext_keynav";
|
|
13
|
+
import { LoggerExtension } from "./wb_ext_logger";
|
|
8
14
|
import { WunderbaumOptions } from "./wb_options";
|
|
9
15
|
import { Wunderbaum } from "./wunderbaum";
|
|
10
16
|
|
|
11
|
-
export type ExtensionsDict = {
|
|
17
|
+
export type ExtensionsDict = {
|
|
18
|
+
dnd: DndExtension;
|
|
19
|
+
edit: EditExtension;
|
|
20
|
+
filter: FilterExtension;
|
|
21
|
+
grid: GridExtension;
|
|
22
|
+
keynav: KeynavExtension;
|
|
23
|
+
logger: LoggerExtension;
|
|
24
|
+
|
|
25
|
+
[key: string]: WunderbaumExtension<any>;
|
|
26
|
+
};
|
|
12
27
|
|
|
13
28
|
export abstract class WunderbaumExtension<TOptions> {
|
|
14
29
|
public enabled = true;
|