wunderbaum 0.0.8 → 0.1.0
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 +2 -2
- package/dist/wunderbaum.d.ts +279 -80
- package/dist/wunderbaum.esm.js +346 -158
- package/dist/wunderbaum.esm.min.js +23 -23
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +346 -158
- package/dist/wunderbaum.umd.min.js +28 -28
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/drag_observer.ts +4 -3
- package/src/types.ts +171 -37
- package/src/wb_ext_dnd.ts +6 -1
- package/src/wb_ext_edit.ts +11 -9
- package/src/wb_ext_filter.ts +17 -7
- package/src/wb_ext_keynav.ts +54 -18
- package/src/wb_node.ts +164 -36
- package/src/wb_options.ts +31 -17
- package/src/wunderbaum.scss +85 -22
- package/src/wunderbaum.ts +144 -77
package/src/types.ts
CHANGED
|
@@ -17,16 +17,24 @@ export type BoolOrStringOptionResolver = (
|
|
|
17
17
|
) => boolean | string;
|
|
18
18
|
|
|
19
19
|
export type NodeAnyCallback = (node: WunderbaumNode) => any;
|
|
20
|
+
export type NodeStringCallback = (node: WunderbaumNode) => string;
|
|
20
21
|
|
|
21
22
|
export type NodeVisitResponse = "skip" | boolean | void;
|
|
22
23
|
export type NodeVisitCallback = (node: WunderbaumNode) => NodeVisitResponse;
|
|
23
24
|
|
|
24
25
|
// type WithWildcards<T> = T & { [key: string]: unknown };
|
|
26
|
+
|
|
27
|
+
/* -----------------------------------------------------------------------------
|
|
28
|
+
* EVENT CALLBACK TYPES
|
|
29
|
+
* ---------------------------------------------------------------------------*/
|
|
30
|
+
|
|
25
31
|
export interface WbTreeEventType {
|
|
26
32
|
/** Name of the event. */
|
|
27
33
|
type: string;
|
|
28
|
-
/** The affected tree. */
|
|
34
|
+
/** The affected tree instance. */
|
|
29
35
|
tree: Wunderbaum;
|
|
36
|
+
/** Exposed utility module methods. */
|
|
37
|
+
util: any;
|
|
30
38
|
/** Originating HTML event, e.g. `click` if any. */
|
|
31
39
|
event?: Event;
|
|
32
40
|
// [key: string]: unknown;
|
|
@@ -42,6 +50,63 @@ export interface WbNodeEventType extends WbTreeEventType {
|
|
|
42
50
|
typeInfo: NodeTypeDefinition;
|
|
43
51
|
}
|
|
44
52
|
|
|
53
|
+
export interface WbActivateEventType extends WbNodeEventType {
|
|
54
|
+
prevNode: WunderbaumNode;
|
|
55
|
+
/** The original event. */
|
|
56
|
+
event: Event;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface WbChangeEventType extends WbNodeEventType {
|
|
60
|
+
info: WbEventInfo;
|
|
61
|
+
inputElem: HTMLInputElement;
|
|
62
|
+
inputValue: any;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface WbClickEventType extends WbTreeEventType {
|
|
66
|
+
/** The original event. */
|
|
67
|
+
event: MouseEvent;
|
|
68
|
+
node: WunderbaumNode;
|
|
69
|
+
info: WbEventInfo;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface WbErrorEventType extends WbNodeEventType {
|
|
73
|
+
error: any;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface WbDeactivateEventType extends WbNodeEventType {
|
|
77
|
+
nextNode: WunderbaumNode;
|
|
78
|
+
/** The original event. */
|
|
79
|
+
event: Event;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface WbEnhanceTitleEventType extends WbNodeEventType {
|
|
83
|
+
titleSpan: HTMLSpanElement;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface WbFocusEventType extends WbTreeEventType {
|
|
87
|
+
/** The original event. */
|
|
88
|
+
event: FocusEvent;
|
|
89
|
+
/** True if `focusin`, false if `focusout`. */
|
|
90
|
+
flag: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WbKeydownEventType extends WbTreeEventType {
|
|
94
|
+
/** The original event. */
|
|
95
|
+
event: KeyboardEvent;
|
|
96
|
+
node: WunderbaumNode;
|
|
97
|
+
info: WbEventInfo;
|
|
98
|
+
/** Canical name of the key including modifiers. @see {@link eventToString} */
|
|
99
|
+
eventName: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface WbInitEventType extends WbTreeEventType {
|
|
103
|
+
error?: any;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface WbReceiveEventType extends WbNodeEventType {
|
|
107
|
+
response: any;
|
|
108
|
+
}
|
|
109
|
+
|
|
45
110
|
export interface WbRenderEventType extends WbNodeEventType {
|
|
46
111
|
/**
|
|
47
112
|
* True if the node's markup was not yet created. In this case the render
|
|
@@ -49,24 +114,22 @@ export interface WbRenderEventType extends WbNodeEventType {
|
|
|
49
114
|
* values according to to current node data).
|
|
50
115
|
*/
|
|
51
116
|
isNew: boolean;
|
|
52
|
-
/** True if the node only displays the title and is stretched over all remaining columns. */
|
|
53
|
-
isColspan: boolean;
|
|
54
|
-
// /** */
|
|
55
|
-
// isDataChange: boolean;
|
|
56
117
|
/** The node's `<span class='wb-node'>` element. */
|
|
57
118
|
nodeElem: HTMLSpanElement;
|
|
119
|
+
/** True if the node only displays the title and is stretched over all remaining columns. */
|
|
120
|
+
isColspan: boolean;
|
|
58
121
|
/**
|
|
59
122
|
* Array of node's `<span class='wb-col'>` elements.
|
|
60
123
|
* The first element is `<span class='wb-node wb-col'>`, which contains the
|
|
61
124
|
* node title and icon (`idx: 0`, id: '*'`).
|
|
62
125
|
*/
|
|
63
|
-
allColInfosById:
|
|
126
|
+
allColInfosById: ColumnEventInfoMap;
|
|
64
127
|
/**
|
|
65
128
|
* Array of node's `<span class='wb-node'>` elements, *that should be rendered*.
|
|
66
129
|
* In contrast to `allColInfosById`, the node title is not part of this array.
|
|
67
130
|
* If node.isColspan() is true, this array is empty (`[]`).
|
|
68
131
|
*/
|
|
69
|
-
renderColInfosById:
|
|
132
|
+
renderColInfosById: ColumnEventInfoMap;
|
|
70
133
|
}
|
|
71
134
|
|
|
72
135
|
/**
|
|
@@ -76,13 +139,13 @@ export interface WbRenderEventType extends WbNodeEventType {
|
|
|
76
139
|
export interface NodeTypeDefinition {
|
|
77
140
|
// /** Type ID that matches `node.type`. */
|
|
78
141
|
// id: string;
|
|
79
|
-
/** En/disable checkbox for matching nodes
|
|
142
|
+
/** En/disable checkbox for matching nodes. */
|
|
80
143
|
checkbox?: boolean | BoolOrStringOptionResolver;
|
|
81
|
-
/**
|
|
82
|
-
colspan?: boolean | BoolOptionResolver;
|
|
83
|
-
/** Optional class names that are added to all `div.wb-row` elements of matching nodes.*/
|
|
144
|
+
/** Optional class names that are added to all `div.wb-row` elements of matching nodes. */
|
|
84
145
|
classes?: string;
|
|
85
|
-
/**
|
|
146
|
+
/** Only show title and hide other columns if any. */
|
|
147
|
+
colspan?: boolean | BoolOptionResolver;
|
|
148
|
+
/** Default icon for matching nodes. */
|
|
86
149
|
icon?: boolean | string | BoolOrStringOptionResolver;
|
|
87
150
|
/**
|
|
88
151
|
* See also {@link WunderbaumNode.getOption|WunderbaumNode.getOption()}
|
|
@@ -93,26 +156,19 @@ export interface NodeTypeDefinition {
|
|
|
93
156
|
// _any: any;
|
|
94
157
|
}
|
|
95
158
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// icon?: string;
|
|
102
|
-
// classes?: string;
|
|
103
|
-
// // and more
|
|
104
|
-
// [key: string]: unknown;
|
|
105
|
-
// };
|
|
106
|
-
export type NodeTypeDefinitions = { [type: string]: NodeTypeDefinition };
|
|
159
|
+
/* -----------------------------------------------------------------------------
|
|
160
|
+
* DATA TYPES
|
|
161
|
+
* ---------------------------------------------------------------------------*/
|
|
162
|
+
|
|
163
|
+
export type NodeTypeDefinitionMap = { [type: string]: NodeTypeDefinition };
|
|
107
164
|
|
|
108
165
|
/**
|
|
166
|
+
* Column type definitions.
|
|
109
167
|
* @see {@link `Wunderbaum.columns`}
|
|
110
168
|
*/
|
|
111
169
|
export interface ColumnDefinition {
|
|
112
170
|
/** Column ID as defined in `tree.columns` definition ("*" for title column). */
|
|
113
171
|
id: string;
|
|
114
|
-
// /** */
|
|
115
|
-
// idx: number;
|
|
116
172
|
/** Column header (defaults to id) */
|
|
117
173
|
title: string;
|
|
118
174
|
/** Column header tooltip (optional) */
|
|
@@ -136,8 +192,12 @@ export interface ColumnDefinition {
|
|
|
136
192
|
_widthPx?: number;
|
|
137
193
|
_ofsPx?: number;
|
|
138
194
|
}
|
|
195
|
+
|
|
139
196
|
export type ColumnDefinitionList = Array<ColumnDefinition>;
|
|
140
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Column information (passed to the `render` event).
|
|
200
|
+
*/
|
|
141
201
|
export interface ColumnEventInfo {
|
|
142
202
|
/** Column ID as defined in `tree.columns` definition ("*" for title column). */
|
|
143
203
|
id: string;
|
|
@@ -148,11 +208,33 @@ export interface ColumnEventInfo {
|
|
|
148
208
|
/** The value of `tree.columns[]` for the current index. */
|
|
149
209
|
info: ColumnDefinition;
|
|
150
210
|
}
|
|
151
|
-
export type ColumnEventInfos = { [colId: string]: ColumnEventInfo };
|
|
152
211
|
|
|
153
|
-
export type
|
|
154
|
-
|
|
155
|
-
|
|
212
|
+
export type ColumnEventInfoMap = { [colId: string]: ColumnEventInfo };
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Additional inforation derived from mouse or keyboard events.
|
|
216
|
+
* @see {@link Wunderbaum.getEventInfo}
|
|
217
|
+
*/
|
|
218
|
+
export interface WbEventInfo {
|
|
219
|
+
/** The tree instance. */
|
|
220
|
+
tree: Wunderbaum;
|
|
221
|
+
/** The affected node instance instance if any. */
|
|
222
|
+
node: WunderbaumNode | null;
|
|
223
|
+
/** The affected part of the node span (e.g. title, expander, ...). */
|
|
224
|
+
region: NodeRegion;
|
|
225
|
+
/** The definition of the affected column if any. */
|
|
226
|
+
colDef?: ColumnDefinition;
|
|
227
|
+
/** The index of affected column or -1. */
|
|
228
|
+
colIdx: number;
|
|
229
|
+
/** The column definition ID of affected column if any. */
|
|
230
|
+
colId?: string;
|
|
231
|
+
/** The affected column's span tag if any. */
|
|
232
|
+
colElem?: HTMLSpanElement;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// export type WbTreeCallbackType = (e: WbTreeEventType) => any;
|
|
236
|
+
// export type WbNodeCallbackType = (e: WbNodeEventType) => any;
|
|
237
|
+
// export type WbRenderCallbackType = (e: WbRenderEventType) => void;
|
|
156
238
|
|
|
157
239
|
export type FilterModeType = null | "dim" | "hide";
|
|
158
240
|
export type ApplyCommandType =
|
|
@@ -210,7 +292,7 @@ export enum NodeStatusType {
|
|
|
210
292
|
}
|
|
211
293
|
|
|
212
294
|
/** Define the subregion of a node, where an event occurred. */
|
|
213
|
-
export enum
|
|
295
|
+
export enum NodeRegion {
|
|
214
296
|
unknown = "",
|
|
215
297
|
checkbox = "checkbox",
|
|
216
298
|
column = "column",
|
|
@@ -220,6 +302,18 @@ export enum TargetType {
|
|
|
220
302
|
title = "title",
|
|
221
303
|
}
|
|
222
304
|
|
|
305
|
+
/** Initial navigation mode and possible transition. */
|
|
306
|
+
export enum NavModeEnum {
|
|
307
|
+
startRow = "startRow", // Start with row mode, but allow cell-nav mode
|
|
308
|
+
cell = "cell", // Cell-nav mode only
|
|
309
|
+
startCell = "startCell", // Start in cell-nav mode, but allow row mode
|
|
310
|
+
row = "row", // Row mode only
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* -----------------------------------------------------------------------------
|
|
314
|
+
* METHOD OPTIONS TYPES
|
|
315
|
+
* ---------------------------------------------------------------------------*/
|
|
316
|
+
|
|
223
317
|
/** Possible values for {@link WunderbaumNode.addChildren()}. */
|
|
224
318
|
export interface AddChildrenOptions {
|
|
225
319
|
/** Insert children before this node (or index)
|
|
@@ -236,6 +330,11 @@ export interface AddChildrenOptions {
|
|
|
236
330
|
_level?: number;
|
|
237
331
|
}
|
|
238
332
|
|
|
333
|
+
/** Possible values for {@link Wunderbaum.applyCommand()} and {@link WunderbaumNode.applyCommand()}. */
|
|
334
|
+
export interface ApplyCommandOptions {
|
|
335
|
+
[key: string]: unknown;
|
|
336
|
+
}
|
|
337
|
+
|
|
239
338
|
/** Possible values for {@link Wunderbaum.expandAll()} and {@link WunderbaumNode.expandAll()}. */
|
|
240
339
|
export interface ExpandAllOptions {
|
|
241
340
|
/** Restrict expand level @default 99 */
|
|
@@ -246,6 +345,17 @@ export interface ExpandAllOptions {
|
|
|
246
345
|
force?: boolean;
|
|
247
346
|
}
|
|
248
347
|
|
|
348
|
+
/** Possible values for {@link Wunderbaum.filterNodes()} and {@link Wunderbaum.filterBranches()}. */
|
|
349
|
+
export interface FilterNodesOptions {
|
|
350
|
+
mode?: string;
|
|
351
|
+
leavesOnly?: boolean;
|
|
352
|
+
fuzzy?: boolean;
|
|
353
|
+
highlight?: boolean;
|
|
354
|
+
hideExpanders?: boolean;
|
|
355
|
+
autoExpand?: boolean;
|
|
356
|
+
noData?: boolean;
|
|
357
|
+
}
|
|
358
|
+
|
|
249
359
|
/** Possible values for {@link WunderbaumNode.makeVisible()}. */
|
|
250
360
|
export interface MakeVisibleOptions {
|
|
251
361
|
/** Do not animate expand (currently not implemented). @default false */
|
|
@@ -256,12 +366,20 @@ export interface MakeVisibleOptions {
|
|
|
256
366
|
noEvents?: boolean;
|
|
257
367
|
}
|
|
258
368
|
|
|
259
|
-
/**
|
|
260
|
-
export
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
369
|
+
/** Possible values for {@link Wunderbaum.navigate()}. */
|
|
370
|
+
export interface NavigateOptions {
|
|
371
|
+
activate?: boolean;
|
|
372
|
+
event?: Event;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Possible values for {@link WunderbaumNode.render()}. */
|
|
376
|
+
export interface RenderOptions {
|
|
377
|
+
change?: ChangeType;
|
|
378
|
+
after?: any;
|
|
379
|
+
isNew?: boolean;
|
|
380
|
+
preventScroll?: boolean;
|
|
381
|
+
isDataChange?: boolean;
|
|
382
|
+
top?: number;
|
|
265
383
|
}
|
|
266
384
|
|
|
267
385
|
/** Possible values for {@link scrollIntoView()}. */
|
|
@@ -336,9 +454,25 @@ export interface SetStatusOptions {
|
|
|
336
454
|
details?: string;
|
|
337
455
|
}
|
|
338
456
|
|
|
457
|
+
/** Possible values for {@link Wunderbaum.updateColumns()}. */
|
|
458
|
+
export interface UpdateColumnsOptions {
|
|
459
|
+
calculateCols?: boolean;
|
|
460
|
+
updateRows?: boolean;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/** Possible values for {@link Wunderbaum.visitRows()} and {@link Wunderbaum.visitRowsUp()}. */
|
|
464
|
+
export interface VisitRowsOptions {
|
|
465
|
+
reverse?: boolean;
|
|
466
|
+
includeSelf?: boolean;
|
|
467
|
+
includeHidden?: boolean;
|
|
468
|
+
wrap?: boolean;
|
|
469
|
+
start?: WunderbaumNode | null;
|
|
470
|
+
}
|
|
471
|
+
|
|
339
472
|
/* -----------------------------------------------------------------------------
|
|
340
473
|
* wb_ext_dnd
|
|
341
|
-
|
|
474
|
+
* ---------------------------------------------------------------------------*/
|
|
475
|
+
|
|
342
476
|
export type DropRegionType = "over" | "before" | "after";
|
|
343
477
|
export type DropRegionTypeSet = Set<DropRegionType>;
|
|
344
478
|
// type AllowedDropRegionType =
|
package/src/wb_ext_dnd.ts
CHANGED
|
@@ -144,7 +144,7 @@ export class DndExtension extends WunderbaumExtension {
|
|
|
144
144
|
protected autoScroll(event: DragEvent): number {
|
|
145
145
|
let tree = this.tree,
|
|
146
146
|
dndOpts = tree.options.dnd!,
|
|
147
|
-
sp = tree.
|
|
147
|
+
sp = tree.listContainerElement,
|
|
148
148
|
sensitivity = dndOpts.scrollSensitivity,
|
|
149
149
|
speed = dndOpts.scrollSpeed,
|
|
150
150
|
scrolled = 0;
|
|
@@ -180,6 +180,11 @@ export class DndExtension extends WunderbaumExtension {
|
|
|
180
180
|
if (e.type === "dragstart") {
|
|
181
181
|
// Set a default definition of allowed effects
|
|
182
182
|
e.dataTransfer!.effectAllowed = dndOpts.effectAllowed; //"copyMove"; // "all";
|
|
183
|
+
if (srcNode.isEditing()) {
|
|
184
|
+
srcNode.logDebug("Prevented dragging node in edit mode.");
|
|
185
|
+
e.preventDefault();
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
183
188
|
// Let user cancel the drag operation, override effectAllowed, etc.:
|
|
184
189
|
const res = srcNode._callEvent("dnd.dragStart", { event: e });
|
|
185
190
|
if (!res) {
|
package/src/wb_ext_edit.ts
CHANGED
|
@@ -196,7 +196,7 @@ export class EditExtension extends WunderbaumExtension {
|
|
|
196
196
|
// (we also treat a `true` return value as 'use default'):
|
|
197
197
|
if (inputHtml === true || !inputHtml) {
|
|
198
198
|
const title = escapeHtml(node.title);
|
|
199
|
-
inputHtml = `<input type=text class="wb-input-edit" value="${title}" required autocorrect=off>`;
|
|
199
|
+
inputHtml = `<input type=text class="wb-input-edit" tabindex=-1 value="${title}" required autocorrect=off>`;
|
|
200
200
|
}
|
|
201
201
|
const titleSpan = node
|
|
202
202
|
.getColElem(0)!
|
|
@@ -236,11 +236,11 @@ export class EditExtension extends WunderbaumExtension {
|
|
|
236
236
|
* @param apply
|
|
237
237
|
* @param opts.canKeepOpen
|
|
238
238
|
*/
|
|
239
|
-
_stopEditTitle(apply: boolean,
|
|
239
|
+
_stopEditTitle(apply: boolean, options: any) {
|
|
240
240
|
const focusElem = document.activeElement as HTMLInputElement;
|
|
241
241
|
let newValue = focusElem ? getValueFromElem(focusElem) : null;
|
|
242
242
|
const node = this.curEditNode;
|
|
243
|
-
const forceClose = !!
|
|
243
|
+
const forceClose = !!options.forceClose;
|
|
244
244
|
const validity = this.getPluginOption("validity");
|
|
245
245
|
|
|
246
246
|
if (newValue && this.getPluginOption("trim")) {
|
|
@@ -250,7 +250,7 @@ export class EditExtension extends WunderbaumExtension {
|
|
|
250
250
|
this.tree.logDebug("stopEditTitle: not in edit mode.");
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
-
node.logDebug(`stopEditTitle(${apply})`,
|
|
253
|
+
node.logDebug(`stopEditTitle(${apply})`, options, focusElem, newValue);
|
|
254
254
|
|
|
255
255
|
if (apply && newValue !== null && newValue !== node.title) {
|
|
256
256
|
const errMsg = focusElem.validationMessage;
|
|
@@ -283,21 +283,23 @@ export class EditExtension extends WunderbaumExtension {
|
|
|
283
283
|
return;
|
|
284
284
|
}
|
|
285
285
|
node?.setTitle(newValue);
|
|
286
|
-
this
|
|
286
|
+
// NOTE: At least on Safari, this render call triggers a scroll event
|
|
287
|
+
// probably because the focused input is replaced.
|
|
288
|
+
this.curEditNode!.render({ preventScroll: true });
|
|
287
289
|
this.curEditNode = null;
|
|
288
290
|
this.relatedNode = null;
|
|
289
291
|
this.tree.setFocus(); // restore focus that was in the input element
|
|
290
292
|
})
|
|
291
293
|
.catch((err) => {
|
|
292
|
-
|
|
293
|
-
// this.curEditNode = null;
|
|
294
|
-
// this.relatedNode = null;
|
|
294
|
+
node.logError(err);
|
|
295
295
|
});
|
|
296
296
|
// Trigger 'change' event for embedded `<input>`
|
|
297
297
|
// focusElem.blur();
|
|
298
298
|
} else {
|
|
299
299
|
// Discard the embedded `<input>`
|
|
300
|
-
this
|
|
300
|
+
// NOTE: At least on Safari, this render call triggers a scroll event
|
|
301
|
+
// probably because the focused input is replaced.
|
|
302
|
+
this.curEditNode!.render({ preventScroll: true });
|
|
301
303
|
this.curEditNode = null;
|
|
302
304
|
this.relatedNode = null;
|
|
303
305
|
// We discarded the <input>, so we have to acquire keyboard focus again
|
package/src/wb_ext_filter.ts
CHANGED
|
@@ -11,7 +11,11 @@ import {
|
|
|
11
11
|
extend,
|
|
12
12
|
onEvent,
|
|
13
13
|
} from "./util";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
FilterNodesOptions,
|
|
16
|
+
NodeFilterCallback,
|
|
17
|
+
NodeStatusType,
|
|
18
|
+
} from "./types";
|
|
15
19
|
import { Wunderbaum } from "./wunderbaum";
|
|
16
20
|
import { WunderbaumNode } from "./wb_node";
|
|
17
21
|
import { WunderbaumExtension } from "./wb_extension_base";
|
|
@@ -243,19 +247,25 @@ export class FilterExtension extends WunderbaumExtension {
|
|
|
243
247
|
/**
|
|
244
248
|
* [ext-filter] Dim or hide nodes.
|
|
245
249
|
*
|
|
246
|
-
* @param {boolean} [
|
|
250
|
+
* @param {boolean} [options={autoExpand: false, leavesOnly: false}]
|
|
247
251
|
*/
|
|
248
|
-
filterNodes(
|
|
249
|
-
|
|
252
|
+
filterNodes(
|
|
253
|
+
filter: string | NodeFilterCallback,
|
|
254
|
+
options: FilterNodesOptions
|
|
255
|
+
) {
|
|
256
|
+
return this._applyFilterNoUpdate(filter, false, options);
|
|
250
257
|
}
|
|
251
258
|
|
|
252
259
|
/**
|
|
253
260
|
* [ext-filter] Dim or hide whole branches.
|
|
254
261
|
*
|
|
255
|
-
* @param {boolean} [
|
|
262
|
+
* @param {boolean} [options={autoExpand: false}]
|
|
256
263
|
*/
|
|
257
|
-
filterBranches(
|
|
258
|
-
|
|
264
|
+
filterBranches(
|
|
265
|
+
filter: string | NodeFilterCallback,
|
|
266
|
+
options: FilterNodesOptions
|
|
267
|
+
) {
|
|
268
|
+
return this._applyFilterNoUpdate(filter, true, options);
|
|
259
269
|
}
|
|
260
270
|
|
|
261
271
|
/**
|
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 {
|
|
7
|
+
import { NavModeEnum } from "./types";
|
|
8
8
|
import { eventToString } from "./util";
|
|
9
9
|
import { Wunderbaum } from "./wunderbaum";
|
|
10
10
|
import { WunderbaumNode } from "./wb_node";
|
|
@@ -47,7 +47,7 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
47
47
|
opts = data.options,
|
|
48
48
|
activate = !event.ctrlKey || opts.autoActivate,
|
|
49
49
|
curInput = this._getEmbeddedInputElem(event.target),
|
|
50
|
-
navModeOption = opts.navigationModeOption as
|
|
50
|
+
navModeOption = opts.navigationModeOption as NavModeEnum;
|
|
51
51
|
// isCellEditMode = tree.navMode === NavigationMode.cellEdit;
|
|
52
52
|
|
|
53
53
|
let focusNode,
|
|
@@ -122,17 +122,30 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
122
122
|
|
|
123
123
|
// Pre-Evaluate expand/collapse action for LEFT/RIGHT
|
|
124
124
|
switch (eventName) {
|
|
125
|
+
case "Enter":
|
|
126
|
+
if (node.isActive()) {
|
|
127
|
+
if (node.isExpanded()) {
|
|
128
|
+
eventName = "Subtract"; // callapse
|
|
129
|
+
} else if (node.isExpandable(true)) {
|
|
130
|
+
eventName = "Add"; // expand
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
125
134
|
case "ArrowLeft":
|
|
126
135
|
if (node.expanded) {
|
|
127
136
|
eventName = "Subtract"; // collapse
|
|
128
137
|
}
|
|
129
138
|
break;
|
|
130
139
|
case "ArrowRight":
|
|
131
|
-
if (!node.expanded &&
|
|
140
|
+
if (!node.expanded && node.isExpandable(true)) {
|
|
132
141
|
eventName = "Add"; // expand
|
|
133
|
-
} else if (
|
|
142
|
+
} else if (
|
|
143
|
+
navModeOption === NavModeEnum.startCell ||
|
|
144
|
+
navModeOption === NavModeEnum.startRow
|
|
145
|
+
) {
|
|
146
|
+
event.preventDefault();
|
|
134
147
|
tree.setCellNav();
|
|
135
|
-
return;
|
|
148
|
+
return false;
|
|
136
149
|
}
|
|
137
150
|
break;
|
|
138
151
|
}
|
|
@@ -148,7 +161,7 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
148
161
|
case "Subtract":
|
|
149
162
|
node.setExpanded(false);
|
|
150
163
|
break;
|
|
151
|
-
case " ":
|
|
164
|
+
case " ": // Space
|
|
152
165
|
// if (node.isPagingNode()) {
|
|
153
166
|
// tree._triggerNodeEvent("clickPaging", ctx, event);
|
|
154
167
|
// } else
|
|
@@ -228,7 +241,16 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
228
241
|
}
|
|
229
242
|
|
|
230
243
|
switch (eventName) {
|
|
231
|
-
case "
|
|
244
|
+
case "+":
|
|
245
|
+
case "Add":
|
|
246
|
+
// case "=": // 187: '+' @ Chrome, Safari
|
|
247
|
+
node.setExpanded(true);
|
|
248
|
+
break;
|
|
249
|
+
case "-":
|
|
250
|
+
case "Subtract":
|
|
251
|
+
node.setExpanded(false);
|
|
252
|
+
break;
|
|
253
|
+
case " ": // Space
|
|
232
254
|
if (tree.activeColIdx === 0 && node.getOption("checkbox")) {
|
|
233
255
|
node.setSelected(!node.isSelected());
|
|
234
256
|
handled = true;
|
|
@@ -248,7 +270,7 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
248
270
|
break;
|
|
249
271
|
case "Enter":
|
|
250
272
|
tree.setFocus(); // Blur prev. input if any
|
|
251
|
-
if (tree.activeColIdx === 0 && node.isExpandable()) {
|
|
273
|
+
if ((tree.activeColIdx === 0 || isColspan) && node.isExpandable()) {
|
|
252
274
|
node.setExpanded(!node.isExpanded());
|
|
253
275
|
handled = true;
|
|
254
276
|
} else if (curInput && !inputHasFocus && inputCanFocus) {
|
|
@@ -258,7 +280,7 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
258
280
|
break;
|
|
259
281
|
case "Escape":
|
|
260
282
|
tree.setFocus(); // Blur prev. input if any
|
|
261
|
-
if (tree.isCellNav() && navModeOption !==
|
|
283
|
+
if (tree.isCellNav() && navModeOption !== NavModeEnum.cell) {
|
|
262
284
|
tree.setCellNav(false); // row-nav mode
|
|
263
285
|
handled = true;
|
|
264
286
|
}
|
|
@@ -269,7 +291,7 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
269
291
|
node.setExpanded(false);
|
|
270
292
|
} else if (!isColspan && tree.activeColIdx > 0) {
|
|
271
293
|
tree.setColumn(tree.activeColIdx - 1);
|
|
272
|
-
} else if (navModeOption !==
|
|
294
|
+
} else if (navModeOption !== NavModeEnum.cell) {
|
|
273
295
|
tree.setCellNav(false); // row-nav mode
|
|
274
296
|
}
|
|
275
297
|
handled = true;
|
|
@@ -286,17 +308,31 @@ export class KeynavExtension extends WunderbaumExtension {
|
|
|
286
308
|
}
|
|
287
309
|
handled = true;
|
|
288
310
|
break;
|
|
311
|
+
case "Home": // Generated by [Fn] + ArrowLeft on Mac
|
|
312
|
+
// case "Meta+ArrowLeft":
|
|
313
|
+
tree.setFocus(); // Blur prev. input if any
|
|
314
|
+
if (!isColspan && tree.activeColIdx > 0) {
|
|
315
|
+
tree.setColumn(0);
|
|
316
|
+
}
|
|
317
|
+
handled = true;
|
|
318
|
+
break;
|
|
319
|
+
case "End": // Generated by [Fn] + ArrowRight on Mac
|
|
320
|
+
// case "Meta+ArrowRight":
|
|
321
|
+
tree.setFocus(); // Blur prev. input if any
|
|
322
|
+
if (!isColspan && tree.activeColIdx < tree.columns.length - 1) {
|
|
323
|
+
tree.setColumn(tree.columns.length - 1);
|
|
324
|
+
}
|
|
325
|
+
handled = true;
|
|
326
|
+
break;
|
|
289
327
|
case "ArrowDown":
|
|
290
328
|
case "ArrowUp":
|
|
291
329
|
case "Backspace":
|
|
292
|
-
case "End":
|
|
293
|
-
case "Home":
|
|
294
|
-
case "
|
|
295
|
-
case "
|
|
296
|
-
case "
|
|
297
|
-
case "
|
|
298
|
-
case "PageDown":
|
|
299
|
-
case "PageUp":
|
|
330
|
+
case "Control+End": // Generated by Control + [Fn] + ArrowRight on Mac
|
|
331
|
+
case "Control+Home": // Generated by Control + [Fn] + Arrowleft on Mac
|
|
332
|
+
case "Meta+ArrowDown": // [⌘] + ArrowDown on Mac
|
|
333
|
+
case "Meta+ArrowUp": // [⌘] + ArrowUp on Mac
|
|
334
|
+
case "PageDown": // Generated by [Fn] + ArrowDown on Mac
|
|
335
|
+
case "PageUp": // Generated by [Fn] + ArrowUp on Mac
|
|
300
336
|
node.navigate(eventName, { activate: activate, event: event });
|
|
301
337
|
// if (isCellEditMode) {
|
|
302
338
|
// this._getEmbeddedInputElem(null, true); // set focus to input
|