wunderbaum 0.13.0 → 0.14.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/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 +622 -222
- package/dist/wunderbaum.esm.min.js +28 -28
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +622 -222
- 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 +225 -107
- package/src/wb_options.ts +169 -108
- package/src/wunderbaum.ts +351 -127
package/src/wunderbaum.ts
CHANGED
|
@@ -25,11 +25,6 @@ import {
|
|
|
25
25
|
ApplyCommandType,
|
|
26
26
|
ChangeType,
|
|
27
27
|
ColumnDefinitionList,
|
|
28
|
-
DynamicBoolOption,
|
|
29
|
-
DynamicCheckboxOption,
|
|
30
|
-
DynamicIconOption,
|
|
31
|
-
DynamicStringOption,
|
|
32
|
-
DynamicTooltipOption,
|
|
33
28
|
ExpandAllOptions,
|
|
34
29
|
FilterModeType,
|
|
35
30
|
FilterNodesOptions,
|
|
@@ -51,7 +46,6 @@ import {
|
|
|
51
46
|
SetColumnOptions,
|
|
52
47
|
SetStateOptions,
|
|
53
48
|
SetStatusOptions,
|
|
54
|
-
SortByPropertyOptions,
|
|
55
49
|
SortCallback,
|
|
56
50
|
SourceType,
|
|
57
51
|
TreeStateDefinition,
|
|
@@ -59,20 +53,29 @@ import {
|
|
|
59
53
|
VisitRowsOptions,
|
|
60
54
|
WbEventInfo,
|
|
61
55
|
WbNodeData,
|
|
56
|
+
FilterOptionsType,
|
|
57
|
+
EditOptionsType,
|
|
58
|
+
DndOptionsType,
|
|
59
|
+
SortOptions,
|
|
60
|
+
DeprecationOptions,
|
|
61
|
+
SortByPropertyOptions,
|
|
62
|
+
ReloadOptions,
|
|
63
|
+
LoadLazyNodesOptions,
|
|
62
64
|
} from "./types";
|
|
63
65
|
import {
|
|
64
66
|
DEFAULT_DEBUGLEVEL,
|
|
65
|
-
|
|
67
|
+
defaultIconMaps,
|
|
66
68
|
makeNodeTitleStartMatcher,
|
|
67
69
|
nodeTitleSorter,
|
|
68
70
|
RENDER_MAX_PREFETCH,
|
|
69
71
|
DEFAULT_ROW_HEIGHT,
|
|
70
|
-
|
|
72
|
+
TEST_FILE_PATH,
|
|
73
|
+
TEST_HTML,
|
|
71
74
|
} from "./common";
|
|
72
75
|
import { WunderbaumNode } from "./wb_node";
|
|
73
76
|
import { Deferred } from "./deferred";
|
|
74
77
|
import { EditExtension } from "./wb_ext_edit";
|
|
75
|
-
import { WunderbaumOptions } from "./wb_options";
|
|
78
|
+
import { InitWunderbaumOptions, WunderbaumOptions } from "./wb_options";
|
|
76
79
|
import { DebouncedFunction } from "./debounce";
|
|
77
80
|
|
|
78
81
|
class WbSystemRoot extends WunderbaumNode {
|
|
@@ -116,7 +119,7 @@ export class Wunderbaum {
|
|
|
116
119
|
|
|
117
120
|
protected readonly _updateViewportThrottled: DebouncedFunction<() => void>;
|
|
118
121
|
protected extensionList: WunderbaumExtension<any>[] = [];
|
|
119
|
-
protected extensions: ExtensionsDict = {};
|
|
122
|
+
protected extensions: ExtensionsDict = <ExtensionsDict>{};
|
|
120
123
|
|
|
121
124
|
/** Merged options from constructor args and tree- and extension defaults. */
|
|
122
125
|
public options: WunderbaumOptions;
|
|
@@ -129,6 +132,7 @@ export class Wunderbaum {
|
|
|
129
132
|
|
|
130
133
|
protected _activeNode: WunderbaumNode | null = null;
|
|
131
134
|
protected _focusNode: WunderbaumNode | null = null;
|
|
135
|
+
protected _initialSource: SourceType | null = null;
|
|
132
136
|
|
|
133
137
|
/** Currently active node if any.
|
|
134
138
|
* Use {@link WunderbaumNode.setActive|setActive} to modify.
|
|
@@ -148,18 +152,7 @@ export class Wunderbaum {
|
|
|
148
152
|
/** Shared properties, referenced by `node.type`. */
|
|
149
153
|
public types: NodeTypeDefinitionMap = {};
|
|
150
154
|
/** List of column definitions. */
|
|
151
|
-
public columns: ColumnDefinitionList = [];
|
|
152
|
-
/** Show/hide a checkbox or radiobutton. */
|
|
153
|
-
public checkbox?: DynamicCheckboxOption;
|
|
154
|
-
/** Show/hide a node icon. */
|
|
155
|
-
public icon?: DynamicIconOption;
|
|
156
|
-
/** Show/hide a tooltip for the node icon. */
|
|
157
|
-
public iconTooltip?: DynamicStringOption;
|
|
158
|
-
/** Show/hide a tooltip. */
|
|
159
|
-
public tooltip?: DynamicTooltipOption;
|
|
160
|
-
/** Define a node checkbox as readonly. */
|
|
161
|
-
public unselectable?: DynamicBoolOption;
|
|
162
|
-
|
|
155
|
+
public columns: ColumnDefinitionList = [];
|
|
163
156
|
protected _columnsById: { [key: string]: any } = {};
|
|
164
157
|
protected resizeObserver: ResizeObserver;
|
|
165
158
|
|
|
@@ -170,11 +163,22 @@ export class Wunderbaum {
|
|
|
170
163
|
public readonly ready: Promise<any>;
|
|
171
164
|
/** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
|
|
172
165
|
public static util = util;
|
|
166
|
+
/** A map of default iconMaps.
|
|
167
|
+
* May be used as default, when passing partial icon definition maps:
|
|
168
|
+
* ```js
|
|
169
|
+
* const tree = new mar10.Wunderbaum({
|
|
170
|
+
* ...
|
|
171
|
+
* iconMap: Object.assign(Wunderbaum.iconMaps.bootstrap, {
|
|
172
|
+
* folder: "bi bi-archive",
|
|
173
|
+
* }),
|
|
174
|
+
* });
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
public static iconMaps = defaultIconMaps;
|
|
173
178
|
/** Expose some useful methods of the util.ts module as `tree._util`. */
|
|
174
179
|
public _util = util;
|
|
175
180
|
|
|
176
181
|
// --- SELECT ---
|
|
177
|
-
// /** @internal */
|
|
178
182
|
// public selectRangeAnchor: WunderbaumNode | null = null;
|
|
179
183
|
|
|
180
184
|
// --- BREADCRUMB ---
|
|
@@ -198,39 +202,50 @@ export class Wunderbaum {
|
|
|
198
202
|
// --- EDIT ---
|
|
199
203
|
protected lastClickTime = 0;
|
|
200
204
|
|
|
201
|
-
constructor(options:
|
|
202
|
-
|
|
205
|
+
constructor(options: InitWunderbaumOptions) {
|
|
206
|
+
// Set default options and merge with user options
|
|
207
|
+
const initOptions = Object.assign<
|
|
208
|
+
InitWunderbaumOptions,
|
|
209
|
+
InitWunderbaumOptions
|
|
210
|
+
>(
|
|
203
211
|
{
|
|
204
|
-
id:
|
|
205
|
-
source:
|
|
206
|
-
element: null,
|
|
212
|
+
id: undefined,
|
|
213
|
+
source: [], // URL for GET/PUT, Ajax options, or callback
|
|
214
|
+
element: util.unsafeCast<string>(null),
|
|
207
215
|
debugLevel: DEFAULT_DEBUGLEVEL, // 0:quiet, 1:errors, 2:warnings, 3:info, 4:verbose
|
|
208
216
|
header: null, // Show/hide header (pass bool or string)
|
|
209
|
-
// headerHeightPx: ROW_HEIGHT,
|
|
210
217
|
rowHeightPx: DEFAULT_ROW_HEIGHT,
|
|
211
218
|
iconMap: "bootstrap",
|
|
212
|
-
columns: null,
|
|
213
|
-
types:
|
|
214
|
-
// escapeTitles: true,
|
|
219
|
+
columns: [], //util.unsafeCast<ColumnDefinitionList>(null),
|
|
220
|
+
types: {},
|
|
215
221
|
enabled: true,
|
|
216
222
|
fixedCol: false,
|
|
217
223
|
showSpinner: false,
|
|
218
224
|
checkbox: false,
|
|
219
225
|
minExpandLevel: 0,
|
|
220
226
|
emptyChildListExpandable: false,
|
|
221
|
-
// updateThrottleWait: 200,
|
|
222
227
|
skeleton: false,
|
|
228
|
+
autoCollapse: false,
|
|
229
|
+
adjustHeight: true,
|
|
223
230
|
connectTopBreadcrumb: null,
|
|
231
|
+
columnsFilterable: false,
|
|
232
|
+
columnsMenu: false,
|
|
233
|
+
columnsResizable: false,
|
|
234
|
+
columnsSortable: false,
|
|
224
235
|
selectMode: "multi", // SelectModeType
|
|
236
|
+
scrollIntoViewOnExpandClick: true,
|
|
237
|
+
// --- Extensions (actually set by exensions on init)
|
|
238
|
+
dnd: util.unsafeCast<DndOptionsType>(null),
|
|
239
|
+
edit: util.unsafeCast<EditOptionsType>(null),
|
|
240
|
+
filter: util.unsafeCast<FilterOptionsType>(null),
|
|
225
241
|
// --- KeyNav ---
|
|
226
|
-
navigationModeOption: null,
|
|
242
|
+
navigationModeOption: util.unsafeCast<NavModeEnum>(null),
|
|
227
243
|
quicksearch: true,
|
|
228
244
|
// --- Events ---
|
|
229
|
-
iconBadge: null,
|
|
230
|
-
change: null,
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
receive: null,
|
|
245
|
+
// iconBadge: null,
|
|
246
|
+
// change: null,
|
|
247
|
+
// ...
|
|
248
|
+
|
|
234
249
|
// --- Strings ---
|
|
235
250
|
strings: {
|
|
236
251
|
loadError: "Error",
|
|
@@ -243,7 +258,9 @@ export class Wunderbaum {
|
|
|
243
258
|
},
|
|
244
259
|
},
|
|
245
260
|
options
|
|
246
|
-
)
|
|
261
|
+
);
|
|
262
|
+
const opts = initOptions as WunderbaumOptions;
|
|
263
|
+
this.options = opts;
|
|
247
264
|
|
|
248
265
|
const readyDeferred = new Deferred();
|
|
249
266
|
this.ready = readyDeferred.promise();
|
|
@@ -270,7 +287,8 @@ export class Wunderbaum {
|
|
|
270
287
|
}
|
|
271
288
|
});
|
|
272
289
|
|
|
273
|
-
this.id =
|
|
290
|
+
this.id = initOptions.id || "wb_" + ++Wunderbaum.sequence;
|
|
291
|
+
delete initOptions.id;
|
|
274
292
|
this.root = new WbSystemRoot(this);
|
|
275
293
|
|
|
276
294
|
this._registerExtension(new KeynavExtension(this));
|
|
@@ -286,21 +304,25 @@ export class Wunderbaum {
|
|
|
286
304
|
);
|
|
287
305
|
|
|
288
306
|
// --- Evaluate options
|
|
289
|
-
this.columns =
|
|
290
|
-
delete
|
|
307
|
+
this.columns = initOptions.columns || [];
|
|
308
|
+
delete initOptions.columns;
|
|
291
309
|
if (!this.columns || !this.columns.length) {
|
|
292
310
|
const title = typeof opts.header === "string" ? opts.header : this.id;
|
|
293
311
|
this.columns = [{ id: "*", title: title, width: "*" }];
|
|
294
312
|
}
|
|
295
313
|
|
|
296
|
-
if (
|
|
297
|
-
this.setTypes(
|
|
314
|
+
if (initOptions.types) {
|
|
315
|
+
this.setTypes(initOptions.types, true);
|
|
298
316
|
}
|
|
299
|
-
delete
|
|
317
|
+
delete initOptions.types;
|
|
300
318
|
|
|
301
319
|
// --- Create Markup
|
|
302
|
-
this.element = util.elemFromSelector<HTMLDivElement>(
|
|
303
|
-
util.assert(
|
|
320
|
+
this.element = util.elemFromSelector<HTMLDivElement>(initOptions.element)!;
|
|
321
|
+
util.assert(
|
|
322
|
+
!!this.element,
|
|
323
|
+
`Invalid 'element' option: ${initOptions.element}`
|
|
324
|
+
);
|
|
325
|
+
delete (<any>initOptions).element;
|
|
304
326
|
|
|
305
327
|
this.element.classList.add("wunderbaum");
|
|
306
328
|
if (!this.element.getAttribute("tabindex")) {
|
|
@@ -403,17 +425,17 @@ export class Wunderbaum {
|
|
|
403
425
|
|
|
404
426
|
// --- apply initial options
|
|
405
427
|
["enabled", "fixedCol"].forEach((optName) => {
|
|
406
|
-
if (opts[optName] != null) {
|
|
407
|
-
this.setOption(optName, opts[optName]);
|
|
428
|
+
if ((opts as any)[optName] != null) {
|
|
429
|
+
this.setOption(optName, (opts as any)[optName]);
|
|
408
430
|
}
|
|
409
431
|
});
|
|
410
432
|
|
|
411
433
|
// --- Load initial data
|
|
412
|
-
if (
|
|
434
|
+
if (initOptions.source) {
|
|
413
435
|
if (opts.showSpinner) {
|
|
414
436
|
this.nodeListElement.innerHTML = `<progress class='spinner'>${opts.strings.loading}</progress>`;
|
|
415
437
|
}
|
|
416
|
-
this.load(
|
|
438
|
+
this.load(initOptions.source)
|
|
417
439
|
.then(() => {
|
|
418
440
|
// The source may have defined columns, so we may adjust the nav mode
|
|
419
441
|
if (opts.navigationModeOption == null) {
|
|
@@ -444,16 +466,20 @@ export class Wunderbaum {
|
|
|
444
466
|
this.update(ChangeType.any);
|
|
445
467
|
|
|
446
468
|
// --- Bind listeners
|
|
447
|
-
this.
|
|
448
|
-
// this.log(`scroll, scrollTop:${e.target.scrollTop}`, e);
|
|
449
|
-
this.update(ChangeType.scroll);
|
|
450
|
-
});
|
|
469
|
+
this._registerEventHandlers();
|
|
451
470
|
|
|
452
471
|
this.resizeObserver = new ResizeObserver((entries) => {
|
|
453
472
|
// this.log("ResizeObserver: Size changed", entries);
|
|
454
473
|
this.update(ChangeType.resize);
|
|
455
474
|
});
|
|
456
475
|
this.resizeObserver.observe(this.element);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private _registerEventHandlers() {
|
|
479
|
+
this.element.addEventListener("scroll", (e: Event) => {
|
|
480
|
+
// this.log(`scroll, scrollTop:${e.target.scrollTop}`, e);
|
|
481
|
+
this.update(ChangeType.scroll);
|
|
482
|
+
});
|
|
457
483
|
|
|
458
484
|
util.onEvent(this.element, "click", ".wb-button,.wb-col-icon", (e) => {
|
|
459
485
|
const info = Wunderbaum.getEventInfo(e);
|
|
@@ -473,10 +499,6 @@ export class Wunderbaum {
|
|
|
473
499
|
|
|
474
500
|
// this.log("click", info);
|
|
475
501
|
|
|
476
|
-
// if (this._selectRange(info) === false) {
|
|
477
|
-
// return;
|
|
478
|
-
// }
|
|
479
|
-
|
|
480
502
|
if (
|
|
481
503
|
this._callEvent("click", { event: e, node: node, info: info }) === false
|
|
482
504
|
) {
|
|
@@ -500,18 +522,18 @@ export class Wunderbaum {
|
|
|
500
522
|
node.startEditTitle();
|
|
501
523
|
}
|
|
502
524
|
|
|
503
|
-
if (info.colIdx >= 0) {
|
|
504
|
-
node.setActive(true, { colIdx: info.colIdx, event: e });
|
|
505
|
-
} else {
|
|
506
|
-
node.setActive(true, { event: e });
|
|
507
|
-
}
|
|
508
|
-
|
|
509
525
|
if (info.region === NodeRegion.expander) {
|
|
510
526
|
node.setExpanded(!node.isExpanded(), {
|
|
511
|
-
scrollIntoView: options.scrollIntoViewOnExpandClick !== false,
|
|
527
|
+
scrollIntoView: this.options.scrollIntoViewOnExpandClick !== false,
|
|
512
528
|
});
|
|
513
529
|
} else if (info.region === NodeRegion.checkbox) {
|
|
514
530
|
node.toggleSelected();
|
|
531
|
+
} else {
|
|
532
|
+
if (info.colIdx >= 0) {
|
|
533
|
+
node.setActive(true, { colIdx: info.colIdx, event: e });
|
|
534
|
+
} else {
|
|
535
|
+
node.setActive(true, { event: e });
|
|
536
|
+
}
|
|
515
537
|
}
|
|
516
538
|
}
|
|
517
539
|
this.lastClickTime = Date.now();
|
|
@@ -559,7 +581,7 @@ export class Wunderbaum {
|
|
|
559
581
|
this._callEvent("focus", { flag: flag, event: e });
|
|
560
582
|
|
|
561
583
|
if (flag && this.isRowNav() && !this.isEditingTitle()) {
|
|
562
|
-
if (
|
|
584
|
+
if (this.options.navigationModeOption === NavModeEnum.row) {
|
|
563
585
|
targetNode?.setActive();
|
|
564
586
|
} else {
|
|
565
587
|
this.setCellNav();
|
|
@@ -573,7 +595,6 @@ export class Wunderbaum {
|
|
|
573
595
|
}
|
|
574
596
|
});
|
|
575
597
|
}
|
|
576
|
-
|
|
577
598
|
/**
|
|
578
599
|
* Return a Wunderbaum instance, from element, id, index, or event.
|
|
579
600
|
*
|
|
@@ -627,14 +648,16 @@ export class Wunderbaum {
|
|
|
627
648
|
|
|
628
649
|
/**
|
|
629
650
|
* Return the icon-function -> icon-definition mapping.
|
|
651
|
+
* @deprecated Use {@link Wunderbaum.iconMaps}
|
|
630
652
|
*/
|
|
631
653
|
get iconMap(): IconMapType {
|
|
632
|
-
const map = this.options.iconMap
|
|
654
|
+
const map = this.options.iconMap;
|
|
633
655
|
if (typeof map === "string") {
|
|
634
|
-
return
|
|
656
|
+
return defaultIconMaps[map as keyof typeof defaultIconMaps];
|
|
635
657
|
}
|
|
636
658
|
return map;
|
|
637
659
|
}
|
|
660
|
+
|
|
638
661
|
/**
|
|
639
662
|
* Return a WunderbaumNode instance from element or event.
|
|
640
663
|
*/
|
|
@@ -687,7 +710,42 @@ export class Wunderbaum {
|
|
|
687
710
|
}
|
|
688
711
|
}
|
|
689
712
|
|
|
690
|
-
/**
|
|
713
|
+
/**
|
|
714
|
+
* Calculate a *stable*, unique key for a node from its refKey (or title).
|
|
715
|
+
* We also add information from the parent, because a refKey may occur multiple
|
|
716
|
+
* times in a tree (but not as child of the same parent).
|
|
717
|
+
* @internal
|
|
718
|
+
*/
|
|
719
|
+
_calculateKey(data: WbNodeData, parent?: WunderbaumNode): string {
|
|
720
|
+
if (data.key) {
|
|
721
|
+
// Always use an explicitly passed key
|
|
722
|
+
return data.key;
|
|
723
|
+
}
|
|
724
|
+
// Auto-keys are optional, use a monotonic counter by default:
|
|
725
|
+
if (!this.options.autoKeys) {
|
|
726
|
+
return "" + ++WunderbaumNode.sequence;
|
|
727
|
+
}
|
|
728
|
+
// Add the parent's key to the hash. Assuming this was generated by the
|
|
729
|
+
// same algorithm, this should incorporate the whole path:
|
|
730
|
+
const s = (parent ? parent.key : "") + (data.refKey || data.title);
|
|
731
|
+
// 32-bit has a high probability of collisions, so we pump up to 64-bit
|
|
732
|
+
// https://security.stackexchange.com/q/209882/207588
|
|
733
|
+
const h1 = util.murmurHash3(s, true);
|
|
734
|
+
let key = "id_" + h1 + util.murmurHash3(h1 + s, true);
|
|
735
|
+
// Check for collisions
|
|
736
|
+
// (Most likely if the same title occurs multiple in the same parent).
|
|
737
|
+
const existingNode = this.keyMap.get(key);
|
|
738
|
+
if (existingNode) {
|
|
739
|
+
key += "." + ++Wunderbaum.sequence;
|
|
740
|
+
this.logWarn(
|
|
741
|
+
`Node with existing key: '${existingNode}', using ${key}.`,
|
|
742
|
+
data
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
return key;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/** Add node to tree's bookkeeping data structures. @internal */
|
|
691
749
|
_registerNode(node: WunderbaumNode): void {
|
|
692
750
|
const key = node.key;
|
|
693
751
|
util.assert(key != null, `Missing key: '${node}'.`);
|
|
@@ -704,7 +762,7 @@ export class Wunderbaum {
|
|
|
704
762
|
}
|
|
705
763
|
}
|
|
706
764
|
|
|
707
|
-
/** Remove node from tree's bookkeeping data structures. */
|
|
765
|
+
/** Remove node from tree's bookkeeping data structures. @internal */
|
|
708
766
|
_unregisterNode(node: WunderbaumNode): void {
|
|
709
767
|
// Remove refKey reference from map (if any)
|
|
710
768
|
const rk = node.refKey;
|
|
@@ -807,7 +865,7 @@ export class Wunderbaum {
|
|
|
807
865
|
* pixel is visible.
|
|
808
866
|
*/
|
|
809
867
|
getTopmostVpNode(complete = true) {
|
|
810
|
-
const rowHeight = this.options.rowHeightPx
|
|
868
|
+
const rowHeight = this.options.rowHeightPx;
|
|
811
869
|
const gracePx = 1; // ignore subpixel scrolling
|
|
812
870
|
const scrollParent = this.element;
|
|
813
871
|
// const headerHeight = this.headerElement.clientHeight; // May be 0
|
|
@@ -824,7 +882,7 @@ export class Wunderbaum {
|
|
|
824
882
|
|
|
825
883
|
/** Return the lowest visible node in the viewport. */
|
|
826
884
|
getLowestVpNode(complete = true) {
|
|
827
|
-
const rowHeight = this.options.rowHeightPx
|
|
885
|
+
const rowHeight = this.options.rowHeightPx;
|
|
828
886
|
const scrollParent = this.element;
|
|
829
887
|
const headerHeight = this.headerElement.clientHeight; // May be 0
|
|
830
888
|
const scrollTop = scrollParent.scrollTop;
|
|
@@ -840,6 +898,20 @@ export class Wunderbaum {
|
|
|
840
898
|
return this._getNodeByRowIdx(bottomIdx)!;
|
|
841
899
|
}
|
|
842
900
|
|
|
901
|
+
/** Return preceding visible node in the viewport. */
|
|
902
|
+
protected _getPrevNodeInView(node?: WunderbaumNode, ofs = 1) {
|
|
903
|
+
this.visitRows(
|
|
904
|
+
(n) => {
|
|
905
|
+
node = n;
|
|
906
|
+
if (ofs-- <= 0) {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
},
|
|
910
|
+
{ reverse: true, start: node || this.getActiveNode() }
|
|
911
|
+
);
|
|
912
|
+
return node;
|
|
913
|
+
}
|
|
914
|
+
|
|
843
915
|
/** Return following visible node in the viewport. */
|
|
844
916
|
protected _getNextNodeInView(
|
|
845
917
|
node?: WunderbaumNode,
|
|
@@ -1138,24 +1210,40 @@ export class Wunderbaum {
|
|
|
1138
1210
|
/** Run code, but defer rendering of viewport until done.
|
|
1139
1211
|
*
|
|
1140
1212
|
* ```js
|
|
1141
|
-
* tree.runWithDeferredUpdate(() => {
|
|
1142
|
-
* return
|
|
1213
|
+
* const res = tree.runWithDeferredUpdate(() => {
|
|
1214
|
+
* return someFunctionThatWouldUpdateManyNodes();
|
|
1143
1215
|
* });
|
|
1144
1216
|
* ```
|
|
1145
1217
|
*/
|
|
1146
|
-
runWithDeferredUpdate(func: () =>
|
|
1218
|
+
runWithDeferredUpdate<T>(func: () => util.NotPromise<T>): T {
|
|
1147
1219
|
try {
|
|
1148
1220
|
this.enableUpdate(false);
|
|
1149
1221
|
const res = func();
|
|
1150
1222
|
util.assert(
|
|
1151
1223
|
!(res instanceof Promise),
|
|
1152
|
-
`Promise return not allowed: ${res}`
|
|
1224
|
+
`Promise return not allowed (see 'runWithDeferredUpdateAsync()'): ${res}`
|
|
1153
1225
|
);
|
|
1154
1226
|
return res;
|
|
1155
1227
|
} finally {
|
|
1156
1228
|
this.enableUpdate(true);
|
|
1157
1229
|
}
|
|
1158
1230
|
}
|
|
1231
|
+
/** Run code, but defer rendering of viewport until done.
|
|
1232
|
+
*
|
|
1233
|
+
* ```js
|
|
1234
|
+
* const res = await tree.runWithDeferredUpdate(async () => {
|
|
1235
|
+
* return someAsyncFunctionThatWouldUpdateManyNodes();
|
|
1236
|
+
* });
|
|
1237
|
+
* ```
|
|
1238
|
+
*/
|
|
1239
|
+
async runWithDeferredUpdateAsync<T>(func: () => Promise<T>): Promise<T> {
|
|
1240
|
+
try {
|
|
1241
|
+
this.enableUpdate(false);
|
|
1242
|
+
return await func();
|
|
1243
|
+
} finally {
|
|
1244
|
+
this.enableUpdate(true);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1159
1247
|
|
|
1160
1248
|
/** Recursively expand all expandable nodes (triggers lazy load if needed). */
|
|
1161
1249
|
async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
|
|
@@ -1180,6 +1268,18 @@ export class Wunderbaum {
|
|
|
1180
1268
|
return this.root.getSelectedNodes(stopOnParents);
|
|
1181
1269
|
}
|
|
1182
1270
|
|
|
1271
|
+
/**
|
|
1272
|
+
* Return an array of refKey values.
|
|
1273
|
+
*
|
|
1274
|
+
* RefKeys are unique identifiers for a node data, and are used to identify
|
|
1275
|
+
* clones.
|
|
1276
|
+
* If more than one node has the same refKey, it is only returned once.
|
|
1277
|
+
* @param selected if true, only return refKeys of selected nodes.
|
|
1278
|
+
*/
|
|
1279
|
+
getRefKeys(selected = false): string[] {
|
|
1280
|
+
return this.root.getRefKeys(selected);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1183
1283
|
/*
|
|
1184
1284
|
* Return an array of selected nodes.
|
|
1185
1285
|
*/
|
|
@@ -1348,7 +1448,7 @@ export class Wunderbaum {
|
|
|
1348
1448
|
where: NavigationType,
|
|
1349
1449
|
includeHidden = false
|
|
1350
1450
|
) {
|
|
1351
|
-
const rowHeight = this.options.rowHeightPx
|
|
1451
|
+
const rowHeight = this.options.rowHeightPx;
|
|
1352
1452
|
let res = null;
|
|
1353
1453
|
const pageSize = Math.floor(
|
|
1354
1454
|
this.listContainerElement.clientHeight / rowHeight
|
|
@@ -1495,6 +1595,20 @@ export class Wunderbaum {
|
|
|
1495
1595
|
return this.root.format(name_cb, connectors);
|
|
1496
1596
|
}
|
|
1497
1597
|
|
|
1598
|
+
/**
|
|
1599
|
+
* Always returns null (so a tree instance behaves as `tree.root`).
|
|
1600
|
+
*/
|
|
1601
|
+
get parent(): null {
|
|
1602
|
+
return null;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
/**
|
|
1606
|
+
* Return a list of top-level nodes.
|
|
1607
|
+
*/
|
|
1608
|
+
get children(): WunderbaumNode[] {
|
|
1609
|
+
return this.root.children || [];
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1498
1612
|
/**
|
|
1499
1613
|
* Return the active cell (`span.wb-col`) of the currently active node or null.
|
|
1500
1614
|
*/
|
|
@@ -1617,7 +1731,7 @@ export class Wunderbaum {
|
|
|
1617
1731
|
|
|
1618
1732
|
/** Return true if any node title or grid cell is currently beeing edited.
|
|
1619
1733
|
*
|
|
1620
|
-
* See also {@link
|
|
1734
|
+
* See also {@link isEditingTitle}.
|
|
1621
1735
|
*/
|
|
1622
1736
|
isEditing(): boolean {
|
|
1623
1737
|
const focusElem = this.nodeListElement.querySelector(
|
|
@@ -1628,7 +1742,7 @@ export class Wunderbaum {
|
|
|
1628
1742
|
|
|
1629
1743
|
/** Return true if any node is currently in edit-title mode.
|
|
1630
1744
|
*
|
|
1631
|
-
* See also {@link WunderbaumNode.isEditingTitle} and {@link
|
|
1745
|
+
* See also {@link WunderbaumNode.isEditingTitle} and {@link isEditing}.
|
|
1632
1746
|
*/
|
|
1633
1747
|
isEditingTitle(): boolean {
|
|
1634
1748
|
return this._callMethod("edit.isEditingTitle");
|
|
@@ -1651,7 +1765,7 @@ export class Wunderbaum {
|
|
|
1651
1765
|
}
|
|
1652
1766
|
|
|
1653
1767
|
/** Write to `console.log` with tree name as prefix if opts.debugLevel >= 4.
|
|
1654
|
-
* @see {@link
|
|
1768
|
+
* @see {@link logDebug}
|
|
1655
1769
|
*/
|
|
1656
1770
|
log(...args: any[]) {
|
|
1657
1771
|
if (this.options.debugLevel! >= 4) {
|
|
@@ -1661,7 +1775,7 @@ export class Wunderbaum {
|
|
|
1661
1775
|
|
|
1662
1776
|
/** Write to `console.debug` with tree name as prefix if opts.debugLevel >= 4.
|
|
1663
1777
|
* and browser console level includes debug/verbose messages.
|
|
1664
|
-
* @see {@link
|
|
1778
|
+
* @see {@link log}
|
|
1665
1779
|
*/
|
|
1666
1780
|
logDebug(...args: any[]) {
|
|
1667
1781
|
if (this.options.debugLevel! >= 4) {
|
|
@@ -1705,6 +1819,20 @@ export class Wunderbaum {
|
|
|
1705
1819
|
}
|
|
1706
1820
|
}
|
|
1707
1821
|
|
|
1822
|
+
/** Emit a warning for deprecated methods. @internal */
|
|
1823
|
+
logDeprecate(method: string, options?: DeprecationOptions) {
|
|
1824
|
+
if (this.options.debugLevel! >= 2) {
|
|
1825
|
+
let msg = `${this}: ${method} is deprecated`;
|
|
1826
|
+
if (options?.since) {
|
|
1827
|
+
msg += ` since ${options.since}`;
|
|
1828
|
+
}
|
|
1829
|
+
if (options?.hint) {
|
|
1830
|
+
msg += ` (${options.since})`;
|
|
1831
|
+
}
|
|
1832
|
+
console.warn(msg + "."); // eslint-disable-line no-console
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1708
1836
|
/** Reset column widths to default. @since 0.10.0 */
|
|
1709
1837
|
resetColumns() {
|
|
1710
1838
|
this.columns.forEach((col) => {
|
|
@@ -1739,7 +1867,7 @@ export class Wunderbaum {
|
|
|
1739
1867
|
}
|
|
1740
1868
|
util.assert(node && node._rowIdx != null, `Invalid node: ${node}`);
|
|
1741
1869
|
|
|
1742
|
-
const rowHeight = this.options.rowHeightPx
|
|
1870
|
+
const rowHeight = this.options.rowHeightPx;
|
|
1743
1871
|
const scrollParent = this.element;
|
|
1744
1872
|
const headerHeight = this.headerElement.clientHeight; // May be 0
|
|
1745
1873
|
const scrollTop = scrollParent.scrollTop;
|
|
@@ -1895,47 +2023,69 @@ export class Wunderbaum {
|
|
|
1895
2023
|
}
|
|
1896
2024
|
|
|
1897
2025
|
/** Return the current selection/expansion/activation status. @experimental */
|
|
1898
|
-
getState(options: GetStateOptions): TreeStateDefinition {
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
expandedKeys =
|
|
2026
|
+
getState(options: GetStateOptions = {}): TreeStateDefinition {
|
|
2027
|
+
const {
|
|
2028
|
+
activeKey = true,
|
|
2029
|
+
expandedKeys = false,
|
|
2030
|
+
selectedKeys = false,
|
|
2031
|
+
} = options;
|
|
2032
|
+
|
|
2033
|
+
const expandSet = new Set<string>();
|
|
2034
|
+
|
|
2035
|
+
if (expandedKeys) {
|
|
1902
2036
|
for (const node of this) {
|
|
1903
|
-
if (node.
|
|
1904
|
-
|
|
2037
|
+
if (node.isExpanded() && node.hasChildren()) {
|
|
2038
|
+
expandSet.add(node.key);
|
|
1905
2039
|
}
|
|
1906
2040
|
}
|
|
1907
2041
|
}
|
|
2042
|
+
// Parents of active node are always expanded
|
|
2043
|
+
if (activeKey && this.activeNode) {
|
|
2044
|
+
this.activeNode.visitParents((n) => {
|
|
2045
|
+
if (n.parent) {
|
|
2046
|
+
expandSet.add(n.key);
|
|
2047
|
+
}
|
|
2048
|
+
}, false);
|
|
2049
|
+
}
|
|
1908
2050
|
|
|
1909
2051
|
const state: TreeStateDefinition = {
|
|
2052
|
+
expandedKeys: expandSet.size ? Array.from(expandSet) : undefined,
|
|
1910
2053
|
activeKey: this.activeNode?.key ?? null,
|
|
1911
2054
|
activeColIdx: this.activeColIdx,
|
|
1912
|
-
selectedKeys:
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
: this.getSelectedNodes().flatMap((n) => n.key),
|
|
1916
|
-
expandedKeys: expandedKeys,
|
|
2055
|
+
selectedKeys: selectedKeys
|
|
2056
|
+
? this.getSelectedNodes().flatMap((n) => n.key)
|
|
2057
|
+
: undefined,
|
|
1917
2058
|
};
|
|
1918
2059
|
return state;
|
|
1919
2060
|
}
|
|
1920
2061
|
|
|
1921
2062
|
/** Apply selection/expansion/activation status. @experimental */
|
|
1922
|
-
setState(state: TreeStateDefinition, options: SetStateOptions) {
|
|
1923
|
-
|
|
2063
|
+
async setState(state: TreeStateDefinition, options: SetStateOptions = {}) {
|
|
2064
|
+
const { expandLazy = true } = options;
|
|
2065
|
+
return this.runWithDeferredUpdateAsync(async () => {
|
|
2066
|
+
if (state.expandedKeys && state.expandedKeys.length) {
|
|
2067
|
+
if (expandLazy) {
|
|
2068
|
+
// Expand all keys recursively, even if they are not in the tree yet
|
|
2069
|
+
await this._loadLazyNodes(state.expandedKeys, {
|
|
2070
|
+
expand: true,
|
|
2071
|
+
noEvents: true,
|
|
2072
|
+
});
|
|
2073
|
+
} else {
|
|
2074
|
+
for (const key of state.expandedKeys) {
|
|
2075
|
+
this.findKey(key)?.setExpanded(true);
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
if (state.activeKey) {
|
|
2080
|
+
this.setActiveNode(state.activeKey);
|
|
2081
|
+
}
|
|
1924
2082
|
if (state.selectedKeys) {
|
|
1925
2083
|
this.selectAll(false);
|
|
1926
2084
|
for (const key of state.selectedKeys) {
|
|
1927
2085
|
this.findKey(key)?.setSelected(true);
|
|
1928
2086
|
}
|
|
1929
2087
|
}
|
|
1930
|
-
if (state.
|
|
1931
|
-
for (const key of state.expandedKeys) {
|
|
1932
|
-
this.findKey(key)?.setExpanded(true);
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
if (state.activeKey) {
|
|
1936
|
-
this.setActiveNode(state.activeKey);
|
|
1937
|
-
}
|
|
1938
|
-
if (state.activeColIdx != null) {
|
|
2088
|
+
if (this.isCellNav() && state.activeColIdx != null) {
|
|
1939
2089
|
this.setColumn(state.activeColIdx);
|
|
1940
2090
|
}
|
|
1941
2091
|
});
|
|
@@ -2136,23 +2286,39 @@ export class Wunderbaum {
|
|
|
2136
2286
|
* @param {function} cmp custom compare function(a, b) that returns -1, 0, or 1
|
|
2137
2287
|
* (defaults to sorting by title).
|
|
2138
2288
|
* @param {boolean} deep pass true to sort all descendant nodes recursively
|
|
2289
|
+
* @deprecated use {@link sort}
|
|
2139
2290
|
*/
|
|
2140
2291
|
sortChildren(
|
|
2141
2292
|
cmp: SortCallback | null = nodeTitleSorter,
|
|
2142
2293
|
deep: boolean = false
|
|
2143
2294
|
): void {
|
|
2144
|
-
this.
|
|
2295
|
+
this.logDeprecate("sortChildren()", { since: "0.14.0" });
|
|
2296
|
+
return this.sort({
|
|
2297
|
+
cmp: cmp ? cmp : undefined,
|
|
2298
|
+
deep: deep,
|
|
2299
|
+
propName: "title",
|
|
2300
|
+
});
|
|
2145
2301
|
}
|
|
2146
2302
|
|
|
2147
2303
|
/**
|
|
2148
2304
|
* Convenience method to implement column sorting.
|
|
2149
2305
|
* @see {@link WunderbaumNode.sortByProperty}.
|
|
2150
2306
|
* @since 0.11.0
|
|
2307
|
+
* @deprecated use {@link sort}
|
|
2151
2308
|
*/
|
|
2152
2309
|
sortByProperty(options: SortByPropertyOptions) {
|
|
2310
|
+
this.logDeprecate("sortByProperty()", { since: "0.14.0" });
|
|
2153
2311
|
this.root.sortByProperty(options);
|
|
2154
2312
|
}
|
|
2155
2313
|
|
|
2314
|
+
/**
|
|
2315
|
+
* Sort nodes list by title or custom criteria.
|
|
2316
|
+
* @since 0.14.0
|
|
2317
|
+
*/
|
|
2318
|
+
sort(options: SortOptions): void {
|
|
2319
|
+
this.root.sort(options);
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2156
2322
|
/** Convert tree to an array of plain objects.
|
|
2157
2323
|
*
|
|
2158
2324
|
* @param callback is called for every node, in order to allow
|
|
@@ -2419,11 +2585,9 @@ export class Wunderbaum {
|
|
|
2419
2585
|
if (!icon) {
|
|
2420
2586
|
iconElem = document.createElement("i");
|
|
2421
2587
|
iconElem.className = "wb-icon";
|
|
2422
|
-
} else if (
|
|
2423
|
-
// HTML
|
|
2588
|
+
} else if (TEST_HTML.test(icon)) {
|
|
2424
2589
|
iconElem = util.elemFromHtml(icon);
|
|
2425
|
-
} else if (
|
|
2426
|
-
// Image URL
|
|
2590
|
+
} else if (TEST_FILE_PATH.test(icon)) {
|
|
2427
2591
|
iconElem = util.elemFromHtml(
|
|
2428
2592
|
`<i class="wb-icon" style="background-image: url('${icon}');">`
|
|
2429
2593
|
);
|
|
@@ -2480,7 +2644,7 @@ export class Wunderbaum {
|
|
|
2480
2644
|
part.href = "#";
|
|
2481
2645
|
part.classList.add("wb-breadcrumb");
|
|
2482
2646
|
part.dataset.key = n.key;
|
|
2483
|
-
breadcrumb.append(part, this.options.strings
|
|
2647
|
+
breadcrumb.append(part, this.options.strings.breadcrumbDelimiter);
|
|
2484
2648
|
}
|
|
2485
2649
|
} else {
|
|
2486
2650
|
breadcrumb.innerHTML = " ";
|
|
@@ -2604,7 +2768,7 @@ export class Wunderbaum {
|
|
|
2604
2768
|
options = Object.assign({ newNodesOnly: false }, options);
|
|
2605
2769
|
const newNodesOnly = !!options.newNodesOnly;
|
|
2606
2770
|
|
|
2607
|
-
const rowHeight = this.options.rowHeightPx
|
|
2771
|
+
const rowHeight = this.options.rowHeightPx;
|
|
2608
2772
|
const vpHeight = this.element.clientHeight;
|
|
2609
2773
|
const prefetch = RENDER_MAX_PREFETCH;
|
|
2610
2774
|
// const grace_prefetch = RENDER_MAX_PREFETCH - RENDER_MIN_PREFETCH;
|
|
@@ -2684,7 +2848,8 @@ export class Wunderbaum {
|
|
|
2684
2848
|
|
|
2685
2849
|
/**
|
|
2686
2850
|
* Call `callback(node)` for all nodes in hierarchical order (depth-first, pre-order).
|
|
2687
|
-
* @see
|
|
2851
|
+
* @see `wb_node.WunderbaumNode.IterableIterator<WunderbaumNode>`
|
|
2852
|
+
* @see {@link WunderbaumNode.visit}.
|
|
2688
2853
|
*
|
|
2689
2854
|
* @param {function} callback the callback function.
|
|
2690
2855
|
* Return false to stop iteration, return "skip" to skip this node and
|
|
@@ -2856,12 +3021,77 @@ export class Wunderbaum {
|
|
|
2856
3021
|
*
|
|
2857
3022
|
* Previous data is cleared. Note that also column- and type defintions may
|
|
2858
3023
|
* be passed with the `source` object.
|
|
3024
|
+
* @see {@link Wunderbaum.reload} for a shortcut to reload the last ajax request
|
|
3025
|
+
* and restore the previous state.
|
|
2859
3026
|
*/
|
|
2860
|
-
load(source: SourceType) {
|
|
3027
|
+
async load(source: SourceType) {
|
|
2861
3028
|
this.clear();
|
|
3029
|
+
this._initialSource = source;
|
|
2862
3030
|
return this.root.load(source);
|
|
2863
3031
|
}
|
|
2864
3032
|
|
|
3033
|
+
/** Reload the tree and optionally restore state.
|
|
3034
|
+
* Source defaults to last ajax url if any.
|
|
3035
|
+
* Restoring the active node requires stable keys
|
|
3036
|
+
* @see {@link WunderbaumOptions.autoKeys}
|
|
3037
|
+
* @see {@link Wunderbaum.load}
|
|
3038
|
+
* @experimental
|
|
3039
|
+
*/
|
|
3040
|
+
async reload(options: ReloadOptions = {}) {
|
|
3041
|
+
const { source = this._initialSource, reactivate = true } = options;
|
|
3042
|
+
if (!source) {
|
|
3043
|
+
this.logWarn("No previous ajax source to reload.");
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
if (!reactivate) {
|
|
3047
|
+
return this.load(source);
|
|
3048
|
+
}
|
|
3049
|
+
const state = this.getState();
|
|
3050
|
+
await this.load(source);
|
|
3051
|
+
return this.setState(state);
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
/**
|
|
3055
|
+
* Make sure that all nodes in the given keyList are accessible.
|
|
3056
|
+
* This may include loading lazy parent nodes.
|
|
3057
|
+
* Recursively load (and optionally expand) all requested node paths.
|
|
3058
|
+
*/
|
|
3059
|
+
protected async _loadLazyNodes(
|
|
3060
|
+
keyList: string[],
|
|
3061
|
+
options: LoadLazyNodesOptions = {}
|
|
3062
|
+
) {
|
|
3063
|
+
const { expand = true } = options;
|
|
3064
|
+
const keySet = new Set<string>(keyList);
|
|
3065
|
+
|
|
3066
|
+
// Make sure that all parent nodes are loaded (and expand if requested)
|
|
3067
|
+
while (keySet.size > 0) {
|
|
3068
|
+
const pendingNodes: Promise<void>[] = [];
|
|
3069
|
+
const curSet = new Set(keySet);
|
|
3070
|
+
for (const key of curSet) {
|
|
3071
|
+
const node = this.findKey(key);
|
|
3072
|
+
if (!node) {
|
|
3073
|
+
continue; // key not yet found (need to load lazy parent?)
|
|
3074
|
+
}
|
|
3075
|
+
keySet.delete(key);
|
|
3076
|
+
if (expand) {
|
|
3077
|
+
pendingNodes.push(node.setExpanded(true));
|
|
3078
|
+
} else if (node.isUnloaded()) {
|
|
3079
|
+
pendingNodes.push(node.loadLazy());
|
|
3080
|
+
}
|
|
3081
|
+
if (node._rowElem) {
|
|
3082
|
+
node._render(); // show spinner even is update is suppressed
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
if (pendingNodes.length === 0) {
|
|
3086
|
+
// will not load any more nodes, so if if there are still keys
|
|
3087
|
+
// left in the set, we will never find them
|
|
3088
|
+
this.logWarn(`Could not expand ${keySet.size} nodes:`, keySet);
|
|
3089
|
+
break;
|
|
3090
|
+
}
|
|
3091
|
+
await Promise.allSettled(pendingNodes);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
|
|
2865
3095
|
/**
|
|
2866
3096
|
* Disable render requests during operations that would trigger many updates.
|
|
2867
3097
|
*
|
|
@@ -2929,10 +3159,7 @@ export class Wunderbaum {
|
|
|
2929
3159
|
filter: string | RegExp | NodeFilterCallback,
|
|
2930
3160
|
options: FilterNodesOptions
|
|
2931
3161
|
): number {
|
|
2932
|
-
return
|
|
2933
|
-
filter,
|
|
2934
|
-
options
|
|
2935
|
-
);
|
|
3162
|
+
return this.extensions.filter.filterNodes(filter, options);
|
|
2936
3163
|
}
|
|
2937
3164
|
|
|
2938
3165
|
/**
|
|
@@ -2941,7 +3168,7 @@ export class Wunderbaum {
|
|
|
2941
3168
|
* @since 0.9.0
|
|
2942
3169
|
*/
|
|
2943
3170
|
countMatches(): number {
|
|
2944
|
-
return
|
|
3171
|
+
return this.extensions.filter.countMatches();
|
|
2945
3172
|
}
|
|
2946
3173
|
|
|
2947
3174
|
/**
|
|
@@ -2952,17 +3179,14 @@ export class Wunderbaum {
|
|
|
2952
3179
|
filter: string | NodeFilterCallback,
|
|
2953
3180
|
options: FilterNodesOptions
|
|
2954
3181
|
) {
|
|
2955
|
-
return
|
|
2956
|
-
filter,
|
|
2957
|
-
options
|
|
2958
|
-
);
|
|
3182
|
+
return this.extensions.filter.filterBranches(filter, options);
|
|
2959
3183
|
}
|
|
2960
3184
|
|
|
2961
3185
|
/**
|
|
2962
3186
|
* Reset the filter.
|
|
2963
3187
|
*/
|
|
2964
3188
|
clearFilter() {
|
|
2965
|
-
return
|
|
3189
|
+
return this.extensions.filter.clearFilter();
|
|
2966
3190
|
}
|
|
2967
3191
|
/**
|
|
2968
3192
|
* Return true if a filter is currently applied.
|
|
@@ -2974,6 +3198,6 @@ export class Wunderbaum {
|
|
|
2974
3198
|
* Re-apply current filter.
|
|
2975
3199
|
*/
|
|
2976
3200
|
updateFilter() {
|
|
2977
|
-
return
|
|
3201
|
+
return this.extensions.filter.updateFilter();
|
|
2978
3202
|
}
|
|
2979
3203
|
}
|