javascript - template - web components
¿Cómo crear un sub documento de navegador con iframe o shadow dom? (2)
Quiero crear un sub-documento totalmente encapsulado en JavaScript, con sus propios <head>
, <body>
, styles, html y js. Básicamente, un dom de sombra, o un iframe, pero sin un atributo src.
Aunque me encanta la idea de la sombra, su soporte es muy bajo y , por lo tanto, no está listo para el horario de máxima audiencia.
Así que he estado trabajando en la creación de un iframe, pero he estado golpeando varios obstáculos en el camino. Aquí hay un jsFiddle demostrando mis varios intentos.
El iframe no puede existir en el dom. Esta parte es crítica. Para aclarar, está bien si existe momentáneamente en el dominio, pero debe poder extraerse y existir solo en JS.
$(''body'').append(''<iframe id="iframeGenerator" />'');
var iframe3 = $(''#iframeGenerator'');
var iframe3Contents = iframe3.contents();
$(''#iframeGenerator'').remove();
var head = iframe3.contents().find(''head'');
dulce, tenemos la cabeza
console.log(head.length);
¿Pero qué aspecto tienen los contenidos?
console.log(iframe3Contents.get(0));
Es un documento, pero no dentro de un elemento, ¿así que intentemos ponerlo en el dom o dentro de otro elemento? Los dos intentos siguientes no funcionan porque el selector no tiene contexto o algo ...
$(''body'').append(iframe3Contents);
var generatedIframe = $(''<iframe />'').append(iframe3Contents);
Me encantaría poder crear el iframe / subdocuemnt sin añadir nada a los dom ... pero si debo, todavía me gustaría poder eliminarlo posteriormente del dom y administrarlo más en js.
Tengo esta pequeña función, que no funciona, pero ilustra el tipo de iframe o generador de subdocumentos que me gustaría crear
var iframeHtml;
giveMeIframe = function() {
var iframeContents;
if (iframeHtml) {
return iframeHtml;
} else {
$(''body'').append(''<iframe id="iframeGenerator" style="display: none" />'');
iframeContents = $(''#iframeGenerator'').contents();
iframeHtml = $(''<iframe />'');
iframeHtml.append(iframeContents);
$(''#iframeGenerator'').remove();
return iframeHtml;
}
}
Jugué con tu violín y pude hacerlo funcionar. Estoy usando seamless (solo Chrome) para que se comporte más en línea con lo que estás buscando y tengo un respaldo de CSS para otros navegadores.
Como nota, el iframe debe agregarse al DOM antes de comenzar a editar su contenido (agregando estilos y cuerpo). Puede eliminar después document.body.removeChild(iframe);
.
Todavía hay mucho que puedes hacer para que se comporte de manera muy similar a un elemento DOM de sombra, esta presentación te ayudará a hacer iframes sin problemas: ¡El futuro, hoy!
JS
var styles = ''<style> .pink { color: pink; width: 100px; height: 100px; } body{background-color:#eee;}</style>'';
var html = ''<div class="pink">PINK!</div>'';
// create iframe
var iframe = document.createElement(''iframe'');
document.body.appendChild(iframe);
//add head and body
iframe.contentDocument.open();
iframe.contentDocument.write(styles);
iframe.contentDocument.write(html);
iframe.contentDocument.close();
iframe.setAttribute(''seamless'', ''seamless'');
//check everything
console.log(iframe);
var head = $(iframe).contents().find(''head'')[0];
console.log(head);
var body = $(iframe).contents().find(''body'')[0];
console.log(body);
//remove from DOM
//document.body.removeChild(iframe);
CSS
iframe[seamless]{
background-color: transparent;
border: 0px none transparent;
padding: 0px;
overflow: hidden;
}
Para acceder a la información desde el marco (o escribir en el marco), debe estar en el DOM. Puede estar oculto, pero aún debe vivir en el objeto de marcos. JQuery está accediendo al iFrame a través del objeto de marcos y cuando se elimina del dominio, se elimina del objeto de marcos
Para referencia futura a cualquiera que se encuentre con esta pregunta, puede obtener la encapsulación así:
$(''#iframeGenerator2'').contents().find(''html'').html(frame2HTML);
Aquí hay un ejemplo: http://jsfiddle.net/yP34y/4/
En el ejemplo de jsfiddle, observe que todo solo funciona después de que se haya agregado al DOM.