Especificar o conteúdo de um iframe em vez do atributo src para uma página

88

Atualmente estou trabalhando em um formulário que inclui algumas entradas de arquivo para fazer upload de fotos. Há um onchange()evento para essas entradas que enviam as imagens para um e iframe, em seguida, carregam dinamicamente as imagens carregadas no formulário, com campos a serem modificados para elas (como nome e geolocalização ).

Como não consigo aninhar formulários, o file_inputtambém está contido em um iframe. No final, uso um iframedentro do outro iframe. Então, eu tenho algo assim:

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

eo HTML carregado no iframeé algo como (excluindo o html, heade bodyetiquetas)

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

Isso funciona muito bem, exceto pelo fato de que leva alguns segundos para carregar o primeiro iframe, de modo que a entrada do arquivo não carrega com o resto da página. Isso não é visualmente ideal. Eu poderia resolver isso se pudesse especificar o iframeconteúdo sem precisar carregar outra página (especificada por file_input_urlno primeiro iframe).

Existe uma maneira de especificar o iframeconteúdo no mesmo documento, ou ele só pode ser especificado com o srcatributo, exigindo o carregamento de outra página?

orlox
fonte
Não deve demorar "alguns segundos" para carregar esse iframe. Eu esperava que fosse mais como um décimo de milissegundo mais o "tempo para morder" (que também deve ser milissegundos). Você deve investigar o que está causando todo o lag - provavelmente algo errado com o seu servidor.
Abhi Beckert

Respostas:

95

Você pode .write()inserir o conteúdo no documento iframe. Exemplo:

<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
fonte
1
Se tivesse pensado nessa possibilidade, entretanto, o html que deve ser carregado no iframe é complexo, e manipulá-lo inteiramente em javascript para gravá-lo no iframe obscureceria muito a implementação (até o ponto que eu prefiro deixe como está).
orlox
2
@orlox: Obtenha seu conteúdo do servidor usando Ajax e injete-o. Se você não quiser ir por esse caminho, crie um divelemento oculto com seu conteúdo e coloque seu conteúdo iframeentre <body>e </body>.
empilhar de
11
Quanto mais aprendo sobre as restrições de iframes, mais os odeio
John Magnolia
1
Como faço para escapar de aspas simples usando este método? Alguns deles são importantes para o HTML (por exemplo, class = 'exemplo'), alguns são importantes para o CSS (por exemplo, font-family: 'Verdana';) e alguns são de conteúdo (por exemplo, George O'Malley).
Dan Bechard
2
@Dan: para escapar qualquer valor a ser usado em uma string JavaScript delimitada por apóstrofo, primeiro você deve escapar as barras invertidas e depois os apóstrofos. Por exemplo, utilizando C # para mostrar uma string no código: doc.write('<%= html.Replace("\\", "\\\\").Replace("'", "\\'") %>');.
Guffa
36

O iframe agora oferece suporte a srcdoc, que pode ser usado para especificar o conteúdo HTML da página a ser exibida no quadro embutido.

Ayush Gupta
fonte
2
O IE não oferece suporte para esse direito, mas você pode verificar o caniuse para obter o status mais recente dele.
Ayush Gupta
Documentação em MDN
Benoit Blanchon
22

Você pode usar o data:URL no 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>

Diferença entre srcdoc = “…” e src = “data: text / html,…” em um iframe .

Converter HTML em dados: link de texto / html usando JavaScript .

do utilizador
fonte
1
Você nem precisa de nenhum JavaScript: o srcatributo pode ser especificado inline se escapado, por exemplo, usando rawurlencodeem PHP:<iframe src="<?php echo htmlspecialchars('data:text/html,' . rawurlencode($content)); ?>"></iframe>
Jake
A Microsoft adicionou suporte para isso praticamente ao mesmo tempo em que adicionou suporte para srcdoc, e srcdocé a melhor maneira de fazer isso. URLs de dados são amplamente suportados apenas para imagens e CSS - pelo que eu sei, nenhuma versão do Internet Explorer oferece suporte para eles em um iframe.
Abhi Beckert
6

Em combinação com o que Guffa descreveu, você poderia usar a técnica descrita em Explicação de <script type = "text / template"> ... </script> para armazenar o documento HTML em um scriptelemento especial (veja o link para uma explicação sobre como isso funciona). Isso é muito mais fácil do que armazenar o documento HTML em uma string.

ximo
fonte
Pensando bem, isso não funcionaria muito bem para um documento HTML completo. Tags como <html>, <body>, <script>só iria confundir o navegador, quebrando a prestação do documento.
ximo
Isso não parece ser um problema, as tags HTML dentro dos scripts são ignoradas.
HBP
Você está certo :) Na verdade, eu ainda não tinha tentado a técnica quando escrevi isso e devo ter percebido essa suposição de algum lugar. Mais tarde, descobri que qualquer coisa dentro de uma <script>tag seria ignorada pelo navegador. Obrigado por me corrigir!
ximo,