L’invasion du html mutant
- Slides en ligne
- ffoodd.fr/devfest.2024/
- Le jeu
- ffoodd.fr/devfest.2024/jeu/
- Les accès wi-fi
codelab
—12ans
Le décor
Préparez-vous à découvrir un script qui vous fera baliser !
- Lancez le jeu dans votre navigateur favori.
- Démarrez votre inspecteur, avec F12 ou Maj+Ctrl+i.
Vous aurez besoin d’ouvrir et refermer votre inspecteur régulièrement.
Le héros
Parce que c’est vous, le héros. Ça change, un peu.
Chaque niveau aura la même structure :
- Un portrait du personnage central — généralement, le mutant !
- Une zone de saisie, plus ou moins complexe.
- Une scène, dans laquelle a lieu l’invasion.
Des personnages mal intentionnés apparaissent inopinément…
À vous de vous en débarrasser avant qu’il ne soit trop tard !
L’échauffement
Prenons quelques repères.
Nous allons nous servir d’un MutationObserver
. Quelques règles :
- Il faut l’instancier.
- Il faut lui donner un cible.
- Il faut le débrancher, à un moment.
Ces éléments seront déjà en place dans la suite du jeu
— mais il est important de savoir qu’ils existent.
Le décollage
Bouclez vos ceintures…
Vous avez remarqué l’objet vide, à la fin ? C’est lui qui va nous intéresser le plus !
Le premier palier du jeu concerne les options de base d’une observation.
Le zombie
Entrons dans le vif du sujet !
Les changements d’attribut
Les attributs, ça va, ça vient…
attributes: true
Cas d’usage
Songez à tous ces attributs qui peuvent être importants :
hidden
, aria-label
, aria-invalid
…
Le vilain
Et oui, il n’y a pas que des gentils, dans la vie.
Les changements textuels
Quoi de pire qu’un changement au sein d’un nœud texte, franchement ?
characterData: true
Cas d’usage
Imaginez un peu : un bouton dont l’intitulé change, mais pas d’état ni de classe auxquels s’accrocher ? Ou mieux, vous faites vos slides en HTML, avec une vue présentateur que vous voulez synchroniser sur votre pagination.
L’alien
Ils sont parmi nous !
Les changements de descendance directe
Les enfants, ça ne tient pas en place !
childList: true
Cas d’usage
Un contenu injecté inopinément — au hasard,
lors d’un scroll infini — c’est irritant ! Ou encore : une iframe
dont vous devriez ajuster la hauteur en fonction de son contenu…
Ceci n’est pas inspiré de faits réels, évidemment !
Le fantôme
Vous n’avez pas entendu un truc ?
Quand il y a trop d’attributs…
Il faut choisir !
attributeFilter: ['id']
Cas d’usage
Imaginez un framework qui indique l’état invalide d’un champ de formulaire
avec une classe, mais sans aria-invalid
? Vous savez comment patcher ça,
maintenant.
Toute ressemblance avec des frameworks serait purement fortuite.
Le sorcier
Il faut se méfier des types encapuchonnés
avec un grand bâton.
Les changements de descendance profonde
Il n’y a pas que les parents pour surveiller les enfants : tous leurs aïeux le peuvent.
childList: true, subtree: true
Cas d’usage
Le saviez-vous ? Un WebComponent ne peut pas émettre un événement en disparaissant… Donc si vous voulez déclencher quelque chose, vous saurez comment faire !
Le vampire
Il faut aussi se méfier des types avec un sourire qui déborde.
Les valeurs disparues
Se souvenir du passé, ça peut aider.
attributeOldValue: true
mutation.oldValue.includes('mutant')
On peut aussi affiner :
mutation.attributeName === 'class'
Cas d’usage
Vous avez connu l’époque des classes .open
et .show
pour afficher ou masquer un élément — et aucun autre changement dans le DOM ?
Ou un script tiers qui fait des trucs sans émettre d’événements ?
Bien entendu, ce sujet est une pure fiction.
Le vieillissement
Vous ne l’aviez pas vu venir, hein ?
Les caractères disparus
C’est presque un cercle, les caractères disparus.
characterDataOldValue: true
mutation.oldValue === '💀'
Cas d’usage
Un composant de création de mot de passe qui enlève la description des contraintes franchies… Vous n’avez jamais vu ça ?
Le boss final
C’est le moment de sauver des vies.
Les solutions
Le bazooka
document.querySelectorAll('mu-tant:not([type=""])')
.forEach(mutant => mutant.remove());
Le précautionneux
if (mutation.target.nodeName === 'MU-TANT' && mutation.target.type !== '') {
mutation.target.remove();
} else if (mutation.target.closest('mu-tant') !== undefined) {
mutation.target.closest('mu-tant').remove();
}
Malgré toutes les options, on peut avoir du mal à trier les mutations.
Fort à propos, le type MutationRecord
dispose de tout un tas de propriétés bien utiles.
Mais encore ?
Les MutationObserver
ne sont pas seuls !
-
Les
IntersectionObserver
permettent de surveiller les collisions visuelles entre éléments ; -
Les
ResizeObserver
permettent de surveiller les changements de dimensions d’un élément ; -
Les
PerformanceObserver
permettent de surveiller différents indicateurs de performance et de les consigner dans les logs.
Merci
Et à bientôt
Crédits
- Emojis : Twemoji — par Twitter ;
- Typographie de titraille : Bello Pro — créée par Underware ;
- Typographie de labeur : Museo Slab — créée par Exljbris ;
- Moteur de présentation inspiré de "CSS scroll-snap slide deck that supports live coding" de Stephanie Eckles sur Smashing Magazine.