Objectifs de cette leçon
- Attacher des gestionnaires d'événements
- Comprendre l'objet event
- Maîtriser la delegation d'événements
Evenements en JavaScript ⚡
Les evenements sont le mechanisme principal pour rendre les pages web interactives. Un evenement est un signal que le navigateur emet quand quelque chose se passe : clic, touche clavier, chargement de page, etc.
1. addEventListener — ecouter les evenements 👂
const bouton = document.querySelector("bouton"); // Syntaxe moderne bouton.addEventListener("click", (event) => { console.log("Bouton clique !"); console.log("Position :", event.clientX, event.clientY); }); // Avec options bouton.addEventListener("click", handler, { once: true, // L'evenement ne se declenche qu'une fois capture: true, // Capture au niveau parent en premier passive: true // Ne previendra pas le scroll (performances) }); // Retirer un listener function handler(e) { console.log("Clique !"); } bouton.addEventListener("click", handler); bouton.removeEventListener("click", handler);
2. L'objet event 📦
document.querySelector("button").addEventListener("click", (event) => { // Informations de base console.log("Type :", event.type); // "click" console.log("Cible :", event.target); // Element clique console.log("Element courant :", event.currentTarget); // Element qui ecoute // Position de la souris console.log("X :", event.clientX); console.log("Y :", event.clientY); console.log("Page X/Y :", event.pageX, event.pageY); // Touche clavier (pour les evenements clavier) console.log("Touche :", event.key); // "Enter", "a", "Escape" console.log("Code :", event.code); // "KeyA", "Enter" console.log("Shift ?", event.shiftKey); // true/false console.log("Ctrl ?", event.ctrlKey); // true/false // Empecher le comportement par defaut event.preventDefault(); // Ex: empecher la soumission d'un formulaire // Propagation event.stopPropagation(); // Empeche l'evenement de monter dans le DOM event.stopImmediatePropagation(); // Empeche les autres listeners du meme element
3. Les evenements courants 📋
| Evenement | Declenche quand | Element typique |
|---|---|---|
click | Clic gauche | Boutons, liens, tout |
dblclick | Double-clic | Elements specifiques |
mouseenter | Souris entre dans | Pour effets hover |
mouseleave | Souris sort de | Pour effets hover |
keydown | Touche enfoncee | Champs de texte, document |
keyup | Touche relachee | Champs de texte |
input | Valeur change | Inputs, textareas |
change | Valeur change + perte de focus | Selects, checkboxes |
submit | Soumission de formulaire | Formulaires |
scroll | Defilement | Window, elements |
resize | Redimensionnement | Window |
load | Page/element charge | Window, images |
DOMContentLoaded | HTML parse, scripts pas encore executes | Document |
// Exemples d'evenements courants window.addEventListener("resize", () => { console.log(`Taille : ${window.innerWidth}x${window.innerHeight}`); }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") { console.log("Touche Echap enfoncee"); } }); const input = document.querySelector("input"); input.addEventListener("input", (e) => { console.log("Valeur actuelle :", e.target.value); }); document.querySelector("form").addEventListener("submit", (e) => { e.preventDefault(); // Empecher le rechargement console.log("Formulaire soumis !"); });
4. La propagation des evenements 🌊
Les evenements suivent un cycle de propagation en 3 phases :
// HTML : <div id="parent"><button id="enfant">Clique</button></div> document.getElementById("parent").addEventListener("click", () => { console.log("Parent clique (bubbling)"); }); document.getElementById("enfant").addEventListener("click", () => { console.log("Enfant clique"); }); // Clic sur le bouton affiche : // "Enfant clique" // "Parent clique (bubbling)"
💡 Par defaut, les evenements bubblent (remontent) du bouton vers le parent. C'est la phase de "bubbling".
Arreter la propagation
document.getElementById("enfant").addEventListener("click", (e) => { e.stopPropagation(); // La bulle ne remonte plus console.log("Seul l'enfant est clique"); });
Capture vs Bubbling
// Troisieme argument = capture (true) ou bubbling (false, defaut) parent.addEventListener("click", handler, true); // Capture parent.addEventListener("click", handler, false); // Bubbling (defaut)
5. Delegation d'evenements 🎯
La delegation consiste a attacher UN SEUL listener a un parent, et a determiner l'element enfant via event.target :
// HTML : <ul id="liste"> // <li>Item 1</li> // <li>Item 2</li> // <li>Item 3</li> // </ul> // ❌ Mauvais — un listener par element document.querySelectorAll("li").forEach(li => { li.addEventListener("click", handler); }); // ✅ Bon — delegation : un seul listener sur le parent document.getElementById("liste").addEventListener("click", (e) => { if (e.target.tagName === "LI") { console.log("Item clique :", e.target.textContent); } }); // ✅ Encore mieux avec closest document.getElementById("liste").addEventListener("click", (e) => { const li = e.target.closest("li"); if (li) { console.log("Item clique :", li.textContent); } });
💡 Pourquoi deleguer ?
- Performances : un seul listener au lieu de 1000
- Dynamique : les elements ajoutes posterioriement fonctionnent aussi
- Memoire : moins d'evenements stockes en memoire
6. Evenements de formulaire 📝
const form = document.querySelector("form"); const input = document.querySelector("input[name=email]"); // Soumission form.addEventListener("submit", (e) => { e.preventDefault(); // Empecher le rechargement const formData = new FormData(form); console.log("Email :", formData.get("email")); }); // Validation en temps reel input.addEventListener("input", (e) => { const email = e.target.value; if (email.includes("@")) { input.classList.add("valide"); input.classList.remove("invalide"); } else { input.classList.add("invalide"); input.classList.remove("valide"); } }); // Focus et blur input.addEventListener("focus", () => { input.classList.add("en-focus"); }); input.addEventListener("blur", () => { input.classList.remove("en-focus"); });
7. Evenements custom 🎨
// Creer un evenement personnalise const monEvenement = new CustomEvent("maNotification", { detail: { message: "Hello depuis un custom event !" }, bubbles: true }); // Emettre l'evenement document.dispatchEvent(monEvenement); // Ecouter l'evenement document.addEventListener("maNotification", (e) => { console.log(e.detail.message); });
8. Bonnes pratiques 📏
| Pratique | Pourquoi |
|---|---|
Utiliser addEventListener | Plutot que onclick (qui ecrase les handlers precedents) |
| Deleguer les events | Pour les listes dynamiques |
preventDefault() | Pour les formulaires et liens |
stopPropagation() | Quand on veut isoler un evenement |
Options passive: true | Pour les evenements de scroll/touch |
Options once: true | Pour les evenements one-shot |
| Nettoyer les listeners | Quand un composant est detruit (SPA) |
9. Exercices pour toi 🎯
Exercice 1 : Clavier Detecte les touches directionnelles et deplace un carre dans la page.
Exercice 2 : Drag & Drop simple Implemente un drag & drop basique avec mousedown, mousemove et mouseup.
Exercice 3 : Raccourcis clavier Implemente des raccourcis : Ctrl+S (empecher la sauvegarde et afficher un message), Escape (fermer un modal).
⚡ Simulateur — Événements
Étape 1/5document.addEventListener attache un écouteur à l'ensemble du document. Le paramètre e est l'objet Event contenant toutes les informations sur l'événement.