# Introduction au DOM
Le Modèle Objet de Document (DOM: Document object Model) est la représentation en objets de la structure, du style et du contenu d'un document web. L'API du DOM permet d'interagir avec le HTML et le CSS grâce à JavaScript.
# Le DOM : Document Object Model
Lors de la lecture du HTML par le navigateur, il convertit les noeuds (c'est-à-dire les balises, les commentaires, les textes...) en objets manipulables par JavaScript. Les éléments du DOM ne font pas partie du langage JavaScript, et ne sont donc pas standardisés par le TC39 mais par le W3C (opens new window).
Le DOM représente le document HTML sous forme d'arbre : Chaque branche est un nœud, et chaque nœud peut contenir un ou d'autres nœud(s).
Par exemple, à partir de ce code (très simple) :
<body>
<header>
<h1>
Cours ESILV
</h1>
</header>
<ul>
<li>HTML</li>
<li>CSS</li>
</ul>
<footer>Stanislas Ormières</footer>
</body>
Le navigateur générera un arbre ressemblant à ceci :
Chacun de ces rectangles sur le schéma est un objet, avec un (très) grand nombre de propriétés. Ces propriétés permettent de connaître de façon programmatique leur contenu, les attributs de la balises, le nom de la balise et d'y attacher des événements (cf. plus loin). On peut aussi changer le contenu, les attributs et leurs valeurs, changer le type de balise (changer le "h1" par un "h2", ajouter une classe CSS...), on peut aussi supprimer du contenu et en ajouter.
Pour plus de détails, visiter l'introduction au DOM sur le MDN (opens new window)
# L'objet document
C'est le point d'entrée du DOM : il contient une représentation de tous les objets de la page (visibles ou non) et une (très) grande quantité de méthodes et propriétés utiles.
Quelques exemples de commandes que vous pouvez taper dans les dev-tools du navigateur :
console.dir(document)
console.dir(document.head)
console.dir(document.body)
console.dir(document.images)
Par exemple, pour console.dir(document.images)
sur cette page, vous verrez quelque chose comme ceci :
HTMLCollection
0: <img class="logo" src="/assets/img/ninja@mini.png" alt="Cours développement web ESILV">
1: <img src="/assets/img/DOM-example.a76141e9.png" alt="Representation DOM">
length: 2
<prototype>: HTMLCollectionPrototype { item: item(), namedItem: namedItem(), length: Getter, … }
C'est-à-dire la liste des éléments images de cette page.
# Récupérer les éléments du DOM
La manipulation des éléments du DOM nécessite d'abord de récupérer ces éléments. L'API DOM fournit plusieurs méthodes pour cela. Regardons celles que nous utiliserons le plus.
# document.getElementById()
Sur cette page, si vous tapez ceci dans la console du navigateur :
const anH2 = document.getElementById('l-objet-document')
console.dir(anH2)
anH2
est un objet représentant l'élement h2
ayant dans son attribut id
la valeur 'l-objet-document'
Vous obtiendrez une sortie ressemblant à ceci :
h2#l-objet-document
accessKey: ""
accessKeyLabel: ""
align: ""
assignedSlot: null
attributes: NamedNodeMap [ id="l-objet-document" ]
baseURI: "http://localhost:8080/dom/#le-dom-document-object-model"
childElementCount: 2
childNodes: NodeList(3) [ a.header-anchor, #text, code
]
children: HTMLCollection { 0: a.header-anchor, 1: code
, length: 2 }
classList: DOMTokenList []
className: ""
clientHeight: 111
clientLeft: 0
clientTop: 0
clientWidth: 497
contentEditable: "inherit"
contextMenu: null
dataset: DOMStringMap(0)
dir: ""
draggable: false
firstChild: <a class="header-anchor" href="#l-objet-document">
firstElementChild: <a class="header-anchor" href="#l-objet-document">
hidden: false
id: "l-objet-document"
innerHTML: "<a href=\"#l-objet-document\" class=\"header-anchor\">#</a> L'objet <code>document</code>"
(...)
# document.getElementsByTagname()
On peut aussi récupérer tous les éléments de la page ayant un type de balise particulier, comme h2
grâce à la méthode
getElementsByTagname()
(opens new window) de l'objet document
:
var listOfH2 = document.getElementsByTagName('h2')
Comme évoqué plus tôt,
listOfH2
sera une liste d'éléments HTML sous la forme d'un objet HTMLCollection
(opens new window),
mais pas un véritable Array. Ce qui veut dire qu'on ne pourra pas utiliser directement les méthodes de
Array.prototype
(opens new window).
Cependant, on peut facilement transformer cet objet en Array avec la méthode
Array.from()
(opens new window)
# document.getElementsByClassname()
On peut aussi récupérer tous les éléments de la page ayant une classe particulière, comme extra-class
grâce à la méthode
getElementsByClassName()
(opens new window) de l'objet document
:
var listOfElts = document.getElementsByClassName('extra-class')
L'objet retourné sera aussi de type HTMLCollection
(opens new window)
# document.querySelector()
et document.querySelectorAll()
Les méthodes précédentes sont des méthodes très anciennes, mais les besoins en manipulation du DOM ayant énormément grandi, de nouvelles méthodes ont été créées, qui sont plus pratiques. Elles nécessitent de connaître les sélecteurs CSS (opens new window), au moins ceux que nous avons vu précédemment.
document.querySelector()
ne renvoie qu'un élément, quel que soit le nombre d'éléments sur la page qui
correspondent au sélecteur CSS utilisé :
var firstEltWithExtraClass = document.querySelector('.extra-class') // Notez le . du début
Cette méthode renvoie un élément DOM (opens new window).
var allEltsWithExtraClass = document.querySelectorAll('.extra-class')
L'objet retourné est cette fois non pas un objet HTMLCollection
mais un objet de type
NodeList
(opens new window),
qui est aussi un Array-like, et donc aussi transformable facilement en Array
avec
Array.from()
(opens new window).
# L'interface Element
Maintenant que nous avons savons sélectionner et récupérer les éléments, nous allons voir comment les manipuler. Les éléments DOM sont de plusieurs types et leurs propriétés changent en fonction de cela.
# Le texte des éléments
# La propriété innerText
On peut récupérer le texte d'un élément avec la propriété innerText
des éléments :
var h1 = document.querySelector('h1')
var titleText = h1.innerText
console.log(titleText) // #
// Introduction au DOM
Cette propriété récupère tout le texte de l'élément, même le texte des éléments qui sont imbriqués :
var sidebarText = document.querySelector('.sidebar').innerText
console.log(sidebarText) /*
"Home
Intro
Chapitres
Introduction au DOM
Le DOM : Document Object Model
L'objet document
Récupérer les éléments du DOM
La méthode document.getElementById
La méthode document.getElementsByTagname()
La méthode document.getElementsByClassname()
Les méthodes document.querySelector() et document.querySelectorAll()
L'interface Element
Le texte des éléments"
*/
Il est possible de changer le texte facilement avec cette propriété :
var h1 = document.querySelector('h1')
h1.innerText = 'Nouveau texte sans intérêt'
Si ce code est exécuté sur une page en cours (qui a une balise h1
), le texte sera remplacé.
# La propriété textContent
La propriété textContent
est similaire, à 2 nuances près :
- Elle va retourner tout le texte, même celui qui n'est pas visible par l'utilisateur, comme
ceux dans les éléments
<script>
ou dans les éléments avecdisplay: none
- Elle va garder le formatage et les espaces blancs
# La propriété innerHTML
La propriété innerHTML
(attention à la casse : HTML est tout en majuscule) des éléments permet de retourner et de modifier le contenu de l'élément.
var h1 = document.querySelector('h1')
var inH1 = h1.innerHTML
console.log(inH1) // <a href="#introduction-au-dom" class="header-anchor">#</a> Introduction au DOM
On peut affecter une nouvelle valeur à cette propriété, et comme pour innerText
, le résultat sera visible
immmédiatement. La différence est qu'on peut y mettre du HTML et qu'il sera interprété comme tel.
Voici un exemple :
var h1 = document.querySelector('h1')
h1.innerHTML = 'Je peux mettre du <em>HTML</em> !'
Il existe d'autres moyens d'insérer de nouveaux éléments, de les remplacer et de les effacer que d'utiliser innerHTML
,
nous le verrons.
# Récupérer la valeur d'un champ d'entrée utilisateur (input
)
Les éléments de type input
n'ont pas de HTML ni de texte à l'intérieur, il faut donc utiliser une autre propriété pour
récupérér leur valeur : value
.
La propriété value
est modifiable :
loginElt.value = 'nouvelle valeur'
# Un mot sur les types checkbox
et radio
Les input
de type checkbox
et radio
auront toujours la même valeur, il faudra donc non pas voir la valeur de value
,
mais la valeur de checked
, c'est-à-dire voir s'ils sont cochés.
# Les événements
(... Suite en cours d'écriture).