Skip to content
This repository was archived by the owner on Sep 20, 2019. It is now read-only.

Commit 1782720

Browse files
author
Steven Orvell
committed
Fix cloneNode/importNode for dom that contains templates.
1 parent 3ff9cdc commit 1782720

File tree

2 files changed

+85
-13
lines changed

2 files changed

+85
-13
lines changed

src/Template/Template.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,25 +85,43 @@ if (typeof HTMLTemplateElement === 'undefined') {
8585
clone.content.appendChild(
8686
nativeCloneNode.call(template.content, true));
8787
// these two lists should be coincident
88-
var s$ = template.content.querySelectorAll(TEMPLATE_TAG);
89-
var t$ = clone.content.querySelectorAll(TEMPLATE_TAG);
90-
for (var i=0, l=t$.length, t, s; i<l; i++) {
91-
s = s$[i];
92-
t = t$[i];
93-
this.decorate(s);
94-
t.parentNode.replaceChild(s.cloneNode(true), t);
95-
}
88+
this.fixClonedDom(clone.content, template.content);
9689
}
9790
return clone;
9891
};
9992

93+
HTMLTemplateElement.fixClonedDom = function(clone, source) {
94+
var s$ = source.querySelectorAll(TEMPLATE_TAG);
95+
var t$ = clone.querySelectorAll(TEMPLATE_TAG);
96+
for (var i=0, l=t$.length, t, s; i<l; i++) {
97+
s = s$[i];
98+
t = t$[i];
99+
this.decorate(s);
100+
t.parentNode.replaceChild(s.cloneNode(true), t);
101+
}
102+
};
103+
100104
var originalImportNode = document.importNode;
101105

106+
Node.prototype.cloneNode = function(deep) {
107+
var dom = nativeCloneNode.call(this, deep);
108+
if (deep) {
109+
HTMLTemplateElement.fixClonedDom(dom, this);
110+
}
111+
return dom;
112+
};
113+
102114
// clone instead of importing <template>
103115
document.importNode = function(element, deep) {
104-
return (element.localName === TEMPLATE_TAG) ?
105-
HTMLTemplateElement.cloneNode(element, deep) :
106-
originalImportNode.call(document, element, deep);
116+
if (element.localName === TEMPLATE_TAG) {
117+
return HTMLTemplateElement.cloneNode(element, deep);
118+
} else {
119+
var dom = originalImportNode.call(document, element, deep);
120+
if (deep) {
121+
HTMLTemplateElement.fixClonedDom(dom, element);
122+
}
123+
return dom;
124+
}
107125
};
108126

109127
/**

tests/Template/tests.html

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
'cloned content is not different from source');
8181
});
8282

83-
test('nested clone', function() {
83+
test('clone nested', function() {
8484
var imp = document.createElement('template');
8585
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
8686
imp.innerHTML = s;
@@ -108,6 +108,33 @@
108108
'deep cloned template.content is empty');
109109
});
110110

111+
test('clone node containing templates', function() {
112+
var imp = document.createElement('div');
113+
var t = document.createElement('template');
114+
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
115+
t.innerHTML = s;
116+
imp.appendChild(t);
117+
var impClone = imp.cloneNode(true);
118+
var imp = imp.firstChild;
119+
var deepClone = impClone.firstChild;
120+
assert.equal(deepClone.content.childNodes.length, 2,
121+
'deep cloned template.content is empty');
122+
assert.notEqual(imp.content.firstChild, deepClone.content.firstChild,
123+
'cloned content is not different from source');
124+
var nested = deepClone.content.lastChild;
125+
assert.isDefined(nested.content, 'nested cloned template content dne');
126+
assert.equal(nested.content.childNodes.length, 2,
127+
'deep cloned template.content is empty');
128+
nested = nested.content.lastChild;
129+
assert.isDefined(nested, 'nested cloned template content dne');
130+
assert.equal(nested.content.childNodes.length, 2,
131+
'deep cloned template.content is empty');
132+
nested = nested.content.lastChild;
133+
assert.isDefined(nested, 'nested cloned template content dne');
134+
assert.equal(nested.content.childNodes.length, 1,
135+
'deep cloned template.content is empty');
136+
});
137+
111138
test('importNode', function() {
112139
var imp = document.createElement('template');
113140
var s = '<div>Hi</div>';
@@ -124,7 +151,7 @@
124151
'cloned content is not different from source');
125152
});
126153

127-
test('nested importNode', function() {
154+
test('importNode: nested', function() {
128155
var imp = document.createElement('template');
129156
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
130157
imp.innerHTML = s;
@@ -152,6 +179,33 @@
152179
'deep cloned template.content is empty');
153180
});
154181

182+
test('importNode: element containing nested templates', function() {
183+
var imp = document.createElement('div');
184+
var t = document.createElement('template');
185+
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
186+
t.innerHTML = s;
187+
imp.appendChild(t);
188+
var impClone = document.importNode(imp, true);
189+
imp = imp.firstChild;
190+
var deepClone = impClone.firstChild;
191+
assert.equal(deepClone.content.childNodes.length, 2,
192+
'deep cloned template.content is empty');
193+
assert.notEqual(imp.content.firstChild, deepClone.content.firstChild,
194+
'cloned content is not different from source');
195+
var nested = deepClone.content.lastChild;
196+
assert.isDefined(nested.content, 'nested cloned template content dne');
197+
assert.equal(nested.content.childNodes.length, 2,
198+
'deep cloned template.content is empty');
199+
nested = nested.content.lastChild;
200+
assert.isDefined(nested, 'nested cloned template content dne');
201+
assert.equal(nested.content.childNodes.length, 2,
202+
'deep cloned template.content is empty');
203+
nested = nested.content.lastChild;
204+
assert.isDefined(nested, 'nested cloned template content dne');
205+
assert.equal(nested.content.childNodes.length, 1,
206+
'deep cloned template.content is empty');
207+
});
208+
155209
});
156210
</script>
157211
</body>

0 commit comments

Comments
 (0)