Another topic that was discussed at the recent accessibility talk was the need to display access keys to keyboard users - as they will certainly make use of them.
After some discussion with Phil Smears on the GeekUp mailing lists about access keys, Tom Adams joined the conversation and pointed us to the NWDA website - when you start using the tab key to cycle through links, you'll see a "pop-up" Access Key panel in the top-right of the page that cycles through the various access keys each time you press the Tab key. After cycling through the access keys, the panel disappears and you can then tab through the rest of the page.
So, we set to work on implementing something similar (well, almost identical) in to Theme Builder 3.0.
Our first port of call was to replace the existing "skip navigation" link:
<a href="#page-content" class="non-visual" accessKey="S" style="display:none;">Skip navigation</a>
While the link had served us well since the days of Theme Builder 2.0, it was time to move to something more modern.
The first task was to replace link with a definition list:
<dl id="accessKeys">
<dt>Access Keys:</dt>
<dd><a href="#page-content" accessKey="S">Skip navigation (Access Key - S)</a></dd>
</dl>
As well as being nice and semantic (it makes it clear that the links listed are access keys) it also provides plenty of HTML elements that we can apply style sheets to.
Next we applied some very simple CSS to make the links "pop-up" when they receive keyboard focus:
#accessKeys {
margin: 0; padding: 0;
}
#accessKeys dt {
margin: 0;
padding: 0;
position: absolute;
top: -9999px;
left: 0;
}
#accessKeys dd {
margin: 0;
padding: 0;
}
#accessKeys dd a {
position: absolute;
top: -9999px;
left: 0;
}
#accessKeys dd a:focus, #accessKeys dd a:active {
background-color: #3556a2;
color: #fff;
top: 0;
font-size: 1.2em;
padding: .5em;
}
All this does is to hide the definition term ("Access Keys:") and the definition descriptions (list of access keys) by positioning them outside the web page.
When an access key link receives keyboard focus (a:focus, a:active) we simply set it's top position to 0, putting it back on the page so people can see it.
Great, now we had our "skip navigation" link brought in to the Web 2.0 era without using a single line of JavaScript. But what about other access keys?
Well, it just so happens that the menulink and compound-menuitem macros supplied with Theme Builder support access keys...
{compound-menuitem:login|icon=user1_into|caption=Log in|accesskey=5}
{compound-menuitem:signup|icon=user1_add|caption=Sign up|accesskey=6}
{compound-menuitem:logout|icon=door2|caption=Log out|accesskey=5}
Menu items that aren't applicable are automatically removed - so if you're logged in only the "log out" link will appear with it's associated access key.
What if we could somehow list those access keys defined elsewhere on the page in our definition list at the top of the page?
To do this, Alain Moran used the Request Object as a temporary storage location. Each time the browser asks for a page, Confluence creates a request object to hold various internal information about the request. The object provides us with a neat gateway between the rendering of the page content and the rendering of the theme, which happen at different times.
When an access key is defined using our menu macros, the access key details (if present) are stored on the request object. As the theme is rendered, it picks up the list of access keys and outputs them in the definition list.
The result is that the list of access keys is automatically built whenever you view a page - a list that's always up-to-date and hassle free. The definition list for this page currently looks something like this:
<dl id="accessKeys">
<dt>Access Keys:</dt>
<dd><a href="#page-content" accesskey="S">Skip navigation (Access Key - S)</a></dd>
<dd><a href="/display/~gfraser" accesskey="1">Home (Access Key - 1)</a></dd>
<dd><a href="/display/My" accesskey="2">My (Access Key - 2)</a></dd>
<dd><a href="/dashboard.action" accesskey="3">All spaces... (Access Key - 3)</a></dd>
<dd><a href="/display/ADAPTAVIST/Contact" accesskey="4">Contact (Access Key - 4)</a></dd>
<dd><a href="/logout.action" accesskey="5">Log out (Access Key - 5)</a></dd>
</dl>
To make the list more usable, we've also alphanumerically sorted the dynamic part of the list - so the keys are listed from 0 to 9, A to Z. The hard-coded "skip navigation" link is always output first because it's the most commonly used link.
So, give it a try - hit tab a few times and you should see the panel appear when the links receive focus. Also, when you use an access key the panel will appear confirming your selection.
One of the other neat features of the menu system used in Theme Builder is that you can prefix a letter in a menu item caption with an underscore ("_") to turn it in to a shortcut key within the menu. Because this is separate from the access key, we can create different ways of accessing the same functionality. A good example is our "Home" menu:
{compound-menuitem:home|caption=_Home|accesskey=1}
You can access the home page for the current space by either pressing Access Key 1 or by using the H shortcut from within the menu. This has another advantage in making the menu accessible via the keyboard - try pressing Alt + H (you'll need to scroll to the top of the screen) and you should see the "Home" menu appear. You can then press Enter (or Space, etc) to instantly go to the home page for the current space, or use the arrow keys to navigate around the menu.