Updated : Déc 15, 2019 in Javascript

Maîtriser Javascript : les événements

Un événement est une notification que quelque chose de particulier s’est produit. Pour Javascript c’est surtout dans l’environnement d’un navigateur que ça se passe. Par exemple on peut connaître le moment où une page HTML a fini de se charger ou lorsqu’un utilisateur clique quelque part.

Javascript reconnaît 4 types d’événements :

  • les actions de l’utilisateur
  • les événements asynchrones (on l’a vu avec les callbacks)
  • les timers
  • les événements spécifiques d’une application

Événements du DOM

L’API du DOM reconnaît presque 200 événements, sans compter que les navigateurs s’amusent à en inventer. Prenons l’exemple d’un clic sur un bouton :

<button>Clic ici !</button>

document.querySelector('button').addEventListener('click', 
  () => console.log('Clic sur le bouton !')
);

On peut faire l’inverse, donc supprimer une écoute, avec la méthode removeEventListener.

Comme tout dans Javascript un événement est un objet avec des propriétés disponibles :

  • target : l’élément du DOM qui déclenche l’événement
  • currentTarget : l’élément du DOM qui est la cible de l’événement
  • bubbles : indique si l’événement se propage à travers le DOM

Vous avez la liste complète ici.

Si vous voulez voir effectivement à quoi ressemble cet objet changez ainsi le code ci-dessus :

document.querySelector('button').addEventListener('click', 
  e => console.log(e)
);

Vous verrez que cet objet est très chargé !

Un question à prendre en compte pour les événements du DOM est : à quel niveau l’événement est-il écouté et pris en compte ? Le DOM a une structure hiérarchique :

Au sommet de la hiérarchie, juste avant html, on a document. Les différents éléments sont appelés des nœuds. Quand on clique quelque part que se passe-t-il ? Le nœud visible le plus proche du clic va émettre un événement click. Si on a prévu d’écouter cet événement au niveau de ce nœud alors il est pris en compte à ce niveau et on lui transmet un objet Event. Si on n’a pas prévu d’écoute au niveau de ce nœud, ou si on a autorisé l’événement à continuer son chemin, alors l’événement poursuit ce chemin (Event bubbling) vers le parent, puis le parent du parent, et ainsi de suite, dans la hiérarchie du DOM.

C’est du moins le fonctionnement par défaut. On peut imposer le fonctionnement inverse, donc du nœud parent vers les enfants en utilisant le troisième paramètre de la méthode addEventListener. On parle plus alors de bubbling mais de capture. Par défaut ce troisième paramètre vaut false, il suffit de lui donner la valeur true pour obtenir ce fonctionnement inverse. Pour bien visualiser tout ça je vous conseille la lecture de cet article très bien fait.

On peut gérer cette propagation avec ces méthodes :

  • preventDefault : l’événement n’est pas arrêté mais sa propriété defaultPrevented a la valeur true, en gros il ne sera plus pris en compte par le navigateur même si on a une action par défaut comme par exemple pour un lien, mais encore par les écoutes que vous avez vous-même mises en place,
  • stopPropagation : l’événement est arrêté,
  • stopImmediatePropagation : là c’est l’artillerie lourde, on arrête la propagation, même pour une écoute attaché au noeud concerné.

Au niveau du DOM on a une foule d’événements disponibles :

  • focus : par exemple quand on « entre » dans un contrôle de formulaire,
  • drag : les mouvements de la souris,
  • form : par exemple la soumission d’un formulaire,
  • media : par exemple la mise en marche d’un vidéo,
  • touch : les actions sur un écran,

Les timers

Une catégorie particulière d’événement est constituée par les timers. Javascript est à thread unique (simple-threaded). Donc à un moment donné Javascript ne peut exécuter qu’une seule chose. J’ai déjà parlé précédemment justement de la nécessité d’opérations asynchrones pour éviter les blocages. Mais si ce n’est pas Javascript qui effectue les opérations c’est qui ? Par exemple on lance une minuterie pour une exécution différée et en attendant on continue tranquillement à exécuter d’autres instructions. C’est qu’il n’y a pas que Javascript dans un navigateur, il y a aussi des Web API, une bonne façon de trouver d’autres threads. Pour une belle explication de ce fonctionnement je vous conseille cette vidéo.

setInterval

La méthode setInterval appelle une fonction de façon répétitive avec un intervalle fixe :

const action = () => console.log('coucou') 
setInterval(action, 2000); // Envoie "coucou" toutes les 2 secondes

setTimeout

La méthode setTimeout appelle une fonction une seule fois au bout du délai précisé :

const action = () => console.log('coucou') 
setTimeout(action, 2000); // Envoie "coucou" au bout de 2 secondes

On peut aussi interrompre un timer avec la méthode clearInterval (pour setInterval), et clearTimeout (pour setTimeout) :

const action = () => console.log('coucou')
const id = setInterval(action, 2000);
const stopAction = () => {
  console.log('Ça a assez duré !')
  clearInterval(id)
}
setTimeout(stopAction , 5000)

Ça implique de prévoir un identifiant pour pouvoir intervenir sur le timer.

Créer des événements

On a vu qu’on dispose de l’objet Event pour les événements. On peut créer un événement facilement :

const evenement = new Event('monEvent');

On peut alors écouter cet événement sur un élément :

elem.addEventListener('monEvent', function (e) { ... }, false)

Et le distribuer :

elem.dispatchEvent(evenement);

Si on veut transmettre des données Event n’est pas suffisant. Heureusement on a aussi  CustomEvent :

const evenement = new CustomEvent('monEvent', { 'detail': mes données })

La propriété detail permet de transmettre des données :

const evenement = new CustomEvent('monEvent', {'detail': 'coucou'})
const action = (e) => console.log(e.detail)
const bouton = document.querySelector('button')
bouton.addEventListener('monEvent', action)
bouton.dispatchEvent(evenement); //  "coucou"

Conclusion

Javascript fait la part belle aux événements et à l’interactivité et on a vu l’importance de ses capacités à gérer des traitement asynchrones. Dans le prochain article j’aborderai node.js, le passage obligé de tout codeur javascript.

 

Laisser un commentaire