version 1.5.6, dernière mise à jour le 10 octobre 2023.
Le Modèle Objet de Document, ou DOM, Document Object Model est un outil permettant l'accès aux documents HTML
et XML
. Il permet deux choses au développeur :
Il fournit une représentation structurée du document ;
Il codifie la manière dont un script peut accéder à cette structure.
Il s'agit donc essentiellement d'un moyen de lier une page Web, par exemple, à un langage de programmation ou de script.
Il est à remarquer que le DOM ne désigne pas une application particulière, ou bien un produit spécifique ou une présentation propriétaire d'une page Web ou, plus généralement, à un document écrit dans un langage de balisage (comme
XML
par exemple). Il s'agit d'une interface qui permet de standardiser les moyens d'accès à un document balisé, notamment une page Web. Toutes les propriétés et méthodes ainsi que tous les événements disponibles pour le développeur pour manipuler et créer des pages dynamiques sont organisés sous forme de hiérarchies d'objets. Le présent cours va donner les bases permettant d'aborder ce riche domaine.
Il existe maintenant des bibliothèques de scripts comme jQuery, Prototype, MooTools ou dōjō, qui offrent des solutions « clé en main » pour lé développement d'interfaces évoluées. Néanmoins, pour les exploiter au mieux, il est souvent nécessaire d'analyser leur code.
Un langage de marquage comme HTML
ou tout autre langage basé sur XML
peut être schématisé comme une arborescence hiérarchisée. Les différentes composantes d'une telle arborescence sont désignés comme étant des nœuds. L'objet central du modèle DOM est pour cette raison l'objet node
(node = nœud). Il existe différents types de nœuds. Dans un document HTML
ordinaire existent dans tous les cas trois types de nœud importants qu'il nous faut distinguer : les nœuds-élément, les nœuds-attribut, et les nœuds-texte.
Pour comprendre, examinons la construction HTML
simple suivante :
<h1 class="centre">Bonjour</h1>
Dans cette construction, il y a un nœud-élément, à savoir le nœud-élément de l'élément h1
. De plus, il y a un nœud-attribut, à savoir celui de l'attribut class
, et enfin il y a ce qu'on appelle des « données en caractères », que l'on trouve à deux endroits : à savoir une fois comme contenu de l'élément h1
, et une fois pour l'affectation de valeur à l'attribut class
. Ces données en caractères représentent elles-mêmes des nœuds, à savoir des nœuds texte (pour plus de détails, il est nécessaire de se reporter à la définition des éléments et attributs dans un cours de XML
).
Un autre exemple de construction peut aider à mieux comprendre :
<h1 class="centre">Bonjour <i>tout le monde</i> !</h1>
Dans cet exemple est ajouté le marquage en italique du groupe de mots « tout le monde ». Il est important de comprendre maintenant à quoi ressemble la hiérarchie des nœuds.
L'élément h1
a d'après les règles du DOM, trois nœuds enfants et un nœud associé : les nœuds enfants sont le nœud texte avec le mot « Bonjour » suivi d'un espace, le nœud élément de l'élément i
, enfin le nœud texte constitué de la chaîne de caractères " !". L'attribut class
dans la balise ouvrante <h1>
n'est pas par contre un nœud enfant mais un nœud associé. Le nœud attribut a toutefois lui-même un nœud enfant à savoir la valeur affectée (centre
). Même le nœud de type élément i
a, à son tour, un nœud enfant, à savoir le nœud de type texte de son contenu de caractères, donc les mots « tout le monde ».
Tous les nœuds de cette arborescence sont accessibles et manipulables -y compris les propriétés des feuilles de style.
Nous allons dans la suite de ce cours nous limiter à des exemples codés en JavaScript
. Plus précisément, nous allons écrire des scripts en JavaScript
, qui utiliseront le DOM pour manipuler dynamiquement les pages où ils se trouvent. Le DOM n'est pas un langage de programmation, mais sans lui, le JavaScript
ne pourrait avoir aucun modèle pour appréhender la page Web. Par le passé, des méthodes et objets propriétaires ont été utilisés, tant par Netscape
qu'Internet Explorer
, amenant à des « bricolages » de code dès lors que l'on voulait s'assurer qu'un effet DHTML
était accepté par les deux familles de navigateurs.
À l'heure actuelle, il n'est heureusement plus nécessaire de passer par des scripts de détection de navigateur. Des solutions bien plus efficaces sont fournies par des détections fondées non plus sur l'identification du navigateur, mais sur la vérification du support ou non des méthodes nécessaires pour l'utilisation d'un script.
L'objet document
est un objet important, qui représente l'ensemble de l'arborescence du document analysé. Il possède de nombreuses propriétés et méthodes. Cinq de ces dernières permettent de « pointer » directement un ou plusieurs éléments dans le document.
La méthode getElementById
permet de sélectionner un élément d'identifiant donné dans une page. Par exemple, si on a dans la page <p id="intro">(...)</p>
, document.getElementById("intro")
permettra de sélectionner précisément l'élément p
en question.
La méthode getElementsByName
permet de sélectionner les éléments portant un nom donné dans une page ; mais cette méthode, survivance de Netscape
, n'est pas supportée par Internet Explorer
;
La méthode getElementsByTagName
permet de sélectionner les éléments portant un nom de balise donné dans une page.
La méthode querySelector
, qui prend en argument une expression CSS
, permet de cibler directement le premier élément d'un ensemble de nœuds. Par exemple, document.querySelector("#truc");
permet de sélectionner l'élément d'identifiant truc
, mais document.querySelector(".machin");
ne sélectionne que le premier élément de classe machin
.
La méthode querySelectorAll
, qui prend en argument une expression CSS
, permet de cibler tous les éléments d'un ensemble de nœuds. Par exemple, document.querySelectorAll("#truc");
renvoie un tableau d'un item contenant l'élément d'identifiant truc
, et document.querySelectorAll(".machin");
renvoie un tableau contenant tous les éléments de classe machin
.
Un exemple montre comment utiliser les méthodes getElementById
, getElementByName
et getElementsByTagName
.
On peut également accéder aux divers éléments d'un document par leur numéro d'ordre dans ce dernier. Par exemple, les collections document.forms
et document.images
permettent d'accéder aux divers éléments de formulaires et images du document. Cette méthode présente cependant l'inconvénient de fortement dépendre d'une connaissance a priori du nombre d'éléments dans la page ; pour peu que par exemple le nombre d'images change, la numérotation des éléments du tableau doit être revue si l'on veut pouvoir accéder à une image en particulier.
Il existe aussi des méthodes qui, à partir d'un élément donné, permettent d'accéder à certains de ses descendants :
La méthode getElementsByTagName()
, comme précédemment, permet d'obtenir une collection d'éléments descendants de l'élément courant, et possédant un nom de balise donné. Par exemple,
parag1=document.getElementById('monpar') ;
liens=parag1.getElementsByTagName('a') ;
renvoie la collection de liens dans le paragraphe identifié par monpar
.
La méthode getAttribute(nom_d_attribut)
permet de sélectionner un attribut particulier d'un élément déterminé.
Les méthodes précédentes demandent de connaître précisément soit l'identifiant, soit le nom exact du nœud cherché. Nous allons voir maintenant comment il est possible d'accéder à des collections de nœuds dont on ne connaît pas ces caractéristiques a priori.
Dans toute la suite, elt
désignera un élément que l'on aura au préalable identifié (par exemple par une méthode getElementById
).
Contrairement à la méthode getAttribute()
, qui permet de retourner la valeur d'un attribut de nom donné, la propriété attributes
renvoie à la collection complète des attributs d'un élément. Par exemple, si elt
désigne l'élément img
suivant, cette méthode renverra une liste constituée des nœuds
src
, alt
, width
et height
(dans cet ordre) :.
<img src="oiseau.gif" alt="Un oiseau sur un arbre" width="45" height="60">
On peut accéder très facilement à la liste des nœuds-enfants d'un élément donné. Pour cela, trois propriétés existent.
elt.childNodes
donne la liste de tous les nœuds-enfants de l'élément elt
sous la forme d'un tableau.
elt.children
donne la liste de tous les éléments-enfants de l'élément elt
sous la forme d'un tableau.
elt.firstChild
est équivalent à elt.childNodes[0]
, et renvoie le premier nœud-enfant de l'élément elt
.
elt.lastChild
renvoie le dernier nœud-enfant de l'élément elt
.
elt.lastElementChild
renvoie le dernier élément-enfant de l'élément elt
.
Le nœud courant peut avoir des frères. On accède au frère précédent à l'aide de la propriété previousSibling
, et au nœud suivant par la propriété nextSibling
.
On peut enfin remonter d'un cran dans la hiérarchie des nœuds avec la propriété parentNode
, et revenir à l'élément-racine d'un document (dans le cas d'un document HTML
, il s'agit bien sûr de html
), avec la propriété documentElement
.
Quatre collections donnent accès à différents éléments du document :
window.frames
permet d'accéder à la liste des frames du document courant ; chaque élément de cette collection est alors du type window
, et manipulable grâce aux propriétés et méthodes correspondantes (voir le chapitre dédié à la manipulation des fenêtres du navigateur).
document.forms
, document.images
et document.links
sont les collections des éléments de formulaire, d'images et de liens du document.
Deux propriétés permettent d'obtenir des informations sur la nature d'un nœud déterminé : nodeName
et nodeType
.
nodeName
renvoie le nom du nœud courant. Par exemple, si elt
désigne un élément img
, elt.nodeName
renvoie la chaîne de caractères "img"
.
nodeType
est d'un usage moins direct. Cette propriété renvoie au type de nœud du nœud courant, selon un code numérique.
Type de nœud |
Valeur renvoyée par la propriété |
---|---|
element_node |
1 |
attribute_node |
2 |
text_node |
3 |
CDATA_section_node |
4 |
entity_reference_node |
5 |
entity_node |
6 |
processing_instruction_node |
7 |
comment_node |
8 |
document_node |
9 |
document_type_node |
10 |
document_fragment_node |
11 |
notation_node |
12 |
Table 1. Liste des codes numériques renvoyés par la méthode nodeType
.
Deux méthodes renvoient des booléens permettant de déterminer si un nœud donné possède des enfants, et/ou des attributs. Ces méthodes, aux noms explicites, sont respectivement hasChildNodes()
et hasAttributes()
.
Cette création est mise à disposition par Gilles Chagnon sous un contrat Creative Commons.