wunderbaum 0.0.1 → 0.0.2

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.
@@ -0,0 +1,169 @@
1
+ /*!
2
+ * Wunderbaum - drag_observer
3
+ * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
4
+ * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
+ */
6
+ import * as util from "./util";
7
+
8
+ export type DragCallbackArgType = {
9
+ /** "dragstart", "drag", or "dragstop". */
10
+ type: string;
11
+ /** Original mouse or touch event that triggered the drag event. */
12
+ event: MouseEvent | TouchEvent;
13
+ /** Element which is currently dragged. */
14
+ dragElem: HTMLElement | null;
15
+ /** Relative horizontal drag distance since start. */
16
+ dx: number;
17
+ /** Relative vertical drag distance since start. */
18
+ dy: number;
19
+ /** False if drag was canceled. */
20
+ apply?: boolean;
21
+ };
22
+ export type DragCallbackType = (e: DragCallbackArgType) => boolean | void;
23
+ type DragObserverOptionsType = {
24
+ /**Event target (typically `window.document`). */
25
+ root: EventTarget;
26
+ /**Event delegation selector.*/
27
+ selector?: string;
28
+ /**Minimum drag distance in px. */
29
+ thresh?: number;
30
+ /**Return `false` to cancel drag. */
31
+ dragstart: DragCallbackType;
32
+ drag?: DragCallbackType;
33
+ dragstop?: DragCallbackType;
34
+ };
35
+
36
+ /**
37
+ * Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
38
+ */
39
+ export class DragObserver {
40
+ protected _handler;
41
+ protected root: EventTarget;
42
+ protected start = {
43
+ x: 0,
44
+ y: 0,
45
+ altKey: false,
46
+ ctrlKey: false,
47
+ metaKey: false,
48
+ shiftKey: false,
49
+ };
50
+ protected dragElem: HTMLElement | null = null;
51
+ protected dragging: boolean = false;
52
+ // TODO: touch events
53
+ protected events = ["mousedown", "mouseup", "mousemove", "keydown"];
54
+ protected opts: DragObserverOptionsType;
55
+
56
+ constructor(opts: DragObserverOptionsType) {
57
+ util.assert(opts.root);
58
+ this.opts = util.extend({ thresh: 5 }, opts);
59
+ this.root = opts.root;
60
+ this._handler = this.handleEvent.bind(this) as EventListener;
61
+ this.events.forEach((type) => {
62
+ this.root.addEventListener(type, this._handler);
63
+ });
64
+ }
65
+ /** Unregister all event listeners. */
66
+ disconnect() {
67
+ this.events.forEach((type) => {
68
+ this.root.removeEventListener(type, this._handler);
69
+ });
70
+ }
71
+
72
+ public getDragElem(): HTMLElement | null {
73
+ return this.dragElem;
74
+ }
75
+
76
+ public isDragging(): boolean {
77
+ return this.dragging;
78
+ }
79
+
80
+ public stopDrag(cb_event?: DragCallbackArgType): void {
81
+ if (this.dragging && this.opts.dragstop && cb_event) {
82
+ cb_event.type = "dragstop";
83
+ this.opts.dragstop(cb_event);
84
+ }
85
+ this.dragElem = null;
86
+ this.dragging = false;
87
+ }
88
+
89
+ protected handleEvent(e: MouseEvent): boolean | void {
90
+ const type = e.type;
91
+ const opts = this.opts;
92
+ const cb_event: DragCallbackArgType = {
93
+ type: e.type,
94
+ event: e,
95
+ dragElem: this.dragElem,
96
+ dx: e.pageX - this.start.x,
97
+ dy: e.pageY - this.start.y,
98
+ apply: undefined,
99
+ };
100
+ switch (type) {
101
+ case "keydown":
102
+ this.stopDrag(cb_event);
103
+ break;
104
+ case "mousedown":
105
+ if (this.dragElem) {
106
+ this.stopDrag(cb_event);
107
+ break;
108
+ }
109
+ if (opts.selector) {
110
+ let elem = e.target as HTMLElement;
111
+ if (elem.matches(opts.selector)) {
112
+ this.dragElem = elem;
113
+ } else {
114
+ elem = elem.closest(opts.selector) as HTMLElement;
115
+ if (elem) {
116
+ this.dragElem = elem;
117
+ } else {
118
+ break; // no event delegation selector matched
119
+ }
120
+ }
121
+ }
122
+ this.start.x = e.pageX;
123
+ this.start.y = e.pageY;
124
+ this.start.altKey = e.altKey;
125
+ this.start.ctrlKey = e.ctrlKey;
126
+ this.start.metaKey = e.metaKey;
127
+ this.start.shiftKey = e.shiftKey;
128
+ break;
129
+
130
+ case "mousemove":
131
+ // TODO: debounce/throttle?
132
+ // TODO: horizontal mode: ignore if dx unchanged
133
+ if (!this.dragElem) {
134
+ break;
135
+ }
136
+ if (!this.dragging) {
137
+ if (opts.thresh) {
138
+ const dist2 = cb_event.dx * cb_event.dx + cb_event.dy * cb_event.dy;
139
+ if (dist2 < opts.thresh * opts.thresh) {
140
+ break;
141
+ }
142
+ }
143
+ cb_event.type = "dragstart";
144
+ if (opts.dragstart(cb_event) === false) {
145
+ this.stopDrag(cb_event);
146
+ break;
147
+ }
148
+ this.dragging = true;
149
+ }
150
+ if (this.dragging && this.opts.drag) {
151
+ cb_event.type = "drag";
152
+ this.opts.drag(cb_event);
153
+ }
154
+ break;
155
+ case "mouseup":
156
+ if (!this.dragging) {
157
+ this.stopDrag(cb_event);
158
+ break;
159
+ }
160
+ if (e.button === 0) {
161
+ cb_event.apply = true;
162
+ } else {
163
+ cb_event.apply = false;
164
+ }
165
+ this.stopDrag(cb_event);
166
+ break;
167
+ }
168
+ }
169
+ }
package/src/util.ts CHANGED
@@ -16,7 +16,7 @@ export const MOUSE_BUTTONS: { [key: number]: string } = {
16
16
 
17
17
  export const MAX_INT = 9007199254740991;
18
18
  const userInfo = _getUserInfo();
19
- /**True if the user is using a macOS platform. */
19
+ /**True if the client is using a macOS platform. */
20
20
  export const isMac = userInfo.isMac;
21
21
 
22
22
  const REX_HTML = /[&<>"'/]/g; // Escape those characters
@@ -186,7 +186,7 @@ export function escapeTooltip(s: string): string {
186
186
  /** TODO */
187
187
  export function extractHtmlText(s: string) {
188
188
  if (s.indexOf(">") >= 0) {
189
- error("not implemented");
189
+ error("Not implemented");
190
190
  // return $("<div/>").html(s).text();
191
191
  }
192
192
  return s;
@@ -315,7 +315,7 @@ export function setValueToElem(elem: HTMLElement, value: any): void {
315
315
  input.valueAsNumber = value;
316
316
  break;
317
317
  case "radio":
318
- assert(false, "not implemented");
318
+ error("Not implemented");
319
319
  // const name = input.name;
320
320
  // const checked = input.parentElement!.querySelector(
321
321
  // `input[name="${name}"]:checked`
@@ -338,7 +338,7 @@ export function setValueToElem(elem: HTMLElement, value: any): void {
338
338
  // return value;
339
339
  }
340
340
 
341
- /** Return an unconnected `HTMLElement` from a HTML string. */
341
+ /** Create and return an unconnected `HTMLElement` from a HTML string. */
342
342
  export function elemFromHtml(html: string): HTMLElement {
343
343
  const t = document.createElement("template");
344
344
  t.innerHTML = html.trim();
@@ -358,11 +358,26 @@ export function elemFromSelector(obj: string | Element): HTMLElement | null {
358
358
  return obj as HTMLElement;
359
359
  }
360
360
 
361
+ /** Return a EventTarget from selector or cast an existing element. */
362
+ export function eventTargetFromSelector(
363
+ obj: string | EventTarget
364
+ ): EventTarget | null {
365
+ if (!obj) {
366
+ return null;
367
+ }
368
+ if (typeof obj === "string") {
369
+ return document.querySelector(obj) as EventTarget;
370
+ }
371
+ return obj as EventTarget;
372
+ }
373
+
361
374
  /**
362
- * Return a descriptive string for a keyboard or mouse event.
375
+ * Return a canonical descriptive string for a keyboard or mouse event.
363
376
  *
364
377
  * The result also contains a prefix for modifiers if any, for example
365
378
  * `"x"`, `"F2"`, `"Control+Home"`, or `"Shift+clickright"`.
379
+ * This is especially useful in `switch` statements, to make sure that modifier
380
+ * keys are considered and handled correctly.
366
381
  */
367
382
  export function eventToString(event: Event): string {
368
383
  let key = (<KeyboardEvent>event).key,
@@ -397,6 +412,13 @@ export function eventToString(event: Event): string {
397
412
  return s.join("+");
398
413
  }
399
414
 
415
+ /**
416
+ * Copy allproperties from one or more source objects to a target object.
417
+ *
418
+ * @returns the modified target object.
419
+ */
420
+ // TODO: use Object.assign()? --> https://stackoverflow.com/a/42740894
421
+ // TODO: support deep merge --> https://stackoverflow.com/a/42740894
400
422
  export function extend(...args: any[]) {
401
423
  for (let i = 1; i < args.length; i++) {
402
424
  let arg = args[i];
@@ -412,18 +434,22 @@ export function extend(...args: any[]) {
412
434
  return args[0];
413
435
  }
414
436
 
437
+ /** Return true if `obj` is of type `array`. */
415
438
  export function isArray(obj: any) {
416
439
  return Array.isArray(obj);
417
440
  }
418
441
 
442
+ /** Return true if `obj` is of type `Object` and has no propertied. */
419
443
  export function isEmptyObject(obj: any) {
420
444
  return Object.keys(obj).length === 0 && obj.constructor === Object;
421
445
  }
422
446
 
447
+ /** Return true if `obj` is of type `function`. */
423
448
  export function isFunction(obj: any) {
424
449
  return typeof obj === "function";
425
450
  }
426
451
 
452
+ /** Return true if `obj` is of type `Object`. */
427
453
  export function isPlainObject(obj: any) {
428
454
  return Object.prototype.toString.call(obj) === "[object Object]";
429
455
  }
@@ -432,14 +458,14 @@ export function isPlainObject(obj: any) {
432
458
  export function noop(...args: any[]): any {}
433
459
 
434
460
  /**
435
- * Bind one or more event handlers directly to an [[HtmlElement]].
461
+ * Bind one or more event handlers directly to an [[EventTarget]].
436
462
  *
437
- * @param element HTMLElement or selector
463
+ * @param element EventTarget or selector
438
464
  * @param eventNames
439
465
  * @param handler
440
466
  */
441
467
  export function onEvent(
442
- rootElem: HTMLElement | string,
468
+ rootTarget: EventTarget | string,
443
469
  eventNames: string,
444
470
  handler: EventCallbackType
445
471
  ): void;
@@ -455,26 +481,26 @@ export function onEvent(
455
481
  * });
456
482
  * ```
457
483
  *
458
- * @param element HTMLElement or selector
484
+ * @param element EventTarget or selector
459
485
  * @param eventNames
460
486
  * @param selector
461
487
  * @param handler
462
488
  */
463
489
  export function onEvent(
464
- rootElem: HTMLElement | string,
490
+ rootTarget: EventTarget | string,
465
491
  eventNames: string,
466
492
  selector: string,
467
493
  handler: EventCallbackType
468
494
  ): void;
469
495
 
470
496
  export function onEvent(
471
- rootElem: HTMLElement | string,
497
+ rootTarget: EventTarget | string,
472
498
  eventNames: string,
473
499
  selectorOrHandler: string | EventCallbackType,
474
500
  handlerOrNone?: EventCallbackType
475
501
  ): void {
476
502
  let selector: string | null, handler: EventCallbackType;
477
- rootElem = elemFromSelector(rootElem)!;
503
+ rootTarget = eventTargetFromSelector(rootTarget)!;
478
504
 
479
505
  if (handlerOrNone) {
480
506
  selector = selectorOrHandler as string;
@@ -485,7 +511,7 @@ export function onEvent(
485
511
  }
486
512
 
487
513
  eventNames.split(" ").forEach((evn) => {
488
- (<HTMLElement>rootElem).addEventListener(evn, function (e) {
514
+ (<EventTarget>rootTarget).addEventListener(evn, function (e) {
489
515
  if (!selector) {
490
516
  return handler!(e); // no event delegation
491
517
  } else if (e.target) {
@@ -578,6 +604,13 @@ export async function sleep(ms: number) {
578
604
 
579
605
  /**
580
606
  * Set or rotate checkbox status with support for tri-state.
607
+ *
608
+ * An initial 'indeterminate' state becomes 'checked' on the first call.
609
+ *
610
+ * If the input element has the class 'wb-tristate' assigned, the sequence is:<br>
611
+ * 'indeterminate' -> 'checked' -> 'unchecked' -> 'indeterminate' -> ...<br>
612
+ * Otherwise we toggle like <br>
613
+ * 'checked' -> 'unchecked' -> 'checked' -> ...
581
614
  */
582
615
  export function toggleCheckbox(
583
616
  element: HTMLElement | string,
@@ -648,6 +681,7 @@ export function toSet(val: any): Set<string> {
648
681
  throw new Error("Cannot convert to Set<string>: " + val);
649
682
  }
650
683
 
684
+ /**Return a canonical string representation for an object's type (e.g. 'array', 'number', ...) */
651
685
  export function type(obj: any): string {
652
686
  return Object.prototype.toString
653
687
  .call(obj)
package/src/wb_ext_dnd.ts CHANGED
@@ -8,7 +8,7 @@ import { EventCallbackType, onEvent } from "./util";
8
8
  import { Wunderbaum } from "./wunderbaum";
9
9
  import { WunderbaumExtension } from "./wb_extension_base";
10
10
  import { WunderbaumNode } from "./wb_node";
11
- import { ROW_HEIGHT } from "./common";
11
+ import { ROW_HEIGHT, WbNodeEventType } from "./common";
12
12
 
13
13
  const nodeMimeType = "application/x-wunderbaum-node";
14
14
  export type DropRegionType = "over" | "before" | "after";
@@ -24,6 +24,147 @@ type DropRegionTypeSet = Set<DropRegionType>;
24
24
  // | "none" // == false == "" == null
25
25
  // | "over"; // == "child"
26
26
 
27
+ export type DndOptionsType = {
28
+ /**
29
+ * Expand nodes after n milliseconds of hovering
30
+ * Default: 1500
31
+ */
32
+ autoExpandMS: 1500;
33
+ // /**
34
+ // * Additional offset for drop-marker with hitMode = "before"/"after"
35
+ // * Default:
36
+ // */
37
+ // dropMarkerInsertOffsetX: -16;
38
+ // /**
39
+ // * Absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
40
+ // * Default:
41
+ // */
42
+ // dropMarkerOffsetX: -24;
43
+ // /**
44
+ // * Root Container used for drop marker (could be a shadow root)
45
+ // * (#1021 `document.body` is not available yet)
46
+ // * Default:
47
+ // */
48
+ // dropMarkerParent: "body";
49
+ /**
50
+ * true: Drag multiple (i.e. selected) nodes. Also a callback() is allowed
51
+ * Default: false
52
+ */
53
+ multiSource: false;
54
+ /**
55
+ * Restrict the possible cursor shapes and modifier operations (can also be set in the dragStart event)
56
+ * Default: "all"
57
+ */
58
+ effectAllowed: "all";
59
+ // /**
60
+ // * 'copy'|'link'|'move'|'auto'(calculate from `effectAllowed`+modifier keys) or callback(node, data) that returns such string.
61
+ // * Default:
62
+ // */
63
+ // dropEffect: "auto";
64
+ /**
65
+ * Default dropEffect ('copy', 'link', or 'move') when no modifier is pressed (overide in dragDrag, dragOver).
66
+ * Default: "move"
67
+ */
68
+ dropEffectDefault: string;
69
+ /**
70
+ * Prevent dropping nodes from different Wunderbaum trees
71
+ * Default: false
72
+ */
73
+ preventForeignNodes: boolean;
74
+ /**
75
+ * Prevent dropping items on unloaded lazy Wunderbaum tree nodes
76
+ * Default: true
77
+ */
78
+ preventLazyParents: boolean;
79
+ /**
80
+ * Prevent dropping items other than Wunderbaum tree nodes
81
+ * Default: false
82
+ */
83
+ preventNonNodes: boolean;
84
+ /**
85
+ * Prevent dropping nodes on own descendants
86
+ * Default: true
87
+ */
88
+ preventRecursion: boolean;
89
+ /**
90
+ * Prevent dropping nodes under same direct parent
91
+ * Default: false
92
+ */
93
+ preventSameParent: false;
94
+ /**
95
+ * Prevent dropping nodes 'before self', etc. (move only)
96
+ * Default: true
97
+ */
98
+ preventVoidMoves: boolean;
99
+ /**
100
+ * Enable auto-scrolling while dragging
101
+ * Default: true
102
+ */
103
+ scroll: boolean;
104
+ /**
105
+ * Active top/bottom margin in pixel
106
+ * Default: 20
107
+ */
108
+ scrollSensitivity: 20;
109
+ /**
110
+ * Pixel per event
111
+ * Default: 5
112
+ */
113
+ scrollSpeed: 5;
114
+ // /**
115
+ // * Allow dragging of nodes to different IE windows
116
+ // * Default: false
117
+ // */
118
+ // setTextTypeJson: boolean;
119
+ /**
120
+ * Optional callback passed to `toDict` on dragStart @since 2.38
121
+ * Default: null
122
+ */
123
+ sourceCopyHook: null;
124
+ // Events (drag support)
125
+ /**
126
+ * Callback(sourceNode, data), return true, to enable dnd drag
127
+ * Default: null
128
+ */
129
+ dragStart?: WbNodeEventType;
130
+ /**
131
+ * Callback(sourceNode, data)
132
+ * Default: null
133
+ */
134
+ dragDrag: null;
135
+ /**
136
+ * Callback(sourceNode, data)
137
+ * Default: null
138
+ */
139
+ dragEnd: null;
140
+ // Events (drop support)
141
+ /**
142
+ * Callback(targetNode, data), return true, to enable dnd drop
143
+ * Default: null
144
+ */
145
+ dragEnter: null;
146
+ /**
147
+ * Callback(targetNode, data)
148
+ * Default: null
149
+ */
150
+ dragOver: null;
151
+ /**
152
+ * Callback(targetNode, data), return false to prevent autoExpand
153
+ * Default: null
154
+ */
155
+ dragExpand: null;
156
+ /**
157
+ * Callback(targetNode, data)
158
+ * Default: null
159
+ */
160
+ dragDrop: null;
161
+ /**
162
+ * Callback(targetNode, data)
163
+ * Default: null
164
+ */
165
+ dragLeave: null;
166
+ };
167
+
27
168
  export class DndExtension extends WunderbaumExtension {
28
169
  // public dropMarkerElem?: HTMLElement;
29
170
  protected srcNode: WunderbaumNode | null = null;
@@ -78,7 +219,7 @@ export class DndExtension extends WunderbaumExtension {
78
219
  // this.$scrollParent = $temp.scrollParent();
79
220
  // $temp.remove();
80
221
  const tree = this.tree;
81
- const dndOpts = tree.options.dnd;
222
+ const dndOpts = tree.options.dnd!;
82
223
 
83
224
  // Enable drag support if dragStart() is specified:
84
225
  if (dndOpts.dragStart) {
@@ -153,7 +294,7 @@ export class DndExtension extends WunderbaumExtension {
153
294
  /* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
154
295
  protected autoScroll(event: DragEvent): number {
155
296
  let tree = this.tree,
156
- dndOpts = tree.options.dnd,
297
+ dndOpts = tree.options.dnd!,
157
298
  sp = tree.scrollContainer,
158
299
  sensitivity = dndOpts.scrollSensitivity,
159
300
  speed = dndOpts.scrollSpeed,
@@ -9,7 +9,6 @@ import {
9
9
  escapeHtml,
10
10
  escapeRegex,
11
11
  extend,
12
- extractHtmlText,
13
12
  onEvent,
14
13
  } from "./util";
15
14
  import { NodeFilterCallback, NodeStatusType } from "./common";
@@ -79,7 +78,7 @@ export class FilterExtension extends WunderbaumExtension {
79
78
  count = 0,
80
79
  tree = this.tree,
81
80
  treeOpts = tree.options,
82
- escapeTitles = treeOpts.escapeTitles,
81
+ // escapeTitles = treeOpts.escapeTitles,
83
82
  prevAutoCollapse = treeOpts.autoCollapse,
84
83
  opts = extend({}, treeOpts.filter, _opts),
85
84
  hideMode = opts.mode === "hide",
@@ -118,35 +117,36 @@ export class FilterExtension extends WunderbaumExtension {
118
117
  if (!node.title) {
119
118
  return false;
120
119
  }
121
- let text = escapeTitles ? node.title : extractHtmlText(node.title);
120
+ // let text = escapeTitles ? node.title : extractHtmlText(node.title);
121
+ let text = node.title;
122
122
  // `.match` instead of `.test` to get the capture groups
123
123
  let res = text.match(re);
124
124
 
125
125
  if (res && opts.highlight) {
126
- if (escapeTitles) {
127
- if (opts.fuzzy) {
128
- temp = _markFuzzyMatchedChars(text, res, escapeTitles);
129
- } else {
130
- // #740: we must not apply the marks to escaped entity names, e.g. `&quot;`
131
- // Use some exotic characters to mark matches:
132
- temp = text.replace(reHighlight, function (s) {
133
- return START_MARKER + s + END_MARKER;
134
- });
135
- }
136
- // now we can escape the title...
137
- node.titleWithHighlight = escapeHtml(temp)
138
- // ... and finally insert the desired `<mark>` tags
139
- .replace(RE_START_MARKER, "<mark>")
140
- .replace(RE_END_MARTKER, "</mark>");
126
+ // if (escapeTitles) {
127
+ if (opts.fuzzy) {
128
+ temp = _markFuzzyMatchedChars(text, res, true);
141
129
  } else {
142
- if (opts.fuzzy) {
143
- node.titleWithHighlight = _markFuzzyMatchedChars(text, res);
144
- } else {
145
- node.titleWithHighlight = text.replace(reHighlight, function (s) {
146
- return "<mark>" + s + "</mark>";
147
- });
148
- }
130
+ // #740: we must not apply the marks to escaped entity names, e.g. `&quot;`
131
+ // Use some exotic characters to mark matches:
132
+ temp = text.replace(reHighlight, function (s) {
133
+ return START_MARKER + s + END_MARKER;
134
+ });
149
135
  }
136
+ // now we can escape the title...
137
+ node.titleWithHighlight = escapeHtml(temp)
138
+ // ... and finally insert the desired `<mark>` tags
139
+ .replace(RE_START_MARKER, "<mark>")
140
+ .replace(RE_END_MARTKER, "</mark>");
141
+ // } else {
142
+ // if (opts.fuzzy) {
143
+ // node.titleWithHighlight = _markFuzzyMatchedChars(text, res);
144
+ // } else {
145
+ // node.titleWithHighlight = text.replace(reHighlight, function (s) {
146
+ // return "<mark>" + s + "</mark>";
147
+ // });
148
+ // }
149
+ // }
150
150
  // node.debug("filter", escapeTitles, text, node.titleWithHighlight);
151
151
  }
152
152
  return !!res;
@@ -266,9 +266,9 @@ export class FilterExtension extends WunderbaumExtension {
266
266
  * [ext-filter] Reset the filter.
267
267
  */
268
268
  clearFilter() {
269
- let tree = this.tree,
270
- // statusNode = tree.root.findDirectChild(KEY_NODATA),
271
- escapeTitles = tree.options.escapeTitles;
269
+ let tree = this.tree;
270
+ // statusNode = tree.root.findDirectChild(KEY_NODATA),
271
+ // escapeTitles = tree.options.escapeTitles;
272
272
  // enhanceTitle = tree.options.enhanceTitle,
273
273
  tree.enableUpdate(false);
274
274
 
@@ -284,11 +284,11 @@ export class FilterExtension extends WunderbaumExtension {
284
284
  if (node.match && node._rowElem) {
285
285
  // #491, #601
286
286
  let titleElem = node._rowElem.querySelector("span.wb-title")!;
287
- if (escapeTitles) {
288
- titleElem.textContent = node.title;
289
- } else {
290
- titleElem.innerHTML = node.title;
291
- }
287
+ // if (escapeTitles) {
288
+ titleElem.textContent = node.title;
289
+ // } else {
290
+ // titleElem.innerHTML = node.title;
291
+ // }
292
292
  node._callEvent("enhanceTitle", { titleElem: titleElem });
293
293
  }
294
294
  delete node.match;
@@ -330,7 +330,7 @@ export class FilterExtension extends WunderbaumExtension {
330
330
  function _markFuzzyMatchedChars(
331
331
  text: string,
332
332
  matches: RegExpMatchArray,
333
- escapeTitles = false
333
+ escapeTitles = true
334
334
  ) {
335
335
  let matchingIndices = [];
336
336
  // get the indices of matched characters (Iterate through `RegExpMatchArray`)
@@ -350,7 +350,7 @@ function _markFuzzyMatchedChars(
350
350
  // Map each `text` char to its position and store in `textPoses`.
351
351
  let textPoses = text.split("");
352
352
  if (escapeTitles) {
353
- // If escaping the title, then wrap the matchng char within exotic chars
353
+ // If escaping the title, then wrap the matching char within exotic chars
354
354
  matchingIndices.forEach(function (v) {
355
355
  textPoses[v] = START_MARKER + textPoses[v] + END_MARKER;
356
356
  });
@@ -0,0 +1,45 @@
1
+ /*!
2
+ * Wunderbaum - ext-grid
3
+ * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
4
+ * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
+ */
6
+ import { Wunderbaum } from "./wunderbaum";
7
+ import { WunderbaumExtension } from "./wb_extension_base";
8
+ import { DragCallbackArgType, DragObserver } from "./drag_observer";
9
+
10
+ export class GridExtension extends WunderbaumExtension {
11
+ protected observer: DragObserver;
12
+
13
+ constructor(tree: Wunderbaum) {
14
+ super(tree, "grid", {
15
+ // throttle: 200,
16
+ });
17
+
18
+ this.observer = new DragObserver({
19
+ root: window.document,
20
+ selector: "span.wb-col-resizer",
21
+ thresh: 4,
22
+ // throttle: 400,
23
+ dragstart: (e) => {
24
+ return this.tree.element.contains(e.dragElem);
25
+ },
26
+ drag: (e) => {
27
+ // TODO: throttle
28
+ return this.handleDrag(e);
29
+ },
30
+ dragstop: (e) => {
31
+ return this.handleDrag(e);
32
+ },
33
+ });
34
+ }
35
+
36
+ init() {
37
+ super.init();
38
+ }
39
+
40
+ protected handleDrag(e: DragCallbackArgType): void {
41
+ const info = Wunderbaum.getEventInfo(e.event);
42
+ // this.tree.options.
43
+ this.tree.log(`${e.type}(${e.dx})`, e, info);
44
+ }
45
+ }