##// END OF EJS Templates
fixed isNode, isWidget, isRendition type predicated, fixed handling primitive values
cin -
r127:8095aad89415 v1.7.1 default
parent child
Show More
@@ -1,215 +1,215
1 1 import { IDestroyable } from "@implab/core-amd/interfaces";
2 2 import { isDestroyable } from "@implab/core-amd/safe";
3 3 import _WidgetBase = require("dijit/_WidgetBase");
4 4 import registry = require("dijit/registry");
5 5
6 6 interface _WidgetBaseConstructor {
7 7 new <E extends { [k in keyof E]: Event } = object>(params?: Partial<_WidgetBase<E>> & ThisType<_WidgetBase<E>>, srcNodeRef?: string | Node): _WidgetBase<E> & dojo._base.DeclareCreatedObject;
8 8 prototype: _WidgetBase;
9 9 }
10 10
11 11 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
12 12
13 13 export type DojoNodeLocation = [Node, DojoNodePosition];
14 14
15 15 export interface Rendition<TNode extends Node = Node> {
16 16 getDomNode(): TNode;
17 17
18 18 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
19 19 }
20 20
21 21 /**
22 22 * @deprecated use Rendition
23 23 */
24 24 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
25 25
26 26 export interface IRecursivelyDestroyable {
27 27 destroyRecursive(): void;
28 28 }
29 29
30 export const isNode = (el: unknown): el is Node => !!(el && (el as Node).nodeName && (el as Node).nodeType);
30 export const isNode = (el: unknown): el is Node => !!(el !== null && typeof el === "object" && (el as Node).nodeName && (el as Node).nodeType);
31 31
32 32 export const isElementNode = (el: unknown): el is Element => isNode(el) && el.nodeType === 1;
33 33
34 34 export const isTextNode = (el: unknown): el is Text => isNode(el) && el.nodeType === 3;
35 35
36 36 export const isProcessingInstructionNode = (el: unknown): el is ProcessingInstruction => isNode(el) && el.nodeType === 7;
37 37
38 38 export const isCommentNode = (el: unknown): el is Comment => isNode(el) && el.nodeType === 8;
39 39
40 40 export const isDocumentNode = (el: unknown): el is Document => isNode(el) && el.nodeType === 9;
41 41
42 42 export const isDocumentTypeNode = (el: unknown): el is DocumentType => isNode(el) && el.nodeType === 10;
43 43
44 44 export const isDocumentFragmentNode = (el: unknown): el is DocumentFragment => isNode(el) && el.nodeType === 11;
45 45
46 export const isWidget = (v: unknown): v is _WidgetBase => !!(v && "domNode" in (v as _WidgetBase));
46 export const isWidget = (v: unknown): v is _WidgetBase => !!(v !== null && typeof v === "object" && "domNode" in (v as _WidgetBase));
47 47
48 export const isRendition = (v: unknown): v is Rendition => !!(v && typeof (v as Rendition).getDomNode === "function");
48 export const isRendition = (v: unknown): v is Rendition => !!(v !== null && typeof v === "object" && typeof (v as Rendition).getDomNode === "function");
49 49
50 50 /**
51 51 * @deprecated use isRendition
52 52 */
53 53 export const isBuildContext = isRendition;
54 54
55 55 export const isPlainObject = (v: object) => {
56 56 if (typeof v !== "object")
57 57 return false;
58 58
59 59 const vp = Object.getPrototypeOf(v) as object;
60 60 return !vp || vp === Object.prototype;
61 61 };
62 62
63 63 export const isWidgetConstructor = (v: unknown): v is _WidgetBaseConstructor =>
64 64 typeof v === "function" && !!v.prototype && (
65 65 "domNode" in v.prototype ||
66 66 "buildRendering" in v.prototype
67 67 );
68 68
69 69
70 70 /** Tests whether the specified node is placed in visible dom.
71 71 * @param {Node} node The node to test
72 72 */
73 73 export const isInPage = (node: Node) => node === document.body ? false : document.body.contains(node);
74 74
75 75 export const isRecursivelyDestroyable = (target: unknown): target is IRecursivelyDestroyable =>
76 76 !!(target && typeof (target as IRecursivelyDestroyable).destroyRecursive === "function");
77 77
78 78
79 79
80 80 /** Destroys DOM Node with all contained widgets.
81 81 * If the specified node is the root node of a widget, then the
82 82 * widget will be destroyed.
83 83 *
84 84 * @param target DOM Node or widget to destroy
85 85 */
86 86 export const destroy = (target: Node | IDestroyable | IRecursivelyDestroyable) => {
87 87 if (isRecursivelyDestroyable(target)) {
88 88 target.destroyRecursive();
89 89 } else if (isDestroyable(target)) {
90 90 target.destroy();
91 91 } else if (isNode(target)) {
92 92 if (isElementNode(target)) {
93 93 const w = registry.byNode(target);
94 94 if (w) {
95 95 w.destroyRecursive();
96 96 return;
97 97 } else {
98 98 emptyNode(target);
99 99 }
100 100 }
101 101 const parent = target.parentNode;
102 102 if (parent)
103 103 parent.removeChild(target);
104 104
105 105 }
106 106 };
107 107
108 108 /** Empties a content of the specified node and destroys all contained widgets.
109 109 *
110 110 * @param target DOM node to empty.
111 111 */
112 112 export const emptyNode = (target: Node) => {
113 113 registry.findWidgets(target).forEach(destroy);
114 114
115 115 // eslint-disable-next-line no-cond-assign
116 116 for (let c; c = target.lastChild;) { // intentional assignment
117 117 target.removeChild(c);
118 118 }
119 119 };
120 120
121 121 /** This function starts all widgets inside the DOM node if the target is a node
122 122 * or starts widget itself if the target is the widget. If the specified node
123 123 * associated with the widget that widget will be started.
124 124 *
125 125 * @param target DOM node to find and start widgets or the widget itself.
126 126 */
127 127 export const startupWidgets = (target: Node | _WidgetBase, skipNode?: Node) => {
128 128 if (isNode(target)) {
129 129 if (isElementNode(target)) {
130 130 const w = registry.byNode(target);
131 131 if (w) {
132 132 if (w.startup)
133 133 w.startup();
134 134 } else {
135 135 registry.findWidgets(target, skipNode).forEach(x => x.startup());
136 136 }
137 137 }
138 138 } else {
139 139 if (target.startup)
140 140 target.startup();
141 141 }
142 142 };
143 143
144 144 /** Places the specified DOM node at the specified location.
145 145 *
146 146 * @param node The node which should be placed
147 147 * @param refNodeOrId The reference node where the created
148 148 * DOM should be placed.
149 149 * @param position Optional parameter, specifies the
150 150 * position relative to refNode. Default is "last" (i.e. last child).
151 151 */
152 152 export const placeAt = (node: Node, refNodeOrId: string | Node, position: DojoNodePosition = "last") => {
153 153 const ref = typeof refNodeOrId == "string" ? document.getElementById(refNodeOrId) : refNodeOrId;
154 154 if (!ref)
155 155 return;
156 156
157 157 const parent = ref.parentNode;
158 158
159 159 if (typeof position == "number") {
160 160 if (ref.childNodes.length <= position) {
161 161 ref.appendChild(node);
162 162 } else {
163 163 ref.insertBefore(node, ref.childNodes[position]);
164 164 }
165 165 } else {
166 166 switch (position) {
167 167 case "before":
168 168 parent && parent.insertBefore(node, ref);
169 169 break;
170 170 case "after":
171 171 parent && parent.insertBefore(node, ref.nextSibling);
172 172 break;
173 173 case "first":
174 174 ref.insertBefore(node, ref.firstChild);
175 175 break;
176 176 case "last":
177 177 ref.appendChild(node);
178 178 break;
179 179 case "only":
180 180 emptyNode(ref);
181 181 ref.appendChild(node);
182 182 break;
183 183 case "replace":
184 184 if (parent)
185 185 parent.replaceChild(node, ref);
186 186 destroy(ref);
187 187 break;
188 188 }
189 189 }
190 190 };
191 191
192 192 /** Collects nodes from collection to an array.
193 193 *
194 194 * @param collection The collection of nodes.
195 195 * @returns The array of nodes.
196 196 */
197 197 export const collectNodes = (collection: NodeListOf<ChildNode>) => {
198 198 const items = [];
199 199 for (let i = 0, n = collection.length; i < n; i++) {
200 200 items.push(collection[i]);
201 201 }
202 202 return items;
203 203 };
204 204
205 205
206 206 export const isMounted = (node: Node) => {
207 207 if (node.parentNode) {
208 208 const parentWidget = registry.getEnclosingWidget(node.parentNode);
209 209 if (parentWidget && parentWidget._started)
210 210 return true;
211 211 }
212 212 if (isInPage(node))
213 213 return true;
214 214 return false;
215 215 }; No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now