388 votes

Comment puis-je faire référence à la balise script qui a chargé le script en cours d'exécution ?

Comment puis-je faire référence à l'élément script qui a chargé le javascript en cours d'exécution ?

Voici la situation. J'ai un script "maître" qui est chargé en haut de la page, en premier lieu sous la balise HEAD.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" src="scripts.js"></script>

Il existe un script dans "script.js" qui doit pouvoir faire un chargement à la demande d'autres script. La méthode normale ne fonctionne pas tout à fait pour moi parce que je dois ajouter de nouveaux script sans référencer la balise HEAD, parce que l'élément HEAD n'a pas terminé son rendu :

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

Ce que je veux faire, c'est référencer l'élément script qui a chargé le script actuel afin que je puisse ensuite ajouter mes nouvelles balises script chargées dynamiquement dans le DOM après lui.

<script type="text/javascript" src="scripts.js"></script>
loaded by scripts.js--><script type="text/javascript" src="new_script1.js"></script>
loaded by scripts.js --><script type="text/javascript" src="new_script2.js"></script>

3voto

LSOJ Points 51

Considérons cet algorithme. Lorsque votre script se charge (s'il y a plusieurs script identiques), regardez dans document.script, trouvez le premier script avec l'attribut "src" correct, et enregistrez-le et marquez-le comme "visité" avec un attribut de données ou un className unique.

Lorsque le script suivant se charge, parcourez à nouveau document.script, en passant par tout script déjà marqué comme visité. Prenez la première instance non visitée de ce script.

Cela suppose que des scripts identiques s'exécuteront probablement dans l'ordre dans lequel ils sont chargés, de la tête au corps, de haut en bas, de synchrone à asynchrone.

(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;
  }
})();

Cela va parcourir tous les script pour trouver le premier script correspondant qui n'est pas marqué par l'attribut spécial.

Marquez ensuite ce nœud, s'il a été trouvé, avec un attribut de données afin que les analyses suivantes ne le choisissent pas. Cette méthode est similaire aux algorithmes de traversée de graphe BFS et DFS, dans lesquels les nœuds peuvent être marqués comme "visités" pour éviter qu'ils ne soient revisités.

1voto

J'ai obtenu ceci, qui fonctionne dans FF3, IE6 et 7. Les méthodes dans les scripts chargés à la demande ne sont pas disponibles tant que le chargement de la page n'est pas terminé, mais cela reste très 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 <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}

0voto

Justin Love Points 3073

Si vous pouvez supposer le nom du fichier du script, vous pouvez le trouver. Pour l'instant, je n'ai vraiment testé la fonction suivante que dans 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');

-1voto

Travis Tidwell Points 31

J'ai trouvé que le code suivant était le plus cohérent, le plus performant et le plus simple.

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);

-1voto

Ron Newcomb Points 975

J'insérais script dynamiquement avec cette alternative habituelle à eval et simplement définir une propriété globale currentComponentScript juste avant de l'ajouter au DOM.

  const old = el.querySelector("script")[0];
  const replacement = document.createElement("script");
  replacement.setAttribute("type", "module");
  replacement.appendChild(document.createTextNode(old.innerHTML));
  window.currentComponentScript = replacement;
  old.replaceWith(replacement);

Mais ça ne fonctionne pas en boucle. Le DOM ne lance pas les scripts avant la prochaine macrotâche, donc un lot d'entre eux ne verra que la dernière valeur définie. Vous devez setTimeout le paragraphe entier, et ensuite setTimeout le suivant après la fin du précédent. C'est-à-dire enchaîner les setTimeouts, et pas seulement appeler setTimeout plusieurs fois de suite à partir d'une boucle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X