Créer et déclencher des évènements

Dans cet article, nous allons voir comment créer et diffuser des évènements dans le DOM. Ce type d'évènements ainsi créés sont appelés des évènements synthétiques, en opposition aux évènements déclenchés par le navigateur.

Créer des évènements spécifiques

Les évènements peuvent être créés avec le constructeur Event, comme ceci :

js
const event = new Event("build");

// On écoute l'évènement
elem.addEventListener(
  "build",
  function (e) {
    /* … */
  },
  false,
);

// On diffuse l'évènement
elem.dispatchEvent(event);

Dans l'exemple précédent, on utilise la méthode EventTarget.dispatchEvent().

Le constructeur est pris en charge par la plupart des navigateurs modernes (Internet Explorer étant l'exception). Pour une approche plus verbeuse (mais qui fonctionne pour Internet Explorer), voir l'ancienne méthode ci-après.

Ajouter des données spécifiques avec CustomEvent()

Afin d'ajouter des données supplémentaires à l'objet représentant l'évènement, on peut utiliser l'interface CustomEvent et la propriété detail afin de passer des données supplémentaires. On peut ainsi créer un évènement avec des données complémentaires de la façon suivante :

js
const event = new CustomEvent("build", { detail: elem.dataset.time });

Ces données seront alors accessibles lors de la gestion de l'évènement :

js
function eventHandler(e) {
  console.log("The time is: " + e.detail);
}

L'ancienne méthode

Cette ancienne approche pour créer des évènements utilise des API inspirées de Java. Dans l'exemple qui suit, on utilise document.createEvent() :

js
// On crée l'évènement
const event = document.createEvent("Event");

// On définit son nom à 'build'.
event.initEvent("build", true, true);

// On écoute l'évènement
elem.addEventListener(
  "build",
  function (e) {
    // e.target === elem
  },
  false,
);

// On diffuse l'évènement sur un élément ou
// tout autre objet EventTarget.
elem.dispatchEvent(event);

Bouillonnement des évènements

Généralement, un évènement sera déclenché depuis un élément enfant et remontera jusqu'à ce qu'un élément ancêtre l'intercepte (éventuellement en gérant les données supplémentaires) :

html
<form>
  <textarea></textarea>
</form>
js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

// On crée un nouvel évènement en permettant le bouillonnement
// et on fournit d'éventuelles données supplémentaires avec la
// propriété "detail"
const eventAwesome = new CustomEvent("awesome", {
  bubbles: true,
  detail: { text: () => textarea.value },
});

// L'élément de formulaire écoute cet évènement spécifique et affiche
// dans la console le résultat de la méthode text() qui a été passée
// avec detail
form.addEventListener("awesome", (e) => console.log(e.detail.text()));

// Lorsque la personne tape dans le champ, on déclenche l'évènement
// sur le même élément qui a généré l'évènement input
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));

Créer et diffuser des évènements dynamiquement

Les éléments peuvent écouter des évènements qui n'ont pas encore été créés :

html
<form>
  <textarea></textarea>
</form>
js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

form.addEventListener("awesome", (e) => console.log(e.detail.text()));

textarea.addEventListener("input", function () {
  // On crée et on diffuse/déclenche un évènement à la volée
  // Note : on a également utilisé une expression de fonction
  // plutôt qu'une fonction fléchée et "this" représentera donc
  // l'élément
  this.dispatchEvent(
    new CustomEvent("awesome", {
      bubbles: true,
      detail: { text: () => textarea.value },
    }),
  );
});

Déclencher des évènements natifs

Cet exemple illustre la simulation d'un clic (ce qui revient à générer l'évènement d'un clic depuis le programme) sur une case à cocher grâce aux méthodes du DOM. Voir l'exemple en action.

js
function simulateClick() {
  const event = new MouseEvent("click", {
    view: window,
    bubbles: true,
    cancelable: true,
  });
  const cb = document.getElementById("checkbox");
  const cancelled = !cb.dispatchEvent(event);

  if (cancelled) {
    // Un gestionnaire a appelé preventDefault.
    console.log("annulé");
  } else {
    // Aucun des gestionnaires n'a appelé preventDefault.
    console.log("pas annulé");
  }
}

Voir aussi