Come posso fare riferimento al tag script che ha caricato lo script attualmente in esecuzione?

Come posso fare riferimento all’elemento script che ha caricato il javascript attualmente in esecuzione?

Ecco la situazione. Ho uno script “master” che viene caricato in alto nella pagina, la prima cosa sotto il tag HEAD.

    

C’è uno script in “scripts.js” che deve essere in grado di eseguire il caricamento su richiesta di altri script. Il metodo normale non funziona per me perché ho bisogno di aggiungere nuovi script senza fare riferimento al tag HEAD, perché l’elemento HEAD non ha terminato il rendering:

 document.getElementsByTagName('head')[0].appendChild(v); 

Quello che voglio fare è fare riferimento all’elemento script che ha caricato lo script corrente in modo da poter aggiungere i miei nuovi tag script caricati dynamicmente nel DOM dopo di esso.

  loaded by scripts.js--> loaded by scripts.js --> 

    Come ottenere l’elemento di script corrente:

    1. Utilizzare document.currentScript

    document.currentScript restituirà l’elemento cui script è attualmente in fase di elaborazione.

      

    Benefici

    • Semplice ed esplicito. Affidabile.
    • Non è necessario modificare il tag dello script
    • Funziona con script asincroni ( defer e async )
    • Funziona con script inseriti dynamicmente

    I problemi

    • Non funzionerà con i browser più vecchi e IE.

    2. Seleziona lo script con ID

    Dando allo script un attributo id ti permetterà di selezionarlo facilmente tramite id dall'interno usando document.getElementById() .

      

    Benefici

    • Semplice ed esplicito. Affidabile.
    • Quasi universalmente supportato
    • Funziona con script asincroni ( defer e async )
    • Funziona con script inseriti dynamicmente

    I problemi

    • Richiede l'aggiunta di un attributo personalizzato al tag dello script
    • id attributo id può causare comportamenti strani per gli script in alcuni browser per alcuni casi limite

    3. Seleziona lo script usando un attributo data-*

    Dare allo script un attributo data-* ti permetterà di selezionarlo facilmente dall'interno.

      

    Questo ha pochi vantaggi rispetto alla precedente opzione.

    Benefici

    • Semplice ed esplicito.
    • Funziona con script asincroni ( defer e async )
    • Funziona con script inseriti dynamicmente

    I problemi

    • Richiede l'aggiunta di un attributo personalizzato al tag dello script
    • HTML5 e querySelector() non conformi in tutti i browser
    • Meno ampiamente supportato rispetto all'utilizzo dell'attributo id
    • Andrà in giro con con casi limite.
    • Può essere confuso se un altro elemento ha lo stesso attributo e valore di dati sulla pagina.

    4. Seleziona lo script da src

    Invece di utilizzare gli attributi dati, puoi utilizzare il selettore per scegliere lo script in base all'origine:

      

    In embed.js:

     var me = document.querySelector('script[src="//example.com/embed.js"]'); 

    Benefici

    • Affidabile
    • Funziona con script asincroni ( defer e async )
    • Funziona con script inseriti dynamicmente
    • Non sono necessari attributi o ID personalizzati

    I problemi

    • Non funziona per gli script locali
    • Causerà problemi in diversi ambienti, come lo sviluppo e la produzione
    • Statico e fragile La modifica della posizione del file di script richiede la modifica dello script
    • Meno ampiamente supportato rispetto all'utilizzo dell'attributo id
    • Causerà problemi se caricerai lo stesso script due volte

    5. Passa sopra tutti gli script per trovare quello che vuoi

    Possiamo anche scorrere su ogni elemento di script e controllarli individualmente per selezionare quello che vogliamo:

      

    Questo ci consente di utilizzare entrambe le tecniche precedenti nei browser meno recenti che non supportano querySelector() con gli attributi. Per esempio:

     function isMe(scriptElem){ return scriptElem.getAttribute('src') === "//example.com/embed.js"; } 

    Ciò eredita i vantaggi e i problemi di qualsiasi approccio, ma non si basa su querySelector() quindi funzionerà con i browser più vecchi.

    6. Ottieni l'ultimo script eseguito

    Poiché gli script vengono eseguiti in sequenza, l'ultimo elemento di script sarà molto spesso lo script attualmente in esecuzione:

      

    Benefici

    • Semplice.
    • Quasi universalmente supportato
    • Non sono necessari attributi o ID personalizzati

    I problemi

    • Non funziona con script asincroni ( defer e async )
    • Non funziona con script inseriti dynamicmente

    Poiché gli script vengono eseguiti in sequenza, il tag script attualmente eseguito è sempre l’ultimo tag di script nella pagina fino a quel momento. Quindi, per ottenere il tag script, puoi fare:

     var scripts = document.getElementsByTagName( 'script' ); var thisScriptTag = scripts[ scripts.length - 1 ]; 

    Probabilmente la cosa più semplice da fare sarebbe dare al tuo tag scrip un attributo id .

    Ecco un po ‘di polyfill che fa leva su document.CurrentScript se esiste e torna a cercare lo script tramite ID.

      

    Se includi questo nella parte superiore di ogni tag script, credo che sarai in grado di sapere in modo coerente quale tag script è stato triggersto e potrai anche fare riferimento al tag script nel contesto di un callback asincrono.

    Non testato, quindi lascia un feedback agli altri se lo provi.

    Gli script vengono eseguiti sequenzialmente solo se non hanno un attributo “differimento” o “asincrono”. Conoscere uno dei possibili attributi ID / SRC / TITLE del tag script potrebbe funzionare anche in questi casi. Quindi entrambi i suggerimenti di Greg e Justin sono corretti.

    Esiste già una proposta per document.currentScript negli elenchi WHATWG.

    EDIT : Firefox> 4 implementa già questa proprietà molto utile ma non è disponibile in IE11 l’ultima volta che ho controllato e disponibile solo in Chrome 29 e Safari 8.

    EDIT : Nessuno ha menzionato la raccolta “document.scripts”, ma credo che quanto segue possa essere una buona alternativa cross browser per ottenere lo script attualmente in esecuzione:

     var me = document.scripts[document.scripts.length -1]; 

    Deve funzionare al caricamento della pagina e quando un tag script viene aggiunto con javascript (es. Con ajax)

      

    Un approccio per gestire gli script asincroni e differiti consiste nell’utilizzare il gestore di onload: impostare un gestore di onload per tutti i tag di script e il primo che esegue dovrebbe essere il tuo.

     function getCurrentScript(callback) { if (document.currentScript) { callback(document.currentScript); return; } var scripts = document.scripts; function onLoad() { for (var i = 0; i < scripts.length; ++i) { scripts[i].removeEventListener('load', onLoad, false); } callback(event.target); } for (var i = 0; i < scripts.length; ++i) { scripts[i].addEventListener('load', onLoad, false); } } getCurrentScript(function(currentScript) { window.console.log(currentScript.src); }); 

    Segui questi semplici passaggi per ottenere riferimento al blocco di script di esecuzione corrente:

    1. Inserisci una stringa univoca casuale all’interno del blocco di script (deve essere univoca / diversa in ogni blocco di script)
    2. Iterate il risultato di document.getElementsByTagName (‘script’), cercando la stringa univoca da ciascuno dei loro contenuti (ottenuta dalla proprietà innerText / textContent).

    Esempio (ABCDE345678 è l’ID univoco) :

      

    btw, per il tuo caso, puoi semplicemente usare il vecchio metodo document.write () per includere un altro script. Come hai detto che il DOM non è ancora stato reso, puoi trarre vantaggio dal fatto che il browser esegue sempre lo script in sequenza lineare (eccetto quello differito che verrà reso in seguito), quindi il resto del documento è ancora “non esistente”. Tutto ciò che scrivi tramite document.write () verrà inserito subito dopo lo script del chiamante.

    Esempio di pagina HTML originale :

         anything 

    Contenuto di script.js :

     document.write(''); 

    Dopo il rendering, la struttura DOM diventerà:

     HEAD SCRIPT script.js SCRIPT inserted.js SCRIPT otherscript.js BODY 

    Considera questo algoritmo. Quando viene caricato lo script (se ci sono più script identici), guardare attraverso document.scripts, trovare il primo script con l’attributo “src” corretto, salvarlo e contrassegnarlo come “visitato” con un attributo dati o className univoco.

    Quando viene caricato lo script successivo, eseguire di nuovo la scansione su document.scripts, passando sopra a qualsiasi script già contrassegnato come visitato. Prendi la prima istanza non visitata di quello script.

    Ciò presuppone che gli script identici eseguiranno probabilmente nell’ordine in cui sono caricati, da capo a corpo, dall’alto verso il basso, da sincrono a asincrono.

     (function () { var scripts = document.scripts; // Scan for this data-* attribute var dataAttr = 'data-your-attribute-here'; var i = 0; var script; while (i < scripts.length) { script = scripts[i]; if (/your_script_here\.js/i.test(script.src) && !script.hasAttribute(dataAttr)) { // A good match will break the loop before // script is set to null. break; } // If we exit the loop through a while condition failure, // a check for null will reveal there are no matches. script = null; ++i; } /** * This specific your_script_here.js script tag. * @type {Element|Node} */ var yourScriptVariable = null; // Mark the script an pass it on. if (script) { script.setAttribute(dataAttr, ''); yourScriptVariable = script; } })(); 

    Verranno esaminati tutti gli script per il primo script corrispondente che non è contrassegnato con l'attributo speciale.

    Quindi contrassegna quel nodo, se trovato, con un attributo dati in modo che le scansioni successive non lo selezionino. Questo è simile al grafico traversal BFS e algoritmi DFS in cui i nodes possono essere contrassegnati come 'visitati' per impedire la revisione.

    Se puoi assumere il nome del file dello script, puoi trovarlo. Finora ho davvero testato la seguente funzione in Firefox.

      function findMe(tag, attr, file) { var tags = document.getElementsByTagName(tag); var r = new RegExp(file + '$'); for (var i = 0;i < tags.length;i++) { if (r.exec(tags[i][attr])) { return tags[i][attr]; } } }; var element = findMe('script', 'src', 'scripts.js'); 

    Per ottenere lo script, che attualmente ha caricato lo script è ansible utilizzare

     var thisScript = document.currentScript; 

    Devi mantenere un riferimento all’inizio del tuo script, così puoi chiamare più tardi

     var url = thisScript.src 

    Ho trovato il seguente codice per essere il più coerente, performante e semplice.

     var scripts = document.getElementsByTagName('script'); var thisScript = null; var i = scripts.length; while (i--) { if (scripts[i].src && (scripts[i].src.indexOf('yourscript.js') !== -1)) { thisScript = scripts[i]; break; } } console.log(thisScript); 

    Ho questo, che funziona in FF3, IE6 e 7. I metodi negli script caricati su richiesta non sono disponibili fino al completamento del caricamento della pagina, ma questo è ancora molto utile.

     //handle on-demand loading of javascripts makescript = function(url){ var v = document.createElement('script'); v.src=url; v.type='text/javascript'; //insertAfter. Get last