Como inserir dinamicamente uma tag <script> via jQuery após o carregamento da página?

101

Estou tendo problemas para fazer isso funcionar. Primeiro tentei definir minhas tags de script como strings e, em seguida, usar jquery replaceWith () para adicioná-las ao documento após o carregamento da página:

var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);

Mas recebi erros literais de string nessa var. Em seguida, tentei codificar a string como:

var a = '&left;script type="text/javascript"&gt;some script here&lt;\/script&gt;';

mas enviar isso para a replaceWith()saída apenas aquela string para o navegador.

Alguém pode me dizer como você faria para adicionar dinamicamente uma <script>tag ao navegador após o carregamento da página, de preferência via jQuery?

Doug
fonte
Você pode explicar o que está tentando alcançar adicionando uma <script>tag ao documento?
Pointy,
A resposta de @ Rocket é a melhor, mas se você definitivamente quiser adicionar script embutido de uma string, basta passá-lo para a eval()função. Mas o uso de eval()quase sempre sugere que existe uma maneira melhor de fazer o que você está tentando fazer.
Nick
estamos tentando adiar o carregamento de anúncios de terceiros até o final da página. esses anúncios são chamados por meio de 2 tags de script, então eu queria executar uma função após o carregamento da página que os jogasse dinamicamente.
Doug,
2
Nem todos os scripts de terceiros são projetados para serem adiados. Se o script usar document.writee você chamá-lo após o carregamento da página, ele destruirá a página.
bobince,
1
Por que não importar essas tags nos <iframe>elementos? Você pode adiar a configuração do <iframe>URL até que esteja pronto.
Pointy,

Respostas:

103

Você pode colocar o script em um arquivo separado e usá-lo $.getScriptpara carregá-lo e executá-lo.

Exemplo:

$.getScript("test.js", function(){
    alert("Running test.js");
});
Foguete Hazmat
fonte
2
obrigado, mas isso vai colocá-lo no DOM? Percebi que deixei de fora uma informação importante, que preciso que a tag de script seja inserida no DOM, avaliada, e nesse ponto ela retorna o código de anúncio de terceiros para exibir em nosso site em um <div> específico.
Doug,
1
$.getScriptirá apenas carregar um arquivo .js via AJAX e executá-lo. O script não precisa estar no DOM para acessar um div em sua página.
Rocket Hazmat
6
Mas com $.getScript()o script precisará estar no mesmo domínio ou tanto o domínio remoto quanto o navegador precisarão suportar CORS.
hippietrail de
14
@hippietrail Isso não é verdade. Ele apenas insere uma tag de script simples, que não requer CORS ou mesmo domínio. Eu uso isso para encurtar o código para carregar o Google Analytics, por exemplo, e ele carrega muito bem. Nos bastidores, o código jquery real que é executado é muito semelhante ao snippet GA, na verdade.
Chris Moschini
39
Uma vez que a resposta de @hippietrail atrairá mais atenção com seus 4 votos positivos, deve-se deixar claro que ele está incorreto. Como os documentos da jQuery destacam em suas $.ajaxnotas: "As solicitações de script e JSONP não estão sujeitas às mesmas restrições de política de origem." fonte . Em outras palavras, $.getScriptpode extrair arquivos .js de outros domínios, não apenas do seu .
EleventyOne
64

Experimente o seguinte:

<script type="text/javascript">
// Use any event to append the code
$(document).ready(function() 
{
    var s = document.createElement("script");
    s.type = "text/javascript";
    s.src = "http://scriptlocation/das.js";
    // Use any selector
    $("head").append(s);
});

http://api.jquery.com/append

Bassem
fonte
4
+1 para uso de appendpara adicionar um script. Append faz com que até mesmo o script embutido avalie imediatamente (exatamente o que eu precisava). Obrigado
Gone Coding
1
Acabo tendo muitos problemas no IE8 / 9 com essa abordagem. Ou seja, erros de estouro de pilha. Recorri ao método $ .getScript () abaixo para fazer com que funcionasse de maneira geral.
zmonteca
1
Sim @jcoffland, isso foi escrito em outubro de 2010 :)
Bassem
Se a página que contém esse código for carregada usando AJAX, o navegador lançará um aviso "XMLHttpRequest síncrono no thread principal está obsoleto devido aos seus efeitos prejudiciais à experiência do usuário final".
Rajshekar Reddy
@Reddy Ótimo comentário. Isso foi postado em outubro de 2010, tenho certeza que agora este método não é mais uma abordagem válida / recomendada, os usuários devem proceder a seu próprio critério.
Bassem
34

Esta é a maneira correta de fazer isso com o JQuery moderno (2014):

$(function () {
  $('<script>')
    .attr('type', 'text/javascript')
    .text('some script here')
    .appendTo('head');
})

ou se você realmente deseja substituir um div, pode fazer:

$(function () {
  $('<script>')
    .attr('type', 'text/javascript')
    .text('some script here')
    .replaceAll('#someelement');
});
Jcoffland
fonte
3
Ou em vez disso .text ('algum script aqui') você pode escrever .attr ('src', 'path_to_your_js_file')
Serhii Maksymchuk
11

Uma maneira mais simples é:

$('head').append('<script type="text/javascript" src="your.js"></script>');

Você também pode usar este formulário para carregar o css.

iman
fonte
6
Você pode querer evitar colocar a string </script>em sua fonte, pois isso pode causar problemas de análise: stackoverflow.com/questions/236073/…
iX3
2
escapar do último /fez o truque para mim:$('head').append('<script src="your.js"><\/script>');
jerik
5

Essa resposta é tecnicamente semelhante ou igual à que jcoffland respondeu. Acabei de adicionar uma consulta para detectar se um script já está presente ou não. Preciso disso porque trabalho em um site de intranet com alguns módulos, alguns dos quais compartilham scripts ou trazem seus próprios, mas esses scripts não precisam ser carregados sempre novamente. Estou usando este snippet há mais de um ano em ambiente de produção, funciona como um encanto. Comentando para mim mesmo: Sim, eu sei, seria mais correto perguntar se existe uma função ... :-)

if (!$('head > script[src="js/jquery.searchable.min.js"]').length) {
    $('head').append($('<script />').attr('src','js/jquery.searchable.min.js'));
}
ddlab
fonte
btw. Eu faço o mesmo com as folhas de estilo: if (! $ ('Head> link [href = "widgets / css / widgets.css"]'). Length) {$ ('head'). Append ($ ('<link / > '). attr (' rel ',' stylesheet '). attr (' href ',' widgets / css / widgets.css '));}
ddlab
2

Existe uma solução alternativa que parece mais um hack e concordo que não é a maneira mais elegante de fazer isso, mas funciona 100%:

Digamos que sua resposta AJAX seja algo como

<b>some html</b>
<script>alert("and some javscript")

Observe que pulei a tag de fechamento de propósito. Em seguida, no script que carrega o acima, faça o seguinte:

$.ajax({
    url: "path/to/return/the-above-js+html.php",
    success: function(newhtml){
        newhtml += "<";
        newhtml += "/script>";
        $("head").append(newhtml);
    }
});

Só não me pergunte por quê :-) Esta é uma das coisas que cheguei como resultado de tentativas desesperadas quase aleatórias e falhas.

Não tenho sugestões completas sobre como funciona, mas curiosamente, NÃO funcionará se você acrescentar a tag de fechamento em uma linha.

Em tempos como estes, sinto que consegui dividir por zero.

Cinza
fonte
3
Não funcionará se a tag de fechamento do script estiver inteira, pois o navegador a vê como a tag de fechamento do seu script em vez de um literal de string.
Gone Coding
1
<\/script>seria válido
SP
Acho que o ponto de @ TrueBlueAussie foi em resposta ao seu comentário "Só não me pergunte por que ... mas curiosamente, NÃO funcionará se você acrescentar a tag de fechamento em uma linha." Ele explicou o porquê, para que qualquer leitor que desejasse uma resposta melhor do que "Não sei" pudesse encontrá-la mais facilmente. Veja também: javascript.crockford.com/script.html
iX3
1
@Sathvik está correto, de acordo com esse link. O comentário de Ash parece ter sido uma resposta a um que foi removido.
Arlen Beiler
2

Exemplo:

var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);

Deve funcionar. Eu tentei; mesmo resultado. Mas quando usei isso:

var length = 1;
var html = "";
for (var i = 0; i < length; i++) {
    html += '<div id="codeSnippet"></div>';
    html += '<script type="text/javascript">';
    html += 'your script here';
    html += '</script>';
}
$('#someElement').replaceWith(a);

Isso funcionou para mim.

Edit: Eu esqueci o #someelement(aliás, talvez eu queira usar #someElementpor causa das convenções)

A coisa mais importante aqui é o + = para que o html seja adicionado e não substituído.

Deixe um comentário se não funcionar. Eu gostaria de te ajudar!

santinobonora
fonte
2

Aqui está uma maneira muito mais clara - sem necessidade de jQuery - que adiciona um script como o último filho de <body>:

document.body.innerHTML +='<script src="mycdn.js"><\/script>'

Mas se você quiser adicionar e carregar scripts, use o método Rocket Hazmat .

Gagik Sargsyan
fonte
-4

Se você estiver tentando executar algum JavaScript gerado dinamicamente, ficará um pouco melhor usando eval. No entanto, JavaScript é uma linguagem tão dinâmica que você realmente não deveria ter necessidade disso.

Se o script for estático, a getScript-sugestão de Rocket é o caminho a percorrer.

Magnar
fonte