wunderbaum 0.10.0 → 0.11.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/README.md +2 -2
- package/dist/wunderbaum.css +13 -5
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +194 -45
- package/dist/wunderbaum.esm.js +212 -52
- package/dist/wunderbaum.esm.min.js +22 -22
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +212 -52
- package/dist/wunderbaum.umd.min.js +29 -29
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +5 -6
- package/src/common.ts +16 -1
- package/src/types.ts +122 -25
- package/src/util.ts +12 -12
- package/src/wb_ext_filter.ts +4 -0
- package/src/wb_ext_grid.ts +1 -1
- package/src/wb_node.ts +116 -5
- package/src/wb_options.ts +26 -2
- package/src/wunderbaum.scss +15 -5
- package/src/wunderbaum.ts +96 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wunderbaum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"title": "A treegrid control.",
|
|
5
5
|
"description": "JavaScript tree/grid/treegrid control.",
|
|
6
6
|
"homepage": "https://github.com/mar10/wunderbaum",
|
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
|
55
55
|
"@typescript-eslint/parser": "^6.7.5",
|
|
56
56
|
"concurrently": "^8.1.0",
|
|
57
|
-
"docsify-cli": "^4.4.4",
|
|
58
57
|
"eslint": "^8.51.0",
|
|
59
58
|
"eslint-config-jquery": "^3.0.0",
|
|
60
59
|
"eslint-config-prettier": "^8.8.0",
|
|
@@ -101,7 +100,7 @@
|
|
|
101
100
|
},
|
|
102
101
|
"scripts": {
|
|
103
102
|
"test": "npm run lint && npm run build:js && grunt ci --verbose",
|
|
104
|
-
"
|
|
103
|
+
"api_docs": "typedoc && touch docs/api/.nojekyll && rm docs/unittest/*.*; cp test/unit/*.* docs/unittest",
|
|
105
104
|
"format": "eslint src --fix && prettier src docs/demo -w && npm run lint",
|
|
106
105
|
"lint": "prettier src docs/demo --check && eslint src docs/demo && tsc -t esnext --moduleResolution node --noEmit src/wunderbaum.ts",
|
|
107
106
|
"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,13 +109,13 @@
|
|
|
110
109
|
"build:scss": "sass src/wunderbaum.scss build/wunderbaum.css",
|
|
111
110
|
"build:js": "rollup -c rollup.config.mjs && npm run build:minjs",
|
|
112
111
|
"build:types": "tsc -t esnext --moduleResolution node -d --emitDeclarationOnly --outFile build/wunderbaum.d.ts src/wunderbaum.ts",
|
|
113
|
-
"build": "npm run format && mkdir build; rm build/*.*; ls build && npm run build:js -s && npm run build:scss && npm run build:types -s && npm run
|
|
112
|
+
"build": "npm run format && mkdir build; rm build/*.*; ls build && npm run build:js -s && npm run build:scss && npm run build:types -s && npm run api_docs",
|
|
114
113
|
"make_dist": "npm run build && rm dist/*.* ; cp build/*.* dist",
|
|
115
114
|
"watch:umd": "nodemon --watch src --ext 'ts' -x \"npm run build:minjs\"",
|
|
116
115
|
"watch": "nodemon",
|
|
117
116
|
"serve": "http-server test -p 8080 -o /",
|
|
118
|
-
"
|
|
119
|
-
"
|
|
117
|
+
"dev": "concurrently \"http-server . -p 8080 -o /docs/demo \" \"nodemon\"",
|
|
118
|
+
"dev_mkdocs": "pipenv run mkdocs serve"
|
|
120
119
|
},
|
|
121
120
|
"npmName": "wunderbaum",
|
|
122
121
|
"npmFileMap": [
|
package/src/common.ts
CHANGED
|
@@ -64,6 +64,15 @@ export const iconMaps: { [key: string]: { [key: string]: string } } = {
|
|
|
64
64
|
folderOpen: "bi bi-folder2-open",
|
|
65
65
|
folderLazy: "bi bi-folder-symlink",
|
|
66
66
|
doc: "bi bi-file-earmark",
|
|
67
|
+
colSortable: "bi bi-chevron-expand",
|
|
68
|
+
// colSortable: "bi bi-arrow-down-up",
|
|
69
|
+
// colSortAsc: "bi bi-chevron-down",
|
|
70
|
+
// colSortDesc: "bi bi-chevron-up",
|
|
71
|
+
colSortAsc: "bi bi-arrow-down",
|
|
72
|
+
colSortDesc: "bi bi-arrow-up",
|
|
73
|
+
colFilter: "bi bi-filter-circle",
|
|
74
|
+
colFilterActive: "bi bi-filter-circle-fill wb-helper-invalid",
|
|
75
|
+
colMenu: "bi bi-three-dots-vertical",
|
|
67
76
|
},
|
|
68
77
|
fontawesome6: {
|
|
69
78
|
error: "fa-solid fa-triangle-exclamation",
|
|
@@ -82,6 +91,12 @@ export const iconMaps: { [key: string]: { [key: string]: string } } = {
|
|
|
82
91
|
folderOpen: "fa-regular fa-folder-open",
|
|
83
92
|
folderLazy: "fa-solid fa-folder-plus",
|
|
84
93
|
doc: "fa-regular fa-file",
|
|
94
|
+
colSortable: "fa-solid fa-fw fa-sort",
|
|
95
|
+
colSortAsc: "fa-solid fa-fw fa-sort-up",
|
|
96
|
+
colSortDesc: "fa-solid fa-fw fa-sort-down",
|
|
97
|
+
colFilter: "fa-solid fa-fw fa-filter",
|
|
98
|
+
colFilterActive: "fa-solid fa-fw fa-filter wb-helper-invalid",
|
|
99
|
+
colMenu: "fa-solid fa-fw fa-ellipsis-v",
|
|
85
100
|
},
|
|
86
101
|
};
|
|
87
102
|
|
|
@@ -149,7 +164,7 @@ export const KEY_TO_ACTION_DICT: { [key: string]: string } = {
|
|
|
149
164
|
|
|
150
165
|
/** Return a callback that returns true if the node title matches the string
|
|
151
166
|
* or regular expression.
|
|
152
|
-
* @see {@link WunderbaumNode.findAll
|
|
167
|
+
* @see {@link WunderbaumNode.findAll}
|
|
153
168
|
*/
|
|
154
169
|
export function makeNodeTitleMatcher(match: string | RegExp): MatcherCallback {
|
|
155
170
|
if (match instanceof RegExp) {
|
package/src/types.ts
CHANGED
|
@@ -72,11 +72,23 @@ export type BoolOrStringOptionResolver = (
|
|
|
72
72
|
export type NodeAnyCallback = (node: WunderbaumNode) => any;
|
|
73
73
|
/** A callback that receives a node instance and returns a string value. */
|
|
74
74
|
export type NodeStringCallback = (node: WunderbaumNode) => string;
|
|
75
|
+
/** A callback that receives a node instance and property name returns a value. */
|
|
76
|
+
export type NodePropertyGetterCallback = (
|
|
77
|
+
node: WunderbaumNode,
|
|
78
|
+
propName: string
|
|
79
|
+
) => any;
|
|
75
80
|
/** A callback that receives a node instance and returns an iteration modifier. */
|
|
76
81
|
export type NodeVisitCallback = (node: WunderbaumNode) => NodeVisitResponse;
|
|
77
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Returned by `NodeVisitCallback` to control iteration.
|
|
84
|
+
* `false` stops iteration, `skip` skips descendants but continues.
|
|
85
|
+
* All other values continue iteration.
|
|
86
|
+
*/
|
|
78
87
|
export type NodeVisitResponse = "skip" | boolean | void;
|
|
79
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* A callback that receives a node-data dictionary and a node instance and
|
|
90
|
+
* returns an iteration modifier.
|
|
91
|
+
*/
|
|
80
92
|
export type NodeToDictCallback = (
|
|
81
93
|
dict: WbNodeData,
|
|
82
94
|
node: WunderbaumNode
|
|
@@ -264,6 +276,12 @@ export interface WbSelectEventType extends WbNodeEventType {
|
|
|
264
276
|
flag: boolean;
|
|
265
277
|
}
|
|
266
278
|
|
|
279
|
+
export interface WbButtonClickEventType extends WbTreeEventType {
|
|
280
|
+
info: WbEventInfo;
|
|
281
|
+
/** The associated command, e.g. 'menu', 'sort', 'filter', ... */
|
|
282
|
+
command: string;
|
|
283
|
+
}
|
|
284
|
+
|
|
267
285
|
export interface WbRenderEventType extends WbNodeEventType {
|
|
268
286
|
/**
|
|
269
287
|
* True if the node's markup was not yet created. In this case the render
|
|
@@ -351,29 +369,58 @@ export interface ColumnDefinition {
|
|
|
351
369
|
*/
|
|
352
370
|
minWidth?: string | number;
|
|
353
371
|
/** Allow user to resize the column.
|
|
354
|
-
*
|
|
372
|
+
* @default false (or global tree option `columnsSortable`)
|
|
373
|
+
* @see {@link WunderbaumOptions.columnsResizable}.
|
|
374
|
+
* @since 0.10.0
|
|
355
375
|
*/
|
|
356
376
|
resizable?: boolean;
|
|
357
377
|
/** Optional custom column width when user resized by mouse drag.
|
|
358
378
|
* Default: unset.
|
|
359
379
|
*/
|
|
360
380
|
customWidthPx?: number;
|
|
361
|
-
/**
|
|
362
|
-
*
|
|
381
|
+
/** Display a 'filter' button in the column header. Default: false. <br>
|
|
382
|
+
* Note: The actual filtering must be implemented in the `buttonClick()` event.
|
|
383
|
+
* @default false (or global tree option `columnsFilterable`)
|
|
384
|
+
* @since 0.11.0
|
|
385
|
+
*/
|
|
386
|
+
filterable?: boolean;
|
|
387
|
+
/** .
|
|
388
|
+
* Default: inactive. <br>
|
|
389
|
+
* Note: The actual filtering must be implemented in the `buttonClick()` event.
|
|
390
|
+
*/
|
|
391
|
+
filterActive?: boolean;
|
|
392
|
+
/** Display a 'sort' button in the column header. Default: false. <br>
|
|
393
|
+
* Note: The actual sorting must be implemented in the `buttonClick()` event.
|
|
394
|
+
* @default false (or global tree option `columnsSortable`)
|
|
395
|
+
* @see {@link WunderbaumOptions.columnsSortable}.
|
|
396
|
+
* @since 0.11.0
|
|
363
397
|
*/
|
|
364
398
|
sortable?: boolean;
|
|
365
399
|
/** Optional custom column sort orde when user clicked the sort icon.
|
|
366
|
-
* Default: unset.
|
|
400
|
+
* Default: unset, e.g. not sorted. <br>
|
|
401
|
+
* Note: The actual sorting must be implemented in the `buttonClick()` event.
|
|
402
|
+
* @since 0.11.0
|
|
367
403
|
*/
|
|
368
404
|
sortOrder?: SortOrderType;
|
|
405
|
+
/** Display a menu icon that may open a context menu for this column.
|
|
406
|
+
* Note: The actual functionality must be implemented in the `buttonClick()` event.
|
|
407
|
+
* @default false (or global tree option `columnsMenu`)
|
|
408
|
+
* @see {@link WunderbaumOptions.columnsMenu}.
|
|
409
|
+
* @since 0.11.0
|
|
410
|
+
*/
|
|
411
|
+
menu?: boolean;
|
|
369
412
|
/** Optional class names that are added to all `span.wb-col` header AND data
|
|
370
|
-
* elements of that column.
|
|
413
|
+
* elements of that column. Separate multiple classes with space.
|
|
371
414
|
*/
|
|
372
415
|
classes?: string;
|
|
373
416
|
/** If `headerClasses` is a set, it will be used for the header element only
|
|
374
417
|
* (unlike `classes`, which is used for body and header cells).
|
|
418
|
+
* Separate multiple classes with space.
|
|
375
419
|
*/
|
|
376
420
|
headerClasses?: string;
|
|
421
|
+
// /** A list of icon definitions added to the column header.
|
|
422
|
+
// */
|
|
423
|
+
// headerIcons?: string;
|
|
377
424
|
/** Optional HTML content that is rendered into all `span.wb-col` elements of that column.*/
|
|
378
425
|
html?: string;
|
|
379
426
|
/** @internal */
|
|
@@ -463,7 +510,7 @@ export type NodeFilterResponse = "skip" | "branch" | boolean | void;
|
|
|
463
510
|
export type NodeFilterCallback = (node: WunderbaumNode) => NodeFilterResponse;
|
|
464
511
|
|
|
465
512
|
/**
|
|
466
|
-
* Possible values for {@link WunderbaumNode.update
|
|
513
|
+
* Possible values for {@link WunderbaumNode.update} and {@link Wunderbaum.update}.
|
|
467
514
|
*/
|
|
468
515
|
export enum ChangeType {
|
|
469
516
|
/** Re-render the whole viewport, headers, and all rows. */
|
|
@@ -492,7 +539,7 @@ export enum RenderFlag {
|
|
|
492
539
|
scroll = "scroll",
|
|
493
540
|
}
|
|
494
541
|
|
|
495
|
-
/** Possible values for {@link WunderbaumNode.setStatus
|
|
542
|
+
/** Possible values for {@link WunderbaumNode.setStatus}. */
|
|
496
543
|
export enum NodeStatusType {
|
|
497
544
|
ok = "ok",
|
|
498
545
|
loading = "loading",
|
|
@@ -524,7 +571,7 @@ export enum NavModeEnum {
|
|
|
524
571
|
* METHOD OPTIONS TYPES
|
|
525
572
|
* ---------------------------------------------------------------------------*/
|
|
526
573
|
|
|
527
|
-
/** Possible values for {@link WunderbaumNode.addChildren
|
|
574
|
+
/** Possible values for {@link WunderbaumNode.addChildren}. */
|
|
528
575
|
export interface AddChildrenOptions {
|
|
529
576
|
/** Insert children before this node (or index)
|
|
530
577
|
* @default undefined or null: append as last child
|
|
@@ -540,12 +587,12 @@ export interface AddChildrenOptions {
|
|
|
540
587
|
_level?: number;
|
|
541
588
|
}
|
|
542
589
|
|
|
543
|
-
/** Possible values for {@link Wunderbaum.applyCommand
|
|
590
|
+
/** Possible values for {@link Wunderbaum.applyCommand} and {@link WunderbaumNode.applyCommand}. */
|
|
544
591
|
export interface ApplyCommandOptions {
|
|
545
592
|
[key: string]: unknown;
|
|
546
593
|
}
|
|
547
594
|
|
|
548
|
-
/** Possible values for {@link Wunderbaum.expandAll
|
|
595
|
+
/** Possible values for {@link Wunderbaum.expandAll} and {@link WunderbaumNode.expandAll}. */
|
|
549
596
|
export interface ExpandAllOptions {
|
|
550
597
|
/** Restrict expand level @default 99 */
|
|
551
598
|
depth?: number;
|
|
@@ -558,7 +605,7 @@ export interface ExpandAllOptions {
|
|
|
558
605
|
}
|
|
559
606
|
|
|
560
607
|
/**
|
|
561
|
-
* Possible option values for {@link Wunderbaum.filterNodes
|
|
608
|
+
* Possible option values for {@link Wunderbaum.filterNodes}.
|
|
562
609
|
* The defaults are inherited from the tree instances ´tree.options.filter`
|
|
563
610
|
* settings (see also {@link FilterOptionsType}).
|
|
564
611
|
*/
|
|
@@ -584,7 +631,7 @@ export interface FilterNodesOptions {
|
|
|
584
631
|
noData?: boolean | string;
|
|
585
632
|
}
|
|
586
633
|
|
|
587
|
-
/** Possible values for {@link WunderbaumNode.makeVisible
|
|
634
|
+
/** Possible values for {@link WunderbaumNode.makeVisible}. */
|
|
588
635
|
export interface MakeVisibleOptions {
|
|
589
636
|
/** Do not animate expand (currently not implemented). @default false */
|
|
590
637
|
noAnimation?: boolean;
|
|
@@ -594,7 +641,7 @@ export interface MakeVisibleOptions {
|
|
|
594
641
|
noEvents?: boolean;
|
|
595
642
|
}
|
|
596
643
|
|
|
597
|
-
/** Possible values for {@link WunderbaumNode.navigate
|
|
644
|
+
/** Possible values for {@link WunderbaumNode.navigate}. */
|
|
598
645
|
export interface NavigateOptions {
|
|
599
646
|
/** Activate the new node (otherwise focus only). @default true */
|
|
600
647
|
activate?: boolean;
|
|
@@ -602,7 +649,7 @@ export interface NavigateOptions {
|
|
|
602
649
|
event?: Event;
|
|
603
650
|
}
|
|
604
651
|
|
|
605
|
-
/** Possible values for {@link WunderbaumNode._render
|
|
652
|
+
/** Possible values for {@link WunderbaumNode._render}. */
|
|
606
653
|
export interface RenderOptions {
|
|
607
654
|
/** Which parts need update? @default ChangeType.data */
|
|
608
655
|
change?: ChangeType;
|
|
@@ -620,7 +667,7 @@ export interface RenderOptions {
|
|
|
620
667
|
resizeCols?: boolean;
|
|
621
668
|
}
|
|
622
669
|
|
|
623
|
-
/** Possible values for {@link WunderbaumNode.scrollIntoView
|
|
670
|
+
/** Possible values for {@link WunderbaumNode.scrollIntoView} `options` argument. */
|
|
624
671
|
export interface ScrollIntoViewOptions {
|
|
625
672
|
/** Do not animate (currently not implemented). @default false */
|
|
626
673
|
noAnimation?: boolean;
|
|
@@ -632,7 +679,7 @@ export interface ScrollIntoViewOptions {
|
|
|
632
679
|
ofsY?: number;
|
|
633
680
|
}
|
|
634
681
|
|
|
635
|
-
/** Possible values for {@link Wunderbaum.scrollTo
|
|
682
|
+
/** Possible values for {@link Wunderbaum.scrollTo} `options` argument. */
|
|
636
683
|
export interface ScrollToOptions extends ScrollIntoViewOptions {
|
|
637
684
|
/** Which node to scroll into the viewport.*/
|
|
638
685
|
node: WunderbaumNode;
|
|
@@ -652,7 +699,7 @@ export interface SetActiveOptions {
|
|
|
652
699
|
focusTree?: boolean;
|
|
653
700
|
/** Optional original event that will be passed to the (de)activate handler. */
|
|
654
701
|
event?: Event;
|
|
655
|
-
/** Also call {@link Wunderbaum.setColumn
|
|
702
|
+
/** Also call {@link Wunderbaum.setColumn}. */
|
|
656
703
|
colIdx?: number | string;
|
|
657
704
|
/**
|
|
658
705
|
* Focus embedded input control of the grid cell if any (requires colIdx >= 0).
|
|
@@ -662,7 +709,7 @@ export interface SetActiveOptions {
|
|
|
662
709
|
edit?: boolean;
|
|
663
710
|
}
|
|
664
711
|
|
|
665
|
-
/** Possible values for {@link Wunderbaum.setColumn
|
|
712
|
+
/** Possible values for {@link Wunderbaum.setColumn} `options` argument. */
|
|
666
713
|
export interface SetColumnOptions {
|
|
667
714
|
/**
|
|
668
715
|
* Focus embedded input control of the grid cell if any .
|
|
@@ -688,7 +735,7 @@ export interface SetExpandedOptions {
|
|
|
688
735
|
scrollIntoView?: boolean;
|
|
689
736
|
}
|
|
690
737
|
|
|
691
|
-
/** Possible values for {@link WunderbaumNode.update
|
|
738
|
+
/** Possible values for {@link WunderbaumNode.update} `options` argument. */
|
|
692
739
|
export interface UpdateOptions {
|
|
693
740
|
/** Force immediate redraw instead of throttled/async mode. @default false */
|
|
694
741
|
immediate?: boolean;
|
|
@@ -696,7 +743,7 @@ export interface UpdateOptions {
|
|
|
696
743
|
// removeMarkup?: boolean;
|
|
697
744
|
}
|
|
698
745
|
|
|
699
|
-
/** Possible values for {@link WunderbaumNode.setSelected
|
|
746
|
+
/** Possible values for {@link WunderbaumNode.setSelected} `options` argument. */
|
|
700
747
|
export interface SetSelectedOptions {
|
|
701
748
|
/** Ignore restrictions, e.g. (`unselectable`). @default false */
|
|
702
749
|
force?: boolean;
|
|
@@ -710,7 +757,7 @@ export interface SetSelectedOptions {
|
|
|
710
757
|
callback?: NodeSelectCallback;
|
|
711
758
|
}
|
|
712
759
|
|
|
713
|
-
/** Possible values for {@link WunderbaumNode.setStatus
|
|
760
|
+
/** Possible values for {@link WunderbaumNode.setStatus} `options` argument. */
|
|
714
761
|
export interface SetStatusOptions {
|
|
715
762
|
/** Displayed as status node title. */
|
|
716
763
|
message?: string;
|
|
@@ -718,7 +765,57 @@ export interface SetStatusOptions {
|
|
|
718
765
|
details?: string;
|
|
719
766
|
}
|
|
720
767
|
|
|
721
|
-
/**
|
|
768
|
+
/**
|
|
769
|
+
* Possible values for {@link WunderbaumNode.sortByProperty} `options` argument.
|
|
770
|
+
*/
|
|
771
|
+
export interface ResetOrderOptions {
|
|
772
|
+
/** Sort descendants recursively. @default true */
|
|
773
|
+
recursive?: boolean;
|
|
774
|
+
/** The name of the node property that will be renumbered.
|
|
775
|
+
* @default `_nativeIndex`.
|
|
776
|
+
*/
|
|
777
|
+
propName?: string;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Possible values for {@link WunderbaumNode.sortByProperty} `options` argument.
|
|
782
|
+
*/
|
|
783
|
+
export interface SortByPropertyOptions {
|
|
784
|
+
/** Column ID as defined in `tree.columns` definition. Required if updateColInfo is true.*/
|
|
785
|
+
colId?: string;
|
|
786
|
+
/** The name of the node property that will be used for sorting.
|
|
787
|
+
* @default use the `colId` as property name.
|
|
788
|
+
*/
|
|
789
|
+
propName?: string;
|
|
790
|
+
// /** If defined, this callback is used to extract the value to be sorted. */
|
|
791
|
+
// vallueGetter?: NodePropertyGetterCallback;
|
|
792
|
+
/** Sort order. @default Use value from column definition (rotated).*/
|
|
793
|
+
order?: SortOrderType;
|
|
794
|
+
/**
|
|
795
|
+
* Sort by this property if order is `undefined`.
|
|
796
|
+
* See also {@link WunderbaumNode.resetNativeChildOrder}.
|
|
797
|
+
* @default `_nativeIndex`.
|
|
798
|
+
*/
|
|
799
|
+
nativeOrderPropName?: string;
|
|
800
|
+
/** Sort string values case insensitive. @default false */
|
|
801
|
+
caseInsensitive?: boolean;
|
|
802
|
+
/** Sort descendants recursively. @default true */
|
|
803
|
+
deep?: boolean;
|
|
804
|
+
// /** Rotate sort order (asc -> desc -> none) before sorting. @default false */
|
|
805
|
+
// rotateOrder?: boolean;
|
|
806
|
+
/**
|
|
807
|
+
* Rotate sort order (asc -> desc -> none) before sorting.
|
|
808
|
+
* Update the sort icons in the column header
|
|
809
|
+
* Note:
|
|
810
|
+
* Sorting is done in-place. There is no 'unsorted' state, but we can
|
|
811
|
+
* call `setCurrentSortOrder()` to renumber the `node._sortIdx` property,
|
|
812
|
+
* which will be used as sort key, when `order` is `undefined`.
|
|
813
|
+
* @default false
|
|
814
|
+
*/
|
|
815
|
+
updateColInfo?: boolean;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/** Options passed to {@link Wunderbaum.visitRows}. */
|
|
722
819
|
export interface VisitRowsOptions {
|
|
723
820
|
/** Skip filtered nodes and children of collapsed nodes. @default false */
|
|
724
821
|
includeHidden?: boolean;
|
|
@@ -997,7 +1094,7 @@ export type DndOptionsType = {
|
|
|
997
1094
|
// */
|
|
998
1095
|
// setTextTypeJson: boolean;
|
|
999
1096
|
/**
|
|
1000
|
-
* Optional callback passed to `toDict` on dragStart
|
|
1097
|
+
* Optional callback passed to `toDict` on dragStart
|
|
1001
1098
|
* @default null
|
|
1002
1099
|
* @category Callback
|
|
1003
1100
|
*/
|
package/src/util.ts
CHANGED
|
@@ -521,7 +521,7 @@ export function isArray(obj: any) {
|
|
|
521
521
|
return Array.isArray(obj);
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
-
/** Return true if `obj` is of type `Object` and has no
|
|
524
|
+
/** Return true if `obj` is of type `Object` and has no properties. */
|
|
525
525
|
export function isEmptyObject(obj: any) {
|
|
526
526
|
return Object.keys(obj).length === 0 && obj.constructor === Object;
|
|
527
527
|
}
|
|
@@ -746,6 +746,12 @@ export function getOption(
|
|
|
746
746
|
return value ?? defaultValue;
|
|
747
747
|
}
|
|
748
748
|
|
|
749
|
+
/** Return the next value from a list of values (rotating). @since 0.11 */
|
|
750
|
+
export function rotate(value: any, values: any[]): any {
|
|
751
|
+
const idx = values.indexOf(value);
|
|
752
|
+
return values[(idx + 1) % values.length];
|
|
753
|
+
}
|
|
754
|
+
|
|
749
755
|
/** Convert an Array or space-separated string to a Set. */
|
|
750
756
|
export function toSet(val: any): Set<string> {
|
|
751
757
|
if (val instanceof Set) {
|
|
@@ -770,16 +776,14 @@ export function toSet(val: any): Set<string> {
|
|
|
770
776
|
*
|
|
771
777
|
* Example:
|
|
772
778
|
* ```js
|
|
773
|
-
*
|
|
779
|
+
* let x = undefined;
|
|
780
|
+
* let y = "123px";
|
|
781
|
+
* const width = util.toPixel(x, y, 100); // returns 123
|
|
774
782
|
* ```
|
|
775
783
|
*/
|
|
776
784
|
export function toPixel(
|
|
777
|
-
// val: string | number | undefined | null,
|
|
778
785
|
...defaults: (string | number | undefined | null)[]
|
|
779
786
|
): number {
|
|
780
|
-
// if (typeof val === "number") {
|
|
781
|
-
// return val;
|
|
782
|
-
// }
|
|
783
787
|
for (const d of defaults) {
|
|
784
788
|
if (typeof d === "number") {
|
|
785
789
|
return d;
|
|
@@ -792,20 +796,16 @@ export function toPixel(
|
|
|
792
796
|
throw new Error(`Expected a string like '123px': ${defaults}`);
|
|
793
797
|
}
|
|
794
798
|
|
|
795
|
-
/**
|
|
799
|
+
/** Return the the boolean value of the first non-null element.
|
|
796
800
|
* Example:
|
|
797
801
|
* ```js
|
|
798
802
|
* const opts = { flag: true };
|
|
799
|
-
* const value = util.toBool(opts.
|
|
803
|
+
* const value = util.toBool(opts.foo, opts.flag, false); // returns true
|
|
800
804
|
* ```
|
|
801
805
|
*/
|
|
802
806
|
export function toBool(
|
|
803
|
-
// val: boolean | undefined | null,
|
|
804
807
|
...boolDefaults: (boolean | undefined | null)[]
|
|
805
808
|
): boolean {
|
|
806
|
-
// if (val != null) {
|
|
807
|
-
// return !!val;
|
|
808
|
-
// }
|
|
809
809
|
for (const d of boolDefaults) {
|
|
810
810
|
if (d != null) {
|
|
811
811
|
return !!d;
|
package/src/wb_ext_filter.ts
CHANGED
|
@@ -52,6 +52,10 @@ export class FilterExtension extends WunderbaumExtension<FilterOptionsType> {
|
|
|
52
52
|
const connectInput = this.getPluginOption("connectInput");
|
|
53
53
|
if (connectInput) {
|
|
54
54
|
this.queryInput = elemFromSelector(connectInput) as HTMLInputElement;
|
|
55
|
+
assert(
|
|
56
|
+
this.queryInput,
|
|
57
|
+
`Invalid 'filter.connectInput' option: ${connectInput}.`
|
|
58
|
+
);
|
|
55
59
|
onEvent(
|
|
56
60
|
this.queryInput,
|
|
57
61
|
"input",
|
package/src/wb_ext_grid.ts
CHANGED
|
@@ -29,7 +29,7 @@ export class GridExtension extends WunderbaumExtension<GridOptionsType> {
|
|
|
29
29
|
const allow =
|
|
30
30
|
colDef &&
|
|
31
31
|
this.tree.element.contains(e.dragElem) &&
|
|
32
|
-
toBool(colDef.resizable, tree.options.
|
|
32
|
+
toBool(colDef.resizable, tree.options.columnsResizable, false);
|
|
33
33
|
|
|
34
34
|
// this.tree.log("dragstart", colDef, e, info);
|
|
35
35
|
|
package/src/wb_node.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ApplyCommandType,
|
|
14
14
|
ChangeType,
|
|
15
15
|
CheckboxOption,
|
|
16
|
+
ColumnDefinition,
|
|
16
17
|
ColumnEventInfoMap,
|
|
17
18
|
ExpandAllOptions,
|
|
18
19
|
IconOption,
|
|
@@ -27,12 +28,15 @@ import {
|
|
|
27
28
|
NodeVisitCallback,
|
|
28
29
|
NodeVisitResponse,
|
|
29
30
|
RenderOptions,
|
|
31
|
+
ResetOrderOptions,
|
|
30
32
|
ScrollIntoViewOptions,
|
|
31
33
|
SetActiveOptions,
|
|
32
34
|
SetExpandedOptions,
|
|
33
35
|
SetSelectedOptions,
|
|
34
36
|
SetStatusOptions,
|
|
37
|
+
SortByPropertyOptions,
|
|
35
38
|
SortCallback,
|
|
39
|
+
SortOrderType,
|
|
36
40
|
SourceType,
|
|
37
41
|
TooltipOption,
|
|
38
42
|
TristateType,
|
|
@@ -104,12 +108,26 @@ export class WunderbaumNode {
|
|
|
104
108
|
* @see Use {@link setKey} to modify.
|
|
105
109
|
*/
|
|
106
110
|
public readonly refKey: string | undefined = undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Array of child nodes (null for leaf nodes).
|
|
113
|
+
* For lazy nodes, this is `null` or ùndefined` until the children are loaded
|
|
114
|
+
* and leaf nodes may be `[]` (empty array).
|
|
115
|
+
* @see {@link hasChildren}, {@link addChildren}, {@link lazy}.
|
|
116
|
+
*/
|
|
107
117
|
public children: WunderbaumNode[] | null = null;
|
|
118
|
+
/** Render a checkbox or radio button @see {@link selected}. */
|
|
108
119
|
public checkbox?: CheckboxOption;
|
|
120
|
+
/** If true, this node's children are considerd radio buttons.
|
|
121
|
+
* @see {@link isRadio}.
|
|
122
|
+
*/
|
|
109
123
|
public radiogroup?: boolean;
|
|
110
124
|
/** If true, (in grid mode) no cells are rendered, except for the node title.*/
|
|
111
125
|
public colspan?: boolean;
|
|
126
|
+
/** Icon definition. */
|
|
112
127
|
public icon?: IconOption;
|
|
128
|
+
/** Lazy loading flag.
|
|
129
|
+
* @see {@link isLazy}, {@link isLoaded}, {@link isUnloaded}.
|
|
130
|
+
*/
|
|
113
131
|
public lazy?: boolean;
|
|
114
132
|
/** Expansion state.
|
|
115
133
|
* @see {@link isExpandable}, {@link isExpanded}, {@link setExpanded}. */
|
|
@@ -118,7 +136,11 @@ export class WunderbaumNode {
|
|
|
118
136
|
* @see {@link isSelected}, {@link setSelected}, {@link toggleSelected}. */
|
|
119
137
|
public selected?: boolean;
|
|
120
138
|
public unselectable?: boolean;
|
|
139
|
+
/** Node type (used for styling).
|
|
140
|
+
* @see {@link Wunderbaum.types}.
|
|
141
|
+
*/
|
|
121
142
|
public type?: string;
|
|
143
|
+
/** Tooltip definition (`true`: use node's title). */
|
|
122
144
|
public tooltip?: string | boolean;
|
|
123
145
|
/** Additional classes added to `div.wb-row`.
|
|
124
146
|
* @see {@link hasClass}, {@link setClass}. */
|
|
@@ -787,7 +809,7 @@ export class WunderbaumNode {
|
|
|
787
809
|
return this.classes ? this.classes.has(className) : false;
|
|
788
810
|
}
|
|
789
811
|
|
|
790
|
-
/** Return true if node ist the currently focused node. */
|
|
812
|
+
/** Return true if node ist the currently focused node. @since 0.9.0 */
|
|
791
813
|
hasFocus(): boolean {
|
|
792
814
|
return this.tree.focusNode === this;
|
|
793
815
|
}
|
|
@@ -1054,6 +1076,8 @@ export class WunderbaumNode {
|
|
|
1054
1076
|
if (tree.options.selectMode === "hier") {
|
|
1055
1077
|
this.fixSelection3FromEndNodes();
|
|
1056
1078
|
}
|
|
1079
|
+
// Allow to un-sort nodes after sorting
|
|
1080
|
+
this.resetNativeChildOrder();
|
|
1057
1081
|
|
|
1058
1082
|
this._callEvent("load");
|
|
1059
1083
|
}
|
|
@@ -2091,7 +2115,7 @@ export class WunderbaumNode {
|
|
|
2091
2115
|
*
|
|
2092
2116
|
* @param name name of the option property (on node and tree)
|
|
2093
2117
|
* @param defaultValue return this if nothing else matched
|
|
2094
|
-
* {@link Wunderbaum.getOption|Wunderbaum.getOption
|
|
2118
|
+
* {@link Wunderbaum.getOption|Wunderbaum.getOption}
|
|
2095
2119
|
*/
|
|
2096
2120
|
getOption(name: string, defaultValue?: any) {
|
|
2097
2121
|
const tree = this.tree;
|
|
@@ -2130,7 +2154,7 @@ export class WunderbaumNode {
|
|
|
2130
2154
|
}
|
|
2131
2155
|
|
|
2132
2156
|
/** Make sure that this node is visible in the viewport.
|
|
2133
|
-
* @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo
|
|
2157
|
+
* @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo}
|
|
2134
2158
|
*/
|
|
2135
2159
|
async scrollIntoView(options?: ScrollIntoViewOptions) {
|
|
2136
2160
|
const opts = Object.assign({ node: this }, options);
|
|
@@ -2284,9 +2308,9 @@ export class WunderbaumNode {
|
|
|
2284
2308
|
* and column content. It can be reduced to 'ChangeType.status' if only
|
|
2285
2309
|
* active/focus/selected state has changed.
|
|
2286
2310
|
*
|
|
2287
|
-
* This method will eventually call {@link WunderbaumNode._render
|
|
2311
|
+
* This method will eventually call {@link WunderbaumNode._render} with
|
|
2288
2312
|
* default options, but may be more consistent with the tree's
|
|
2289
|
-
* {@link Wunderbaum.update
|
|
2313
|
+
* {@link Wunderbaum.update} API.
|
|
2290
2314
|
*/
|
|
2291
2315
|
update(change: ChangeType = ChangeType.data) {
|
|
2292
2316
|
util.assert(
|
|
@@ -2669,6 +2693,93 @@ export class WunderbaumNode {
|
|
|
2669
2693
|
// this.triggerModify("sort"); // TODO
|
|
2670
2694
|
}
|
|
2671
2695
|
|
|
2696
|
+
/**
|
|
2697
|
+
* Renumber nodes `_nativeIndex`. This is useful to allow to restore the
|
|
2698
|
+
* order after sorting a column.
|
|
2699
|
+
* This method is automatically called after loading new child nodes.
|
|
2700
|
+
* @since 0.11.0
|
|
2701
|
+
*/
|
|
2702
|
+
resetNativeChildOrder(options?: ResetOrderOptions) {
|
|
2703
|
+
const { recursive = true, propName = "_nativeIndex" } = options ?? {};
|
|
2704
|
+
|
|
2705
|
+
if (this.children) {
|
|
2706
|
+
this.children.forEach((child, i) => {
|
|
2707
|
+
child.data[propName] = i;
|
|
2708
|
+
if (recursive && child.children) {
|
|
2709
|
+
child.resetNativeChildOrder(options);
|
|
2710
|
+
}
|
|
2711
|
+
});
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
/**
|
|
2716
|
+
* Convenience method to implement column sorting.
|
|
2717
|
+
* @since 0.11.0
|
|
2718
|
+
*/
|
|
2719
|
+
sortByProperty(options: SortByPropertyOptions) {
|
|
2720
|
+
const {
|
|
2721
|
+
caseInsensitive = true,
|
|
2722
|
+
deep = true,
|
|
2723
|
+
nativeOrderPropName = "_nativeIndex",
|
|
2724
|
+
updateColInfo = false,
|
|
2725
|
+
} = options;
|
|
2726
|
+
|
|
2727
|
+
let order: SortOrderType;
|
|
2728
|
+
let colDef: ColumnDefinition | null;
|
|
2729
|
+
|
|
2730
|
+
if (updateColInfo) {
|
|
2731
|
+
colDef = this.tree["_columnsById"][options.colId!];
|
|
2732
|
+
util.assert(colDef, `Invalid colId specified: ${options.colId}`);
|
|
2733
|
+
order =
|
|
2734
|
+
options.order ??
|
|
2735
|
+
util.rotate(colDef!.sortOrder, ["asc", "desc", undefined]);
|
|
2736
|
+
|
|
2737
|
+
for (const col of this.tree.columns) {
|
|
2738
|
+
col.sortOrder = col === colDef ? order : undefined;
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
this.tree.update(ChangeType.colStructure);
|
|
2742
|
+
} else {
|
|
2743
|
+
order = options.order ?? "asc";
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
let propName = options.propName ?? (options.colId || "");
|
|
2747
|
+
if (propName === "*") {
|
|
2748
|
+
propName = "title";
|
|
2749
|
+
}
|
|
2750
|
+
if (order == null) {
|
|
2751
|
+
propName = nativeOrderPropName;
|
|
2752
|
+
order = "asc";
|
|
2753
|
+
}
|
|
2754
|
+
this.logDebug(`sortByProperty(), propName=${propName}, ${order}`, options);
|
|
2755
|
+
util.assert(propName, "No property name specified");
|
|
2756
|
+
|
|
2757
|
+
const cmp = (a: WunderbaumNode, b: WunderbaumNode) => {
|
|
2758
|
+
let av, bv;
|
|
2759
|
+
if (NODE_DICT_PROPS.has(<string>propName)) {
|
|
2760
|
+
av = a[propName as keyof WunderbaumNode];
|
|
2761
|
+
bv = b[propName as keyof WunderbaumNode];
|
|
2762
|
+
} else {
|
|
2763
|
+
av = a.data[propName];
|
|
2764
|
+
bv = b.data[propName];
|
|
2765
|
+
}
|
|
2766
|
+
if (caseInsensitive) {
|
|
2767
|
+
if (typeof av === "string") {
|
|
2768
|
+
av = av.toLowerCase();
|
|
2769
|
+
}
|
|
2770
|
+
if (typeof bv === "string") {
|
|
2771
|
+
bv = bv.toLowerCase();
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
if (order === "desc") {
|
|
2775
|
+
return av === bv ? 0 : av > bv ? -1 : 1;
|
|
2776
|
+
}
|
|
2777
|
+
return av === bv ? 0 : av > bv ? 1 : -1;
|
|
2778
|
+
};
|
|
2779
|
+
|
|
2780
|
+
return this.sortChildren(cmp, deep);
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2672
2783
|
/**
|
|
2673
2784
|
* Trigger `modifyChild` event on a parent to signal that a child was modified.
|
|
2674
2785
|
* @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
|