Skip to content

Commit dd96572

Browse files
New XNode method to clone nodes.
1 parent b54f2e2 commit dd96572

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

src/dom/functions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function domCreateComment(doc: any, text: any) {
6060
return doc.createComment(text);
6161
}
6262

63-
export function domCreateDocumentFragment(doc: XDocument) {
63+
export function domCreateDocumentFragment(doc: XDocument): XNode {
6464
return doc.createDocumentFragment();
6565
}
6666

src/dom/xdocument.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class XDocument extends XNode {
3737
return XNode.create(DOM_ELEMENT_NODE, name, null, this, namespace);
3838
}
3939

40-
createDocumentFragment() {
40+
createDocumentFragment(): XNode {
4141
return XNode.create(DOM_DOCUMENT_FRAGMENT_NODE, '#document-fragment', null, this);
4242
}
4343

src/dom/xnode.ts

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { XDocument } from './xdocument';
99

1010
// operate on native DOM nodes.
1111
export class XNode {
12-
attributes: any[];
12+
attributes: XNode[];
1313
childNodes: XNode[];
1414
nodeType: any;
1515
nodeName: string;
@@ -36,12 +36,20 @@ export class XNode {
3636
this.init(type, name, opt_value, opt_owner, opt_namespace);
3737
}
3838

39-
init(type: any, name: string, value: string, owner: any, namespace: any) {
39+
/**
40+
* Node initialization. Called by the constructor and `recycle` method.
41+
* @param type The node type.
42+
* @param name The node name.
43+
* @param value The node value.
44+
* @param owner The node owner.
45+
* @param namespaceUri The node namespace.
46+
*/
47+
init(type: any, name: string, value: string, owner: any, namespaceUri: any) {
4048
this.nodeType = type - 0;
4149
this.nodeName = `${name}`;
4250
this.nodeValue = `${value}`;
4351
this.ownerDocument = owner;
44-
this.namespaceURI = namespace || null;
52+
this.namespaceURI = namespaceUri || null;
4553
[this.prefix, this.localName] = this.qualifiedNameToParts(`${name}`);
4654

4755
this.firstChild = null;
@@ -51,7 +59,7 @@ export class XNode {
5159
this.parentNode = null;
5260
}
5361

54-
qualifiedNameToParts(name) {
62+
protected qualifiedNameToParts(name: string) {
5563
if (name.includes(':')) {
5664
return name.split(':');
5765
}
@@ -77,9 +85,11 @@ export class XNode {
7785
for (let a = 0; a < node.attributes.length; ++a) {
7886
this.recycle(node.attributes[a]);
7987
}
88+
8089
for (let c = 0; c < node.childNodes.length; ++c) {
8190
this.recycle(node.childNodes[c]);
8291
}
92+
8393
node.attributes.length = 0;
8494
node.childNodes.length = 0;
8595
node.init.call(0, '', '', null);
@@ -95,6 +105,19 @@ export class XNode {
95105
return new XNode(type, name, value, owner, namespace);
96106
}
97107

108+
static clone(node: XNode, newOwner: XNode): XNode {
109+
const newNode = new XNode(node.nodeType, node.nodeName, node.nodeValue, newOwner, node.namespaceURI);
110+
for (let child of node.childNodes) {
111+
newNode.appendChild(XNode.clone(child, newNode));
112+
}
113+
114+
for (let attribute of node.attributes) {
115+
newNode.setAttribute(attribute.nodeName, attribute.nodeValue);
116+
}
117+
118+
return newNode;
119+
}
120+
98121
appendChild(node: any) {
99122
// firstChild
100123
if (this.childNodes.length == 0) {
@@ -120,7 +143,7 @@ export class XNode {
120143
this.childNodes.push(node);
121144
}
122145

123-
replaceChild(newNode, oldNode) {
146+
replaceChild(newNode: any, oldNode: any) {
124147
if (oldNode == newNode) {
125148
return;
126149
}
@@ -160,7 +183,7 @@ export class XNode {
160183
}
161184
}
162185

163-
insertBefore(newNode, oldNode) {
186+
insertBefore(newNode: any, oldNode: any) {
164187
if (oldNode == newNode) {
165188
return;
166189
}
@@ -199,7 +222,7 @@ export class XNode {
199222
this.childNodes = newChildren;
200223
}
201224

202-
removeChild(node) {
225+
removeChild(node: any) {
203226
const newChildren = [];
204227

205228
for (const c of this.childNodes) {
@@ -228,17 +251,18 @@ export class XNode {
228251
return this.attributes.length > 0;
229252
}
230253

231-
setAttribute(name, value) {
254+
setAttribute(name: any, value: any) {
232255
for (let i = 0; i < this.attributes.length; ++i) {
233256
if (this.attributes[i].nodeName == name) {
234257
this.attributes[i].nodeValue = `${value}`;
235258
return;
236259
}
237260
}
261+
238262
this.attributes.push(XNode.create(DOM_ATTRIBUTE_NODE, name, value, this));
239263
}
240264

241-
setAttributeNS(namespace, name, value) {
265+
setAttributeNS(namespace: any, name: any, value: any) {
242266
for (let i = 0; i < this.attributes.length; ++i) {
243267
if (
244268
this.attributes[i].namespaceURI == namespace &&
@@ -250,37 +274,41 @@ export class XNode {
250274
return;
251275
}
252276
}
277+
253278
this.attributes.push(XNode.create(DOM_ATTRIBUTE_NODE, name, value, this, namespace));
254279
}
255280

256-
getAttribute(name) {
281+
getAttribute(name: any) {
257282
for (let i = 0; i < this.attributes.length; ++i) {
258283
if (this.attributes[i].nodeName == name) {
259284
return this.attributes[i].nodeValue;
260285
}
261286
}
287+
262288
return null;
263289
}
264290

265-
getAttributeNS(namespace, localName) {
291+
getAttributeNS(namespace: any, localName: any) {
266292
for (let i = 0; i < this.attributes.length; ++i) {
267293
if (this.attributes[i].namespaceURI == namespace && this.attributes[i].localName == localName) {
268294
return this.attributes[i].nodeValue;
269295
}
270296
}
297+
271298
return null;
272299
}
273300

274-
hasAttribute(name) {
301+
hasAttribute(name: any) {
275302
for (let i = 0; i < this.attributes.length; ++i) {
276303
if (this.attributes[i].nodeName == name) {
277304
return true;
278305
}
279306
}
307+
280308
return false;
281309
}
282310

283-
hasAttributeNS(namespace, localName) {
311+
hasAttributeNS(namespace: any, localName: any) {
284312
for (let i = 0; i < this.attributes.length; ++i) {
285313
if (this.attributes[i].namespaceURI == namespace && this.attributes[i].localName == localName) {
286314
return true;
@@ -289,7 +317,7 @@ export class XNode {
289317
return false;
290318
}
291319

292-
removeAttribute(name) {
320+
removeAttribute(name: any) {
293321
const a = [];
294322
for (let i = 0; i < this.attributes.length; ++i) {
295323
if (this.attributes[i].nodeName != name) {
@@ -299,7 +327,7 @@ export class XNode {
299327
this.attributes = a;
300328
}
301329

302-
removeAttributeNS(namespace, localName) {
330+
removeAttributeNS(namespace: any, localName: any) {
303331
const a = [];
304332
for (let i = 0; i < this.attributes.length; ++i) {
305333
if (this.attributes[i].localName != localName || this.attributes[i].namespaceURI != namespace) {
@@ -309,13 +337,13 @@ export class XNode {
309337
this.attributes = a;
310338
}
311339

312-
getElementsByTagName(name) {
340+
getElementsByTagName(name: any) {
313341
const ret = [];
314342
const self = this;
315343
if ('*' == name) {
316344
domTraverseElements(
317345
this,
318-
(node) => {
346+
(node: any) => {
319347
if (self == node) return;
320348
ret.push(node);
321349
},
@@ -324,7 +352,7 @@ export class XNode {
324352
} else {
325353
domTraverseElements(
326354
this,
327-
(node) => {
355+
(node: any) => {
328356
if (self == node) return;
329357
if (node.nodeName == name) {
330358
ret.push(node);
@@ -336,13 +364,13 @@ export class XNode {
336364
return ret;
337365
}
338366

339-
getElementsByTagNameNS(namespace, localName) {
367+
getElementsByTagNameNS(namespace: any, localName: any) {
340368
const ret = [];
341369
const self = this;
342370
if ('*' == namespace && '*' == localName) {
343371
domTraverseElements(
344372
this,
345-
(node) => {
373+
(node: any) => {
346374
if (self == node) return;
347375
ret.push(node);
348376
},
@@ -351,7 +379,7 @@ export class XNode {
351379
} else if ('*' == namespace) {
352380
domTraverseElements(
353381
this,
354-
(node) => {
382+
(node: any) => {
355383
if (self == node) return;
356384
if (node.localName == localName) ret.push(node);
357385
},
@@ -360,7 +388,7 @@ export class XNode {
360388
} else if ('*' == localName) {
361389
domTraverseElements(
362390
this,
363-
(node) => {
391+
(node: any) => {
364392
if (self == node) return;
365393
if (node.namespaceURI == namespace) ret.push(node);
366394
},
@@ -369,7 +397,7 @@ export class XNode {
369397
} else {
370398
domTraverseElements(
371399
this,
372-
(node) => {
400+
(node: any) => {
373401
if (self == node) return;
374402
if (node.localName == localName && node.namespaceURI == namespace) {
375403
ret.push(node);
@@ -381,11 +409,11 @@ export class XNode {
381409
return ret;
382410
}
383411

384-
getElementById(id): any {
412+
getElementById(id: any): any {
385413
let ret = null;
386414
domTraverseElements(
387415
this,
388-
(node) => {
416+
(node: any) => {
389417
if (node.getAttribute('id') == id) {
390418
ret = node;
391419
return false;

0 commit comments

Comments
 (0)