M3203 - Programmation objet et événementielle - TP2


Objectifs de la séance

  • Comprendre la notion d'évènements et de programmation évènementielle
  • Savoir gérer des évènements en Javascript

Pré-requis

  • Être capable de manipuler le DOM

Résumé de la séance précédente

  • Pour accéder à un élément HTML, on utilise document.getElementById("identifiant"), avec "identifiant", l'id de l'élément HTML.
  • Pour accéder à plusieurs éléments HTML, on utilise :
    • document.getElementsByTagName("balise"), avec "balise", la balise des éléments qu'on veut récupérer ("ul", ou "p" par exemple).
    • document.getElementsByName("nom"), avec "nom", la valeur de l'attribut name des éléments qu'on veut récupérer.
    • Il existe d'autres méthodes consultables ici. Attention au "s" derrière Element pour ces méthodes ! Et attention aux majuscules !
    • Ces méthodes renvoient toujours une structure similaire à un tableau.
  • Pour ajouter un nouvel élément HTML au document :
    • On crée l'élément avec var nouvel_element = document.createElement("balise")
    • On l'ajoute au DOM avec element_parent.appendChild(nouvel_element)

Les évènements en Javascript

La notion d'évènement

Le Javascript offre des fonctionnalités permettant de rendre des pages web interactives. Jusqu'ici, nos programmes étaient exécutés séquentiellement, ligne de code par ligne de code. Pendant cette séance, nous allons voir que la page peut réagir aux actions de l'utilisateur sur les éléments du DOM. Les scripts seront alors exécutés en fonction de son comportement : le mouvement de la souris, un clic sur un bouton etc. L'exécution du script dépendra alors de ces actions, des évènements se produisant sur la page : c'est la programmation évènementielle.

Les évènements les plus courants

Les évènements permettent de déclencher l'exécution d'une fonction quand une action est effectuée sur la page (afficher un message lors d'un clic sur un bouton par exemple). Voici une liste non exhaustive de quelques évènements courants :

Évènement Action à effectuer
Évènements liés aux ressources
load Une ressource et ses dépendances ont fini de charger
beforeunload La fenêtre, le document et ses ressources sont sur le point d'être fermés
Évènements liés au focus
focus Un élement a reçu le focus
blur Un élément a perdu le focus
Évènements liés aux formulaires
reset Le bouton reset est cliqué
submit Le bouton submit est cliqué
Évènements liés à la vue
resize Le document a été redimensionné
scroll Un élément a été défilé
Évènements liés au clavier
keydown Une touche est pressée
keypress Une touche (sauf Shift, Fn, CapsLock) est dans la position "pressée"
keyup Une touche est levée
Évènements liés à la souris
mouseenter Le pointeur est placé sur l'élément auquel est attaché l'écouteur
mouseover Le pointeur est placé sur l'élément auquel est attaché l'écouteur ou l'un de ses enfants
mousemove Le pointeur est déplacé sur l'élément (déclenché de façon continu tant que le pointeur se déplace)
mousedown Un bouton du pointeur est pressé sur un élément
mouseup Un bouton du pointeur est libéré sur un élément
click Un bouton du pointeur est pressé ET libéré sur un élément
dblclick Un bouton du pointeur est cliqué deux fois sur un élément
mouseleave Le pointeur sort de l'élément auquel est attaché l'écouteur
mouseout Le pointeur sort de l'élément auquel est attaché l'écouteur ou un de ses enfants
select Du texte est sélectionné
Évènements liés au drag and drop
dragstart L'utilisateur commence à glisser un élément
drag Un élement est en train d'être glissé
dragend L'opération de glissement s'arrête
dragenter Un élément glissé entre dans une cible valide
dragover Un élément est en train d'être glissé sur une cible valide
dragleave L'élément glissé sort de la cible valide
drop L'élément est lâché sur une cible valide
Vous pouvez trouver la liste complète dans la doc.

Ajouter un évènement au travers du DOM

Nous allons voir comment utiliser les évènements à travers de l'interface standard DOM-2. Il existe d'autres techniques pour implémenter des évènements : dans les balises HTML sans passer par le DOM, on évitera ceci afin de séparer HTML et Javascript et l'interface DOM-0, plus ancienne et plus limitée.

Pour implémenter un évènement, on utilise la méthode addEventListener qui va ajouter un écouteur d'évènements sur un élément HTML se chargeant de surveiller les actions de l'utilisateur sur cet élément. Elle prend trois paramètres :

  • Le nom de l'évènement : "click", "mouseover"...
  • La fonction à exécuter
  • Optionnel : Un booléen pour spécifier le type de phase, capture ou bouillonnement

Voici comment utiliser cette méthode pour déclencher un évènement lors d'un clic sur un bouton :

						

Comment est ce que ça fonctionne ?

  • On a tout d'abord déclaré une fonction test qui lance une alerte avec le message "Vous avez cliqué".
  • On récupère ensuite l'élément HTML qui réagira à un clic de l'utilisateur : le bouton portant l'identifiant go dans la variable bouton.
  • Pour finir, on ajoute un écouteur d'évènements à ce bouton avec la méthode addEventListener en lui donnant deux paramètres : l'évènement à gérer, "click", et la fonction à appeler test. Dorénavant, à chaque clic sur le bouton go, la fonction test sera appelée et l'utilisateur recevra une alerte lui disant "Vous avez cliqué".
Et si on veut supprimer l'écouteur d'évènements ?
On utilise la méthode removeEventListener comme ceci :

// Suppression de l'écouteur avec la méthode removeEventListener
// en lui donnant les mêmes paramètres que lors de l'ajout
bouton.removeEventListener("click", test);
							

Phases de capture et bouillonnement
On a vu que la méthode addEventListener prenait en troisième paramètre un booléen optionnel désignant le type de phase. Les phases de capture et bouillonnement déterminent le sens de propagation de l'évènement. Par exemple, si on clique dans une cellule d'un tableau :
  • En phase de bouillonnement (bubbling) : c'est d'abord l'écouteur d'évènements de l'élément td qui réagira, puis celui de l'élément tr, puis celui de l'élément table et ainsi de suite vers les ancêtres suivants.
  • En phase de capture (capture), c'est le sens inverse, l'évènement est d'abord capturé par l'ancêtre puis descend dans la hiérarchie jusqu'à l'élément td.

Par défaut, la valeur de ce booléen est false, ce qui correspond à la phase de bouillonnement. Vous l'utiliserez la plupart du temps.

Vous savez maintenant ajouter un écouteur d'évènements à un élément HTML pour qu'il réagisse à toute action de l'utilisateur. À partir de là, les possibilités sont très nombreuses ! Vous pouvez bien sûr créer des jeux, valider des formulaires, créer des infographies interactives, des applications web... Voyez ce qu'on peut faire à partir de quelques formulaires, des évènements et un trombone (je ne dévoilerai pas la fin du jeu mais ça peut aller très loin).

Place aux exemples

Déclencher un évènement à la fin du chargement de la page

On utilise l'évènement load sur la fenêtre du navigateur window au tout début de son code javascript.

window.addEventListener("load", function () {
    alert("La page est chargée");
});							
							

Déclencher un évènement à l'appui d'une touche

Dans cet exemple, une alerte affiche le message "Vous avez appuyé sur une touche" quand l'utilisateur appuie sur une touche dans le champ input.
						

Déclencher un évènement au survol de la souris

Ici, le message "Vous avez survolé l'image" s'affiche quand l'utilisateur survole l'image.
						

Utiliser une fonction anonyme

Plutôt que donner le nom d'une fonction en paramètre à la méthode addEventListener, on peut utiliser une fonction anonyme (une fonction qui n'a pas de nom !). La fonction est déclarée directement dans le deuxième paramètre de la méthode addEventListener. L'exemple précédent de l'évènement au survol de la souris peut aussi s'écrire comme ceci avec une fonction anonyme. Le résultat sera identique.

						

L'objet Event

L'objet Event est créé quand un évènement a été déclenché. Il permet d'obtenir de nombreuses informations : l'élément à l'origine de l'évènement, la touche pressée, les coordonnées du pointeur...

Cet objet est fourni à la fonction qui gère l'événement sous la forme d'un paramètre qu'on nommera ici e.

Voici un exemple de son utilisation :

						

Lors d'un clic sur le bouton go, la fonction exécutée modifie le contenu de l'élément cible de l'évènement (le bouton, e.target) avec la propriété innerHTML.

On peut ainsi accéder à l'élément à l'origine de l'évènement avec la propriété target, à l'élément auquel a été implémenté l'évènement avec currentTarget ou au type de l'évènement avec la propriété type.

Déclencher un évènement à la fermeture de la page

Grâce à l'objet Event, on peut intercepter la fermeture de l'onglet/de la page pour demander une confirmation à l'utilisateur. C'est utile pour des applications où l'utilisateur a pu rentrer des informations et devraient les enregistrer.
						

Attention à cet évènement, le comportement des navigateurs peut varier. Voir la compatibilité des navigateurs ici.

Récupérer la position de la souris

						

Récupérer la touche frappée

						

Attention, keyCode, charCode et which sont dépréciées et non standards, elles peuvent ne pas avoir le même comportement selon les navigateurs, privilégier key comme montré ci-dessus.

Pour terminer, je vous propose de programmer une petite animation qui réagira au survol de la souris. Aller à l'exercice