LE MODELE OBJET DU DOCUMENT

Introduction

Le JavaScript s'appuie de plus en plus sur le DOM. Il permet de visualiser, d'ajouter ou d'enlever des éléments d'un document HTML.

Lorsque du code HTML est interprété par un navigateur, celui-ci crée, à partir de ce code, une interface de programmation appelée modèle objet du document, ou document objet model en anglais, ou plus simplement DOM. Les navigateurs évoluant avec le temps, il existe plusieurs niveaux pour le DOM, le dernier étant le niveau 3 datant de 2004.

Une page HTML est constituée de balises à l'intérieur desquelles se trouvent d'autres balises. Du fait de cette forme hiérarchique, le DOM construit une arborescence de la structure du document et de ses éléments.

Dans l'exemple ci-dessus, on trouve :

Chaque élément, nœud ou texte, à l’exception du nœud de premier niveau, la racine <html>, est contenu dans un autre élément, son parent. Cet élément peut, en retour, contenir d’autres éléments enfants. On notera que les textes n’ont jamais d’enfants.

Identifier les éléments du DOM

Accéder à un élément

Solution classique

Le DOM comporte de nombreuses interfaces : Window, Document, Node... On accède aux éléments du DOM avec les propriétés de l'interface document.

Propriété Utilité
document.documentElement Permet d'accéder au premier élément du DOM, le nœud html.
document.body Permet d'accéder à la partie body du document.
document.getElementById(identifiant) Permet d'accéder à un élément auquel on a associé un identifiant unique.
document.getElementsByTagName(balise) Retourne un tableau donnant accès aux divers nœuds trouvés.
document.getElementsByClassName(classe) Retourne un tableau donnant accès aux divers éléments de même classe.
document.images Retourne un tableau donnant accès aux images contenues dans la page.

Exemple :

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8">
  <style>
    .vert { color: #0a0; }
  </style>
  <script>
    onload=function() {
      alert(document.documentElement.innerHTML);
      alert(document.body.innerHTML);
      alert(document.getElementById("para").innerHTML);
      alert(document.getElementsByTagName("P")[1].innerHTML);
      alert(document.getElementsByClassName("vert")[1].innerHTML);
    };
  </script>
  </head>
  <body>
    <h1>Un titre...</h1>
    <p id="para" class="vert">Un texte...</p>
    <p><input type="button" value="OK"></p>
    <div id="vue" class="vert">La suite du texte...</div>
  </body>
</html>

Sinon, chaque élément du DOM possède aussi des propriétés :

Propriété Utilité
parentNode Permet d'accéder à l'élément parent, si parent il y a.
childNodes Retourne un tableau donnant accès aux divers éléments enfants.
firstChild Permet d'accéder au premier élément enfant.
lastChild Permet d'accéder au dernier élément enfant.

Dans l'exemple d'application ci-dessous, lorsqu'on clique sur le bouton OK, le nombre d'éléments enfants du nœud body s'affiche dans une petite fenêtre.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script>
      function voir() {
        var ch="";
        ch+="Nombre d'enfants du nœud body : ";
        ch+=document.body.childNodes.length;
        alert(ch);
      }
    </script>
  </head>
  <body>
    <h1>Un titre...</h1>
    <p id="para">Un texte...</p>
    <p><input type="button" value="OK" onclick="voir();"></p>
    <div id="vue">La suite du texte...</div>
  </body>
</html>

Solution plus récente

Deux méthodes, querySelector() et querySelectorAll(), simplifient la sélection d'éléments dans l'arbre du DOM. Elles prennent pour paramètre un sélecteur CSS sous la forme d'une chaîne de caractères.

Propriété Utilité
querySelector() Retourne le premier élément trouvé.
querySelectorAll() Retourne un tableau contenant tous les éléments trouvés.

Dans l'exemple ci-dessous, couleur est un tableau donnant accès à tous le éléments de classes vert ou bleu.

var couleur=document.querySelectorAll('.vert , .bleu');

Une convention

Parce que document.getElementById est un nom plutôt long pour une opération assez commune, l’abréger par la variable $ est devenu une convention assez commune au sein des développeurs JavaScript. Attention à ne pas confondre cette variable avec l'objet $ de jQuery!

function $(id) { return document.getElementById(id); }

Reconnaître un élément

La propriété nodeType permet de savoir si un élément représente un nœud ou un texte. Elle contient un nombre, 1 pour un nœud et 3 pour un texte.

Les nœuds ont une propriété nodeName, indiquant le type de balise HTML qu’ils représentent.

Exemple de code :

for (var i=0; i<document.body.childNodes.length; i++) {
  ch+="Type de l'enfant "+i+" : "+document.body.childNodes[i].nodeType+"<br>";
  ch+="Nom de l'enfant "+i+" : "+document.body.childNodes[i].nodeName+"<br><br>";
}

Visualiser le contenu d'un élément

Il y a deux cas de figures, selon que l'élément soit un nœud ou un texte :

Exemple de code :

alert(document.body.innerHTML);
alert(document.body.childNodes[1].firstChild.nodeValue);
ch+=document.body.innerHTML+"<br><br>";
ch+=document.body.childNodes[1].firstChild.nodeValue;

Inspecteur du DOM

L’utilisation d'un inspecteur DOM aide à comprendre le contenu d'une page HTML.

Exemple de code :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test DOM</title>
  </head>
  <body>
    <h1>Un titre...</h1>
    <p id="para">Un paragraphe...</p>
  </body>
</html>

Résultat donné par l’inspecteur DOM de Firefox :

Gérer le contenu d'un élément

Avec document.write();

La méthode document.write(); ajoute du contenu là où est situé le script. Très utilisée autrefois, cette solution présente peu d'intérêt de nos jours. Exemple :

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <script>
      function test() { document.write("Bienvenue!"); }
    </script>
  </head>
  <body>
    Bonjour
    <script>document.write("<i>Léa.</i>");</script>
    Veuillez
    <button type="button" onclick="test()">cliquer</button>
  </body>
</html>

Dans le code ci-dessus, un clic sur le bouton remplace le contenu de la page par celui défini dans la fonction test().

Avec innerHTML

La propriété innerHTML donne accès, en lecture comme en écriture, au contenu placé entre une balise entrante et la balise fermante correspondante. Le contenu est formaté selon les balises qu'il contient. Exemple :

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p id="message">Bonjour!</p>
    <script>document.getElementById("message").innerHTML="<b>Au revoir.</b>";</script>
  </body>
</html>

Note

Cette solution s'utilise plutôt en lecture. En écriture elle pose, dans certains cas, des problèmes de sécurité, de compatibilité avec certains navigateurs, de corruption du DOM (gestion des événements). Elle est peu performante quand il s'agit :

Variantes

function supprime_classe_bleu() {
  var tab_bleu=document.getElementsByClassName("bleu");
  while (tab_bleu.length) {
    tab_bleu[0].outerHTML=tab_bleu[0].innerHTML ;	         	
  }
}

Avec insertAdjacentHTML();

La méthode insertAdjacentHTML(); insère du contenu à la position spécifiée. Les quatre positions possibles sont définies avec les paramètres beforebegin, afterbegin, beforeend ou afterend : Avant ou après les balises ouvrante ou fermante. Exemple :

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p id="message">Bonjour </p>
    <script>
      suite="<b>à tous!</b>";
      document.getElementById("message").insertAdjacentHTML('beforeend',suite);
    </script>
  </body>
</html>

Note

Cette solution, bien pratique, reste toutefois limitée à l'ajout de contenu.

Variante

insertBefore() : Bien que moins facile à utiliser, cette méthode plus ancienne a probablement une meilleure compatibilité avec les anciens navigateurs.

Avec createElement() et appendChild()

Ajouter un élément

L’objet document possède les méthodes createElement() et createTextNode(). La première est utilisée pour créer un nœud, la seconde pour créer un texte.

balisage=document.createElement("H2");
sous_titre=document.createTextNode("Un sous-titre...");

Pour mettre le sous-titre dans l’élément h2, puis ajouter cet élément au document, une solution consiste à faire appel à la méthode appendChild(). Elle peut être appelée sur chaque nœud.

balisage.appendChild(sous_titre);
document.body.appendChild(balisage);

Plus simplement peut-être, on peut aussi écrire :

balisage=document.createElement("H2");
balisage.innerHTML="Un sous-titre...";
document.body.appendChild(balisage);

Naturellement, il est possible de placer un élément et son contenu à n'importe quel endroit de la page. Exemple :

suite=document.createElement("P");
suite.innerHTML="Un schéma explicatif : ";
document.getElementById("paragraphe_2").appendChild(suite);
schema=document.createElement("IMG");
schema.src="schema.png";
suite.appendChild(schema);

Enlever un élément

La méthode removeChild() supprime un élément enfant, nœud ou texte. Elle doit être appelée sur le parent du nœud à supprimer, en lui donnant l’enfant comme argument.

Exemple de code :

document.body.removeChild(document.body.childNodes[1]);

Autre exemple, permettant de supprimer une ligne de tableau en cliquant sur le lien correspondant.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script>
      function suppr(n) {
        ligne_a_sup=document.getElementById(n);
        ligne_a_sup.parentNode.removeChild(ligne_a_sup);
      }
    </script>
  </head>
  <body>
    <table border="1">
      <tr id="l0"><td>Ligne 1</td><td onclick="suppr('l0');">Sup</td></tr>
      <tr id="l1"><td>Ligne 2</td><td onclick="suppr('l1');">Sup</td></tr>
      <tr id="l2"><td>Ligne 3</td><td onclick="suppr('l2');">Sup</td></tr>
      <tr id="l3"><td>Ligne 4</td><td onclick="suppr('l3');">Sup</td></tr>
      <tr id="l4"><td>Ligne 5</td><td onclick="suppr('l4');">Sup</td></tr>
    </table>
  </body>
</html>

Un code similaire, qui permet de se passer des identifiants :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script>
      function suppr(ligne_a_sup) {
        ligne_a_sup.parentNode.removeChild(ligne_a_sup);
      }
    </script>
  </head>
  <body>
    <table border="1">
      <tr><td>Ligne 1</td><td onclick="suppr(this.parentNode);">Sup</td></tr>
      <tr><td>Ligne 2</td><td onclick="suppr(this.parentNode);">Sup</td></tr>
      <tr><td>Ligne 3</td><td onclick="suppr(this.parentNode);">Sup</td></tr>
      <tr><td>Ligne 4</td><td onclick="suppr(this.parentNode);">Sup</td></tr>
      <tr><td>Ligne 5</td><td onclick="suppr(this.parentNode);">Sup</td></tr>
    </table>
  </body>
</html>

Gérer les attributs d'un élément

Cas général

Créer un nouvel attribut

On peut ajouter un nouvel attribut de balise ou changer sa valeur avec la méthode setAttribute(). Exemple :

cadre=document.createElement("iframe");
cadre.setAttribute('src','http://eleydet.free.fr/');
document.body.appendChild(cadre);

Lire la valeur d'un attribut

On lit la valeur d'un attribut de balise avec la méthode getAttribute(). Exemple :

var url = cadre.getAttribute('src');

Avant de lire sa valeur, on peut vérifier l'existence de l'attribut avec la méthode hasAttribute().

var existe = cadre.hasAttribute('src'); // true ou false

Supprimer un attribut

On peut retirer un attribut de balise avec la méthode removeAttribute(). Exemple :

cadre.removeAttribute('src');

Cas particuliers

Les cas les plus courants ont une solution plus directe. Exemples :

mon_element.className="nouvelle_classe";
mon_element.id="nouvel_identifiant";
mon_lien.href="page.html";
mon_image.src="nom_image.png";

Gérer le style d'un élément

Pour changer la valeur d'une propriété de style, il suffit de modifier la propriété style de l'élément. Exemples :

document.getElementById("identifiant").style.display="none";
document.getElementById("identifiant").style.color="#2b6";
document.getElementById("identifiant").style.width="60%";
document.getElementById("identifiant").style.backgroundColor="#36b";
document.getElementById("identifiant").style["background-color"]="#36b";
document.getElementById("identifiant").style.textAlign="center";
document.getElementById("identifiant").style["text-align"]="center";