11543 sujets

JavaScript, DOM et API Web HTML5

Bonjour,
Je bloque avec la fonction "document.getElementById ".

<!DOCTYPE html>
<html>
<head>
    <title>Calcul</title>
    <meta charset="utf-8">
</head>
<body>
     Valeur de ma variable: <span id="variable1">Pas de communication</span>
    <script>
       let var1 =10
       document.getElementById("variable1").innerHTML = var1;
    </script>
   </body>
</html>

Cela affiche correctement ma valeur var1 . Par contre si je fait appel a un script extérieur à mon fichier html , j'ai l'erreur: log1.js:2 Uncaught TypeError: Cannot set properties of null (setting 'innerHTML') at log1.js:2:48

mon fichier html:

<!DOCTYPE html>
<html>
<head>
    <title>Calcul</title>
    <meta charset="utf-8">
     <script type="text/javascript" src="log1.js"></script>
</head>
<body>
    Valeur de ma variable: <span id="variable1">Pas de communication</span>
</body>
</html>

mon fichier log1.js

let var1 =10
document.getElementById("variable1").innerHTML = var1;
Bonjour, c'est parce que veux modifier le DOM alors qu'il n'est pas encore construit, le code JS s'exécute avant que le HTML soit écrit.
Plusieurs solution: L'ancienne solution (qui fonctionne toujours) consiste à placer les scripts juste avant la balise </body>.
Solution plus actuel : Dans le <head> ajouter l'attribut
defer
à la balise <script>. Exemple :
<script src="log1.js" defer></script>

Note que l'attribut type n'est plus obligatoire pour JS.
Dernière solution, s'assurer que le dom est charger
https://developer.mozilla.org/fr/docs/Web/API/Document/DOMContentLoaded_event
Pour apprendre le JS => https://fr.javascript.info/
Modérateur
Bonjour,

L'attribut defer est plutôt fait pour décaler l'exécution des gros scripts à la fin du chargement de la page et non pas pour attendre que les éléments HTML de la page soit chargés.

Ça peut marcher, mais l'inconvenient avec defer est que si on a plusieurs scripts, on ne sait pas trop dans quel ordre ces scripts vont être exécutés. Personnellement, je n'aime pas du tout, d'autant plus qu'on a par ailleurs en javascript des tas d'autres occasions de voir du code exécuté avec un délai (et ce n'est pas facile à gérer).

La dernière solution proposée par casper, celle avec le DOMContentLoaded_event (https://developer.mozilla.org/fr/docs/Web/API/Document/DOMContentLoaded_event), ou bien une solution en surveillant d'autres évènements comme le load_event (https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event) sont à privilégier, où qu'on mette le script dans le html.

Personnellement, je préfère agir dans le cas général après le load event quand je manipule le DOM (les éléments HTML de la page), parce que si on agit après le DOMContentLoaded_event (qui arrive avant le load event), selon ce que fait le script js, ça peut ne pas marcher comme attendu vu que toutes les ressources ne sont pas chargées à ce moment-là, et c'est parfois une grosse prise de tête de savoir pourquoi.

Mais bon, y a beaucoup de fans du DOMContentLoaded_event aussi ! Tant qu'ils savent ce qu'ils font, pourquoi pas ! Smiley cligne

Amicalement,
Modifié par parsimonhi (03 May 2025 - 11:48)
Merci casper2.D'accord, je pensais que c'était le code html qui "appelait" le code javascript .

Cela explique certainement un autre problème , j'utilise un script commun pour plusieurs pages html n'affichant pas les mêmes variables . Sur la console j'ai des erreurs sur les variables qui ne sont pas affichées sur la page html mais "rafraichies" dans le script .
Pour être le plus souple possible, Il faudrait que mon script détecte si ma variable est utilisée dans ma page html ?
Modifié par herve_37 (03 May 2025 - 11:49)
Modérateur
Bonjour,
herve_37 a écrit :
Merci casper2.D'accord, je pensais que c'était le code html qui "appelait" le code javascript.
C'est le cas en quelque sorte. Mais le script est exécuté immédiatement sauf mention contraire. Donc s'il cherche à modifier quelque chose qui est situé après dans le code HTML, ça ne va pas marcher "comme ça".

Amicalement,
Modérateur
Bonjour,
herve_37 a écrit :
Pour être le plus souple possible, Il faudrait que mon script détecte si ma variable est utilisée dans ma page html ?
On ne sait pas ce que fait ton script, mais a priori, on ne s'amuse pas à "détecter" via un script si une "variable" est utilisée.

Par contre, on vérifie assez souvent si un élément html est présent ou pas.

Amicalement,
Il faut donc que mon script ne s'exécute qu'après l'exécution de ma page web et tester si la variable est utilisée :

window.onload = (event) => {
    console.log("La page est complètement chargée");
  
    let var1 =10
    let var2 =20

    if (document.getElementById("variable1"))
        {
        document.getElementById("variable1").innerHTML = var1;
        }
    if (document.getElementById("variable2"))
        {
        document.getElementById("variable2").innerHTML = var2;
        }
};
Modérateur
Bonjour,

Ce que tu appelles "variable" est en fait l'id d'un élément html, donc pas vraiment une variable.

Ceci étant, oui, tu peux tester l'existence des éléments html comme le fait ton code ci-dessus.

Tu peux légèrement raccourcir ton code aussi. Par exemple, tu peux remplacer :
if (document.getElementById("variable1"))
{
        document.getElementById("variable1").innerHTML = var1;
 }
par
let e1 =  document.getElementById("variable1")
if (e1) e1.innerHTML = var1
Tu évites ainsi de demander au navigateur d'exécuter deux fois le document.getElementById("variable1")

Amicalement,
Modérateur
Bonjour,

Pour ajouter aux autres infos.
Il y a aussi une différence importante entre ta version avec le script en ligne et celle avec le script externe. Cette différence est l'endroit où le script est appelé.

     Valeur de ma variable: <span id="variable1">Pas de communication</span>
    <script>
       let var1 =10
       document.getElementById("variable1").innerHTML = var1;
    </script>

dans ce cas, le document se charge et le span existe (chargé/lu) avant ton script. Pas de soucis, le script trouve ton id et modifie son contenu.
Si tu fait :

    <script>
       let var1 =10
       document.getElementById("variable1").innerHTML = var1;
    </script>
     Valeur de ma variable: <span id="variable1">Pas de communication</span>

tu as le même soucis qu'en faisant :
<!DOCTYPE html>
<html>
<head>
    <title>Calcul</title>
    <meta charset="utf-8">
     <script src="log1.js"></script>
</head>
<body>
    Valeur de ma variable: <span id="variable1">Pas de communication</span>
</body>
</html>

le script est chargé ou lancé avant que ton span soit lu et chargé.

En ajoutant un évènement onload sur le document tu peut attendre le chargement(lecture) du document avant de lancé ta fonction.

document.addEventListener("load", 
 function() {
    let var1 =10
    document.getElementById("variable1").innerHTML = var1;
  }
);


tu peut aussi chargé ton script en fin de page lorsque ton span est déjà chargé, juste avant la fermeture de body par exemple
<!DOCTYPE html>
<html>
<head>
    <title>Calcul</title>
    <meta charset="utf-8">
</head>
<body>
    Valeur de ma variable: <span id="variable1">Pas de communication</span>

     <script src="log1.js"></script>
</body>
</html>


Cdt
Administrateur
Bonjour,

concernant l'attribut defer, un article de dew sur le sujet : Les attributs async et defer pour <script>.

Pour remplacer le test if (élément existe) élément.propriété= faitQqch, il y a cette écriture un peu avancée avec un point d'interrogation (que l'on apprend viiite en se lançant dans TypeScript Smiley ravi ) :

document.getElementById("monId")?.addClass("is-active")
/*                           --^                                    */


- Chaînage optionnel (optional chaining) (MDN FR)
- Chaînage optionnel '?.' (javascript.info FR)
Modifié par Felipe (04 May 2025 - 11:29)