Friday, November 7, 2014

Dynamic aria-live for better accessibility experience

Every web developer working with the web accessibility (WAI ARIA) knows or heard about aria-live. This is an attribute, which indicates a live region - any updatable HTML element - and describes the types of updates the user agents, assistive technologies (screen readers), and user can expect from the live region. The default value of the aria-live is off. That means, updates to the region will not be presented to the user unless the assistive technology is currently focused on that region. The value polite means, assistive technologies should announce updates at the next graceful opportunity, such as at the end of speaking the current sentence or when the user pauses typing. There is also the value assertive, which forces assistive technologies to notify the user immediately. In additional, the aria-relevant attribute can specify if the updates on the live region should only be spoken when the corresponding DOM node is added or removed or both.

Most time you need to set the value once and don't care about it. E.g. markup for error messages can contain aria-live="polite".
<div class="messages" aria-live="polite">
    ... some messages ...
</div>
Every time when the content of the div container with class="messages" is updated, it will be spoken by screen readers. That's good, but sometimes you only would like to notify a sightless user when the new (after update) and old (before update) contents are not equal. Imagine a railway ticket shop where users can choose fare class, number of traveler, book places, etc. The total buy price is permanently updated. We can write
<span aria-live="polite">
    <div id="pricetotal">
        <span class="hiddenOfScreen">Total price </span>
        #{price}
    </div>
</span>
and update the div by AJAX. #{price} is a current price as EL expression calculated on the server-side (coming from the JSF world, but JavaScript templating has similar expressions). Whenever the div gets updated, screen readers speak the total price regardless if the amount was changed or not. A more clever approach sets aria-live dynamically at runtime. If the amount was changed, the aria-live on the div should have the value polite. If the old and new prices are equal, the div should have the value off. The off value prevents speaking by screen readers.

The idea is to save the last updated price in the data-price attribute of the parent element and compare the old and new prices on every AJAX update. In the code snippet below, the div with id="pricetotal" gets updated. The JavaScript block inside is being executed on every update. We read and compare old and new prices and manipulate the aria-live attribute at runtime. Whenever the aria-live is set to polite, screen readers speak "Total price" and the amount.
<span data-price="#{price}">
    <div id="pricetotal">
        <span class="hiddenOfScreen">Total price </span>
        <span class="priceoutput">#{price}</span>
        <script type="text/javascript">
            $(document).ready(function () {
                $pricetotal = $('#pricetotal');
                var oldPrice = $pricetotal.parent().data('price');
                var newPrice = $pricetotal.find('.priceoutput').text();
                if (oldPrice != newPrice) {
                    $pricetotal.attr('aria-live', 'polite');
                    $pricetotal.parent().data('price', newPrice);
                } else {
                    $pricetotal.attr('aria-live', 'off');
                }
            });
        </script>
    </div>
</span>
If prices are not equal, the new price is saved in the data-price to make it available in the next update.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.