Lorsqu'une page Web est chargée, les lecteurs d'écran (comme celui fourni avec OS X ou JAWS sous Windows) lisent le contenu de la page entière. Mais dites que votre page est dynamique, et que les utilisateurs effectuant une action, le nouveau contenu est ajouté à la page. Par souci de simplicité, disons que vous affichez un message quelque part dans un <span>
. Comment pouvez-vous obtenir le lecteur d'écran pour lire ce nouveau message?Obtention du lecteur d'écran pour lire le nouveau contenu ajouté avec JavaScript
Répondre
La spécification WAI-ARIA définit plusieurs façons par lesquelles les lecteurs d'écran peuvent "regarder" un élément DOM. La meilleure méthode prise en charge est l'attribut aria-live
. Il a les modes off
, polite
, assertive
et rude
. Plus le degré d'assertivité est élevé, plus il est probable que l'on interrompt ce qui est actuellement prononcé par le lecteur d'écran.
Ce qui suit a été testé avec NVDA sous Firefox 3 et Firefox 4.0b9:
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery-1.4.2.min.js"></script>
</head>
<body>
<button onclick="$('#statusbar').html(new Date().toString())">Update</button>
<div id="statusbar" aria-live="assertive"></div>
</body>
La même chose peut être accomplished avec WAI-ARIA rolesrole="status"
et role="alert"
. J'ai eu des rapports d'incompatibilité, mais je n'ai pas été en mesure de les reproduire.
<div id="statusbar" role="status">...</div>
Juste pour être clair, les seules valeurs valides pour 'aria-live' sont' off', 'polite' et' assertive'. Si quelqu'un est curieux de connaître les valeurs par défaut des rôles associés aux régions actives ou même s'il veut simplement voir ce qu'ils font, j'ai écrit un petit terrain de jeu qui montre les régions actives en action: http://schne324.github.io/live-region-playground/ – harris
Cela ne fonctionne pas pour moi dans Mac avec Firefox 41.0.2 avez-vous la moindre idée? Fonctionne très bien avec Safari et Chrome –
Juste pour ajouter aux valeurs valides pour aria-live, il y a en réalité 4 valeurs. ** off **, ** poli **, ** assertif **, et ** impoli ** comme indiqué dans les documents ici: https://msdn.microsoft.com/en-us/library/windows/apps /hh465711.aspx –
Voici un exemple du monde réel adapté - ce balisage haut niveau a déjà été converti à partir d'une liste non ordonnée avec des liens dans un menu de sélection via JS. Le code réel est beaucoup plus complexe et ne peut évidemment pas être inclus dans son intégralité, alors rappelez-vous que cela devra être repensé pour une utilisation en production. Pour que le menu de sélection soit accessible au clavier, nous avons enregistré les événements onchange & et déclenché l'appel AJAX lorsque les utilisateurs sont sortis de la liste (attention aux différences de synchronisation de l'événement onchange dans le navigateur). C'était un PITA sérieux à rendre accessible, mais c'est possible.
// HTML
<!-- select element with content URL -->
<label for="select_element">State</label>
<select id="select_element">
<option value="#URL_TO_CONTENT_PAGE#" rel="alabama">Alabama</option>
</select>
<p id="loading_element">Content Loading</p>
<!-- AJAX content loads into this container -->
<div id="results_container"></div>
// JAVASCRIPT (abstracted from a Prototype class, DO NOT use as-is)
var selectMenu = $('select_element');
var loadingElement = $('loading_element');
var resultsContainer = $('results_container');
// listen for keypress event (omitted other listeners and support test logic)
this.selectMenu.addEventListener('keypress', this.__keyPressDetector, false);
/* event callbacks */
// Keypress listener
__keyPressDetector:function(e){
// if we are arrowing through the select, enable the loading element
if(e.keyCode === 40 || e.keyCode === 38){
if(e.target.id === 'select_element'){
this.loadingElement.setAttribute('tabIndex','0');
}
}
// if we tab off of the select, send focus to the loading element
// while it is fetching data
else if(e.keyCode === 9){
if(targ.id === 'select_element' && targ.options[targ.selectedIndex].value !== ''){
this.__changeStateDetector(e);
this.loadingElement.focus();
}
}
}
// content changer (also used for clicks)
__changeStateDetector:function(e){
// only execute if there is a state change
if(this.selectedState !== e.target.options[e.target.selectedIndex].rel){
// get state name and file path
var stateName = e.target.options[e.target.selectedIndex].rel;
var stateFile = e.target.options[e.target.selectedIndex].value;
// get the state file
this.getStateFile(stateFile);
this.selectedState = stateName;
}
}
getStateFile:function(stateFile){
new Ajax.Request(stateFile, {
method: 'get',
onSuccess:function(transport){
// insert markup into container
var markup = transport.responseText;
// NOTE: select which part of the fetched page you want to insert,
// this code was written to grab the whole page and sort later
this.resultsContainer.update(markup);
var timeout = setTimeout(function(){
// focus on new content
this.resultsContainer.focus();
}.bind(this), 150);
}.bind(this)
});
}
Les lecteurs d'écran lisent les champs de formulaire et les liens lorsqu'ils obtiennent le focus. Une possibilité est donc de mettre une ancre autour du texte et de mettre l'accent sur cette ancre. Avec CSS, vous pouvez obtenir le lien pour ne pas montrer comme un lien pour les utilisateurs qui regardent la page. Mais cette méthode n'est pas très satisfaisante car les utilisateurs de lecteurs d'écran seront faussement amenés à croire qu'il s'agit d'un lien. – avernet
Ajouter tabindex à n'importe quel élément et il deviendra lisible, je crois (tabindex = -1 rend scriptable mais pas tabable). J'envoie souvent par programmation un focus sur un nouveau contenu après avoir cliqué sur un lien (comme un sélecteur d'onglets ou un accordéon) - mais ce n'est pas forcément un lien à focaliser. Lire sur tabindex. –