ti-enxame.com

Como você executa um bloco JavaScript carregado dinamicamente?

Estou trabalhando em uma página da web em que estou fazendo uma chamada AJAX que retorna um pedaço de HTML como:

<div>
  <!-- some html -->
  <script type="text/javascript">
    /** some javascript */
  </script>
</div>

Estou inserindo a coisa toda no DOM, mas o JavaScript não está sendo executado. Existe uma maneira de executá-lo?

Alguns detalhes: não consigo controlar o que está no bloco de scripts (então não posso alterá-lo para uma função que possa ser chamada), só preciso que todo o bloco seja executado. Não posso chamar eval na resposta porque o JavaScript está dentro de um bloco maior de HTML. Eu poderia fazer algum tipo de regex para separar o JavaScript e depois chamar eval, mas isso é muito nojento. Alguém sabe uma maneira melhor?

38
kristina

O script adicionado ao definir a propriedade innerHTML de um elemento não é executado. Tente criar uma nova div, definindo seu innerHTML e adicionando essa nova div ao DOM. Por exemplo:

 <html> 
 <head> 
 <tipo de script = 'text/javascript'> 
 função addScript () 
 {
 var str = "<script> alerta ('eu estou aqui'); <\/script>"; 
 var newdiv = document.createElement ('div'); 
 newdiv.innerHTML = str; 
 document.getElementById ('target'). appendChild (newdiv); 
} 
 </script> 
 </head> 
 <body> 
 <input type = "button" value = "adicionar script" onclick = "addScript ()" />
 <div> olá mundo </div> 
 < div id = "target"> </div> 
 </body> 
 </html> 
16
Ed.

Você não precisa usar regex se estiver usando a resposta para preencher uma div ou algo assim. Você pode usar getElementsByTagName.

div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
    eval(scripts[ix].text);
}
15
Scott Nichols

Enquanto a resposta aceita de @Ed. não funciona nas versões atuais do Firefox, Google Chrome ou navegadores Safari, consegui adotar seu exemplo para invocar scripts adicionados dinamicamente).

As alterações necessárias são apenas na maneira como os scripts são adicionados ao DOM. Em vez de adicioná-lo como innerHTML, o truque era criar um novo elemento de script e adicionar o conteúdo real do script como innerHTML ao elemento criado e, em seguida, anexar o elemento de script ao destino real.

<html>
<head>
<script type='text/javascript'>
function addScript()
{
    var newdiv = document.createElement('div');

    var p = document.createElement('p');
    p.innerHTML = "Dynamically added text";
    newdiv.appendChild(p);

    var script = document.createElement('script');
    script.innerHTML = "alert('i am here');";
    newdiv.appendChild(script);

    document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>

Isso funciona para mim no Firefox 42, Google Chrome 48 e Safari 9.0.3

8
Roman Vottner

Uma alternativa é não apenas despejar o retorno da chamada Ajax no DOM usando o InnerHTML.

Você pode inserir cada nó dinamicamente e, em seguida, o script será executado.

Caso contrário, o navegador simplesmente assume que você está inserindo um nó de texto e ignora os scripts.

Usar Eval é bastante ruim, porque exige que outra instância do Javascript VM seja ativada e JIT a sequência passada.

2
FlySwat

O melhor método provavelmente seria identificar e avaliar o conteúdo do bloco de scripts diretamente via DOM.

Eu seria cuidadoso. Se você está implementando isso para superar uma limitação de alguma chamada externa, está abrindo uma brecha na segurança.

Tudo o que você implementar pode ser explorado para o XSS.

1
Quintin Robinson

Você pode usar uma das bibliotecas populares do Ajax que fazem isso nativamente por você. Eu gosto Prototype . Você pode adicionar evalScripts: true como parte de sua chamada do Ajax e isso acontece automaticamente.

0
Diodeus - James MacFarlane