HTML5 Web Components

Michel Buffa
Juin 2016

buffa@unice.fr

Web Components: créez vos propres éléments HTML5 (widgets)!

<multitrack src="Bass">
<tr>
    <td class="trackBox" style="height : 75px">
        <progress class="pisteProgress" id="progress0" value="3"
                  max="3" style="width : 75px">
        </progress>
        Bass
        <div style="float : right;">
            <button class="mute" id="mute0" onclick="muteUnmuteTrack(0);"
                    disabled="disabled">
                <span class="glyphicon glyphicon-volume-up"></span>
            </button>
            <button class="solo" id="solo0" onclick="soloNosoloTrack(0);"
                    disabled="disabled">
                <img src="../img/earphones.png">
            </button>
        </div>
        <span id="volspan">
            <input type="range" class="volumeSlider" id="volume0" min="0"
                   max="100" value="100"
                   onchange="setVolumeOfTrackDependingOnSliderValue(0);">
        </span>
    </td>
</tr>
                

Web Components : utilisez les mêmes outils que les développeurs de browsers !

Comment ont-ils créé l'élément <video> ?


Web Components s'appuient sur plusieurs APIs du W3C !

  • Templates: squelettes pour des éléments HTML instanciables,
  • Shadow DOM: ce qui sera public/privé dans vos éléments,
  • Custom Elements : pour créer / enregistrer de nouveaux éléments HTML et les faire reconnaitre par le browser,
  • HTML Imports: pour packager ses composants (CSS, JavaScript, etc.)

Templates

Ce sont des parties de code HTML (incluant scripts et styles) qui peuvent être réutilisés,

Ces parties de code sont inertes (les règles CSS ne seront pas appliquées, le JS non executé, les images non chargées, les vidéos non jouées, etc) until the template is used.

 <template id="mytemplate">
    <img src="" alt="great image">
    <div class="comment"></div>
</template>               
On peut laisser l'attribut src vide ici... nous l'initialiserons plus tard...

Pour utliser un template, on clone son contenu HTML !

var t = document.querySelector('#mytemplate');
// Populate the src at runtime.
t.content.querySelector('img').src = 'http://webcomponents.github.io/img/logo.svg';

var clone = document.importNode(t.content, true);
document.body.appendChild(clone);
JS Bin

Shadow DOM

Fournis des outils d'encapsulation du DOM : cacher ce qui n'est pas nécessaire !

Déja utilisé par les développeurs de browsers pour les éléments <audio> ou <video> etc.

Les trois règles du Shadow DOM:

  1. Avec Shadow DOM les éléments ont un nouveau noeud associé : un shadow root.
  2. Un élément qui a un shadow root associé est appelé un shadow host.
  3. le contenu d'un shadow host n'est pas "rendu" (rendered) en HTML: c'est celui de son shadow root qui est "rendu" à la place.

Shadow DOM: petite démonstration

<button>Hello, world (not rendered)!</button>
<script>
    var host = document.querySelector('button');
    var root = host.createShadowRoot();
    root.textContent = 'the shadow root node is rendered';
</script>
                
Démonstration!

Shadow DOM : encapsuler les styles et les scripts...

On mélanhge templates et shadow DOM ! Démonstration!

<template id="mytemplate">
  <style>
    h1 {color:white; background:red}
    </style>
  <h1>This is a shadowed H1</h1>
</template>
// Instanciate the template
var t = document.querySelector('#mytemplate');
var clone = document.importNode(t.content, true);

// Create a root node under our H1 title
var host = document.querySelector('h1');
var root =  host.createShadowRoot();

// Put template content in the root node
root.appendChild(document.importNode(t.content, true));
                

Shadow DOM: autoriser ou interdire l'application de règles CSS externes, ou faire un CSS reset interne,


Autoriser les règles CSS externes : (Demonstration!)
root.applyAuthorStyles = true; // false by default
CSS reset des styles internes : (Démonstration!)
root.resetStyleInheritance = true; // false by default
                

Styler avec CSS des parties d'un template

<template id="mytemplate">
    <h1 part="heading">This is a shadowed H1</h1>
    <p part="paragraph">Paragraph part</p>
</template>

<body>
    <div id="myWidget"></div>
</body>
#myWidget::part(heading) {
  color:red;
}
                

Insérer du contenu du shadow host dans le shadow DOM (paramétrer un widget/component)


Démonstration!
 <template id="mytemplate">
  <h1 part='heading'>This is a shadowed H1</h1>
  <p part="paragraph">
    <content></content>
  </p>
</template>

<body>
  <H1 class="myWidget">Injected content</h1>
</body>
 

Shadow DOM: injection de contenu plus spécifique à l'aide de l'attribut "select"

La valeur de cet attribut est un sélecteur CSS : Démonstration!

 <template id="mytemplate">
    <h1 part='heading'><content select="#titleToInject"></content></h1>
    <p part="paragraph">
    <content select="#partToInject"></content>
</p>
</template>

<body>
    <div class="myWidget">
        <span id="titleToInject">Title injected</span>
        <span id="partToInject">Paragraph injected</span>
    </div>
</body>
            

Outil pratique : shadow DOM visualizer par E.Bilderman

Custom Elements

Ce sont des éléments HTML custom qui seront reconnus par le navigateur, en plus des éléments standards de HTML5.

Utilisation typique :

  document.registerElement('tag-name', {
    prototype: proto
})
                 

Le nom du nouvel élément doit avoir un tiret (dash, en anglais) !

Le prototype doit hériter de HTMLElement.

Exemple

 // Instanciate the template
var t = document.querySelector('#mytemplate');
var clone = document.importNode(t.content, true);

var widgetProto = Object.create(HTMLElement.prototype);

widgetProto.createdCallback = function() {
  car root = this.createShadowRoot();
  root.appendChild(clone);
}

var Widget = document.registerElement("my-widget", {
  prototype : widgetProto
})
 

Utilisation et démonstration

Le nouvel élément peut dorénavant être inséré dans la page: Démonstration!

<body>
  <my-widget>
     <span id="titleToInject">Title injected</span>
    <span id="partToInject">Paragraph injected</span>
  </my-widget>
</body>
              

Packager ses composants custom : HTML imports!

Utilisation similaire à l'insertion d'un fichier CSS dans une page !

On package ses composans dans une page HTML (qui utilise CSS, JS, etc) et on l'importe !

Aussi simple que :

<head>
<link rel="imports" href="components/myComponents.html">
</head>
<body>
  <my-widget>
     <span id="titleToInject">Title injected</span>
    <span id="partToInject">Paragraph injected</span>
  </my-widget>
</body>