CentraleSupélecDépartement informatique
Gâteau du Glouton
3 rue Joliot-Curie
F-91192 Gif-sur-Yvette cedex
DOM: ''Document Object Model''

Introduction

Un document XML ou HTML peut être vu sous la forme d'un arbre:

DOM est conçu pour XML de façon générique, et comporte des objets dédiés à HTML. Il s'agit d'un modèle abstrait, indépendant du langage :

  • Spécification officielle en IDL
  • Interfaces officielles pour Java et ECMAScript
  • Implémentations pour Java, JavaScript (navigateurs),
  • et presque tous les autres langages

Il s'agit d'une approche objet du modèle d'arbre: Chaque nœuds est un objet, et des méthodes permettent d'accèder aux noeuds en relation avec un noeud donné.

Les principaux types de nœuds sont:

  • Document: la racine
  • Element: les balises standards
  • Text: le... texte
  • Comment: les commentaires
  • Attr: les attributs des balises
  • Processing instructions: les balises spécifiques comme par exemple <?php...?>

La navigation dans l'arbre se fait en appelant:

  • le parent d'un noeud
  • les fils d'un noeud (child)
  • les attributs d'un noeud
  • les noeud-frères (sibling)

DOM en Javascript

Lorsqu'une page internet se charge, un objet particulier est créé: l'objet window.document. Il propose en particulier des « raccourcis » pour accéder à certains éléments d'une page web.

Attention: L'objet document n'est disponible qu'une fois que la page est complètement chargée, après l'événement load (voir le tuto qui parle de la gestion des évènements).

A partir du nœud « window.document » :

  • window.document.head : élément <head>
  • window.document.title : élément <title>
  • window.document.body : élément <body>

Et aussi:

  • window.document.images : collection d'éléments <img>
  • window.document.links : collection d'éléments <a>
  • window.document.forms : collection d'éléments <form>

Par exemple, si avec Firefox depuis cette page vous lancez la console javascript (Ctrl+Shift+K) et que vous exécutez:

var d = window.document;
console.log(d.title); 

la console doit vous répondre :

DOM: ''Document Object Model''

c'est à dire le titre de la page à comparer avec ce qu'il y a dans le source (Ctrl+U pour y accèder).

Exploration générique de l'arbre

Sur n'importe quel nœud « n », on peut obtenir son nom et son type:

  • n.nodeName : chaîne de caractères
  • n.nodeType : entier (1: élément, 2: attribut, 3: texte, … voir la liste complète)
  • n.nodeValue : chaîne de caractères (pour nœuds attributs et texte)

Mais aussi ses attributs:

  • n.hasAttributes() : booléen
  • n.attributes : collection ordonnée des attributs (se traite comme un tableau)

Sa relation verticale dans l'arbre:

  • n.parentNode : objet
  • n.hasChildNodes() : booléen
  • n.childNodes : collection ordonnée des noeuds fils (se traite comme un tableau)
  • n.firstChild : objet
  • n.lastChild : objet

Et sa relation parallèle dans l'arbre:

  • n.previousSibling : objet
  • n.nextSibling : objet

On peut enfin savoir quel est le window.document racine de l'arbre:

  • n.ownerDocument : objet

Exemple

Ouvrez la page exemple.html dans firefox, et

  • ouvrez la console (Ctrl+Shift+K dans firefox)
  • ouvrez le source de la page (Ctrl+U):
  • ouvrez le scratchpad javascript (Shift+F4)

Que donne les instructions ? (Attention, il faut que le focus de la fenêtre soit bien sur la page à considèrer, donc exemple.html), et pas sur son code soure, quand vous faites la manip).

console.log(window.document.titre);
console.log(window.document.body.childNodes[0]);
console.log(window.document.body.childNodes[0].nodeType);
  • Le noeud commentaire est parmis les fils du noeud body: quel est son index dans la liste ?
  • Quelle valeur rend nodeType sur le commentaire ?
  • Pouvez-vous afficher le texte de la deuxième balise <h1> dans la console ?
  • Notez comme les espaces entre les balises forment bien des noeuds textes.

Recherche dans l'arbre

On peut rechercher des éléments et des attributs:

Éléments

À partir du noeud document, peut chercher un élément par son attribut id

var e = window.document.getElementById(idOfElement); // l'élément portant l'identifiant donné

À partir d'un noeud quelconque, on peut rechercher dans son sous-arbre un ensemble (ordonné) d'éléments filtré par le nom de leur balise. Par exemple, dans l'exemple précédant, si on place dans le scratchpad:

"use strict";
var elements = window.document.getElementsByTagName("h1");
for(var i = 0; i < elements.length; i++){
   console.log(elements[i].nodeName);               // "H1"
   console.log(elements[i].firstChild.nodeValue);   // --> le titre en question
}

on récupère les deux noeuds <h1> et on peut directement afficher leur texte.

Attributs

A partir d'un nœud de type élément « e » :

  • e.id : chaîne de caractères (si l'élément a un id...)

et de façon générale:

  • e.hasAttribute(name) : booléen
  • e.getAttribute(name) : chaîne de caractères

On peut aussi modifier les attributs d'un noeud:

  • e.setAttribute(name, value)
  • e.removeAttribute(name)

Dans l'exemple précédant, comme on sait récupérer les éléments correspondant aux balises <h1>, on peut leur mettre de la couleur en leur ajoutant un attribut style bien choisi:

"use strict";
var elements = window.document.getElementsByTagName("h1");
for(var i = 0; i < elements.length; i++){
  elements[i].setAttribute("style","color:red;"); 
}

Si cela ne nous convient pas:

"use strict";
var elements = window.document.getElementsByTagName("h1");
for(var i = 0; i < elements.length; i++){
  elements[i].removeAttribute("style");
}

Modification de l'arbre

Outre l'ajout et la suppression d'attribut, l'interface DOM permets de rajouter ou de supprimer des noeuds quelconques.

L'ajout d'un noeud se fait en deux temps:

  • fabrication du noeud
  • puis quand il est prêt, insertion dans l'arbre DOM.

La suppression d'un noeud se fait directement, bien sûr.

Création de noeuds

Comme ces noeuds seront dans l'arbre dont la racine est le noeud document, toutes ces fonctions sont des méthodes de window.document. On trouve en particulier:

  • window.document.createElement(tagName) : retourne l'élément créé
  • window.document.createElementNS(namespaceURI, tagName) : pour fixer un espace de nom à l'élément ; retourne l'élément créé
  • window.document.createTextNode(text) : retourne le nœud texte créé
  • window.document.createComment(text) : retourne le nœud commentaire créé
  • window.document.createAttribute(name) : retourne le nœud attribut créé

Modification de l'arbre DOM

On peut ensuite placer ces noeuds comme fils ou noeuds-frères dans l'arbre. Si "n" est n'importe quel noeud:

  • n.removeChild(nodeToRemove) : retourne l'objet supprimé
  • n.insertBefore(nodeToInsert, childRef) : retourne l'objet inséré
  • n.appendChild(nodeToAppend) : retourne l'objet inséré
  • n.replaceChild(newNode, oldNode) : retourne l'objet remplacé
  • n.cloneNode(deepOrNot) : retourne l'objet résultat de la copie

Exemple

Création d'un noeud <h1>

Que se passe-t-il si vous appliquez ces instructions dans le scratchpad de l'exemple du dessus ?

Conclusion

JavaScript + DOM = pages web dynamiques !

Plus loin? nous verrons ensuite comment Jquery facilitera énormément l'écriture de vos programmes JavaScript ! Nous verrons aussi comment utiliser javascript coté serveur.

Petits bémols :

  • Il est possible de faire n'importe quoi en JavaScript... Trop de JavaScript tue le JavaScript !
  • Il peut y avoir des problèmes de compatibilité entre navigateurs (JS & DOM)