Especificar el contenido de un iframe en lugar del atributo src de una página

88

Actualmente estoy trabajando en un formulario que incluye algunas entradas de archivo para cargar imágenes. Hay un onchange()evento para esas entradas que envía las imágenes a un iframe, luego carga dinámicamente las imágenes cargadas en el formulario, con campos para ser modificados para ellos (como nombre y geolocalización ).

Como no puedo anidar formularios, file_inputtambién está contenido en un iframe. Al final uso un iframeinterior de otro iframe. Entonces tengo algo como esto:

<form>
<!-- LOTS OF FIELDS!! -->
<iframe src="file_input_url">
<!-- iframe which loads a page of a form with a file input-->
</iframe>
</form>

y el HTML cargado en iframees algo así como (excluyendo las etiquetas html, heady body)

<form target="upload_iframe">
<input type="file" onchange="this.form.submit()">
</form>
<iframe name="upload_iframe"></iframe>

Esto funciona muy bien, excepto por el hecho de que toma un par de segundos cargar el primero iframe, por lo que la entrada del archivo no se carga con el resto de la página. Esto no es visualmente ideal. Podría resolverlo si pudiera especificar el iframecontenido sin necesidad de cargar otra página (especificada por file_input_urlen la primera iframe).

¿Hay alguna forma de especificar el iframecontenido en el mismo documento, o solo se puede especificar con el srcatributo, requiriendo la carga de otra página?

orlox
fuente
No debería tomar "un par de segundos" cargar ese iframe. Esperaría que fuera más como una décima de milisegundo más el "tiempo para morder" (que también debería ser milisegundos). Debería investigar qué está causando todo el retraso, probablemente algo mal con su servidor.
Abhi Beckert

Respuestas:

95

Puede .write()el contenido en el documento iframe. Ejemplo:

<iframe id="FileFrame" src="about:blank"></iframe>

<script type="text/javascript">
   var doc = document.getElementById('FileFrame').contentWindow.document;
   doc.open();
   doc.write('<html><head><title></title></head><body>Hello world.</body></html>');
   doc.close();
</script>
Guffa
fuente
1
Sin embargo, había pensado en esta posibilidad, el html que debe cargarse en el iframe es complejo, y manejarlo completamente en javascript para escribirlo en el iframe oscurecería demasiado la implementación (hasta el punto en que prefiero déjalo así).
orlox
2
@orlox: Obtenga su contenido del servidor usando Ajax e inyéctelo. Si no quiere ir por ese camino, cree un divelemento oculto con su contenido y coloque su contenido iframeentre <body>y </body>.
stackular
11
Cuanto más aprendo sobre las restricciones de iframes, más las odio
John Magnolia
1
¿Cómo puedo escapar de las comillas simples usando este método? Algunos de ellos son importantes para HTML (por ejemplo, clase = 'ejemplo'), algunos son importantes para CSS (por ejemplo, familia de fuentes: 'Verdana';) y algunos son contenido (por ejemplo, George O'Malley).
Dan Bechard
2
@Dan: para escapar de cualquier valor que se use en una cadena de JavaScript delimitada por apóstrofos, primero debe escapar de las barras diagonales inversas y luego de los apóstrofos. Por ejemplo, usando C # a la salida una cadena con el código: doc.write('<%= html.Replace("\\", "\\\\").Replace("'", "\\'") %>');.
Guffa
36

iframe ahora admite srcdoc, que se puede usar para especificar el contenido HTML de la página para mostrar en el marco en línea.

Ayush Gupta
fuente
2
IE no admite este derecho, pero puede verificar caniuse para conocer el estado más reciente.
Ayush Gupta
Documentación sobre MDN
Benoit Blanchon
22

Puede utilizar la data:URL en src:

var html = 'Hello from <img src="http://stackoverflow.com/favicon.ico" alt="SO">';
var iframe = document.querySelector('iframe');
iframe.src = 'data:text/html,' + encodeURIComponent(html);
<iframe></iframe>

Diferencia entre srcdoc = “…” y src = “data: text / html,…” en un iframe .

Convierta HTML a datos: enlace de texto / html usando JavaScript .

usuario
fuente
1
Ni siquiera necesita JavaScript: el srcatributo se puede especificar en línea si se escapa, por ejemplo, usando rawurlencodePHP:<iframe src="<?php echo htmlspecialchars('data:text/html,' . rawurlencode($content)); ?>"></iframe>
Jake
Microsoft agregó soporte para esto prácticamente al mismo tiempo que agregó soporte srcdoc, y srcdoces la mejor manera de hacerlo. Las URL de datos solo son ampliamente compatibles con imágenes y CSS; hasta donde yo sé, ninguna versión de Internet Explorer las admite en un iframe.
Abhi Beckert
6

En combinación con lo que describió Guffa, puede utilizar la técnica descrita en Explicación de <script type = "text / template"> ... </script> para almacenar el documento HTML en un scriptelemento especial (consulte el enlace para obtener una explicación sobre cómo funciona esto). Eso es mucho más fácil que almacenar el documento HTML en una cadena.

ximo
fuente
Pensándolo bien, eso no funcionaría muy bien para un documento HTML completo. Etiquetas tales como <html>, <body>, <script>sólo se confundirían el navegador, rompiendo la prestación del documento.
ximo
Eso no parece ser un problema, las etiquetas HTML dentro de los scripts se ignoran.
HBP
Tienes razón :) En realidad, todavía no había probado la técnica cuando escribí eso, y debo haber aprendido esa suposición de alguna parte. Más tarde descubrí que <script>el navegador ignoraría cualquier cosa dentro de una etiqueta. ¡Gracias por corregirme!
ximo