I\'m looking for the most standards-compliant / future-proof method for front-end HTML templating.
There exists a relatively new W3C draft specification for HTML Tem
There is a jsfiddle that demonstrates such a polyfill.
<script>
// Shim so we can style in IE6/7/8
document.createElement('template');
</script>
<template id="example">
<h1>
This is template content.
</h1>
<p>
It's really great.
</p>
</template>
<div id="target">
<p>
This is regular old content.
</p>
</div>
/* POLYFILL */
(function templatePolyfill(d) {
if('content' in d.createElement('template')) {
return false;
}
var qPlates = d.getElementsByTagName('template'),
plateLen = qPlates.length,
elPlate,
qContent,
contentLen,
docContent;
for(var x=0; x<plateLen; ++x) {
elPlate = qPlates[x];
qContent = elPlate.childNodes;
contentLen = qContent.length;
docContent = d.createDocumentFragment();
while(qContent[0]) {
docContent.appendChild(qContent[0]);
}
elPlate.content = docContent;
}
})(document);
/* EXAMPLE */
var elExample = document.getElementById('example'),
elTarget = document.getElementById('target');
elTarget.appendChild(elExample.content.cloneNode(true));
As for libraries, and I don't know that they support it yet, but try something like Modernizr and Initializr
Another possibility are the Web Components polyfills, which include a polyfill for the <template>
tag. Keep in mind that webcomponents.js includes polyfills for more than just the <template>
tag though.
Xotic750 offered a solid polyfill that works by mutating HTML elements — but it will fail if any new templates are later added to the DOM, and mutation is increasingly discouraged (where avoidable).
Instead, I recommend introducing the "polyfill" behaviour at the point where you use the templates. Add this function to your JS:
function templateContent(template) {
if("content" in document.createElement("template")) {
return document.importNode(template.content, true);
} else {
var fragment = document.createDocumentFragment();
var children = template.childNodes;
for (i = 0; i < children.length; i++) {
fragment.appendChild(children[i].cloneNode(true));
}
return fragment;
}
}
Call the function with a reference to your template element. It'll extract the content, and return a documentFragment that you can then attach to another element (or do whatever else you might want to do with the template content). Like this:
var template = document.querySelector("template#my-template");
var content = templateContent(template);
someElm.appendChild(content);
Now, the other answer didn't mention it, but you probably want some CSS to hide the <template>
element.
template { display: none; }
Here's a CodePen that puts it all together.
Now, this will work correctly in browsers that natively support the <template>
element, and in those that don't. Similar to the other answer, it's not a perfect polyfill, since it doesn't render templates inert (that'd be complex, slow, and error-prone). But it works well enough for me to use in production.
Leave a comment if you've got questions or issues, and I'll revise accordingly.
Yet another possibility is Neovov's Template-Element-Polyfill.
It's a dedicated <template>
polyfill that you can find on Github.