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.
- package/README.md +3 -2
- package/dist/wunderbaum.css +1 -1
- package/dist/wunderbaum.d.ts +400 -80
- package/dist/wunderbaum.esm.js +356 -135
- package/dist/wunderbaum.esm.min.js +28 -18
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +358 -137
- package/dist/wunderbaum.umd.min.js +34 -24
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +29 -30
- package/src/common.ts +6 -5
- package/src/drag_observer.ts +169 -0
- package/src/util.ts +47 -13
- package/src/wb_ext_dnd.ts +144 -3
- package/src/wb_ext_filter.ts +35 -35
- package/src/wb_ext_grid.ts +45 -0
- package/src/wb_node.ts +23 -29
- package/src/wb_options.ts +138 -25
- package/src/wunderbaum.scss +20 -1
- package/src/wunderbaum.ts +82 -37
package/dist/wunderbaum.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - util
|
|
3
3
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
4
|
-
* v0.0.
|
|
4
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
/** Readable names for `MouseEvent.button` */
|
|
7
7
|
const MOUSE_BUTTONS = {
|
|
@@ -14,7 +14,7 @@ const MOUSE_BUTTONS = {
|
|
|
14
14
|
};
|
|
15
15
|
const MAX_INT = 9007199254740991;
|
|
16
16
|
const userInfo = _getUserInfo();
|
|
17
|
-
/**True if the
|
|
17
|
+
/**True if the client is using a macOS platform. */
|
|
18
18
|
const isMac = userInfo.isMac;
|
|
19
19
|
const REX_HTML = /[&<>"'/]/g; // Escape those characters
|
|
20
20
|
const REX_TOOLTIP = /[<>"'/]/g; // Don't escape `&` in tooltips
|
|
@@ -162,7 +162,7 @@ function escapeTooltip(s) {
|
|
|
162
162
|
/** TODO */
|
|
163
163
|
function extractHtmlText(s) {
|
|
164
164
|
if (s.indexOf(">") >= 0) {
|
|
165
|
-
error("
|
|
165
|
+
error("Not implemented");
|
|
166
166
|
// return $("<div/>").html(s).text();
|
|
167
167
|
}
|
|
168
168
|
return s;
|
|
@@ -284,7 +284,7 @@ function setValueToElem(elem, value) {
|
|
|
284
284
|
input.valueAsNumber = value;
|
|
285
285
|
break;
|
|
286
286
|
case "radio":
|
|
287
|
-
|
|
287
|
+
error("Not implemented");
|
|
288
288
|
// const name = input.name;
|
|
289
289
|
// const checked = input.parentElement!.querySelector(
|
|
290
290
|
// `input[name="${name}"]:checked`
|
|
@@ -307,7 +307,7 @@ function setValueToElem(elem, value) {
|
|
|
307
307
|
}
|
|
308
308
|
// return value;
|
|
309
309
|
}
|
|
310
|
-
/**
|
|
310
|
+
/** Create and return an unconnected `HTMLElement` from a HTML string. */
|
|
311
311
|
function elemFromHtml(html) {
|
|
312
312
|
const t = document.createElement("template");
|
|
313
313
|
t.innerHTML = html.trim();
|
|
@@ -324,11 +324,23 @@ function elemFromSelector(obj) {
|
|
|
324
324
|
}
|
|
325
325
|
return obj;
|
|
326
326
|
}
|
|
327
|
+
/** Return a EventTarget from selector or cast an existing element. */
|
|
328
|
+
function eventTargetFromSelector(obj) {
|
|
329
|
+
if (!obj) {
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
if (typeof obj === "string") {
|
|
333
|
+
return document.querySelector(obj);
|
|
334
|
+
}
|
|
335
|
+
return obj;
|
|
336
|
+
}
|
|
327
337
|
/**
|
|
328
|
-
* Return a descriptive string for a keyboard or mouse event.
|
|
338
|
+
* Return a canonical descriptive string for a keyboard or mouse event.
|
|
329
339
|
*
|
|
330
340
|
* The result also contains a prefix for modifiers if any, for example
|
|
331
341
|
* `"x"`, `"F2"`, `"Control+Home"`, or `"Shift+clickright"`.
|
|
342
|
+
* This is especially useful in `switch` statements, to make sure that modifier
|
|
343
|
+
* keys are considered and handled correctly.
|
|
332
344
|
*/
|
|
333
345
|
function eventToString(event) {
|
|
334
346
|
let key = event.key, et = event.type, s = [];
|
|
@@ -360,6 +372,13 @@ function eventToString(event) {
|
|
|
360
372
|
}
|
|
361
373
|
return s.join("+");
|
|
362
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Copy allproperties from one or more source objects to a target object.
|
|
377
|
+
*
|
|
378
|
+
* @returns the modified target object.
|
|
379
|
+
*/
|
|
380
|
+
// TODO: use Object.assign()? --> https://stackoverflow.com/a/42740894
|
|
381
|
+
// TODO: support deep merge --> https://stackoverflow.com/a/42740894
|
|
363
382
|
function extend(...args) {
|
|
364
383
|
for (let i = 1; i < args.length; i++) {
|
|
365
384
|
let arg = args[i];
|
|
@@ -374,23 +393,27 @@ function extend(...args) {
|
|
|
374
393
|
}
|
|
375
394
|
return args[0];
|
|
376
395
|
}
|
|
396
|
+
/** Return true if `obj` is of type `array`. */
|
|
377
397
|
function isArray(obj) {
|
|
378
398
|
return Array.isArray(obj);
|
|
379
399
|
}
|
|
400
|
+
/** Return true if `obj` is of type `Object` and has no propertied. */
|
|
380
401
|
function isEmptyObject(obj) {
|
|
381
402
|
return Object.keys(obj).length === 0 && obj.constructor === Object;
|
|
382
403
|
}
|
|
404
|
+
/** Return true if `obj` is of type `function`. */
|
|
383
405
|
function isFunction(obj) {
|
|
384
406
|
return typeof obj === "function";
|
|
385
407
|
}
|
|
408
|
+
/** Return true if `obj` is of type `Object`. */
|
|
386
409
|
function isPlainObject(obj) {
|
|
387
410
|
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
388
411
|
}
|
|
389
412
|
/** A dummy function that does nothing ('no operation'). */
|
|
390
413
|
function noop(...args) { }
|
|
391
|
-
function onEvent(
|
|
414
|
+
function onEvent(rootTarget, eventNames, selectorOrHandler, handlerOrNone) {
|
|
392
415
|
let selector, handler;
|
|
393
|
-
|
|
416
|
+
rootTarget = eventTargetFromSelector(rootTarget);
|
|
394
417
|
if (handlerOrNone) {
|
|
395
418
|
selector = selectorOrHandler;
|
|
396
419
|
handler = handlerOrNone;
|
|
@@ -400,7 +423,7 @@ function onEvent(rootElem, eventNames, selectorOrHandler, handlerOrNone) {
|
|
|
400
423
|
handler = selectorOrHandler;
|
|
401
424
|
}
|
|
402
425
|
eventNames.split(" ").forEach((evn) => {
|
|
403
|
-
|
|
426
|
+
rootTarget.addEventListener(evn, function (e) {
|
|
404
427
|
if (!selector) {
|
|
405
428
|
return handler(e); // no event delegation
|
|
406
429
|
}
|
|
@@ -478,6 +501,13 @@ async function sleep(ms) {
|
|
|
478
501
|
}
|
|
479
502
|
/**
|
|
480
503
|
* Set or rotate checkbox status with support for tri-state.
|
|
504
|
+
*
|
|
505
|
+
* An initial 'indeterminate' state becomes 'checked' on the first call.
|
|
506
|
+
*
|
|
507
|
+
* If the input element has the class 'wb-tristate' assigned, the sequence is:<br>
|
|
508
|
+
* 'indeterminate' -> 'checked' -> 'unchecked' -> 'indeterminate' -> ...<br>
|
|
509
|
+
* Otherwise we toggle like <br>
|
|
510
|
+
* 'checked' -> 'unchecked' -> 'checked' -> ...
|
|
481
511
|
*/
|
|
482
512
|
function toggleCheckbox(element, value, tristate) {
|
|
483
513
|
const input = elemFromSelector(element);
|
|
@@ -535,6 +565,7 @@ function toSet(val) {
|
|
|
535
565
|
}
|
|
536
566
|
throw new Error("Cannot convert to Set<string>: " + val);
|
|
537
567
|
}
|
|
568
|
+
/**Return a canonical string representation for an object's type (e.g. 'array', 'number', ...) */
|
|
538
569
|
function type(obj) {
|
|
539
570
|
return Object.prototype.toString
|
|
540
571
|
.call(obj)
|
|
@@ -561,6 +592,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
561
592
|
setValueToElem: setValueToElem,
|
|
562
593
|
elemFromHtml: elemFromHtml,
|
|
563
594
|
elemFromSelector: elemFromSelector,
|
|
595
|
+
eventTargetFromSelector: eventTargetFromSelector,
|
|
564
596
|
eventToString: eventToString,
|
|
565
597
|
extend: extend,
|
|
566
598
|
isArray: isArray,
|
|
@@ -581,7 +613,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
581
613
|
/*!
|
|
582
614
|
* Wunderbaum - common
|
|
583
615
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
584
|
-
* v0.0.
|
|
616
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
585
617
|
*/
|
|
586
618
|
const DEFAULT_DEBUGLEVEL = 4; // Replaced by rollup script
|
|
587
619
|
const ROW_HEIGHT = 22;
|
|
@@ -595,6 +627,8 @@ var ChangeType;
|
|
|
595
627
|
ChangeType["row"] = "row";
|
|
596
628
|
ChangeType["structure"] = "structure";
|
|
597
629
|
ChangeType["status"] = "status";
|
|
630
|
+
ChangeType["vscroll"] = "vscroll";
|
|
631
|
+
ChangeType["header"] = "header";
|
|
598
632
|
})(ChangeType || (ChangeType = {}));
|
|
599
633
|
var NodeStatusType;
|
|
600
634
|
(function (NodeStatusType) {
|
|
@@ -693,7 +727,7 @@ function makeNodeTitleStartMatcher(s) {
|
|
|
693
727
|
/*!
|
|
694
728
|
* Wunderbaum - wb_extension_base
|
|
695
729
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
696
|
-
* v0.0.
|
|
730
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
697
731
|
*/
|
|
698
732
|
class WunderbaumExtension {
|
|
699
733
|
constructor(tree, id, defaults) {
|
|
@@ -1048,7 +1082,7 @@ function throttle(func, wait = 0, options = {}) {
|
|
|
1048
1082
|
/*!
|
|
1049
1083
|
* Wunderbaum - ext-filter
|
|
1050
1084
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1051
|
-
* v0.0.
|
|
1085
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1052
1086
|
*/
|
|
1053
1087
|
const START_MARKER = "\uFFF7";
|
|
1054
1088
|
const END_MARKER = "\uFFF8";
|
|
@@ -1087,7 +1121,9 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1087
1121
|
});
|
|
1088
1122
|
}
|
|
1089
1123
|
_applyFilterImpl(filter, branchMode, _opts) {
|
|
1090
|
-
let match, temp, start = Date.now(), count = 0, tree = this.tree, treeOpts = tree.options,
|
|
1124
|
+
let match, temp, start = Date.now(), count = 0, tree = this.tree, treeOpts = tree.options,
|
|
1125
|
+
// escapeTitles = treeOpts.escapeTitles,
|
|
1126
|
+
prevAutoCollapse = treeOpts.autoCollapse, opts = extend({}, treeOpts.filter, _opts), hideMode = opts.mode === "hide", leavesOnly = !!opts.leavesOnly && !branchMode;
|
|
1091
1127
|
// Default to 'match title substring (case insensitive)'
|
|
1092
1128
|
if (typeof filter === "string") {
|
|
1093
1129
|
if (filter === "") {
|
|
@@ -1120,37 +1156,36 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1120
1156
|
if (!node.title) {
|
|
1121
1157
|
return false;
|
|
1122
1158
|
}
|
|
1123
|
-
let text = escapeTitles ? node.title : extractHtmlText(node.title);
|
|
1159
|
+
// let text = escapeTitles ? node.title : extractHtmlText(node.title);
|
|
1160
|
+
let text = node.title;
|
|
1124
1161
|
// `.match` instead of `.test` to get the capture groups
|
|
1125
1162
|
let res = text.match(re);
|
|
1126
1163
|
if (res && opts.highlight) {
|
|
1127
|
-
if (escapeTitles) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
}
|
|
1131
|
-
else {
|
|
1132
|
-
// #740: we must not apply the marks to escaped entity names, e.g. `"`
|
|
1133
|
-
// Use some exotic characters to mark matches:
|
|
1134
|
-
temp = text.replace(reHighlight, function (s) {
|
|
1135
|
-
return START_MARKER + s + END_MARKER;
|
|
1136
|
-
});
|
|
1137
|
-
}
|
|
1138
|
-
// now we can escape the title...
|
|
1139
|
-
node.titleWithHighlight = escapeHtml(temp)
|
|
1140
|
-
// ... and finally insert the desired `<mark>` tags
|
|
1141
|
-
.replace(RE_START_MARKER, "<mark>")
|
|
1142
|
-
.replace(RE_END_MARTKER, "</mark>");
|
|
1164
|
+
// if (escapeTitles) {
|
|
1165
|
+
if (opts.fuzzy) {
|
|
1166
|
+
temp = _markFuzzyMatchedChars(text, res, true);
|
|
1143
1167
|
}
|
|
1144
1168
|
else {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
return "<mark>" + s + "</mark>";
|
|
1151
|
-
});
|
|
1152
|
-
}
|
|
1169
|
+
// #740: we must not apply the marks to escaped entity names, e.g. `"`
|
|
1170
|
+
// Use some exotic characters to mark matches:
|
|
1171
|
+
temp = text.replace(reHighlight, function (s) {
|
|
1172
|
+
return START_MARKER + s + END_MARKER;
|
|
1173
|
+
});
|
|
1153
1174
|
}
|
|
1175
|
+
// now we can escape the title...
|
|
1176
|
+
node.titleWithHighlight = escapeHtml(temp)
|
|
1177
|
+
// ... and finally insert the desired `<mark>` tags
|
|
1178
|
+
.replace(RE_START_MARKER, "<mark>")
|
|
1179
|
+
.replace(RE_END_MARTKER, "</mark>");
|
|
1180
|
+
// } else {
|
|
1181
|
+
// if (opts.fuzzy) {
|
|
1182
|
+
// node.titleWithHighlight = _markFuzzyMatchedChars(text, res);
|
|
1183
|
+
// } else {
|
|
1184
|
+
// node.titleWithHighlight = text.replace(reHighlight, function (s) {
|
|
1185
|
+
// return "<mark>" + s + "</mark>";
|
|
1186
|
+
// });
|
|
1187
|
+
// }
|
|
1188
|
+
// }
|
|
1154
1189
|
// node.debug("filter", escapeTitles, text, node.titleWithHighlight);
|
|
1155
1190
|
}
|
|
1156
1191
|
return !!res;
|
|
@@ -1252,9 +1287,9 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1252
1287
|
* [ext-filter] Reset the filter.
|
|
1253
1288
|
*/
|
|
1254
1289
|
clearFilter() {
|
|
1255
|
-
let tree = this.tree
|
|
1290
|
+
let tree = this.tree;
|
|
1256
1291
|
// statusNode = tree.root.findDirectChild(KEY_NODATA),
|
|
1257
|
-
escapeTitles = tree.options.escapeTitles;
|
|
1292
|
+
// escapeTitles = tree.options.escapeTitles;
|
|
1258
1293
|
// enhanceTitle = tree.options.enhanceTitle,
|
|
1259
1294
|
tree.enableUpdate(false);
|
|
1260
1295
|
// if (statusNode) {
|
|
@@ -1268,12 +1303,11 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1268
1303
|
if (node.match && node._rowElem) {
|
|
1269
1304
|
// #491, #601
|
|
1270
1305
|
let titleElem = node._rowElem.querySelector("span.wb-title");
|
|
1271
|
-
if (escapeTitles) {
|
|
1272
|
-
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1306
|
+
// if (escapeTitles) {
|
|
1307
|
+
titleElem.textContent = node.title;
|
|
1308
|
+
// } else {
|
|
1309
|
+
// titleElem.innerHTML = node.title;
|
|
1310
|
+
// }
|
|
1277
1311
|
node._callEvent("enhanceTitle", { titleElem: titleElem });
|
|
1278
1312
|
}
|
|
1279
1313
|
delete node.match;
|
|
@@ -1309,7 +1343,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1309
1343
|
* @param {string} text
|
|
1310
1344
|
* @param {RegExpMatchArray} matches
|
|
1311
1345
|
*/
|
|
1312
|
-
function _markFuzzyMatchedChars(text, matches, escapeTitles =
|
|
1346
|
+
function _markFuzzyMatchedChars(text, matches, escapeTitles = true) {
|
|
1313
1347
|
let matchingIndices = [];
|
|
1314
1348
|
// get the indices of matched characters (Iterate through `RegExpMatchArray`)
|
|
1315
1349
|
for (let _matchingArrIdx = 1; _matchingArrIdx < matches.length; _matchingArrIdx++) {
|
|
@@ -1324,7 +1358,7 @@ function _markFuzzyMatchedChars(text, matches, escapeTitles = false) {
|
|
|
1324
1358
|
// Map each `text` char to its position and store in `textPoses`.
|
|
1325
1359
|
let textPoses = text.split("");
|
|
1326
1360
|
if (escapeTitles) {
|
|
1327
|
-
// If escaping the title, then wrap the
|
|
1361
|
+
// If escaping the title, then wrap the matching char within exotic chars
|
|
1328
1362
|
matchingIndices.forEach(function (v) {
|
|
1329
1363
|
textPoses[v] = START_MARKER + textPoses[v] + END_MARKER;
|
|
1330
1364
|
});
|
|
@@ -1342,7 +1376,7 @@ function _markFuzzyMatchedChars(text, matches, escapeTitles = false) {
|
|
|
1342
1376
|
/*!
|
|
1343
1377
|
* Wunderbaum - ext-keynav
|
|
1344
1378
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1345
|
-
* v0.0.
|
|
1379
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1346
1380
|
*/
|
|
1347
1381
|
class KeynavExtension extends WunderbaumExtension {
|
|
1348
1382
|
constructor(tree) {
|
|
@@ -1528,7 +1562,7 @@ class KeynavExtension extends WunderbaumExtension {
|
|
|
1528
1562
|
/*!
|
|
1529
1563
|
* Wunderbaum - ext-logger
|
|
1530
1564
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1531
|
-
* v0.0.
|
|
1565
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1532
1566
|
*/
|
|
1533
1567
|
class LoggerExtension extends WunderbaumExtension {
|
|
1534
1568
|
constructor(tree) {
|
|
@@ -1568,19 +1602,9 @@ class LoggerExtension extends WunderbaumExtension {
|
|
|
1568
1602
|
/*!
|
|
1569
1603
|
* Wunderbaum - ext-dnd
|
|
1570
1604
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1571
|
-
* v0.0.
|
|
1605
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1572
1606
|
*/
|
|
1573
1607
|
const nodeMimeType = "application/x-wunderbaum-node";
|
|
1574
|
-
// type AllowedDropRegionType =
|
|
1575
|
-
// | "after"
|
|
1576
|
-
// | "afterBefore"
|
|
1577
|
-
// // | "afterBeforeOver" // == all == true
|
|
1578
|
-
// | "afterOver"
|
|
1579
|
-
// | "all" // == true
|
|
1580
|
-
// | "before"
|
|
1581
|
-
// | "beforeOver"
|
|
1582
|
-
// | "none" // == false == "" == null
|
|
1583
|
-
// | "over"; // == "child"
|
|
1584
1608
|
class DndExtension extends WunderbaumExtension {
|
|
1585
1609
|
constructor(tree) {
|
|
1586
1610
|
super(tree, "dnd", {
|
|
@@ -1843,10 +1867,181 @@ class DndExtension extends WunderbaumExtension {
|
|
|
1843
1867
|
}
|
|
1844
1868
|
}
|
|
1845
1869
|
|
|
1870
|
+
/*!
|
|
1871
|
+
* Wunderbaum - drag_observer
|
|
1872
|
+
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1873
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1874
|
+
*/
|
|
1875
|
+
/**
|
|
1876
|
+
* Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
|
|
1877
|
+
*/
|
|
1878
|
+
class DragObserver {
|
|
1879
|
+
constructor(opts) {
|
|
1880
|
+
this.start = {
|
|
1881
|
+
x: 0,
|
|
1882
|
+
y: 0,
|
|
1883
|
+
altKey: false,
|
|
1884
|
+
ctrlKey: false,
|
|
1885
|
+
metaKey: false,
|
|
1886
|
+
shiftKey: false,
|
|
1887
|
+
};
|
|
1888
|
+
this.dragElem = null;
|
|
1889
|
+
this.dragging = false;
|
|
1890
|
+
// TODO: touch events
|
|
1891
|
+
this.events = ["mousedown", "mouseup", "mousemove", "keydown"];
|
|
1892
|
+
assert(opts.root);
|
|
1893
|
+
this.opts = extend({ thresh: 5 }, opts);
|
|
1894
|
+
this.root = opts.root;
|
|
1895
|
+
this._handler = this.handleEvent.bind(this);
|
|
1896
|
+
this.events.forEach((type) => {
|
|
1897
|
+
this.root.addEventListener(type, this._handler);
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
/** Unregister all event listeners. */
|
|
1901
|
+
disconnect() {
|
|
1902
|
+
this.events.forEach((type) => {
|
|
1903
|
+
this.root.removeEventListener(type, this._handler);
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
getDragElem() {
|
|
1907
|
+
return this.dragElem;
|
|
1908
|
+
}
|
|
1909
|
+
isDragging() {
|
|
1910
|
+
return this.dragging;
|
|
1911
|
+
}
|
|
1912
|
+
stopDrag(cb_event) {
|
|
1913
|
+
if (this.dragging && this.opts.dragstop && cb_event) {
|
|
1914
|
+
cb_event.type = "dragstop";
|
|
1915
|
+
this.opts.dragstop(cb_event);
|
|
1916
|
+
}
|
|
1917
|
+
this.dragElem = null;
|
|
1918
|
+
this.dragging = false;
|
|
1919
|
+
}
|
|
1920
|
+
handleEvent(e) {
|
|
1921
|
+
const type = e.type;
|
|
1922
|
+
const opts = this.opts;
|
|
1923
|
+
const cb_event = {
|
|
1924
|
+
type: e.type,
|
|
1925
|
+
event: e,
|
|
1926
|
+
dragElem: this.dragElem,
|
|
1927
|
+
dx: e.pageX - this.start.x,
|
|
1928
|
+
dy: e.pageY - this.start.y,
|
|
1929
|
+
apply: undefined,
|
|
1930
|
+
};
|
|
1931
|
+
switch (type) {
|
|
1932
|
+
case "keydown":
|
|
1933
|
+
this.stopDrag(cb_event);
|
|
1934
|
+
break;
|
|
1935
|
+
case "mousedown":
|
|
1936
|
+
if (this.dragElem) {
|
|
1937
|
+
this.stopDrag(cb_event);
|
|
1938
|
+
break;
|
|
1939
|
+
}
|
|
1940
|
+
if (opts.selector) {
|
|
1941
|
+
let elem = e.target;
|
|
1942
|
+
if (elem.matches(opts.selector)) {
|
|
1943
|
+
this.dragElem = elem;
|
|
1944
|
+
}
|
|
1945
|
+
else {
|
|
1946
|
+
elem = elem.closest(opts.selector);
|
|
1947
|
+
if (elem) {
|
|
1948
|
+
this.dragElem = elem;
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
break; // no event delegation selector matched
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
this.start.x = e.pageX;
|
|
1956
|
+
this.start.y = e.pageY;
|
|
1957
|
+
this.start.altKey = e.altKey;
|
|
1958
|
+
this.start.ctrlKey = e.ctrlKey;
|
|
1959
|
+
this.start.metaKey = e.metaKey;
|
|
1960
|
+
this.start.shiftKey = e.shiftKey;
|
|
1961
|
+
break;
|
|
1962
|
+
case "mousemove":
|
|
1963
|
+
// TODO: debounce/throttle?
|
|
1964
|
+
// TODO: horizontal mode: ignore if dx unchanged
|
|
1965
|
+
if (!this.dragElem) {
|
|
1966
|
+
break;
|
|
1967
|
+
}
|
|
1968
|
+
if (!this.dragging) {
|
|
1969
|
+
if (opts.thresh) {
|
|
1970
|
+
const dist2 = cb_event.dx * cb_event.dx + cb_event.dy * cb_event.dy;
|
|
1971
|
+
if (dist2 < opts.thresh * opts.thresh) {
|
|
1972
|
+
break;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
cb_event.type = "dragstart";
|
|
1976
|
+
if (opts.dragstart(cb_event) === false) {
|
|
1977
|
+
this.stopDrag(cb_event);
|
|
1978
|
+
break;
|
|
1979
|
+
}
|
|
1980
|
+
this.dragging = true;
|
|
1981
|
+
}
|
|
1982
|
+
if (this.dragging && this.opts.drag) {
|
|
1983
|
+
cb_event.type = "drag";
|
|
1984
|
+
this.opts.drag(cb_event);
|
|
1985
|
+
}
|
|
1986
|
+
break;
|
|
1987
|
+
case "mouseup":
|
|
1988
|
+
if (!this.dragging) {
|
|
1989
|
+
this.stopDrag(cb_event);
|
|
1990
|
+
break;
|
|
1991
|
+
}
|
|
1992
|
+
if (e.button === 0) {
|
|
1993
|
+
cb_event.apply = true;
|
|
1994
|
+
}
|
|
1995
|
+
else {
|
|
1996
|
+
cb_event.apply = false;
|
|
1997
|
+
}
|
|
1998
|
+
this.stopDrag(cb_event);
|
|
1999
|
+
break;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
/*!
|
|
2005
|
+
* Wunderbaum - ext-grid
|
|
2006
|
+
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
2007
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
2008
|
+
*/
|
|
2009
|
+
class GridExtension extends WunderbaumExtension {
|
|
2010
|
+
constructor(tree) {
|
|
2011
|
+
super(tree, "grid", {
|
|
2012
|
+
// throttle: 200,
|
|
2013
|
+
});
|
|
2014
|
+
this.observer = new DragObserver({
|
|
2015
|
+
root: window.document,
|
|
2016
|
+
selector: "span.wb-col-resizer",
|
|
2017
|
+
thresh: 4,
|
|
2018
|
+
// throttle: 400,
|
|
2019
|
+
dragstart: (e) => {
|
|
2020
|
+
return this.tree.element.contains(e.dragElem);
|
|
2021
|
+
},
|
|
2022
|
+
drag: (e) => {
|
|
2023
|
+
// TODO: throttle
|
|
2024
|
+
return this.handleDrag(e);
|
|
2025
|
+
},
|
|
2026
|
+
dragstop: (e) => {
|
|
2027
|
+
return this.handleDrag(e);
|
|
2028
|
+
},
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
init() {
|
|
2032
|
+
super.init();
|
|
2033
|
+
}
|
|
2034
|
+
handleDrag(e) {
|
|
2035
|
+
const info = Wunderbaum.getEventInfo(e.event);
|
|
2036
|
+
// this.tree.options.
|
|
2037
|
+
this.tree.log(`${e.type}(${e.dx})`, e, info);
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
|
|
1846
2041
|
/*!
|
|
1847
2042
|
* Wunderbaum - deferred
|
|
1848
2043
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1849
|
-
* v0.0.
|
|
2044
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1850
2045
|
*/
|
|
1851
2046
|
/**
|
|
1852
2047
|
* Deferred is a ES6 Promise, that exposes the resolve() and reject()` method.
|
|
@@ -1889,7 +2084,7 @@ class Deferred {
|
|
|
1889
2084
|
/*!
|
|
1890
2085
|
* Wunderbaum - wunderbaum_node
|
|
1891
2086
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1892
|
-
* v0.0.
|
|
2087
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
1893
2088
|
*/
|
|
1894
2089
|
/** Top-level properties that can be passed with `data`. */
|
|
1895
2090
|
const NODE_PROPS = new Set([
|
|
@@ -2061,7 +2256,7 @@ class WunderbaumNode {
|
|
|
2061
2256
|
// this.fixSelection3FromEndNodes();
|
|
2062
2257
|
// }
|
|
2063
2258
|
// this.triggerModifyChild("add", nodeList.length === 1 ? nodeList[0] : null);
|
|
2064
|
-
this.tree.setModified(ChangeType.structure
|
|
2259
|
+
this.tree.setModified(ChangeType.structure);
|
|
2065
2260
|
return nodeList[0];
|
|
2066
2261
|
}
|
|
2067
2262
|
finally {
|
|
@@ -2535,7 +2730,7 @@ class WunderbaumNode {
|
|
|
2535
2730
|
await this.load(source); // also calls setStatus('ok')
|
|
2536
2731
|
if (wasExpanded) {
|
|
2537
2732
|
this.expanded = true;
|
|
2538
|
-
this.tree.
|
|
2733
|
+
this.tree.setModified(ChangeType.structure);
|
|
2539
2734
|
}
|
|
2540
2735
|
else {
|
|
2541
2736
|
this.render(); // Fix expander icon to 'loaded'
|
|
@@ -2691,7 +2886,7 @@ class WunderbaumNode {
|
|
|
2691
2886
|
n.tree = targetNode.tree;
|
|
2692
2887
|
}, true);
|
|
2693
2888
|
}
|
|
2694
|
-
tree.
|
|
2889
|
+
tree.setModified(ChangeType.structure);
|
|
2695
2890
|
// TODO: fix selection state
|
|
2696
2891
|
// TODO: fix active state
|
|
2697
2892
|
}
|
|
@@ -2767,7 +2962,7 @@ class WunderbaumNode {
|
|
|
2767
2962
|
if (!this.isRootNode()) {
|
|
2768
2963
|
this.expanded = false;
|
|
2769
2964
|
}
|
|
2770
|
-
this.tree.
|
|
2965
|
+
this.tree.setModified(ChangeType.structure);
|
|
2771
2966
|
}
|
|
2772
2967
|
/** Remove all HTML markup from the DOM. */
|
|
2773
2968
|
removeMarkup() {
|
|
@@ -2911,7 +3106,7 @@ class WunderbaumNode {
|
|
|
2911
3106
|
nodeElem.appendChild(elem);
|
|
2912
3107
|
ofsTitlePx += ICON_WIDTH;
|
|
2913
3108
|
}
|
|
2914
|
-
if (level > treeOptions.minExpandLevel) {
|
|
3109
|
+
if (treeOptions.minExpandLevel && level > treeOptions.minExpandLevel) {
|
|
2915
3110
|
expanderSpan = document.createElement("i");
|
|
2916
3111
|
nodeElem.appendChild(expanderSpan);
|
|
2917
3112
|
ofsTitlePx += ICON_WIDTH;
|
|
@@ -3002,11 +3197,11 @@ class WunderbaumNode {
|
|
|
3002
3197
|
if (this.titleWithHighlight) {
|
|
3003
3198
|
titleSpan.innerHTML = this.titleWithHighlight;
|
|
3004
3199
|
}
|
|
3005
|
-
else if (tree.options.escapeTitles) {
|
|
3006
|
-
titleSpan.textContent = this.title;
|
|
3007
|
-
}
|
|
3008
3200
|
else {
|
|
3009
|
-
|
|
3201
|
+
// } else if (tree.options.escapeTitles) {
|
|
3202
|
+
titleSpan.textContent = this.title;
|
|
3203
|
+
// } else {
|
|
3204
|
+
// titleSpan.innerHTML = this.title;
|
|
3010
3205
|
}
|
|
3011
3206
|
// Set the width of the title span, so overflow ellipsis work
|
|
3012
3207
|
if (!treeOptions.skeleton) {
|
|
@@ -3053,7 +3248,7 @@ class WunderbaumNode {
|
|
|
3053
3248
|
this.expanded = false;
|
|
3054
3249
|
this.lazy = true;
|
|
3055
3250
|
this.children = null;
|
|
3056
|
-
this.tree.
|
|
3251
|
+
this.tree.setModified(ChangeType.structure);
|
|
3057
3252
|
}
|
|
3058
3253
|
/** Convert node (or whole branch) into a plain object.
|
|
3059
3254
|
*
|
|
@@ -3181,7 +3376,7 @@ class WunderbaumNode {
|
|
|
3181
3376
|
orgEvent: orgEvent,
|
|
3182
3377
|
}) === false) {
|
|
3183
3378
|
tree.activeNode = null;
|
|
3184
|
-
prev === null || prev === void 0 ? void 0 : prev.
|
|
3379
|
+
prev === null || prev === void 0 ? void 0 : prev.setModified();
|
|
3185
3380
|
return;
|
|
3186
3381
|
}
|
|
3187
3382
|
}
|
|
@@ -3192,8 +3387,8 @@ class WunderbaumNode {
|
|
|
3192
3387
|
}
|
|
3193
3388
|
if (prev !== this) {
|
|
3194
3389
|
tree.activeNode = this;
|
|
3195
|
-
prev === null || prev === void 0 ? void 0 : prev.
|
|
3196
|
-
this.
|
|
3390
|
+
prev === null || prev === void 0 ? void 0 : prev.setModified();
|
|
3391
|
+
this.setModified();
|
|
3197
3392
|
}
|
|
3198
3393
|
if (options &&
|
|
3199
3394
|
options.colIdx != null &&
|
|
@@ -3206,17 +3401,9 @@ class WunderbaumNode {
|
|
|
3206
3401
|
// })
|
|
3207
3402
|
this.scrollIntoView();
|
|
3208
3403
|
}
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
}
|
|
3213
|
-
if (type === ChangeType.structure) {
|
|
3214
|
-
this.tree.updateViewport();
|
|
3215
|
-
}
|
|
3216
|
-
else if (this._rowElem) {
|
|
3217
|
-
// otherwise not in viewport, so no need to render
|
|
3218
|
-
this.render();
|
|
3219
|
-
}
|
|
3404
|
+
setModified(change = ChangeType.status) {
|
|
3405
|
+
assert(change === ChangeType.status);
|
|
3406
|
+
this.tree.setModified(ChangeType.row, this);
|
|
3220
3407
|
}
|
|
3221
3408
|
async setExpanded(flag = true, options) {
|
|
3222
3409
|
// alert("" + this.getLevel() + ", "+ this.getOption("minExpandLevel");
|
|
@@ -3231,7 +3418,7 @@ class WunderbaumNode {
|
|
|
3231
3418
|
await this.loadLazy();
|
|
3232
3419
|
}
|
|
3233
3420
|
this.expanded = flag;
|
|
3234
|
-
this.
|
|
3421
|
+
this.tree.setModified(ChangeType.structure);
|
|
3235
3422
|
}
|
|
3236
3423
|
setIcon() {
|
|
3237
3424
|
throw new Error("Not yet implemented");
|
|
@@ -3240,8 +3427,8 @@ class WunderbaumNode {
|
|
|
3240
3427
|
setFocus(flag = true, options) {
|
|
3241
3428
|
const prev = this.tree.focusNode;
|
|
3242
3429
|
this.tree.focusNode = this;
|
|
3243
|
-
prev === null || prev === void 0 ? void 0 : prev.
|
|
3244
|
-
this.
|
|
3430
|
+
prev === null || prev === void 0 ? void 0 : prev.setModified();
|
|
3431
|
+
this.setModified();
|
|
3245
3432
|
}
|
|
3246
3433
|
setSelected(flag = true, options) {
|
|
3247
3434
|
const prev = this.selected;
|
|
@@ -3249,7 +3436,7 @@ class WunderbaumNode {
|
|
|
3249
3436
|
this._callEvent("select", { flag: flag });
|
|
3250
3437
|
}
|
|
3251
3438
|
this.selected = !!flag;
|
|
3252
|
-
this.
|
|
3439
|
+
this.setModified();
|
|
3253
3440
|
}
|
|
3254
3441
|
/** Show node status (ok, loading, error, noData) using styles and a dummy child node.
|
|
3255
3442
|
*/
|
|
@@ -3325,12 +3512,12 @@ class WunderbaumNode {
|
|
|
3325
3512
|
default:
|
|
3326
3513
|
error("invalid node status " + status);
|
|
3327
3514
|
}
|
|
3328
|
-
tree.
|
|
3515
|
+
tree.setModified(ChangeType.structure);
|
|
3329
3516
|
return statusNode;
|
|
3330
3517
|
}
|
|
3331
3518
|
setTitle(title) {
|
|
3332
3519
|
this.title = title;
|
|
3333
|
-
this.
|
|
3520
|
+
this.setModified();
|
|
3334
3521
|
// this.triggerModify("rename"); // TODO
|
|
3335
3522
|
}
|
|
3336
3523
|
/**
|
|
@@ -3429,7 +3616,7 @@ WunderbaumNode.sequence = 0;
|
|
|
3429
3616
|
/*!
|
|
3430
3617
|
* Wunderbaum - ext-edit
|
|
3431
3618
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
3432
|
-
* v0.0.
|
|
3619
|
+
* v0.0.2, Tue, 12 Apr 2022 18:36:21 GMT (https://github.com/mar10/wunderbaum)
|
|
3433
3620
|
*/
|
|
3434
3621
|
// const START_MARKER = "\uFFF7";
|
|
3435
3622
|
class EditExtension extends WunderbaumExtension {
|
|
@@ -3714,12 +3901,12 @@ class EditExtension extends WunderbaumExtension {
|
|
|
3714
3901
|
* Copyright (c) 2021-2022, Martin Wendt (https://wwWendt.de).
|
|
3715
3902
|
* Released under the MIT license.
|
|
3716
3903
|
*
|
|
3717
|
-
* @version v0.0.
|
|
3718
|
-
* @date
|
|
3904
|
+
* @version v0.0.2
|
|
3905
|
+
* @date Tue, 12 Apr 2022 18:36:21 GMT
|
|
3719
3906
|
*/
|
|
3720
3907
|
// const class_prefix = "wb-";
|
|
3721
3908
|
// const node_props: string[] = ["title", "key", "refKey"];
|
|
3722
|
-
const MAX_CHANGED_NODES = 10;
|
|
3909
|
+
// const MAX_CHANGED_NODES = 10;
|
|
3723
3910
|
/**
|
|
3724
3911
|
* A persistent plain object or array.
|
|
3725
3912
|
*
|
|
@@ -3748,6 +3935,7 @@ class Wunderbaum {
|
|
|
3748
3935
|
this.changedSince = 0;
|
|
3749
3936
|
this.changes = new Set();
|
|
3750
3937
|
this.changedNodes = new Set();
|
|
3938
|
+
this.changeRedrawPending = false;
|
|
3751
3939
|
// --- FILTER ---
|
|
3752
3940
|
this.filterMode = null;
|
|
3753
3941
|
// --- KEYNAV ---
|
|
@@ -3771,7 +3959,7 @@ class Wunderbaum {
|
|
|
3771
3959
|
rowHeightPx: ROW_HEIGHT,
|
|
3772
3960
|
columns: null,
|
|
3773
3961
|
types: null,
|
|
3774
|
-
escapeTitles: true,
|
|
3962
|
+
// escapeTitles: true,
|
|
3775
3963
|
showSpinner: false,
|
|
3776
3964
|
checkbox: true,
|
|
3777
3965
|
minExpandLevel: 0,
|
|
@@ -3828,6 +4016,7 @@ class Wunderbaum {
|
|
|
3828
4016
|
this._registerExtension(new EditExtension(this));
|
|
3829
4017
|
this._registerExtension(new FilterExtension(this));
|
|
3830
4018
|
this._registerExtension(new DndExtension(this));
|
|
4019
|
+
this._registerExtension(new GridExtension(this));
|
|
3831
4020
|
this._registerExtension(new LoggerExtension(this));
|
|
3832
4021
|
// --- Evaluate options
|
|
3833
4022
|
this.columns = opts.columns;
|
|
@@ -3921,11 +4110,9 @@ class Wunderbaum {
|
|
|
3921
4110
|
var _a;
|
|
3922
4111
|
(_a = this.element.querySelector("progress.spinner")) === null || _a === void 0 ? void 0 : _a.remove();
|
|
3923
4112
|
this.element.classList.remove("wb-initializing");
|
|
3924
|
-
// this.updateViewport();
|
|
3925
4113
|
});
|
|
3926
4114
|
}
|
|
3927
4115
|
else {
|
|
3928
|
-
// this.updateViewport();
|
|
3929
4116
|
readyDeferred.resolve();
|
|
3930
4117
|
}
|
|
3931
4118
|
// TODO: This is sometimes required, because this.element.clientWidth
|
|
@@ -3935,13 +4122,10 @@ class Wunderbaum {
|
|
|
3935
4122
|
}, 50);
|
|
3936
4123
|
// --- Bind listeners
|
|
3937
4124
|
this.scrollContainer.addEventListener("scroll", (e) => {
|
|
3938
|
-
this.
|
|
4125
|
+
this.setModified(ChangeType.vscroll);
|
|
3939
4126
|
});
|
|
3940
|
-
// window.addEventListener("resize", (e: Event) => {
|
|
3941
|
-
// this.updateViewport();
|
|
3942
|
-
// });
|
|
3943
4127
|
this.resizeObserver = new ResizeObserver((entries) => {
|
|
3944
|
-
this.
|
|
4128
|
+
this.setModified(ChangeType.vscroll);
|
|
3945
4129
|
console.log("ResizeObserver: Size changed", entries);
|
|
3946
4130
|
});
|
|
3947
4131
|
this.resizeObserver.observe(this.element);
|
|
@@ -4391,7 +4575,7 @@ class Wunderbaum {
|
|
|
4391
4575
|
// public cellNavMode = false;
|
|
4392
4576
|
// public lastQuicksearchTime = 0;
|
|
4393
4577
|
// public lastQuicksearchTerm = "";
|
|
4394
|
-
this.
|
|
4578
|
+
this.setModified(ChangeType.structure);
|
|
4395
4579
|
}
|
|
4396
4580
|
/**
|
|
4397
4581
|
* Clear nodes and markup and detach events and observers.
|
|
@@ -4678,7 +4862,8 @@ class Wunderbaum {
|
|
|
4678
4862
|
* TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
|
|
4679
4863
|
*/
|
|
4680
4864
|
static getEventInfo(event) {
|
|
4681
|
-
let target = event.target, cl = target.classList, parentCol = target.closest(".wb-col"), node = Wunderbaum.getNode(target), res = {
|
|
4865
|
+
let target = event.target, cl = target.classList, parentCol = target.closest("span.wb-col"), node = Wunderbaum.getNode(target), tree = node ? node.tree : Wunderbaum.getTree(event), res = {
|
|
4866
|
+
tree: tree,
|
|
4682
4867
|
node: node,
|
|
4683
4868
|
region: TargetType.unknown,
|
|
4684
4869
|
colDef: undefined,
|
|
@@ -4710,13 +4895,15 @@ class Wunderbaum {
|
|
|
4710
4895
|
}
|
|
4711
4896
|
else {
|
|
4712
4897
|
// Somewhere near the title
|
|
4713
|
-
|
|
4898
|
+
if (event.type !== "mousemove") {
|
|
4899
|
+
console.warn("getEventInfo(): not found", event, res);
|
|
4900
|
+
}
|
|
4714
4901
|
return res;
|
|
4715
4902
|
}
|
|
4716
4903
|
if (res.colIdx === -1) {
|
|
4717
4904
|
res.colIdx = 0;
|
|
4718
4905
|
}
|
|
4719
|
-
res.colDef =
|
|
4906
|
+
res.colDef = tree === null || tree === void 0 ? void 0 : tree.columns[res.colIdx];
|
|
4720
4907
|
res.colDef != null ? (res.colId = res.colDef.id) : 0;
|
|
4721
4908
|
// this.log("Event", event, res);
|
|
4722
4909
|
return res;
|
|
@@ -4804,6 +4991,7 @@ class Wunderbaum {
|
|
|
4804
4991
|
let start = opts === null || opts === void 0 ? void 0 : opts.startIdx;
|
|
4805
4992
|
let end = opts === null || opts === void 0 ? void 0 : opts.endIdx;
|
|
4806
4993
|
const obsoleteViewNodes = this.viewNodes;
|
|
4994
|
+
const newNodesOnly = !!getOption(opts, "newNodesOnly");
|
|
4807
4995
|
this.viewNodes = new Set();
|
|
4808
4996
|
let viewNodes = this.viewNodes;
|
|
4809
4997
|
// this.debug("render", opts);
|
|
@@ -4825,9 +5013,10 @@ class Wunderbaum {
|
|
|
4825
5013
|
node._callEvent("discard");
|
|
4826
5014
|
node.removeMarkup();
|
|
4827
5015
|
}
|
|
4828
|
-
else {
|
|
4829
|
-
// if (!node._rowElem || prevIdx != idx) {
|
|
5016
|
+
else if (!node._rowElem || !newNodesOnly) {
|
|
4830
5017
|
node.render({ top: top });
|
|
5018
|
+
// }else{
|
|
5019
|
+
// node.log("ignrored render")
|
|
4831
5020
|
}
|
|
4832
5021
|
idx++;
|
|
4833
5022
|
top += height;
|
|
@@ -4851,20 +5040,23 @@ class Wunderbaum {
|
|
|
4851
5040
|
assert(headerRow);
|
|
4852
5041
|
headerRow.innerHTML = "<span class='wb-col'></span>".repeat(this.columns.length);
|
|
4853
5042
|
for (let i = 0; i < this.columns.length; i++) {
|
|
4854
|
-
|
|
4855
|
-
|
|
5043
|
+
const col = this.columns[i];
|
|
5044
|
+
const colElem = headerRow.children[i];
|
|
4856
5045
|
colElem.style.left = col._ofsPx + "px";
|
|
4857
5046
|
colElem.style.width = col._widthPx + "px";
|
|
4858
|
-
colElem.textContent = col.title || col.id;
|
|
5047
|
+
// colElem.textContent = col.title || col.id;
|
|
5048
|
+
const title = escapeHtml(col.title || col.id);
|
|
5049
|
+
colElem.innerHTML = `<span class="wb-col-title">${title}</span> <span class="wb-col-resizer"></span>`;
|
|
5050
|
+
// colElem.innerHTML = `${title} <span class="wb-col-resizer"></span>`;
|
|
4859
5051
|
}
|
|
4860
5052
|
}
|
|
4861
5053
|
/**
|
|
5054
|
+
* Make sure that this node is scrolled into the viewport.
|
|
4862
5055
|
*
|
|
4863
5056
|
* @param {boolean | PlainObject} [effects=false] animation options.
|
|
4864
5057
|
* @param {object} [options=null] {topNode: null, effects: ..., parent: ...}
|
|
4865
5058
|
* this node will remain visible in
|
|
4866
5059
|
* any case, even if `this` is outside the scroll pane.
|
|
4867
|
-
* Make sure that a node is scrolled into the viewport.
|
|
4868
5060
|
*/
|
|
4869
5061
|
scrollTo(opts) {
|
|
4870
5062
|
const MARGIN = 1;
|
|
@@ -4885,10 +5077,10 @@ class Wunderbaum {
|
|
|
4885
5077
|
// Node is above viewport
|
|
4886
5078
|
newTop = nodeOfs + MARGIN;
|
|
4887
5079
|
}
|
|
4888
|
-
this.log("scrollTo(" + nodeOfs + "): " + curTop + " => " + newTop, height);
|
|
4889
5080
|
if (newTop != null) {
|
|
5081
|
+
this.log("scrollTo(" + nodeOfs + "): " + curTop + " => " + newTop, height);
|
|
4890
5082
|
this.scrollContainer.scrollTop = newTop;
|
|
4891
|
-
this.
|
|
5083
|
+
this.setModified(ChangeType.vscroll);
|
|
4892
5084
|
}
|
|
4893
5085
|
}
|
|
4894
5086
|
/** */
|
|
@@ -4942,24 +5134,50 @@ class Wunderbaum {
|
|
|
4942
5134
|
this.element.blur();
|
|
4943
5135
|
}
|
|
4944
5136
|
}
|
|
4945
|
-
|
|
5137
|
+
/* */
|
|
4946
5138
|
setModified(change, node, options) {
|
|
4947
|
-
if (!
|
|
4948
|
-
|
|
5139
|
+
if (!(node instanceof WunderbaumNode)) {
|
|
5140
|
+
options = node;
|
|
4949
5141
|
}
|
|
4950
|
-
this.
|
|
4951
|
-
|
|
4952
|
-
this.changedNodes.clear();
|
|
5142
|
+
if (this._disableUpdate) {
|
|
5143
|
+
return;
|
|
4953
5144
|
}
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
this.
|
|
4960
|
-
this.
|
|
4961
|
-
|
|
5145
|
+
const immediate = !!getOption(options, "immediate");
|
|
5146
|
+
switch (change) {
|
|
5147
|
+
case ChangeType.any:
|
|
5148
|
+
case ChangeType.structure:
|
|
5149
|
+
case ChangeType.header:
|
|
5150
|
+
this.changeRedrawPending = true;
|
|
5151
|
+
this.updateViewport(immediate);
|
|
5152
|
+
break;
|
|
5153
|
+
case ChangeType.vscroll:
|
|
5154
|
+
this.updateViewport(immediate);
|
|
5155
|
+
break;
|
|
5156
|
+
case ChangeType.row:
|
|
5157
|
+
case ChangeType.status:
|
|
5158
|
+
// Single nodes are immedialtely updated if already inside the viewport
|
|
5159
|
+
// (otherwise we can ignore)
|
|
5160
|
+
if (node._rowElem) {
|
|
5161
|
+
node.render();
|
|
5162
|
+
}
|
|
5163
|
+
break;
|
|
5164
|
+
default:
|
|
5165
|
+
error(`Invalid change type ${change}`);
|
|
4962
5166
|
}
|
|
5167
|
+
// if (!this.changedSince) {
|
|
5168
|
+
// this.changedSince = Date.now();
|
|
5169
|
+
// }
|
|
5170
|
+
// this.changes.add(change);
|
|
5171
|
+
// if (change === ChangeType.structure) {
|
|
5172
|
+
// this.changedNodes.clear();
|
|
5173
|
+
// } else if (node && !this.changes.has(ChangeType.structure)) {
|
|
5174
|
+
// if (this.changedNodes.size < MAX_CHANGED_NODES) {
|
|
5175
|
+
// this.changedNodes.add(node);
|
|
5176
|
+
// } else {
|
|
5177
|
+
// this.changes.add(ChangeType.structure);
|
|
5178
|
+
// this.changedNodes.clear();
|
|
5179
|
+
// }
|
|
5180
|
+
// }
|
|
4963
5181
|
// this.log("setModified(" + change + ")", node);
|
|
4964
5182
|
}
|
|
4965
5183
|
setStatus(status, message, details) {
|
|
@@ -5036,13 +5254,15 @@ class Wunderbaum {
|
|
|
5036
5254
|
if (this._disableUpdate) {
|
|
5037
5255
|
return;
|
|
5038
5256
|
}
|
|
5257
|
+
const newNodesOnly = !this.changeRedrawPending;
|
|
5258
|
+
this.changeRedrawPending = false;
|
|
5039
5259
|
let height = this.scrollContainer.clientHeight;
|
|
5040
|
-
// We cannot get the height for
|
|
5260
|
+
// We cannot get the height for absolut positioned parent, so look at first col
|
|
5041
5261
|
// let headerHeight = this.headerElement.clientHeight
|
|
5042
5262
|
// let headerHeight = this.headerElement.children[0].children[0].clientHeight;
|
|
5043
5263
|
const headerHeight = this.options.headerHeightPx;
|
|
5044
|
-
|
|
5045
|
-
|
|
5264
|
+
const wantHeight = this.element.clientHeight - headerHeight;
|
|
5265
|
+
const ofs = this.scrollContainer.scrollTop;
|
|
5046
5266
|
if (Math.abs(height - wantHeight) > 1.0) {
|
|
5047
5267
|
// this.log("resize", height, wantHeight);
|
|
5048
5268
|
this.scrollContainer.style.height = wantHeight + "px";
|
|
@@ -5052,6 +5272,7 @@ class Wunderbaum {
|
|
|
5052
5272
|
this.render({
|
|
5053
5273
|
startIdx: Math.max(0, ofs / ROW_HEIGHT - RENDER_MAX_PREFETCH),
|
|
5054
5274
|
endIdx: Math.max(0, (ofs + height) / ROW_HEIGHT + RENDER_MAX_PREFETCH),
|
|
5275
|
+
newNodesOnly: newNodesOnly,
|
|
5055
5276
|
});
|
|
5056
5277
|
this._callEvent("update");
|
|
5057
5278
|
}
|
|
@@ -5254,7 +5475,7 @@ class Wunderbaum {
|
|
|
5254
5475
|
return this.extensions.filter.updateFilter();
|
|
5255
5476
|
}
|
|
5256
5477
|
}
|
|
5257
|
-
Wunderbaum.version = "v0.0.
|
|
5478
|
+
Wunderbaum.version = "v0.0.2"; // Set to semver by 'grunt release'
|
|
5258
5479
|
Wunderbaum.sequence = 0;
|
|
5259
5480
|
Wunderbaum.util = util;
|
|
5260
5481
|
|