wunderbaum 0.7.0 → 0.8.1
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/dist/wunderbaum.css +4 -1
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +492 -277
- package/dist/wunderbaum.esm.js +915 -668
- package/dist/wunderbaum.esm.min.js +32 -32
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +7853 -7606
- package/dist/wunderbaum.umd.min.js +69 -70
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common.ts +1 -1
- package/src/deferred.ts +9 -9
- package/src/types.ts +186 -45
- package/src/util.ts +73 -33
- package/src/wb_ext_dnd.ts +37 -13
- package/src/wb_ext_edit.ts +90 -58
- package/src/wb_ext_filter.ts +5 -1
- package/src/wb_ext_keynav.ts +22 -11
- package/src/wb_ext_logger.ts +2 -1
- package/src/wb_node.ts +114 -50
- package/src/wb_options.ts +55 -29
- package/src/wunderbaum.scss +7 -1
- package/src/wunderbaum.ts +168 -74
package/src/wunderbaum.ts
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
DynamicIconOption,
|
|
52
52
|
DynamicStringOption,
|
|
53
53
|
DynamicBoolOption,
|
|
54
|
+
SetColumnOptions,
|
|
54
55
|
} from "./types";
|
|
55
56
|
import {
|
|
56
57
|
DEFAULT_DEBUGLEVEL,
|
|
@@ -64,6 +65,7 @@ import { WunderbaumNode } from "./wb_node";
|
|
|
64
65
|
import { Deferred } from "./deferred";
|
|
65
66
|
import { EditExtension } from "./wb_ext_edit";
|
|
66
67
|
import { WunderbaumOptions } from "./wb_options";
|
|
68
|
+
import { DebouncedFunction } from "./debounce";
|
|
67
69
|
|
|
68
70
|
class WbSystemRoot extends WunderbaumNode {
|
|
69
71
|
constructor(tree: Wunderbaum) {
|
|
@@ -80,7 +82,7 @@ class WbSystemRoot extends WunderbaumNode {
|
|
|
80
82
|
/**
|
|
81
83
|
* A persistent plain object or array.
|
|
82
84
|
*
|
|
83
|
-
* See also
|
|
85
|
+
* See also {@link WunderbaumOptions}.
|
|
84
86
|
*/
|
|
85
87
|
export class Wunderbaum {
|
|
86
88
|
protected static sequence = 0;
|
|
@@ -104,7 +106,7 @@ export class Wunderbaum {
|
|
|
104
106
|
/** Contains additional data that was sent as response to an Ajax source load request. */
|
|
105
107
|
public readonly data: { [key: string]: any } = {};
|
|
106
108
|
|
|
107
|
-
protected readonly _updateViewportThrottled: (
|
|
109
|
+
protected readonly _updateViewportThrottled: DebouncedFunction<() => void>;
|
|
108
110
|
protected extensionList: WunderbaumExtension<any>[] = [];
|
|
109
111
|
protected extensions: ExtensionsDict = {};
|
|
110
112
|
|
|
@@ -117,10 +119,23 @@ export class Wunderbaum {
|
|
|
117
119
|
protected _disableUpdateCount = 0;
|
|
118
120
|
protected _disableUpdateIgnoreCount = 0;
|
|
119
121
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
protected _activeNode: WunderbaumNode | null = null;
|
|
123
|
+
protected _focusNode: WunderbaumNode | null = null;
|
|
124
|
+
|
|
125
|
+
/** Currently active node if any.
|
|
126
|
+
* Use @link {WunderbaumNode.setActive|setActive} to modify.
|
|
127
|
+
*/
|
|
128
|
+
public get activeNode() {
|
|
129
|
+
// Check for deleted node, i.e. node.tree === null
|
|
130
|
+
return this._activeNode?.tree ? this._activeNode : null;
|
|
131
|
+
}
|
|
132
|
+
/** Current node hat has keyboard focus if any.
|
|
133
|
+
* Use @link {WunderbaumNode.setFocus|setFocus()} to modify.
|
|
134
|
+
*/
|
|
135
|
+
public get focusNode() {
|
|
136
|
+
// Check for deleted node, i.e. node.tree === null
|
|
137
|
+
return this._focusNode?.tree ? this._focusNode : null;
|
|
138
|
+
}
|
|
124
139
|
|
|
125
140
|
/** Shared properties, referenced by `node.type`. */
|
|
126
141
|
public types: NodeTypeDefinitionMap = {};
|
|
@@ -153,7 +168,7 @@ export class Wunderbaum {
|
|
|
153
168
|
public filterMode: FilterModeType = null;
|
|
154
169
|
|
|
155
170
|
// --- KEYNAV ---
|
|
156
|
-
/** @internal Use `setColumn()`/`getActiveColElem()
|
|
171
|
+
/** @internal Use `setColumn()`/`getActiveColElem()` to access. */
|
|
157
172
|
public activeColIdx = 0;
|
|
158
173
|
/** @internal */
|
|
159
174
|
public _cellNavMode = false;
|
|
@@ -366,6 +381,7 @@ export class Wunderbaum {
|
|
|
366
381
|
} else {
|
|
367
382
|
this.setNavigationOption(opts.navigationModeOption);
|
|
368
383
|
}
|
|
384
|
+
this.update(ChangeType.structure, { immediate: true });
|
|
369
385
|
readyDeferred.resolve();
|
|
370
386
|
})
|
|
371
387
|
.catch((error) => {
|
|
@@ -426,7 +442,7 @@ export class Wunderbaum {
|
|
|
426
442
|
node.isActive() &&
|
|
427
443
|
(!slowClickDelay || Date.now() - this.lastClickTime < slowClickDelay)
|
|
428
444
|
) {
|
|
429
|
-
|
|
445
|
+
node.startEditTitle();
|
|
430
446
|
}
|
|
431
447
|
|
|
432
448
|
if (info.colIdx >= 0) {
|
|
@@ -482,7 +498,7 @@ export class Wunderbaum {
|
|
|
482
498
|
|
|
483
499
|
this._callEvent("focus", { flag: flag, event: e });
|
|
484
500
|
|
|
485
|
-
if (flag && this.isRowNav() && !this.
|
|
501
|
+
if (flag && this.isRowNav() && !this.isEditingTitle()) {
|
|
486
502
|
if ((opts.navigationModeOption as NavModeEnum) === NavModeEnum.row) {
|
|
487
503
|
targetNode?.setActive();
|
|
488
504
|
} else {
|
|
@@ -506,7 +522,7 @@ export class Wunderbaum {
|
|
|
506
522
|
* getTree(1); // Get second Wunderbaum instance on page
|
|
507
523
|
* getTree(event); // Get tree for this mouse- or keyboard event
|
|
508
524
|
* getTree("foo"); // Get tree for this `tree.options.id`
|
|
509
|
-
* getTree("#tree"); // Get tree for
|
|
525
|
+
* getTree("#tree"); // Get tree for first matching element selector
|
|
510
526
|
* ```
|
|
511
527
|
*/
|
|
512
528
|
public static getTree(
|
|
@@ -614,37 +630,37 @@ export class Wunderbaum {
|
|
|
614
630
|
/** Add node to tree's bookkeeping data structures. */
|
|
615
631
|
_registerNode(node: WunderbaumNode): void {
|
|
616
632
|
const key = node.key;
|
|
617
|
-
util.assert(
|
|
618
|
-
|
|
619
|
-
`Missing or duplicate key: '${key}'.`
|
|
620
|
-
);
|
|
633
|
+
util.assert(key != null, `Missing key: '${node}'.`);
|
|
634
|
+
util.assert(!this.keyMap.has(key), `Duplicate key: '${key}': ${node}.`);
|
|
621
635
|
this.keyMap.set(key, node);
|
|
622
636
|
const rk = node.refKey;
|
|
623
|
-
if (rk) {
|
|
637
|
+
if (rk != null) {
|
|
624
638
|
const rks = this.refKeyMap.get(rk); // Set of nodes with this refKey
|
|
625
639
|
if (rks) {
|
|
626
640
|
rks.add(node);
|
|
627
641
|
} else {
|
|
628
|
-
this.refKeyMap.set(rk, new Set());
|
|
642
|
+
this.refKeyMap.set(rk, new Set([node]));
|
|
629
643
|
}
|
|
630
644
|
}
|
|
631
645
|
}
|
|
632
646
|
|
|
633
647
|
/** Remove node from tree's bookkeeping data structures. */
|
|
634
648
|
_unregisterNode(node: WunderbaumNode): void {
|
|
649
|
+
// Remove refKey reference from map (if any)
|
|
635
650
|
const rk = node.refKey;
|
|
636
|
-
if (rk) {
|
|
651
|
+
if (rk != null) {
|
|
637
652
|
const rks = this.refKeyMap.get(rk);
|
|
638
653
|
if (rks && rks.delete(node) && !rks.size) {
|
|
639
654
|
// We just removed the last element
|
|
640
655
|
this.refKeyMap.delete(rk);
|
|
641
656
|
}
|
|
642
657
|
}
|
|
643
|
-
//
|
|
658
|
+
// Remove key reference from map
|
|
659
|
+
this.keyMap.delete(node.key);
|
|
660
|
+
// Mark as disposed
|
|
644
661
|
(node.tree as any) = null;
|
|
645
662
|
(node.parent as any) = null;
|
|
646
|
-
//
|
|
647
|
-
// this.viewNodes.delete(node);
|
|
663
|
+
// Remove HTML markup
|
|
648
664
|
node.removeMarkup();
|
|
649
665
|
}
|
|
650
666
|
|
|
@@ -894,7 +910,7 @@ export class Wunderbaum {
|
|
|
894
910
|
this._callMethod("edit.createNode", "after");
|
|
895
911
|
break;
|
|
896
912
|
case "rename":
|
|
897
|
-
|
|
913
|
+
node.startEditTitle();
|
|
898
914
|
break;
|
|
899
915
|
// Simple clipboard simulation:
|
|
900
916
|
// case "cut":
|
|
@@ -942,10 +958,9 @@ export class Wunderbaum {
|
|
|
942
958
|
this.root.children = null;
|
|
943
959
|
this.keyMap.clear();
|
|
944
960
|
this.refKeyMap.clear();
|
|
945
|
-
// this.viewNodes.clear();
|
|
946
961
|
this.treeRowCount = 0;
|
|
947
|
-
this.
|
|
948
|
-
this.
|
|
962
|
+
this._activeNode = null;
|
|
963
|
+
this._focusNode = null;
|
|
949
964
|
|
|
950
965
|
// this.types = {};
|
|
951
966
|
// this. columns =[];
|
|
@@ -1159,15 +1174,33 @@ export class Wunderbaum {
|
|
|
1159
1174
|
/**
|
|
1160
1175
|
* Find all nodes that match condition.
|
|
1161
1176
|
*
|
|
1177
|
+
* @param match title string to search for, or a
|
|
1178
|
+
* callback function that returns `true` if a node is matched.
|
|
1162
1179
|
* @see {@link WunderbaumNode.findAll}
|
|
1163
1180
|
*/
|
|
1164
1181
|
findAll(match: string | RegExp | MatcherCallback) {
|
|
1165
1182
|
return this.root.findAll(match);
|
|
1166
1183
|
}
|
|
1167
1184
|
|
|
1185
|
+
/**
|
|
1186
|
+
* Find all nodes with a given _refKey_ (aka a list of clones).
|
|
1187
|
+
*
|
|
1188
|
+
* @param refKey a `node.refKey` value to search for.
|
|
1189
|
+
* @returns an array of matching nodes with at least two element or `[]`
|
|
1190
|
+
* if nothing found.
|
|
1191
|
+
*
|
|
1192
|
+
* @see {@link WunderbaumNode.getCloneList}
|
|
1193
|
+
*/
|
|
1194
|
+
findByRefKey(refKey: string): WunderbaumNode[] {
|
|
1195
|
+
const clones = this.refKeyMap.get(refKey);
|
|
1196
|
+
return clones ? Array.from(clones) : [];
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1168
1199
|
/**
|
|
1169
1200
|
* Find first node that matches condition.
|
|
1170
1201
|
*
|
|
1202
|
+
* @param match title string to search for, or a
|
|
1203
|
+
* callback function that returns `true` if a node is matched.
|
|
1171
1204
|
* @see {@link WunderbaumNode.findFirst}
|
|
1172
1205
|
*/
|
|
1173
1206
|
findFirst(match: string | RegExp | MatcherCallback) {
|
|
@@ -1177,8 +1210,6 @@ export class Wunderbaum {
|
|
|
1177
1210
|
/**
|
|
1178
1211
|
* Find first node that matches condition.
|
|
1179
1212
|
*
|
|
1180
|
-
* @param match title string to search for, or a
|
|
1181
|
-
* callback function that returns `true` if a node is matched.
|
|
1182
1213
|
* @see {@link WunderbaumNode.findFirst}
|
|
1183
1214
|
*
|
|
1184
1215
|
*/
|
|
@@ -1189,6 +1220,7 @@ export class Wunderbaum {
|
|
|
1189
1220
|
/**
|
|
1190
1221
|
* Find the next visible node that starts with `match`, starting at `startNode`
|
|
1191
1222
|
* and wrap-around at the end.
|
|
1223
|
+
* Used by quicksearch and keyboard navigation.
|
|
1192
1224
|
*/
|
|
1193
1225
|
findNextNode(
|
|
1194
1226
|
match: string | MatcherCallback,
|
|
@@ -1371,7 +1403,13 @@ export class Wunderbaum {
|
|
|
1371
1403
|
}
|
|
1372
1404
|
|
|
1373
1405
|
/**
|
|
1374
|
-
* Return the currently active node or null.
|
|
1406
|
+
* Return the currently active node or null (alias for `tree.activeNode`).
|
|
1407
|
+
* Alias for {@link Wunderbaum.activeNode}.
|
|
1408
|
+
*
|
|
1409
|
+
* @see {@link WunderbaumNode.setActive}
|
|
1410
|
+
* @see {@link WunderbaumNode.isActive}
|
|
1411
|
+
* @see {@link Wunderbaum.activeNode}
|
|
1412
|
+
* @see {@link Wunderbaum.focusNode}
|
|
1375
1413
|
*/
|
|
1376
1414
|
getActiveNode() {
|
|
1377
1415
|
return this.activeNode;
|
|
@@ -1385,7 +1423,12 @@ export class Wunderbaum {
|
|
|
1385
1423
|
}
|
|
1386
1424
|
|
|
1387
1425
|
/**
|
|
1388
|
-
* Return the currently
|
|
1426
|
+
* Return the node that currently has keyboard focus or null.
|
|
1427
|
+
* Alias for {@link Wunderbaum.focusNode}.
|
|
1428
|
+
* @see {@link WunderbaumNode.setFocus}
|
|
1429
|
+
* @see {@link WunderbaumNode.hasFocus}
|
|
1430
|
+
* @see {@link Wunderbaum.activeNode}
|
|
1431
|
+
* @see {@link Wunderbaum.focusNode}
|
|
1389
1432
|
*/
|
|
1390
1433
|
getFocusNode() {
|
|
1391
1434
|
return this.focusNode;
|
|
@@ -1462,8 +1505,22 @@ export class Wunderbaum {
|
|
|
1462
1505
|
return `Wunderbaum<'${this.id}'>`;
|
|
1463
1506
|
}
|
|
1464
1507
|
|
|
1465
|
-
/** Return true if any node is currently
|
|
1508
|
+
/** Return true if any node title or grid cell is currently beeing edited.
|
|
1509
|
+
*
|
|
1510
|
+
* See also {@link Wunderbaum.isEditingTitle}.
|
|
1511
|
+
*/
|
|
1466
1512
|
isEditing(): boolean {
|
|
1513
|
+
const focusElem = this.nodeListElement.querySelector(
|
|
1514
|
+
"input:focus,select:focus"
|
|
1515
|
+
);
|
|
1516
|
+
return !!focusElem;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
/** Return true if any node is currently in edit-title mode.
|
|
1520
|
+
*
|
|
1521
|
+
* See also {@link WunderbaumNode.isEditingTitle} and {@link Wunderbaum.isEditing}.
|
|
1522
|
+
*/
|
|
1523
|
+
isEditingTitle(): boolean {
|
|
1467
1524
|
return this._callMethod("edit.isEditingTitle");
|
|
1468
1525
|
}
|
|
1469
1526
|
|
|
@@ -1483,26 +1540,33 @@ export class Wunderbaum {
|
|
|
1483
1540
|
return res;
|
|
1484
1541
|
}
|
|
1485
1542
|
|
|
1486
|
-
/**
|
|
1487
|
-
* @
|
|
1543
|
+
/** Write to `console.log` with tree name as prefix if opts.debugLevel >= 4.
|
|
1544
|
+
* @see {@link Wunderbaum.logDebug}
|
|
1488
1545
|
*/
|
|
1489
|
-
log
|
|
1546
|
+
log(...args: any[]) {
|
|
1547
|
+
if (this.options.debugLevel! >= 4) {
|
|
1548
|
+
console.log(this.toString(), ...args); // eslint-disable-line no-console
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1490
1551
|
|
|
1491
|
-
/**
|
|
1552
|
+
/** Write to `console.debug` with tree name as prefix if opts.debugLevel >= 4.
|
|
1553
|
+
* and browser console level includes debug/verbose messages.
|
|
1554
|
+
* @see {@link Wunderbaum.log}
|
|
1555
|
+
*/
|
|
1492
1556
|
logDebug(...args: any[]) {
|
|
1493
1557
|
if (this.options.debugLevel! >= 4) {
|
|
1494
|
-
console.
|
|
1558
|
+
console.debug(this.toString(), ...args); // eslint-disable-line no-console
|
|
1495
1559
|
}
|
|
1496
1560
|
}
|
|
1497
1561
|
|
|
1498
|
-
/**
|
|
1562
|
+
/** Write to `console.error` with tree name as prefix. */
|
|
1499
1563
|
logError(...args: any[]) {
|
|
1500
1564
|
if (this.options.debugLevel! >= 1) {
|
|
1501
1565
|
console.error(this.toString(), ...args); // eslint-disable-line no-console
|
|
1502
1566
|
}
|
|
1503
1567
|
}
|
|
1504
1568
|
|
|
1505
|
-
/**
|
|
1569
|
+
/** Write to `console.info` with tree name as prefix if opts.debugLevel >= 3. */
|
|
1506
1570
|
logInfo(...args: any[]) {
|
|
1507
1571
|
if (this.options.debugLevel! >= 3) {
|
|
1508
1572
|
console.info(this.toString(), ...args); // eslint-disable-line no-console
|
|
@@ -1524,7 +1588,7 @@ export class Wunderbaum {
|
|
|
1524
1588
|
}
|
|
1525
1589
|
}
|
|
1526
1590
|
|
|
1527
|
-
/**
|
|
1591
|
+
/** Write to `console.warn` with tree name as prefix with if opts.debugLevel >= 2. */
|
|
1528
1592
|
logWarn(...args: any[]) {
|
|
1529
1593
|
if (this.options.debugLevel! >= 2) {
|
|
1530
1594
|
console.warn(this.toString(), ...args); // eslint-disable-line no-console
|
|
@@ -1622,11 +1686,24 @@ export class Wunderbaum {
|
|
|
1622
1686
|
/**
|
|
1623
1687
|
* Set column #colIdx to 'active'.
|
|
1624
1688
|
*
|
|
1625
|
-
* This higlights the column header and -cells by adding the `wb-active`
|
|
1689
|
+
* This higlights the column header and -cells by adding the `wb-active`
|
|
1690
|
+
* class to all grid cells of the active column. <br>
|
|
1626
1691
|
* Available in cell-nav mode only.
|
|
1692
|
+
*
|
|
1693
|
+
* If _options.edit_ is true, the embedded input element is focused, or if
|
|
1694
|
+
* colIdx is 0, the node title is put into edit mode.
|
|
1627
1695
|
*/
|
|
1628
|
-
setColumn(colIdx: number) {
|
|
1629
|
-
|
|
1696
|
+
setColumn(colIdx: number | string, options?: SetColumnOptions) {
|
|
1697
|
+
const edit = options?.edit;
|
|
1698
|
+
const scroll = options?.scrollIntoView !== false;
|
|
1699
|
+
|
|
1700
|
+
util.assert(this.isCellNav(), "Expected cellNav mode");
|
|
1701
|
+
|
|
1702
|
+
if (typeof colIdx === "string") {
|
|
1703
|
+
const cid = colIdx;
|
|
1704
|
+
colIdx = this.columns.findIndex((c) => c.id === colIdx);
|
|
1705
|
+
util.assert(colIdx >= 0, `Invalid colId: ${cid}`);
|
|
1706
|
+
}
|
|
1630
1707
|
util.assert(
|
|
1631
1708
|
0 <= colIdx && colIdx < this.columns.length,
|
|
1632
1709
|
`Invalid colIdx: ${colIdx}`
|
|
@@ -1652,18 +1729,34 @@ export class Wunderbaum {
|
|
|
1652
1729
|
(colDiv as HTMLElement).classList.toggle("wb-active", i++ === colIdx);
|
|
1653
1730
|
}
|
|
1654
1731
|
}
|
|
1655
|
-
//
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1732
|
+
// Horizontically scroll into view
|
|
1733
|
+
if (scroll || edit) {
|
|
1734
|
+
this.scrollToHorz();
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
if (edit && this.activeNode) {
|
|
1738
|
+
// this.activeNode.setFocus(); // Blur prev. input if any
|
|
1739
|
+
if (colIdx === 0) {
|
|
1740
|
+
this.activeNode.startEditTitle();
|
|
1741
|
+
} else {
|
|
1742
|
+
this.getActiveColElem()
|
|
1743
|
+
?.querySelector<HTMLInputElement>("input,select")
|
|
1744
|
+
?.focus();
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
/* Set or remove keyboard focus to the tree container. @internal */
|
|
1750
|
+
_setActiveNode(node: WunderbaumNode | null) {
|
|
1751
|
+
this._activeNode = node;
|
|
1659
1752
|
}
|
|
1660
1753
|
|
|
1661
|
-
/** Set or remove
|
|
1754
|
+
/** Set or remove keyboard focus to the tree container. */
|
|
1662
1755
|
setActiveNode(key: string, flag: boolean = true, options?: SetActiveOptions) {
|
|
1663
1756
|
this.findKey(key)?.setActive(flag, options);
|
|
1664
1757
|
}
|
|
1665
1758
|
|
|
1666
|
-
/** Set or remove
|
|
1759
|
+
/** Set or remove keyboard focus to the tree container. */
|
|
1667
1760
|
setFocus(flag = true) {
|
|
1668
1761
|
if (flag) {
|
|
1669
1762
|
this.element.focus();
|
|
@@ -1672,10 +1765,16 @@ export class Wunderbaum {
|
|
|
1672
1765
|
}
|
|
1673
1766
|
}
|
|
1674
1767
|
|
|
1768
|
+
/* Set or remove keyboard focus to the tree container. @internal */
|
|
1769
|
+
_setFocusNode(node: WunderbaumNode | null) {
|
|
1770
|
+
this._focusNode = node;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1675
1773
|
/**
|
|
1676
1774
|
* Schedule an update request to reflect a tree change.
|
|
1677
1775
|
* The render operation is async and debounced unless the `immediate` option
|
|
1678
1776
|
* is set.
|
|
1777
|
+
*
|
|
1679
1778
|
* Use {@link WunderbaumNode.update()} if only a single node has changed,
|
|
1680
1779
|
* or {@link WunderbaumNode._render()}) to pass special options.
|
|
1681
1780
|
*/
|
|
@@ -1694,26 +1793,27 @@ export class Wunderbaum {
|
|
|
1694
1793
|
|
|
1695
1794
|
update(
|
|
1696
1795
|
change: ChangeType,
|
|
1697
|
-
node?: WunderbaumNode |
|
|
1796
|
+
node?: WunderbaumNode | UpdateOptions,
|
|
1698
1797
|
options?: UpdateOptions
|
|
1699
1798
|
): void {
|
|
1700
|
-
if (this._disableUpdateCount) {
|
|
1701
|
-
// Assuming that we redraw all when enableUpdate() is re-enabled.
|
|
1702
|
-
// this.log(
|
|
1703
|
-
// `IGNORED update(${change}) node=${node} (disable level ${this._disableUpdateCount})`
|
|
1704
|
-
// );
|
|
1705
|
-
this._disableUpdateIgnoreCount++;
|
|
1706
|
-
return;
|
|
1707
|
-
}
|
|
1708
1799
|
// this.log(`update(${change}) node=${node}`);
|
|
1709
1800
|
if (!(node instanceof WunderbaumNode)) {
|
|
1710
1801
|
options = node;
|
|
1711
|
-
node =
|
|
1802
|
+
node = undefined;
|
|
1712
1803
|
}
|
|
1804
|
+
|
|
1713
1805
|
const immediate = !!util.getOption(options, "immediate");
|
|
1714
1806
|
const RF = RenderFlag;
|
|
1715
1807
|
const pending = this.pendingChangeTypes;
|
|
1716
1808
|
|
|
1809
|
+
if (this._disableUpdateCount) {
|
|
1810
|
+
// Assuming that we redraw all when enableUpdate() is re-enabled.
|
|
1811
|
+
// this.log(
|
|
1812
|
+
// `IGNORED update(${change}) node=${node} (disable level ${this._disableUpdateCount})`
|
|
1813
|
+
// );
|
|
1814
|
+
this._disableUpdateIgnoreCount++;
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1717
1817
|
switch (change) {
|
|
1718
1818
|
case ChangeType.any:
|
|
1719
1819
|
case ChangeType.colStructure:
|
|
@@ -1739,8 +1839,8 @@ export class Wunderbaum {
|
|
|
1739
1839
|
util.assert(node, `Option '${change}' requires a node.`);
|
|
1740
1840
|
// Single nodes are immediately updated if already inside the viewport
|
|
1741
1841
|
// (otherwise we can ignore)
|
|
1742
|
-
if (node
|
|
1743
|
-
node
|
|
1842
|
+
if ((<WunderbaumNode>node)!._rowElem) {
|
|
1843
|
+
(<WunderbaumNode>node)!._render({ change: change });
|
|
1744
1844
|
}
|
|
1745
1845
|
break;
|
|
1746
1846
|
default:
|
|
@@ -2069,12 +2169,15 @@ export class Wunderbaum {
|
|
|
2069
2169
|
protected _updateViewportImmediately() {
|
|
2070
2170
|
if (this._disableUpdateCount) {
|
|
2071
2171
|
this.log(
|
|
2072
|
-
`_updateViewportImmediately() IGNORED (disable level: ${this._disableUpdateCount})
|
|
2172
|
+
`_updateViewportImmediately() IGNORED (disable level: ${this._disableUpdateCount}).`
|
|
2073
2173
|
);
|
|
2074
2174
|
this._disableUpdateIgnoreCount++;
|
|
2075
2175
|
return;
|
|
2076
2176
|
}
|
|
2077
|
-
|
|
2177
|
+
if (this._updateViewportThrottled.pending()) {
|
|
2178
|
+
// this.logWarn(`_updateViewportImmediately() cancel pending timer.`);
|
|
2179
|
+
this._updateViewportThrottled.cancel();
|
|
2180
|
+
}
|
|
2078
2181
|
// Shorten container height to avoid v-scrollbar
|
|
2079
2182
|
const FIX_ADJUST_HEIGHT = 1;
|
|
2080
2183
|
const RF = RenderFlag;
|
|
@@ -2189,9 +2292,6 @@ export class Wunderbaum {
|
|
|
2189
2292
|
let endIdx = Math.max(0, (ofs + vp_height) / row_height + prefetch);
|
|
2190
2293
|
endIdx = Math.ceil(endIdx);
|
|
2191
2294
|
|
|
2192
|
-
// const obsoleteViewNodes = this.viewNodes;
|
|
2193
|
-
// this.viewNodes = new Set();
|
|
2194
|
-
// const viewNodes = this.viewNodes;
|
|
2195
2295
|
// this.debug("render", opts);
|
|
2196
2296
|
const obsoleteNodes = new Set<WunderbaumNode>();
|
|
2197
2297
|
this.nodeListElement.childNodes.forEach((elem) => {
|
|
@@ -2485,7 +2585,7 @@ export class Wunderbaum {
|
|
|
2485
2585
|
* FILTER
|
|
2486
2586
|
* -------------------------------------------------------------------------*/
|
|
2487
2587
|
/**
|
|
2488
|
-
*
|
|
2588
|
+
* Dim or hide nodes.
|
|
2489
2589
|
*/
|
|
2490
2590
|
filterNodes(
|
|
2491
2591
|
filter: string | NodeFilterCallback,
|
|
@@ -2498,7 +2598,7 @@ export class Wunderbaum {
|
|
|
2498
2598
|
}
|
|
2499
2599
|
|
|
2500
2600
|
/**
|
|
2501
|
-
*
|
|
2601
|
+
* Dim or hide whole branches.
|
|
2502
2602
|
*/
|
|
2503
2603
|
filterBranches(
|
|
2504
2604
|
filter: string | NodeFilterCallback,
|
|
@@ -2511,25 +2611,19 @@ export class Wunderbaum {
|
|
|
2511
2611
|
}
|
|
2512
2612
|
|
|
2513
2613
|
/**
|
|
2514
|
-
*
|
|
2515
|
-
*
|
|
2516
|
-
* @requires [[FilterExtension]]
|
|
2614
|
+
* Reset the filter.
|
|
2517
2615
|
*/
|
|
2518
2616
|
clearFilter() {
|
|
2519
2617
|
return (this.extensions.filter as FilterExtension).clearFilter();
|
|
2520
2618
|
}
|
|
2521
2619
|
/**
|
|
2522
|
-
*
|
|
2523
|
-
*
|
|
2524
|
-
* @requires [[FilterExtension]]
|
|
2620
|
+
* Return true if a filter is currently applied.
|
|
2525
2621
|
*/
|
|
2526
2622
|
isFilterActive() {
|
|
2527
2623
|
return !!this.filterMode;
|
|
2528
2624
|
}
|
|
2529
2625
|
/**
|
|
2530
|
-
*
|
|
2531
|
-
*
|
|
2532
|
-
* @requires [[FilterExtension]]
|
|
2626
|
+
* Re-apply current filter.
|
|
2533
2627
|
*/
|
|
2534
2628
|
updateFilter() {
|
|
2535
2629
|
return (this.extensions.filter as FilterExtension).updateFilter();
|