À partir de Chrome 135, introduction de `command` et `commandfor` sur les boutons
(developer.chrome.com)- Les boutons sont essentiels pour créer des applications web dynamiques. Ils servent à ouvrir des menus, changer d’action et soumettre des formulaires
- Dans Chrome 135, les nouveaux attributs
commandetcommandforaméliorent et remplacent les anciens attributspopovertargetactionetpopovertarget - Problèmes rencontrés jusqu’ici lors de l’implémentation du comportement des boutons :
- Les gestionnaires HTML
onclickpeuvent être limités dans le code réel à cause des politiques de sécurité (CSP) - Il faut synchroniser l’état entre le bouton et d’autres éléments, et le code de gestion d’état tout en préservant l’accessibilité est complexe
- Même avec React, AlpineJS, Svelte, etc., la gestion de l’état et des événements reste complexe
- Les gestionnaires HTML
Le modèle command et commandfor
- Les attributs
commandetcommandforpermettent à un bouton d’agir de manière déclarative sur un autre élément. Cela apporte la commodité d’un framework tout en conservant la flexibilité - Le bouton
commandforutilise un ID (comme l’attributfor) etcommandaccepte des valeurs intégrées, ce qui offre une approche plus intuitive - Exemple : implémentation d’un bouton d’ouverture de menu
- Pas besoin de
aria-expandedni de JavaScript supplémentaire
<button commandfor="my-menu" command="show-popover"> Open Menu </button> <div popover id="my-menu"> <!-- ... --> </div> - Pas besoin de
command et commandfor vs popovertargetaction et popovertarget
- Si vous avez déjà utilisé
popover, ces attributspopovertargetetpopovertargetactionvous sont peut-être familiers - Ils fonctionnent de manière similaire à
commandforetcommand, mais sont spécifiques aux popovers - Les nouveaux attributs remplacent complètement les anciens et apportent des fonctionnalités supplémentaires
Commandes intégrées
- L’attribut
commandintègre des actions associées à différentes APIshow-popover: correspond àel.showPopover()hide-popover: correspond àel.hidePopover()toggle-popover: correspond àel.togglePopover()show-modal: correspond àdialogEl.showModal()close: correspond àdialogEl.close()
- Exemple : implémentation d’une boîte de dialogue de confirmation de suppression
- Gestion de l’état et de l’accessibilité possible sans JavaScript
<button commandfor="confirm-dialog" command="show-modal"> Delete Record </button> <dialog id="confirm-dialog"> <header> <h1>Delete Record?</h1> <button commandfor="confirm-dialog" command="close" aria-label="Close"> <img role="none" src="/close-icon.svg"> </button> </header> <p>Are you sure? This action cannot be undone</p> <footer> <button commandfor="confirm-dialog" command="close" value="cancel"> Cancel </button> <button commandfor="confirm-dialog" command="close" value="delete"> Delete </button> </footer> </dialog>- Code de traitement du résultat : la valeur de retour peut être traitée dans l’événement
closede la boîte de dialogue
dialog.addEventListener("close", (event) => { if (event.target.returnValue === "cancel") { console.log("Cancel was clicked"); } else if (event.target.returnValue === "delete") { console.log("Delete was clicked"); } });
Commandes personnalisées
- En plus des commandes intégrées, il est possible de définir des commandes personnalisées en utilisant le préfixe
-- - Les commandes personnalisées déclenchent un événement
"command"sur l’élément cible, mais n’exécutent pas de logique supplémentaire - Exemple : implémentation d’une commande de rotation d’image
<button commandfor="the-image" command="--rotate-landscape"> Landscape </button> <button commandfor="the-image" command="--rotate-portrait"> Portrait </button> <img id="the-image" src="photo.jpg"> <script type="module"> const image = document.getElementById("the-image"); image.addEventListener("command", (event) => { if (event.command === "--rotate-landscape") { image.style.rotate = "-90deg"; } else if (event.command === "--rotate-portrait") { image.style.rotate = "0deg"; } }); </script>
Traitement des commandes dans le Shadow DOM
- Dans le Shadow DOM,
commandforfonctionne sur la base des ID, ce qui impose les limitations suivantes :- Impossible de référencer des éléments entre plusieurs Shadow DOM
- Dans ce cas, il est possible d’utiliser l’API JavaScript pour définir la propriété
.commandForElement
- Exemple : connexion de commande dans le Shadow DOM
<my-element> <template shadowrootmode="open"> <button command="show-popover">Show popover</button> <slot></slot> </template> <div popover><!-- ... --></div> </my-element> <script> customElements.define("my-element", class extends HTMLElement { connectedCallback() { const popover = this.querySelector('[popover]'); this.shadowRoot.querySelector('button').commandForElement = popover; } }); </script>
Suite du programme
- Chrome prévoit d’ajouter d’autres commandes intégrées :
- ouverture et fermeture des éléments <details>
- prise en charge de la commande
show-pickersur <input> et <select> - commandes de lecture pour <video> et <audio>
- fonctionnalité de copie de texte depuis un élément
1 commentaires
Avis Hacker News
Les théoriciens des langages de programmation spéculent depuis les années 80 sur « comefrom », une version plus puissante de « goto ». Cela n’a été implémenté que dans intercal. intercal est supérieur à des langages comme C en matière de sécurité, de performances et d’ergonomie, mais peine à percer sur le marché commercial. Il est intéressant de voir JavaScript intégrer cette fonctionnalité d’intercal. Espérons que cela mène à une explosion de la programmation courtoise, comme les objets à fermeture de JavaScript ont amené la programmation fonctionnelle dans le courant dominant
Les invokers ne sont pas propres à Chrome. Ils sont déjà disponibles aussi dans Firefox nightly
L’idée d’implémenter des comportements d’UI déclaratifs sans JS est séduisante
aria-expanded)show-modalintègrent l’accessibilité directement dans le balisage--rotate-landscape) permettent aux composants d’exposer une API via HTMLQuestions :
.commandForElemententre des shadow roots. Cela ressemble à un problème seulement à moitié résolushow-picker,toggle-details), la plateforme va-t-elle enfler avec une syntaxe de niche ?Spécification :
button, attributcommandforbutton, attributcommandEst-ce que c’est le pattern action/messagerie qu’utilisaient Next, Be, Apple et d’autres il y a environ 30 ans, ou bien est-ce que quelque chose m’échappe ?
La première boîte à outils UI Java de Netscape (IFC) permettait de relier des éléments d’action
Les nouveaux attributs
commandetcommandforaméliorent et remplacentpopovertargetactionetpopovertargetJe suis complètement allergique au fait de programmer avec des chaînes de caractères. Je comprends les avantages pour l’accessibilité, mais je ne suis pas particulièrement enthousiaste à l’idée d’utiliser des ID d’éléments comme une couche supplémentaire de comportement pour les applications web
Cela n’aurait pas dû être implémenté sans l’API complète. Au lieu de 5 commandes environ, on dirait qu’il devrait être possible d’implémenter toutes les fonctionnalités JavaScript via HTML. Cela pourrait représenter des milliers de commandes
Je m’attendais à du command and conquer dans HTML
C’est bien d’améliorer et d’étendre HTML, mais il reste encore beaucoup de chemin à parcourir. L’équipe HTMX a quelques bonnes idées