|
11 | 11 | // minimal template polyfill |
12 | 12 | (function() { |
13 | 13 | var needsTemplate = (typeof HTMLTemplateElement === 'undefined'); |
| 14 | + // NOTE: Patch document.importNode to work around IE11 bug that |
| 15 | + // casues children of a document fragment imported while |
| 16 | + // there is a mutation observer to not have a parentNode (!?!) |
| 17 | + // This needs to happen *after* patching importNode to fix template cloning |
| 18 | + if (/Trident/.test(navigator.userAgent)) { |
| 19 | + (function() { |
| 20 | + var importNode = document.importNode; |
| 21 | + document.importNode = function() { |
| 22 | + var n = importNode.apply(document, arguments); |
| 23 | + // Copy all children to a new document fragment since |
| 24 | + // this one may be broken |
| 25 | + if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { |
| 26 | + var f = document.createDocumentFragment(); |
| 27 | + f.appendChild(n); |
| 28 | + return f; |
| 29 | + } else { |
| 30 | + return n; |
| 31 | + } |
| 32 | + }; |
| 33 | + })(); |
| 34 | + } |
14 | 35 |
|
15 | | - // returns true if nested templates can be cloned (they cannot be on |
| 36 | + // returns true if nested templates cannot be cloned (they cannot be on |
16 | 37 | // some impl's like Safari 8) |
17 | 38 | var needsCloning = (function() { |
18 | 39 | if (!needsTemplate) { |
19 | | - var frag = document.createDocumentFragment(); |
20 | 40 | var t = document.createElement('template'); |
21 | | - frag.appendChild(t); |
22 | | - t.content.appendChild(document.createElement('div')); |
23 | | - var clone = frag.cloneNode(true); |
24 | | - return (clone.firstChild.content.childNodes.length === 0); |
| 41 | + var t2 = document.createElement('template'); |
| 42 | + t2.content.appendChild(document.createElement('div')); |
| 43 | + t.content.appendChild(t2); |
| 44 | + var clone = t.cloneNode(true); |
| 45 | + return (clone.content.childNodes.length === 0 || clone.content.firstChild.content.childNodes.length === 0); |
25 | 46 | } |
26 | 47 | })(); |
27 | 48 |
|
|
42 | 63 | /** |
43 | 64 | Provides a minimal shim for the <template> element. |
44 | 65 | */ |
45 | | - |
46 | 66 | TemplateImpl.prototype = Object.create(HTMLElement.prototype); |
47 | 67 |
|
48 | 68 | /** |
|
59 | 79 | while (child = template.firstChild) { |
60 | 80 | template.content.appendChild(child); |
61 | 81 | } |
| 82 | + |
| 83 | + template.cloneNode = function(deep) { |
| 84 | + return TemplateImpl.cloneNode(this, deep); |
| 85 | + }; |
| 86 | + |
62 | 87 | // add innerHTML to template, if possible |
63 | 88 | // Note: this throws on Safari 7 |
64 | 89 | if (canDecorate) { |
|
84 | 109 | configurable: true |
85 | 110 | }); |
86 | 111 |
|
87 | | - template.cloneNode = function(deep) { |
88 | | - return TemplateImpl.cloneNode(this, deep); |
89 | | - }; |
90 | | - |
91 | 112 | } catch (err) { |
92 | 113 | canDecorate = false; |
93 | 114 | } |
|
117 | 138 | document.createElement = function() { |
118 | 139 | 'use strict'; |
119 | 140 | var el = createElement.apply(document, arguments); |
120 | | - if (el.localName == 'template') { |
| 141 | + if (el.localName === 'template') { |
121 | 142 | TemplateImpl.decorate(el); |
122 | 143 | } |
123 | 144 | return el; |
|
152 | 173 | var nativeCloneNode = Node.prototype.cloneNode; |
153 | 174 |
|
154 | 175 | TemplateImpl.cloneNode = function(template, deep) { |
155 | | - var clone = nativeCloneNode.call(template); |
| 176 | + var clone = nativeCloneNode.call(template, false); |
156 | 177 | // NOTE: decorate doesn't auto-fix children because they are already |
157 | 178 | // decorated so they need special clone fixup. |
158 | 179 | if (this.decorate) { |
|
169 | 190 | return clone; |
170 | 191 | }; |
171 | 192 |
|
172 | | - // Given a source and cloned subtree, find <template>'s in the cloned |
| 193 | + // Given a source and cloned subtree, find <template>'s in the cloned |
173 | 194 | // subtree and replace them with cloned <template>'s from source. |
174 | 195 | // We must do this because only the source templates have proper .content. |
175 | 196 | TemplateImpl.fixClonedDom = function(clone, source) { |
|
203 | 224 |
|
204 | 225 | // NOTE: we are cloning instead of importing <template>'s. |
205 | 226 | // However, the ownerDocument of the cloned template will be correct! |
206 | | - // This is because the native import node creates the right document owned |
| 227 | + // This is because the native import node creates the right document owned |
207 | 228 | // subtree and `fixClonedDom` inserts cloned templates into this subtree, |
208 | 229 | // thus updating the owner doc. |
209 | 230 | document.importNode = function(element, deep) { |
|
223 | 244 | return TemplateImpl.cloneNode(this, deep); |
224 | 245 | }; |
225 | 246 | } |
226 | | - |
227 | 247 | } |
228 | 248 |
|
229 | 249 | if (needsTemplate) { |
|
0 commit comments