Appearance
Module 11 : JavaScript – Création et manipulation avancée du DOM, validation et objets
Introduction
Ce module approfondit la manipulation du DOM en JavaScript, en se concentrant sur la création dynamique d’éléments, la gestion des classes CSS, la validation avancée avec les expressions régulières, et l’utilisation de tableaux et objets pour générer du contenu HTML.
Objectifs du cours
- Comprendre comment créer et insérer dynamiquement des éléments dans le DOM avec JavaScript
- Maîtriser l’utilisation de
classListpour manipuler les classes CSS - Valider des champs de formulaire à l’aide d’expressions régulières
- Utiliser des tableaux et objets pour générer et mettre à jour dynamiquement le contenu HTML
Théorie
1 : Manipulation des classes CSS avec classList
Définition
La propriété
classListpermet d’ajouter, de retirer, de basculer ou de vérifier la présence de classes CSS sur un élément HTML.
Contexte d’utilisation
classList est très utile pour gérer dynamiquement l’apparence des éléments (ex : afficher/masquer, indiquer une erreur, changer de thème, etc.).
Exemples pratiques
javascript
// Ajouter une classe
element.classList.add('active');
// Retirer une classe
element.classList.remove('error');
// Basculer une classe
element.classList.toggle('visible');
// Vérifier la présence
if (element.classList.contains('selected')) {
// faire quelque chose
}html
<label id="lblNom" for="nom">Nom :</label>
<input type="text" id="nom">css
.erreur {
color: red;
}javascript
/**
* Valide le champ de nom et ajoute une classe d'erreur si le champ est vide. Utilise `input` pour une validation en temps réel et `classList` pour gérer les classes CSS de manière efficace.
*/
function validationNom() {
const labelNom = document.getElementById('lblNom');
const inputNom = document.getElementById('nom');
// Trim permet de supprimer les espaces avant et après la valeur
if (inputNom.value.trim() === '')
{
// Si le champ est vide, ajouter la classe d'erreur
labelNom.classList.add('erreur');
}
else
{
// Sinon, on doit penser à retirer la classe d'erreur
labelNom.classList.remove('erreur');
}
}
function initialisation() {
const inputNom = document.getElementById('nom');
// On utilise 'input' pour valider en temps réel à chaque modification du champ. On aurait aussi pu utiliser 'blur' pour valider uniquement lorsque l'utilisateur quitte le champ.
inputNom.addEventListener('input', validationNom);
}
addEventListener('load', initialisation);Note :
inputvérifie à chaque modification du champ, tandis queblurvérifie uniquement lorsque l'utilisateur quitte le champ. Choisissez en fonction de l'expérience utilisateur souhaitée.
Avantages de classList
Plus simple et plus lisible que manipuler directement l’attribut class et permet d'ajouter/retirer plusieurs classes facilement au lieu de "tout remplacer" l'attribut class.
Avantage de toggle
toggle est particulièrement utile pour appliquer une classe, si elle n’est pas présente, ou la retirer si elle est déjà appliquée, ce qui est idéal pour les fonctionnalités d’affichage/masquage.
css
.hidden {
display: none;
}html
<button id="toggleImage">Afficher/Masquer l'image</button>
<img id="image" src="image.jpg" alt="Image à afficher/masquer">javascript
// Afficher/masquer une image au clic d'un bouton
let bouton = document.getElementById('toggleImage');
let image = document.getElementById('image');
function gererClick() {
// Si la classe 'hidden' est présente dans la liste de classes de l'image : elle sera retirée
// Si la classe 'hidden' n'est pas présente dans la liste de classes de l'image : elle sera ajoutée
image.classList.toggle('hidden');
}
bouton.addEventListener('click', gererClick);2 : Création et ajout d’éléments dans le DOM
Définition
Créer et ajouter dynamiquement des éléments HTML dans le DOM permet de modifier la structure d’une page web en réponse à des actions utilisateur ou à des besoins applicatifs, sans recharger la page.
Contexte d’utilisation
On utilise ces méthodes pour générer dynamiquement du contenu (ex : ajouter des messages, des cartes, des listes, etc.) ou pour construire des interfaces interactives. Lorsqu'on veut alors ajouter une ou des balises HTML dans une page web, on va prévilégier cette façon de faire plutôt que d'utiliser innerHTML qui est plus rapide à écrire mais moins performante et plus risquée (risque de faille XSS).
createElement()
La méthode createElement() permet de créer un nouvel élément HTML à partir de son nom de balise. Par exemple, document.createElement('div') crée une nouvelle balise <div> qui n'est pas encore ajoutée à la page web (DOM). createElement('a') crée une balise <a>, createElement('p') crée une balise <p>, etc.
appendChild()
La méthode appendChild() permet d'ajouter un élément en tant que dernier enfant d'un élément parent dans le DOM. Par exemple, parent.appendChild(child) ajoute l'élément child à la fin de la liste des enfants de parent. Si child est déjà présent ailleurs dans le DOM, il sera déplacé à sa nouvelle position.
Départ
html
<div id="parent">
<p>Premier enfant</p>
<p>Deuxième enfant</p>
<!-- NOUVEL ENFANT SERA AJOUTÉ ICI -->
</div>Modification avec appendChild()
javascript
let parent = document.getElementById('parent');
let newChild = document.createElement('p');
newChild.textContent = "Nouvel enfant ajouté avec appendChild";
parent.appendChild(newChild);Résultat
html
<div id="parent">
<p>Premier enfant</p>
<p>Deuxième enfant</p>
<p>Nouvel enfant ajouté avec appendChild</p>
</div>insertBefore()
La méthode insertBefore() permet d'insérer un élément avant un élément de référence dans le DOM. Par exemple, parent.insertBefore(child, reference) ajoute l'élément child avant l'élément reference dans la liste des enfants de parent.
Départ
html
<div id="parent">
<p>Premier enfant</p>
<!-- NOUVEL ENFANT SERA AJOUTÉ ICI, JUSTE AVANT CE PARAGRAPHE -->
<p id="reference">Deuxième enfant (référence)</p>
</div>javascript
let parent = document.getElementById('parent');
let newChild = document.createElement('p');
newChild.textContent = "Nouvel enfant ajouté avec insertBefore";
let reference = document.getElementById('reference');
parent.insertBefore(newChild, reference);Résultat
html
<div id="parent">
<p>Premier enfant</p>
<p>Nouvel enfant ajouté avec insertBefore</p>
<p id="reference">Deuxième enfant (référence)</p>
</div>remove()
La méthode remove() permet de supprimer un élément du DOM. Par exemple, element.remove() supprime l'élément ciblé de la page web.
html
<div id="parent">
<p>Premier enfant</p>
<p id="toRemove">Deuxième enfant à supprimer</p>
<p>Troisième enfant</p>
</div>javascript
let elementToRemove = document.getElementById('toRemove');
elementToRemove.remove();Résultat
html
<div id="parent">
<p>Premier enfant</p>
<!-- <p id="toRemove">Deuxième enfant à supprimer</p> -->
<p>Troisième enfant</p>
</div>Exemple 1 : ajouter à la fin de <body>
Créer un élément HTML, lui associer des attributs, et l'ajouter à la page web (DOM).
javascript
// Créer un nouvel élément <div>
let newDiv = document.createElement("div");
// Si c'est une balise de contenu ou, y ajouter du texte
newDiv.textContent = "Ceci est une nouvelle div créée dynamiquement !";
// Ajouter sa ou ses classes, son id, ses attributs, etc.
newDiv.classList.add("my-class");
newDiv.setAttribute("id", "div1");
// Ajouter la balise créee à la page web (DOM), à l'endroit désiré.
// Dans ce cas-ci, on l'ajoute à la fin du body
// AppendChild ajoute un élément à la fin de la liste des enfants d'un élément parent
document.body.appendChild(newDiv);
// Soi un tableau d'objets.
const fruits = ['Pomme', 'Banane', 'Orange'];
// Créer une balise <ul> pour la liste
const ul = document.createElement('ul');
// Créer chaque élément de la liste <li> à partir du tableau et les ajouter à la balise <ul>
for (const fruit of fruits) {
// Créer un <li>
const li = document.createElement('li');
// Remplir le contenu du <li> avec le nom du fruit
li.textContent = fruit;
// Ajouter le <li> comme enfant à la balise <ul>
ul.appendChild(li);
}
// Rendu ici, la balise <ul> contient déjà tous les <li> créés à partir du tableau. Mais elle n'est pas encore "ajoutée" à la page web (DOM).
// On l'ajoute à la page web (DOM) en l'ajoutant à un élément parent, par exemple le body
document.body.appendChild(ul);Résultat avant
html
<html>
<head>
<title>Exemple de création d'éléments</title>
</head>
<body>
</body>
</html>Résultat après
html
<html>
<head>
<title>Exemple de création d'éléments</title>
</head>
<body>
<div id="div1" class="my-class">Ceci est une nouvelle div créée dynamiquement !</div>
<ul>
<li>Pomme</li>
<li>Banane</li>
<li>Orange</li>
</ul>
</body>
</html>Exemple 2 : AJOUTER des balises à un endroit précis dans la page web
Interface HTML/ CSS de départ :
html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Web Complète</title>
</head>
<body>
<header>
<h1>Logo</h1>
<button id="btn1">OK</button>
</header>
<nav>
<ul>
<li><a href="#">Page 1</a></li>
<li><a href="#">Page 2</a></li>
</ul>
</nav>
<main id="content">
<h2>Bienvenue sur ma page web</h2>
<!-- ON VEUT AJOUTER UN PARAGRAPHE ICI -->
</main>
</body>
</html>css
/* Styles de base pour la page web */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.rouge
{
color: red;
}Javascript :
Ajouter un paragraphe juste après le h2 du main. Il faudra :
- Créer un nouvel élément
<p>aveccreateElement - Remplir le contenu du paragraphe avec
textContent - Récupérer avec getElementById l'endroit où l'on veut ajouter le paragraphe (à la fin du main dans ce cas)
- Ajouter le paragraphe à la page web (DOM) à l'endroit désiré
javascript
// Créer un nouvel élément <p>
let newParagraph = document.createElement("p");
newParagraph.textContent = "Ceci est un nouveau paragraphe.";
newParagraph.classList.add("rouge");
// Sélectionner l'élément de référence (parent) dans lequel on veut insérer le nouveau paragraphe
let mainContent = document.getElementById("content");
// Ajouter le nouveau paragraphe à la fin du main
// Ceci va l'ajouter vraiment à la fin du main. Donc si il y avait d'autres éléments après le h2, le nouveau paragraphe serait ajouté après tous les autres éléments du main.
mainContent.appendChild(newParagraph);
function gererClick() {
// Créer un nouvel élément <p>
let newParagraph = document.createElement("p");
newParagraph.textContent = "Ceci est un nouveau paragraphe ajouté au clic.";
newParagraph.classList.add("rouge");
// Sélectionner l'élément de référence (parent) dans lequel on veut insérer le nouveau paragraphe
let mainContent = document.getElementById("content");
// Ajouter le nouveau paragraphe à la fin du main
mainContent.appendChild(newParagraph);
}
function initialisation() {
// Récupérer le bouton et lui ajouter un écouteur d'événement pour gérer les clics.
let btnAjouter = document.getElementById("btn1");
btnAjouter.addEventListener('click', gererClick);
}
addEventListener('load', initialisation);Exemple 3 : REMPLACER du HTML existant à un endroit précis dans la page web
Même Interface HTML/ CSS de départ
Javascript :
On veut remplacer le contenu du main (tout ce qui est à l'intérieur du main) par un nouveau contenu.
Il faudra :
- Créer les nouveaux éléments à ajouter (ex : un h2 et un p)
- Récupérer avec getElementById l'endroit où l'on veut ajouter le nouveau contenu (le main dans ce cas)
- Vider le contenu actuel du main (ex : en mettant innerHTML à une chaîne vide)
- Ajouter les nouveaux éléments au main, dans l'ordre souhaité (ex : d'abord le h2, puis le p)
javascript
function gererClick() {
// Se brancher sur l'élément parent dans lequel on veut remplacer le contenu
let mainContent = document.getElementById("content");
// Vider le contenu actuel du main
mainContent.innerHTML = "";
// Créer le nouveau contenu à ajouter
let h2 = document.createElement("h2");
h2.textContent = "Nouveau titre";
let p = document.createElement("p");
p.textContent = "Ceci est un nouveau paragraphe qui remplace l'ancien contenu du main.";
p.classList.add("rouge");
// Ajouter le nouveau contenu au main, dans l'ordre souhaité
mainContent.appendChild(h2); // <h2> Nouveau titre </h2>
mainContent.appendChild(p); // <p class="rouge"> Ceci est un nouveau paragraphe qui remplace l'ancien contenu du main.</p>
}
function initialisation() {
// Récupérer le bouton et lui ajouter un écouteur d'événement pour gérer les clics.
let btnAjouter = document.getElementById("btn1");
btnAjouter.addEventListener('click', gererClick);
}
addEventListener('load', initialisation);Points importants
- Toujours créer l'élément avec
createElementavant de l'ajouter - Utiliser
appendChildpour insérer l'élément dans le DOM - On peut ajouter plusieurs classes avec
classList.add() - On peut insérer dans n'importe quel élément du DOM
3 : Validation avec expressions régulières
Définition
Les expressions régulières (regex) permettent de vérifier si une chaîne de caractères respecte un motif précis. Elles sont très utilisées pour valider des champs de formulaire (ex : courriel, mot de passe, etc.).
Contexte d’utilisation
On utilise les regex pour valider des données complexes, comme les adresses courriel, numéros de téléphone, etc., avant de les envoyer au serveur.
Avantages des expressions régulières
| Avantage | Description |
|---|---|
| Précision | Validation exacte selon des motifs complexes |
| Performance | Vérification rapide côté client |
| Réutilisabilité | Motifs applicables à plusieurs champs |
| Robustesse | Détection d'erreurs avant soumission |
| Personnalisation | Adaptation aux besoins spécifiques |
Exemples pratiques
javascript
function validateEmail() {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const emailInput = document.getElementById('email');
const emailValue = emailInput.value;
if (emailRegex.test(emailValue)) {
emailInput.classList.remove('error');
return true;
} else {
emailInput.classList.add('error');
return false;
}
}
document.getElementById('email').addEventListener("input", validateEmail);Types de regex courantes
| Type | Exemple | Description |
|---|---|---|
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ | Adresse email valide | |
| Téléphone | `/^(+33 | 0)1-9$/` |
| Code postal | /^\d{5}$/ | Code postal français |
| Mot de passe | /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/ | Au moins 8 caractères, maj, min, chiffre |
| URL | /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/ | URL valide |
Bonnes pratiques pour les regex
javascript
// ✅ Bonne pratique : utiliser des variables pour la lisibilité
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (emailPattern.test(email)) {
// valide
}
// ❌ À éviter : regex en ligne difficile à maintenir
if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) {
// valide
}Points importants
- Utiliser des sites comme regexr.com pour tester vos regex
- Toujours tester la regex avec plusieurs cas (valides et invalides)
- Combiner avec
classListpour l'indication visuelle d'erreur - Utiliser
inputpour validation en temps réel
4 : Manipuler des tableaux d'objets et les générer dans le DOM
Définition
Les tableaux et objets permettent de stocker et manipuler des collections de données. On peut ensuite parcourir ces structures pour générer dynamiquement du contenu HTML.
Contexte d’utilisation
Très utile pour afficher des listes, des tableaux, des cartes, etc., à partir de données dynamiques (ex : résultats d'une API, catalogue de produits, etc.).
Exemples pratiques
javascript
// Exemple d'une source de données (tableau d'objets) qui contient 3 utilisateurs avec leurs propriétés nom, age et ville
// Cette variable est globale. Elle peut être utilisée dans n'importe quelle fonction du script.
const utilisateurs = [
{
nom: "Alice",
age: 25,
ville: "Paris"
},
{
nom: "Bob",
age: 30,
ville: "Lyon"
},
{
nom: "Charlie",
age: 22,
ville: "Marseille"
}
];
function genererListeUtilisateurs() {
let container = document.getElementById('users-container');
let ul = document.createElement("ul");
for (let user of utilisateurs) {
let li = document.createElement("li");
li.textContent = `${user.nom} (${user.age} ans) - ${user.ville}`;
ul.appendChild(li);
}
container.appendChild(ul);
}
function initialisation() {
// Appeler la fonction pour générer la liste des utilisateurs à partir du tableau d'objets
genererListeUtilisateurs();
}
addEventListener('load', initialisation);Résultat HTML attendu
html
<div id="users-container">
<ul>
<li>Alice (25 ans) - Paris</li>
<li>Bob (30 ans) - Lyon</li>
<li>Charlie (22 ans) - Marseille</li>
</ul>
</div>Points importants
- Utiliser
for,for...of, oumappour parcourir les tableaux - Créer les éléments avec
createElementet remplir avectextContentouinnerHTML - Toujours ajouter les éléments au DOM avec
appendChildouinsertBefore
Exercices pratiques
Exercice 1 : Validation de formulaire et gestion d'utilisateurs (Intermédiaire)
Énoncé
Créer une page web interactive avec un formulaire de connexion comportant deux champs : pseudo et mot de passe. Implémenter une validation en temps réel des champs avec des classes CSS pour la rétroaction visuelle. Lorsque le formulaire est valide, ajouter l'utilisateur à un tableau en mémoire (maximum 5 utilisateurs). Ajouter un bouton pour afficher la liste des utilisateurs enregistrés.
Consignes
Compléter le formulaire de départ avec :
- Un champ input de type "text" pour le pseudo (id="pseudo")
- Un champ input de type "password" pour le mot de passe (id="password")
- Un bouton de soumission (id="submitBtn")
- Ce formulaire doit avoir un attribut novalidate pour éviter la validation HTML par défaut et sa soumission par défaut devra être bloquée avec
event.preventDefault().
Implémenter, par javascript, la validation en temps réel des champs :
- Le pseudo doit contenir au moins 6 caractères
- Le mot de passe doit contenir au moins 8 caractères et commencer par le symbole "$"
- Utiliser des classes CSS "valid" et "invalid" pour la rétroaction visuelle
Gérer un tableau d'utilisateurs en mémoire :
- Ce tableau, créé globalement, servira à y ajouter, au fur et à mesure, les utilisateurs validés (à la fin de la fonction qui gère le clic du bouton de soumission)
- Chaque élément du tableau doit être un objet utilisateur avec les propriétés "pseudo" et "password"
- Limite maximale : 5 utilisateurs
- Empêcher l'ajout si le tableau est plein et afficher un alert() en conséquence
Utiliser le bouton "Afficher utilisateurs" (id="showUsersBtn") qui devrait :
- Génèrer dynamiquement une liste à puce dans la page, à un endroit réservé à cet effet (div id="usersList")
- Format : "Pseudo : Mot de passe" pour chaque utilisateur
- Remplacer le contenu de la div existante "usersList" à chaque fois que le bouton est cliqué
- Génèrer dynamiquement une liste à puce dans la page, à un endroit réservé à cet effet (div id="usersList")
Structure HTML attendue
html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exercice 1 - Validation Formulaire</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Formulaire d'inscription</h1>
<form id="userForm" novalidate>
<!-- Champs... -->
<!-- Bouton de soumission... -->
</form>
<!-- Bouton pour afficher les utilisateurs -->
<button id="showUsersBtn">Afficher les utilisateurs</button>
<!-- Zone pour afficher la liste des utilisateurs -->
<div id="usersList"></div>
</main>
<script src="script.js"></script>
</body>
</html>Exercice 2 : Création d'un menu de navigation dynamique (Facile)
Énoncé
À partir d'une page web vide qui contient déjà une structure
header,nav,mainetfooter, créer dynamiquement un menu de navigation simple avec 3 éléments et l'insérer à l'intérieur de la balise<nav>qui possède déjà un ID.
Consignes
- Associer un événement click sur le bouton btn1. C'est dans cet événement que la création de l'intérieur du menu de navigation (#2) doit être effectuée.
- Créer les éléments HTML suivants à l'aide de JavaScript :
- Une liste
<ul>contenant 3 éléments<li> - Chaque
<li>contient un lien<a>avec du texte (ex: Accueil, À propos, Contact) - Chaque lien a un ID unique et la classe CSS "lien"
- Une liste
- Insérer cette structure à l'intérieur de la balise
<nav>(qui a déjà un ID dans le HTML) - Utiliser
createElement,textContent,classList.add,setAttributeetappendChilddans l'ordre approprié pour construire et insérer les éléments dans le DOM au bon endroit.
Code HTML de base de la page
html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Menu Dynamique</title>
</head>
<body>
<header>
<h1>Mon Site Web</h1>
</header>
<nav id="mainNav">
<p>NAVIGATION À MODIFIER</p>
</nav>
<main>
<h2>Contenu principal</h2>
<p>Contenu de la page...</p>
<button id="btn1">Ajouter un paragraphe</button>
</main>
<footer>
<p>Pied de page</p>
</footer>
<script src="script.js"></script>
</body>
</html>Structure HTML à créer dynamiquement
html
<ul>
<li><a href="#" id="accueil" class="lien">Accueil</a></li>
<li><a href="#" id="apropos" class="lien">À propos</a></li>
<li><a href="#" id="contact" class="lien">Contact</a></li>
</ul>Résultat HTML attendu
html
<!-- Avant le clic sur le bouton : -->
<nav id="mainNav">
<p>NAVIGATION À MODIFIER</p>
</nav>
<!-- Après le clic sur le bouton: -->
<nav id="mainNav">
<ul>
<li><a href="#" id="accueil" class="lien">Accueil</a></li>
<li><a href="#" id="apropos" class="lien">À propos</a></li>
<li><a href="#" id="contact" class="lien">Contact</a></li>
</ul>
</nav>Vérifications des connaissances
Testez vos connaissances acquises dans ce cours en répondant aux questions suivantes. Cliquez sur chaque question pour révéler la réponse.
Question 1
Quelle méthode permet de créer un nouvel élément HTML en JavaScript ?
Réponse
createElement()
Question 2
Comment ajouter une classe CSS à un élément en JavaScript ?
Réponse
Avec element.classList.add("nomDeClasse")
Question 3
À quoi sert la méthode test() d'une expression régulière ?
Réponse
Elle vérifie si une chaîne correspond au motif de la regex et retourne true ou false.
Question 4
Comment générer dynamiquement une liste HTML à partir d'un tableau d'objets ?
Réponse
En parcourant le tableau avec une boucle, en créant les éléments avec createElement, en remplissant avec textContent puis en ajoutant au DOM avec appendChild.
Question 5
Comment vérifier si un élément possède une classe spécifique ?
Réponse
Avec element.classList.contains('nomDeClasse') qui retourne true si la classe est présente.
Question 6
Quelle méthode permet de basculer (ajouter/retirer) une classe CSS ?
Réponse
element.classList.toggle('nomDeClasse')