Saturday, October 11, 2014

WAI-ARIA support for AutoComplete widget

In this post I would like to discuss the accessibility for an AutoComplete widget. A typically AutoComplete widget provides suggestions while you type into the field. On my current work I implemented an JSF component on basis of Twitter's Typeahead - a flexible JavaScript library that provides a strong foundation for building robust typeaheads. The Typeahead widget has a solid specification in form of pseudocode that details how the UI reacts to events. The Typeahed can show a hint in the corresponsing input field, like the google's search field shows it, highlight matches, deal with custom datasets and precompiled template. Furthermore, the Bloodhound suggestion engine offers prefetching, intelligent caching, fast lookups, and backfilling with remote data.


Despite many features, one big shortcoming of the Typeahead is an insufficient WAI-ARIA support (I would say it was completely missing until now). An AutoComplete widget should be designed to be accessible out of the box to users of screen readers and other assistive tools. I have decided to add a fully WAI-ARIA support, done this taks and sent my pull request to the GitHub. Below is the new "WAI-ARIA aware" markup with an explanaition (not relevant HTML attributes are omitted).
<input class="typeahead tt-hint" aria-hidden="true">

<input class="typeahead tt-input" role="combobox"
    aria-autocomplete="list/both"
    aria-owns="someUniqueID"
    aria-activedescendant="set dynamically to someUniqueID-1, etc."
    aria-expanded="false/true">
  
<span id="someUniqueID" class="tt-dropdown-menu" role="listbox">
    <div class="tt-dataset-somename" role="presentation">
        ...
        <span class="tt-suggestions" role="presentation">
            <div id="someUniqueID-1" class="tt-suggestion" role="option">
                ... single suggestion ...
            </div>
            ...
        </span>
        ...
    </div>
</span>

<span class="tt-status" role="status" aria-live="polite" style="border:0 none; clip:rect(0, 0, 0, 0); height:1px;
      width:1px; margin:-1px; overflow:hidden; padding:0; position:absolute;">
      ... HTML string or a precompiled template ...
</span>
The first input field with the class tt-hint simulates a visual hint (s. the picture above). The hint completes the input query to the matched suggestion visually. The query can be completed to the suggestion (hint) by pressing either right arrow or tab key. The hint is not relevant for the screen readers, hence we can apply the aria-hidden="true" to that field. The hint is ignored by screen readers then. Why is it not important? Because we will force reading the matched suggestion more intelligent by the "status" area with aria-live="polite" (will be explained below).

The next input field is the main element where the user inputs query. It should have a role="combobox". This is a recommended role for an AutoComplete. See the official WAI-ARIA docu for more details. In fact, the docu also shows a rough markup structure of an AutoComplete!

The main input field should have various ARIA states and properties. aria-autocomplete="list" indicates that the input provides autocomplete suggestions in the form of a list as the user types. aria-autocomplete="both" indicates that suggestions are also provided by a hint (additional to a list). The property aria-owns indicates that there is a parent / child relationship between the input field and the list with suggestions. This property should be always set when the DOM hierarchy cannot be used to represent the relationship. Otherwise, screen readers will get a problem to find a list with suggestions. In our case, it points to the ID of the list. The most interesting property is aria-activedescendant. A sightless user navigates through the list via arrow keys. The property aria-activedescendant propagates changes in focus to assistive technology - it is adjusted to reflect the ID attribute of the current child element which has been navigated to. In the picture above, the item "Lawrence of Arabia" is selected (highlighted). aria-activedescendant is set to the ID of this item and screen readers read to blind users "Lawrence of Arabia". Note: the focus stays on the input field, so that you can still edit the input value. I suggest to read more about this property in the Google's Introduction to Web Accessibility.


The property aria-expanded indicates whether the list with suggestions is expanded (true) or collapsed (false). This property will be updated automatically when the list's state changes.

The list with suggestions itself should have a role "listbox". That means, the widget allows the user to select one or more items from a list of choices. role="option" should be applied to individual result item nodes within the list. There is an interesting article "Use "listbox" and "option" roles when constructing AutoComplete lists", which I suggest to read. Not important for the screen readers parts should be marked with role="presentation". This role says "My markup is only for non sightless users". You probably ask, what is about the role="application"? Is it important for us? Not really. I skipped it after reading "Not All ARIA Widgets Deserve role="application"".

The last element in the markup is a span with the role="status" and the property aria-live="polite". What it is good for? You can spice up your widget by letting the user know that autocomplete results are available via a text that gets automatically spoken. The text to be spoken should be added by the widget to an element that is moved outside the viewport. This is the mentioned span element with applied styles. The styles are exactly the same as the jQuery CSS class ui-helper-hidden-accessible, which hides content visually, but leaves it available to assistive technologies. The property aria-live="polite" on the span element means – updates within this element should be announced at the next graceful interval, such as when the user stops typing. Generally, The aria-live property indicates a section within the content that is live and the verbosity in which changes shall be announced. I defined the spoken text for the AutoComplete in my project as an JavaScript template compiled by Handlebars (any other templating engine such as Hogan can be used too).
Handlebars.compile(
    '{{#unless isEmpty}}{{count}} suggestions available.' +
    '{{#if withHint}}Top suggestion {{hint}} can be chosen by right arrow or tab key.' +
    '{{/if}}{{/unless}}')
When user stops to type and suggestions are shown, a screen reader reads the count of available suggestions and the top suggestion. Really nice.

Last but not least is the testing. If you do not already have a screen reader installed, install the Google Chrome extensions ChromeVox and Accessibility Developer Tools. These are good tools for the development. Please watch a short ChromeVox demo and a demo for Accessibility Developer Tools too. Alternative, you can also try a free standalone screen reader NVDA. Simple give the tools a try.

Thursday, September 18, 2014

Brand new JSF components in PrimeFaces Extensions

The PrimeFaces Extensions team is glad to announce several new components for the upcoming 3.0.0 main release. Our new committer Francesco Strazzullo gave a "Turbo Boost" for the project and brought at least 6 JSF components which have been successfully intergrated! The current development state is deployet on OpenShift - please look the showcase Below is a short overview about added components with screenshots.

Analog Clock. This is a component similar to digital PrimeFaces Clock, but as an analog variant, enhanced with advanced settings.


Countdown. It simulates a countdown and fires an JSF listener after an customizable interval. You can start, stop and pause the countdown.


DocumentViewer. This is JSF wrapper of Mozilla Foundation project PDF.js - a full HTML PDF reader.


GChart. This is a JSF wrapper of Google Charts API. It's the same chart library used by Google Analytics and other Google services. Please look at Organizational Chart and Geo Chart.


A small note from me: charts can be built completely by model in Java. There is only one GChartModel which allows to add any options you want programmatically. I have used the same approach for my Chart library based on Flotcharts (thinking right now about adding it to the PF Extensions). There is only one generic model with generic setters to set options (options are serialized to JSON then). Advantage: you can export a chart on the server-side, e.g. with PhantomJS. This is a different approach to PrimeFaces' charts where each chart type has a separate model class and hard-coded fix methods for options settings.

Gravatar. This is a component for Gravatar services.


Knob. This is a nice theme-aware component to insert numeric values in a range. It has many settings for visual customization, AJAX listener and more.


Last but not least: we plan to deploy current SNAPSHOTs on the OpenShift in the future. More new components are coming soon. I intend to bring a component called pe:typeahead to the 3.0.0 too. It is based on Twitter's Typeahed. In the next post, I will explain how I have added an excellent WAI ARIA support to this great autocomplete widget. Stay tuned!

Friday, August 22, 2014

PrimeFaces Extensions 2.1.0 released

Today, we released the PrimeFaces Extensions 2.1.0. This is a maintenance release with many fixed issues and some new features for the existing components. The full issue list is on the GitHub.

As usually, you will find all infos on the homepage. The release is available in the Maven central repo.

Good news:
  • New snapshots and releases seem to be uploaded perodically to the public Sonatype's repository again, so that everybody can download them from there.
  • We will have new "sexy" components in the next main release because we could win a new commiter for us. His name is Francesco Strazzullo and he is a creator of StrazzFaces. The plan is to adopt his components for the PrimeFaces Extensions. Furthermore, I plan to bring cool components too (although I have less free time due to my current work).
  • PrimeFaces Extensions will go PRO! Thanks to Cagatay for this idea and his support. Please follow his announcement soon.

Have fun!

Sunday, July 13, 2014

How to get JSON response from JSF?

Many JavaScript widgets expect data and options in JSON format. Nowadays, it is really easy to choose a cool widget and wrap it in a composite component. But the first question is how to send an AJAX request and to recieve a response in a proper JSON format. This question is often raised by JSF users. All what you need is a XHTML facelet like this one
<f:view encoding="UTF-8" contentType="text/html"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core">
  <h:outputText value="#{stationView.getClosestStations(param.longitude, param.latitude)}" escape="false"/>
</f:view>
Please consider the contentType="text/html" (application/json will not work here) and escape="false" in the h:outputText. The method getClosestStations() in the bean StationView produces an JSON output for a list of special Java objects. I advise to use the Gson library in order to serialize any Java object to JSON. Short example:
String[] strings = {"abc", "def", "ghi"};
Gson gson = new Gson();
gson.toJson(strings);  ==> prints ["abc", "def", "ghi"]
The XHTML file above is located under the web context. Say, under the path /rest/stations.xhtml. Ajax call in your JavaScript code should look like this one:
$.ajax({
    url: requestContextPath + '/rest/stations.xhtml',
    type: "GET",
    data: {
        "longitude": x,
        "latitude": y
    },
    dataType: "json",
    success: function (data) {
        $.each(data, function (i, station) {
            ...
        });
    },
    error: function () {
        ...
    }
});
Please refer the jQuery docu for more information regarding $.ajax. Note: if you omit dataType: "json", you have to parse the JSON string manually.
success: function (data) {
    $.each($.parseJSON(data), function (i, station) {
        ...
    });
}
The response is a pure JSON string (no HTML tags) like this one:
[{"latitude":46.947045,"longitude":7.443922,"distanz":110,"name":"Bern, Bundesplatz"},{....},...]
Need more examples for JSON response in JSF? In one of my next post I will probably explain how to implement a cool autocomplete component without writing too much code.

Monday, July 7, 2014

How to implement a custom password strength indicator in JSF

Verifying password strength using JavaScript is a common task. In this post, I will show how to add a password strength indicator to an JSF based web application. The password component in PrimeFaces already has a feedback indicator of the password strength, but it has two major shortcomings:
  • Feedback indicator is not responsive (fix width, not mobile friendly, etc.)
  • Rules for the password strength verification are hard coded in JavaScript. No customization is possible.
What we need is a good looking, easy customizable and responsive password strength indicator / meter. Fortunately, PrimeFaces has another component - progress bar which we can use for our purpose. This is not a misusage. The end result is actually impressive.

Let's start with XHTML. First, define a quite normal passwort field.
 
<p:password id="passwort" value="#{mybean.password}" label="Password" required="true" autocomplete="off"/>
 
Second, define a progress bar with displayOnly="true" and some messages for the passwort strength (weak, medium, strong).
<div style="white-space:nowrap;">
    <h:outputText value="Password strength "/>
    <h:outputText id="pwdWeak" value="weak" style="display:none" styleClass="bold weakMsg"/>
    <h:outputText id="pwdMedium" value="medium" style="display:none" styleClass="bold mediumMsg"/>
    <h:outputText id="pwdStrong" value="strong" style="display:none" styleClass="bold strongMsg"/>
</div>
<p:progressBar id="pwdStrength" value="0" styleClass="pwdStrength" displayOnly="true"/>
Let's go to the JavaScript part. We need a script block (placed somewhere after the p:progressBar) where we intend to invoke a custom JS function setupPasswordStrength().
<script type="text/javascript">
    $(document).ready(function () {
        setupPasswordStrength("passwort", "pwdStrength");
    });
</script>
The JS function has two arguments: an Id of the password field and an Id of the progress bar. In the function, we will register a callback for the namespaced keyup event. In the callback, we will check the current input value by means of reg. expressions. We would like to take the following rules (rules are up to you):
  • Password length is less than 8 characters or doesn't contain at least one digit ==> weak password
  • Password length is equal or greater than 8 characters, contains at least one digit, but doesn't have at least one lower and one upper case letter OR one special char: ==> medium password
  • Password length is equal or greater than 8 characters, contains at least one digit AND has at least one lower and one upper case letter OR one special char: ==> strong password
These are good rules I have often seen across the internet. Let's me show the JS function.
function setupPasswordStrength(pwdid, pbarid) {
    // reg. exp. for a weak password
    var weak = XRegExp("^(?=.*\\d{1,}).{8,}$");
    // reg. exp. for a strong password
    var strong = XRegExp("^(?=.*[a-z])(?=.*[A-Z]).+|(?=.*[!,%,&,@,#,$,^,*,?,_,~,\\-]).+$");

    var $this = $("#" + pwdid);
    var pbar = $("#" + pbarid).find(".ui-progressbar-value");

    // visualize on keyup
    $this.off('keyup.' + pwdid).on('keyup.' + pwdid, function(e) {
        visualizePasswordStrength($(this).val(), pbar, weak, strong);
    });

    // fix chrome issue with autofill fields
    setTimeout(function(){$this.triggerHandler('keyup.' + pwdid);}, 150);
}

function visualizePasswordStrength(pwd, pbar, weak, strong) {
    var pparent = pbar.parent().parent().parent();
    var weakMsg = pparent.find(".weakMsg");
    var mediumMsg = pparent.find(".mediumMsg");
    var strongMsg = pparent.find(".strongMsg");

    if (pwd == null || pwd.length < 1) {
        pbar.removeClass("weak medium strong");
        weakMsg.hide();
        mediumMsg.hide();
        strongMsg.hide();
        return;
    }

    if (!weak.test(pwd)) {
        // weak
        pbar.removeClass("medium strong").addClass("weak");
        mediumMsg.hide();
        strongMsg.hide();
        weakMsg.show();
        return;
    }

    if (!strong.test(pwd)) {
        // medium
        pbar.removeClass("weak strong").addClass("medium");
        weakMsg.hide();
        strongMsg.hide();
        mediumMsg.show();
        return;
    }

    // strong
    pbar.removeClass("weak medium").addClass("strong");
    weakMsg.hide();
    mediumMsg.hide();
    strongMsg.show();
}
In the function visualizePasswordStrength(), we remove and add style classes to the progress bar dependent on the password strength (when user is typing his password). They are
.weak {
    background-color: #F88E7D !important;
    border: 1px solid #F95D24 !important;
    width: 33.33% !important;
}

.medium {
    background-color: #FEE379 !important;
    border: 1px solid #EDB605 !important;
    width: 66.66% !important;
}

.strong {
    background-color: #81FF6C !important;
    border: 1px solid #05E428 !important;
    width: 101% !important;
}
The weak indicator reserves one-third of the progress bar's length. The medium and strong indicators reserve respectively two-thirds and all available space. The styling of the progress bar looks as follows:
.pwdStaerke.ui-progressbar {
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    margin-top: 8px;
    height: 18px !important;
    border: solid 1px #c2c2c2 !important;
}

.pwdStaerke.ui-progressbar .ui-progressbar-value {
    display: block !important;
    margin-left: -2px !important;
    -moz-border-radius: 6px !important;
    -webkit-border-radius: 6px !important;
    border-radius: 6px !important;
}