0 XP
?
Intermédiaire40 min25 XP

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 📋

EvenementDeclenche quandElement typique
clickClic gaucheBoutons, liens, tout
dblclickDouble-clicElements specifiques
mouseenterSouris entre dansPour effets hover
mouseleaveSouris sort dePour effets hover
keydownTouche enfonceeChamps de texte, document
keyupTouche relacheeChamps de texte
inputValeur changeInputs, textareas
changeValeur change + perte de focusSelects, checkboxes
submitSoumission de formulaireFormulaires
scrollDefilementWindow, elements
resizeRedimensionnementWindow
loadPage/element chargeWindow, images
DOMContentLoadedHTML parse, scripts pas encore executesDocument
// 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 📏

PratiquePourquoi
Utiliser addEventListenerPlutot que onclick (qui ecrase les handlers precedents)
Deleguer les eventsPour les listes dynamiques
preventDefault()Pour les formulaires et liens
stopPropagation()Quand on veut isoler un evenement
Options passive: truePour les evenements de scroll/touch
Options once: truePour les evenements one-shot
Nettoyer les listenersQuand 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/5
📝 Pseudo-code
1document.addEventListener("click", (e) => {
2 console.log("Clic détecté !");
3 console.log("Cible:", e.target.tagName);
4});
5// L'étudiant voit l'Event Loop ici
⚙️ Exécution
📦 Mémoire
Aucune variable
🔀 Flux d'exécution
addEventListener
3
Enregistrement de l'écouteur

document.addEventListener attache un écouteur à l'ensemble du document. Le paramètre e est l'objet Event contenant toutes les informations sur l'événement.