Injecteur de Composants 0.1*
L' injecteur de Composants ajoute une étape avant la fin du chargement du DOM d'un document durant laquelle des éléments seront supprimés ou transformés selon un ensemble de règles déclarées dans des fichiers DSS (Design System Sheets). Cela permet de distinguer l'état initial du DOM de son état développé (ou état de rendu), et offre une meilleure séparation des préocupation en ajoutant une couche déclarative dédiée au design.
En effet, un document HTML NE DEVRAIT PAS être écrit pour satisfaire un design particulier, mais pour structurer des données et exposer des éléments selon des roles précis (POSH, Plain Old Semantic HTML). C'est à la couche design de fournir au navigateur des règles de transformations sur ces éléments pour satisfaire des éxigeances visuels et/ou améliorer l'expérience utilisateur.
Chaque Design System déployé par l'injecteur de composants et non obstrusif par nature : S'il est retiré, la version POSH initial du document offrira une expérience utilisateur minimale et un aspect visuel présumés suffisant.
Design System Sheets
Chaque DSS comporte un ensemble de Design Request ciblant des éléments par des selecteurs pour les transformer ou les supprimer. Les transformations peuvent porter sur un ou plusierus de ces aspects:
- le shadow dom de l'élément,
- son type (le tagName),
- ses attributs,
Lorsqu'une Design Request est préfixée du mot clef "LIVE", cela signifie que la règle s'appliquera automatiquement à tout nouvel élément correspondant au selecteur donné.
TODO : priorités, stratégie de rendue et sensitivity (= le mot clef OBSERVE), anatomie d'une Design Request, moteur de template Handlebars avec liste des helpersSet unobstrusive custom elements :
Dans cet exemple, tout les input type range seront remplacés par des custom elements my-input-range, auquels seront oté l'attribut type.
Les élements input perdent d'abord leur role et leur comportement par défaut.
Le behavior "slider" restaure le role et le comportement.
Le mot clef "LIVE" indique que la transformation a lieu à chaque fois que l'on ajoute un élément de type input range dans le DOM (ex par javascript).
"OBSERVE" nous indique ici que l'élément sera redessiné à chaque fois que l'un de ses attributs ou son contenu (noeuds enfants) seront modifiés.
"IF" nous indique à quelle(s) condition(s) la transformation aura lieu.
LIVE TRANSFORM(input[type="range"]) TO slider(my-input-range) [-type] REVERSE [+type="{{original.type}}"] OBSERVE inner, attr, registeredCustomElements.my-input-range IF and(support.javascript registeredCustomElements.my-input-range);
Wrapping :
Ici, toute les div qui ont pour attribut video-bg auront leur shadowdom automatiquement attribué tel que défini par le template ci dessous.
Celui ci sera redessiné chaque fois que l'attribut video-bg sera modifié. S'il cet attribut est supprimé, la div redeviendra "normale".
LIVE TRANSFORM(div[video-bg]) OBSERVE attr.video-bg<#><!--shadow dom template--> <style> ... style to put video on the background </style> <video id="bg"> <source src="{{attr.video-bg}}" type="video/mp4" /> </video> <div id="wrap"> <slot></slot> </div> <#/>;
Web Components (no custom elements, no JS)
Les "injected behaviors" permettent de définir le comportement de l'élément.
Ici, les select class thumb sont transformés en "select-" (notez le "-"). Cependant, aucun custom element "select-" n'a été déclaré. La nature de l'élément est désormais "HTMLElement". Ce qui signifie qu'il a perdu sa sémantique et son comportement naturels.
Cependant, on peut lui assigner un shadowdom (ce que fait le template), un role, et un comportement (ce que fait le "injected behavior"). Si l'élément possède l'attribut name, il sera interprêté comme un élément de formulaire et fonctionnera de la même manière qu'un champ select natif.
Dans notre cas, la présence de l'attribut autofocus sur un élément du shadowdom indique que notre élément héritera de la valeur de #combo1 (cf dde-unit aria), Puisque #combo1 a déjà un role, le select parent n'en aura pas besion.
TODO: gestion du labelLIVE TRANSFORM(select.thumbs) TO combobox(select-) [-class.thumb +class.transformed-select] REVERSE [+class.thumb -class.transformed-select] OBSERVE inner, attr<#><!--shadow dom template--> <div class="combo js-select"> <div aria-controls="listbox1" aria-expanded="false" aria-haspopup="listbox aria-labelledby="combo1-label" id="combo1" class="combo-input" role="combobox" tabindex="0" aria-activedescendant="" autofocus>Banana</div> <div class="combo-menu" role="listbox" id="listbox1" aria-labelledby="combo1-label" tabindex="-1"> {{#each (children)}} {{#if or(eq(nodeType 'HTMLElement') eq(tagName 'option'))}} <div role="option" aria-selected="{{#if selected}}true{{#else}}false{{/if}}">{{{inner}}}</div> {{/if}} {{#if or(eq(nodeType 'HTMLElement') eq(tagName 'optgroup'))}} <div role="group" label="{{textContent}}"> {{#each (children ">option")}} <div role="option" aria-selected="{{#if selected}}true{{#else}}false{{/if}}"> {{#if CStyle.--thumb}} <img src="{{CStyle.--thumb}}" alt="{{attr.value}}"> <!-- from computed style "--thmub" custom property --> {{else if attr.data-img}} <img src="{{attr.data-img}}" alt="{{attr.value}}"> <!-- else, from "data-img" attribute --> {{/if}} {{{inner}}} </div> {{/each}} </div> {{/if}} {{#each}} </div> </div> <#/>;