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, noeud ou texte, à l’exception du noeud 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.

Visualiser les éléments du DOM

Accéder à un élément

Solution classique

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 noeud 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 noeuds 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 noeud "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 noeud 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); }

Identifier un élément

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

Les noeuds 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 noeud 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 :

Modifier les éléments du DOM

Ajouter un élément

Modifier les propriétés "innerHTML" d’un noeud ou "nodeValue" d’un texte change son contenu. Mais l'ancien contenu est remplacé par le nouveau. L'objectif ici est d'ajouter du contenu à celui déjà existant ou de supprimer une partie seulement du contenu déjà présent.

L’objet document possède les méthodes "createElement" et "createTextNode". La première est utilisée pour créer un noeud, 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 noeud.

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, noeud ou texte. Elle doit être appelée sur le parent du noeud à 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>

Changer le contenu d'un élément

Pour remplacer le contenu d'un élément par un autre contenu, une solution classique consiste à modifier la propriété "innerHTML" de l'élément. Par exemple :

document.getElementById("identifiant").innerHTML="Un texte...";
On notera que la propriété "innerHTML" permet de récupérer et de modifier ce qui est contenu entre deux balises. La propriété "outerHTML", moins connue, permet de récupérer les deux balises et ce qu'elles contiennent. Par exemple, le code ci-dessous permet de supprimer toutes les balises de classe "bleu".

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

Modifier 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";

Modifier, ajouter un attribut à un élément

Cas général

On vient de voir comment créer une balise avec du contenu. On peut également ajouter n'importe quel attribut de balise, avec la méthode "setAttribute".

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

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