Shadow DOM & Templates
by mgiuffrida
HTML
<template id="simpleTemplate">
<h1>Template Header</h1>
<p>Lorem ipsum dolor sit amet.</p>
</template>
<template id="wcTemplate">
<h1>
Header A
</h1>
<x-foo>
This is the x-foo in the template.
</x-foo>
</template>
<x-foo>This is the x-foo in the main document.</x-foo>
JavaScript
// Tested with Chrome and FF. In FF, enable dom.webcomponents in about:config.
// Some setup.
function assert(x) {
if (x) return;
console.trace();
throw Error(x);
}
function assertUndefined(x) {
assert(x === undefined);
}
console.clear();
// document.createElement(foo) --> foo.ownerDocument === document
// importNode https://dom.spec.whatwg.org/#dom-document-importnode
//
// DocumentFragment (https://dom.spec.whatwg.org/#documentfragment)
//
// The DocumentFragment interface, like Document and Element, extends the Node interface.
// It is not an Element.
var fragment = new DocumentFragment();
assert(fragment.nodeName == '#document-fragment');
assertUndefined(fragment.tagName);
assertUndefined(fragment.id);
assertUndefined(fragment.innerHTML);
assert(fragment.ownerDocument == document);
assert(fragment.parentNode === null);
//
// HTMLTemplateElement
//
// <template> creates a template element. Templates are never rendered.
var tmpl = document.querySelector('template#simpleTemplate');
assert(tmpl instanceof HTMLTemplateElement);
// At first glance, templates are like any other HTMLElement.
assert(tmpl.tagName == 'TEMPLATE');
assert(tmpl.innerHTML.includes('<h1>Template Header</h1>'));
// Templates have a read-only DocumentFragment property, 'content'.
assert(tmpl.content instanceof DocumentFragment);
assert(tmpl.content.nodeName == '#document-fragment');
assert(!tmpl.content.tagName && !tmpl.content.id && !tmpl.content.innerHTML);
// It is a standalone node? associated with a separate Document.
assert(tmpl.ownerDocument === document);
assert(tmpl.content.ownerDocument != document);
assert(tmpl.content.parentNode === null);
var XFoo = document.registerElement('x-foo', {
prototype: {
__proto__: HTMLElement.prototype,
createdCallback: function() {
this._created = true;
},
}
});
// Element is created immediately.
assert(document.querySelector('x-foo')._created)
var wcTmpl =...