I recently was asked a question about Ajax frameworks and if how they generate the UI is an accessibility barrier by default, or if some are better than others.
“We are starting to work on a new component using the Yahoo User Interface Library (YUI) data table and saw something that raises a red flag for me. When I viewed the source for our example, I noticed that there is no HTML to look at. Since it is all JavaScript, the HTML is dynamically generated. So I couldn’t verify that heading tags and table column headers were being used.
“The big question, though, is how the screen readers and other AT do their work. Can they function in this environment where everything is dynamically generated or do they require plain old basic HTML with all the heading, label, and column header tags right there for everyone to see?
“Here is a link to an example data table on Yahoo’s site: http://developer.yahoo.com/yui/examples/datatable/dt_basic_clean.html.”
The cryptic and often hard to follow and trace source code can cause alarm bells to go off for those who are used to checking the accessibility of web pages by reviewing the underlying HTML source code. This is still one of the best ways to determine what exactly is being provided to assistive technology (AT) and if there are any errors. With client-side, dynamically generated pages, we often have to go through a lot more steps to verify what the HTML is.
The important thing to remember here is the end result of these JavaScript frameworks—whether it is Yahoo, Google, Dojo or other–is still to produce HTML, as browsers render HTML to the screen to create the visible content. I have included a sample of the HTML from the yahoo example at the bottom of this post. (For one method to get at the HTML of a client-side, dynamically generated page, look at the post “Retrieving HTML from dynamic pages.”)
It comes down to functionality a lot of what the widget is doing to how clean the HTML is versus how much hacking has been done to get presentation and functionality to meet the designer’s intent. So each needs to be tested to make sure it is making an accessible interface. For example, the YUI tree view component
is not 100% accessible, as it is not conveying the hierarchy information to the screen reader, this means the user does not know if Label-1 is a child of Label-0 or if they are both root nodes.
The original concern of the questioner is does AT pick up what the JavaScript is conveying? In the case of JAWS, and most other modern AT, what it does is wait for the browser to execute the JavaScript (JS) and come up with the final HTML in the DOM. It then reads the DOM to present the page.
So the JS isn’t the problem as much as what the end HTML and event handlers are. I mention event handlers as remember interfaces need to be keyboard accessible as well as mouse, so the drag and drop examples could have some issues for accessibility if used on their own– I have not tested Yahoo’s.
ARIA it is a technology being mapped out and promoted by the W3C. This technology is used to provide extra information to AT that regular HTML does not do by itself. It works in conjunction with the user agent (browsers). For example, taking the tree view control, ARIA can be implemented to describe the layout of the tree, and the relationship of the nodes. (See Mozilla’s tree example here.) The browser passes this information to the AT. Currently Firefox 3 has the fullest ARIA implementation. IE 8 will have some although at this time I am not sure how much.
The AT also needs to support this, and that is coming along slowly. JAWS and Window Eyes work best with ARIA in Firefox. JAWS 10 will support the ARIA that IE 8 will have.
Depending on how complex your UI is will depend on if you would benefit from ARIA support and planning it. For example, if you want to use the tree view, I’d recommend ARIA.
There is a framework that has some ARIA support now: Dojo. IBM has contributed ARIA code to this framework. Depending on your UI and accessibility needs Dojo may be worth a look. According to the “Accessible Rich Internet Applications - MDC” page, the Dijit widgets in the Dojo 1.0 widget toolkit support ARIA. My experience with it is its documentation is bad to non-existent so your mileage may vary, however at the minimum its examples should serve as a useful reference of ways to implement ARIA.
—
Sample HTML from the YUI table example as generated by IE
—-
<!–BEGIN SOURCE CODE FOR EXAMPLE =============================== –>
<DIV class=”yui-dt yui-dt-noop” id=basic> <DIV class=yui-dt-hd style=”BACKGROUND-COLOR: #f2f2f2″> <TABLE id=yui-dt0-headtable> <THEAD> <TR id=yui-dt0-hdrow0-a11y> <TH id=yui-dt0-th0-a11y yuiCellIndex=”0″ yuiColumnKey=”id” yuiColumnId=”0″> <DIV><SPAN>id</SPAN></DIV></TH> <TH id=yui-dt0-th1-a11y yuiCellIndex=”1″ yuiColumnKey=”date” yuiColumnId=”1″> <DIV><SPAN>date</SPAN></DIV></TH> <TH id=yui-dt0-th2-a11y yuiCellIndex=”2″ yuiColumnKey=”quantity” yuiColumnId=”2″> <DIV><SPAN>quantity</SPAN></DIV></TH>
<TH id=yui-dt0-th3-a11y yuiCellIndex=”3″ yuiColumnKey=”amount” yuiColumnId=”3″> <DIV><SPAN>amount</SPAN></DIV></TH>
<TH id=yui-dt0-th4-a11y yuiCellIndex=”4″ yuiColumnKey=”title” yuiColumnId=”4″> <DIV><SPAN>title</SPAN></DIV></TH></TR></THEAD></TABLE></DIV>
<DIV class=yui-dt-bd>
<TABLE id=yui-dt0-bodytable>
<CAPTION>DataTable Caption</CAPTION>
<THEAD>
<TR class=”yui-dt-first yui-dt-last” id=yui-dt0-hdrow0> <TH class=”yui-dt-resizeable yui-dt-sortable yui-dt-first” id=yui-dt0-th0 yuiCellIndex=”0″ yuiColumnKey=”id” yuiColumnId=”0″> <DIV class=”yui-dt-col-id yui-dt-col-0 yui-dt-liner” id=yui-dt0-th0-liner><SPAN class=yui-dt-label><A class=yui-dt-sortable title=”Click to sort ascending” href=”http://developer.yahoo.com/yui/examples/datatable/yui-dt0-sort0-ascending”>id</A></SPAN>
<DIV class=yui-dt-resizer id=yui-dt0-colresizer0></DIV></DIV></TH>
<TH class=”yui-dt-resizeable yui-dt-sortable” id=yui-dt0-th1 yuiCellIndex=”1″ yuiColumnKey=”date” yuiColumnId=”1″> <DIV class=”yui-dt-col-date yui-dt-col-1 yui-dt-liner” id=yui-dt0-th1-liner><SPAN class=yui-dt-label><A class=yui-dt-sortable title=”Click to sort descending” href=”http://developer.yahoo.com/yui/examples/datatable/yui-dt0-sort1-descending”>date</A></SPAN>
<DIV class=yui-dt-resizer id=yui-dt0-colresizer1></DIV></DIV></TH>
<TH class=”yui-dt-resizeable yui-dt-sortable” id=yui-dt0-th2 yuiCellIndex=”2″ yuiColumnKey=”quantity” yuiColumnId=”2″> <DIV class=”yui-dt-col-quantity yui-dt-col-2 yui-dt-liner” id=yui-dt0-th2-liner><SPAN class=yui-dt-label><A class=yui-dt-sortable title=”Click to sort ascending” href=”http://developer.yahoo.com/yui/examples/datatable/yui-dt0-sort2-ascending”>quantity</A></SPAN>
<DIV class=yui-dt-resizer id=yui-dt0-colresizer2></DIV></DIV></TH>
<TH class=”yui-dt-resizeable yui-dt-sortable” id=yui-dt0-th3 yuiCellIndex=”3″ yuiColumnKey=”amount” yuiColumnId=”3″> <DIV class=”yui-dt-col-amount yui-dt-col-3 yui-dt-liner” id=yui-dt0-th3-liner><SPAN class=yui-dt-label><A class=yui-dt-sortable title=”Click to sort ascending” href=”http://developer.yahoo.com/yui/examples/datatable/yui-dt0-sort3-ascending”>amount</A></SPAN>
<DIV class=yui-dt-resizer id=yui-dt0-colresizer3></DIV></DIV></TH>
<TH class=”yui-dt-resizeable yui-dt-sortable yui-dt-last” id=yui-dt0-th4 yuiCellIndex=”4″ yuiColumnKey=”title” yuiColumnId=”4″> <DIV class=”yui-dt-col-title yui-dt-col-4 yui-dt-liner” id=yui-dt0-th4-liner><SPAN class=yui-dt-label><A class=yui-dt-sortable title=”Click to sort ascending” href=”http://developer.yahoo.com/yui/examples/datatable/yui-dt0-sort4-ascending”>title</A></SPAN>
<DIV class=yui-dt-resizer id=yui-dt0-colresizer4></DIV></DIV></TH></TR></THEAD>
<TBODY class=”" hideFocus tabIndex=0>
<TR class=”yui-dt-even yui-dt-first” id=yui-dt0-bdrow0 yuiRecordId=”yui-rec0″> <TD class=yui-dt-first id=yui-dt0-bdrow0-cell0 headers=”yui-dt0-th0 ” yuiCellIndex=”undefined” yuiColumnKey=”id” yuiColumnId=”0″> <DIV class=”yui-dt-col-id yui-dt-col-0 yui-dt-liner yui-dt-sortable yui-dt-resizeable”>po-0167</DIV></TD>
<TD id=yui-dt0-bdrow0-cell1 headers=”yui-dt0-th1 ” yuiCellIndex=”1″ yuiColumnKey=”date” yuiColumnId=”1″> <DIV class=”yui-dt-col-date yui-dt-col-1 yui-dt-liner yui-dt-sortable yui-dt-resizeable”>3/24/1980</DIV></TD>
<TD id=yui-dt0-bdrow0-cell2 headers=”yui-dt0-th2 ” yuiCellIndex=”2″ yuiColumnKey=”quantity” yuiColumnId=”2″> <DIV class=”yui-dt-col-quantity yui-dt-col-2 yui-dt-liner yui-dt-sortable yui-dt-resizeable”>1</DIV></TD> <TD id=yui-dt0-bdrow0-cell3 headers=”yui-dt0-th3 ” yuiCellIndex=”3″ yuiColumnKey=”amount” yuiColumnId=”3″> <DIV class=”yui-dt-col-amount yui-dt-col-3 yui-dt-liner yui-dt-sortable yui-dt-resizeable”>$4.00</DIV></TD>
…