Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

Les gestionnaires d'événements : addEventListener et l'objet Event

Les gestionnaires d'événements : addEventListener et l'objet Event. Dans cette leçon du cours JavaScript, vous apprendrez à : maîtriser addEventListener et ses options (once, signal, capture) ; retire...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Les gestionnaires d'événements : addEventListener et l'objet Event. Dans cette leçon du cours JavaScript, vous apprendrez à : maîtriser addEventListener et ses options (once, signal, capture) ; retirer un écouteur avec removeEventListener ; lire les informations de l'objet Event ; distinguer target et currentTarget.

Chapitre 13 — Les événements · 13.2 Les gestionnaires d'événements : addEventListener et l'objet Event

🎯 Objectifs de la leçon
• maîtriser addEventListener et ses options (once, signal, capture) ;
• retirer un écouteur avec removeEventListener;
• lire les informations de l'objet Event;
• distinguer target et currentTarget.

1. addEventListener en détail

element.addEventListener(type, ecouteur, options);

// type      : nom de l'événement, en minuscules, sans « on » : "click", "keydown"…
// ecouteur  : la fonction à appeler (elle reçoit l'objet Event)
// options   : facultatif, par exemple { once: true }

function direBonjour(ev) {
  console.log("Bonjour, événement :", ev.type);
}
bouton.addEventListener("click", direBonjour);          // fonction nommée
bouton.addEventListener("click", (ev) => { /* … */ });  // fonction fléchée

2. L'objet Event

Le navigateur passe toujours à l'écouteur un objet qui décrit l'événement. Il contient des propriétés communes, et d'autres propres au type d'événement (souris, clavier…).

Propriétés de l'objet Event
Figure 1 — Les propriétés les plus utiles de l'objet Event.

📄 l2_objet_event.html

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="zone" id="zone">
    <p>Cliquez dans cette zone, <strong>sur le texte en gras</strong> ou sur le bouton.</p>
    <button>Bouton</button>
  </div>
  <label>Tapez ici <input id="champ"></label>
  <pre id="sortie"></pre>

  <script>
    const sortie = document.querySelector("#sortie");

    // Le navigateur passe un objet Event à la fonction écouteur
    document.querySelector("#zone").addEventListener("click", function (ev) {
      sortie.textContent = [
        `ev.type           = ${ev.type}`,
        `ev.target         = <${ev.target.tagName.toLowerCase()}>   (élément cliqué)`,
        `ev.currentTarget  = <${ev.currentTarget.tagName.toLowerCase()} id="${ev.currentTarget.id}">   (élément qui écoute)`,
        `this === currentTarget ? ${this === ev.currentTarget}`,
        `ev.clientX, clientY = ${ev.clientX}, ${ev.clientY}`,
        `ev.timeStamp      = ${Math.round(ev.timeStamp)} ms après l'ouverture de la page`,
      ].join("\n");
    });

    document.querySelector("#champ").addEventListener("keydown", (ev) => {
      sortie.textContent = `ev.type = ${ev.type}\nev.key  = "${ev.key}"\nev.target.value (avant la touche) = "${ev.target.value}"`;
    });
  </script>
</body>
</html>

Après un clic sur le texte en gras
Après un clic sur le texte en gras

target ou currentTarget? L'écouteur est posé sur la zone (currentTarget), mais le clic a eu lieu sur le <strong> à l'intérieur (target). Cette différence est la clé de la délégation (leçon 13.5). Dans une fonction classique, this vaut currentTarget; dans une fonction fléchée, this ne désigne pas l'élément (chapitre 16) : utilisez ev.currentTarget.

3. Retirer un écouteur

📄 l2_retirer.html

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="btns">
    <button id="vote">Voter (3 votes maximum)</button>
    <button id="cadeau">Ouvrir le cadeau (une seule fois)</button>
    <button id="suivre">Suivre la souris</button>
    <button id="arreter">Arrêter le suivi</button>
  </div>
  <pre id="sortie"></pre>

  <script>
    const sortie = document.querySelector("#sortie");
    const ecrire = (t) => (sortie.textContent += t + "\n");

    // 1. removeEventListener : il faut la MÊME fonction (nommée) qu'à l'ajout
    let votes = 0;
    const bouton = document.querySelector("#vote");
    function voter() {
      votes++;
      ecrire(`Vote n° ${votes}`);
      if (votes === 3) {
        bouton.removeEventListener("click", voter);
        ecrire("→ écouteur retiré : les clics suivants sont ignorés");
      }
    }
    bouton.addEventListener("click", voter);

    // 2. Option once : l'écouteur se retire tout seul après le premier appel
    document.querySelector("#cadeau").addEventListener("click", () => ecrire("🎁 Surprise !"), { once: true });

    // 3. AbortController : retirer plusieurs écouteurs d'un coup
    let controleur = null;
    document.querySelector("#suivre").addEventListener("click", () => {
      controleur = new AbortController();
      let n = 0;
      document.addEventListener("mousemove", () => n++, { signal: controleur.signal });
      document.addEventListener("keydown", () => n++, { signal: controleur.signal });
      ecrire("Suivi démarré (souris + clavier)");
      document.querySelector("#arreter").onclick = () => {
        controleur.abort(); // retire les deux écouteurs
        ecrire(`Suivi arrêté après ${n} événements`);
      };
    });
  </script>
</body>
</html>

Après 5 clics sur Voter, 2 sur le cadeau, puis le suivi de la souris
Après 5 clics sur Voter, 2 sur le cadeau, puis le suivi de la souris

  • removeEventListener exige la même fonction qu'à l'ajout : impossible de retirer une fonction anonyme écrite directement dans l'appel.
  • { once: true }: l'écouteur ne servira qu'une fois.
  • { signal } avec un AbortController: un seul abort() retire tous les écouteurs liés à ce signal.
ℹ️ À retenir
• addEventListener(type, fonction, options); options utiles : once, signal, capture, passive.
• L'écouteur reçoit un objet Event: type, target, currentTarget, et des propriétés propres au type.
• target = élément réellement touché ; currentTarget = élément qui écoute.
• removeEventListener avec la même fonction, ou once, ou AbortController.

🛠 Activité 2 — Un sondage à vote unique

Mission : Créez trois boutons de vote (Pour, Contre, Abstention). Chaque visiteur ne peut voter qu'une seule fois ; un bouton « Nouveau vote » permet de recommencer.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Écrivez un seul écouteur réutilisé pour les trois boutons. Comment savez-vous quel bouton a été cliqué, à partir de l'objet Event?
  2. Après un vote, les trois boutons doivent cesser de réagir. Essayez d'abord avec removeEventListener et une fonction anonyme : pourquoi cela ne marche-t-il pas ? Corrigez.
  3. Réécrivez la même logique avec un AbortController. Combien de lignes avez-vous économisé ? Comment réactivez-vous les votes avec « Nouveau vote » ?
  4. Mettez un <span> avec une icône dans chaque bouton. Affichez ev.target et ev.currentTarget en cliquant sur l'icône : que constatez-vous ? Lequel devez-vous utiliser pour lire l'attribut data-vote du bouton ?
  5. Utilisez this à la place de ev.currentTarget, d'abord dans une fonction classique, puis dans une fonction fléchée. Expliquez la différence.
  6. Affichez ev.timeStamp à chaque vote. Que représente cette valeur ? Comment calculer le temps de réflexion du visiteur depuis l'ouverture de la page ?

Je vérifie / je rends :

  • ☐ La page de vote et les réponses aux questions 2, 4 et 5.

← 13.1 Les événements en JavaScript13.3 Les événements de la souris et du clavier →