L'élément HTML5 progress

Auteur
Nibau Rui
Date
()
Catégories
Web
Tags
, , , ,

Petite introduction à l'utilisation de l'élément progress, apparu dans les recommendations HTML 5.

Introduction

L'élément progress est un nouvel élément qui permet de créer un objet plutôt courant dans les librairies graphiques d'applications : représenter la progression d'un traitement, d'une tâche, d'une action. Il se traduit simplement par une barre verticale ou horizontale qui se « remplit » au cours du temps et dont l'apparence varit en fonction du navigateur web et du système d'exploitation.

<progress value="0.7">70%</progress>
Code HTML pour la création d'un élément progress.
70%
Rendu d'un élément progress par défaut, positionné à 70%.

Si vous affichez cette page avec Internet Explorer, Safari, Chrome < 6, Firefox < 6 ou Opera < 11, vous ne verrez pas grand chose, sans doute uniquement le texte contenu dans l'élément. Ces « anciens » navigateurs ne savent pas comment rendre un élément HTML portant le nom « progress ». Nous allons voir comment apporter un minimum de support avec un peu de CSS et du javascript.

Le principe est simple : la mise en forme de l'élément se fera à travers la classe « progress » ; celle-ci ne sera appliquée que si le navigateur ne gère pas nativement l'élément ; enfin, une fonction générique permettra de mettre à jour la valeur de progression. Par ailleurs :

Il s'agit ici avant tout de comprendre et d'implémenter les bases du fonctionnement de l'élément.

Appliquer les traitements

La première étape consiste donc à déterminer si le navigateur gère nativement les éléments progress :

/**
 *  Le navigateur gère-t-il nativement progress ?
 *  @type Boolean
 */
var supportsProgress = ('value' in document.createElement('progress')) ? true : false;
Test de vérification du support natif de l'élément progress.

Si ce n'est pas le cas, nous allons chercher tous les éléments progress de la page pour les traiter convenablement avec une fonction dédiée, initProgress :

if (!supportsProgress) {
    var els = document.body.getElementsByTagName('progress'),
        i, n = els.length;
    for (i = 0; i < n; i++) {
        initProgress(els[i]);
    }
}
Lancement du traitement des éléments progress si nécessaire.

Initialiser les éléments

La fonction d'initialisation va effectuer plusieurs traitements :

/**
 *  Méthode d'initialisation des éléments progress
 *  @param {HTMLProgressElement} el Elément progress à initialiser
 */
var initProgress = function (el) {
    var
        // Element enfant à ajouter
        span = document.createElement('span');
        // contenu textuel de l'élément
        textNode = el.firstChild || document.createTextNode(' '),
        // Valeur de progression
        value = el.getAttribute('value') || 0,
        // valeur maximale
        maxi = el.getAttribute('max') || 1;
    // append markup
    span.appendChild(textNode);
    el.appendChild(span);                       
    // define className
    el.className = el.className + ' progress';
    // init values
    updateProgress(el, parseFloat(value, 10), parseFloat(maxi, 10));
};
Initialisation d'un élément progress.

Comme préciser plus haut, il s'agit ici d'une version simplifiée de ce qu'il faudrait faire. Nous devrions par exemple vérifier que l'élément ne contienne pas déjà un élément enfant, et utiliser celui-ci au lieu d'en créer un artificiellement.

Définir la valeur de progression

La modification de la valeur de progression est assurer par la fonction updateProgress, en faisant varier la taille de l'élément enfant que la fonction initProgress à préalablement inséré :

/**
 *  Mettre à jour la valeur d'un élément progress.
 *  @param {HTMLProgressElement} el Elément progress à initialiser.
 *  @param {Number} value Nouvelle valeur (doit être supréieure à -1).
 *  @param {Number} [maxi] Si la valeur maximale est aussi à modifier (doit être positive).
 */
var updateProgress = function (el, value, maxi) {
    if (maxi && maxi !== el.max) {
        el.max = maxi;
        el.setAttribute('max', maxi);
    }
    if (value < 0) {
        value = 0;
    } else if (value > el.max) {
        value = el.max;
    }
    if (value !== el.value) {
        el.value = value;
        if (!supportsProgress) {
            var w = (el.clientWidth * (el.value/el.max)) + 'px';
            if (value === null) {
                w = 0;
                el.removeAttribute('value');
            } else {
                el.setAttribute('value', value);
            }
            el.firstChild.style.width = w;
        }
    }
};
Mise à jour de la valeur de progression de l'élément.

Nous utilisons le test supportsProgress pour pouvoir utiliser la même fonction à la fois avec les navigateurs gérant nativement progress et ceux ne le gérant pas.

Là aussi, le traitement est simplifié : pour un élément progress vertical, les grandeurs à récupérer et à calculer ne seront pas les mêmes.

Mise en forme

Il ne nous reste plus qu'à définir les règles css pour assurer le rendu. Ce rendu variant grandement selon les navigateurs et le système d'exploitation, nous appliquerons un look dés plus simple.

.progress {
    /* flow content */
    display: inline-block;
    /* size */
    height: 1em;
    width: 10em;
    /* typo */
    font-size: 1em;
    line-height: 1;
    vertical-align: middle;
    /* box */
    padding: 0;
    margin: 0;
    /* borders */
    border-width: 1px;
    border-style: solid;
    -webkit-border-radius: 0.5em;
       -moz-border-radius: 0.5em;
            border-radius: 0.5em;
    /* colors */
    background: #E6E6E6;
    border-color: #666;
}
.progress > span {
    /* flow content */
    display: inline-block;
    /* size */
    height: 1em;
    /* borders */
    -webkit-border-radius: 0.5em;
       -moz-border-radius: 0.5em;
            border-radius: 0.5em;
    /* colors */
    background: #999;
    color: #999;
}
Règles CSS de base pour un élément progress.

Exemple d'utilisation

<p>
    <progress id="myProgress" value="0.2">20%</progress>
    <button id="update">Mise à jour</button>
</p>
Utilisation d'un élément progress avec un bouton de mise à jour.
// code javascript précédent

document.getElementById('update').addEventlistener('click', function (e) {
    var el = document.getElementById('myProgress');
    updateProgress(el, el.value + 0.2);
}, false);    
Ecoute du bouton pour mettre à jour la valeur de l'élément progress.

20%

Rendu de l'exemple.

Ressources et références

HICKSON, Ian. HTML 5. W3C, . 4.10.16 The progress element

HICKSON, Ian. HTML 5. W3C, . 10.4.13 The progress element

COLLECTIF. progress. Mozilla Developer Network,