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

webcomponents-lite.js does not polyfill importNode/cloneNode for Template #362

Closed
kevinpschaaf opened this issue Jul 27, 2015 · 4 comments
Closed
Assignees

Comments

@kevinpschaaf
Copy link
Contributor

Calling document.importNode(template, true) on a template on IE will not result in the template content being cloned as it should. Likewise, calling document.importNode(fragContainingTemplate, true) on a document fragment containing a nested template will not result in that template's content being cloned either.

Note Safari has a bug in their native Template implementation that manifests itself in basically the same way (nested template content is empty, see https://bugs.webkit.org/show_bug.cgi?id=137619) which could benefit from the same polyfill implementation. Note the Safari bug has been resolved in Webkit nightly but has not yet shipped in a stable version of Safari on Mac or iOS.

@gertcuykens
Copy link

(0.7.17) Although webcomponentsjs is working, just want to point out that webcomponents-lite.js is still not working for IE11

@reekoheek
Copy link

(0.7.20) polyfill template. after decorate template with inner template then doing importNode(template, true), the inner template not cloned as it should (empty template).

<template id="t">
  outer template content
  <template id="inner-t">
    inner template content
  </template>
</template>

<script>
HTMLTemplateElement.decorate(t);
console.log('template content clone');
var cloned = document.importNode(t.content, true);
console.log('t.content innerHTML: ' + t.content.querySelector('#inner-t').innerHTML);
console.log('t.content content  : ' + t.content.querySelector('#inner-t').content.childNodes.length);
console.log('cloned    innerHTML: ' + cloned.querySelector('#inner-t').innerHTML);
console.log('cloned    content  : ' + cloned.querySelector('#inner-t').content.childNodes.length);
</script>

@IceCreamYou
Copy link

Confirming this - although I think the cause of the problem is not quite as previously described.

Neither template.js nor webcomponents-lite.js can run document.importNode on templates without errors, but the full webcomponents.js does work. A minimal test case is:

<!DOCTYPE html>
<html>
<head>
    <title>Testing web components</title>
</head>
<body>
    <!-- Also try https://rawgit.com/webcomponents/webcomponentsjs/v0.7.22/webcomponents-lite.js or https://rawgit.com/webcomponents/webcomponentsjs/master/src/Template/Template.js -->
    <script src="https://rawgit.com/webcomponents/webcomponentsjs/v0.7.22/webcomponents.js"></script>
    <template id="template">
        <div>
            <p style="color: red;">Hello, world!</p>
        </div>
    </template>
    <script>
var template = document.getElementById('template').content,
    clone = document.importNode(template, true), // throws error unless using all polyfills
    wrapper = document.createElement('div');
wrapper.id = 'clone';
wrapper.appendChild(clone);
document.body.appendChild(wrapper);
console.log(document.getElementById('clone'));
    </script>
</body>
</html>

The error that this produces in IE 11 for webcomponents-lite.min.js v0.7.22 looks something like:

Unable to get property 'localName' of undefined or null reference (11, 16405)

That error happens in document.importNode(). However, it implies that the issue is not actually with importing the node but rather with turning the template into a usable DocumentFragment. This can be tested by running this code in a context that has webcomponents.js vs. webcomponents-lite.js:

var f = document.createDocumentFragment();
f.appendChild(document.createElement('div');
console.log(f.children.length);

With webcomponents.js, this will return 1. With webcomponents-lite.js, this will throw an error in IE 11: Unable to get property 'length' of undefined or null reference. That's because DocumentFragments are crippled in IE 11.

Here is a workaround to get templates working in IE 11. It does not provide a polyfill; instead it provides a function, cloneTemplate, that accepts a <template> element and returns a DocumentFragment containing a clone of the template's contents. This does not rely on any part of webcomponents.js, but it does require a CSS style to hide template elements (included below).

<!DOCTYPE html>
<html>
<head>
    <title>Testing web components</title>
    <style>template { display: none; }</style>
</head>
<body>
    <template id="template">
        <div>
            <p style="color: red;">Hello, world!</p>
        </div>
    </template>
    <script>
function cloneTemplate(templateElement) {
    try {
        return document.importNode(templateElement.content, true);
    }
    catch (e) {
        var wrapper = document.createElement('div'),
            fragment = document.createDocumentFragment();
        wrapper.innerHTML = templateElement.innerHTML;
        while (wrapper.firstChild) {
            var child = wrapper.removeChild(wrapper.firstChild);
            fragment.appendChild(child);
        }
        return fragment;
    }
}

var template = document.getElementById('template'),
    clone = cloneTemplate(template),
    wrapper = document.createElement('div');
wrapper.id = 'clone';
wrapper.appendChild(clone);
document.body.appendChild(wrapper);
console.log(document.getElementById('clone'));
    </script>
</body>
</html>

@kevinpschaaf
Copy link
Contributor Author

This was solved in #489 and looks like the issue wasn't closed (current code implementation is located at https://github.com/webcomponents/template/blob/master/template.js#L266-L276).

Any issues with <template>s not having their content created using recent releases is likely due to code querying for templates in the main document prior to DOMContentLoaded, which is when the template polyfill finds and upgrades templates: https://github.com/webcomponents/template/blob/master/template.js#L161-L163. Please file as a separate issue if so.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants