traits.ts
214 lines
| 7.0 KiB
| video/mp2t
|
TypeScriptLexer
cin
|
r89 | import { IDestroyable } from "@implab/core-amd/interfaces"; | |
cin
|
r65 | import { isDestroyable } from "@implab/core-amd/safe"; | |
import _WidgetBase = require("dijit/_WidgetBase"); | |||
import registry = require("dijit/registry"); | |||
cin
|
r97 | interface _WidgetBaseConstructor { | |
cin
|
r108 | new <E extends { [k in keyof E]: Event } = object>(params?: Partial<_WidgetBase<E>> & ThisType<_WidgetBase<E>>, srcNodeRef?: string | Node): _WidgetBase<E> & dojo._base.DeclareCreatedObject; | |
cin
|
r107 | prototype: _WidgetBase; | |
cin
|
r97 | } | |
cin
|
r65 | ||
export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number; | |||
cin
|
r96 | export type DojoNodeLocation = [Node, DojoNodePosition]; | |
cin
|
r94 | ||
cin
|
r65 | export interface Rendition<TNode extends Node = Node> { | |
cin
|
r101 | getDomNode(): TNode; | |
cin
|
r65 | ||
placeAt(refNode: string | Node, position?: DojoNodePosition): void; | |||
} | |||
cin
|
r72 | /** | |
cin
|
r65 | * @deprecated use Rendition | |
*/ | |||
export type BuildContext<TNode extends Node = Node> = Rendition<TNode>; | |||
export interface IRecursivelyDestroyable { | |||
destroyRecursive(): void; | |||
} | |||
cin
|
r127 | export const isNode = (el: unknown): el is Node => !!(el !== null && typeof el === "object" && (el as Node).nodeName && (el as Node).nodeType); | |
cin
|
r65 | ||
cin
|
r96 | export const isElementNode = (el: unknown): el is Element => isNode(el) && el.nodeType === 1; | |
cin
|
r65 | ||
cin
|
r96 | export const isTextNode = (el: unknown): el is Text => isNode(el) && el.nodeType === 3; | |
cin
|
r65 | ||
cin
|
r96 | export const isProcessingInstructionNode = (el: unknown): el is ProcessingInstruction => isNode(el) && el.nodeType === 7; | |
cin
|
r65 | ||
cin
|
r96 | export const isCommentNode = (el: unknown): el is Comment => isNode(el) && el.nodeType === 8; | |
cin
|
r65 | ||
cin
|
r96 | export const isDocumentNode = (el: unknown): el is Document => isNode(el) && el.nodeType === 9; | |
cin
|
r65 | ||
cin
|
r96 | export const isDocumentTypeNode = (el: unknown): el is DocumentType => isNode(el) && el.nodeType === 10; | |
cin
|
r65 | ||
cin
|
r107 | export const isDocumentFragmentNode = (el: unknown): el is DocumentFragment => isNode(el) && el.nodeType === 11; | |
cin
|
r65 | ||
cin
|
r127 | export const isWidget = (v: unknown): v is _WidgetBase => !!(v !== null && typeof v === "object" && "domNode" in (v as _WidgetBase)); | |
cin
|
r65 | ||
cin
|
r127 | export const isRendition = (v: unknown): v is Rendition => !!(v !== null && typeof v === "object" && typeof (v as Rendition).getDomNode === "function"); | |
cin
|
r65 | ||
/** | |||
* @deprecated use isRendition | |||
*/ | |||
export const isBuildContext = isRendition; | |||
cin
|
r96 | export const isPlainObject = (v: object) => { | |
cin
|
r65 | if (typeof v !== "object") | |
return false; | |||
cin
|
r107 | const vp = Object.getPrototypeOf(v) as object; | |
cin
|
r65 | return !vp || vp === Object.prototype; | |
cin
|
r107 | }; | |
cin
|
r65 | ||
cin
|
r96 | export const isWidgetConstructor = (v: unknown): v is _WidgetBaseConstructor => | |
cin
|
r107 | typeof v === "function" && !!v.prototype && ( | |
cin
|
r65 | "domNode" in v.prototype || | |
"buildRendering" in v.prototype | |||
); | |||
cin
|
r96 | ||
cin
|
r65 | ||
/** Tests whether the specified node is placed in visible dom. | |||
* @param {Node} node The node to test | |||
*/ | |||
cin
|
r96 | export const isInPage = (node: Node) => node === document.body ? false : document.body.contains(node); | |
cin
|
r65 | ||
cin
|
r96 | export const isRecursivelyDestroyable = (target: unknown): target is IRecursivelyDestroyable => | |
!!(target && typeof (target as IRecursivelyDestroyable).destroyRecursive === "function"); | |||
cin
|
r65 | ||
/** Destroys DOM Node with all contained widgets. | |||
* If the specified node is the root node of a widget, then the | |||
* widget will be destroyed. | |||
* | |||
* @param target DOM Node or widget to destroy | |||
*/ | |||
cin
|
r96 | export const destroy = (target: Node | IDestroyable | IRecursivelyDestroyable) => { | |
cin
|
r65 | if (isRecursivelyDestroyable(target)) { | |
target.destroyRecursive(); | |||
} else if (isDestroyable(target)) { | |||
target.destroy(); | |||
} else if (isNode(target)) { | |||
cin
|
r93 | if (isElementNode(target)) { | |
const w = registry.byNode(target); | |||
if (w) { | |||
w.destroyRecursive(); | |||
cin
|
r102 | return; | |
cin
|
r93 | } else { | |
cin
|
r96 | emptyNode(target); | |
cin
|
r93 | } | |
cin
|
r65 | } | |
cin
|
r102 | const parent = target.parentNode; | |
if (parent) | |||
parent.removeChild(target); | |||
cin
|
r65 | } | |
cin
|
r107 | }; | |
cin
|
r65 | ||
/** Empties a content of the specified node and destroys all contained widgets. | |||
* | |||
cin
|
r96 | * @param target DOM node to empty. | |
cin
|
r65 | */ | |
cin
|
r96 | export const emptyNode = (target: Node) => { | |
cin
|
r65 | registry.findWidgets(target).forEach(destroy); | |
cin
|
r96 | ||
cin
|
r107 | // eslint-disable-next-line no-cond-assign | |
cin
|
r101 | for (let c; c = target.lastChild;) { // intentional assignment | |
cin
|
r96 | target.removeChild(c); | |
} | |||
cin
|
r107 | }; | |
cin
|
r65 | ||
/** This function starts all widgets inside the DOM node if the target is a node | |||
* or starts widget itself if the target is the widget. If the specified node | |||
* associated with the widget that widget will be started. | |||
cin
|
r72 | * | |
cin
|
r65 | * @param target DOM node to find and start widgets or the widget itself. | |
*/ | |||
cin
|
r96 | export const startupWidgets = (target: Node | _WidgetBase, skipNode?: Node) => { | |
cin
|
r65 | if (isNode(target)) { | |
cin
|
r93 | if (isElementNode(target)) { | |
const w = registry.byNode(target); | |||
if (w) { | |||
if (w.startup) | |||
w.startup(); | |||
} else { | |||
registry.findWidgets(target, skipNode).forEach(x => x.startup()); | |||
} | |||
cin
|
r65 | } | |
} else { | |||
cin
|
r72 | if (target.startup) | |
cin
|
r69 | target.startup(); | |
cin
|
r65 | } | |
cin
|
r107 | }; | |
cin
|
r94 | ||
cin
|
r96 | /** Places the specified DOM node at the specified location. | |
* | |||
* @param node The node which should be placed | |||
* @param refNodeOrId The reference node where the created | |||
* DOM should be placed. | |||
* @param position Optional parameter, specifies the | |||
* position relative to refNode. Default is "last" (i.e. last child). | |||
*/ | |||
export const placeAt = (node: Node, refNodeOrId: string | Node, position: DojoNodePosition = "last") => { | |||
cin
|
r95 | const ref = typeof refNodeOrId == "string" ? document.getElementById(refNodeOrId) : refNodeOrId; | |
if (!ref) | |||
return; | |||
const parent = ref.parentNode; | |||
cin
|
r96 | if (typeof position == "number") { | |
if (ref.childNodes.length <= position) { | |||
ref.appendChild(node); | |||
} else { | |||
ref.insertBefore(node, ref.childNodes[position]); | |||
} | |||
cin
|
r95 | } else { | |
cin
|
r96 | switch (position) { | |
cin
|
r95 | case "before": | |
cin
|
r99 | parent && parent.insertBefore(node, ref); | |
cin
|
r96 | break; | |
cin
|
r95 | case "after": | |
cin
|
r99 | parent && parent.insertBefore(node, ref.nextSibling); | |
cin
|
r96 | break; | |
case "first": | |||
cin
|
r101 | ref.insertBefore(node, ref.firstChild); | |
cin
|
r96 | break; | |
case "last": | |||
cin
|
r99 | ref.appendChild(node); | |
cin
|
r96 | break; | |
case "only": | |||
emptyNode(ref); | |||
ref.appendChild(node); | |||
break; | |||
case "replace": | |||
cin
|
r95 | if (parent) | |
cin
|
r96 | parent.replaceChild(node, ref); | |
destroy(ref); | |||
break; | |||
cin
|
r95 | } | |
} | |||
cin
|
r107 | }; | |
cin
|
r95 | ||
cin
|
r96 | /** Collects nodes from collection to an array. | |
* | |||
* @param collection The collection of nodes. | |||
* @returns The array of nodes. | |||
*/ | |||
cin
|
r102 | export const collectNodes = (collection: NodeListOf<ChildNode>) => { | |
cin
|
r96 | const items = []; | |
for (let i = 0, n = collection.length; i < n; i++) { | |||
items.push(collection[i]); | |||
} | |||
return items; | |||
}; | |||
cin
|
r95 | ||
cin
|
r102 | ||
export const isMounted = (node: Node) => { | |||
cin
|
r96 | if (node.parentNode) { | |
const parentWidget = registry.getEnclosingWidget(node.parentNode); | |||
if (parentWidget && parentWidget._started) | |||
cin
|
r102 | return true; | |
cin
|
r96 | } | |
if (isInPage(node)) | |||
cin
|
r102 | return true; | |
return false; | |||
cin
|
r96 | }; |