Impossibile aggiungere l'elemento <script>


276

Qualche idea sul perché il pezzo di codice qui sotto non aggiunge l'elemento di script al DOM?

var code = "<script></script>";
$("#someElement").append(code);

4
definire "non funzionante" - anche se sospetto che il problema sia che gli script non fanno realmente parte dell'albero dom.
Joel Coehoorn,

1
La mia scommessa è che il nodo dello script viene aggiunto al DOM, ma il browser non sta eseguendo lo script.
Programmatore fuorilegge il

Dan, come l'hai provato?
James

1
@Joel - "non funziona" = non ha alcun effetto, ovvero il codice all'interno dello script non viene eseguito @Outlaw Programmer - il nodo non viene aggiunto al DOM @Jimmy Sì, l'ho testato e non funziona
Dan Burzo,

Risposte:


259

Ho riscontrato problemi in cui alcuni browser non rispettano alcune modifiche quando le esegui direttamente (per cui intendo creare l'HTML dal testo come se stessi provando con il tag dello script), ma quando le esegui con i comandi integrati le cose vanno meglio. Prova questo:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

Da: JSON per jQuery


18
Il tag <script> deve essere aggiunto al DOM stesso, non al innerHTML di un elemento esistente.
Diodeus - James MacFarlane,

6
@Diodeus innerHTML fa parte del DOM ed è analizzato al volo dal browser, quindi questo è un caso valido.
Cristian Toma,


5
Non limitarti a utilizzare l'appendice di jQuery se vuoi davvero che l'elemento appaia nel DOM. Utilizza l'appendChild nativo per raggiungere questo obiettivo.
Minqi Pan

8
$("#someElement")[0].appendChild( script );
Minqi Pan

352

La buona notizia è:

Funziona al 100%.

Basta aggiungere qualcosa all'interno del tag dello script come alert('voila!');. La domanda giusta che potresti voler porre forse, "Perché non l'ho vista nel DOM?".

Karl Swedberg ha fornito una bella spiegazione al commento del visitatore nel sito dell'API jQuery . Io non voglio ripetere tutte le sue parole, è possibile leggere direttamente qui (ho trovato difficile da navigare attraverso i commenti lì) .

Tutti i metodi di inserimento di jQuery utilizzano internamente una funzione domManip per pulire / elaborare gli elementi prima e dopo che sono stati inseriti nel DOM. Una delle cose che fa la funzione domManip è estrarre tutti gli elementi di script che stanno per essere inseriti ed eseguirli attraverso una "routine evalScript" anziché iniettarli con il resto del frammento DOM. Inserisce gli script separatamente, li valuta e quindi li rimuove dal DOM.

Credo che uno dei motivi per cui jQuery faccia questo sia quello di evitare errori "Autorizzazione negata" che possono verificarsi in Internet Explorer quando si inseriscono script in determinate circostanze. Evita inoltre di inserire / valutare ripetutamente lo stesso script (che potrebbe potenzialmente causare problemi) se si trova all'interno di un elemento contenitore che si sta inserendo e quindi spostando nel DOM.

La prossima cosa è che riassumerò quali sono le cattive notizie usando la .append()funzione per aggiungere uno script.


E le cattive notizie sono ...

Non è possibile eseguire il debug del codice.

Non sto scherzando, anche se aggiungi una debugger;parola chiave tra la linea che vuoi impostare come punto di interruzione, finirai per ottenere solo lo stack di chiamate dell'oggetto senza vedere il punto di interruzione sul codice sorgente (per non parlare del fatto che questo la parola chiave funziona solo nel browser webkit, tutti gli altri principali browser sembrano omettere questa parola chiave) .

Se capisci perfettamente cosa fa il tuo codice, questo sarà un piccolo inconveniente. Ma se non lo fai, finirai per aggiungere una debugger;parola chiave in tutto il luogo solo per scoprire cosa c'è che non va nel tuo (o nel mio) codice. Comunque, c'è un'alternativa, non dimenticare che JavaScript può manipolare nativamente il DOM HTML.


Soluzione.

Usa javascript (non jQuery) per manipolare il DOM HTML

Se non vuoi perdere la funzionalità di debug, puoi utilizzare la manipolazione DOM HTML nativa javascript. Considera questo esempio:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

Eccolo, proprio come ai vecchi tempi non è vero. E non dimenticare di ripulire le cose sia nel DOM che nella memoria per tutti gli oggetti a cui viene fatto riferimento e che non sono più necessari per evitare perdite di memoria. Puoi considerare questo codice per ripulire le cose:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

Lo svantaggio di questa soluzione alternativa è che potresti accidentalmente aggiungere uno script duplicato, e questo è male. Da qui puoi simulare leggermente la .append()funzione aggiungendo una verifica oggetto prima di aggiungere e rimuovendo lo script dal DOM subito dopo che è stato aggiunto. Considera questo esempio:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

In questo modo, puoi aggiungere script con funzionalità di debug mentre sei al sicuro dalla duplicità degli script. Questo è solo un prototipo, puoi espanderlo per quello che vuoi che sia. Ho usato questo approccio e abbastanza soddisfatto di questo. Abbastanza sicuro non userò mai jQuery .append()per aggiungere uno script.


2
Grande spiegazione, grazie! Ma era "UnusedReferencedObjects"?
Acme,

Grazie. Presumo che ti riferissi alla prima occorrenza di "UnusedReferencedObjects", che dovrebbe essere qualsiasi oggetto che hai creato nello script che carichi. Immagino che tu capisca meglio se vedi cosa fa la funzione DeleteObject, elimina semplicemente qualsiasi oggetto che hai passato alla funzione. Aggiungerò alcuni commenti nel codice per essere chiari. :)
Hendra Uzia,

Super post! L'esempio di aCrosman non ha funzionato per me e dopo aver pronto il tuo post ho sostituito $ ("# someElement"). Append (script); con $ ("# someElement") [0] .appendChild (script); Che risolto :) Thnx per la spiegazione
Maarten Kieft

7
$.getScriptè integrato in jQuery.
zzzzBov

SourceURLs ( blog.getfirebug.com/2009/08/11/… ) potrebbe aiutare con problemi di debug.
vsevik

23

È possibile caricare dinamicamente un file JavaScript utilizzando la funzione jQuerygetScript

$ .getScript ('http://www.whatever.com/shareprice/shareprice.js', function () {
  Display.sharePrice ();
});

Ora verrà chiamato lo script esterno e, se non può essere caricato, si degraderà con grazia.


7
Questo non inserisce nulla nel DOM. Chiama eval().
nh2,

20

Cosa intendi con "non funzionante"?

jQuery rileva che stai tentando di creare un elemento SCRIPT e eseguirà automaticamente il contenuto dell'elemento nel contesto globale. Mi stai dicendo che questo non funziona per te? -

$('#someElement').append('<script>alert("WORKING");</script>');

Modifica: se non vedi l'elemento SCRIPT nel DOM (ad esempio in Firebug) dopo aver eseguito il comando perché jQuery, come ho detto, eseguirà il codice e quindi eliminerà l'elemento SCRIPT - Credo che gli elementi SCRIPT vengono sempre aggiunti al corpo ... ma comunque - il posizionamento non ha assolutamente alcun effetto sull'esecuzione del codice in questa situazione.


17

Questo funziona:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

Sembra che jQuery stia facendo qualcosa di intelligente con gli script, quindi è necessario aggiungere l'elemento html anziché l'oggetto jQuery.


2
Questa è l'unica soluzione che funziona nel mio caso. Le altre soluzioni precedenti dipendono dal codice javascript presente in anticipo nel file html. Dal momento che sto aggiungendo il codice in modo dinamico, tale codice javascript non può essere conosciuto in anticipo! GRAZIE Darwin !!
tgoneil,

14

Prova questo può essere utile:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

9
non ho idea del perché questo tipo di negativi sia l'unico non abbastanza stupido da continuare a usare jquery per tutto!
SSpoke il

Probabilmente la maggior parte delle risposte utilizza jQuery perché nella domanda l'OP utilizza jQuery.
sanbor,

3

Voglio fare la stessa cosa ma aggiungere un tag di script in un altro frame!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);

3
<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

L' </script>all'interno della stringa termina letterali l'intero script, per evitare che "</scr" + "ipt>"può essere utilizzato invece.


Oppure non incorporare il tuo javascript direttamente nel documento HTML. I file di script esterni non presentano questo problema.
Ian Clelland,

Sequenze di escape: "\x3cscript\x3e\x3c/script\x3e". In XHTML, devi solo inserire un blocco CDATA commentato.
Eli Grey,

2
È piuttosto </ciò che non è permesso. Vedi stackoverflow.com/questions/236073/…
Gumbo


1

Il tuo script è in esecuzione, non puoi usarlo document.write. Utilizzare un avviso per testarlo ed evitare di utilizzarlo document.write. Le istruzioni del tuo file js con document.writenon verranno eseguite e il resto della funzione verrà eseguito.


1

Questa è quella che penso sia la soluzione migliore. Google Analytics viene iniettato in questo modo.

var (function(){
    var p="https:" == document.location.protocol ? "https://" : "http://";
        d=document,
        g=d.createElement('script'),
        s=d.getElementsByTagName('script')[0];
        g.type='text/javascript';
        g.src=p+'url-to-your-script.js';
        s.parentNode.insertBefore(g,s); })();

1

Non è necessario jQuery per creare un elemento DOM di script . Può essere fatto con vaniglia ES6 in questo modo:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

Non è necessario racchiuderlo in a Promise, ma ciò consente di risolvere la promessa quando lo script viene caricato, contribuendo a prevenire le condizioni di competizione per gli script di lunga durata.


0

Aggiungi script al corpo:

$(document).ready(function() {
    $("<script>", {  src : "bootstrap.min.js",  type : "text/javascript" }).appendTo("body");
});

0

Un altro modo per farlo se si desidera aggiungere il codice è utilizzare il document.createElementmetodo ma quindi utilizzare .innerHTMLinvece di .src.

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );

0

Ho provato questo uno e funziona bene. Sostituisci semplicemente il <simbolo con quello \x3C.

// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);

o

//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");

Puoi testare il codice qui .


0

Puoi provare così

var code = "<script></" + "script>";
$("#someElement").append(code);

L'unico motivo per cui non puoi farlo "<script></script>"è perché la stringa non è consentita all'interno di JavaScript perché il livello DOM non può analizzare ciò che è js e ciò che è HTML.


0

Ho scritto un npmpacchetto che ti consente di prendere una stringa HTML, inclusi tag script e aggiungerla a un contenitore mentre esecuzione degli script

Esempio:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

Lo trovi qui: https://www.npmjs.com/package/appendhtml


-1

Basta creare un elemento analizzandolo con jQuery.

<div id="someElement"></div>
<script>
    var code = "<script>alert(123);<\/script>";
    $("#someElement").append($(code));
</script>

Esempio di lavoro: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz


Questo ha ancora lo stesso problema, alcuni browser non lo rispettano.
Martin Massera,

Potresti farmi sapere quali browser e quale versione di jQuery stai utilizzando? Grazie!
sanbor,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.