Ajout d'éléments "script" dans "head" impossible

Le problème exposé dans ce sujet a été résolu.

Salut à tous,

J'ai un petit soucis d'import de fichiers JavaScript. Dans ma page HTML, j'importe un .js qui s'occupe d'ajouter dans le head divers scripts. Cet ajout d'éléments "script" dans le "head" fonctionne parfaitement. Firebug m'indique clairement que Firefox a bien trouvé les fichiers importés. En revanche, il ne semble pas les interpréter.

En effet, chaque fichier importé contient la déclaration d'un objet. Et Firebug m'indique que les objets ne sont pas définis. Or je suis sûr que le code de ces fichiers est 100% correct : le problème ne vient pas d'eux. Donc, il semblerait que le bug provienne d'une absence d'interprétation des fichiers importés.

Ci-joint l'appel au fichier qui importe les autres .JS et son code-source. Je ne montrerai par le code des fichiers importés sauf demande de votre part (puisque je suis sûr que le problème ne vient pas de là).

Merci d'avance, bonne continuation.

PS : je rajouterais que lorsque j'ajoute les <script…> manuellement dans le fichier HTML, ça marche.

1
<script type = "text/javascript" src = "Stats_Module.js"></script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// This array contains the name of the JS-scripts to import.
var scripts = ["data", "html block", "droppable", "sub data", "super type", "useful functions", "operations box", "top axis", "left axis", "super types tree"];

var head_scripts_imports = "";

// These variables contains the path where the .JS are
var scripts_directory = "js-scripts_inc/";
var overlay_path = scripts_directory+"overlay/";

// For each item of the above array, we add it to the HEAD element in a SCRIPT element
for (var i = 0; i < scripts.length; i++) {
    scripts[i] = transform_name(scripts[i]);
    add_To_Header(scripts[i]);
}

// In reality, for example : the file "sub data" doesn't exist : so we change "sub data" to "Sub_Data.js", which really exists.
function transform_name(str)
{
    return minus_To_Majus(replace_Spaces_By_Underscore(str))+".js";
}

function replace_Spaces_By_Underscore(str)
{
    return str.replace(/ /g, "_"); // Replaces all the occurences (take a look at the MDN guide : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
}

// sub_data becomes Sub_Data for example
function minus_To_Majus (str)
{
    var res = '';
    for (var z = 0; z < str.length; z++) {
        if (str[z] == '_' && z+1 < str.length) {
            res += str[z] + str[z+1].toUpperCase();
            z++;
        }
        else if (z == 0) {
            res += str[z].toUpperCase();
        }
        else {
            res += str[z];
        }
    }

    return res;
}

// We add the SCRIPT element to the string that contains all the SCRIPT elements
function add_To_Header (str)
{
    head_scripts_imports += "<script type = 'text/javascript' src = '"+overlay_path+str+"'></script>";
}

// Then, we add all these SCRIPT element to the HEAD one
document.head.innerHTML = document.head.innerHTML + head_scripts_imports;
+0 -0

Salut.

Tu ne peux pas injecter de code a la volé en utilisant innerHTML. Il faut que tu utilise la fonction appendChild(monScript) pour pouvoir utiliser le code que tu rajoute.

Par contre il faut faire attention, si tu a des dépendances entre tes scripts, l'ordre d'ajout avec appendChild des scripts ne sera pas forcément l'ordre d’import.

Par exemple, je changerais ta fonction add_To_Header comme ceci :

1
2
3
4
5
6
7
8
9
function add_To_Header (str)
{
    var newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = overlay_path+str;

    var head = document.getElementsByTagName("head")[0];
    head.appendChild(newScript);
}

Source

+1 -0

Qu'est-ce qui ne marche pas ? Je viens d'essayer le même code chez moi ça charge bien mes fichiers et le contenu à l’intérieur.

Par contre il faut faire attention puisque tes fichiers ne sont pas forcément chargé tout de suite, donc si tu as un script qui utilise les variables / fonctions directement après les fonctions de chargement, il peut arriver qu'ils ne soient pas encore chargé lorsque tu les appelles.

Si tu veux lancer certaines fonctions après le chargement de l'ensemble, je te conseille de jeter un coup d’œil aux fonctions de callback.

Par contre il faut faire attention puisque tes fichiers ne sont pas forcément chargé tout de suite, donc si tu as un script qui utilise les variables / fonctions directement après les fonctions de chargement, il peut arriver qu'ils ne soient pas encore chargé lorsque tu les appelles.

Bibi

Qu'entends-tu par "directement" ? L'import du script qui importe les autres se fait plusieurs lignes avant la première instruction qui nécessite l'un des scripts importés.

Donc a priori, il ne devrait pas y avoir de problème de ce côté-là.

L'erreur affichée par la console, c'est "ReferenceError : Super_Type is not defined". Je suis absolument sûr que le code des scripts à importer est exempt d'erreur : quand je les importe petit-à-petit (i.e. : par succession de <script…></script> et sans utiliser mon fichier qui importe), il n'y a aucun problème.

Si tu veux lancer certaines fonctions après le chargement de l'ensemble, je te conseille de jeter un coup d’œil aux fonctions de callback.

Bibi

Nope, je ne crois pas en avoir besoin :)

+0 -0

Si je fait l'import et que j'utilise ce qu'il y a dans les fichiers inclus, j'ai effectivement une erreur de définition.

1
2
add_To_Header(Data) // Import de la variable objet
alert(objet);

me retourne un ReferenceError: objet is not defined.

Par contre, si j'utilise une fonctions de callback au chargement du script :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var callback = function() {
    alert(objet);
};
function add_To_Header (str) {
  var newScript = document.createElement('script');
  newScript.type = 'text/javascript';
  newScript.src = overlay_path+str;
  newScript.onreadystatechange = callback;
  newScript.onload = callback;

  var head = document.getElementsByTagName("head")[0];
  head.appendChild(newScript)
}
add_To_Header(Data); // Import de la variable objet + callback

cela m’exécute le alert sans soucis.

Le soucis que tu rencontre c'est que tu va exécuter du code alors que ton navigateur n'aura pas encore récupéré ce que tu viens d'importer. Il faut donc attendre que ton navigateur ait connaissance de ces fichiers avant de les utiliser. Après, à toi de vérifier que tu as bien tout importé avant d’exécuter ton code.

Si je fait l'import et que j'utilise ce qu'il y a dans les fichiers inclus, j'ai effectivement une erreur de définition.

1
  newScript.onreadystatechange = callback;

Bibi

Attention avec ça : la fonction peut être appelée plusieurs fois pendant le chargement et surtout pour plusieurs raisons


Au passage, en général on se fixe à utiliser du CamelCase ou du snake_case, mais pas un mélange des deux ;)

Si je fait l'import et que j'utilise ce qu'il y a dans les fichiers inclus, j'ai effectivement une erreur de définition.

1
2
add_To_Header(Data) // Import de la variable objet
alert(objet);

me retourne un ReferenceError: objet is not defined.

Par contre, si j'utilise une fonctions de callback au chargement du script :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var callback = function() {
  alert(objet);
};
function add_To_Header (str) {
  var newScript = document.createElement('script');
  newScript.type = 'text/javascript';
  newScript.src = overlay_path+str;
  newScript.onreadystatechange = callback;
  newScript.onload = callback;

  var head = document.getElementsByTagName("head")[0];
  head.appendChild(newScript)
}
add_To_Header(Data); // Import de la variable objet + callback

cela m’exécute le alert sans soucis.

Le soucis que tu rencontre c'est que tu va exécuter du code alors que ton navigateur n'aura pas encore récupéré ce que tu viens d'importer. Il faut donc attendre que ton navigateur ait connaissance de ces fichiers avant de les utiliser. Après, à toi de vérifier que tu as bien tout importé avant d’exécuter ton code.

Bibi

A priori je ne dois pas faire de callback. Tant pis, merci pour ton aide ! :)

Pourquoi est-ce-que tu dis cela ? C'est un exercice ?

Parce que je pense sincèrement que Bibi a cerné le soucis. Les scripts qui sont insérés programmatiquement dans la page seront exécutés après le chargement de la page.

Et afin de savoir quand est-ce-qu'ils ont été injectés et évalués par le navigateur (et du coup savoir que ta page est "prête") tu as besoin d'une fonction de callback.

Je ne te suis pas.

+0 -0

Pourquoi est-ce-que tu dis cela ? C'est un exercice ?

Parce que je pense sincèrement que Bibi a cerné le soucis. Les scripts qui sont insérés programmatiquement dans la page seront exécutés après le chargement de la page.

Et afin de savoir quand est-ce-qu'ils ont été injectés et évalués par le navigateur (et du coup savoir que ta page est "prête") tu as besoin d'une fonction de callback.

Je ne te suis pas.

Javier

C'est juste que la callback (peut-on parler vraiment parler de "callback", alors qu'on est ici dans un traitement synchrone ?) contiendrait vraiment pas mal de code avec du HTML entrecoupé dedans. Bref, je pense que ça donnerait quelque chose d'assez lourd, je préfère éviter. :)

Je ne vois pas en quoi ça peut être plus lourd que de tout exécuter lors du chargement de la page. Tu va faire la même chose dans les deux cas non ?

Et non justement, ton traitement n'est pas synchrone, puisque tu continue à exécuter ton JavaScript initial en attendant le chargement de tes autres scripts. La notion de callback est donc tout à fait justifié ici.

Chaque fichier chargé contient les méthodes d'un objet (un objet par fichier). Dans la page HTML qui charge ces scripts, des appels à ces méthodes peuvent être faits dans tel ou tel ordre, après tel ou tel extrait de code HTML, etc.

Et le développeur qui utilisera ce fichier HTML (et donc qui fera usage des méthodes précédemment citées), ce ne sera pas moi.

Ce sont les deux raisons qui me font penser qu'une callback n'est pas adaptée à ce que je souhaite faire (que cette callback soit mise dans le fichier HTML ou dans le fichier JavaScript qui charge les différents scripts, fichier JS qui serait chargé par le fichier HTML).

Après, peut-être que je n'ai pas totalement bien compris ta solution ?

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte