The Paciello Group - home page. back to article

Glisser-déposer accessible avec WAI-ARIA

Traduction de Accessible drag and drop using WAI-ARIA par Gez Lemon. Traduit par Cédric Trévisan

Introduction

Cet article est destiné aux personnes voulant créer des applications internet riches avec une fonctionnalité de glisser-déposer et souhaitant la rendre accessible. Aucune connaissance préalable de WAI-ARIA n'est nécessaire, mais il est recommandé de lire mon Introduction à WAI-ARIA avant de commencer cet article. Une connaissance de base du script est nécessaire pour comprendre exactement ce qui se passe dans l'exemple de code, mais cette connaissance n'est pas nécessaire pour comprendre les concepts de base.

Après la lecture de cet article, vous aurez une compréhension de la façon dont on structure les applications, avec des fonctionnalités de glisser-déposer, pour qu'elles soient accessibles.

Le terme de glisser-déposer induit l'utilisation de la souris pour déplacer un objet d'un endroit à un autre. Wikipedia donne la description suivante du glisser-déposer:

Le glisser-déposer (de l'anglais drag-and-drop, aussi appelé cliquer-glisser) est dans un environnement graphique une méthode consistant à utiliser un dispositif de pointage (généralement une souris) pour déplacer d'un endroit à un autre un élément graphique présent sur l'écran d'un micro ordinateur.

Les défis de l'accessibilité du glisser-déposer

Certaines personnes ayant peu de dextérité manuelle ont des difficultés à faire de petits mouvements et rester stable. Pour ce groupe de personnes, la dextérité nécessaire pour bien sélectionner et déplacer un objet en utilisant un dispositif de pointage peut poser des problèmes. Ces utilisateurs peuvent avoir besoin d'un équivalent clavier mis à leur disposition pour leur permettre d'utiliser une telle fonctionnalité d'une manière différente.

Les personnes avec peu d'acuité visuelle sont incapables de percevoir le début et la fin d'une opération de glisser-déposer quand elle est transmise de façon purement visuelle. Pour ces deux groupes, les opérations de glisser-déposer peut être impossible à exécuter, sans une prise en compte de l'accessibilité au cours du processus de conception.

Pour être accessible, toutes les fonctionnalités doivent pouvoir être actionnées par le clavier uniquement. Rendre les opérations de glisser-déposer accessible au clavier est un processus relativement simple, mais il y a quelques défis pour les personnes utilisant des technologies d'assistance, tels que les utilisateurs de loupe et lecteur d'écran. Ces défis sont les suivants:

Heureusement, WAI-ARIA a des propriétés pour surmonter ces problèmes.

Glisser-déposer utilisant WAI-ARIA

WAI-ARIA fourni deux propriétés pour aider à rendre le Glisser-déposer accessible aux utilisateurs de technologies d'assistance:

La propriété aria-grabbed

La propriété aria-grabbed est utilisée pour déterminer si un élément est dans un état de sélection pour une opération de glisser-déposer.

valeurs aria-grabbed
Valeur Description
true Indique que l'élément à été sélectionné pour être déplacé.
false Indique que l'élément n'est pas sélectionné pour être déplacé, mais peut-être disponible pour être déplacé en déclarant la propriété à true.

Si l'élément ne possède pas de propriété aria-grabbed, l'élément ne peut pas être déplacé.

L'attribut aria-grabbed, dans l'exemple suivant, indique que l'élément de liste a été sélectionné pour effectuer une opération de glisser-déposer.

<li aria-grabbed="true">

La propriété aria-dropeffect

La propriété aria-dropeffect est un attribut indiquant le type d'opération qui sera effectué quand un objet sélectionné pour un glisser-déposer sera relâché sur sa destination. Plus d'une valeur peut être fournie dans une liste de valeurs séparées par des espaces. La table suivante liste toutes les valeurs possible pour aria-dropeffect.

Valeurs aria-dropeffect
Valeur Description
copy La source est dupliquée et déposée sur la destination.
move La source est enlevée de sa place initiale et déposée sur la destination.
reference Une référence ou lien vers l'objet source sera créé depuis la destination.
execute Une fonction, supportée par la destination, est exécutée utilisant la source déplacée comme paramètre.
popup Un menu ou dialogue est présenté pour que l'utilisateur puisse choisir l'une des opération supportée (copie, déplacement, lien ou exécution) ou autre fonctionnalité de déplacement.
none La destination n'accepte pas la source.

L'attribut aria-dropeffect, dans l'exemple suivant, indique que le dépôt d'un objet sur cet élément de liste non ordonné sera supprimé de sa place initiale et copié dans cette liste.

<ul aria-dropeffect="move">

Le modèle d'évènement glisser-déposer de HTML 5

Il existe un modèle HTML 5 d'évènement pour les opérations de glisser-déposer. Le modèle est trop complexe pour être couvert en détail dans cet article, mais il couvre les propriétés qui peuvent être utiles pour l'accessibilité.

L'attribut draggable

HTML 5 possède un attribut draggable pour indiquer si un objet peut participer à une opération de glisser-déposer. L'attribut a trois valeurs possibles:

Valeurs draggable
Valeur Description
true L'élément peut être sélectionné pour être déplacé.
false L'élément ne peut pas être sélectionné pour être déplacé.
auto L'élément utilise le comportement par défaut du navigateur.

Le modèle d'évènement glisser-déposer HTML 5 ne possède pas de propriété indiquant si un objet a été sélectionné pour participer à une opération de glisser-déposer, mais il existe un évènement dragstart pour débuter une opération de glisser-déposer.

L'attribut draggable dans l'exemple suivant indique que l'élément de liste peut être sélectionné pour participer à une opération de glisser-déposer.

<li draggable="true">

Cette information peut être complétée par la propriété aria-grabbed de WAI-ARIA pour indiquer non seulement qu'il est déplaçable, mais aussi si il a été sélectionné pour participer à une opération de glisser-déposer.

<li draggable="true"
    aria-grabbed="true">

L'attribut dropEffect

L'objet DataTransfer gère les attributs pour l'opération de glisser-déposer et dont l'attribut dropEffect détermine se qu'il se passe quand l'objet est relâché. L'attribut accepte quatre valeurs.

Valeurs dropEffect
Valeur Description
none L'opération n'est pas permise.
copy La source sera dupliquée et relâchée sur la zone destination.
link La source sera liée.
move La source sera effacée de sa position actuelle et relâchée sur la zone destination.
objEvent.dataTransfer.dropEffect='move';

La valeur de dropEffect doit correspondre à l'une de celles spécifiées par l'attribut effectAllowed de l'objet DataTransfer, qui peuvent être soit none, copy, copyLink, copyMove, link, linkMove, move, all, ou uninitialized.

Un procédé pour le glisser-déposer

J'ai réalisé une application simple pour démontrer le glisser-déposer avec ARIA et esquissé un 'workflow' basé sur les recommandationss WAI-ARIA best practice for drag and drop operations. La démonstration consiste en une liste d'artistes qui peuvent être pris et déposés dans des listes selon différentes rubriques, comme le montre la figure 1.

List of artists with three targets favourites tolerable rejected

Figure 1: Liste d'artistes avec trois possibilités: favourites, tolerable, rejected.

Vous pouvez essayer l'exemple glisser-déposer, en ligne, ou télécharger le code source et l'essayer chez vous.

S'assurer que tous les objets peuvent être atteints à l'aide du clavier

Tous les objets qui peuvent être déplacés doivent être accessibles en utilisant seulement le clavier. Certains éléments sont déjà accessibles à l'aide du clavier uniquement, tels que les éléments standard d'interface et les ancres. Pour les éléments que ne peuvent pas recevoir de focus, vous pouvez utiliser l'attribut tabindex.

Il y a deux valeurs utiles: une valeur 0 de l'attribut tabindex qui organise l'ordre de tabulation du clavier de façon identique à l'ordre d'apparition dans le document source et une valeur négative de l'attribut tabindex qui ne fait pas apparaitre l'élément dans l'ordre de tabulation du clavier, mais lui permet de recevoir un focus programatiquement. L'utilisation d'une valeur négative de l'attribut tabindex est utile si vous ne souhaitez pas encombrer l'ordre de tabulation et la navigation en définissant vos propres combinaisons clavier, par exemple à l'aide des touches Haut et Bas pour naviguer dans un menu.

L'exemple simple utilisé dans cet article ajoute la liste des artistes dans l'ordre de tabulation en positionnant l'attribut tabindex à une valeur 0 pour qu'il puisse être atteint à l'aide de la touche Tab.

objItems[iCounter].tabIndex = 0;

Identifier les objets déplaçables

Les objets pouvant être déplacés doivent avoir la propriété aria-grabbed configurée à false pour indiquer qu'ils sont déplaçables, mais pas actuellement sélectionnés pour.

objItems[iCounter].setAttribute('aria-grabbed', 'false');

Dans la démonstration, les éléments déplaçables ont une propriété CSS cursor pour fournir un indicateur visuel définissant que l'élément est déplaçable en utilisant une souris.

li.draggable
{
    cursor: move;
}

Il est aussi important de s'assurer que l'élément d'interface a bien un indicateur de focus clavier. La démonstration ajoute un attribut class focus quand les objets sources reçoivent le focus. Le code CSS pour l'attribut class focus change la couleur d'arrière plan pour fournir un indicateur visible de focus, de la même façon que les éléments sont mis en évidence quand la souris passe au dessus d'objets déplaçables.

ul li.hover, ul li.focused
{
    background: #fc0;
}

S'assurer que l'utilisateur peut initier l'opération de glisser-déposer à l'aide du clavier

L'utilisateur doit pouvoir sélectionner un ou plusieurs éléments à déplacer. Le DHTML Style Guide suggère les combinaisons clavier à utiliser pour le glisser-déposer. Espace est recommandé pour une sélection unique. Shift + Espace peut être utilisé pour sélectionner des objets contigus, et Control + Espace peut être utilisé pour ajouter des objets non-contigus à la sélection. Pour chaque objet sélectionné, la propriété aria-grabbed doit être configurée à true.

Dans la démonstration, l'attribut aria-grabbed est configuré pour répondre à un événement mousedown ou keydown.

drag.objCurrent.setAttribute('aria-grabbed', 'true');

Identifier les zones destinations de dépôt

Après que les objets sources ai été 'agrippés', les zones valides de dépôt peuvent être identifiées en utilisant la propriété aria-dropeffect configurée à une valeur adéquate. Dans la démonstration, une fonction est appelée, après qu'un élément ait été sélectionné, pour identifier les zones destinations avec aria-dropeffect; elle utilise aussi l'attribut class pour rendre les zones destinations visuellement identifiables.

objList.className = 'highlight';
objList.setAttribute('aria-dropeffect', 'move');

La classe CSS change simplement la couleur d'arrière plan de la liste pour la faire apparaitre évidente visuellement comme zone destination (voir Figure 2):

ul.highlight
{
	background: #c00;
	color: #000;	
}

List targets visually identified with a red background

Figure 2: Les listes destinations visuellement identifiées avec un arrière plan rouge.

S'assurer que l'objet peut être déposé à l'aide du clavier

L'utilisateur doit être capable de naviguer rapidement vers la zone destination et de réaliser l'opération de dépôt. La combinaison clavier recommandée pour déposer un objet sur une zone destination est Control + M. Si le dépôt risque de conduire l'utilisateur à naviguer à travers de nombreux éléments de l'interface pour atteindre la zone destination, il est recommandé qu'un menu contextuel soit fourni, pouvant être activé à l'aide de Shift + F10. Celui-ci contient la liste des zones destinations que l'utilisateur peut sélectionner avec les touches Haut et Bas.

Dans la démonstration, seul un élément peux être déplacé à la fois. On utilise Espace, quand le focus est sur la source, pour indiquer que l'élément est à utiliser pour l'opération de glisser-déposer, il a semblé inutile d'introduire des combinaisons de touches supplémentaires pour activer un menu contextuel, car l'exemple fournit automatiquement le menu contextuel quand un artiste est sélectionné. La première étape est d'indiquer que chaque élément a un menu déroulant.

objItems[iCounter].setAttribute('aria-haspopup', 'true');

Quand un artiste est sélectionné avec le clavier pour être déplacer, une boite de dialogue est automatiquement présentée à l'utilisateur pour sélectionner une zone destination, comme présenté avec la Figure 3.

Popup with two targets to choose from

Figure 3: Boite de dialogue avec deux possibilités de destination.

Si plus d'une opération est possible comme copy ou move, une boite de dialogue, utilisant ARIA, doit être proposée pour que l'utilisateur puisse choisir l'opération qu'il souhaite effectuer. La zone de destination doit utiliser la propriété aria-dropeffect de popup.

objList.setAttribute('aria-dropeffect', 'move');

Si une boite de dialogue est utilisée pour sélectionner la destination, les opérations possibles de dépôt doivent être proposées à l'aide d'un sous menu pour chaque destination; sinon, la boite de dialogue d'opérations doit être affichée sur la destination.

Annuler le glisser-déposer

L'utilisateur doit être en mesure d'annuler l'opération de glisser-déposer. La touche recommandée pour annuler l'opération est Escape. Une fois l'opération annulée, tous les objets déplaçables doivent avoir leur valeur aria-grabbed configuré à false, et toutes les destinations doivent avoir leur propriété aria-dropeffect, soit configuré à none, ou supprimé. Dans la démonstration, les propriétés aria-grabbed sont configurées à false et les propriétés aria-dropeffect sont supprimées.

drag.objCurrent.setAttribute('aria-grabbed', 'false');
objList.removeAttribute('aria-dropeffect');

Le focus clavier doit être repositionné sur le dernier objet pris quand le déplacement fut interrompu.

drag.objCurrent.focus();

Nettoyage après les opérations de glisser-déposer

Lorsque qu'un glisser-déposer est annulé, toutes les destinations ayant une propriété aria-dropeffect doivent, soit avoir leur valeur configuré à none, soit avoir leur propriété complètement supprimé après l'opération. Tous les objets ayant une propriété aria-grabbed doivent êtres configurés à false.

drag.objCurrent.setAttribute('aria-grabbed', 'false');
objList.removeAttribute('aria-dropeffect');

Les objets qui ne sont plus déplaçables et ayant une propriété aria-grabbed, doivent l'enlever du DOM, ou la configurer undefined.

drag.objCurrent.removeAttribute('aria-grabbed');

Support actuel

Mon collègue, Steve Faulkner, a testé la démonstration et fournit des commentaires sur la façon dont il fonctionne avec les navigateurs actuels. Internet Explorer et Firefox fournissent la propriété aria-grabbed. Malheureusement, au moment ou cet article est écrit, aucun lecteur d'écran ne supporte ces propriétés ARIA, bien que NVDA prévoit de les supporter dans le futur. Même si le support n'est pas bon pour le moment, il est recommandé d'utiliser les propriétés WAI-ARIA aria-grabbed et aria-dropeffect; il est simple d'implémenter maintenant afin que tout soit en place quand le support sera finalement disponible.

Une petite note à propos du support CSS

Si vous regardez cet exemple CSS, vous remarquerez que j'ai utilisé des classes pour hover et focus:

ul li.hover, ul li.focused {
  background: #fc0;
}

Ceci du fait que IE 6 et inférieurs ne supportent pas les pseudo-classes :hover et :focus pour un élément qui ne soit pas un lien.

Pour en savoir plus