14 - HTML DOM

Qu’est-ce que le DOM ?

Le DOM (Document Object Model, modèle objet de document) est la représentation qu’un navigateur construit en mémoire à partir d’une page HTML : un arbre dont chaque balise, chaque texte et chaque attribut devient un objet. C’est par cet arbre qu’un programme JavaScript lit la page affichée et la modifie. Le DOM n’est pas un langage de programmation : c’est une interface, identique dans tous les navigateurs, que JavaScript utilise pour agir sur la page.

L’arbre d’une page

Soit le fichier HTML ci-dessous.

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="utf-8">
        <title> arbre du DOM  </title>
    </head>

    <body>
        <h1> Titre principal </h1>

        <section>
            <h2> titre de la section 1 </h2>
            <article>
                <h3> titre article </h3>
                <p> du contenu </p>
            </article>
        </section>

        <section>
            <h2> titre de la section 2 </h2>
            <p> bla bla </p>
        </section>
    </body>
</html>

L’arbre associé à cette page est le suivant :

Chaque case de cet arbre est un nœud. Un document HTML contient trois sortes de nœuds :

  • les éléments, un par balise (html, body, h1, p…) ;
  • les textes, écrits entre les balises ;
  • les attributs (class, id, src…), rattachés à leur élément.

On emploie le vocabulaire des arbres généalogiques : html est la racine ; head et body sont ses enfants ; body est le parent de h1 et des deux section ; les deux section sont des frères.

Exemple. Dans la construction <h1 class="centre"> Bonjour <i> tout le monde </i> ! </h1>, l’élément h1 a trois enfants : le texte « Bonjour », l’élément i (qui a lui-même un enfant, le texte « tout le monde ») et le texte « ! ». L’attribut class appartient à h1 mais n’est pas un enfant dans l’arbre.

Nous allons dans la suite de ce cours écrire des scripts en JavaScript qui utilisent le DOM pour lire et modifier la page où ils se trouvent.

Accéder aux éléments

L’objet document représente la page entière. Quatre de ses méthodes permettent d’atteindre un ou plusieurs éléments.

  • document.getElementById("intro") renvoie l’élément dont l’attribut id vaut intro (un identifiant est unique dans la page).
  • document.querySelector(".machin") renvoie le premier élément qui correspond à un sélecteur CSS (#truc, .machin, p, nav a…).
  • document.querySelectorAll("p") renvoie tous les éléments qui correspondent au sélecteur, dans une liste (NodeList) que l’on parcourt avec for ... of.
  • document.getElementsByTagName("a") renvoie la collection des éléments portant ce nom de balise ; appliquée à un élément (elt.getElementsByTagName("a")), elle ne renvoie que ses descendants.
const intro = document.getElementById("intro");
const premierLien = document.querySelector("nav a");
for (const p of document.querySelectorAll("p")) {
  console.log(p.textContent);
}

Une fois l’élément obtenu, on lit son contenu et ses attributs :

  • elt.textContent : le texte contenu dans l’élément (sans les balises) ;
  • elt.innerHTML : le code HTML contenu dans l’élément ;
  • elt.getAttribute("href") : la valeur d’un attribut ; les attributs courants sont aussi des propriétés (elt.id, elt.src, elt.value pour un champ de saisie).

À partir d’un élément elt, on atteint ses voisins sans connaître leur identifiant :

  • elt.children : la liste de ses éléments enfants ; elt.firstElementChild et elt.lastElementChild : le premier et le dernier ;
  • elt.childNodes : la liste de tous ses nœuds enfants, textes compris (les retours à la ligne du code HTML comptent comme des nœuds texte) ;
  • elt.parentNode : son parent ;
  • elt.nextElementSibling et elt.previousElementSibling : ses frères suivant et précédent.

Deux propriétés renseignent sur la nature d’un nœud : nodeName renvoie son nom ("H1", "#text"…) et nodeType un code numérique.

Type de nœudnodeType
élément1
texte3
commentaire8
document9

Modifier la page

Le DOM permet surtout d’écrire dans la page. Tout changement est immédiatement affiché.

  • elt.textContent = "Nouveau texte" remplace le texte ;
  • elt.innerHTML = "<b>gras</b>" remplace le contenu par du HTML ;
  • elt.setAttribute("src", "photo.png") modifie un attribut ;
  • elt.style.color = "red" modifie le style ; elt.classList.add("important") ajoute une classe CSS ;
  • document.createElement("li") crée un élément en mémoire, que parent.appendChild(nouveau) insère dans la page ;
  • elt.remove() retire l’élément de la page.

Exemple 1 : un compteur.

<p id="compteur">0</p>
<button onclick="incrementer()">+1</button>

<script>
  function incrementer() {
    const p = document.getElementById("compteur");
    p.textContent = Number(p.textContent) + 1;
  }
</script>

Exemple 2 : ajouter un élément à une liste.

<ul id="courses">
  <li>Pain</li>
</ul>
<input type="text" id="article">
<button onclick="ajouter()">Ajouter</button>

<script>
  function ajouter() {
    const li = document.createElement("li");
    li.textContent = document.getElementById("article").value;
    document.getElementById("courses").appendChild(li);
  }
</script>

Réagir aux événements

Un événement est un fait qui se produit dans la page : un clic, une touche enfoncée, une saisie dans un champ, la fin du chargement. Un gestionnaire d’événement est une fonction que le navigateur exécute quand l’événement se produit. Deux écritures sont possibles.

  1. Dans le HTML, avec un attribut onclick, oninput… : <button onclick="incrementer()">. C’est l’écriture des exemples ci-dessus.
  2. Dans le script, avec addEventListener : le HTML ne contient plus de code, et un même élément peut avoir plusieurs gestionnaires.
<input type="text" id="prenom">
<p id="salut"></p>

<script>
  const champ = document.getElementById("prenom");
  champ.addEventListener("input", function (event) {
    document.getElementById("salut").textContent = "Bonjour " + event.target.value;
  });
</script>

La fonction reçoit un objet event qui décrit l’événement : event.target est l’élément concerné, event.key la touche enfoncée, et event.preventDefault() annule l’action par défaut (par exemple l’envoi d’un formulaire).

ÉvénementSe produit quand…
clickl’utilisateur clique sur l’élément
inputle contenu d’un champ de saisie change
changeune sélection ou une saisie est validée
submitun formulaire est envoyé
keydownune touche du clavier est enfoncée
mouseoverla souris entre dans l’élément
loadla page a fini de se charger

Le TD JavaScript fait manipuler ces notions sur sept exemples à tester, et la fiche 29 - JavaScript les met en pratique.