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/wb_ext_keynav.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { NavModeEnum } from "./types";
|
|
7
|
+
import { KeynavOptionsType, NavModeEnum } from "./types";
|
|
8
8
|
import { eventToString } from "./util";
|
|
9
9
|
import { Wunderbaum } from "./wunderbaum";
|
|
10
10
|
import { WunderbaumNode } from "./wb_node";
|
|
@@ -12,7 +12,7 @@ import { WunderbaumExtension } from "./wb_extension_base";
|
|
|
12
12
|
|
|
13
13
|
const QUICKSEARCH_DELAY = 500;
|
|
14
14
|
|
|
15
|
-
export class KeynavExtension extends WunderbaumExtension<
|
|
15
|
+
export class KeynavExtension extends WunderbaumExtension<KeynavOptionsType> {
|
|
16
16
|
constructor(tree: Wunderbaum) {
|
|
17
17
|
super(tree, "keynav", {});
|
|
18
18
|
}
|
|
@@ -32,6 +32,14 @@ export class KeynavExtension extends WunderbaumExtension<any> {
|
|
|
32
32
|
return input;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// /* Return the current cell's embedded input that has keyboard focus. */
|
|
36
|
+
// protected _getFocusedInputElem(): HTMLInputElement | null {
|
|
37
|
+
// const ace = this.tree
|
|
38
|
+
// .getActiveColElem()
|
|
39
|
+
// ?.querySelector<HTMLInputElement>("input:focus,select:focus");
|
|
40
|
+
// return ace || null;
|
|
41
|
+
// }
|
|
42
|
+
|
|
35
43
|
/* Return true if the current cell's embedded input has keyboard focus. */
|
|
36
44
|
protected _isCurInputFocused(): boolean {
|
|
37
45
|
const ace = this.tree
|
|
@@ -48,7 +56,6 @@ export class KeynavExtension extends WunderbaumExtension<any> {
|
|
|
48
56
|
const curInput = this._getEmbeddedInputElem(event.target);
|
|
49
57
|
const inputHasFocus = curInput && this._isCurInputFocused();
|
|
50
58
|
const navModeOption = opts.navigationModeOption as NavModeEnum;
|
|
51
|
-
// isCellEditMode = tree.navMode === NavigationMode.cellEdit;
|
|
52
59
|
|
|
53
60
|
let focusNode,
|
|
54
61
|
eventName = eventToString(event),
|
|
@@ -215,23 +222,28 @@ export class KeynavExtension extends WunderbaumExtension<any> {
|
|
|
215
222
|
// // Standard navigation (cell mode)
|
|
216
223
|
// if (isCellEditMode && INPUT_BREAKOUT_KEYS.has(eventName)) {
|
|
217
224
|
// }
|
|
218
|
-
const
|
|
219
|
-
const curInput = this._getEmbeddedInputElem(null);
|
|
225
|
+
// const curInput = this._getEmbeddedInputElem(null);
|
|
220
226
|
const curInputType = curInput ? curInput.type || curInput.tagName : "";
|
|
221
|
-
const inputHasFocus = curInput && this._isCurInputFocused();
|
|
227
|
+
// const inputHasFocus = curInput && this._isCurInputFocused();
|
|
222
228
|
const inputCanFocus = curInput && curInputType !== "checkbox";
|
|
223
229
|
|
|
224
230
|
if (inputHasFocus) {
|
|
225
231
|
if (eventName === "Escape") {
|
|
226
|
-
|
|
232
|
+
node.logDebug(`Reset focused input on Escape`);
|
|
233
|
+
// Discard changes and reset input validation state
|
|
234
|
+
curInput.setCustomValidity("");
|
|
227
235
|
node._render();
|
|
228
236
|
// Keep cell-nav mode
|
|
229
|
-
node.logDebug(`Reset focused input`);
|
|
230
237
|
tree.setFocus();
|
|
231
238
|
tree.setColumn(tree.activeColIdx);
|
|
232
239
|
return;
|
|
233
240
|
// } else if (!INPUT_BREAKOUT_KEYS.has(eventName)) {
|
|
234
241
|
} else if (eventName !== "Enter") {
|
|
242
|
+
if (curInput && curInput.checkValidity && !curInput.checkValidity()) {
|
|
243
|
+
// Invalid input: ignore all keys except Enter and Escape
|
|
244
|
+
node.logDebug(`Ignored ${eventName} inside invalid input`);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
235
247
|
// Let current `<input>` handle it
|
|
236
248
|
node.logDebug(`Ignored ${eventName} inside focused input`);
|
|
237
249
|
return;
|
|
@@ -245,9 +257,10 @@ export class KeynavExtension extends WunderbaumExtension<any> {
|
|
|
245
257
|
} else if (curInput) {
|
|
246
258
|
// On a cell that has an embedded, unfocused <input>
|
|
247
259
|
if (eventName.length === 1 && inputCanFocus) {
|
|
260
|
+
// Typing a single char
|
|
248
261
|
curInput.focus();
|
|
249
262
|
curInput.value = "";
|
|
250
|
-
node.logDebug(`Focus
|
|
263
|
+
node.logDebug(`Focus input: ${eventName}`);
|
|
251
264
|
return false;
|
|
252
265
|
}
|
|
253
266
|
}
|
|
@@ -257,8 +270,6 @@ export class KeynavExtension extends WunderbaumExtension<any> {
|
|
|
257
270
|
} else if (eventName === "Shift+Tab") {
|
|
258
271
|
eventName = tree.activeColIdx > 0 ? "ArrowLeft" : "";
|
|
259
272
|
handled = true;
|
|
260
|
-
} else if (ENTER_EDITS && eventName === "Enter") {
|
|
261
|
-
eventName = "F2";
|
|
262
273
|
}
|
|
263
274
|
|
|
264
275
|
switch (eventName) {
|
package/src/wb_ext_logger.ts
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { LoggerOptionsType } from "./types";
|
|
7
8
|
import { overrideMethod } from "./util";
|
|
8
9
|
import { WunderbaumExtension } from "./wb_extension_base";
|
|
9
10
|
import { Wunderbaum } from "./wunderbaum";
|
|
10
11
|
|
|
11
|
-
export class LoggerExtension extends WunderbaumExtension<
|
|
12
|
+
export class LoggerExtension extends WunderbaumExtension<LoggerOptionsType> {
|
|
12
13
|
readonly prefix: string;
|
|
13
14
|
protected ignoreEvents = new Set<string>([
|
|
14
15
|
"iconBadge",
|
package/src/wb_node.ts
CHANGED
|
@@ -420,6 +420,11 @@ export class WunderbaumNode {
|
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
/** Start editing this node's title. */
|
|
424
|
+
startEditTitle(): void {
|
|
425
|
+
this.tree._callMethod("edit.startEditTitle", this);
|
|
426
|
+
}
|
|
427
|
+
|
|
423
428
|
/** Call `setExpanded()` on all descendant nodes. */
|
|
424
429
|
async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
|
|
425
430
|
const tree = this.tree;
|
|
@@ -648,6 +653,22 @@ export class WunderbaumNode {
|
|
|
648
653
|
const colElems = this._rowElem?.querySelectorAll("span.wb-col");
|
|
649
654
|
return colElems ? (colElems[colIdx] as HTMLSpanElement) : null;
|
|
650
655
|
}
|
|
656
|
+
/**
|
|
657
|
+
* Return all nodes with the same refKey.
|
|
658
|
+
*
|
|
659
|
+
* @param includeSelf Include this node itself.
|
|
660
|
+
* @see {@link Wunderbaum.findByRefKey}
|
|
661
|
+
*/
|
|
662
|
+
getCloneList(includeSelf = false): WunderbaumNode[] {
|
|
663
|
+
if (!this.refKey) {
|
|
664
|
+
return [];
|
|
665
|
+
}
|
|
666
|
+
const clones = this.tree.findByRefKey(this.refKey);
|
|
667
|
+
if (includeSelf) {
|
|
668
|
+
return clones;
|
|
669
|
+
}
|
|
670
|
+
return [...clones].filter((n) => n !== this);
|
|
671
|
+
}
|
|
651
672
|
|
|
652
673
|
/** Return the first child node or null.
|
|
653
674
|
* @returns {WunderbaumNode | null}
|
|
@@ -771,19 +792,24 @@ export class WunderbaumNode {
|
|
|
771
792
|
}
|
|
772
793
|
|
|
773
794
|
/** Return true if this node is a direct or indirect parent of `other`.
|
|
774
|
-
*
|
|
795
|
+
* @see {@link WunderbaumNode.isParentOf}
|
|
775
796
|
*/
|
|
776
797
|
isAncestorOf(other: WunderbaumNode) {
|
|
777
798
|
return other && other.isDescendantOf(this);
|
|
778
799
|
}
|
|
779
800
|
|
|
780
801
|
/** Return true if this node is a **direct** subnode of `other`.
|
|
781
|
-
*
|
|
802
|
+
* @see {@link WunderbaumNode.isDescendantOf}
|
|
782
803
|
*/
|
|
783
804
|
isChildOf(other: WunderbaumNode) {
|
|
784
805
|
return other && this.parent === other;
|
|
785
806
|
}
|
|
786
807
|
|
|
808
|
+
/** Return true if this node's refKey is used by at least one other node.
|
|
809
|
+
*/
|
|
810
|
+
isClone() {
|
|
811
|
+
return !!this.refKey && this.tree.findByRefKey(this.refKey).length > 1;
|
|
812
|
+
}
|
|
787
813
|
/** Return true if this node's title spans all columns, i.e. the node has no
|
|
788
814
|
* grid cells.
|
|
789
815
|
*/
|
|
@@ -792,7 +818,7 @@ export class WunderbaumNode {
|
|
|
792
818
|
}
|
|
793
819
|
|
|
794
820
|
/** Return true if this node is a direct or indirect subnode of `other`.
|
|
795
|
-
*
|
|
821
|
+
* @see {@link WunderbaumNode.isChildOf}
|
|
796
822
|
*/
|
|
797
823
|
isDescendantOf(other: WunderbaumNode) {
|
|
798
824
|
if (!other || other.tree !== this.tree) {
|
|
@@ -829,8 +855,11 @@ export class WunderbaumNode {
|
|
|
829
855
|
return true;
|
|
830
856
|
}
|
|
831
857
|
|
|
832
|
-
/** Return true if
|
|
833
|
-
|
|
858
|
+
/** Return true if _this_ node is currently in edit-title mode.
|
|
859
|
+
*
|
|
860
|
+
* See {@link Wunderbaum.startEditTitle} to check if any node is currently edited.
|
|
861
|
+
*/
|
|
862
|
+
isEditingTitle(): boolean {
|
|
834
863
|
return this.tree._callMethod("edit.isEditingTitle", this);
|
|
835
864
|
}
|
|
836
865
|
|
|
@@ -872,7 +901,7 @@ export class WunderbaumNode {
|
|
|
872
901
|
}
|
|
873
902
|
|
|
874
903
|
/** Return true if this node is a **direct** parent of `other`.
|
|
875
|
-
*
|
|
904
|
+
* @see {@link WunderbaumNode.isAncestorOf}
|
|
876
905
|
*/
|
|
877
906
|
isParentOf(other: WunderbaumNode) {
|
|
878
907
|
return other && other.parent === this;
|
|
@@ -899,7 +928,7 @@ export class WunderbaumNode {
|
|
|
899
928
|
}
|
|
900
929
|
|
|
901
930
|
/** Return true if this node is the (invisible) system root node.
|
|
902
|
-
*
|
|
931
|
+
* @see {@link WunderbaumNode.isTopLevel}
|
|
903
932
|
*/
|
|
904
933
|
isRootNode(): boolean {
|
|
905
934
|
return this.tree.root === this;
|
|
@@ -1152,14 +1181,22 @@ export class WunderbaumNode {
|
|
|
1152
1181
|
}
|
|
1153
1182
|
}
|
|
1154
1183
|
|
|
1155
|
-
/**
|
|
1156
|
-
|
|
1184
|
+
/**
|
|
1185
|
+
* Load content of a lazy node.
|
|
1186
|
+
* If the node is already loaded, nothing happens.
|
|
1187
|
+
* @param [forceReload=false] If true, reload even if already loaded.
|
|
1188
|
+
*/
|
|
1189
|
+
async loadLazy(forceReload: boolean = false) {
|
|
1157
1190
|
const wasExpanded = this.expanded;
|
|
1158
1191
|
|
|
1159
1192
|
util.assert(this.lazy, "load() requires a lazy node");
|
|
1160
|
-
|
|
1193
|
+
|
|
1161
1194
|
if (!forceReload && !this.isUnloaded()) {
|
|
1162
|
-
return;
|
|
1195
|
+
return; // Already loaded: nothing to do
|
|
1196
|
+
}
|
|
1197
|
+
if (this.isLoading()) {
|
|
1198
|
+
this.logWarn("loadLazy() called while already loading: ignored.");
|
|
1199
|
+
return; // Already loading: prevent duplicate requests
|
|
1163
1200
|
}
|
|
1164
1201
|
if (this.isLoaded()) {
|
|
1165
1202
|
this.resetLazy(); // Also collapses if currently expanded
|
|
@@ -1180,7 +1217,7 @@ export class WunderbaumNode {
|
|
|
1180
1217
|
|
|
1181
1218
|
await this.load(source);
|
|
1182
1219
|
|
|
1183
|
-
this.setStatus(NodeStatusType.ok);
|
|
1220
|
+
this.setStatus(NodeStatusType.ok); // Also resets `this._isLoading`
|
|
1184
1221
|
|
|
1185
1222
|
if (wasExpanded) {
|
|
1186
1223
|
this.expanded = true;
|
|
@@ -1191,38 +1228,46 @@ export class WunderbaumNode {
|
|
|
1191
1228
|
} catch (e) {
|
|
1192
1229
|
this.logError("Error during loadLazy()", e);
|
|
1193
1230
|
this._callEvent("error", { error: e });
|
|
1231
|
+
// Also resets `this._isLoading`:
|
|
1194
1232
|
this.setStatus(NodeStatusType.error, { message: "" + e });
|
|
1195
1233
|
}
|
|
1196
1234
|
return;
|
|
1197
1235
|
}
|
|
1198
1236
|
|
|
1199
|
-
/**
|
|
1237
|
+
/** Write to `console.log` with node name as prefix if opts.debugLevel >= 4.
|
|
1238
|
+
* @see {@link WunderbaumNode.logDebug}
|
|
1239
|
+
*/
|
|
1200
1240
|
log(...args: any[]) {
|
|
1201
|
-
this.
|
|
1241
|
+
if (this.tree.options.debugLevel! >= 4) {
|
|
1242
|
+
console.log(this.toString(), ...args); // eslint-disable-line no-console
|
|
1243
|
+
}
|
|
1202
1244
|
}
|
|
1203
1245
|
|
|
1204
|
-
|
|
1246
|
+
/** Write to `console.debug` with node name as prefix if opts.debugLevel >= 4
|
|
1247
|
+
* and browser console level includes debug/verbose messages.
|
|
1248
|
+
* @see {@link WunderbaumNode.log}
|
|
1249
|
+
*/
|
|
1205
1250
|
logDebug(...args: any[]) {
|
|
1206
1251
|
if (this.tree.options.debugLevel! >= 4) {
|
|
1207
|
-
console.
|
|
1252
|
+
console.debug(this.toString(), ...args); // eslint-disable-line no-console
|
|
1208
1253
|
}
|
|
1209
1254
|
}
|
|
1210
1255
|
|
|
1211
|
-
|
|
1256
|
+
/** Write to `console.error` with node name as prefix if opts.debugLevel >= 1. */
|
|
1212
1257
|
logError(...args: any[]) {
|
|
1213
1258
|
if (this.tree.options.debugLevel! >= 1) {
|
|
1214
1259
|
console.error(this.toString(), ...args); // eslint-disable-line no-console
|
|
1215
1260
|
}
|
|
1216
1261
|
}
|
|
1217
1262
|
|
|
1218
|
-
|
|
1263
|
+
/** Write to `console.info` with node name as prefix if opts.debugLevel >= 3. */
|
|
1219
1264
|
logInfo(...args: any[]) {
|
|
1220
1265
|
if (this.tree.options.debugLevel! >= 3) {
|
|
1221
1266
|
console.info(this.toString(), ...args); // eslint-disable-line no-console
|
|
1222
1267
|
}
|
|
1223
1268
|
}
|
|
1224
1269
|
|
|
1225
|
-
|
|
1270
|
+
/** Write to `console.warn` with node name as prefix if opts.debugLevel >= 2. */
|
|
1226
1271
|
logWarn(...args: any[]) {
|
|
1227
1272
|
if (this.tree.options.debugLevel! >= 2) {
|
|
1228
1273
|
console.warn(this.toString(), ...args); // eslint-disable-line no-console
|
|
@@ -1425,11 +1470,11 @@ export class WunderbaumNode {
|
|
|
1425
1470
|
if (!this.children) {
|
|
1426
1471
|
return;
|
|
1427
1472
|
}
|
|
1428
|
-
if (tree.activeNode
|
|
1473
|
+
if (tree.activeNode?.isDescendantOf(this)) {
|
|
1429
1474
|
tree.activeNode.setActive(false); // TODO: don't fire events
|
|
1430
1475
|
}
|
|
1431
|
-
if (tree.focusNode
|
|
1432
|
-
tree.
|
|
1476
|
+
if (tree.focusNode?.isDescendantOf(this)) {
|
|
1477
|
+
tree._setFocusNode(null);
|
|
1433
1478
|
}
|
|
1434
1479
|
// TODO: persist must take care to clear select and expand cookies
|
|
1435
1480
|
// Unlink children to support GC
|
|
@@ -1613,7 +1658,7 @@ export class WunderbaumNode {
|
|
|
1613
1658
|
// Attach a node reference to the DOM Element:
|
|
1614
1659
|
(<any>rowDiv)._wb_node = this;
|
|
1615
1660
|
|
|
1616
|
-
const nodeElem:
|
|
1661
|
+
const nodeElem: HTMLSpanElement = document.createElement("span");
|
|
1617
1662
|
nodeElem.classList.add("wb-node", "wb-col");
|
|
1618
1663
|
rowDiv.appendChild(nodeElem);
|
|
1619
1664
|
|
|
@@ -1891,6 +1936,7 @@ export class WunderbaumNode {
|
|
|
1891
1936
|
let i = 0;
|
|
1892
1937
|
for (const colSpan of rowDiv.children) {
|
|
1893
1938
|
colSpan.classList.toggle("wb-active", i++ === tree.activeColIdx);
|
|
1939
|
+
colSpan.classList.remove("wb-error", "wb-invalid");
|
|
1894
1940
|
}
|
|
1895
1941
|
// Update icon (if not opts.isNew, which would rebuild markup anyway)
|
|
1896
1942
|
const iconSpan = nodeElem.querySelector("i.wb-icon") as HTMLElement;
|
|
@@ -2081,16 +2127,22 @@ export class WunderbaumNode {
|
|
|
2081
2127
|
}
|
|
2082
2128
|
|
|
2083
2129
|
/**
|
|
2084
|
-
* Activate this node, deactivate previous, send events, activate column and
|
|
2130
|
+
* Activate this node, deactivate previous, send events, activate column and
|
|
2131
|
+
* scroll into viewport.
|
|
2085
2132
|
*/
|
|
2086
2133
|
async setActive(flag: boolean = true, options?: SetActiveOptions) {
|
|
2087
2134
|
const tree = this.tree;
|
|
2088
|
-
const prev = tree.
|
|
2135
|
+
const prev = tree.getActiveNode();
|
|
2089
2136
|
const retrigger = options?.retrigger; // Default: false
|
|
2090
2137
|
const focusTree = options?.focusTree; // Default: false
|
|
2091
|
-
const focusNode = options?.focusNode !== false; // Default: true
|
|
2138
|
+
// const focusNode = options?.focusNode !== false; // Default: true
|
|
2092
2139
|
const noEvents = options?.noEvents; // Default: false
|
|
2093
|
-
const orgEvent = options?.event; // Default:
|
|
2140
|
+
const orgEvent = options?.event; // Default: null
|
|
2141
|
+
const colIdx = options?.colIdx; // Default: null
|
|
2142
|
+
const edit = options?.edit; // Default: false
|
|
2143
|
+
|
|
2144
|
+
util.assert(!colIdx || tree.isCellNav(), "colIdx requires cellNav");
|
|
2145
|
+
util.assert(!edit || colIdx != null, "edit requires colIdx");
|
|
2094
2146
|
|
|
2095
2147
|
if (!noEvents) {
|
|
2096
2148
|
if (flag) {
|
|
@@ -2107,7 +2159,7 @@ export class WunderbaumNode {
|
|
|
2107
2159
|
) {
|
|
2108
2160
|
return;
|
|
2109
2161
|
}
|
|
2110
|
-
tree.
|
|
2162
|
+
tree._setActiveNode(null);
|
|
2111
2163
|
prev?.update(ChangeType.status);
|
|
2112
2164
|
}
|
|
2113
2165
|
} else if (prev === this || retrigger) {
|
|
@@ -2117,29 +2169,30 @@ export class WunderbaumNode {
|
|
|
2117
2169
|
|
|
2118
2170
|
if (prev !== this) {
|
|
2119
2171
|
if (flag) {
|
|
2120
|
-
tree.
|
|
2121
|
-
if (focusNode || focusTree) {
|
|
2122
|
-
tree.focusNode = this;
|
|
2123
|
-
}
|
|
2124
|
-
if (focusTree) {
|
|
2125
|
-
tree.setFocus();
|
|
2126
|
-
}
|
|
2172
|
+
tree._setActiveNode(this);
|
|
2127
2173
|
}
|
|
2128
2174
|
prev?.update(ChangeType.status);
|
|
2129
2175
|
this.update(ChangeType.status);
|
|
2130
2176
|
}
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2177
|
+
return this.makeVisible().then(() => {
|
|
2178
|
+
if (flag) {
|
|
2179
|
+
if (focusTree || edit) {
|
|
2180
|
+
tree.setFocus();
|
|
2181
|
+
tree._setFocusNode(this);
|
|
2182
|
+
tree.focusNode!.setFocus();
|
|
2183
|
+
}
|
|
2184
|
+
// if (focusNode || edit) {
|
|
2185
|
+
// tree.focusNode = this;
|
|
2186
|
+
// tree.focusNode.setFocus();
|
|
2187
|
+
// }
|
|
2188
|
+
if (colIdx != null && tree.isCellNav()) {
|
|
2189
|
+
tree.setColumn(colIdx, { edit: edit });
|
|
2190
|
+
}
|
|
2191
|
+
if (!noEvents) {
|
|
2192
|
+
this._callEvent("activate", { prevNode: prev, event: orgEvent });
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2143
2196
|
}
|
|
2144
2197
|
|
|
2145
2198
|
/**
|
|
@@ -2147,18 +2200,26 @@ export class WunderbaumNode {
|
|
|
2147
2200
|
*/
|
|
2148
2201
|
async setExpanded(flag: boolean = true, options?: SetExpandedOptions) {
|
|
2149
2202
|
const { force, scrollIntoView, immediate } = options ?? {};
|
|
2203
|
+
const sendEvents = !options?.noEvents; // Default: send events
|
|
2150
2204
|
if (
|
|
2151
2205
|
!flag &&
|
|
2152
2206
|
this.isExpanded() &&
|
|
2153
2207
|
this.getLevel() <= this.tree.getOption("minExpandLevel") &&
|
|
2154
2208
|
!force
|
|
2155
2209
|
) {
|
|
2156
|
-
this.logDebug("Ignored collapse request below
|
|
2210
|
+
this.logDebug("Ignored collapse request below minExpandLevel.");
|
|
2157
2211
|
return;
|
|
2158
2212
|
}
|
|
2159
2213
|
if (!flag === !this.expanded) {
|
|
2160
2214
|
return; // Nothing to do
|
|
2161
2215
|
}
|
|
2216
|
+
if (
|
|
2217
|
+
sendEvents &&
|
|
2218
|
+
this._callEvent("beforeExpand", { flag: flag }) === false
|
|
2219
|
+
) {
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2162
2223
|
// this.log("setExpanded()");
|
|
2163
2224
|
if (flag && this.getOption("autoCollapse")) {
|
|
2164
2225
|
this.collapseSiblings(options);
|
|
@@ -2177,6 +2238,9 @@ export class WunderbaumNode {
|
|
|
2177
2238
|
lastChild.scrollIntoView({ topNode: this });
|
|
2178
2239
|
}
|
|
2179
2240
|
}
|
|
2241
|
+
if (sendEvents) {
|
|
2242
|
+
this._callEvent("expand", { flag: flag });
|
|
2243
|
+
}
|
|
2180
2244
|
}
|
|
2181
2245
|
|
|
2182
2246
|
/**
|
|
@@ -2184,9 +2248,9 @@ export class WunderbaumNode {
|
|
|
2184
2248
|
* @see {@link setActive}
|
|
2185
2249
|
*/
|
|
2186
2250
|
setFocus(flag: boolean = true) {
|
|
2187
|
-
util.assert(!!flag, "
|
|
2251
|
+
util.assert(!!flag, "Blur is not yet implemented");
|
|
2188
2252
|
const prev = this.tree.focusNode;
|
|
2189
|
-
this.tree.
|
|
2253
|
+
this.tree._setFocusNode(this);
|
|
2190
2254
|
prev?.update();
|
|
2191
2255
|
this.update();
|
|
2192
2256
|
}
|
package/src/wb_options.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
WbCancelableEventResultType,
|
|
8
9
|
ColumnDefinitionList,
|
|
9
10
|
DndOptionsType,
|
|
10
11
|
DynamicBoolOption,
|
|
@@ -13,6 +14,9 @@ import {
|
|
|
13
14
|
DynamicIconOption,
|
|
14
15
|
EditOptionsType,
|
|
15
16
|
FilterOptionsType,
|
|
17
|
+
GridOptionsType,
|
|
18
|
+
KeynavOptionsType,
|
|
19
|
+
LoggerOptionsType,
|
|
16
20
|
NavModeEnum,
|
|
17
21
|
NodeTypeDefinitionMap,
|
|
18
22
|
SelectModeType,
|
|
@@ -21,6 +25,7 @@ import {
|
|
|
21
25
|
WbClickEventType,
|
|
22
26
|
WbDeactivateEventType,
|
|
23
27
|
WbErrorEventType,
|
|
28
|
+
WbExpandEventType,
|
|
24
29
|
WbIconBadgeCallback,
|
|
25
30
|
WbInitEventType,
|
|
26
31
|
WbKeydownEventType,
|
|
@@ -28,11 +33,13 @@ import {
|
|
|
28
33
|
WbNodeEventType,
|
|
29
34
|
WbReceiveEventType,
|
|
30
35
|
WbRenderEventType,
|
|
36
|
+
WbSelectEventType,
|
|
31
37
|
WbTreeEventType,
|
|
38
|
+
WbIconBadgeEventResultType,
|
|
32
39
|
} from "./types";
|
|
33
40
|
|
|
34
41
|
/**
|
|
35
|
-
* Available options for
|
|
42
|
+
* Available options for {@link wunderbaum.Wunderbaum}.
|
|
36
43
|
*
|
|
37
44
|
* Options are passed to the constructor as plain object:
|
|
38
45
|
*
|
|
@@ -230,24 +237,40 @@ export interface WunderbaumOptions {
|
|
|
230
237
|
scrollIntoViewOnExpandClick?: boolean;
|
|
231
238
|
|
|
232
239
|
// --- Extensions ------------------------------------------------------------
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
|
|
241
|
+
dnd?: DndOptionsType;
|
|
242
|
+
edit?: EditOptionsType;
|
|
243
|
+
filter?: FilterOptionsType;
|
|
244
|
+
// grid?: GridOptionsType;
|
|
245
|
+
// keynav?: KeynavOptionsType;
|
|
246
|
+
// logger?: LoggerOptionsType;
|
|
237
247
|
|
|
238
248
|
// --- Events ----------------------------------------------------------------
|
|
239
249
|
|
|
240
250
|
/**
|
|
241
|
-
*
|
|
251
|
+
* `e.node` was activated.
|
|
242
252
|
* @category Callback
|
|
243
253
|
*/
|
|
244
254
|
activate?: (e: WbActivateEventType) => void;
|
|
255
|
+
/**
|
|
256
|
+
* `e.node` is about to be activated.
|
|
257
|
+
* Return `false` to prevent default handling, i.e. activating the node.
|
|
258
|
+
* See also `deactivate` event.
|
|
259
|
+
* @category Callback
|
|
260
|
+
*/
|
|
261
|
+
beforeActivate?: (e: WbActivateEventType) => WbCancelableEventResultType;
|
|
262
|
+
/**
|
|
263
|
+
* `e.node` is about to be expanded/collapsed.
|
|
264
|
+
* Return `false` to prevent default handling, i.e. expanding/collapsing the node.
|
|
265
|
+
* @category Callback
|
|
266
|
+
*/
|
|
267
|
+
beforeExpand?: (e: WbExpandEventType) => WbCancelableEventResultType;
|
|
245
268
|
/**
|
|
246
269
|
*
|
|
247
|
-
* Return `false` to prevent default handling, e.
|
|
270
|
+
* Return `false` to prevent default handling, i.e. (de)selecting the node.
|
|
248
271
|
* @category Callback
|
|
249
272
|
*/
|
|
250
|
-
|
|
273
|
+
beforeSelect?: (e: WbSelectEventType) => WbCancelableEventResultType;
|
|
251
274
|
/**
|
|
252
275
|
*
|
|
253
276
|
* @category Callback
|
|
@@ -255,44 +278,46 @@ export interface WunderbaumOptions {
|
|
|
255
278
|
change?: (e: WbChangeEventType) => void;
|
|
256
279
|
/**
|
|
257
280
|
*
|
|
258
|
-
* Return `false` to prevent default
|
|
281
|
+
* Return `false` to prevent default behavior, e.g. expand/collapse, (de)selection, or activation.
|
|
259
282
|
* @category Callback
|
|
260
283
|
*/
|
|
261
|
-
click?: (e: WbClickEventType) =>
|
|
284
|
+
click?: (e: WbClickEventType) => WbCancelableEventResultType;
|
|
262
285
|
/**
|
|
263
|
-
*
|
|
286
|
+
* Return `false` to prevent default behavior, e.g. expand/collapse.
|
|
264
287
|
* @category Callback
|
|
265
288
|
*/
|
|
266
|
-
dblclick?: (e: WbClickEventType) =>
|
|
289
|
+
dblclick?: (e: WbClickEventType) => WbCancelableEventResultType;
|
|
267
290
|
/**
|
|
291
|
+
* `e.node` was deactivated.
|
|
268
292
|
*
|
|
269
293
|
* Return `false` to prevent default handling, e.g. deactivating the node
|
|
270
294
|
* and activating the next.
|
|
295
|
+
* See also `activate` event.
|
|
271
296
|
* @category Callback
|
|
272
297
|
*/
|
|
273
|
-
deactivate?: (e: WbDeactivateEventType) =>
|
|
298
|
+
deactivate?: (e: WbDeactivateEventType) => WbCancelableEventResultType;
|
|
274
299
|
/**
|
|
275
|
-
*
|
|
300
|
+
* `e.node` was discarded from the viewport and its HTML markup removed.
|
|
276
301
|
* @category Callback
|
|
277
302
|
*/
|
|
278
303
|
discard?: (e: WbNodeEventType) => void;
|
|
279
304
|
/**
|
|
280
|
-
*
|
|
305
|
+
* `e.node` is about to be rendered. We can add a badge to the icon cell here.
|
|
281
306
|
* @category Callback
|
|
282
307
|
*/
|
|
283
|
-
iconBadge?: WbIconBadgeCallback;
|
|
284
|
-
// /**
|
|
285
|
-
// *
|
|
286
|
-
// * @category Callback
|
|
287
|
-
// */
|
|
288
|
-
// enhanceTitle?: (e: WbEnhanceTitleEventType) => void;
|
|
308
|
+
iconBadge?: (e: WbIconBadgeCallback) => WbIconBadgeEventResultType;
|
|
289
309
|
/**
|
|
290
|
-
*
|
|
310
|
+
* An error occurred, e.g. during initialization or lazy loading.
|
|
291
311
|
* @category Callback
|
|
292
312
|
*/
|
|
293
313
|
error?: (e: WbErrorEventType) => void;
|
|
294
314
|
/**
|
|
295
|
-
*
|
|
315
|
+
* `e.node` was expanded (`e.flag === true`) or collapsed (`e.flag === false`)
|
|
316
|
+
* @category Callback
|
|
317
|
+
*/
|
|
318
|
+
expand?: (e: WbTreeEventType) => void;
|
|
319
|
+
/**
|
|
320
|
+
* The tree received or lost focus.
|
|
296
321
|
* Check `e.flag` for status.
|
|
297
322
|
* @category Callback
|
|
298
323
|
*/
|
|
@@ -301,15 +326,17 @@ export interface WunderbaumOptions {
|
|
|
301
326
|
* Fires when the tree markup was created and the initial source data was loaded.
|
|
302
327
|
* Typical use cases would be activating a node, setting focus, enabling other
|
|
303
328
|
* controls on the page, etc.<br>
|
|
304
|
-
*
|
|
329
|
+
* Also sent if an error occured during initialization (check `e.error` for status).
|
|
305
330
|
* @category Callback
|
|
306
331
|
*/
|
|
307
332
|
init?: (e: WbInitEventType) => void;
|
|
308
333
|
/**
|
|
309
|
-
*
|
|
334
|
+
* Fires when a key was pressed while the tree has focus.
|
|
335
|
+
* `e.node` is set if a node is currently active.
|
|
336
|
+
* Return `false` to prevent default navigation.
|
|
310
337
|
* @category Callback
|
|
311
338
|
*/
|
|
312
|
-
keydown?: (e: WbKeydownEventType) =>
|
|
339
|
+
keydown?: (e: WbKeydownEventType) => WbCancelableEventResultType;
|
|
313
340
|
/**
|
|
314
341
|
* Fires when a node that was marked 'lazy', is expanded for the first time.
|
|
315
342
|
* Typically we return an endpoint URL or the Promise of a fetch request that
|
|
@@ -345,13 +372,12 @@ export interface WunderbaumOptions {
|
|
|
345
372
|
*/
|
|
346
373
|
render?: (e: WbRenderEventType) => void;
|
|
347
374
|
/**
|
|
348
|
-
*
|
|
375
|
+
* Same as `render(e)`, but for the status nodes, i.e. `e.node.statusNodeType`.
|
|
349
376
|
* @category Callback
|
|
350
377
|
*/
|
|
351
378
|
renderStatusNode?: (e: WbRenderEventType) => void;
|
|
352
379
|
/**
|
|
353
|
-
|
|
354
|
-
* Check `e.flag` for status.
|
|
380
|
+
*`e.node` was selected (`e.flag === true`) or deselected (`e.flag === false`)
|
|
355
381
|
* @category Callback
|
|
356
382
|
*/
|
|
357
383
|
select?: (e: WbNodeEventType) => void;
|
package/src/wunderbaum.scss
CHANGED
|
@@ -830,10 +830,16 @@ i.wb-icon {
|
|
|
830
830
|
|
|
831
831
|
.wb-col input:invalid {
|
|
832
832
|
// border-color: var(--wb-error-color);
|
|
833
|
-
color: var(--wb-error-color);
|
|
833
|
+
// color: var(--wb-error-color);
|
|
834
834
|
background-color: var(--wb-error-background-color);
|
|
835
835
|
}
|
|
836
836
|
|
|
837
|
+
.wb-col.wb-invalid {
|
|
838
|
+
border: 1px dotted var(--wb-error-color);
|
|
839
|
+
// color: var(--wb-error-color);
|
|
840
|
+
// background-color: var(--wb-error-background-color);
|
|
841
|
+
}
|
|
842
|
+
|
|
837
843
|
@keyframes wb-spin-animation {
|
|
838
844
|
0% {
|
|
839
845
|
transform: rotate(0deg);
|