From fd2e0d40b21bd1da712271443d6968622019a662 Mon Sep 17 00:00:00 2001 From: denmigda Date: Wed, 8 Nov 2023 14:42:25 +0100 Subject: [PATCH] Add events --- Readme.md | 2 - Web/X - API JS-DOM/index.md | 111 +++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index 2880725..882d561 100644 --- a/Readme.md +++ b/Readme.md @@ -10,5 +10,3 @@ include_toc: true # Web - [API JS-DOM](./Web/X%20-%20API%20JS-DOM/index.md) - - diff --git a/Web/X - API JS-DOM/index.md b/Web/X - API JS-DOM/index.md index 158c8a2..bd64d5d 100644 --- a/Web/X - API JS-DOM/index.md +++ b/Web/X - API JS-DOM/index.md @@ -101,6 +101,115 @@ for name in $ELEM.getAttributeNames(): 📖 [Plus de méthodes disponibles dans la documentation.](https://developer.mozilla.org/en-US/docs/Web/API/Element) + + +# Événements + +## Bubble vs Capture + + Dans les navigateurs, les interactions sont gérées via des événements, qui se composent de 2 phases : + +- capture + +- bubble + + + +**Capture :** La phase de capture est descendante, elle part du noeud racine et descend vers le noeud cible (target) final. Par exemple, lorsque vous cliquez sur un élément, l'événement de clic va d'abord partir du document, puis par le body. Le navigateur va propager l'événement en se demandant quel fils de l'élément courant est la cible de l'événement, afin de lui transmettre l'événement, puis recommence de manière récursive, l'élément fils cible devenant l'élément courant. + +**Bubble :** La phase de buble est montante, elle part du noeud cible (target) final et remonte vers le noeud racine. Si l'événement se propage dans le DOM (`bubble: true`), le navigateur va transmettre l'événement à l'élément père de l'élément courant, puis recommence de manière récursive, l'élément père devant l'élément courant. + + + +## Écouter un événement + +```javascript +// [JS] Javascript + +function handler(ev) { + // ev.currentTarget : $ELEM + // ev.target : source of the event. + // ev.type : $EVENT_TYPE + // ev.detail : $EVENT_DATA (si CustomEvent, cf plus bas) + // ev.preventDefault() : annuler l'action par défaut du navigateur + // e.g. lorsqu'on clique sur un lien, empêcher d'aller vers la page. + // ev.stopImmediatePropagation() : ne pas appeler les autres + // handleurs pour cet événement. +} + +$ELEM.addEventListener($EVENT_TYPE, handler); +// ou +$ELEM.addEventListener($EVENT_TYPE, ev => ... ); +``` + +```python +# [🐍] Python + +def handler(ev): + # ev.currentTarget : $ELEM + # ev.target : source of the event. + # ev.type : $EVENT_TYPE + # ev.detail : $EVENT_DATA (si CustomEvent, cf plus bas) + # ev.preventDefault() : annuler l'action par défaut du navigateur + # e.g. lorsqu'on clique sur un lien, empêcher d'aller vers la page. + # ev.stopImmediatePropagation() : ne pas appeler les autres + # handleurs pour cet événement. + +$ELEM.addEventListener($EVENT_TYPE, handler) +``` + +📖 [Plus d'informations dans la documentation.](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) + +## Écouteur délégué + +Il arrive qu'on souhaite écouter des événements sur les descendants d'un élément, qui peuvent être ajoutés, déplacés, supprimés, etc. Le problème est que cela nécessiterait de créer un écouteur pour chaque éléments et de les supprimer/ajouter à chaque modifications du DOM. + +Heureusement, il est possible d'utiliser un écouteur délégué, i.e. d'écouter l'événement sur le descendant (nécessite que l'événement soit `bubble`, i.e. se propage dans le DOM). + +```javascript +// [JS] Javascript + +function handler(ev) { + if( ev.target.matches($CSS_SELECTOR) ) { + // ... + } +} + +$ELEM.addEventListener($EVENT_TYPE, handler); +``` + +```python +# [🐍] Python + +def handler(ev): + if ev.target.matches($CSS_SELECTOR): + # ... + +$ELEM.addEventListener($EVENT_TYPE, handler) +``` + +## Créer un événement + +```javascript +// [JS] Javascript + +$ELEM.dispatchEvent( new Event($EVENT_NAME) ); +// ou +$ELEM.dispatchEvent( new CustomEvent($EVENT_NAME, {detail: $EVENT_DATA}) ); +``` + +```python +# [🐍] Python + +$ELEM.dispatchEvent( Event.new($EVENT_NAME) ) +# ou +$ELEM.dispatchEvent( CustomEvent.new($EVENT_NAME, {"detail": $EVENT_DATA}) ) +``` + +💡 Vous pouvez aussi ajouter, au 2ème argument, l'option `bubble: true` pour faire en sorte que l'événement soit bubble, i.e. se propage dans le DOM (par default `bubble: false`). + + + # Envoyer une requête REST ```javascript @@ -109,7 +218,6 @@ async query() { const anwser = await fetch($URL); // ou const answer = await fetch($URL, {method: "POST", body: $PARAMS); - // [🚩] TODO: tester mode: "no-cors" if( ! answer.ok ) throw new Error(`${answer.status}: ${answer.statusText}`); @@ -128,7 +236,6 @@ async query(): answer = fetch($URL) # ou answer = fetch($URL, {"method": "POST", "body": $PARAMS) - # [🚩] TODO: tester mode: "no-cors" if not answer.ok: raise Error(f"{answer.status}: {answer.statusText}");