wunderbaum 0.0.6 → 0.0.8
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/README.md +6 -1
- package/dist/wunderbaum.css +1 -1
- package/dist/wunderbaum.d.ts +125 -60
- package/dist/wunderbaum.esm.js +480 -231
- package/dist/wunderbaum.esm.min.js +26 -26
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +480 -231
- package/dist/wunderbaum.umd.min.js +34 -34
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/common.ts +187 -26
- package/src/types.ts +43 -19
- package/src/util.ts +10 -5
- package/src/wb_ext_edit.ts +3 -2
- package/src/wb_ext_keynav.ts +12 -13
- package/src/wb_ext_logger.ts +1 -1
- package/src/wb_node.ts +173 -58
- package/src/wunderbaum.ts +63 -63
package/src/wunderbaum.ts
CHANGED
|
@@ -23,8 +23,9 @@ import {
|
|
|
23
23
|
ApplyCommandType,
|
|
24
24
|
ChangeType,
|
|
25
25
|
ColumnDefinitionList,
|
|
26
|
+
ExpandAllOptions,
|
|
26
27
|
FilterModeType,
|
|
27
|
-
|
|
28
|
+
MatcherCallback,
|
|
28
29
|
NavigationOptions,
|
|
29
30
|
NodeStatusType,
|
|
30
31
|
NodeTypeDefinitions,
|
|
@@ -710,13 +711,13 @@ export class Wunderbaum {
|
|
|
710
711
|
/**
|
|
711
712
|
* Apply a modification (or navigation) operation on the **tree or active node**.
|
|
712
713
|
*/
|
|
713
|
-
applyCommand(cmd: ApplyCommandType,
|
|
714
|
+
applyCommand(cmd: ApplyCommandType, options?: any): any;
|
|
714
715
|
|
|
715
716
|
/**
|
|
716
717
|
* Apply a modification (or navigation) operation on a **node**.
|
|
717
718
|
* @see {@link WunderbaumNode.applyCommand}
|
|
718
719
|
*/
|
|
719
|
-
applyCommand(cmd: ApplyCommandType, node: WunderbaumNode,
|
|
720
|
+
applyCommand(cmd: ApplyCommandType, node: WunderbaumNode, options?: any): any;
|
|
720
721
|
|
|
721
722
|
/**
|
|
722
723
|
* Apply a modification or navigation operation.
|
|
@@ -737,23 +738,23 @@ export class Wunderbaum {
|
|
|
737
738
|
applyCommand(
|
|
738
739
|
cmd: ApplyCommandType,
|
|
739
740
|
nodeOrOpts?: WunderbaumNode | any,
|
|
740
|
-
|
|
741
|
+
options?: any
|
|
741
742
|
): any {
|
|
742
743
|
let // clipboard,
|
|
743
744
|
node,
|
|
744
745
|
refNode;
|
|
745
|
-
//
|
|
746
|
+
// options = $.extend(
|
|
746
747
|
// { setActive: true, clipboard: CLIPBOARD },
|
|
747
|
-
//
|
|
748
|
+
// options_
|
|
748
749
|
// );
|
|
749
750
|
if (nodeOrOpts instanceof WunderbaumNode) {
|
|
750
751
|
node = nodeOrOpts;
|
|
751
752
|
} else {
|
|
752
753
|
node = this.getActiveNode()!;
|
|
753
|
-
util.assert(
|
|
754
|
-
|
|
754
|
+
util.assert(options === undefined);
|
|
755
|
+
options = nodeOrOpts;
|
|
755
756
|
}
|
|
756
|
-
// clipboard =
|
|
757
|
+
// clipboard = options.clipboard;
|
|
757
758
|
|
|
758
759
|
switch (cmd) {
|
|
759
760
|
// Sorting and indentation:
|
|
@@ -973,15 +974,8 @@ export class Wunderbaum {
|
|
|
973
974
|
}
|
|
974
975
|
|
|
975
976
|
/** Recursively expand all expandable nodes (triggers lazy load id needed). */
|
|
976
|
-
async expandAll(flag: boolean = true) {
|
|
977
|
-
|
|
978
|
-
try {
|
|
979
|
-
this.enableUpdate(false);
|
|
980
|
-
await this.root.expandAll(flag);
|
|
981
|
-
} finally {
|
|
982
|
-
this.enableUpdate(true);
|
|
983
|
-
this.logTimeEnd(tag);
|
|
984
|
-
}
|
|
977
|
+
async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
|
|
978
|
+
await this.root.expandAll(flag, options);
|
|
985
979
|
}
|
|
986
980
|
|
|
987
981
|
/** Recursively select all nodes. */
|
|
@@ -1018,26 +1012,20 @@ export class Wunderbaum {
|
|
|
1018
1012
|
}
|
|
1019
1013
|
|
|
1020
1014
|
/**
|
|
1021
|
-
* Find all nodes that
|
|
1022
|
-
*
|
|
1023
|
-
* @param match title string to search for, or a
|
|
1024
|
-
* callback function that returns `true` if a node is matched.
|
|
1015
|
+
* Find all nodes that match condition.
|
|
1025
1016
|
*
|
|
1026
1017
|
* @see {@link WunderbaumNode.findAll}
|
|
1027
1018
|
*/
|
|
1028
|
-
findAll(match: string |
|
|
1019
|
+
findAll(match: string | RegExp | MatcherCallback) {
|
|
1029
1020
|
return this.root.findAll(match);
|
|
1030
1021
|
}
|
|
1031
1022
|
|
|
1032
1023
|
/**
|
|
1033
1024
|
* Find first node that matches condition.
|
|
1034
1025
|
*
|
|
1035
|
-
* @param match title string to search for, or a
|
|
1036
|
-
* callback function that returns `true` if a node is matched.
|
|
1037
1026
|
* @see {@link WunderbaumNode.findFirst}
|
|
1038
|
-
*
|
|
1039
1027
|
*/
|
|
1040
|
-
findFirst(match: string |
|
|
1028
|
+
findFirst(match: string | RegExp | MatcherCallback) {
|
|
1041
1029
|
return this.root.findFirst(match);
|
|
1042
1030
|
}
|
|
1043
1031
|
|
|
@@ -1049,8 +1037,8 @@ export class Wunderbaum {
|
|
|
1049
1037
|
* @see {@link WunderbaumNode.findFirst}
|
|
1050
1038
|
*
|
|
1051
1039
|
*/
|
|
1052
|
-
findKey(key: string): WunderbaumNode |
|
|
1053
|
-
return this.keyMap.get(key);
|
|
1040
|
+
findKey(key: string): WunderbaumNode | null {
|
|
1041
|
+
return this.keyMap.get(key) || null;
|
|
1054
1042
|
}
|
|
1055
1043
|
|
|
1056
1044
|
/**
|
|
@@ -1058,7 +1046,7 @@ export class Wunderbaum {
|
|
|
1058
1046
|
* and wrap-around at the end.
|
|
1059
1047
|
*/
|
|
1060
1048
|
findNextNode(
|
|
1061
|
-
match: string |
|
|
1049
|
+
match: string | MatcherCallback,
|
|
1062
1050
|
startNode?: WunderbaumNode | null
|
|
1063
1051
|
): WunderbaumNode | null {
|
|
1064
1052
|
//, visibleOnly) {
|
|
@@ -1374,19 +1362,22 @@ export class Wunderbaum {
|
|
|
1374
1362
|
|
|
1375
1363
|
/**
|
|
1376
1364
|
* Make sure that this node is vertically scrolled into the viewport.
|
|
1365
|
+
*
|
|
1366
|
+
* Nodes that are above the visible area become the top row, nodes that are
|
|
1367
|
+
* below the viewport become the bottom row.
|
|
1377
1368
|
*/
|
|
1378
1369
|
scrollTo(nodeOrOpts: ScrollToOptions | WunderbaumNode) {
|
|
1379
1370
|
const PADDING = 2; // leave some pixels between viewport bounds
|
|
1380
1371
|
|
|
1381
1372
|
let node;
|
|
1382
1373
|
WunderbaumNode;
|
|
1383
|
-
let
|
|
1374
|
+
let options: ScrollToOptions | undefined;
|
|
1384
1375
|
|
|
1385
1376
|
if (nodeOrOpts instanceof WunderbaumNode) {
|
|
1386
1377
|
node = nodeOrOpts;
|
|
1387
1378
|
} else {
|
|
1388
|
-
|
|
1389
|
-
node =
|
|
1379
|
+
options = nodeOrOpts;
|
|
1380
|
+
node = options.node;
|
|
1390
1381
|
}
|
|
1391
1382
|
util.assert(node && node._rowIdx != null);
|
|
1392
1383
|
|
|
@@ -1398,6 +1389,7 @@ export class Wunderbaum {
|
|
|
1398
1389
|
const vpTop = headerHeight;
|
|
1399
1390
|
const vpRowTop = rowTop - scrollTop;
|
|
1400
1391
|
const vpRowBottom = vpRowTop + ROW_HEIGHT;
|
|
1392
|
+
const topNode = options?.topNode;
|
|
1401
1393
|
|
|
1402
1394
|
// this.log( `scrollTo(${node.title}), vpTop:${vpTop}px, scrollTop:${scrollTop}, vpHeight:${vpHeight}, rowTop:${rowTop}, vpRowTop:${vpRowTop}`, nodeOrOpts );
|
|
1403
1395
|
let newScrollTop: number | null = null;
|
|
@@ -1408,16 +1400,20 @@ export class Wunderbaum {
|
|
|
1408
1400
|
} else {
|
|
1409
1401
|
// Node is below viewport
|
|
1410
1402
|
// this.log("Below viewport");
|
|
1411
|
-
newScrollTop = rowTop + ROW_HEIGHT - vpHeight + PADDING; // leave some pixels between
|
|
1403
|
+
newScrollTop = rowTop + ROW_HEIGHT - vpHeight + PADDING; // leave some pixels between viewport bounds
|
|
1412
1404
|
}
|
|
1413
1405
|
} else {
|
|
1414
1406
|
// Node is above viewport
|
|
1415
1407
|
// this.log("Above viewport");
|
|
1416
|
-
newScrollTop = rowTop - vpTop - PADDING; // leave some pixels between
|
|
1408
|
+
newScrollTop = rowTop - vpTop - PADDING; // leave some pixels between viewport bounds
|
|
1417
1409
|
}
|
|
1418
1410
|
if (newScrollTop != null) {
|
|
1419
1411
|
this.log(`scrollTo(${rowTop}): ${scrollTop} => ${newScrollTop}`);
|
|
1420
1412
|
scrollParent.scrollTop = newScrollTop;
|
|
1413
|
+
if (topNode) {
|
|
1414
|
+
// Make sure the topNode is always visible
|
|
1415
|
+
this.scrollTo(topNode);
|
|
1416
|
+
}
|
|
1421
1417
|
// this.setModified(ChangeType.vscroll);
|
|
1422
1418
|
}
|
|
1423
1419
|
}
|
|
@@ -1447,13 +1443,9 @@ export class Wunderbaum {
|
|
|
1447
1443
|
newLeft = colRight - vpWidth;
|
|
1448
1444
|
}
|
|
1449
1445
|
// util.assert(node._rowIdx != null);
|
|
1450
|
-
//
|
|
1451
|
-
this.
|
|
1452
|
-
|
|
1453
|
-
);
|
|
1454
|
-
// const nodeOfs = node._rowIdx * ROW_HEIGHT;
|
|
1455
|
-
// let newLeft;
|
|
1456
|
-
|
|
1446
|
+
// this.log(
|
|
1447
|
+
// `scrollToHorz(${this.activeColIdx}): ${colLeft}..${colRight}, fixedOfs=${fixedWidth}, vpWidth=${vpWidth}, curLeft=${scrollLeft} -> ${newLeft}`
|
|
1448
|
+
// );
|
|
1457
1449
|
this.element.scrollLeft = newLeft;
|
|
1458
1450
|
// this.setModified(ChangeType.vscroll);
|
|
1459
1451
|
// }
|
|
@@ -1666,11 +1658,13 @@ export class Wunderbaum {
|
|
|
1666
1658
|
}
|
|
1667
1659
|
}
|
|
1668
1660
|
/** Update column headers and width. */
|
|
1669
|
-
updateColumns(
|
|
1670
|
-
|
|
1661
|
+
updateColumns(options?: any) {
|
|
1662
|
+
options = Object.assign({ calculateCols: true, updateRows: true }, options);
|
|
1671
1663
|
const defaultMinWidth = 4;
|
|
1672
1664
|
const vpWidth = this.element.clientWidth;
|
|
1673
1665
|
const isGrid = this.isGrid();
|
|
1666
|
+
// Shorten last column width to avoid h-scrollbar
|
|
1667
|
+
const FIX_ADJUST_LAST_COL = 2;
|
|
1674
1668
|
|
|
1675
1669
|
let totalWidth = 0;
|
|
1676
1670
|
let totalWeight = 0;
|
|
@@ -1682,7 +1676,7 @@ export class Wunderbaum {
|
|
|
1682
1676
|
this.setCellNav(false);
|
|
1683
1677
|
}
|
|
1684
1678
|
|
|
1685
|
-
if (
|
|
1679
|
+
if (options.calculateCols) {
|
|
1686
1680
|
// Gather width definitions
|
|
1687
1681
|
this._columnsById = {};
|
|
1688
1682
|
for (let col of this.columns) {
|
|
@@ -1732,7 +1726,8 @@ export class Wunderbaum {
|
|
|
1732
1726
|
col._ofsPx = ofsPx;
|
|
1733
1727
|
ofsPx += col._widthPx!;
|
|
1734
1728
|
}
|
|
1735
|
-
|
|
1729
|
+
this.columns[this.columns.length - 1]._widthPx! -= FIX_ADJUST_LAST_COL;
|
|
1730
|
+
totalWidth = ofsPx - FIX_ADJUST_LAST_COL;
|
|
1736
1731
|
}
|
|
1737
1732
|
// if (this.options.fixedCol) {
|
|
1738
1733
|
// 'position: fixed' requires that the content has the correct size
|
|
@@ -1747,7 +1742,7 @@ export class Wunderbaum {
|
|
|
1747
1742
|
// util.error("BREAK");
|
|
1748
1743
|
if (modified) {
|
|
1749
1744
|
this._renderHeaderMarkup();
|
|
1750
|
-
if (
|
|
1745
|
+
if (options.updateRows) {
|
|
1751
1746
|
this._updateRows();
|
|
1752
1747
|
}
|
|
1753
1748
|
}
|
|
@@ -1815,6 +1810,9 @@ export class Wunderbaum {
|
|
|
1815
1810
|
* @internal
|
|
1816
1811
|
*/
|
|
1817
1812
|
protected _updateViewportImmediately() {
|
|
1813
|
+
// Shorten container height to avoid v-scrollbar
|
|
1814
|
+
const FIX_ADJUST_HEIGHT = 1;
|
|
1815
|
+
|
|
1818
1816
|
if (this._disableUpdateCount) {
|
|
1819
1817
|
this.log(
|
|
1820
1818
|
`IGNORED _updateViewportImmediately() disable level: ${this._disableUpdateCount}`
|
|
@@ -1831,7 +1829,8 @@ export class Wunderbaum {
|
|
|
1831
1829
|
// let headerHeight = this.headerElement.children[0].children[0].clientHeight;
|
|
1832
1830
|
// const headerHeight = this.options.headerHeightPx;
|
|
1833
1831
|
const headerHeight = this.headerElement.clientHeight; // May be 0
|
|
1834
|
-
const wantHeight =
|
|
1832
|
+
const wantHeight =
|
|
1833
|
+
this.element.clientHeight - headerHeight - FIX_ADJUST_HEIGHT;
|
|
1835
1834
|
|
|
1836
1835
|
if (Math.abs(height - wantHeight) > 1.0) {
|
|
1837
1836
|
// this.log("resize", height, wantHeight);
|
|
@@ -1895,15 +1894,16 @@ export class Wunderbaum {
|
|
|
1895
1894
|
* (including upper and lower prefetch)
|
|
1896
1895
|
* -
|
|
1897
1896
|
*/
|
|
1898
|
-
protected _updateRows(
|
|
1897
|
+
protected _updateRows(options?: any): boolean {
|
|
1899
1898
|
// const label = this.logTime("_updateRows");
|
|
1900
1899
|
// this.log("_updateRows", opts)
|
|
1901
|
-
|
|
1902
|
-
const newNodesOnly = !!
|
|
1900
|
+
options = Object.assign({ newNodesOnly: false }, options);
|
|
1901
|
+
const newNodesOnly = !!options.newNodesOnly;
|
|
1903
1902
|
|
|
1904
1903
|
const row_height = ROW_HEIGHT;
|
|
1905
1904
|
const vp_height = this.element.clientHeight;
|
|
1906
1905
|
const prefetch = RENDER_MAX_PREFETCH;
|
|
1906
|
+
// const grace_prefetch = RENDER_MAX_PREFETCH - RENDER_MIN_PREFETCH;
|
|
1907
1907
|
const ofs = this.element.scrollTop;
|
|
1908
1908
|
|
|
1909
1909
|
let startIdx = Math.max(0, ofs / row_height - prefetch);
|
|
@@ -2008,15 +2008,15 @@ export class Wunderbaum {
|
|
|
2008
2008
|
* {start: First tree node, reverse: false, includeSelf: true, includeHidden: false, wrap: false}
|
|
2009
2009
|
* @returns {boolean} false if iteration was canceled
|
|
2010
2010
|
*/
|
|
2011
|
-
visitRows(callback: (node: WunderbaumNode) => any,
|
|
2011
|
+
visitRows(callback: (node: WunderbaumNode) => any, options?: any): boolean {
|
|
2012
2012
|
if (!this.root.hasChildren()) {
|
|
2013
2013
|
return false;
|
|
2014
2014
|
}
|
|
2015
|
-
if (
|
|
2016
|
-
delete
|
|
2017
|
-
return this._visitRowsUp(callback,
|
|
2015
|
+
if (options && options.reverse) {
|
|
2016
|
+
delete options.reverse;
|
|
2017
|
+
return this._visitRowsUp(callback, options);
|
|
2018
2018
|
}
|
|
2019
|
-
|
|
2019
|
+
options = options || {};
|
|
2020
2020
|
let i,
|
|
2021
2021
|
nextIdx,
|
|
2022
2022
|
parent,
|
|
@@ -2024,10 +2024,10 @@ export class Wunderbaum {
|
|
|
2024
2024
|
siblings,
|
|
2025
2025
|
stopNode: WunderbaumNode,
|
|
2026
2026
|
siblingOfs = 0,
|
|
2027
|
-
skipFirstNode =
|
|
2028
|
-
includeHidden = !!
|
|
2027
|
+
skipFirstNode = options.includeSelf === false,
|
|
2028
|
+
includeHidden = !!options.includeHidden,
|
|
2029
2029
|
checkFilter = !includeHidden && this.filterMode === "hide",
|
|
2030
|
-
node: WunderbaumNode =
|
|
2030
|
+
node: WunderbaumNode = options.start || this.root.children![0];
|
|
2031
2031
|
|
|
2032
2032
|
parent = node.parent;
|
|
2033
2033
|
while (parent) {
|
|
@@ -2086,11 +2086,11 @@ export class Wunderbaum {
|
|
|
2086
2086
|
parent = parent.parent;
|
|
2087
2087
|
siblingOfs = 1; //
|
|
2088
2088
|
|
|
2089
|
-
if (!parent &&
|
|
2089
|
+
if (!parent && options.wrap) {
|
|
2090
2090
|
this.logDebug("visitRows(): wrap around");
|
|
2091
|
-
util.assert(
|
|
2092
|
-
stopNode =
|
|
2093
|
-
|
|
2091
|
+
util.assert(options.start, "`wrap` option requires `start`");
|
|
2092
|
+
stopNode = options.start;
|
|
2093
|
+
options.wrap = false;
|
|
2094
2094
|
parent = this.root;
|
|
2095
2095
|
siblingOfs = 0;
|
|
2096
2096
|
}
|