Eu tenho um script que insere algum conteúdo em um elemento usando innerHTML
.
O conteúdo pode ser, por exemplo:
<script type="text/javascript">alert('test');</script>
<strong>test</strong>
O problema é que o código dentro da <script>
tag não é executado. Pesquisei um pouco no Google, mas não havia soluções aparentes. Se eu inserisse o conteúdo usando jQuery, $(element).append(content);
as partes do script seriam obtidas eval
antes de serem injetadas no DOM.
Alguém tem um trecho de código que executa todos os <script>
elementos? O código jQuery era um pouco complexo, então não consegui descobrir como era feito.
Editar :
Observando o código jQuery, consegui descobrir como o jQuery faz isso, o que resultou no seguinte código:
Demo:
<div id="element"></div>
<script type="text/javascript">
function insertAndExecute(id, text)
{
domelement = document.getElementById(id);
domelement.innerHTML = text;
var scripts = [];
ret = domelement.childNodes;
for ( var i = 0; ret[i]; i++ ) {
if ( scripts && nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
}
}
for(script in scripts)
{
evalScript(scripts[script]);
}
}
function nodeName( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
}
function evalScript( elem ) {
data = ( elem.text || elem.textContent || elem.innerHTML || "" );
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
script.appendChild( document.createTextNode( data ) );
head.insertBefore( script, head.firstChild );
head.removeChild( script );
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
insertAndExecute("element", "<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt><strong>this text should also be inserted.</strong>");
</script>
javascript
dom
eval
innerhtml
phidah
fonte
fonte
function testFunction(){ alert('test'); }
ao código inserido no innerHTML, e depois tentar chamá-la, diz que a função não está definida.Respostas:
O script do OP não funciona no IE 7. Com a ajuda do SO, aqui está um script que faz:
fonte
$(parent).html(code)
- veja minha resposta abaixo.if (nodeName(child, "script" ) && (!child.type || child.type.toLowerCase() === "text/javascript")) { scripts.push(child); } else { exec_body_scripts(child); }
elem.src
e definir condicionalmente asrc
propriedade do elemento de script criado em vez de definir seu conteúdo de texto.eval
truque global em vez de criar um<script>
elemento e inseri-lo no<head>
? Ambos executam o código JS sem expor o encerramento atual.@phidah ... Aqui está uma solução muito interessante para o seu problema: http://24ways.org/2005/have-your-dom-and-script-it-too
Então, seria assim:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
fonte
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">
se quiser evitar uma solicitação http inútil.style="display:none;
) para ocultar o ícone da imagem quebrada<style>
é melhor do que<img>
, porque não faz uma solicitação de redeEste é um script mais curto e eficiente que também funciona para scripts com a
src
propriedade:Nota: embora
eval
possa causar uma vulnerabilidade de segurança se não for usado corretamente, é muito mais rápido do que criar uma tag de script na hora.fonte
eval
foi projetado para prejudicar os usuários. Qualquer execução de script dinâmico é um risco e é por isso que CSP o chama'unsafe-eval'
porque é. Você também está prejudicando a segurança de seus sites se estiver usando-o em uma biblioteca, pois eles não podem desligá-lo.src
propriedade serão baixados de forma assíncrona e executados quando chegados. A ordenação não é preservada. Os scripts embutidos também serão executados fora da ordem, de forma síncrona antes dos assíncronos.Você não deve usar a propriedade innerHTML, mas sim o método appendChild do Nó: um nó em uma árvore de documento [HTML DOM]. Desta forma, você pode chamar mais tarde o código injetado.
Certifique-se de entender que
node.innerHTML
não é o mesmo quenode.appendChild
. Você pode querer passar algum tempo na Referência do cliente Javascript para obter mais detalhes e o DOM. Espero que o seguinte ajude ...A injeção de amostra funciona:
Saudações,
fonte
try this, look how clever I am
respostas. Merece um UV, pegou o meu.var _in = document.getElementById(inject);
, Eu acho que.Versão ES6 simplificada da resposta de @joshcomley com um exemplo.
Sem JQuery, sem biblioteca, sem eval, sem alteração de DOM, apenas Javascript puro.
http://plnkr.co/edit/MMegiu?p=preview
Uso
fonte
setInnerHtml
não ésetInnerHTML
setInnerHTML
mas está sendo chamadosetInnerHtml
de dentro darunB
função. Portanto, o exemplo não funcionaExperimente este snippet:
fonte
Funciona no Chrome em meu projeto
fonte
Uma solução sem usar "eval":
Essencialmente, isso clona a tag do script e, em seguida, substitui a tag do script bloqueada pela recém-gerada, permitindo a execução.
fonte
scriptNode.innerHTML = code
não funcionou para o IE. A única coisa a fazer é substituirscriptNode.text = code
e funcionar bemfonte
É mais fácil usar jquery em
$(parent).html(code)
vez deparent.innerHTML = code
:Isso também funciona com scripts que usam
document.write
e scripts carregados viasrc
atributo. Infelizmente, mesmo isso não funciona com os scripts do Google AdSense.fonte
Apenas faça:
fonte
Você pode dar uma olhada neste post . O código pode ser assim:
fonte
Graças ao script de Larry, que funcionou perfeitamente bem no IE10, usei isto:
fonte
Estendendo fora da casa de Larry. Fiz uma busca recursiva em todo o bloco e nodos filhos.
O script agora também chamará scripts externos que são especificados com o parâmetro src. Os scripts são anexados ao cabeçalho em vez de inseridos e colocados na ordem em que são encontrados. Assim, especificamente, os scripts de pedidos são preservados. E cada script é executado de forma síncrona de forma semelhante à forma como o navegador lida com o carregamento inicial do DOM. Portanto, se você tem um bloco de script que chama jQuery de um CDN e o próximo nó de script usa jQuery ... Sem problemas! Ah, e eu marquei os scripts anexados com um id serializado baseado no que você definiu no parâmetro de tag para que você possa encontrar o que foi adicionado por este script.
fonte
Experimente, funciona para mim no Chrome, Safari e Firefox:
Porém, uma coisa a ser observada é que o seguinte script aninhado em div NÃO será executado:
Para que um script seja executado, ele deve ser criado como um nó e depois anexado como um filho. Você pode até mesmo anexar um script dentro de um div injetado anteriormente e ele será executado (já encontrei isso antes ao tentar fazer o código do servidor de anúncios funcionar):
fonte
Gastando a resposta de Lambder
Você pode usar a imagem base64 para criar e carregar seu script
Ou se você tiver um,
Iframe
você pode usá-lo em vez dissofonte
Eu precisava de algo semelhante, mas precisava que o script permanecesse ou fosse recriado no mesmo local que o script original, uma vez que meu script visa a localização da tag do script no DOM para criar / direcionar os elementos. Também tornei o script recursivo para ter certeza de que também funcionará se estiver mais de um nível abaixo.
NOTA: Eu uso
const
aqui, se você tiver um navegador mais antigo, é só usarvar
.fonte
Feito esta nova função auxiliar no TypeScript, talvez alguém goste. Se você remover a declaração de tipo do parâmetro de script, será apenas JS simples.
fonte
Experimente a função eval ().
Este é um exemplo real de um projeto que estou desenvolvendo. Graças a esta postagem
fonte
Aqui está minha solução em um projeto recente.
fonte