polyfill - Plantillas HTML JavaScript polifills
polyfill material (4)
Estoy buscando el método más compatible con los estándares / a prueba de futuro para las plantillas HTML front-end.
Existe una especificación de borrador W3C relativamente nueva para plantillas HTML , por ejemplo:
<template id="mytemplate">
<img src="" alt="great image">
<div class="comment"></div>
</template>
¿Alguien sabe si ya existe algún buen relleno de JavaScript para hacer que el elemento <template>
pueda utilizarse de forma cruzada en el navegador? Preferiblemente cumpliendo con esta norma.
Dificultades
De acuerdo con la guía de HTML5Rocks, estas plantillas tienen las siguientes propiedades:
- "Su contenido es efectivamente inerte hasta que se activa".
- "El script no se ejecuta, las imágenes no se cargan, el audio no se reproduce"
- "Se considera que el contenido no está en el documento"
- "Las plantillas se pueden colocar en cualquier lugar dentro de
<head>
,<body>
o<frameset>
"
Creo que es imposible implementar estas cuatro propiedades solo con un polyfill de JavaScript, por lo que cualquier solución solo sería parcial.
Hay un jsfiddle que demuestra tal 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));
En cuanto a las bibliotecas, y aún no sé si lo admiten, pero intente algo como Modernizr e Initializr
Otra posibilidad más es la Template-Element-Polyfill .
Es un polyfill dedicado <template>
que puedes encontrar en Github.
Otra posibilidad son los polyfills de componentes web , que incluyen un polyfill para la etiqueta <template>
. Tenga en cuenta que webcomponents.js incluye polyfills para más que solo la etiqueta <template>
.
Xotic750 ofreció un polyfill sólido que funciona mediante la mutación de elementos HTML, pero fallará si posteriormente se agregan nuevas plantillas al DOM, y se desaconseja cada vez más la mutación (cuando sea posible).
En su lugar, recomiendo introducir el comportamiento "polyfill" en el punto en el que utiliza las plantillas. Agrega esta función a tu 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;
}
}
Llame a la función con una referencia a su elemento de plantilla. Extraerá el contenido y devolverá un DocumentFragment que luego podrá adjuntar a otro elemento (o hacer cualquier otra cosa que desee hacer con el contenido de la plantilla). Me gusta esto:
var template = document.querySelector("template#my-template");
var content = templateContent(template);
someElm.appendChild(content);
Ahora, la otra respuesta no lo mencionó, pero es probable que desee algo de CSS para ocultar el elemento <template>
.
template { display: none; }
Aquí hay un CodePen que lo pone todo junto.
Ahora, esto funcionará correctamente en los navegadores que admiten de forma nativa el elemento <template>
, y en aquellos que no lo hacen. Similar a la otra respuesta, no es un polyfill perfecto, ya que no hace que las plantillas sean inertes (eso sería complejo, lento y propenso a errores). Pero funciona lo suficientemente bien como para que yo lo use en producción.
Deje un comentario si tiene preguntas o problemas, y los revisaré en consecuencia.