UNPKG

wunderbaum

Version:

JavaScript tree/grid/treegrid control.

1,108 lines (1,107 loc) 149 kB
declare module "debounce" { /*! * Wunderbaum - debounce.ts * Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license. * @VERSION, @DATE (https://github.com/mar10/wunderbaum) */ type Procedure = (...args: any[]) => any; type DebounceOptions = { /** Specify invoking on the leading edge of the timeout. @default false */ leading?: boolean; /** The maximum time `func` is allowed to be delayed before it's invoked.*/ maxWait?: number; /** Specify invoking on the trailing edge of the timeout. @default true */ trailing?: boolean; }; type ThrottleOptions = { /** Specify invoking on the leading edge of the timeout. @default true */ leading?: boolean; /** Specify invoking on the trailing edge of the timeout. @default true */ trailing?: boolean; }; export interface DebouncedFunction<F extends Procedure> { (this: ThisParameterType<F>, ...args: Parameters<F>): ReturnType<F>; cancel: () => void; flush: () => any; pending: () => boolean; } /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked, or until the next browser frame is drawn. The debounced function * comes with a `cancel` method to cancel delayed `func` invocations and a * `flush` method to immediately invoke them. Provide `options` to indicate * whether `func` should be invoked on the leading and/or trailing edge of the * `wait` timeout. The `func` is invoked with the last arguments provided to the * debounced function. Subsequent calls to the debounced function return the * result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the debounced function * is invoked more than once during the `wait` timeout. * * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred * until the next tick, similar to `setTimeout` with a timeout of `0`. * * If `wait` is omitted in an environment with `requestAnimationFrame`, `func` * invocation will be deferred until the next frame is drawn (typically about * 16ms). * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `debounce` and `throttle`. * * @since 0.1.0 * @category Function * @param {Function} func The function to debounce. * @param {number} [wait=0] * The number of milliseconds to delay; if omitted, `requestAnimationFrame` is * used (if available). * @param [options={}] The options object. * @returns {Function} Returns the new debounced function. * @example * * // Avoid costly calculations while the window size is in flux. * jQuery(window).on('resize', debounce(calculateLayout, 150)) * * // Invoke `sendMail` when clicked, debouncing subsequent calls. * jQuery(element).on('click', debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })) * * // Ensure `batchLog` is invoked once after 1 second of debounced calls. * const debounced = debounce(batchLog, 250, { 'maxWait': 1000 }) * const source = new EventSource('/stream') * jQuery(source).on('message', debounced) * * // Cancel the trailing debounced invocation. * jQuery(window).on('popstate', debounced.cancel) * * // Check for pending invocations. * const status = debounced.pending() ? "Pending..." : "Ready" */ export function debounce<F extends Procedure>(func: F, wait?: number, options?: DebounceOptions): DebouncedFunction<F>; /** * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds (or once per browser frame). The throttled function * comes with a `cancel` method to cancel delayed `func` invocations and a * `flush` method to immediately invoke them. Provide `options` to indicate * whether `func` should be invoked on the leading and/or trailing edge of the * `wait` timeout. The `func` is invoked with the last arguments provided to the * throttled function. Subsequent calls to the throttled function return the * result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the throttled function * is invoked more than once during the `wait` timeout. * * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred * until the next tick, similar to `setTimeout` with a timeout of `0`. * * If `wait` is omitted in an environment with `requestAnimationFrame`, `func` * invocation will be deferred until the next frame is drawn (typically about * 16ms). * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `throttle` and `debounce`. * * @since 0.1.0 * @category Function * @param {Function} func The function to throttle. * @param {number} [wait=0] * The number of milliseconds to throttle invocations to; if omitted, * `requestAnimationFrame` is used (if available). * @param [options={}] The options object. * @returns {Function} Returns the new throttled function. * @example * * // Avoid excessively updating the position while scrolling. * jQuery(window).on('scroll', throttle(updatePosition, 100)) * * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. * const throttled = throttle(renewToken, 300000, { 'trailing': false }) * jQuery(element).on('click', throttled) * * // Cancel the trailing throttled invocation. * jQuery(window).on('popstate', throttled.cancel) */ export function throttle<F extends Procedure>(func: F, wait?: number, options?: ThrottleOptions): DebouncedFunction<F>; } declare module "util" { /*! * Wunderbaum - util * Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license. * @VERSION, @DATE (https://github.com/mar10/wunderbaum) */ /** @module util */ import { DebouncedFunction, debounce, throttle } from "debounce"; export { debounce, throttle }; /** Readable names for `MouseEvent.button` */ export const MOUSE_BUTTONS: { [key: number]: string; }; export const MAX_INT = 9007199254740991; /**True if the client is using a macOS platform. */ export const isMac: boolean; export type FunctionType = (...args: any[]) => any; export type EventCallbackType = (e: Event) => boolean | void; /** A generic error that can be thrown to indicate a validation error when * handling the `apply` event for a node title or the `change` event for a * grid cell. */ export class ValidationError extends Error { constructor(message: string); } /** * A ES6 Promise, that exposes the resolve()/reject() methods. * * TODO: See [Promise.withResolvers()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers#description) * , a proposed standard, but not yet implemented in any browser. */ export class Deferred { private thens; private catches; private status; private resolvedValue; private rejectedError; constructor(); resolve(value?: any): void; reject(error?: any): void; then(cb: any): void; catch(cb: any): void; promise(): { then: (cb: any) => void; catch: (cb: any) => void; }; } /**Throw an `Error` if `cond` is falsey. */ export function assert(cond: any, msg: string): void; /** Run `callback` when document was loaded. */ export function documentReady(callback: () => void): void; /** Resolve when document was loaded. */ export function documentReadyPromise(): Promise<void>; /** * Iterate over Object properties or array elements. * * @param obj `Object`, `Array` or null * @param callback called for every item. * `this` also contains the item. * Return `false` to stop the iteration. */ export function each(obj: any, callback: (index: number | string, item: any) => void | boolean): any; /** Shortcut for `throw new Error(msg)`.*/ export function error(msg: string): void; /** Convert `<`, `>`, `&`, `"`, `'`, and `/` to the equivalent entities. */ export function escapeHtml(s: string): string; /**Convert a regular expression string by escaping special characters (e.g. `"$"` -> `"\$"`) */ export function escapeRegex(s: string): string; /** Convert `<`, `>`, `"`, `'`, and `/` (but not `&`) to the equivalent entities. */ export function escapeTooltip(s: string): string; /** TODO */ export function extractHtmlText(s: string): string; /** * Read the value from an HTML input element. * * If a `<span class="wb-col">` is passed, the first child input is used. * Depending on the target element type, `value` is interpreted accordingly. * For example for a checkbox, a value of true, false, or null is returned if * the element is checked, unchecked, or indeterminate. * For datetime input control a numerical value is assumed, etc. * * Common use case: store the new user input in a `change` event handler: * * ```ts * change: (e) => { * const tree = e.tree; * const node = e.node; * // Read the value from the input control that triggered the change event: * let value = tree.getValueFromElem(e.element); * // and store it to the node model (assuming the column id matches the property name) * node.data[e.info.colId] = value; * }, * ``` * @param elem `<input>` or `<select>` element. Also a parent `span.wb-col` is accepted. * @param coerce pass true to convert date/time inputs to `Date`. * @returns the value */ export function getValueFromElem(elem: HTMLElement, coerce?: boolean): any; /** * Set the value of an HTML input element. * * If a `<span class="wb-col">` is passed, the first child input is used. * Depending on the target element type, `value` is interpreted accordingly. * For example a checkbox is set to checked, unchecked, or indeterminate if the * value is truethy, falsy, or `null`. * For datetime input control a numerical value is assumed, etc. * * Common use case: update embedded input controls in a `render` event handler: * * ```ts * render: (e) => { * // e.node.log(e.type, e, e.node.data); * * for (const col of Object.values(e.renderColInfosById)) { * switch (col.id) { * default: * // Assumption: we named column.id === node.data.NAME * util.setValueToElem(col.elem, e.node.data[col.id]); * break; * } * } * }, * ``` * * @param elem `<input>` or `<select>` element Also a parent `span.wb-col` is accepted. * @param value a value that matches the target element. */ export function setValueToElem(elem: HTMLElement, value: any): void; /** Show/hide element by setting the `display` style to 'none'. */ export function setElemDisplay(elem: string | HTMLElement, flag: boolean): void; /** Create and return an unconnected `HTMLElement` from a HTML string. */ export function elemFromHtml<T = HTMLElement>(html: string): T; /** Return a HtmlElement from selector or cast an existing element. */ export function elemFromSelector<T = HTMLElement>(obj: string | T): T | null; /** * Return a canonical descriptive string for a keyboard or mouse event. * * The result also contains a prefix for modifiers if any, for example * `"x"`, `"F2"`, `"Control+Home"`, or `"Shift+clickright"`. * This is especially useful in `switch` statements, to make sure that modifier * keys are considered and handled correctly: * ```ts * const eventName = util.eventToString(e); * switch (eventName) { * case "+": * case "Add": * ... * break; * case "Enter": * case "End": * case "Control+End": * case "Meta+ArrowDown": * case "PageDown": * ... * break; * } * ``` */ export function eventToString(event: Event): string; /** * Copy allproperties from one or more source objects to a target object. * * @returns the modified target object. */ export function extend(...args: any[]): any; /** Return true if `obj` is of type `array`. */ export function isArray(obj: any): obj is any[]; /** Return true if `obj` is of type `Object` and has no properties. */ export function isEmptyObject(obj: any): boolean; /** Return true if `obj` is of type `function`. */ export function isFunction(obj: any): boolean; /** Return true if `obj` is of type `Object`. */ export function isPlainObject(obj: any): boolean; /** A dummy function that does nothing ('no operation'). */ export function noop(...args: any[]): any; /** * Bind one or more event handlers directly to an [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget). * * @param rootTarget EventTarget or selector * @param eventNames * @param handler */ export function onEvent(rootTarget: EventTarget | string, eventNames: string, handler: EventCallbackType): void; /** * Bind one or more event handlers using event delegation. * * E.g. handle all 'input' events for input and textarea elements of a given * form: * ```ts * onEvent("#form_1", "input", "input,textarea", function (e: Event) { * console.log(e.type, e.target); * }); * ``` * * @param rootTarget EventTarget or selector * @param eventNames * @param selector * @param handler */ export function onEvent(rootTarget: EventTarget | string, eventNames: string, selector: string, handler: EventCallbackType): void; /** Return a wrapped handler method, that provides `this._super` and `this._superApply`. * * ```ts // Implement `opts.createNode` event to add the 'draggable' attribute overrideMethod(ctx.options, "createNode", (event, data) => { // Default processing if any this._super.apply(this, event, data); // Add 'draggable' attribute data.node.span.draggable = true; }); ``` */ export function overrideMethod(instance: any, methodName: string, handler: FunctionType, ctx?: any): void; /** Run function after ms milliseconds and return a promise that resolves when done. */ export function setTimeoutPromise<T = unknown>(this: unknown, callback: (...args: any[]) => T, ms: number): Promise<T>; /** * Wait `ms` microseconds. * * Example: * ```js * await sleep(1000); * ``` * @param ms duration * @returns */ export function sleep(ms: number): Promise<unknown>; /** * Set or rotate checkbox status with support for tri-state. * * An initial 'indeterminate' state becomes 'checked' on the first call. * * If the input element has the class 'wb-tristate' assigned, the sequence is:<br> * 'indeterminate' -> 'checked' -> 'unchecked' -> 'indeterminate' -> ...<br> * Otherwise we toggle like <br> * 'checked' -> 'unchecked' -> 'checked' -> ... */ export function toggleCheckbox(element: HTMLElement | string, value?: boolean | null, tristate?: boolean): void; /** * Return `opts.NAME` if opts is valid and * * @param opts dict, object, or null * @param name option name (use dot notation to access extension option, e.g. `filter.mode`) * @param defaultValue returned when `opts` is not an object, or does not have a NAME property */ export function getOption(opts: any, name: string, defaultValue?: any): any; /** Return the next value from a list of values (rotating). @since 0.11 */ export function rotate(value: any, values: any[]): any; /** Convert an Array or space-separated string to a Set. */ export function toSet(val: any): Set<string>; /** Convert a pixel string to number. * We accept a number or a string like '123px'. If undefined, the first default * value that is a number or a string ending with 'px' is returned. * * Example: * ```js * let x = undefined; * let y = "123px"; * const width = util.toPixel(x, y, 100); // returns 123 * ``` */ export function toPixel(...defaults: (string | number | undefined | null)[]): number; /** Return the the boolean value of the first non-null element. * Example: * ```js * const opts = { flag: true }; * const value = util.toBool(opts.foo, opts.flag, false); // returns true * ``` */ export function toBool(...boolDefaults: (boolean | undefined | null)[]): boolean; /** * Return `val` unless `val` is a number in which case we convert to boolean. * This is useful when a boolean value is stored as a 0/1 (e.g. in JSON) and * we still want to maintain string values. null and undefined are returned as * is. E.g. `checkbox` may be boolean or 'radio'. */ export function intToBool(val: boolean | number | string | undefined): boolean | string | undefined; /** Return a canonical string representation for an object's type (e.g. 'array', 'number', ...). */ export function type(obj: any): string; /** * Return a function that can be called instead of `callback`, but guarantees * a limited execution rate. * The execution rate is calculated based on the runtime duration of the * previous call. * Example: * ```js * throttledFoo = util.adaptiveThrottle(foo.bind(this), {}); * throttledFoo(); * throttledFoo(); * ``` */ export function adaptiveThrottle(this: unknown, callback: (...args: any[]) => void, options: object): DebouncedFunction<(...args: any[]) => void>; } declare module "common" { /*! * Wunderbaum - common * Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license. * @VERSION, @DATE (https://github.com/mar10/wunderbaum) */ import { ApplyCommandType, NavigationType, SourceObjectType, IconMapType, MatcherCallback } from "types"; import { WunderbaumNode } from "wb_node"; export const DEFAULT_DEBUGLEVEL = 4; /** * Fixed height of a row in pixel. Must match the SCSS variable `$row-outer-height`. */ export const DEFAULT_ROW_HEIGHT = 22; /** * Fixed width of node icons in pixel. Must match the SCSS variable `$icon-outer-width`. */ export const ICON_WIDTH = 20; /** * Adjust the width of the title span, so overflow ellipsis work. * (2 x `$col-padding-x` + 3px rounding errors). */ export const TITLE_SPAN_PAD_Y = 7; /** Render row markup for N nodes above and below the visible viewport. */ export const RENDER_MAX_PREFETCH = 5; /** Skip rendering new rows when we have at least N nodes rendeed above and below the viewport. */ export const RENDER_MIN_PREFETCH = 5; /** Minimum column width if not set otherwise. */ export const DEFAULT_MIN_COL_WIDTH = 4; /** Regular expression to detect if a string describes an image URL (in contrast * to a class name). Strings are considered image urls if they contain '.' or '/'. */ export const TEST_IMG: RegExp; /** * Default node icons for icon libraries * * - 'bootstrap': {@link https://icons.getbootstrap.com} * - 'fontawesome6' {@link https://fontawesome.com/icons} * */ export const iconMaps: { [key: string]: IconMapType; }; export const KEY_NODATA = "__not_found__"; /** Define which keys are handled by embedded <input> control, and should * *not* be passed to tree navigation handler in cell-edit mode. */ export const INPUT_KEYS: { [key: string]: Array<string>; }; /** Dict keys that are evaluated by source loader (others are added to `tree.data` instead). */ export const RESERVED_TREE_SOURCE_KEYS: Set<string>; /** Map `KeyEvent.key` to navigation action. */ export const KEY_TO_NAVIGATION_MAP: { [key: string]: NavigationType; }; /** Map `KeyEvent.key` to navigation action. */ export const KEY_TO_COMMAND_MAP: { [key: string]: ApplyCommandType; }; /** Return a callback that returns true if the node title matches the string * or regular expression. * @see {@link WunderbaumNode.findAll} */ export function makeNodeTitleMatcher(match: string | RegExp): MatcherCallback; /** Return a callback that returns true if the node title starts with a string (case-insensitive). */ export function makeNodeTitleStartMatcher(s: string): MatcherCallback; /** Compare two nodes by title (case-insensitive). */ export function nodeTitleSorter(a: WunderbaumNode, b: WunderbaumNode): number; /** * Decompresses the source data by * - converting from 'flat' to 'nested' format * - expanding short alias names to long names (if defined in _keyMap) * - resolving value indexes to value strings (if defined in _valueMap) * * @param source - The source object to be decompressed. * @returns void */ export function decompressSourceData(source: SourceObjectType): void; } declare module "deferred" { /*! * Wunderbaum - deferred * Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license. * @VERSION, @DATE (https://github.com/mar10/wunderbaum) */ type PromiseCallbackType = (val: any) => void; type finallyCallbackType = () => void; /** * Implement a ES6 Promise, that exposes a resolve() and reject() method. * * Loosely mimics {@link https://api.jquery.com/category/deferred-object/ | jQuery.Deferred}. * Example: * ```js * function foo() { * let dfd = new Deferred(), * ... * dfd.resolve('foo') * ... * return dfd.promise(); * } * ``` */ export class Deferred<T> { private _promise; protected _resolve: any; protected _reject: any; constructor(); /** Resolve the Promise. */ resolve(value?: any): void; /** Reject the Promise. */ reject(reason?: any): void; /** Return the native Promise instance.*/ promise(): Promise<T>; /** Call Promise.then on the embedded promise instance.*/ then(cb: PromiseCallbackType): Promise<void>; /** Call Promise.catch on the embedded promise instance.*/ catch(cb: PromiseCallbackType): Promise<void | T>; /** Call Promise.finally on the embedded promise instance.*/ finally(cb: finallyCallbackType): Promise<T>; } } declare module "wb_node" { import { Wunderbaum } from "wunderbaum"; import { AddChildrenOptions, ApplyCommandOptions, ApplyCommandType, ChangeType, CheckboxOption, ExpandAllOptions, IconOption, InsertNodeType, MakeVisibleOptions, MatcherCallback, NavigateOptions, NavigationType, NodeAnyCallback, NodeStatusType, NodeStringCallback, NodeToDictCallback, NodeVisitCallback, NodeVisitResponse, RenderOptions, ResetOrderOptions, ScrollIntoViewOptions, SetActiveOptions, SetExpandedOptions, SetSelectedOptions, SetStatusOptions, SortByPropertyOptions, SortCallback, SourceType, TooltipOption, TristateType, WbNodeData } from "types"; /** * A single tree node. * * **NOTE:** <br> * Generally you should not modify properties directly, since this may break * the internal bookkeeping. */ export class WunderbaumNode { static sequence: number; /** Reference to owning tree. */ tree: Wunderbaum; /** Parent node (null for the invisible root node `tree.root`). */ parent: WunderbaumNode; /** Name of the node. * @see Use {@link setTitle} to modify. */ title: string; /** Unique key. Passed with constructor or defaults to `SEQUENCE`. * @see Use {@link setKey} to modify. */ readonly key: string; /** Reference key. Unlike {@link key}, a `refKey` may occur multiple * times within a tree (in this case we have 'clone nodes'). * @see Use {@link setKey} to modify. */ readonly refKey: string | undefined; /** * Array of child nodes (null for leaf nodes). * For lazy nodes, this is `null` or ùndefined` until the children are loaded * and leaf nodes may be `[]` (empty array). * @see {@link hasChildren}, {@link addChildren}, {@link lazy}. */ children: WunderbaumNode[] | null; /** Render a checkbox or radio button @see {@link selected}. */ checkbox?: CheckboxOption; /** If true, this node's children are considerd radio buttons. * @see {@link isRadio}. */ radiogroup?: boolean; /** If true, (in grid mode) no cells are rendered, except for the node title.*/ colspan?: boolean; /** Icon definition. */ icon?: IconOption; /** Lazy loading flag. * @see {@link isLazy}, {@link isLoaded}, {@link isUnloaded}. */ lazy?: boolean; /** Expansion state. * @see {@link isExpandable}, {@link isExpanded}, {@link setExpanded}. */ expanded?: boolean; /** Selection state. * @see {@link isSelected}, {@link setSelected}, {@link toggleSelected}. */ selected?: boolean; unselectable?: boolean; /** Node type (used for styling). * @see {@link Wunderbaum.types}. */ type?: string; /** Tooltip definition (`true`: use node's title). */ tooltip?: TooltipOption; /** Icon tooltip definition (`true`: use node's title). */ iconTooltip?: TooltipOption; /** Additional classes added to `div.wb-row`. * @see {@link hasClass}, {@link setClass}. */ classes: Set<string> | null; /** Custom data that was passed to the constructor */ data: any; statusNodeType?: NodeStatusType; _isLoading: boolean; _requestId: number; _errorInfo: any | null; _partsel: boolean; _partload: boolean; /** * > 0 if matched (-1 to keep system nodes visible); * Added and removed by filter code. */ match?: number; subMatchCount?: number; /** @internal */ titleWithHighlight?: string; _filterAutoExpanded?: boolean; _rowIdx: number | undefined; _rowElem: HTMLDivElement | undefined; constructor(tree: Wunderbaum, parent: WunderbaumNode, data: any); /** * Return readable string representation for this instance. * @internal */ toString(): string; /** * Iterate all descendant nodes depth-first, pre-order using `for ... of ...` syntax. * More concise, but slightly slower than {@link WunderbaumNode.visit}. * * Example: * ```js * for(const n of node) { * ... * } * ``` */ [Symbol.iterator](): IterableIterator<WunderbaumNode>; /** Call event handler if defined in tree.options. * Example: * ```js * node._callEvent("edit.beforeEdit", {foo: 42}) * ``` */ _callEvent(type: string, extra?: any): any; /** * Append (or insert) a list of child nodes. * * Tip: pass `{ before: 0 }` to prepend new nodes as first children. * * @returns first child added */ addChildren(nodeData: WbNodeData | WbNodeData[], options?: AddChildrenOptions): WunderbaumNode; /** * Append or prepend a node, or append a child node. * * This a convenience function that calls addChildren() * * @param nodeData node definition * @param [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child') * @returns new node */ addNode(nodeData: WbNodeData, mode?: InsertNodeType): WunderbaumNode; /** * Apply a modification (or navigation) operation. * * @see {@link Wunderbaum.applyCommand} */ applyCommand(cmd: ApplyCommandType, options: ApplyCommandOptions): any; /** * Collapse all expanded sibling nodes if any. * (Automatically called when `autoCollapse` is true.) */ collapseSiblings(options?: SetExpandedOptions): any; /** * Add/remove one or more classes to `<div class='wb-row'>`. * * This also maintains `node.classes`, so the class will survive a re-render. * * @param className one or more class names. Multiple classes can be passed * as space-separated string, array of strings, or set of strings. */ setClass(className: string | string[] | Set<string>, flag?: boolean): void; /** Start editing this node's title. */ startEditTitle(): void; /** * Call `setExpanded()` on all descendant nodes. * * @param flag true to expand, false to collapse. * @param options Additional options. * @see {@link Wunderbaum.expandAll} * @see {@link WunderbaumNode.setExpanded} */ expandAll(flag?: boolean, options?: ExpandAllOptions): Promise<void>; /** * Find all descendant nodes that match condition (excluding self). * * If `match` is a string, search for exact node title. * If `match` is a RegExp expression, apply it to node.title, using * [RegExp.test()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test). * If `match` is a callback, match all nodes for that the callback(node) returns true. * * Returns an empty array if no nodes were found. * * Examples: * ```js * // Match all node titles that match exactly 'Joe': * nodeList = node.findAll("Joe") * // Match all node titles that start with 'Joe' case sensitive: * nodeList = node.findAll(/^Joe/) * // Match all node titles that contain 'oe', case insensitive: * nodeList = node.findAll(/oe/i) * // Match all nodes with `data.price` >= 99: * nodeList = node.findAll((n) => { * return n.data.price >= 99; * }) * ``` */ findAll(match: string | RegExp | MatcherCallback): WunderbaumNode[]; /** Return the direct child with a given key, index or null. */ findDirectChild(ptr: number | string | WunderbaumNode): WunderbaumNode | null; /** * Find first descendant node that matches condition (excluding self) or null. * * @see {@link WunderbaumNode.findAll} for examples. */ findFirst(match: string | RegExp | MatcherCallback): WunderbaumNode | null; /** Find a node relative to self. * * @see {@link Wunderbaum.findRelatedNode|tree.findRelatedNode()} */ findRelatedNode(where: NavigationType, includeHidden?: boolean): any; /** * Iterator version of {@link WunderbaumNode.format}. */ format_iter(name_cb?: NodeStringCallback, connectors?: string[]): IterableIterator<string>; /** * Return a multiline string representation of a node/subnode hierarchy. * Mostly useful for debugging. * * Example: * ```js * console.info(tree.getActiveNode().format((n)=>n.title)); * ``` * logs * ``` * Books * ├─ Art of War * ╰─ Don Quixote * ``` * @see {@link WunderbaumNode.format_iter} */ format(name_cb?: NodeStringCallback, connectors?: string[]): string; /** Return the `<span class='wb-col'>` element with a given index or id. * @returns {WunderbaumNode | null} */ getColElem(colIdx: number | string): HTMLSpanElement; /** * Return all nodes with the same refKey. * * @param includeSelf Include this node itself. * @see {@link Wunderbaum.findByRefKey} */ getCloneList(includeSelf?: boolean): WunderbaumNode[]; /** Return the first child node or null. * @returns {WunderbaumNode | null} */ getFirstChild(): WunderbaumNode; /** Return the last child node or null. * @returns {WunderbaumNode | null} */ getLastChild(): WunderbaumNode; /** Return node depth (starting with 1 for top level nodes). */ getLevel(): number; /** Return the successive node (under the same parent) or null. */ getNextSibling(): WunderbaumNode | null; /** Return the parent node (null for the system root node). */ getParent(): WunderbaumNode | null; /** Return an array of all parent nodes (top-down). * @param includeRoot Include the invisible system root node. * @param includeSelf Include the node itself. */ getParentList(includeRoot?: boolean, includeSelf?: boolean): any[]; /** Return a string representing the hierachical node path, e.g. "a/b/c". * @param includeSelf * @param part property name or callback * @param separator */ getPath(includeSelf?: boolean, part?: keyof WunderbaumNode | NodeAnyCallback, separator?: string): string; /** Return the preceeding node (under the same parent) or null. */ getPrevSibling(): WunderbaumNode | null; /** Return true if node has children. * Return undefined if not sure, i.e. the node is lazy and not yet loaded. */ hasChildren(): boolean; /** Return true if node has className set. */ hasClass(className: string): boolean; /** Return true if node ist the currently focused node. @since 0.9.0 */ hasFocus(): boolean; /** Return true if this node is the currently active tree node. */ isActive(): boolean; /** Return true if this node is a direct or indirect parent of `other`. * @see {@link WunderbaumNode.isParentOf} */ isAncestorOf(other: WunderbaumNode): boolean; /** Return true if this node is a **direct** subnode of `other`. * @see {@link WunderbaumNode.isDescendantOf} */ isChildOf(other: WunderbaumNode): boolean; /** Return true if this node's refKey is used by at least one other node. */ isClone(): boolean; /** Return true if this node's title spans all columns, i.e. the node has no * grid cells. */ isColspan(): boolean; /** Return true if this node is a direct or indirect subnode of `other`. * @see {@link WunderbaumNode.isChildOf} */ isDescendantOf(other: WunderbaumNode): boolean; /** Return true if this node has children, i.e. the node is generally expandable. * If `andCollapsed` is set, we also check if this node is collapsed, i.e. * an expand operation is currently possible. */ isExpandable(andCollapsed?: boolean): boolean; /** Return true if _this_ node is currently in edit-title mode. * * See {@link WunderbaumNode.startEditTitle}. */ isEditingTitle(): boolean; /** Return true if this node is currently expanded. */ isExpanded(): boolean; /** Return true if this node is the first node of its parent's children. */ isFirstSibling(): boolean; /** Return true if this node is the last node of its parent's children. */ isLastSibling(): boolean; /** Return true if this node is lazy (even if data was already loaded) */ isLazy(): boolean; /** Return true if node is lazy and loaded. For non-lazy nodes always return true. */ isLoaded(): boolean; /** Return true if node is currently loading, i.e. a GET request is pending. */ isLoading(): boolean; /** Return true if this node is a temporarily generated status node of type 'paging'. */ isPagingNode(): boolean; /** Return true if this node is a **direct** parent of `other`. * @see {@link WunderbaumNode.isAncestorOf} */ isParentOf(other: WunderbaumNode): boolean; /** Return true if this node is partially loaded. @experimental */ isPartload(): boolean; /** Return true if this node is partially selected (tri-state). */ isPartsel(): boolean; /** Return true if this node has DOM representaion, i.e. is displayed in the viewport. */ isRadio(): boolean; /** Return true if this node has DOM representaion, i.e. is displayed in the viewport. */ isRendered(): boolean; /** Return true if this node is the (invisible) system root node. * @see {@link WunderbaumNode.isTopLevel} */ isRootNode(): boolean; /** Return true if this node is selected, i.e. the checkbox is set. * `undefined` if partly selected (tri-state), false otherwise. */ isSelected(): TristateType; /** Return true if this node is a temporarily generated system node like * 'loading', 'paging', or 'error' (node.statusNodeType contains the type). */ isStatusNode(): boolean; /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node. */ isTopLevel(): boolean; /** Return true if node is marked lazy but not yet loaded. * For non-lazy nodes always return false. */ isUnloaded(): boolean; /** Return true if all parent nodes are expanded. Note: this does not check * whether the node is scrolled into the visible part of the screen or viewport. */ isVisible(): boolean; protected _loadSourceObject(source: any, level?: number): void; _fetchWithOptions(source: any): Promise<any>; /** Download data from the cloud, then call `.update()`. */ load(source: SourceType): Promise<void>; /** * Load content of a lazy node. * If the node is already loaded, nothing happens. * @param [forceReload=false] If true, reload even if already loaded. */ loadLazy(forceReload?: boolean): Promise<void>; /** Write to `console.log` with node name as prefix if opts.debugLevel >= 4. * @see {@link WunderbaumNode.logDebug} */ log(...args: any[]): void; /** Write to `console.debug` with node name as prefix if opts.debugLevel >= 4 * and browser console level includes debug/verbose messages. * @see {@link WunderbaumNode.log} */ logDebug(...args: any[]): void; /** Write to `console.error` with node name as prefix if opts.debugLevel >= 1. */ logError(...args: any[]): void; /** Write to `console.info` with node name as prefix if opts.debugLevel >= 3. */ logInfo(...args: any[]): void; /** Write to `console.warn` with node name as prefix if opts.debugLevel >= 2. */ logWarn(...args: any[]): void; /** Expand all parents and optionally scroll into visible area as neccessary. * Promise is resolved, when lazy loading and animations are done. * @param {object} [options] passed to `setExpanded()`. * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true} */ makeVisible(options?: MakeVisibleOptions): Promise<unknown>; /** Move this node to targetNode. */ moveTo(targetNode: WunderbaumNode, mode?: InsertNodeType, map?: NodeAnyCallback): void; /** Set focus relative to this node and optionally activate. * * 'left' collapses the node if it is expanded, or move to the parent * otherwise. * 'right' expands the node if it is collapsed, or move to the first * child otherwise. * * @param where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'. * (Alternatively the `event.key` that would normally trigger this move, * e.g. `ArrowLeft` = 'left'. * @param options */ navigate(where: NavigationType | string, options?: NavigateOptions): Promise<any>; /** Delete this node and all descendants. */ remove(): void; /** Remove all descendants of this node. */ removeChildren(): void; /** Remove all HTML markup from the DOM. */ removeMarkup(): void; protected _getRenderInfo(): any; protected _createIcon(parentElem: HTMLElement, replaceChild: HTMLElement | null, showLoading: boolean): HTMLElement | null; /** * Create a whole new `<div class="wb-row">` element. * @see {@link WunderbaumNode._render} */ protected _render_markup(opts: RenderOptions): void; /** * Render `node.title`, `.icon` into an existing row. * * @see {@link WunderbaumNode._render} */ protected _render_data(opts: RenderOptions): void; /** * Update row classes to reflect active, focuses, etc. * @see {@link WunderbaumNode._render} */ protected _render_status(opts: RenderOptions): void; _render(options?: RenderOptions): void; /** * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad * event is triggered on next expand. */ resetLazy(): void; /** Convert node (or whole branch) into a plain object. * * The result is compatible with node.addChildren(). * * @param recursive include child nodes * @param callback is called for every node, in order to allow * modifications. * Return `false` to ignore this node or `"skip"` to include this node * without its children. * @see {@link Wunderbaum.toDictArray}. */ toDict(recursive?: boolean, callback?: NodeToDictCallback): WbNodeData; /** Return an option value that has a default, but may be overridden by a * callback or a node instance attribute. * * Evaluation sequence: * * - If `tree.options.<name>` is a callback that returns something, use that. * - Else if `node.<name>` is defined, use that. * - Else if `tree.types[<node.type>]` is a value, use that. * - Else if `tree.options.<name>` is a value, use that. * - Else use `defaultValue`. * * @param name name of the option property (on node and tree) * @param defaultValue return this if nothing else matched * {@link Wunderbaum.getOption|Wunderbaum.getOption} */ getOption(name: string, defaultValue?: any): any; /** Make sure that this node is visible in the viewport. * @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo} */ scrollIntoView(options?: ScrollIntoViewOptions): Promise<void>; /** * Activate this node, deactivate previous, send events, activate column and * scroll into viewport. */ setActive(flag?: boolean, options?: SetActiveOptions): Promise<void>; /** * Expand or collapse this node. */ setExpanded(flag?: boolean, options?: SetExpandedOptions): Promise<void>; /** * Set keyboard focus here. * @see {@link setActive} */ setFocus(flag?: boolean): void; /** Set a new icon path or class. */ setIcon(icon: string): void; /** Change node's {@link key} and/or {@link refKey}. */ setKey(key: string | null, refKey: string | null): void; /** * Trigger a repaint, typically after a status or data change. * * `change` defaults to 'data', which handles modifcations of title, icon, * and column content. It can be reduced to 'ChangeType.status' if only * active/focus/selected state has changed. * * This method will eventually call {@link WunderbaumNode._render} with * default options, but may be more consistent with the tree's * {@link Wunderbaum.update} API. */ update(change?: ChangeType): void; /** * Return an array of selected nodes. * @param stopOnParents only return the topmost selected node (useful with selectMode 'hier') */ getSelectedNodes(stopOnParents?: boolean): WunderbaumNode[]; /** Toggle the check/uncheck state. */ toggleSelected(options?: SetSelectedOptions): TristateType; /** Return true if at least on selectable descendant end-node is unselected. @internal */ _anySelectable(): boolean; protected _changeSelectStatusProps(state: TristateType): boolean; /** * Fix selection status, after this node was (de)selected in `selectMode: 'hier'`. * This includes (de)selecting all descendants. */ fixSelection3AfterClick(opts?: SetSelectedOptions): void; /** * Fix selection status for multi-hier mode. * Only end-nodes are considered to update the descendants branch and parents. * Should be called after this node has loaded new children or after * children have been modified using the API. */ fixSelection3FromEndNodes(opts?: SetSelectedOptions): void; /** Modify the check/uncheck state. */ setSelected(flag?: boolean, options?: SetSelectedOptions): TristateType; /** Display node status (ok, loading, error, noData) using styles and a dummy child node. */ setStatus(status: NodeStatusType, options?: SetStatusOptions): WunderbaumNode | null; /** Rename this node. */ setTitle(title: string): void; /** Set the node tooltip. */ setTooltip(tooltip: TooltipOption): void; _sortChildren(cmp: SortCallback, deep: boolean): void; /** * Sort child list by title or custom criteria. * @param {function} cmp custom compare function(a, b) that returns -1, 0, or 1 * (defaults to sorting by title). * @param {boolean} deep pass true to sort all descendant nodes recursively */ sortChildren(cmp?: SortCallback | null, deep?: boolean): void; /** * Renumber nodes `_nativeIndex`. This is useful to allow to restore the * order after sorting a column. * This method is automatically called after loading new child nodes. * @since 0.11.0 */ resetNativeChildOrder(options?: ResetOrderOptions): void; /** * Convenience method to implement column sorting. * @since 0.11.0 */ sortByProperty(options: SortByPropertyOptions): void; /** * Trigger `modifyChild` event on a parent to signal that a child was modified. * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ... */ triggerModifyChild(operation: string, child: WunderbaumNode | null, extra?: any): void; /** * Trigger `modifyChild` event on node.parent(!). * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ... * @param {object} [extra] */ triggerModify(operation: string, extra?: any): void; /** * Call `callback(node)` for all descendant nodes in hierarchical order (depth-first, pre-order). * * Stop iteration, if fn() returns false. Skip current branch, if fn() * returns "skip".<br> * Return false if iteration was stopped. * * @param {function} callback the callback function. * Return false to stop iteration, return "skip" to skip this node and * its children only. * @see {@link IterableIterator<WunderbaumNode>}, {@link Wunderbaum.visit}. */ visit(callback: NodeVisitCallback, includeSelf?: boolean): NodeVisitResponse; /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br> * Stop iteration, if callback() returns false.<br> * Return false if iteration was stopped. * * @param callback the callback function. Return false to stop iteration */ visitParents(callback: (node: WunderbaumNode) => boolean | void, includeSelf?: boolean): boolean; /** * Call fn(node) for all sibling nodes.<br> * Stop iteration, if fn() returns false.<br>