JS (4/5) — Évènements
Objectif pour le projet
Savoir ce qu'est un évènement, le récupérer et le gérer
Définir vos fonctions de callbacks
Supprimer du contenu en réaction à une action utilisateur (click, frappe de touche, etc...)
Cours
Généralité
Un évènement est le signal que quelque chose s'est produit, généralement sur votre page HTML. En JavaScript, il s'agit d'une abstraction du pattern observeur/observable. Par exemple :
Mouse events
click
– quand la souris clique sur un élément (sur les dispositif tactile, cela survient au tap).contextmenu
– quand un clique droit survient.mouseover
/mouseout
– quand le cursor de la souris survole / sort d'un élement.
Form element events
submit
– quand un visiteur soumet un<form>
.focus
– quand un visiteur focus un élément d'un form, e.g.<input>
.
Document events
DOMContentLoaded
– quand le HTML est totalement interprété, et donc que le DOM est totalement construit.
CSS events
transitionend
- quand une animation CSS se termine.
Pour réagir à ces évènements, on utilise des handler (gestionnaires). Ce sont des fonctions qui s'exécutent dans le cas où un évènement précis survient. Pour cela, on écoute avec un listener ledit évènement.
Vous pouvez aussi utiliser des objets comme handler. L'un des avantages est de permettre une approche de délégation par objet. Un petit exemple dans mon cours ici.
Quand un évènement survient, un objet event généralement est généré, et contient un nombre d'information imporante pour traiter correctement l'action réalisée. La propriété target
de l'évènement contient le noeud qui subit l'action (le type de noeud est déréférencable via la propriété tagName
de target).
Bubbling
Le principe du bubbling est le suivant : quand un évènement survient sur un élément de votre page, le handler associé à cet élément est appelé, puis l'évènement est passé à l'élément parent qui appelle son handler (s'il en a un) pour cet évènement, et ainsi de suite jusqu'au root de la page.
Ce principe est très utile pour attacher des comportements génériques ou rendre des noeuds imbriqués réactif à un même évènement. Par exemple :
Quid de la propriété target
de l'évènement alors ? C'est simple :
event.target
correspond toujours au noeud le plus profond qui a reçu l'évènement (i.e. le premier élément de la page qui a reçu l'évènement) ;this
ouevent.currentTarget
(en fonction de si vous utilisez des fonctions anonymes ou des arrows) dans un handler permet de savoir quel élément est en train de traiter l'évènement.
En reprenant l'exemple précédent, en cliquant sur l'élément code
:
event.target.tagName
=code
this.tagName
=div
Alors qu'en cliquant sur la div
: En reprenant l'exemple précédent, en cliquant sur l'élément code
:
event.target.tagName
=div
this.tagName
=div
Dans certains cas, on a besoin de stopper le bubbling -- par exemple lorsque un élément parent écoute le même évènement que son enfant, mais n'a pas le même handler. Si on ne supprimait pas le bubbling, et en supposant qu'on clique sur le noeud enfant, on exécuterait d'abord l'handler de l'enfant PUIS celui du parent ! Pour arrêter le bubbling, on invoque la fonction stopPropagation()
de l'évènement dans un handler.
Exercice d'introduction
Pour vous aider à vous approprier l'ajout et la suppression d'handlers, considérer l'exercice suivant. Soit deux boutons HTML classique sur votre page, identifiés respectivement par b1
et b2
, on veut alterné le bouton qui possède un listener sur l'évènement click
.
Aussi, lorsque la page est servi à votre client, seul b1
possède un handler pour son évènement de click
; b2
n'en possède pas. Lorsque b1
est cliqué, il associe à b2
un listener sur l'évènement click
, et b1
lui perd le sien, de tel sorte qu'en cliquant deux fois de suite sur b1
, rien ne se passe. Le comporte est identique pour b2
: en cliquant une fois dessus lorsqu'il s'est vu attribué son listener, il le perd et le donne de nouveau à b1
et donc, cliquer une deuxième fois de suite sur b2
ne fait plus rien.
Exercice
Dans cette exercice, nous implémenterons un bouton "like" sur nos médias.
Imaginons le code HTML du bouton
Stylisons le un peu. Importez directement dans votre page ou via un fichier le CSS suivant (car je suis gentil alors que j'écris les lignes pendant mon WE ! grr)
Il vous faudra accéder à Font Awesome pour récupérer le logo. Je vous invite à passer par le CDN suivant, en rajoutant cela dans le de votre page HTML : <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
Que fait ce code CSS ?
Avez-vous identifié comment le comportement du bouton ?
En effet, nous utiliserons la classe .press
pour identifier si oui ou non le bouton a été cliqué.
Codez la logique associé à ce bouton like. Vous utiliserez la méthode
toggle
qui utilise uneDOMString
pour jouer avec les jetons classes. Vous aurez aussi envie d'utiliser la propriété.children
d'un noeud pour ne récupérer que les noeuds HTML, sans le texte et autre.
Le corps de la fonction ne fait que deux lignes.
Exercice -- Déplacement via le clavier
Dans cet exercice, vous réagirez à certaines touches clavier pour parcours votre bibliothèque de média (par exemple avec Ctrl + arrow left/right).
Vous pouvez partir du code HTML suivant
La zone en haut, de focus, donne des détails sur le média sélectionné (on-focus
). Par défaut, les descriptions et les images doivent être masqués dans la liste. A chaque appuie de flèche, mettre à jour votre zone de focus.
Vous aurez encore besoin de jouer avec la propriété CSS visibility:hidden
.
Exercice
Imaginons maintenant qu'en tant qu'administrateur votre serveur peut vous renvoyer un tableau d'utilisateurs. Vous voulez pouvoir l'ordonner de manière ascendante. Soit le code HTML suivant :
Et le code JavaScript suivant :
Imprégnez vous du code JS ;
Faîtes fonctionner le code.
Exercice -- délégation d'évènements
Cet exercice va vous servir à bien comprendre le concept de capture et de "Bubbling" des évènements.
Recopiez et jouer avec le code suivant : ```html
FORMDIV
P
``` 2. Que constatez vous ?
Très bien. Imaginez maintenant que vous êtes en train de consulter le catalogue de média, sous forme de grille, pour les ajouter à une playlist :
Vous allez déléguer la gestion du click à votre
table
en jouant avec la propriététarget
de l'évènementclick
; cela évitera d'avoir une quantité faramineuse de listener sur votre page et améliorera drastiquement la qualité et la maintenabilité de votre code. Du coup, aucuntd
ne doit directement avoir de handler ni de listenerclick
. Faîtes apparaître une alerte pour indiquer que l'élémentMx
à bien été ajouté à la playlist.
Attention, dans votre table
, il n'y a pas que des td
! Vous devez donc vérifier si le target est bien un td
. Vous pouvez utiliser la propriété tagName
de votre target pour cela (comme pour l'exercice précédent avec th
donc).
Vous avez dû remarquer la présence de balise
strong
dans vostd
. Que se passe-t-il si vous cliquez dessus ? Normalement, votre délégation d'évènement ne doit pas fonctionner, puisque vous vérifier uniquement que le clique se produit bien dans une cellule. En utilisantevent.target.closest('td')
vous récupérer l'ancêtre le plus proche de l'ancêtre passé en paramètre. Assurez vous juste que l'élément que vous récupérez appartient bien au tableau, et le tour est joué !
Exercice -- image de profil
Dans cette partie, nous travaillerons à uploader une image de profil pour un utilisateur donner. Considérons le code HTML suivant :
Attacher un handler à l'input qui appellera la fonction
handleFiles
et qui lui enverra la liste des fichiers.
Soit la fonction handleFiles
suivante, à compléter, qui permet de créer une balise image et d'afficher le contenu de l'image dans la div preview
:
Compléter la fonction en créant une balise
img
à laquelle vous ajouterez à sa propriétéfile
l'image courante avant de mettre la balise dans le preview.On veut maintenant cacher le bouton
input
qui est moche, et ne réagir que sur le clique de l'avatar pour modifier ce dernier. Faîtes les modifications nécessaires.
Nous allons maintenant gérer le drag and drop d'une image qui s'affichera toujours dans le preview
. Modifier votre code HTML en rajoutant une zone de D&D
Identifier les 3 évènements qui sont liés au drag & drop dont vous aurez besoins ;
Ajouter simplement les listeners associés à la zone de
dropbox
, avec une alerte -- testez le comportement.Vous remarquerez peut-être que ces 3 évènements bubbles : empêcher cela avec la bonne méthode.
Maintenant, on va supprimer le comportement par défaut qui pourrait exister pour ces évènements pour implémenter le notre. Si vous ne vous souvenez plus de la méthode, il s'agit de
preventDefault
que l'on a vue dans la section sur les formulaires.On veut accéder aux données lâchées au moment du "drop". Pour ce faire, l'évènement possède une propriété
dataTransfert
.Avant d'envoyer la liste des fichiers à notre fonction
handleFiles
il faut les récupérer dansdataTransfert
.
Et voila, une image de profil qui gère du D&D, classe !
Last updated
Was this helpful?