Inserindo javascript dinamicamente em HTML que usa document.write
-
09-06-2019 - |
Pergunta
No momento, estou carregando um pop-up estilo lightbox que carrega seu HTML a partir de uma chamada XHR.Este conteúdo é então exibido em um pop-up 'modal' usando element.innerHTML = content
Isso funciona perfeitamente.
Em outra seção deste site eu uso um 'emblema' do Flickr (http://www.elliotswan.com/2006/08/06/custom-flickr-badge-api-documentation/) para carregar imagens do flickr dinamicamente.Isso é feito incluindo uma tag de script que carrega um javascript do flickr, que por sua vez faz algumas document.write
declarações.
Ambos funcionam perfeitamente quando incluídos no HTML.Somente ao carregar o código do emblema do flickr dentro na lightbox, nenhum conteúdo é renderizado.Parece que usar innerHTML
escrever document.write
declarações está indo longe demais, mas não consigo encontrar nenhuma pista nas implementações javascript (FF2 e 3, IE6 e 7) desse comportamento.
Alguém pode esclarecer se isso deve ou não funcionar?Obrigado.
Solução
Em geral, as tags de script não são executadas ao usar innerHTML.No seu caso, isso é bom, porque o document.write
call eliminaria tudo o que já está na página.No entanto, isso deixa você sem qualquer HTML document.write que deveria adicionar.
Os métodos de manipulação de HTML do jQuery executarão scripts em HTML para você, o truque é então capturar as chamadas para document.write
e colocando o HTML no lugar apropriado.Se for bastante simples, algo assim servirá:
var content = '';
document.write = function(s) {
content += s;
};
// execute the script
$('#foo').html(markupWithScriptInIt);
$('#foo .whereverTheDocumentWriteContentGoes').html(content);
Mas fica complicado.Se o script estiver em outro domínio, ele será carregado de forma assíncrona, então você terá que esperar até terminar para obter o conteúdo.Além disso, e se ele apenas gravar o HTML no meio do fragmento sem um elemento wrapper que você possa selecionar facilmente? writeCapture.js (transparência completa:Eu escrevi) lida com todos esses problemas.Eu recomendo apenas usá-lo, mas pelo menos você pode olhar o código para ver como ele lida com tudo.
EDITAR:Aqui está um página demonstrando o que parece ser o efeito que você deseja.
Outras dicas
Criei uma página de teste simples que ilustra o problema:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Document Write Testcase</title>
</head>
<body>
<div id="container">
</div>
<div id="container2">
</div>
<script>
// This doesn't work!
var container = document.getElementById('container');
container.innerHTML = "<script type='text/javascript'>alert('foo');document.write('bar');<\/script>";
// This does!
var container2 = document.getElementById('container2');
var script = document.createElement("script");
script.type = 'text/javascript';
script.innerHTML = "alert('bar');document.write('foo');";
container.appendChild(script);
</script>
</body>
</html>
Esta página alerta 'bar' e imprime 'foo', enquanto eu esperava que ela também alertasse 'foo' e imprimisse 'bar'.Mas, infelizmente, desde o script
tag faz parte de uma página HTML maior, não posso destacar essa tag e anexá-la como no exemplo acima.Bem, eu posso, mas isso exigiria digitalização innerHTML
conteúdo para script
tags e substituindo-as na string por espaços reservados e, em seguida, inserindo-as usando o DOM.Parece que não que trivial.
Usar document.writeln(content);
em vez de document.write(content)
.
No entanto, o melhor método é usar a concatenação de innerHTML
, assim:
element.innerHTML += content;
O element.innerHTML = content;
método que substituirá o conteúdo antigo pelo novo, ele substituirá o innerHTML do seu elemento!
Considerando que o +=
operador em element.innerHTML += content;
irá adicionar seu texto após o conteúdo antigo.(como o que document.write
faz.)
document.write
é tão obsoleto quanto parece.Graças às maravilhas do JavaScript, você pode simplesmente atribuir sua própria função ao write
método do document
objeto que usa innerHTML
em um elemento de sua escolha para anexar o conteúdo fornecido.
Posso obter alguns esclarecimentos primeiro para ter certeza de que entendi o problema?
document.write
as chamadas adicionarão conteúdo à marcação no ponto da marcação em que ocorrem.Por exemplo, se você incluir document.write
chama uma função, mas chama a função em outro lugar, o document.write
a saída acontecerá no ponto da marcação em que a função está definiram não onde está chamado.
Portanto para que isso funcione em todo o Flickr document.write
declarações precisarão fazer parte do content
em element.innerHTML = content
.Este é definitivamente o caso?
Você pode testar rapidamente se isso deve funcionar adicionando um único e simples document.write
chame o conteúdo que está definido como o innerHTML
e veja o que isso faz:
<script>
var content = "<p>1st para</p><script>document.write('<p>2nd para</p>');</script>"
element.innerHTML = content;
</script>
Se isso funcionar, o conceito de document.write
trabalhando em conteúdo definido como o innerHTML
de um elemento pode simplesmente funcionar.
Meu pressentimento é que não funcionará, mas deve ser bastante simples testar o conceito.
Então você está usando um método DOM para criar um script
elemento e anexá-lo a um elemento existente e isso faz com que o conteúdo do elemento anexado script
elemento a ser executado?Isso soa bem.
Você diz que a tag script faz parte de uma página HTML maior e, portanto, não pode ser isolada.Você não pode fornecer um ID à tag do script e direcioná-la?Provavelmente estou perdendo algo óbvio aqui.
Em teoria, sim, posso destacar uma tag de script dessa forma.O problema é que potencialmente temos dezenas de situações em que isso ocorre, por isso estou tentando encontrar alguma causa ou documentação desse comportamento.
Também o script
tag não parece mais fazer parte do DOM depois de carregada.Em nosso ambiente, meu container
div permanece vazio, então não consigo buscar o script
marcação.Deve funcionar, porém, porque no meu exemplo acima o script não é executado, mas ainda faz parte do DOM.