##// END OF EJS Templates
Corrected Scope.own() to cleanup the supplied object immediately when the scope is disposed already
Corrected Scope.own() to cleanup the supplied object immediately when the scope is disposed already

File last commit:

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