Manipuler une page web avec le Document Object Model

Programmation web - Client riche

Objectifs

  • Comprendre ce qu'est le DOM conceptuellement
  • Apprendre à récupérer des éléments de la page
  • Apprendre à manipuler ces éléments
  • Appendre à créer de nouveaux éléments
  • Apprendre à supprimer des éléments

L'environnement du navigateur (1)

window
document
navigator
screen
location
frames
history
XMLHttpRequest
Object
Array
Function
JavaScript
BOM
DOM
Object
Array
Function
JavaScript

C'est ce qu'on a vu au cours précédent : les objets et fonctions qui sont le coeur du langage JavaScript (communs à tous les environnements)

...

L'environnement du navigateur (2)

navigator
screen
location
frames
history
XMLHttpRequest
BOM

Le Browser Object Model regroupe des API propres au navigateur. Elles nous permettent d'obtenir des détails sur l'OS, le navigateur et l'écran de l'utilisateur. Mais aussi de manipuler l'historique du navigateur ou de faire des requêtes sur le réseau.

L'environnement du navigateur (3)

Le Document Object Model est une représentation de la structure HTML de la page sous forme d'arbre d'objets représentant les différents noeuds du document

document
DOM

L'environnement du navigateur (4)

Le DOM : qu'est-ce que c'est ?

Le DOM : définition

Le Document Object Model ou DOM (pour modèle objet de document) est une interface de programmation pour les documents HTML, XML et SVG. Il fournit une représentation structurée du document sous forme d'un arbre et définit la façon dont la structure peut être manipulée par les programmes, en termes de style et de contenu. Le DOM représente le document comme un ensemble de nœuds et d'objets possédant des propriétés et des méthodes. Les nœuds peuvent également avoir des gestionnaires d'événements qui se déclenchent lorsqu'un événement se produit. Cela permet de manipuler des pages web grâce à des scripts et/ou des langages de programmation.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mon super site</title>
  </head>
  <body>
    <h1>Bienvenue sur mon super site</h1>
    <p>Ceci est un paragraphe</p>
    <div>Et ceci est une div</div>
  </body>
</html>
html
head
meta
body
title
text
h1
p
text
text
div
text

Réprésentation sous forme d'abre

Il y a un inspecteur de DOM dans les outils de développement de votre navigateur (F12 ou CTRL+SHIFT+I)

  • Modifier des éléments présents sur la page
    • Contenu, style, attributs...
  • Supprimer des éléments présents sur la page
  • Ajouter des éléments à la page

A quoi sert le DOM ?

Rechercher des éléments dans le DOM

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mon super site</title>
  </head>
  <body>
    <h1>Hello world</h1>
    <p>
      Ceci est un paragraphe
    </p>
    <div>Ceci est une div</div>
  </body>
</html>

Rechercher des élément dans le DOM (1)

Rechercher des élément dans le DOM (2)

html
head
meta
body
title
text
h1
p
text
text
div
text

L'objet `document` nous donne des références directes vers certains éléments clef du DOM

document.documentElement
document.body
document.head
<body>
<html>
<head>
<h1>
<p>
<div>

parentNode

parentNode

firstChild

parentNode

firstChild

parentNode

lastChild

parentNode

lastChild

nextSibling

previousSibling

nextSibling

previousSibling

Rechercher des élément dans le DOM (3)

Les éléments ont des relations les uns avec les autres

<body>
<div>
<div>

parentNode

firstChild

parentNode

nextSibling

previousSibling

Rechercher des élément dans le DOM (4)

const body = document.body

const div = body.firstChild.nextSibling

On peut donc théoriquement accéder à n'importe quel élément à partir d'un des éléments clef

Mais ça va vite devenir long quand on va avoir des critères plus compliqués...

Rechercher des élément dans le DOM (5)

On connait déjà un mécanisme de "ciblage" des éléments HTML : les sélecteurs CSS. Et si on pouvait réutiliser cette syntaxe pour cibler des éléments en JS ?

document.querySelector(sélecteur CSS)

Permet de récupérer le premier élément correspondant au sélecteur CSS passé en paramètre (ou null si aucun ne correspond)

document.querySelectorAll(sélecteur CSS)

Permet de récupérer une liste contenant tous les éléments correspondants au sélecteur CSS passé en paramètre

Rechercher des élément dans le DOM (6)

<body>
<div>
<div>
const div = document.querySelector("div:nth-child(2)")

// => <div></div>
<body>
<div>
const divs = document.querySelectorAll("div")

// => NodeList [2 items]
<div>

querySelectorAll ne renvoie pas un Array, mais une NodeList. Cet objet ressemble à un Array, mais n'en possède pas toutes les méthodes utiles. Il est toutefois possible de transformer une NodeList en Array :

Array.from(document.querySelectorAll(".important"))

querySelector et querySelectorAll peuvent être appliqués au document ou sur un élément :

const element = document.querySelector(".js-element")
const subelement = element.querySelector(".js-subelement")

Modifier un élément du DOM

Récupérer / modifier le contenu d'un élément

<p>
  Lorem <strong>ipsum</strong> dolor
  sit amet consectetur adipiscing
</p>
const p = document.querySelector("p")

p.innerHTML
// => "Lorem <strong>ipsum</strong> dolor sit amet consectetur adipiscing"

p.innerHTML = "Lorem <em>ipsum</em> dolor"

Récupérer/modifier le contenu d'un élément (1)

<p>
  Lorem <strong>ipsum</strong>
  <span style="display: none;">hidden text</span>
  dolor sit amet consectetur adipiscing
</p>
const p = document.querySelector("p")

p.innerText
/*
 Lorem ipsum dolor sit amet consectetur adipiscing
*/

p.innerText = "Lorem <em>ipsum</em> dolor"

Récupérer/modifier le contenu d'un élément (3)

<p>
  Lorem <strong>ipsum</strong> <span style="display: none;">hidden text</span>
  dolor sit amet consectetur adipiscing
</p>
const p = document.querySelector("p")

p.textContent
/*
Lorem ipsum hidden text dolor sit amet consectetur adipiscing     
*/

p.textContent = "Lorem <em>ipsum</em> dolor"

Récupérer/modifier le contenu d'un élément (4)

Récupérer/modifier le contenu d'un élément (5)

Propriété Valeur retournée Comportement à l'affectation
innerHTML Contenu HTML Prend en compte les éléments HTML
innerText Contenu textuel (en tenant compte du style) Echappe les éléments HTML
textContent Contenu textuel (sans tenir compte du style) Echappe les éléments HTML

Récupérer / modifier des attributs d'un élément

<input
  id="login"
  name="login"
  placeholder="Enter your login"
/>
const input = document.querySelector("#login")

input.id // => "login"
input.name // => "login"
input.placeholder // => "Enter your login"

input.id = "login-field"
// <input id="login-field" ... />

Récupérer / modifier des attributs d'un élément (1)

On peut mettre n'importe quel attribut sur un élément HTML. Mais seuls ceux listés comme étant valides pour cet élément dans la spécification seront disponibles en propriétés de l'objet représentant l'élément en JS

<div id="container" data-current-state="loading">
  Loading...
</div>
const container = document.querySelector("#container")

container.dataset.currentState // => "loading"

container.dataset.currentState = "loaded"

container.dataset.currentState // => "loaded"

Récupérer / modifier des attributs d'un élément (2)

<div id="container" aria-label="custom label">
  Loading...
</div>
const container = document.querySelector("#container")

container.getAttribute("aria-label") // => "custom label"

container.setAttribute("aria-label", "Updated custom label")

Récupérer / modifier des attributs d'un élément (3)

Modifier le style d'un élément

<p class="alert alert-error">Une erreur est survenue</p>
const alert = document.querySelector(".alert")

for(const className of alert.classList) {
  console.log(className)
}
// => "alert" "alert-error"

alert.classList.contains("alert-error") // => true

alert.classList.remove("alert-error") // => class="alert"

alert.classList.add("alert-warning")
// => class="alert alert-warning"

alert.classList.toggle("alert-warning")
// => class="alert"

alert.classList.toggle("alert-warning")
// => class="alert alert-warning"

alert.classList.toggle("alert-warning", someBoolean)

Manipuler les classes d'un élément

<p style="font-size: 3rem; color: red;">Une erreur est survenue</p>
const alert = document.querySelector("p")

alert.style.fontSize // => "3rem"

alert.style.color // => "red"

alert.style.fontSize = "2rem"
// => style="font-size: 2rem; color: red"

alert.style.backgroundColor = "white"
// => style="font-size: 3rem; color: red; background-color: white;"

Manipuler le style inline d'un élément

Ajouter un nouvel élément dans le DOM

const item = document.createElement("li")
item.textContent = "Lorem ipsum"

Créer un nouvel élément

Une fois l'élément créé, on a l'objet en mémoire, mais il n'est pas automatiquement inséré dans le DOM : le navigateur ne peut pas savoir où on souhaite qu'il apparaisse

Insérer un nouvel élément (1)

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const newItem = document.createElement("li")
newItem.textContent = "Item 0"
newItem.style.color = "red"

list.prepend(newItem)

Insérer un nouvel élément (2)

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const newItem = document.createElement("li")
newItem.textContent = "Item 4"
newItem.style.color = "red"

list.append(newItem)

Insérer un nouvel élément (3)

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const secondItem = list.querySelector(":nth-child(2)")

const newItem = document.createElement("li")
newItem.textContent = "Item 2bis"
newItem.style.color = "red"

secondItem.after(newItem)

Insérer un nouvel élément (4)

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const thirdItem = list.querySelector(":nth-child(3)")

const newItem = document.createElement("li")
newItem.textContent = "Item 2bis"
newItem.style.color = "red"

thirdItem.before(newItem)

Remplacer un élément

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const thirdItem = list.querySelector(":nth-child(3)")

const newItem = document.createElement("li")
newItem.textContent = "Item 3 replaced"
newItem.style.color = "red"

thirdItem.replaceWith(newItem)

Supprimer un élément

Supprimer un élément

<ul class="js-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>ITem 3</li>
</ul>
const list = document.querySelector(".js-list")

const thirdItem = list.querySelector(":nth-child(3)")

thirdItem.remove()

Récap ! (1)

  • Les éléments qui composent une page web sont représentés sous forme d'un arbre
  • Il est possible de récupérer n'importe quel élément de cet arbre avec querySelector et querySelectorAll en leur passant un sélecteur CSS
  • On peut accéder au contenu d'un élément et le modifier avec innerHTML, innerText ou textContent
  • On peut accéder aux classes (classList), style inline (style) et aux attributs des éléments (propriété directe ou dataset ou getAttribute / setAttribute(attr, val))

Récap ! (2)

  • On peut créer des éléments avec document.createElement(type)
  • On peut insérer un élément dans le DOM avec prepend, append, before, after
  • On peut remplacer un élément par un autre avec replaceWith
  • On peut supprimer un élément avec remove

Des questions ?

Programmation web - client riche - Le DOM

By Cyrille Perois

Programmation web - client riche - Le DOM

  • 986