Tentei carregar alguns scripts em uma página usando innerHTML
a <div>
. Parece que o script é carregado no DOM, mas nunca é executado (pelo menos no Firefox e Chrome). Existe uma maneira de executar scripts ao inseri-los innerHTML
?
Código de amostra:
<!DOCTYPE html>
<html>
<body onload="document.getElementById('loader').innerHTML = '<script>alert(\'hi\')<\/script>'">
Shouldn't an alert saying 'hi' appear?
<div id="loader"></div>
</body>
</html>
fonte
<script>
tag cominnerHTML
pode ser curto, mas não funciona. É tudo apenas texto sem formatação até que seja executadoeval()
. E, infelizmente,eval()
não analisa tags HTML, então você acaba com uma cadeia de problemas.Aqui está uma solução muito interessante para o seu problema: http://24ways.org/2005/have-your-dom-and-script-it-too
Portanto, use isso em vez de tags de script:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
fonte
onload
atributo. Além disso, isso requer que um arquivo adicional exista e seja carregado. A solução da momo é menos comprometida.<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
(isso não fará uma solicitação de rede) Na verdade ... você NÃO precisa de uma imagem, faça referência a uma imagem inexistente e, em vez deonload
usaronerror
(mas isso fará uma solicitação de rede)Aqui está um método que substitui recursivamente todos os scripts por executáveis:
Chamada de exemplo:
fonte
Você pode criar um script e injetar o conteúdo.
Isso funciona em todos os navegadores :)
fonte
document.documentElement
vez disso.<script>
var g = document.createElement('script');
var s = document.getElementsByTagName('script')[0]; //reference this script
g.text = "alert(\"hi\");"
s.parentNode.insertBefore(g, s);
</script>
<script>
elementos. Por exemplo,<img onerror="..." src="#">
e<body onload="...">
. Se você quiser ser técnico, isso não funcionará em documentos não HTML / SVG, devido ao espaço para nome inexplicado.Eu usei esse código, está funcionando bem
fonte
Eu tive esse problema com o innerHTML, tive que anexar um script Hotjar à tag "head" do meu aplicativo Reactjs e ele teria que ser executado logo após o acréscimo.
Uma das boas soluções para importação dinâmica de Nó para a tag "head" é o módulo React-helment .
Além disso, há uma solução útil para o problema proposto:
Nenhuma tag de script no innerHTML!
Acontece que o HTML5 não permite que tags de script sejam adicionadas dinamicamente usando a propriedade innerHTML. Portanto, o seguinte não será executado e não haverá alerta dizendo Olá, mundo!
Isso está documentado na especificação HTML5:
Mas cuidado, isso não significa que innerHTML esteja a salvo de scripts entre sites. É possível executar JavaScript via innerHTML sem usar tags, conforme ilustrado na página innerHTML do MDN .
Solução: Adicionando scripts dinamicamente
Para adicionar dinamicamente uma tag de script, você precisa criar um novo elemento de script e anexá-lo ao elemento de destino.
Você pode fazer isso para scripts externos:
E scripts embutidos:
fonte
Para quem ainda tentando fazer isso, não, você não pode injetar um script usando
innerHTML
, mas é possível carregar uma string em uma marca de script usando umBlob
eURL.createObjectURL
.Eu criei um exemplo que permite executar uma string como um script e obter as 'exportações' do script retornadas por meio de uma promessa:
Eu simplifiquei isso da minha implementação real, então não há promessas de que não haja nenhum bug nela. Mas o princípio funciona.
Se você não se importa em recuperar qualquer valor após a execução do script, é ainda mais fácil; apenas deixar de fora os
Promise
eonload
pedaços. Você nem precisa quebrar o script ou criar awindow.__load_script_exports_
propriedade global .fonte
Aqui está uma função recursiva para definir o innerHTML de um elemento que eu uso em nosso servidor de anúncios:
Você pode ver a demonstração aqui .
fonte
Você poderia fazer assim:
fonte
Aqui, uma solução que não usa
eval
e funciona com scripts , scripts vinculados e também com módulos .A função aceita 3 parâmetros:
fonte
eval('console.log(this)')
e você verá a mais óbviaeval('let b=100')
.. e tente acessarb
de fora do eval .... boa sorte com ele, você precisará deleKrasimir Tsonev tem uma ótima solução que supera todos os problemas. Seu método não precisa usar eval; portanto, não existem problemas de desempenho nem de segurança. Ele permite que você defina a string innerHTML que contenha html com js e traduza-a imediatamente para um elemento DOM, além de executar as partes js existentes no código. curto, simples e funciona exatamente como você deseja.
Aproveite sua solução:
http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element
Anotações importantes:
fonte
Use em
$(parent).html(code)
vez deparent.innerHTML = code
.O seguinte também corrige scripts que usam
document.write
e scripts carregados viasrc
atributo. Infelizmente, mesmo isso não funciona com os scripts do Google AdSense.Fonte
fonte
Tente usar o template e document.importNode. Aqui está um exemplo:
fonte
Você também pode quebrar o seu
<script>
assim e ele será executado:Observe: O escopo interno
srcdoc
refere-se ao iframe, portanto, você deve usartop
como no exemplo acima para acessar o documento pai.fonte
Sim, você pode, mas precisa fazer isso fora do DOM e a ordem deve estar correta.
... irá alertar 'foo'. Isso não vai funcionar:
E mesmo isso não funcionará, porque o nó é inserido primeiro:
fonte
Minha solução para esse problema é definir um Mutation Observer para detectar
<script></script>
nós e substituí-lo por um novo<script></script>
nó com o mesmo src. Por exemplo:fonte
A menção de Gabriel Garcia aos MutationObservers está no caminho certo, mas não funcionou muito bem para mim. Não tenho certeza se isso foi devido a uma peculiaridade do navegador ou devido a um erro do meu lado, mas a versão que acabou funcionando para mim foi a seguinte:
Obviamente, você deve substituir
element_to_watch
pelo nome do elemento que está sendo modificado.node.parentElement.added
é usado para armazenar as tags de script adicionadasdocument.head
. Na função usada para carregar a página externa, você pode usar algo como o seguinte para remover as tags de script não mais relevantes:E um exemplo do início de uma função de carregamento:
fonte
MutationObserver
cada vez que um elemento é anexado ao documento, certo? Btw, eu me pergunto por que você diz que meu código não é funcional.Para mim, a melhor maneira é inserir o novo conteúdo HTML através do innerHtml e, em seguida, usar
O setTimeout não é necessário, mas funciona melhor. Isso funcionou para mim.
fonte
Etiqueta Executar (Java Script) do innerHTML
Substitua seu elemento de script por div com um atributo de classe class = "javascript" e feche-o com
</div>
Não altere o conteúdo que você deseja executar (anteriormente estava na tag de script e agora está na tag div)
Adicione um estilo à sua página ...
<style type="text/css"> .javascript { display: none; } </style>
Agora execute eval usando jquery (o jquery js já deve estar incluído)
Você pode explorar mais aqui , no meu blog.
fonte