E-mail List Archives

Help with ARIA: menu widget

for

From: Ney André de Mello Zunino
Date: Apr 28, 2011 12:27PM


Hello.

I've been trying to get acquainted with ARIA roles and techniques and
chose to play with a simple menu widget, based on sample code from the
ARIA Practices document [1]. Note: if this is not the right forum for
this kind of question, I'be thankful if you could point me in the right
direction.

Anyway, I've taken that sample code, made minor modifications (mainly
adding id attributes to some elements), used CSS to lay out the menu in
a tree-like form and Javascript to add expand/collapse behavior. I've
been careful in my JS code to keep CSS and ARIA in sync, as recommended
[2]. The files (HTML, CSS, JS) are available inline, further below.

For testing, I've been using the 11 and 12 demo versions of JAWS and
also NVDA. So far, my overall experience with screen readers has not
been very positive, as I'm often confronted with a feeling of
non-determinism in the interaction. E.g. JAWS recognizes and announces
the navigation landmark and allows me to navigate there. Then it also
recognizes the menu widget. I can then press the ENTER key to expand the
submenus. Sometimes, it takes only one press of the key, but most of the
time it will only respond at each other key press. Another thing is
inconsistency: JAWS tells me I should use the up and down arrow keys to
navigate the menu. But doing that will cause the whole page to scroll
instead. NVDA seems to handle this part adequately.

I belive most of what I've been seeing is due to my lack of experience
with this kind of software. In addition to that, I may have got the
wrong idea about ARIA and its "promises". I somehow assumed that by
merely adding semantic information via ARIA attributes, the widgets
would become interactive entities, following some kind of default
behavior (likely, one that would mimic the UI experience of desktop
applications).

I was further convinced that my incomplete understanding was to blame
when I found one example of an interactive ARIA grid widget [3] and
noticed the huge amount of Javascript code written to define the
behavior of the widgets. Is that how it's done? I mean, must we,
developers, actually implement each and every detail of the interaction
with widgets, even the simplest ones? Don't get me wrong, I like to be
able to have control and fine tune the behavior of the components I
create; but I thought that more basic, well-defined behaviors for common
widgets could, somehow, be deduced/provided by the browser/reader, based
on the semantic given by ARIA attributes.

FWIW, the browsers I've been using for testing are: Firefox 4 and
Internet Explorer 8. The code of the 3 files follows below:


=== test06.html ========================================================

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html lang="en-US">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>ARIA menu widget test</title>
<link rel="stylesheet" type="text/css" href="test06.css">
<script type="text/javascript" src="test06.js"></script>
</head>

<body onload="onBodyLoad()">

<div role="banner">
<h1>Testing ARIA menu widget</h1>
</div>

<div role="navigation">
<h2 id="menu">Menu</h2>
<div id="menu-bar" role="menubar">
<!--
File menu: File menuitem has an aria-haspopup attribute set to 'true'.
That popup div follows immediately below.
-->
<div role="menuitem" aria-haspopup="true" id="fileMenu"
tabindex="0">File</div>
<div role="menu" aria-labelledby="fileMenu" aria-hidden="true"
id="fileSubmenu">
<div role="menuitem"><a href="">Open</a></div>
<div role="menuitem"><a href="">Save</a></div>
<div role="menuitem"><a href="">Save as...</a></div>
</div>
<!--
View menu:
-->
<div role="menuitem" aria-haspopup="true" id="viewMenu"
tabindex="0">View</div>
<div role="menu" aria-labelledby="viewMenu" aria-hidden="true"
id="viewSubmenu">
<div role="menuitem"><a href="">Normal</a></div>
<div role="menuitem"><a href="">Outline</a></div>
<!--
The View's Zoom menuitem has aria-haspopup='true' as it leads to a
submenu.
-->
<div role="menuitem" aria-haspopup="true" id="zoomMenu">Zoom</div>
<div role="menu" aria-labelledby="zoomSubMenu" aria-hidden="true"
id="zoomSubmenu">
<div role="menuitem"><a href="">50%</a></div>
<div role="menuitem"><a href="">75%</a></div>
<div role="menuitem"><a href="">100%</a></div>
<div role="menuitem"><a href="">150%</a></div>
<div role="menuitem"><a href="">200%</a></div>
</div>
</div>
</div>

</div>

</body>

</html>

=== <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> ===



=== test06.css =========================================================

div[role=menubar] {
width: 15em;
}

div[role=menu] > div[role=menuitem], div[role=menu] > div[role=menu] {
margin-left: 1.5em;
}

div[role=menu], div[role=menuitem] {
cursor: pointer;
padding-left: .2em;
}

div[role=menuitem] a {
display: block;
}

#fileMenu, #viewMenu, #zoomMenu {
background-color: #efefef;
font-weight: bold;
}

div[role=menuitem]:hover {
background-color: #cec;
}

*[aria-hidden=true] {
display: none;
}

=== <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> ===


=== test06.js ==========================================================

function onBodyLoad() {
setUpEventHandlers();
}

function setUpEventHandlers() {
var divs = [
{ elem: document.getElementById("fileMenu"), submenu:
document.getElementById("fileSubmenu") }
, { elem: document.getElementById("viewMenu"), submenu:
document.getElementById("viewSubmenu") }
, { elem: document.getElementById("zoomMenu"), submenu:
document.getElementById("zoomSubmenu") }
];
var childrenCount = divs.length;
for (var i = 0; i < childrenCount; ++i) {
(function() {
var item = divs[i].elem;
var submenu = divs[i].submenu;
var clickHandlerFunction = function(evt) { openClose(evt, item,
submenu); };
if (item.addEventListener) {
item.addEventListener("click", clickHandlerFunction, true);
} else if (item.attachEvent) {
item.attachEvent("onclick", clickHandlerFunction);
}
})();
}
}

function openClose(evt, node, submenu) {
if (submenu.style.display != "block") {
submenu.style.display = "block";
submenu.setAttribute("aria-hidden", false);
} else {
submenu.style.display = "none";
submenu.setAttribute("aria-hidden", true);
}
}

=== <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> <EOF> ===


[1] http://www.w3.org/TR/wai-aria-practices/#relations_haspopup
[2] http://www.w3.org/TR/wai-aria-practices/#ContentPresChanges
[3] http://codetalks.org/source/widgets/grid/grid.html

Thank you,

--
Ney André de Mello Zunino
Pesquisa e Desenvolvimento
Softplan/Poligraph
Sistema da Qualidade Certificado ISO9001:2008
Fone/Fax: 0xx(48) 3027-8000
http://www.softplan.com.br/