wunderbaum 0.0.5 → 0.0.6
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 +1 -1
- package/dist/wunderbaum.css +1 -1
- package/dist/wunderbaum.d.ts +468 -329
- package/dist/wunderbaum.esm.js +599 -374
- package/dist/wunderbaum.esm.min.js +29 -23
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +599 -374
- package/dist/wunderbaum.umd.min.js +35 -30
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +3 -3
- package/src/common.ts +18 -142
- package/src/types.ts +470 -0
- package/src/util.ts +18 -1
- package/src/wb_ext_dnd.ts +2 -154
- package/src/wb_ext_edit.ts +3 -3
- package/src/wb_ext_filter.ts +5 -5
- package/src/wb_ext_keynav.ts +93 -57
- package/src/wb_node.ts +149 -80
- package/src/wb_options.ts +35 -53
- package/src/wunderbaum.scss +82 -62
- package/src/wunderbaum.ts +279 -199
package/src/wb_node.ts
CHANGED
|
@@ -9,25 +9,31 @@ import * as util from "./util";
|
|
|
9
9
|
|
|
10
10
|
import { Wunderbaum } from "./wunderbaum";
|
|
11
11
|
import {
|
|
12
|
-
|
|
12
|
+
AddNodeType,
|
|
13
|
+
ApplyCommandType,
|
|
13
14
|
ChangeType,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
KEY_TO_ACTION_DICT,
|
|
17
|
-
makeNodeTitleMatcher,
|
|
15
|
+
ColumnEventInfos,
|
|
16
|
+
MakeVisibleOptions,
|
|
18
17
|
MatcherType,
|
|
19
18
|
NodeAnyCallback,
|
|
20
19
|
NodeStatusType,
|
|
21
20
|
NodeVisitCallback,
|
|
22
21
|
NodeVisitResponse,
|
|
23
|
-
|
|
24
|
-
ROW_HEIGHT,
|
|
25
|
-
TEST_IMG,
|
|
26
|
-
ApplyCommandType,
|
|
27
|
-
AddNodeType,
|
|
22
|
+
ScrollIntoViewOptions,
|
|
28
23
|
SetActiveOptions,
|
|
29
24
|
SetExpandedOptions,
|
|
30
25
|
SetSelectedOptions,
|
|
26
|
+
SetStatusOptions,
|
|
27
|
+
} from "./types";
|
|
28
|
+
import {
|
|
29
|
+
iconMap,
|
|
30
|
+
ICON_WIDTH,
|
|
31
|
+
KEY_TO_ACTION_DICT,
|
|
32
|
+
makeNodeTitleMatcher,
|
|
33
|
+
RESERVED_TREE_SOURCE_KEYS,
|
|
34
|
+
ROW_EXTRA_PAD,
|
|
35
|
+
ROW_HEIGHT,
|
|
36
|
+
TEST_IMG,
|
|
31
37
|
} from "./common";
|
|
32
38
|
import { Deferred } from "./deferred";
|
|
33
39
|
import { WbNodeData } from "./wb_options";
|
|
@@ -96,6 +102,7 @@ export class WunderbaumNode {
|
|
|
96
102
|
public readonly refKey: string | undefined = undefined;
|
|
97
103
|
public children: WunderbaumNode[] | null = null;
|
|
98
104
|
public checkbox?: boolean;
|
|
105
|
+
/** If true, (in grid mode) no cells are rendered, except for the node title.*/
|
|
99
106
|
public colspan?: boolean;
|
|
100
107
|
public icon?: boolean | string;
|
|
101
108
|
public lazy: boolean = false;
|
|
@@ -340,7 +347,7 @@ export class WunderbaumNode {
|
|
|
340
347
|
}
|
|
341
348
|
}
|
|
342
349
|
|
|
343
|
-
/** */
|
|
350
|
+
/** Call `setExpanded()` on al child nodes*/
|
|
344
351
|
async expandAll(flag: boolean = true) {
|
|
345
352
|
this.visit((node) => {
|
|
346
353
|
node.setExpanded(flag);
|
|
@@ -553,6 +560,13 @@ export class WunderbaumNode {
|
|
|
553
560
|
return this.parent && this.parent === other;
|
|
554
561
|
}
|
|
555
562
|
|
|
563
|
+
/** Return true if this node's title spans all columns, i.e. the node has no
|
|
564
|
+
* grid cells.
|
|
565
|
+
*/
|
|
566
|
+
isColspan() {
|
|
567
|
+
return !!this.getOption("colspan");
|
|
568
|
+
}
|
|
569
|
+
|
|
556
570
|
/** Return true if this node is a direct or indirect sub node of `other`.
|
|
557
571
|
* (See also [[isChildOf]].)
|
|
558
572
|
*/
|
|
@@ -719,14 +733,26 @@ export class WunderbaumNode {
|
|
|
719
733
|
"If `source` is an object, it must have a `children` property"
|
|
720
734
|
);
|
|
721
735
|
if (source.types) {
|
|
736
|
+
tree.logInfo("Redefine types", source.columns);
|
|
722
737
|
tree.setTypes(source.types, false);
|
|
738
|
+
delete source.types;
|
|
723
739
|
}
|
|
724
740
|
if (source.columns) {
|
|
741
|
+
tree.logInfo("Redefine columns", source.columns);
|
|
725
742
|
tree.columns = source.columns;
|
|
743
|
+
delete source.columns;
|
|
726
744
|
tree.updateColumns({ calculateCols: false });
|
|
727
745
|
}
|
|
728
|
-
|
|
729
746
|
this.addChildren(source.children);
|
|
747
|
+
delete source.columns;
|
|
748
|
+
|
|
749
|
+
// Add extra data to `tree.data`
|
|
750
|
+
for (const [key, value] of Object.entries(source)) {
|
|
751
|
+
if (!RESERVED_TREE_SOURCE_KEYS.has(key)) {
|
|
752
|
+
tree.data[key] = value;
|
|
753
|
+
tree.logDebug(`Add source.${key} to tree.data.${key}`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
730
756
|
|
|
731
757
|
this._callEvent("load");
|
|
732
758
|
}
|
|
@@ -734,10 +760,13 @@ export class WunderbaumNode {
|
|
|
734
760
|
/** Download data from the cloud, then call `.update()`. */
|
|
735
761
|
async load(source: any) {
|
|
736
762
|
const tree = this.tree;
|
|
737
|
-
// const opts = tree.options;
|
|
738
763
|
const requestId = Date.now();
|
|
739
764
|
const prevParent = this.parent;
|
|
740
765
|
const url = typeof source === "string" ? source : source.url;
|
|
766
|
+
const start = Date.now();
|
|
767
|
+
let elap = 0,
|
|
768
|
+
elapLoad = 0,
|
|
769
|
+
elapProcess = 0;
|
|
741
770
|
|
|
742
771
|
// Check for overlapping requests
|
|
743
772
|
if (this._requestId) {
|
|
@@ -748,11 +777,12 @@ export class WunderbaumNode {
|
|
|
748
777
|
}
|
|
749
778
|
this._requestId = requestId;
|
|
750
779
|
|
|
751
|
-
const timerLabel = tree.logTime(this + ".load()");
|
|
780
|
+
// const timerLabel = tree.logTime(this + ".load()");
|
|
752
781
|
|
|
753
782
|
try {
|
|
754
783
|
if (!url) {
|
|
755
784
|
this._loadSourceObject(source);
|
|
785
|
+
elapProcess = Date.now() - start;
|
|
756
786
|
} else {
|
|
757
787
|
this.setStatus(NodeStatusType.loading);
|
|
758
788
|
const response = await fetch(url, { method: "GET" });
|
|
@@ -760,6 +790,7 @@ export class WunderbaumNode {
|
|
|
760
790
|
util.error(`GET ${url} returned ${response.status}, ${response}`);
|
|
761
791
|
}
|
|
762
792
|
const data = await response.json();
|
|
793
|
+
elapLoad = Date.now() - start;
|
|
763
794
|
|
|
764
795
|
if (this._requestId && this._requestId > requestId) {
|
|
765
796
|
this.logWarn(
|
|
@@ -776,23 +807,32 @@ export class WunderbaumNode {
|
|
|
776
807
|
return;
|
|
777
808
|
}
|
|
778
809
|
this.setStatus(NodeStatusType.ok);
|
|
779
|
-
if (data.columns) {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
}
|
|
810
|
+
// if (data.columns) {
|
|
811
|
+
// tree.logInfo("Re-define columns", data.columns);
|
|
812
|
+
// util.assert(!this.parent);
|
|
813
|
+
// tree.columns = data.columns;
|
|
814
|
+
// delete data.columns;
|
|
815
|
+
// tree.updateColumns({ calculateCols: false });
|
|
816
|
+
// }
|
|
817
|
+
const startProcess = Date.now();
|
|
786
818
|
this._loadSourceObject(data);
|
|
819
|
+
elapProcess = Date.now() - startProcess;
|
|
787
820
|
}
|
|
788
821
|
} catch (error) {
|
|
789
822
|
this.logError("Error during load()", source, error);
|
|
790
823
|
this._callEvent("error", { error: error });
|
|
791
|
-
this.setStatus(NodeStatusType.error, "" + error);
|
|
824
|
+
this.setStatus(NodeStatusType.error, { message: "" + error });
|
|
792
825
|
throw error;
|
|
793
826
|
} finally {
|
|
794
827
|
this._requestId = 0;
|
|
795
|
-
|
|
828
|
+
elap = Date.now() - start;
|
|
829
|
+
if (tree.options.debugLevel >= 3) {
|
|
830
|
+
tree.logInfo(
|
|
831
|
+
`Load source took ${elap / 1000} seconds (transfer: ${
|
|
832
|
+
elapLoad / 1000
|
|
833
|
+
}s, processing: ${elapProcess / 1000}s)`
|
|
834
|
+
);
|
|
835
|
+
}
|
|
796
836
|
}
|
|
797
837
|
}
|
|
798
838
|
|
|
@@ -833,7 +873,7 @@ export class WunderbaumNode {
|
|
|
833
873
|
} catch (e) {
|
|
834
874
|
this.logError("Error during loadLazy()", e);
|
|
835
875
|
this._callEvent("error", { error: e });
|
|
836
|
-
this.setStatus(NodeStatusType.error, "" + e);
|
|
876
|
+
this.setStatus(NodeStatusType.error, { message: "" + e });
|
|
837
877
|
}
|
|
838
878
|
return;
|
|
839
879
|
}
|
|
@@ -880,25 +920,29 @@ export class WunderbaumNode {
|
|
|
880
920
|
* @param {object} [opts] passed to `setExpanded()`.
|
|
881
921
|
* Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
|
|
882
922
|
*/
|
|
883
|
-
async makeVisible(opts
|
|
923
|
+
async makeVisible(opts?: MakeVisibleOptions) {
|
|
884
924
|
let i,
|
|
885
925
|
dfd = new Deferred(),
|
|
886
926
|
deferreds = [],
|
|
887
927
|
parents = this.getParentList(false, false),
|
|
888
928
|
len = parents.length,
|
|
889
|
-
effects = !(opts && opts.noAnimation === true),
|
|
929
|
+
// effects = !(opts && opts.noAnimation === true),
|
|
890
930
|
scroll = !(opts && opts.scrollIntoView === false);
|
|
891
931
|
|
|
892
932
|
// Expand bottom-up, so only the top node is animated
|
|
893
933
|
for (i = len - 1; i >= 0; i--) {
|
|
894
934
|
// self.debug("pushexpand" + parents[i]);
|
|
895
|
-
|
|
935
|
+
const seOpts = { noAnimation: opts?.noAnimation };
|
|
936
|
+
deferreds.push(parents[i].setExpanded(true, seOpts));
|
|
896
937
|
}
|
|
897
938
|
Promise.all(deferreds).then(() => {
|
|
898
939
|
// All expands have finished
|
|
899
940
|
// self.debug("expand DONE", scroll);
|
|
900
|
-
|
|
901
|
-
|
|
941
|
+
// Note: this.tree may be none when switching demo trees
|
|
942
|
+
if (scroll && this.tree) {
|
|
943
|
+
// Make sure markup and _rowIdx is updated before we do the scroll calculations
|
|
944
|
+
this.tree.updatePendingModifications();
|
|
945
|
+
this.scrollIntoView().then(() => {
|
|
902
946
|
// self.debug("scroll DONE");
|
|
903
947
|
dfd.resolve();
|
|
904
948
|
});
|
|
@@ -1092,25 +1136,35 @@ export class WunderbaumNode {
|
|
|
1092
1136
|
}
|
|
1093
1137
|
}
|
|
1094
1138
|
|
|
1095
|
-
protected _getRenderInfo() {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1139
|
+
protected _getRenderInfo(): any {
|
|
1140
|
+
const allColInfosById: ColumnEventInfos = {};
|
|
1141
|
+
const renderColInfosById: ColumnEventInfos = {};
|
|
1142
|
+
const isColspan = this.isColspan();
|
|
1143
|
+
|
|
1144
|
+
const colElems = this._rowElem
|
|
1099
1145
|
? ((<unknown>(
|
|
1100
1146
|
this._rowElem.querySelectorAll("span.wb-col")
|
|
1101
|
-
)) as
|
|
1147
|
+
)) as HTMLSpanElement[])
|
|
1102
1148
|
: null;
|
|
1103
1149
|
|
|
1150
|
+
let idx = 0;
|
|
1104
1151
|
for (let col of this.tree.columns) {
|
|
1105
|
-
|
|
1152
|
+
allColInfosById[col.id] = {
|
|
1106
1153
|
id: col.id,
|
|
1107
1154
|
idx: idx,
|
|
1108
1155
|
elem: colElems ? colElems[idx] : null,
|
|
1109
1156
|
info: col,
|
|
1110
1157
|
};
|
|
1158
|
+
// renderColInfosById only contains columns that need rendering:
|
|
1159
|
+
if (!isColspan && col.id !== "*") {
|
|
1160
|
+
renderColInfosById[col.id] = allColInfosById[col.id];
|
|
1161
|
+
}
|
|
1111
1162
|
idx++;
|
|
1112
1163
|
}
|
|
1113
|
-
return
|
|
1164
|
+
return {
|
|
1165
|
+
allColInfosById: allColInfosById,
|
|
1166
|
+
renderColInfosById: renderColInfosById,
|
|
1167
|
+
};
|
|
1114
1168
|
}
|
|
1115
1169
|
|
|
1116
1170
|
protected _createIcon(
|
|
@@ -1163,7 +1217,7 @@ export class WunderbaumNode {
|
|
|
1163
1217
|
|
|
1164
1218
|
/**
|
|
1165
1219
|
* Create a whole new `<div class="wb-row">` element.
|
|
1166
|
-
* @see {@link
|
|
1220
|
+
* @see {@link WunderbaumNode.render}
|
|
1167
1221
|
*/
|
|
1168
1222
|
protected _render_markup(opts: any) {
|
|
1169
1223
|
const tree = this.tree;
|
|
@@ -1178,8 +1232,7 @@ export class WunderbaumNode {
|
|
|
1178
1232
|
let checkboxSpan: HTMLElement | null = null;
|
|
1179
1233
|
let iconSpan: HTMLElement | null;
|
|
1180
1234
|
let expanderSpan: HTMLElement | null = null;
|
|
1181
|
-
const activeColIdx =
|
|
1182
|
-
tree.navMode === NavigationMode.row ? null : tree.activeColIdx;
|
|
1235
|
+
const activeColIdx = tree.isRowNav() ? null : tree.activeColIdx;
|
|
1183
1236
|
|
|
1184
1237
|
const isNew = !rowDiv;
|
|
1185
1238
|
util.assert(isNew);
|
|
@@ -1247,7 +1300,9 @@ export class WunderbaumNode {
|
|
|
1247
1300
|
}
|
|
1248
1301
|
|
|
1249
1302
|
// Render columns
|
|
1250
|
-
|
|
1303
|
+
const isColspan = this.isColspan();
|
|
1304
|
+
|
|
1305
|
+
if (!isColspan && columns.length > 1) {
|
|
1251
1306
|
let colIdx = 0;
|
|
1252
1307
|
for (let col of columns) {
|
|
1253
1308
|
colIdx++;
|
|
@@ -1275,11 +1330,6 @@ export class WunderbaumNode {
|
|
|
1275
1330
|
}
|
|
1276
1331
|
}
|
|
1277
1332
|
}
|
|
1278
|
-
|
|
1279
|
-
// Now go on and fill in data and update classes
|
|
1280
|
-
opts.isNew = true;
|
|
1281
|
-
this._render_data(opts);
|
|
1282
|
-
|
|
1283
1333
|
// Attach to DOM as late as possible
|
|
1284
1334
|
const after = opts ? opts.after : "last";
|
|
1285
1335
|
switch (after) {
|
|
@@ -1292,12 +1342,15 @@ export class WunderbaumNode {
|
|
|
1292
1342
|
default:
|
|
1293
1343
|
opts.after.after(rowDiv);
|
|
1294
1344
|
}
|
|
1345
|
+
// Now go on and fill in data and update classes
|
|
1346
|
+
opts.isNew = true;
|
|
1347
|
+
this._render_data(opts);
|
|
1295
1348
|
}
|
|
1296
1349
|
|
|
1297
1350
|
/**
|
|
1298
1351
|
* Render `node.title`, `.icon` into an existing row.
|
|
1299
1352
|
*
|
|
1300
|
-
* @see {@link
|
|
1353
|
+
* @see {@link WunderbaumNode.render}
|
|
1301
1354
|
*/
|
|
1302
1355
|
protected _render_data(opts: any) {
|
|
1303
1356
|
util.assert(this._rowElem);
|
|
@@ -1307,7 +1360,7 @@ export class WunderbaumNode {
|
|
|
1307
1360
|
const rowDiv = this._rowElem!;
|
|
1308
1361
|
const isNew = !!opts.isNew; // Called by _render_markup()?
|
|
1309
1362
|
const columns = tree.columns;
|
|
1310
|
-
const
|
|
1363
|
+
const isColspan = this.isColspan();
|
|
1311
1364
|
|
|
1312
1365
|
// Row markup already exists
|
|
1313
1366
|
const nodeElem = rowDiv.querySelector("span.wb-node") as HTMLSpanElement;
|
|
@@ -1323,13 +1376,13 @@ export class WunderbaumNode {
|
|
|
1323
1376
|
|
|
1324
1377
|
// Set the width of the title span, so overflow ellipsis work
|
|
1325
1378
|
if (!treeOptions.skeleton) {
|
|
1326
|
-
if (
|
|
1379
|
+
if (isColspan) {
|
|
1327
1380
|
let vpWidth = tree.element.clientWidth;
|
|
1328
1381
|
titleSpan.style.width =
|
|
1329
1382
|
vpWidth - (<any>nodeElem)._ofsTitlePx - ROW_EXTRA_PAD + "px";
|
|
1330
1383
|
} else {
|
|
1331
1384
|
titleSpan.style.width =
|
|
1332
|
-
columns[0]._widthPx -
|
|
1385
|
+
columns[0]._widthPx! -
|
|
1333
1386
|
(<any>nodeElem)._ofsTitlePx -
|
|
1334
1387
|
ROW_EXTRA_PAD +
|
|
1335
1388
|
"px";
|
|
@@ -1348,19 +1401,22 @@ export class WunderbaumNode {
|
|
|
1348
1401
|
});
|
|
1349
1402
|
} else if (this.parent) {
|
|
1350
1403
|
// Skip root node
|
|
1404
|
+
const renderInfo = this._getRenderInfo();
|
|
1405
|
+
|
|
1351
1406
|
this._callEvent("render", {
|
|
1352
1407
|
isNew: isNew,
|
|
1353
|
-
|
|
1408
|
+
isColspan: isColspan,
|
|
1409
|
+
// isDataChange: true,
|
|
1354
1410
|
nodeElem: nodeElem,
|
|
1355
|
-
|
|
1356
|
-
|
|
1411
|
+
allColInfosById: renderInfo.allColInfosById,
|
|
1412
|
+
renderColInfosById: renderInfo.renderColInfosById,
|
|
1357
1413
|
});
|
|
1358
1414
|
}
|
|
1359
1415
|
}
|
|
1360
1416
|
|
|
1361
1417
|
/**
|
|
1362
1418
|
* Update row classes to reflect active, focuses, etc.
|
|
1363
|
-
* @see {@link
|
|
1419
|
+
* @see {@link WunderbaumNode.render}
|
|
1364
1420
|
*/
|
|
1365
1421
|
protected _render_status(opts: any) {
|
|
1366
1422
|
// this.log("_render_status", opts);
|
|
@@ -1377,8 +1433,6 @@ export class WunderbaumNode {
|
|
|
1377
1433
|
const checkboxSpan = nodeElem.querySelector(
|
|
1378
1434
|
"i.wb-checkbox"
|
|
1379
1435
|
) as HTMLLIElement;
|
|
1380
|
-
// TODO: update icon (if not opts.isNew)
|
|
1381
|
-
// const iconSpan = nodeElem.querySelector("i.wb-icon") as HTMLElement;
|
|
1382
1436
|
|
|
1383
1437
|
let rowClasses = ["wb-row"];
|
|
1384
1438
|
this.expanded ? rowClasses.push("wb-expanded") : 0;
|
|
@@ -1388,6 +1442,7 @@ export class WunderbaumNode {
|
|
|
1388
1442
|
this === tree.focusNode ? rowClasses.push("wb-focus") : 0;
|
|
1389
1443
|
this._errorInfo ? rowClasses.push("wb-error") : 0;
|
|
1390
1444
|
this._isLoading ? rowClasses.push("wb-loading") : 0;
|
|
1445
|
+
this.isColspan() ? rowClasses.push("wb-colspan") : 0;
|
|
1391
1446
|
this.statusNodeType
|
|
1392
1447
|
? rowClasses.push("wb-status-" + this.statusNodeType)
|
|
1393
1448
|
: 0;
|
|
@@ -1435,6 +1490,11 @@ export class WunderbaumNode {
|
|
|
1435
1490
|
for (let colSpan of rowDiv.children) {
|
|
1436
1491
|
colSpan.classList.toggle("wb-active", i++ === tree.activeColIdx);
|
|
1437
1492
|
}
|
|
1493
|
+
// Update icon (if not opts.isNew, which would rebuild markup anyway)
|
|
1494
|
+
const iconSpan = nodeElem.querySelector("i.wb-icon") as HTMLElement;
|
|
1495
|
+
if (iconSpan) {
|
|
1496
|
+
this._createIcon(nodeElem, iconSpan);
|
|
1497
|
+
}
|
|
1438
1498
|
}
|
|
1439
1499
|
}
|
|
1440
1500
|
|
|
@@ -1592,8 +1652,9 @@ export class WunderbaumNode {
|
|
|
1592
1652
|
/** Make sure that this node is visible in the viewport.
|
|
1593
1653
|
* @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo()}
|
|
1594
1654
|
*/
|
|
1595
|
-
async scrollIntoView(options?:
|
|
1596
|
-
|
|
1655
|
+
async scrollIntoView(options?: ScrollIntoViewOptions) {
|
|
1656
|
+
const opts = Object.assign({ node: this }, options);
|
|
1657
|
+
return this.tree.scrollTo(opts);
|
|
1597
1658
|
}
|
|
1598
1659
|
|
|
1599
1660
|
/**
|
|
@@ -1602,31 +1663,29 @@ export class WunderbaumNode {
|
|
|
1602
1663
|
async setActive(flag: boolean = true, options?: SetActiveOptions) {
|
|
1603
1664
|
const tree = this.tree;
|
|
1604
1665
|
const prev = tree.activeNode;
|
|
1605
|
-
const retrigger = options?.retrigger;
|
|
1606
|
-
const
|
|
1666
|
+
const retrigger = options?.retrigger; // Default: false
|
|
1667
|
+
const focusTree = options?.focusTree; // Default: false
|
|
1668
|
+
const focusNode = options?.focusNode !== false; // Default: true
|
|
1669
|
+
const noEvents = options?.noEvents; // Default: false
|
|
1670
|
+
const orgEvent = options?.event; // Default: false
|
|
1607
1671
|
|
|
1608
1672
|
if (!noEvents) {
|
|
1609
|
-
let orgEvent = options?.event;
|
|
1610
1673
|
if (flag) {
|
|
1611
1674
|
if (prev !== this || retrigger) {
|
|
1612
1675
|
if (
|
|
1613
1676
|
prev?._callEvent("deactivate", {
|
|
1614
1677
|
nextNode: this,
|
|
1615
1678
|
orgEvent: orgEvent,
|
|
1616
|
-
}) === false
|
|
1617
|
-
|
|
1618
|
-
return;
|
|
1619
|
-
}
|
|
1620
|
-
if (
|
|
1621
|
-
this._callEvent("activate", {
|
|
1679
|
+
}) === false ||
|
|
1680
|
+
this._callEvent("beforeActivate", {
|
|
1622
1681
|
prevNode: prev,
|
|
1623
1682
|
orgEvent: orgEvent,
|
|
1624
1683
|
}) === false
|
|
1625
1684
|
) {
|
|
1626
|
-
tree.activeNode = null;
|
|
1627
|
-
prev?.setModified();
|
|
1628
1685
|
return;
|
|
1629
1686
|
}
|
|
1687
|
+
tree.activeNode = null;
|
|
1688
|
+
prev?.setModified(ChangeType.status);
|
|
1630
1689
|
}
|
|
1631
1690
|
} else if (prev === this || retrigger) {
|
|
1632
1691
|
this._callEvent("deactivate", { nextNode: null, orgEvent: orgEvent });
|
|
@@ -1634,7 +1693,11 @@ export class WunderbaumNode {
|
|
|
1634
1693
|
}
|
|
1635
1694
|
|
|
1636
1695
|
if (prev !== this) {
|
|
1637
|
-
|
|
1696
|
+
if (flag) {
|
|
1697
|
+
tree.activeNode = this;
|
|
1698
|
+
if (focusNode || focusTree) tree.focusNode = this;
|
|
1699
|
+
if (focusTree) tree.setFocus();
|
|
1700
|
+
}
|
|
1638
1701
|
prev?.setModified(ChangeType.status);
|
|
1639
1702
|
this.setModified(ChangeType.status);
|
|
1640
1703
|
}
|
|
@@ -1642,42 +1705,46 @@ export class WunderbaumNode {
|
|
|
1642
1705
|
options &&
|
|
1643
1706
|
options.colIdx != null &&
|
|
1644
1707
|
options.colIdx !== tree.activeColIdx &&
|
|
1645
|
-
tree.
|
|
1708
|
+
tree.isCellNav()
|
|
1646
1709
|
) {
|
|
1647
1710
|
tree.setColumn(options.colIdx);
|
|
1648
1711
|
}
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
return this.
|
|
1712
|
+
if (flag && !noEvents) {
|
|
1713
|
+
this._callEvent("activate", { prevNode: prev, orgEvent: orgEvent });
|
|
1714
|
+
}
|
|
1715
|
+
return this.makeVisible();
|
|
1653
1716
|
}
|
|
1654
1717
|
|
|
1655
1718
|
/**
|
|
1656
1719
|
* Expand or collapse this node.
|
|
1657
1720
|
*/
|
|
1658
1721
|
async setExpanded(flag: boolean = true, options?: SetExpandedOptions) {
|
|
1659
|
-
// alert("" + this.getLevel() + ", "+ this.getOption("minExpandLevel");
|
|
1660
1722
|
if (
|
|
1661
1723
|
!flag &&
|
|
1662
1724
|
this.isExpanded() &&
|
|
1663
|
-
this.getLevel()
|
|
1725
|
+
this.getLevel() <= this.tree.getOption("minExpandLevel") &&
|
|
1664
1726
|
!util.getOption(options, "force")
|
|
1665
1727
|
) {
|
|
1666
1728
|
this.logDebug("Ignored collapse request below expandLevel.");
|
|
1667
1729
|
return;
|
|
1668
1730
|
}
|
|
1731
|
+
if (!flag === !this.expanded) {
|
|
1732
|
+
return; // Nothing to do
|
|
1733
|
+
}
|
|
1669
1734
|
if (flag && this.lazy && this.children == null) {
|
|
1670
1735
|
await this.loadLazy();
|
|
1671
1736
|
}
|
|
1672
1737
|
this.expanded = flag;
|
|
1673
|
-
|
|
1738
|
+
const updateOpts = { immediate: !!util.getOption(options, "immediate") };
|
|
1739
|
+
this.tree.setModified(ChangeType.structure, updateOpts);
|
|
1674
1740
|
}
|
|
1675
1741
|
|
|
1676
1742
|
/**
|
|
1677
1743
|
* Set keyboard focus here.
|
|
1678
1744
|
* @see {@link setActive}
|
|
1679
1745
|
*/
|
|
1680
|
-
setFocus(flag: boolean = true
|
|
1746
|
+
setFocus(flag: boolean = true) {
|
|
1747
|
+
util.assert(!!flag, "blur is not yet implemented");
|
|
1681
1748
|
const prev = this.tree.focusNode;
|
|
1682
1749
|
this.tree.focusNode = this;
|
|
1683
1750
|
prev?.setModified();
|
|
@@ -1720,10 +1787,12 @@ export class WunderbaumNode {
|
|
|
1720
1787
|
/** Display node status (ok, loading, error, noData) using styles and a dummy child node. */
|
|
1721
1788
|
setStatus(
|
|
1722
1789
|
status: NodeStatusType,
|
|
1723
|
-
|
|
1724
|
-
details?: string
|
|
1790
|
+
options?: SetStatusOptions
|
|
1725
1791
|
): WunderbaumNode | null {
|
|
1726
1792
|
const tree = this.tree;
|
|
1793
|
+
const message = options?.message;
|
|
1794
|
+
const details = options?.details;
|
|
1795
|
+
|
|
1727
1796
|
let statusNode: WunderbaumNode | null = null;
|
|
1728
1797
|
|
|
1729
1798
|
const _clearStatusNode = () => {
|
package/src/wb_options.ts
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
BoolOptionResolver,
|
|
9
|
-
|
|
9
|
+
ColumnDefinitionList,
|
|
10
|
+
DndOptionsType,
|
|
11
|
+
NavigationOptions,
|
|
12
|
+
NodeTypeDefinitions,
|
|
10
13
|
WbNodeEventType,
|
|
14
|
+
WbRenderEventType,
|
|
11
15
|
WbTreeEventType,
|
|
12
|
-
} from "./
|
|
13
|
-
import { DndOptionsType } from "./wb_ext_dnd";
|
|
16
|
+
} from "./types";
|
|
14
17
|
|
|
15
18
|
export interface WbNodeData {
|
|
16
19
|
title: string;
|
|
@@ -23,43 +26,6 @@ export interface WbNodeData {
|
|
|
23
26
|
// ...any?: Any;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
export interface ColumnDefinition {
|
|
27
|
-
/** Column ID (pass "*" for the main tree nodes column ) */
|
|
28
|
-
id: string;
|
|
29
|
-
/** Column header (defaults to id) */
|
|
30
|
-
title: string;
|
|
31
|
-
/** Column width or weight.
|
|
32
|
-
* Either an absolute pixel value (e.g. `"50px"`) or a relative weight (e.g. `1`)
|
|
33
|
-
* that is used to calculate the width inside the remaining available space.
|
|
34
|
-
* Default: `"*"`, which is interpreted as `1`.
|
|
35
|
-
*/
|
|
36
|
-
width?: string | number;
|
|
37
|
-
/** Only used for columns with a relative weight.
|
|
38
|
-
* Default: `4px`.
|
|
39
|
-
*/
|
|
40
|
-
minWidth?: string | number;
|
|
41
|
-
/** Optional class names that are added to all `span.wb-col` elements of that column.*/
|
|
42
|
-
classes?: string;
|
|
43
|
-
/** Optional HTML content that is rendered into all `span.wb-col` elements of that column.*/
|
|
44
|
-
html: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface TypeDefinition {
|
|
48
|
-
// /** Type ID that matches `node.type`. */
|
|
49
|
-
// id: string;
|
|
50
|
-
/** En/disable checkbox for matching nodes.*/
|
|
51
|
-
checkbox?: boolean | BoolOptionResolver;
|
|
52
|
-
/** Optional class names that are added to all `div.wb-row` elements of matching nodes.*/
|
|
53
|
-
classes?: string;
|
|
54
|
-
/**Default icon for matching nodes.*/
|
|
55
|
-
icon?: boolean | string | BoolOptionResolver;
|
|
56
|
-
/**
|
|
57
|
-
* See also {@link WunderbaumNode.getOption|WunderbaumNode.getOption()}
|
|
58
|
-
* to evaluate `node.NAME` setting and `tree.types[node.type].NAME`.
|
|
59
|
-
*/
|
|
60
|
-
_any: any;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
29
|
/**
|
|
64
30
|
* Available options for [[Wunderbaum]].
|
|
65
31
|
*
|
|
@@ -116,7 +82,7 @@ export interface WunderbaumOptions {
|
|
|
116
82
|
*
|
|
117
83
|
* Default: `{}`.
|
|
118
84
|
*/
|
|
119
|
-
types?: { [key: string]:
|
|
85
|
+
types?: NodeTypeDefinitions; // { [key: string]: NodeTypeDefinition };
|
|
120
86
|
/**
|
|
121
87
|
* A list of maps that define column headers. If this option is set,
|
|
122
88
|
* Wunderbaum becomes a treegrid control instead of a plain tree.
|
|
@@ -124,7 +90,7 @@ export interface WunderbaumOptions {
|
|
|
124
90
|
* response.
|
|
125
91
|
* Default: `[]` meaning this is a plain tree.
|
|
126
92
|
*/
|
|
127
|
-
columns?:
|
|
93
|
+
columns?: ColumnDefinitionList;
|
|
128
94
|
/**
|
|
129
95
|
* If true, add a `wb-skeleton` class to all nodes, that will result in a
|
|
130
96
|
* 'glow' effect. Typically used with initial dummy nodes, while loading the
|
|
@@ -143,15 +109,16 @@ export interface WunderbaumOptions {
|
|
|
143
109
|
debugLevel: number;
|
|
144
110
|
/**
|
|
145
111
|
* Number of levels that are forced to be expanded, and have no expander icon.
|
|
112
|
+
* E.g. 1 would keep all toplevel nodes expanded.
|
|
146
113
|
* Default: 0
|
|
147
114
|
*/
|
|
148
115
|
minExpandLevel?: number;
|
|
149
116
|
// escapeTitles: boolean;
|
|
150
|
-
/**
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
headerHeightPx: number;
|
|
117
|
+
// /**
|
|
118
|
+
// * Height of the header row div.
|
|
119
|
+
// * Default: 22
|
|
120
|
+
// */
|
|
121
|
+
// headerHeightPx: number;
|
|
155
122
|
/**
|
|
156
123
|
* Height of a node row div.
|
|
157
124
|
* Default: 22
|
|
@@ -166,13 +133,17 @@ export interface WunderbaumOptions {
|
|
|
166
133
|
* HTMLElement that receives the top nodes breadcrumb.
|
|
167
134
|
* Default: undefined
|
|
168
135
|
*/
|
|
169
|
-
|
|
136
|
+
connectTopBreadcrumb?: HTMLElement;
|
|
170
137
|
/**
|
|
171
|
-
* Default:
|
|
138
|
+
* Default: NavigationOptions.startRow
|
|
172
139
|
*/
|
|
173
|
-
|
|
140
|
+
navigationModeOption?: NavigationOptions;
|
|
174
141
|
/**
|
|
175
|
-
* Show/hide header (
|
|
142
|
+
* Show/hide header (default: null)
|
|
143
|
+
* null: assume false for plain tree and true for grids.
|
|
144
|
+
* string: use text as header (only for plain trees)
|
|
145
|
+
* true: display a header (use tree's id as text for plain trees)
|
|
146
|
+
* false: do not display a header
|
|
176
147
|
*/
|
|
177
148
|
header?: boolean | string | null;
|
|
178
149
|
/**
|
|
@@ -180,7 +151,9 @@ export interface WunderbaumOptions {
|
|
|
180
151
|
*/
|
|
181
152
|
showSpinner?: boolean;
|
|
182
153
|
/**
|
|
183
|
-
*
|
|
154
|
+
* If true, render a checkbox before the node tile to allow selection with the
|
|
155
|
+
* mouse.
|
|
156
|
+
* Default: false.
|
|
184
157
|
*/
|
|
185
158
|
checkbox?: boolean | "radio" | BoolOptionResolver;
|
|
186
159
|
/**
|
|
@@ -228,6 +201,15 @@ export interface WunderbaumOptions {
|
|
|
228
201
|
click?: (e: WbTreeEventType) => void;
|
|
229
202
|
/**
|
|
230
203
|
*
|
|
204
|
+
* Return `false` to prevent default handling, e.g. activating the node.
|
|
205
|
+
* @category Callback
|
|
206
|
+
*/
|
|
207
|
+
beforeActivate?: (e: WbNodeEventType) => void;
|
|
208
|
+
/**
|
|
209
|
+
/**
|
|
210
|
+
*
|
|
211
|
+
* Return `false` to prevent default handling, e.g. deactivating the node
|
|
212
|
+
* and activating the next.
|
|
231
213
|
* @category Callback
|
|
232
214
|
*/
|
|
233
215
|
deactivate?: (e: WbNodeEventType) => void;
|
|
@@ -298,7 +280,7 @@ export interface WunderbaumOptions {
|
|
|
298
280
|
* See also `Custom Rendering` for details.
|
|
299
281
|
* @category Callback
|
|
300
282
|
*/
|
|
301
|
-
render?: (e:
|
|
283
|
+
render?: (e: WbRenderEventType) => void;
|
|
302
284
|
/**
|
|
303
285
|
*
|
|
304
286
|
* @category Callback
|