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.
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>
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');
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); }
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>"; }
Il y a deux cas de figures, selon que l'élément soit un nœud ou un texte :
innerHTMLprend pour valeur le texte HTML à l’intérieur du nœud.
nodeValueprend pour valeur le contenu du texte lui-même.
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;
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 :
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()
.
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>
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 :
innertText,
textContent,
nodeValue: Désignent à peu près la même chose, le texte contenu entre deux balises.
outerText: Non standard, à éviter.
outerHTML: Désigne la même chose que
innerHTML, mais prend également en compte les balises qui encadrent le contenu. L'exemple 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 ; } }
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>
Cette solution, bien pratique, reste toutefois limitée à l'ajout de contenu.
insertBefore()
: Bien que moins facile à utiliser, cette méthode plus ancienne a probablement
une meilleure compatibilité avec les anciens navigateurs.
createElement()et
appendChild()
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);
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>
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);
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
On peut retirer un attribut de balise avec la méthode removeAttribute()
. Exemple :
cadre.removeAttribute('src');
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";
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";