Leçon 6/9 7 min

Les événements

Réagissez aux clics, saisies clavier et soumissions de formulaire avec addEventListener et l'objet event.

addEventListener : écouter les actions

Les événements sont le cœur de l'interactivité. Quand l'utilisateur clique, tape, défile : JavaScript peut réagir.

const bouton = document.querySelector("#monBouton");

bouton.addEventListener("click", function() {
  alert("Vous avez cliqué !");
});

La méthode addEventListener prend deux arguments :

  1. Le type d'événement : "click", "submit", "input", "keydown"...
  2. La fonction handler : ce qui se passe quand l'événement survient

Événements courants

  • click : clic souris
  • submit : soumission d'un formulaire
  • input : saisie dans un champ (en temps réel)
  • keydown : touche enfoncée
  • mouseover / mouseout : survol souris
  • change : valeur d'un champ modifiée (quand il perd le focus)

Ce ne sont que les plus courants : il existe des dizaines de types d'événements (clavier, souris, tactile, glisser-déposer, formulaire, média, défilement...). Pour la liste complète, garde ces deux références sous la main :

L'objet event

Un détail a pu te surprendre : nos fonctions reçoivent un paramètre event qu'on n'a jamais demandé. D'où sort-il ?

La clé, c'est de comprendre que ce n'est pas toi qui appelles ta fonction. Avec addEventListener, tu te contentes de confier ta fonction au navigateur : « quand on cliquera, exécute celle-ci ». C'est ensuite le navigateur qui l'appelle, au moment du clic. Et quand il l'appelle, il en profite pour lui passer un objet event en premier argument, qui décrit ce qui vient de se passer : le type d'action, l'élément visé, la touche pressée, la position du clic...

Autrement dit, l'argument arrive tout seul parce que l'appelant, c'est le navigateur, pas toi. Toi, tu choisis juste son nom (event, e, ce que tu veux) : ce qui compte, c'est sa place, le premier paramètre.

Pourquoi le handler reçoit un objet event : tu confies ta fonction au navigateur ; au moment du clic, le navigateur fabrique un objet event puis appelle ta fonction en lui passant cet objet. 1. Tu confies ta fonction au navigateur addEventListener("click", maFonction) 2. L'utilisateur clique 3. Le navigateur fabrique un objet event type, élément visé, touche, position du clic… 4. Le navigateur appelle TA fonction maFonction(event)
C'est le navigateur qui appelle ta fonction, pas toi : au passage, il lui tend l'objet event. Voilà pourquoi tu reçois un argument sans l'avoir demandé.

Chaque handler reçoit donc cet objet. Voici comment s'en servir :

document.querySelector("form").addEventListener("submit", function(event) {
  event.preventDefault(); // empêche le rechargement de la page

  const input = document.querySelector("#email");
  console.log("Email :", input.value);
});

document.addEventListener("keydown", function(event) {
  console.log("Touche :", event.key); // "Enter", "Escape", "a"...
});

event.preventDefault() est indispensable pour les formulaires : sans ça, la page se recharge et tu perds tout.

Délégation d'événements

Au lieu d'ajouter un événement sur chaque élément, tu l'ajoutes sur le parent et tu vérifies quel enfant a été cliqué :

Prédisez avant de lire

Un <ul> contient plusieurs <li>. On attache UN SEUL addEventListener("click", ...) sur le <ul>. Avant de dérouler : si l'utilisateur clique sur un <li> enfant, le listener posé sur le <ul> parent se déclenchera-t-il ? Et dans le handler, à quoi correspondent event.target et event.currentTarget ?

Voir la réponse

Oui, le listener du <ul> se déclenche. Quand on clique sur un <li>, l'événement remonte de l'élément cliqué vers ses ancêtres : c'est la propagation par remontée (event bubbling). Le <ul> parent reçoit donc l'événement. Dans le handler : event.target est l'élément réellement cliqué (le <li> précis), tandis que event.currentTarget est l'élément qui porte le listener (le <ul>). C'est le principe de la délégation d'événements : un seul écouteur sur le parent gère tous les enfants, y compris ceux ajoutés dynamiquement plus tard.

document.querySelector("#liste").addEventListener("click", function(event) {
  if (event.target.tagName === "LI") {
    event.target.classList.toggle("fait");
  }
});

Avantage : ça fonctionne même pour les éléments ajoutés dynamiquement après le chargement de la page.

addEventListener — listening to actions

Events are the heart of interactivity. When a user clicks, types, scrolls — JavaScript can react.

const button = document.querySelector("#myButton");

button.addEventListener("click", function() {
  alert("You clicked!");
});

The addEventListener method takes two arguments:

  1. The event type: "click", "submit", "input", "keydown"...
  2. The handler function: what happens when the event occurs

Common events

  • click — mouse click
  • submit — form submission
  • input — typing in a field (real-time)
  • keydown — key pressed
  • mouseover / mouseout — mouse hover
  • change — field value changed (when it loses focus)

These are just the most common ones: there are dozens of event types (keyboard, mouse, touch, drag & drop, form, media, scroll...). For the full list, keep these two references handy:

The event object

One detail may have surprised you: our functions receive an event parameter we never asked for. Where does it come from?

The key is to realize that you are not the one calling your function. With addEventListener, you simply hand your function to the browser: "when a click happens, run this one". It's then the browser that calls it, at the moment of the click. And when it does, it takes the opportunity to pass it an event object as the first argument, describing what just happened: the action type, the target element, the key pressed, the click position...

In other words, the argument shows up on its own because the caller is the browser, not you. You just pick its name (event, e, whatever): what matters is its position, the first parameter.

Why the handler receives an event object: you hand your function to the browser; at the moment of the click, the browser builds an event object then calls your function passing it that object. 1. You hand your function to the browser addEventListener("click", myFunction) 2. The user clicks 3. The browser builds an event object type, target element, key, click position… 4. The browser calls YOUR function myFunction(event)
The browser calls your function, not you: as it does, it hands over the event object. That's why you receive an argument you never asked for.

So every handler receives this object. Here's how to use it:

document.querySelector("form").addEventListener("submit", function(event) {
  event.preventDefault(); // prevents page reload

  const input = document.querySelector("#email");
  console.log("Email:", input.value);
});

document.addEventListener("keydown", function(event) {
  console.log("Key:", event.key); // "Enter", "Escape", "a"...
});

event.preventDefault() is essential for forms — without it, the page reloads and you lose everything.

Event delegation

Instead of adding an event on each element, you add it on the parent and check which child was clicked:

Predict before reading

A <ul> contains several <li> items. A single addEventListener("click", ...) is attached to the <ul>. Before scrolling down: if the user clicks on a child <li>, will the listener placed on the <ul> parent fire? And in the handler, what do event.target and event.currentTarget refer to?

See the answer

Yes, the <ul> listener fires. When you click on a <li>, the event travels up from the clicked element to its ancestors: this is event bubbling. The <ul> parent therefore receives the event. In the handler: event.target is the element actually clicked (the specific <li>), while event.currentTarget is the element that holds the listener (the <ul>). This is the principle of event delegation: a single listener on the parent handles all children, including those added dynamically later.

document.querySelector("#list").addEventListener("click", function(event) {
  if (event.target.tagName === "LI") {
    event.target.classList.toggle("done");
  }
});

Advantage: it works even for elements added dynamically after the page loads.

Essayez vous-même

🎯 Pratique

S'entraîner (clique pour ouvrir) :

Prompt IA
Avec l'IA

Copiez ce prompt dans Claude ou ChatGPT :

Crée un formulaire de contact HTML avec validation JavaScript en temps réel. Utilise addEventListener sur les champs input et submit. Explique chaque événement utilisé.
💬 Ré-explique sans regarder
Ré-explique sans regarder

Sans relire la réponse de l'IA : sur la soumission d'un formulaire, pourquoi appelle-t-on event.preventDefault(), et que se passe-t-il si on l'oublie ?

Une bonne explication dit : par défaut, le navigateur réagit à un submit en envoyant le formulaire et en rechargeant la page. event.preventDefault() annule ce comportement natif pour qu'on gère la soumission en JavaScript (lire les .value, valider, appeler une API). Si on l'oublie : la page se recharge, le code après ne s'exécute pas et tout est perdu.
Exercice : Corrigez le code de l'IA

L'IA a oublié event.preventDefault() dans le handler de formulaire. La page se recharge au lieu d'afficher le message. Ajoutez la ligne manquante.

Corrigez le code
⚖️ Juge le code de l'IA
Accepter ou rejeter le code de l'IA

Tu demandes à l'IA de rendre chaque tâche d'une liste cliquable (clic = barrer). Elle propose ce code. Ton rôle de relecteur : l'accepter tel quel ou le rejeter, et dire pourquoi.

const taches = document.querySelectorAll("#liste li");
taches.forEach(function(li) {
  li.addEventListener("click", function() {
    li.classList.toggle("fait");
  });
});
À rejeter pour ce besoin. Le code tourne, mais il attache un listener à chaque <li> existant au moment de l'exécution : toute tâche ajoutée ensuite (cas typique d'une todo-list) ne réagira pas au clic. C'est exactement le piège que résout la délégation : un seul addEventListener("click") sur le #liste parent, puis un test sur event.target. Ça couvre les éléments dynamiques et évite des dizaines de listeners.
🧠 Rappel libre
Rappel libre

Sans remonter dans la leçon : quels sont les deux arguments d'addEventListener, et d'où vient l'objet event que reçoit le handler alors qu'on ne l'a jamais demandé ?

addEventListener prend le type d'événement ("click", "submit", "input"…) et une fonction handler. On ne fait que confier cette fonction au navigateur : ce n'est pas nous qui l'appelons. Au moment de l'action, c'est le navigateur qui l'appelle et lui passe un objet event en premier argument (type, event.target, event.key, position…). Le nom est libre, c'est sa place de premier paramètre qui compte.
Que fait event.preventDefault() ?
Quel événement détecte la saisie en temps réel dans un champ ?
Qu'est-ce que la délégation d'événements ?
Prochaine étape

Votre page réagit désormais aux clics et aux saisies du visiteur. Reste à la nourrir avec des données venues d'ailleurs. La prochaine leçon va chercher l'information sur le web : Fetch et les API, pour récupérer des données distantes sans jamais recharger la page.

Leçon 7 : Fetch et API →

Une erreur dans cette leçon, un passage flou, une question ? Écrivez-moi : chaque retour améliore ce cours.

Besoin d'un développeur pour votre projet ?

Réponse sous 24h · Sans engagement