wunderbaum 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/wunderbaum.css +1 -1
- package/dist/wunderbaum.d.ts +130 -34
- package/dist/wunderbaum.esm.js +359 -270
- package/dist/wunderbaum.esm.min.js +19 -19
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +359 -270
- package/dist/wunderbaum.umd.min.js +22 -23
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/common.ts +10 -2
- package/src/deferred.ts +12 -2
- package/src/util.ts +81 -3
- package/src/wb_extension_base.ts +3 -3
- package/src/wb_node.ts +239 -158
- package/src/wb_options.ts +52 -18
- package/src/wunderbaum.scss +86 -23
- package/src/wunderbaum.ts +42 -36
package/dist/wunderbaum.umd.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/*!
|
|
8
8
|
* Wunderbaum - util
|
|
9
9
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
10
|
-
* v0.0.
|
|
10
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
11
11
|
*/
|
|
12
12
|
/** @module util */
|
|
13
13
|
/** Readable names for `MouseEvent.button` */
|
|
@@ -305,14 +305,13 @@
|
|
|
305
305
|
break;
|
|
306
306
|
case "text":
|
|
307
307
|
default:
|
|
308
|
-
input.
|
|
308
|
+
input.value = value || "";
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
else if (tag === "SELECT") {
|
|
312
312
|
const select = elem;
|
|
313
313
|
select.value = value;
|
|
314
314
|
}
|
|
315
|
-
// return value;
|
|
316
315
|
}
|
|
317
316
|
/** Create and return an unconnected `HTMLElement` from a HTML string. */
|
|
318
317
|
function elemFromHtml(html) {
|
|
@@ -485,7 +484,7 @@
|
|
|
485
484
|
return new Promise((resolve, reject) => {
|
|
486
485
|
setTimeout(() => {
|
|
487
486
|
try {
|
|
488
|
-
resolve(callback.apply(
|
|
487
|
+
resolve(callback.apply(this));
|
|
489
488
|
}
|
|
490
489
|
catch (err) {
|
|
491
490
|
reject(err);
|
|
@@ -579,6 +578,72 @@
|
|
|
579
578
|
.replace(/^\[object (.+)\]$/, "$1")
|
|
580
579
|
.toLowerCase();
|
|
581
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Return a function that can be called instead of `callback`, but guarantees
|
|
583
|
+
* a limited execution rate.
|
|
584
|
+
* The execution rate is calculated based on the runtime duration of the
|
|
585
|
+
* previous call.
|
|
586
|
+
* Example:
|
|
587
|
+
* ```js
|
|
588
|
+
* throttledFoo = util.addaptiveThrottle(foo.bind(this), {});
|
|
589
|
+
* throttledFoo();
|
|
590
|
+
* throttledFoo();
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
function addaptiveThrottle(callback, options) {
|
|
594
|
+
let waiting = 0; // Initially, we're not waiting
|
|
595
|
+
let pendingArgs = null;
|
|
596
|
+
const opts = Object.assign({
|
|
597
|
+
minDelay: 16,
|
|
598
|
+
defaultDelay: 200,
|
|
599
|
+
maxDelay: 5000,
|
|
600
|
+
delayFactor: 2.0,
|
|
601
|
+
}, options);
|
|
602
|
+
const minDelay = Math.max(16, +opts.minDelay);
|
|
603
|
+
const maxDelay = +opts.maxDelay;
|
|
604
|
+
const throttledFn = (...args) => {
|
|
605
|
+
if (waiting) {
|
|
606
|
+
pendingArgs = args;
|
|
607
|
+
// console.log(`addaptiveThrottle() queing request #${waiting}...`, args);
|
|
608
|
+
waiting += 1;
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
// Prevent invocations while running or blocking
|
|
612
|
+
waiting = 1;
|
|
613
|
+
const useArgs = args; // pendingArgs || args;
|
|
614
|
+
pendingArgs = null;
|
|
615
|
+
// console.log(`addaptiveThrottle() execute...`, useArgs);
|
|
616
|
+
const start = Date.now();
|
|
617
|
+
try {
|
|
618
|
+
callback.apply(this, useArgs);
|
|
619
|
+
}
|
|
620
|
+
catch (error) {
|
|
621
|
+
console.error(error);
|
|
622
|
+
}
|
|
623
|
+
const elap = Date.now() - start;
|
|
624
|
+
const curDelay = Math.min(Math.max(minDelay, elap * opts.delayFactor), maxDelay);
|
|
625
|
+
const useDelay = Math.max(minDelay, curDelay - elap);
|
|
626
|
+
// console.log(
|
|
627
|
+
// `addaptiveThrottle() calling worker took ${elap}ms. delay = ${curDelay}ms, using ${useDelay}ms`,
|
|
628
|
+
// pendingArgs
|
|
629
|
+
// );
|
|
630
|
+
setTimeout(() => {
|
|
631
|
+
// Unblock, and trigger pending requests if any
|
|
632
|
+
// const skipped = waiting - 1;
|
|
633
|
+
waiting = 0; // And allow future invocations
|
|
634
|
+
if (pendingArgs != null) {
|
|
635
|
+
// There was another request while running or waiting
|
|
636
|
+
// console.log(
|
|
637
|
+
// `addaptiveThrottle() re-trigger (missed ${skipped})...`,
|
|
638
|
+
// pendingArgs
|
|
639
|
+
// );
|
|
640
|
+
throttledFn.apply(this, pendingArgs);
|
|
641
|
+
}
|
|
642
|
+
}, useDelay);
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
return throttledFn;
|
|
646
|
+
}
|
|
582
647
|
|
|
583
648
|
var util = /*#__PURE__*/Object.freeze({
|
|
584
649
|
__proto__: null,
|
|
@@ -614,13 +679,14 @@
|
|
|
614
679
|
toggleCheckbox: toggleCheckbox,
|
|
615
680
|
getOption: getOption,
|
|
616
681
|
toSet: toSet,
|
|
617
|
-
type: type
|
|
682
|
+
type: type,
|
|
683
|
+
addaptiveThrottle: addaptiveThrottle
|
|
618
684
|
});
|
|
619
685
|
|
|
620
686
|
/*!
|
|
621
687
|
* Wunderbaum - common
|
|
622
688
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
623
|
-
* v0.0.
|
|
689
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
624
690
|
*/
|
|
625
691
|
const DEFAULT_DEBUGLEVEL = 4; // Replaced by rollup script
|
|
626
692
|
const ROW_HEIGHT = 22;
|
|
@@ -630,12 +696,20 @@
|
|
|
630
696
|
const TEST_IMG = new RegExp(/\.|\//); // strings are considered image urls if they contain '.' or '/'
|
|
631
697
|
var ChangeType;
|
|
632
698
|
(function (ChangeType) {
|
|
699
|
+
/** Re-render the whole viewport, headers, and all rows. */
|
|
633
700
|
ChangeType["any"] = "any";
|
|
701
|
+
/** Update current row title, icon, columns, and status. */
|
|
702
|
+
ChangeType["data"] = "data";
|
|
703
|
+
/** Redraw the header and update the width of all row columns. */
|
|
704
|
+
ChangeType["header"] = "header";
|
|
705
|
+
/** Re-render the whole current row. */
|
|
634
706
|
ChangeType["row"] = "row";
|
|
707
|
+
/** Alias for 'any'. */
|
|
635
708
|
ChangeType["structure"] = "structure";
|
|
709
|
+
/** Update current row's classes, to reflect active, selected, ... */
|
|
636
710
|
ChangeType["status"] = "status";
|
|
711
|
+
/** Update the 'top' property of all rows. */
|
|
637
712
|
ChangeType["vscroll"] = "vscroll";
|
|
638
|
-
ChangeType["header"] = "header";
|
|
639
713
|
})(ChangeType || (ChangeType = {}));
|
|
640
714
|
var NodeStatusType;
|
|
641
715
|
(function (NodeStatusType) {
|
|
@@ -736,7 +810,7 @@
|
|
|
736
810
|
/*!
|
|
737
811
|
* Wunderbaum - wb_extension_base
|
|
738
812
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
739
|
-
* v0.0.
|
|
813
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
740
814
|
*/
|
|
741
815
|
class WunderbaumExtension {
|
|
742
816
|
constructor(tree, id, defaults) {
|
|
@@ -759,14 +833,14 @@
|
|
|
759
833
|
init() {
|
|
760
834
|
this.tree.element.classList.add("wb-ext-" + this.id);
|
|
761
835
|
}
|
|
762
|
-
// protected callEvent(
|
|
763
|
-
// let func = this.extensionOpts[
|
|
836
|
+
// protected callEvent(type: string, extra?: any): any {
|
|
837
|
+
// let func = this.extensionOpts[type];
|
|
764
838
|
// if (func) {
|
|
765
839
|
// return func.call(
|
|
766
840
|
// this.tree,
|
|
767
841
|
// util.extend(
|
|
768
842
|
// {
|
|
769
|
-
// event: this.id + "." +
|
|
843
|
+
// event: this.id + "." + type,
|
|
770
844
|
// },
|
|
771
845
|
// extra
|
|
772
846
|
// )
|
|
@@ -1023,75 +1097,11 @@
|
|
|
1023
1097
|
debounced.pending = pending;
|
|
1024
1098
|
return debounced;
|
|
1025
1099
|
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Creates a throttled function that only invokes `func` at most once per
|
|
1028
|
-
* every `wait` milliseconds (or once per browser frame). The throttled function
|
|
1029
|
-
* comes with a `cancel` method to cancel delayed `func` invocations and a
|
|
1030
|
-
* `flush` method to immediately invoke them. Provide `options` to indicate
|
|
1031
|
-
* whether `func` should be invoked on the leading and/or trailing edge of the
|
|
1032
|
-
* `wait` timeout. The `func` is invoked with the last arguments provided to the
|
|
1033
|
-
* throttled function. Subsequent calls to the throttled function return the
|
|
1034
|
-
* result of the last `func` invocation.
|
|
1035
|
-
*
|
|
1036
|
-
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
1037
|
-
* invoked on the trailing edge of the timeout only if the throttled function
|
|
1038
|
-
* is invoked more than once during the `wait` timeout.
|
|
1039
|
-
*
|
|
1040
|
-
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
1041
|
-
* until the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
1042
|
-
*
|
|
1043
|
-
* If `wait` is omitted in an environment with `requestAnimationFrame`, `func`
|
|
1044
|
-
* invocation will be deferred until the next frame is drawn (typically about
|
|
1045
|
-
* 16ms).
|
|
1046
|
-
*
|
|
1047
|
-
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
1048
|
-
* for details over the differences between `throttle` and `debounce`.
|
|
1049
|
-
*
|
|
1050
|
-
* @since 0.1.0
|
|
1051
|
-
* @category Function
|
|
1052
|
-
* @param {Function} func The function to throttle.
|
|
1053
|
-
* @param {number} [wait=0]
|
|
1054
|
-
* The number of milliseconds to throttle invocations to; if omitted,
|
|
1055
|
-
* `requestAnimationFrame` is used (if available).
|
|
1056
|
-
* @param {Object} [options={}] The options object.
|
|
1057
|
-
* @param {boolean} [options.leading=true]
|
|
1058
|
-
* Specify invoking on the leading edge of the timeout.
|
|
1059
|
-
* @param {boolean} [options.trailing=true]
|
|
1060
|
-
* Specify invoking on the trailing edge of the timeout.
|
|
1061
|
-
* @returns {Function} Returns the new throttled function.
|
|
1062
|
-
* @example
|
|
1063
|
-
*
|
|
1064
|
-
* // Avoid excessively updating the position while scrolling.
|
|
1065
|
-
* jQuery(window).on('scroll', throttle(updatePosition, 100))
|
|
1066
|
-
*
|
|
1067
|
-
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
|
|
1068
|
-
* const throttled = throttle(renewToken, 300000, { 'trailing': false })
|
|
1069
|
-
* jQuery(element).on('click', throttled)
|
|
1070
|
-
*
|
|
1071
|
-
* // Cancel the trailing throttled invocation.
|
|
1072
|
-
* jQuery(window).on('popstate', throttled.cancel)
|
|
1073
|
-
*/
|
|
1074
|
-
function throttle(func, wait = 0, options = {}) {
|
|
1075
|
-
let leading = true;
|
|
1076
|
-
let trailing = true;
|
|
1077
|
-
if (typeof func !== "function") {
|
|
1078
|
-
throw new TypeError("Expected a function");
|
|
1079
|
-
}
|
|
1080
|
-
if (isObject(options)) {
|
|
1081
|
-
leading = "leading" in options ? !!options.leading : leading;
|
|
1082
|
-
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
1083
|
-
}
|
|
1084
|
-
return debounce(func, wait, {
|
|
1085
|
-
leading,
|
|
1086
|
-
trailing,
|
|
1087
|
-
maxWait: wait,
|
|
1088
|
-
});
|
|
1089
|
-
}
|
|
1090
1100
|
|
|
1091
1101
|
/*!
|
|
1092
1102
|
* Wunderbaum - ext-filter
|
|
1093
1103
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1094
|
-
* v0.0.
|
|
1104
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1095
1105
|
*/
|
|
1096
1106
|
const START_MARKER = "\uFFF7";
|
|
1097
1107
|
const END_MARKER = "\uFFF8";
|
|
@@ -1385,7 +1395,7 @@
|
|
|
1385
1395
|
/*!
|
|
1386
1396
|
* Wunderbaum - ext-keynav
|
|
1387
1397
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1388
|
-
* v0.0.
|
|
1398
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1389
1399
|
*/
|
|
1390
1400
|
class KeynavExtension extends WunderbaumExtension {
|
|
1391
1401
|
constructor(tree) {
|
|
@@ -1575,7 +1585,7 @@
|
|
|
1575
1585
|
/*!
|
|
1576
1586
|
* Wunderbaum - ext-logger
|
|
1577
1587
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1578
|
-
* v0.0.
|
|
1588
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1579
1589
|
*/
|
|
1580
1590
|
class LoggerExtension extends WunderbaumExtension {
|
|
1581
1591
|
constructor(tree) {
|
|
@@ -1615,7 +1625,7 @@
|
|
|
1615
1625
|
/*!
|
|
1616
1626
|
* Wunderbaum - ext-dnd
|
|
1617
1627
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1618
|
-
* v0.0.
|
|
1628
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1619
1629
|
*/
|
|
1620
1630
|
const nodeMimeType = "application/x-wunderbaum-node";
|
|
1621
1631
|
class DndExtension extends WunderbaumExtension {
|
|
@@ -1883,7 +1893,7 @@
|
|
|
1883
1893
|
/*!
|
|
1884
1894
|
* Wunderbaum - drag_observer
|
|
1885
1895
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
1886
|
-
* v0.0.
|
|
1896
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1887
1897
|
*/
|
|
1888
1898
|
/**
|
|
1889
1899
|
* Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
|
|
@@ -2017,7 +2027,7 @@
|
|
|
2017
2027
|
/*!
|
|
2018
2028
|
* Wunderbaum - ext-grid
|
|
2019
2029
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
2020
|
-
* v0.0.
|
|
2030
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2021
2031
|
*/
|
|
2022
2032
|
class GridExtension extends WunderbaumExtension {
|
|
2023
2033
|
constructor(tree) {
|
|
@@ -2054,12 +2064,22 @@
|
|
|
2054
2064
|
/*!
|
|
2055
2065
|
* Wunderbaum - deferred
|
|
2056
2066
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
2057
|
-
* v0.0.
|
|
2067
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2058
2068
|
*/
|
|
2059
2069
|
/**
|
|
2060
|
-
*
|
|
2070
|
+
* Implement a ES6 Promise, that exposes a resolve() and reject() method.
|
|
2061
2071
|
*
|
|
2062
|
-
* Loosely mimics
|
|
2072
|
+
* Loosely mimics {@link https://api.jquery.com/category/deferred-object/ | jQuery.Deferred}.
|
|
2073
|
+
* Example:
|
|
2074
|
+
* ```js
|
|
2075
|
+
* function foo() {
|
|
2076
|
+
* let dfd = new Deferred(),
|
|
2077
|
+
* ...
|
|
2078
|
+
* dfd.resolve('foo')
|
|
2079
|
+
* ...
|
|
2080
|
+
* return dfd.promise();
|
|
2081
|
+
* }
|
|
2082
|
+
* ```
|
|
2063
2083
|
*/
|
|
2064
2084
|
class Deferred {
|
|
2065
2085
|
constructor() {
|
|
@@ -2097,7 +2117,7 @@
|
|
|
2097
2117
|
/*!
|
|
2098
2118
|
* Wunderbaum - wunderbaum_node
|
|
2099
2119
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
2100
|
-
* v0.0.
|
|
2120
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2101
2121
|
*/
|
|
2102
2122
|
/** Top-level properties that can be passed with `data`. */
|
|
2103
2123
|
const NODE_PROPS = new Set([
|
|
@@ -2231,8 +2251,8 @@
|
|
|
2231
2251
|
* node._callEvent("edit.beforeEdit", {foo: 42})
|
|
2232
2252
|
* ```
|
|
2233
2253
|
*/
|
|
2234
|
-
_callEvent(
|
|
2235
|
-
return this.tree._callEvent(
|
|
2254
|
+
_callEvent(type, extra) {
|
|
2255
|
+
return this.tree._callEvent(type, extend({
|
|
2236
2256
|
node: this,
|
|
2237
2257
|
typeInfo: this.type ? this.tree.types[this.type] : {},
|
|
2238
2258
|
}, extra));
|
|
@@ -3069,13 +3089,15 @@
|
|
|
3069
3089
|
// this.log("_createIcon: ", iconSpan);
|
|
3070
3090
|
return iconSpan;
|
|
3071
3091
|
}
|
|
3072
|
-
/**
|
|
3073
|
-
|
|
3092
|
+
/**
|
|
3093
|
+
* Create a whole new `<div class="wb-row">` element.
|
|
3094
|
+
* @see {@link Wunderbaumode.render}
|
|
3095
|
+
*/
|
|
3096
|
+
_render_markup(opts) {
|
|
3074
3097
|
const tree = this.tree;
|
|
3075
3098
|
const treeOptions = tree.options;
|
|
3076
3099
|
const checkbox = this.getOption("checkbox") !== false;
|
|
3077
3100
|
const columns = tree.columns;
|
|
3078
|
-
const typeInfo = this.type ? tree.types[this.type] : null;
|
|
3079
3101
|
const level = this.getLevel();
|
|
3080
3102
|
let elem;
|
|
3081
3103
|
let nodeElem;
|
|
@@ -3085,11 +3107,171 @@
|
|
|
3085
3107
|
let iconSpan;
|
|
3086
3108
|
let expanderSpan = null;
|
|
3087
3109
|
const activeColIdx = tree.navMode === NavigationMode.row ? null : tree.activeColIdx;
|
|
3088
|
-
// let colElems: HTMLElement[];
|
|
3089
3110
|
const isNew = !rowDiv;
|
|
3111
|
+
assert(isNew);
|
|
3090
3112
|
assert(!isNew || (opts && opts.after), "opts.after expected, unless updating");
|
|
3091
3113
|
assert(!this.isRootNode());
|
|
3092
|
-
|
|
3114
|
+
rowDiv = document.createElement("div");
|
|
3115
|
+
rowDiv.classList.add("wb-row");
|
|
3116
|
+
rowDiv.style.top = this._rowIdx * ROW_HEIGHT + "px";
|
|
3117
|
+
this._rowElem = rowDiv;
|
|
3118
|
+
// Attach a node reference to the DOM Element:
|
|
3119
|
+
rowDiv._wb_node = this;
|
|
3120
|
+
nodeElem = document.createElement("span");
|
|
3121
|
+
nodeElem.classList.add("wb-node", "wb-col");
|
|
3122
|
+
rowDiv.appendChild(nodeElem);
|
|
3123
|
+
let ofsTitlePx = 0;
|
|
3124
|
+
if (checkbox) {
|
|
3125
|
+
checkboxSpan = document.createElement("i");
|
|
3126
|
+
checkboxSpan.classList.add("wb-checkbox");
|
|
3127
|
+
nodeElem.appendChild(checkboxSpan);
|
|
3128
|
+
ofsTitlePx += ICON_WIDTH;
|
|
3129
|
+
}
|
|
3130
|
+
for (let i = level - 1; i > 0; i--) {
|
|
3131
|
+
elem = document.createElement("i");
|
|
3132
|
+
elem.classList.add("wb-indent");
|
|
3133
|
+
nodeElem.appendChild(elem);
|
|
3134
|
+
ofsTitlePx += ICON_WIDTH;
|
|
3135
|
+
}
|
|
3136
|
+
if (!treeOptions.minExpandLevel || level > treeOptions.minExpandLevel) {
|
|
3137
|
+
expanderSpan = document.createElement("i");
|
|
3138
|
+
expanderSpan.classList.add("wb-expander");
|
|
3139
|
+
nodeElem.appendChild(expanderSpan);
|
|
3140
|
+
ofsTitlePx += ICON_WIDTH;
|
|
3141
|
+
}
|
|
3142
|
+
iconSpan = this._createIcon(nodeElem);
|
|
3143
|
+
if (iconSpan) {
|
|
3144
|
+
ofsTitlePx += ICON_WIDTH;
|
|
3145
|
+
}
|
|
3146
|
+
titleSpan = document.createElement("span");
|
|
3147
|
+
titleSpan.classList.add("wb-title");
|
|
3148
|
+
nodeElem.appendChild(titleSpan);
|
|
3149
|
+
this._callEvent("enhanceTitle", { titleSpan: titleSpan });
|
|
3150
|
+
// Store the width of leading icons with the node, so we can calculate
|
|
3151
|
+
// the width of the embedded title span later
|
|
3152
|
+
nodeElem._ofsTitlePx = ofsTitlePx;
|
|
3153
|
+
// Support HTML5 drag-n-drop
|
|
3154
|
+
if (tree.options.dnd.dragStart) {
|
|
3155
|
+
nodeElem.draggable = true;
|
|
3156
|
+
}
|
|
3157
|
+
// Render columns
|
|
3158
|
+
if (!this.colspan && columns.length > 1) {
|
|
3159
|
+
let colIdx = 0;
|
|
3160
|
+
for (let col of columns) {
|
|
3161
|
+
colIdx++;
|
|
3162
|
+
let colElem;
|
|
3163
|
+
if (col.id === "*") {
|
|
3164
|
+
colElem = nodeElem;
|
|
3165
|
+
}
|
|
3166
|
+
else {
|
|
3167
|
+
colElem = document.createElement("span");
|
|
3168
|
+
colElem.classList.add("wb-col");
|
|
3169
|
+
rowDiv.appendChild(colElem);
|
|
3170
|
+
}
|
|
3171
|
+
if (colIdx === activeColIdx) {
|
|
3172
|
+
colElem.classList.add("wb-active");
|
|
3173
|
+
}
|
|
3174
|
+
// Add classes from `columns` definition to `<div.wb-col>` cells
|
|
3175
|
+
col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
|
|
3176
|
+
colElem.style.left = col._ofsPx + "px";
|
|
3177
|
+
colElem.style.width = col._widthPx + "px";
|
|
3178
|
+
if (isNew && col.html) {
|
|
3179
|
+
if (typeof col.html === "string") {
|
|
3180
|
+
colElem.innerHTML = col.html;
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
// Now go on and fill in data and update classes
|
|
3186
|
+
opts.isNew = true;
|
|
3187
|
+
this._render_data(opts);
|
|
3188
|
+
// Attach to DOM as late as possible
|
|
3189
|
+
const after = opts ? opts.after : "last";
|
|
3190
|
+
switch (after) {
|
|
3191
|
+
case "first":
|
|
3192
|
+
tree.nodeListElement.prepend(rowDiv);
|
|
3193
|
+
break;
|
|
3194
|
+
case "last":
|
|
3195
|
+
tree.nodeListElement.appendChild(rowDiv);
|
|
3196
|
+
break;
|
|
3197
|
+
default:
|
|
3198
|
+
opts.after.after(rowDiv);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* Render `node.title`, `.icon` into an existing row.
|
|
3203
|
+
*
|
|
3204
|
+
* @see {@link Wunderbaumode.render}
|
|
3205
|
+
*/
|
|
3206
|
+
_render_data(opts) {
|
|
3207
|
+
assert(this._rowElem);
|
|
3208
|
+
const tree = this.tree;
|
|
3209
|
+
const treeOptions = tree.options;
|
|
3210
|
+
const rowDiv = this._rowElem;
|
|
3211
|
+
const isNew = !!opts.isNew; // Called by _render_markup()?
|
|
3212
|
+
const columns = tree.columns;
|
|
3213
|
+
const typeInfo = this.type ? tree.types[this.type] : null;
|
|
3214
|
+
// Row markup already exists
|
|
3215
|
+
const nodeElem = rowDiv.querySelector("span.wb-node");
|
|
3216
|
+
const titleSpan = nodeElem.querySelector("span.wb-title");
|
|
3217
|
+
if (this.titleWithHighlight) {
|
|
3218
|
+
titleSpan.innerHTML = this.titleWithHighlight;
|
|
3219
|
+
}
|
|
3220
|
+
else {
|
|
3221
|
+
titleSpan.textContent = this.title;
|
|
3222
|
+
}
|
|
3223
|
+
// Set the width of the title span, so overflow ellipsis work
|
|
3224
|
+
if (!treeOptions.skeleton) {
|
|
3225
|
+
if (this.colspan) {
|
|
3226
|
+
let vpWidth = tree.element.clientWidth;
|
|
3227
|
+
titleSpan.style.width =
|
|
3228
|
+
vpWidth - nodeElem._ofsTitlePx - ROW_EXTRA_PAD + "px";
|
|
3229
|
+
}
|
|
3230
|
+
else {
|
|
3231
|
+
titleSpan.style.width =
|
|
3232
|
+
columns[0]._widthPx -
|
|
3233
|
+
nodeElem._ofsTitlePx -
|
|
3234
|
+
ROW_EXTRA_PAD +
|
|
3235
|
+
"px";
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
// Update row classes
|
|
3239
|
+
opts.isDataChange = true;
|
|
3240
|
+
this._render_status(opts);
|
|
3241
|
+
// Let user modify the result
|
|
3242
|
+
if (this.statusNodeType) {
|
|
3243
|
+
this._callEvent("renderStatusNode", {
|
|
3244
|
+
isNew: isNew,
|
|
3245
|
+
nodeElem: nodeElem,
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
else if (this.parent) {
|
|
3249
|
+
// Skip root node
|
|
3250
|
+
this._callEvent("render", {
|
|
3251
|
+
isNew: isNew,
|
|
3252
|
+
isDataChange: true,
|
|
3253
|
+
nodeElem: nodeElem,
|
|
3254
|
+
typeInfo: typeInfo,
|
|
3255
|
+
colInfosById: this._getRenderInfo(),
|
|
3256
|
+
});
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* Update row classes to reflect active, focuses, etc.
|
|
3261
|
+
* @see {@link Wunderbaumode.render}
|
|
3262
|
+
*/
|
|
3263
|
+
_render_status(opts) {
|
|
3264
|
+
// this.log("_render_status", opts);
|
|
3265
|
+
const tree = this.tree;
|
|
3266
|
+
const treeOptions = tree.options;
|
|
3267
|
+
const typeInfo = this.type ? tree.types[this.type] : null;
|
|
3268
|
+
const rowDiv = this._rowElem;
|
|
3269
|
+
// Row markup already exists
|
|
3270
|
+
const nodeElem = rowDiv.querySelector("span.wb-node");
|
|
3271
|
+
const expanderSpan = nodeElem.querySelector("i.wb-expander");
|
|
3272
|
+
const checkboxSpan = nodeElem.querySelector("i.wb-checkbox");
|
|
3273
|
+
// TODO: update icon (if not opts.isNew)
|
|
3274
|
+
// const iconSpan = nodeElem.querySelector("i.wb-icon") as HTMLElement;
|
|
3093
3275
|
let rowClasses = ["wb-row"];
|
|
3094
3276
|
this.expanded ? rowClasses.push("wb-expanded") : 0;
|
|
3095
3277
|
this.lazy ? rowClasses.push("wb-lazy") : 0;
|
|
@@ -3104,102 +3286,14 @@
|
|
|
3104
3286
|
this.match ? rowClasses.push("wb-match") : 0;
|
|
3105
3287
|
this.subMatchCount ? rowClasses.push("wb-submatch") : 0;
|
|
3106
3288
|
treeOptions.skeleton ? rowClasses.push("wb-skeleton") : 0;
|
|
3107
|
-
//
|
|
3108
|
-
|
|
3109
|
-
if (rowDiv) {
|
|
3110
|
-
// Row markup already exists
|
|
3111
|
-
nodeElem = rowDiv.querySelector("span.wb-node");
|
|
3112
|
-
titleSpan = nodeElem.querySelector("span.wb-title");
|
|
3113
|
-
expanderSpan = nodeElem.querySelector("i.wb-expander");
|
|
3114
|
-
checkboxSpan = nodeElem.querySelector("i.wb-checkbox");
|
|
3115
|
-
iconSpan = nodeElem.querySelector("i.wb-icon");
|
|
3116
|
-
// TODO: we need this, when icons should be replacable
|
|
3117
|
-
// iconSpan = this._createIcon(nodeElem, iconSpan);
|
|
3118
|
-
// colElems = (<unknown>(
|
|
3119
|
-
// rowDiv.querySelectorAll("span.wb-col")
|
|
3120
|
-
// )) as HTMLElement[];
|
|
3121
|
-
}
|
|
3122
|
-
else {
|
|
3123
|
-
rowDiv = document.createElement("div");
|
|
3124
|
-
// rowDiv.classList.add("wb-row");
|
|
3125
|
-
// Attach a node reference to the DOM Element:
|
|
3126
|
-
rowDiv._wb_node = this;
|
|
3127
|
-
nodeElem = document.createElement("span");
|
|
3128
|
-
nodeElem.classList.add("wb-node", "wb-col");
|
|
3129
|
-
rowDiv.appendChild(nodeElem);
|
|
3130
|
-
let ofsTitlePx = 0;
|
|
3131
|
-
if (checkbox) {
|
|
3132
|
-
checkboxSpan = document.createElement("i");
|
|
3133
|
-
nodeElem.appendChild(checkboxSpan);
|
|
3134
|
-
ofsTitlePx += ICON_WIDTH;
|
|
3135
|
-
}
|
|
3136
|
-
for (let i = level - 1; i > 0; i--) {
|
|
3137
|
-
elem = document.createElement("i");
|
|
3138
|
-
elem.classList.add("wb-indent");
|
|
3139
|
-
nodeElem.appendChild(elem);
|
|
3140
|
-
ofsTitlePx += ICON_WIDTH;
|
|
3141
|
-
}
|
|
3142
|
-
if (!treeOptions.minExpandLevel || level > treeOptions.minExpandLevel) {
|
|
3143
|
-
expanderSpan = document.createElement("i");
|
|
3144
|
-
nodeElem.appendChild(expanderSpan);
|
|
3145
|
-
ofsTitlePx += ICON_WIDTH;
|
|
3146
|
-
}
|
|
3147
|
-
iconSpan = this._createIcon(nodeElem);
|
|
3148
|
-
if (iconSpan) {
|
|
3149
|
-
ofsTitlePx += ICON_WIDTH;
|
|
3150
|
-
}
|
|
3151
|
-
titleSpan = document.createElement("span");
|
|
3152
|
-
titleSpan.classList.add("wb-title");
|
|
3153
|
-
nodeElem.appendChild(titleSpan);
|
|
3154
|
-
this._callEvent("enhanceTitle", { titleSpan: titleSpan });
|
|
3155
|
-
// Store the width of leading icons with the node, so we can calculate
|
|
3156
|
-
// the width of the embedded title span later
|
|
3157
|
-
nodeElem._ofsTitlePx = ofsTitlePx;
|
|
3158
|
-
if (tree.options.dnd.dragStart) {
|
|
3159
|
-
nodeElem.draggable = true;
|
|
3160
|
-
}
|
|
3161
|
-
// Render columns
|
|
3162
|
-
// colElems = [];
|
|
3163
|
-
if (!this.colspan && columns.length > 1) {
|
|
3164
|
-
let colIdx = 0;
|
|
3165
|
-
for (let col of columns) {
|
|
3166
|
-
colIdx++;
|
|
3167
|
-
let colElem;
|
|
3168
|
-
if (col.id === "*") {
|
|
3169
|
-
colElem = nodeElem;
|
|
3170
|
-
}
|
|
3171
|
-
else {
|
|
3172
|
-
colElem = document.createElement("span");
|
|
3173
|
-
colElem.classList.add("wb-col");
|
|
3174
|
-
// colElem.textContent = "" + col.id;
|
|
3175
|
-
rowDiv.appendChild(colElem);
|
|
3176
|
-
}
|
|
3177
|
-
if (colIdx === activeColIdx) {
|
|
3178
|
-
colElem.classList.add("wb-active");
|
|
3179
|
-
}
|
|
3180
|
-
// Add classes from `columns` definition to `<div.wb-col>` cells
|
|
3181
|
-
col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
|
|
3182
|
-
colElem.style.left = col._ofsPx + "px";
|
|
3183
|
-
colElem.style.width = col._widthPx + "px";
|
|
3184
|
-
// colElems.push(colElem);
|
|
3185
|
-
if (isNew && col.html) {
|
|
3186
|
-
if (typeof col.html === "string") {
|
|
3187
|
-
colElem.innerHTML = col.html;
|
|
3188
|
-
}
|
|
3189
|
-
}
|
|
3190
|
-
}
|
|
3191
|
-
}
|
|
3192
|
-
}
|
|
3193
|
-
// --- From here common code starts (either new or existing markup):
|
|
3194
|
-
rowDiv.className = rowClasses.join(" "); // Reset prev. classes
|
|
3289
|
+
// Replace previous classes:
|
|
3290
|
+
rowDiv.className = rowClasses.join(" ");
|
|
3195
3291
|
// Add classes from `node.extraClasses`
|
|
3196
3292
|
rowDiv.classList.add(...this.extraClasses);
|
|
3197
3293
|
// Add classes from `tree.types[node.type]`
|
|
3198
3294
|
if (typeInfo && typeInfo.classes) {
|
|
3199
3295
|
rowDiv.classList.add(...typeInfo.classes);
|
|
3200
3296
|
}
|
|
3201
|
-
// rowDiv.style.top = (this._rowIdx! * 1.1) + "em";
|
|
3202
|
-
rowDiv.style.top = this._rowIdx * ROW_HEIGHT + "px";
|
|
3203
3297
|
if (expanderSpan) {
|
|
3204
3298
|
if (this.isExpandable(false)) {
|
|
3205
3299
|
if (this.expanded) {
|
|
@@ -3227,59 +3321,41 @@
|
|
|
3227
3321
|
checkboxSpan.className = "wb-checkbox " + iconMap.checkUnchecked;
|
|
3228
3322
|
}
|
|
3229
3323
|
}
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
titleSpan.textContent = this.title;
|
|
3236
|
-
// } else {
|
|
3237
|
-
// titleSpan.innerHTML = this.title;
|
|
3238
|
-
}
|
|
3239
|
-
// Set the width of the title span, so overflow ellipsis work
|
|
3240
|
-
if (!treeOptions.skeleton) {
|
|
3241
|
-
if (this.colspan) {
|
|
3242
|
-
let vpWidth = tree.element.clientWidth;
|
|
3243
|
-
titleSpan.style.width =
|
|
3244
|
-
vpWidth - nodeElem._ofsTitlePx - ROW_EXTRA_PAD + "px";
|
|
3245
|
-
}
|
|
3246
|
-
else {
|
|
3247
|
-
titleSpan.style.width =
|
|
3248
|
-
columns[0]._widthPx -
|
|
3249
|
-
nodeElem._ofsTitlePx -
|
|
3250
|
-
ROW_EXTRA_PAD +
|
|
3251
|
-
"px";
|
|
3324
|
+
// Fix active cell in cell-nav mode
|
|
3325
|
+
if (!opts.isNew) {
|
|
3326
|
+
let i = 0;
|
|
3327
|
+
for (let colSpan of rowDiv.children) {
|
|
3328
|
+
colSpan.classList.toggle("wb-active", i++ === tree.activeColIdx);
|
|
3252
3329
|
}
|
|
3253
3330
|
}
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
}
|
|
3331
|
+
}
|
|
3332
|
+
/**
|
|
3333
|
+
* Create or update node's markup.
|
|
3334
|
+
*
|
|
3335
|
+
* `options.change` defaults to ChangeType.data, which updates the title,
|
|
3336
|
+
* icon, and status. It also triggers the `render` event, that lets the user
|
|
3337
|
+
* create or update the content of embeded cell elements.<br>
|
|
3338
|
+
*
|
|
3339
|
+
* If only the status or other class-only modifications have changed,
|
|
3340
|
+
* `options.change` should be set to ChangeType.status instead for best
|
|
3341
|
+
* efficiency.
|
|
3342
|
+
*/
|
|
3343
|
+
render(options) {
|
|
3344
|
+
// this.log("render", options);
|
|
3345
|
+
const opts = Object.assign({ change: ChangeType.data }, options);
|
|
3346
|
+
if (!this._rowElem) {
|
|
3347
|
+
opts.change = "row";
|
|
3348
|
+
}
|
|
3349
|
+
switch (opts.change) {
|
|
3350
|
+
case "status":
|
|
3351
|
+
this._render_status(opts);
|
|
3352
|
+
break;
|
|
3353
|
+
case "data":
|
|
3354
|
+
this._render_data(opts);
|
|
3355
|
+
break;
|
|
3356
|
+
default:
|
|
3357
|
+
this._render_markup(opts);
|
|
3358
|
+
break;
|
|
3283
3359
|
}
|
|
3284
3360
|
}
|
|
3285
3361
|
/**
|
|
@@ -3437,8 +3513,8 @@
|
|
|
3437
3513
|
}
|
|
3438
3514
|
if (prev !== this) {
|
|
3439
3515
|
tree.activeNode = this;
|
|
3440
|
-
prev === null || prev === void 0 ? void 0 : prev.setModified();
|
|
3441
|
-
this.setModified();
|
|
3516
|
+
prev === null || prev === void 0 ? void 0 : prev.setModified(ChangeType.status);
|
|
3517
|
+
this.setModified(ChangeType.status);
|
|
3442
3518
|
}
|
|
3443
3519
|
if (options &&
|
|
3444
3520
|
options.colIdx != null &&
|
|
@@ -3488,10 +3564,16 @@
|
|
|
3488
3564
|
setKey(key, refKey) {
|
|
3489
3565
|
throw new Error("Not yet implemented");
|
|
3490
3566
|
}
|
|
3491
|
-
/**
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3567
|
+
/**
|
|
3568
|
+
* Schedule a render, typically called to update after a status or data change.
|
|
3569
|
+
*
|
|
3570
|
+
* `change` defaults to 'data', which handles modifcations of title, icon,
|
|
3571
|
+
* and column content. It can be reduced to 'ChangeType.status' if only
|
|
3572
|
+
* active/focus/selected state has changed.
|
|
3573
|
+
*/
|
|
3574
|
+
setModified(change = ChangeType.data) {
|
|
3575
|
+
assert(change === ChangeType.status || change === ChangeType.data);
|
|
3576
|
+
this.tree.setModified(change, this);
|
|
3495
3577
|
}
|
|
3496
3578
|
/** Modify the check/uncheck state. */
|
|
3497
3579
|
setSelected(flag = true, options) {
|
|
@@ -3687,7 +3769,7 @@
|
|
|
3687
3769
|
/*!
|
|
3688
3770
|
* Wunderbaum - ext-edit
|
|
3689
3771
|
* Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
|
|
3690
|
-
* v0.0.
|
|
3772
|
+
* v0.0.4, Tue, 03 May 2022 06:21:31 GMT (https://github.com/mar10/wunderbaum)
|
|
3691
3773
|
*/
|
|
3692
3774
|
// const START_MARKER = "\uFFF7";
|
|
3693
3775
|
class EditExtension extends WunderbaumExtension {
|
|
@@ -3978,8 +4060,8 @@
|
|
|
3978
4060
|
* Copyright (c) 2021-2022, Martin Wendt (https://wwWendt.de).
|
|
3979
4061
|
* Released under the MIT license.
|
|
3980
4062
|
*
|
|
3981
|
-
* @version v0.0.
|
|
3982
|
-
* @date
|
|
4063
|
+
* @version v0.0.4
|
|
4064
|
+
* @date Tue, 03 May 2022 06:21:31 GMT
|
|
3983
4065
|
*/
|
|
3984
4066
|
// const class_prefix = "wb-";
|
|
3985
4067
|
// const node_props: string[] = ["title", "key", "refKey"];
|
|
@@ -4123,9 +4205,7 @@
|
|
|
4123
4205
|
opts.navigationMode === NavigationModeOption.startCell) {
|
|
4124
4206
|
this.navMode = NavigationMode.cellNav;
|
|
4125
4207
|
}
|
|
4126
|
-
this._updateViewportThrottled =
|
|
4127
|
-
this._updateViewport();
|
|
4128
|
-
}, opts.updateThrottleWait, { leading: true, trailing: true });
|
|
4208
|
+
this._updateViewportThrottled = addaptiveThrottle(this._updateViewport.bind(this), {});
|
|
4129
4209
|
// --- Create Markup
|
|
4130
4210
|
this.element = elemFromSelector(opts.element);
|
|
4131
4211
|
assert(!!this.element, `Invalid 'element' option: ${opts.element}`);
|
|
@@ -4209,12 +4289,13 @@
|
|
|
4209
4289
|
});
|
|
4210
4290
|
this.resizeObserver = new ResizeObserver((entries) => {
|
|
4211
4291
|
this.setModified(ChangeType.vscroll);
|
|
4212
|
-
|
|
4292
|
+
// this.log("ResizeObserver: Size changed", entries);
|
|
4213
4293
|
});
|
|
4214
4294
|
this.resizeObserver.observe(this.element);
|
|
4215
4295
|
onEvent(this.nodeListElement, "click", "div.wb-row", (e) => {
|
|
4216
4296
|
const info = Wunderbaum.getEventInfo(e);
|
|
4217
4297
|
const node = info.node;
|
|
4298
|
+
// this.log("click", info, e);
|
|
4218
4299
|
if (this._callEvent("click", { event: e, node: node, info: info }) === false) {
|
|
4219
4300
|
this.lastClickTime = Date.now();
|
|
4220
4301
|
return false;
|
|
@@ -4242,8 +4323,6 @@
|
|
|
4242
4323
|
node.setSelected(!node.isSelected());
|
|
4243
4324
|
}
|
|
4244
4325
|
}
|
|
4245
|
-
// if(e.target.classList.)
|
|
4246
|
-
// this.log("click", info);
|
|
4247
4326
|
this.lastClickTime = Date.now();
|
|
4248
4327
|
});
|
|
4249
4328
|
onEvent(this.element, "keydown", (e) => {
|
|
@@ -4427,14 +4506,14 @@
|
|
|
4427
4506
|
* tree._callEvent("edit.beforeEdit", {foo: 42})
|
|
4428
4507
|
* ```
|
|
4429
4508
|
*/
|
|
4430
|
-
_callEvent(
|
|
4431
|
-
const [p, n] =
|
|
4509
|
+
_callEvent(type, extra) {
|
|
4510
|
+
const [p, n] = type.split(".");
|
|
4432
4511
|
const opts = this.options;
|
|
4433
4512
|
const func = n ? opts[p][n] : opts[p];
|
|
4434
4513
|
if (func) {
|
|
4435
|
-
return func.call(this, extend({
|
|
4514
|
+
return func.call(this, extend({ type: type, tree: this, util: this._util }, extra));
|
|
4436
4515
|
// } else {
|
|
4437
|
-
// this.logError(`Triggering undefined event '${
|
|
4516
|
+
// this.logError(`Triggering undefined event '${type}'.`)
|
|
4438
4517
|
}
|
|
4439
4518
|
}
|
|
4440
4519
|
/** Return the node for given row index. */
|
|
@@ -4450,7 +4529,7 @@
|
|
|
4450
4529
|
return node;
|
|
4451
4530
|
}
|
|
4452
4531
|
/** Return the topmost visible node in the viewport. */
|
|
4453
|
-
|
|
4532
|
+
getTopmostVpNode(complete = true) {
|
|
4454
4533
|
let topIdx;
|
|
4455
4534
|
const gracePy = 1; // ignore subpixel scrolling
|
|
4456
4535
|
if (complete) {
|
|
@@ -4462,7 +4541,7 @@
|
|
|
4462
4541
|
return this._getNodeByRowIdx(topIdx);
|
|
4463
4542
|
}
|
|
4464
4543
|
/** Return the lowest visible node in the viewport. */
|
|
4465
|
-
|
|
4544
|
+
getLowestVpNode(complete = true) {
|
|
4466
4545
|
let bottomIdx;
|
|
4467
4546
|
if (complete) {
|
|
4468
4547
|
bottomIdx =
|
|
@@ -4877,7 +4956,7 @@
|
|
|
4877
4956
|
res = this._getNextNodeInView(node);
|
|
4878
4957
|
break;
|
|
4879
4958
|
case "pageDown":
|
|
4880
|
-
const bottomNode = this.
|
|
4959
|
+
const bottomNode = this.getLowestVpNode();
|
|
4881
4960
|
// this.logDebug(`${where}(${node}) -> ${bottomNode}`);
|
|
4882
4961
|
if (node._rowIdx < bottomNode._rowIdx) {
|
|
4883
4962
|
res = bottomNode;
|
|
@@ -4891,7 +4970,7 @@
|
|
|
4891
4970
|
res = node;
|
|
4892
4971
|
}
|
|
4893
4972
|
else {
|
|
4894
|
-
const topNode = this.
|
|
4973
|
+
const topNode = this.getTopmostVpNode();
|
|
4895
4974
|
// this.logDebug(`${where}(${node}) -> ${topNode}`);
|
|
4896
4975
|
if (node._rowIdx > topNode._rowIdx) {
|
|
4897
4976
|
res = topNode;
|
|
@@ -5100,22 +5179,21 @@
|
|
|
5100
5179
|
* Available in cell-nav and cell-edit mode, not in row-mode.
|
|
5101
5180
|
*/
|
|
5102
5181
|
setColumn(colIdx) {
|
|
5182
|
+
var _a;
|
|
5103
5183
|
assert(this.navMode !== NavigationMode.row);
|
|
5104
5184
|
assert(0 <= colIdx && colIdx < this.columns.length);
|
|
5105
5185
|
this.activeColIdx = colIdx;
|
|
5106
|
-
// node.setActive(true, { column: tree.activeColIdx + 1 });
|
|
5107
|
-
this.setModified(ChangeType.row, this.activeNode);
|
|
5108
5186
|
// Update `wb-active` class for all headers
|
|
5109
5187
|
if (this.headerElement) {
|
|
5110
5188
|
for (let rowDiv of this.headerElement.children) {
|
|
5111
|
-
// for (let rowDiv of document.querySelector("div.wb-header").children) {
|
|
5112
5189
|
let i = 0;
|
|
5113
5190
|
for (let colDiv of rowDiv.children) {
|
|
5114
5191
|
colDiv.classList.toggle("wb-active", i++ === colIdx);
|
|
5115
5192
|
}
|
|
5116
5193
|
}
|
|
5117
5194
|
}
|
|
5118
|
-
|
|
5195
|
+
(_a = this.activeNode) === null || _a === void 0 ? void 0 : _a.setModified(ChangeType.status);
|
|
5196
|
+
// Update `wb-active` class for all cell spans
|
|
5119
5197
|
for (let rowDiv of this.nodeListElement.children) {
|
|
5120
5198
|
let i = 0;
|
|
5121
5199
|
for (let colDiv of rowDiv.children) {
|
|
@@ -5156,11 +5234,12 @@
|
|
|
5156
5234
|
this.updateViewport(immediate);
|
|
5157
5235
|
break;
|
|
5158
5236
|
case ChangeType.row:
|
|
5237
|
+
case ChangeType.data:
|
|
5159
5238
|
case ChangeType.status:
|
|
5160
5239
|
// Single nodes are immedialtely updated if already inside the viewport
|
|
5161
5240
|
// (otherwise we can ignore)
|
|
5162
5241
|
if (node._rowElem) {
|
|
5163
|
-
node.render();
|
|
5242
|
+
node.render({ change: change });
|
|
5164
5243
|
}
|
|
5165
5244
|
break;
|
|
5166
5245
|
default:
|
|
@@ -5169,6 +5248,7 @@
|
|
|
5169
5248
|
}
|
|
5170
5249
|
/** Set the tree's navigation mode. */
|
|
5171
5250
|
setNavigationMode(mode) {
|
|
5251
|
+
var _a;
|
|
5172
5252
|
// util.assert(this.cellNavMode);
|
|
5173
5253
|
// util.assert(0 <= colIdx && colIdx < this.columns.length);
|
|
5174
5254
|
if (mode === this.navMode) {
|
|
@@ -5182,7 +5262,8 @@
|
|
|
5182
5262
|
}
|
|
5183
5263
|
this.element.classList.toggle("wb-cell-mode", cellMode);
|
|
5184
5264
|
this.element.classList.toggle("wb-cell-edit-mode", mode === NavigationMode.cellEdit);
|
|
5185
|
-
this.setModified(ChangeType.row, this.activeNode);
|
|
5265
|
+
// this.setModified(ChangeType.row, this.activeNode);
|
|
5266
|
+
(_a = this.activeNode) === null || _a === void 0 ? void 0 : _a.setModified(ChangeType.status);
|
|
5186
5267
|
}
|
|
5187
5268
|
/** Display tree status (ok, loading, error, noData) using styles and a dummy root node. */
|
|
5188
5269
|
setStatus(status, message, details) {
|
|
@@ -5274,9 +5355,11 @@
|
|
|
5274
5355
|
updateViewport(immediate = false) {
|
|
5275
5356
|
// Call the `throttle` wrapper for `this._updateViewport()` which will
|
|
5276
5357
|
// execute immediately on the leading edge of a sequence:
|
|
5277
|
-
this._updateViewportThrottled();
|
|
5278
5358
|
if (immediate) {
|
|
5279
|
-
this.
|
|
5359
|
+
this._updateViewport();
|
|
5360
|
+
}
|
|
5361
|
+
else {
|
|
5362
|
+
this._updateViewportThrottled();
|
|
5280
5363
|
}
|
|
5281
5364
|
}
|
|
5282
5365
|
/**
|
|
@@ -5304,8 +5387,10 @@
|
|
|
5304
5387
|
this.scrollContainer.style.height = wantHeight + "px";
|
|
5305
5388
|
height = wantHeight;
|
|
5306
5389
|
}
|
|
5390
|
+
// console.profile(`_updateViewport()`)
|
|
5307
5391
|
this.updateColumns({ updateRows: false });
|
|
5308
5392
|
this._updateRows({ newNodesOnly: newNodesOnly });
|
|
5393
|
+
// console.profileEnd(`_updateViewport()`)
|
|
5309
5394
|
this._callEvent("update");
|
|
5310
5395
|
}
|
|
5311
5396
|
/**
|
|
@@ -5326,8 +5411,8 @@
|
|
|
5326
5411
|
// `TR#${i}, rowIdx=${n._rowIdx} , top=${top}px: '${n.title}'`
|
|
5327
5412
|
// );
|
|
5328
5413
|
// }
|
|
5329
|
-
if (top
|
|
5330
|
-
|
|
5414
|
+
if (prev >= 0 && top !== prev + ROW_HEIGHT) {
|
|
5415
|
+
n.logWarn(`TR order mismatch at index ${i}: top=${top}px != ${prev + ROW_HEIGHT}`);
|
|
5331
5416
|
// throw new Error("fault");
|
|
5332
5417
|
ok = false;
|
|
5333
5418
|
}
|
|
@@ -5346,6 +5431,7 @@
|
|
|
5346
5431
|
*/
|
|
5347
5432
|
_updateRows(opts) {
|
|
5348
5433
|
const label = this.logTime("_updateRows");
|
|
5434
|
+
// this.log("_updateRows", opts)
|
|
5349
5435
|
opts = Object.assign({ newNodesOnly: false }, opts);
|
|
5350
5436
|
const newNodesOnly = !!opts.newNodesOnly;
|
|
5351
5437
|
const row_height = ROW_HEIGHT;
|
|
@@ -5375,7 +5461,7 @@
|
|
|
5375
5461
|
let modified = false;
|
|
5376
5462
|
let prevElem = "first";
|
|
5377
5463
|
this.visitRows(function (node) {
|
|
5378
|
-
//
|
|
5464
|
+
// node.log("visit")
|
|
5379
5465
|
const rowDiv = node._rowElem;
|
|
5380
5466
|
// Renumber all expanded nodes
|
|
5381
5467
|
if (node._rowIdx !== idx) {
|
|
@@ -5397,8 +5483,11 @@
|
|
|
5397
5483
|
else {
|
|
5398
5484
|
obsoleteNodes.delete(node);
|
|
5399
5485
|
// Create new markup
|
|
5486
|
+
if (rowDiv) {
|
|
5487
|
+
rowDiv.style.top = idx * ROW_HEIGHT + "px";
|
|
5488
|
+
}
|
|
5400
5489
|
node.render({ top: top, after: prevElem });
|
|
5401
|
-
//
|
|
5490
|
+
// node.log("render", top, prevElem, "=>", node._rowElem);
|
|
5402
5491
|
prevElem = node._rowElem;
|
|
5403
5492
|
}
|
|
5404
5493
|
idx++;
|
|
@@ -5584,7 +5673,7 @@
|
|
|
5584
5673
|
* tree.enableUpdate(false);
|
|
5585
5674
|
* // ... (long running operation that would trigger many updates)
|
|
5586
5675
|
* foo();
|
|
5587
|
-
* // ... NOTE: make sure that async operations have finished
|
|
5676
|
+
* // ... NOTE: make sure that async operations have finished, e.g.
|
|
5588
5677
|
* await foo();
|
|
5589
5678
|
* } finally {
|
|
5590
5679
|
* tree.enableUpdate(true);
|
|
@@ -5647,7 +5736,7 @@
|
|
|
5647
5736
|
}
|
|
5648
5737
|
Wunderbaum.sequence = 0;
|
|
5649
5738
|
/** Wunderbaum release version number "MAJOR.MINOR.PATCH". */
|
|
5650
|
-
Wunderbaum.version = "v0.0.
|
|
5739
|
+
Wunderbaum.version = "v0.0.4"; // Set to semver by 'grunt release'
|
|
5651
5740
|
/** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
|
|
5652
5741
|
Wunderbaum.util = util;
|
|
5653
5742
|
|