There are some things in the world of accessibility that appear, on the face of it, to be really wonderful ideas… until you scratch slightly below the service. What may seem feasible when putting together some guidelines on accessibility might not ultimately translate well to a real-world application. Hands up who can remember the last time they felt compelled to use a longdesc
attribute? And what about the accesskey
attribute? Oh, you have used them you say. OK, let’s back up a little and find out what went wrong here.
Contents
The Problem With Accesskeys
The accesskey
attribute is a neat little feature that is supposed to enable the user to quickly access a navigation, search, or some other feature of a page quickly. For example, I could use an accesskey
of ’s’ for search on a site – on all sites that I might run – and have that as the trigger. Depending on the browser or other assistive technology (AT) used, that might involve the user hitting CTRL+s to activate it, or maybe ALT+S, or perhaps some other configuration.
However, those very same commands might be the same as existing commands in the browser or AT. So which command takes precedence? There is another factor to this ‘key already assigned’ problem, and that’s one of localization. While you may think that your browser has a spare key that you could use, in many other languages this won’t be the case.
Another problem with the accesskey
attribute is how do you let the user know about it? As with the longdesc
attribute, the availability of the attribute is not really shouted from the rooftops (with the exception of the little-used iCab browser). Unless you make a point of informing the user of accesskey
s being used on the site in a separate page, perhaps backed up by judicious use of the title
attribute for the relevant links, the user may never know that you made them available.
So it seems that, while accesskeys are a great idea, they are largely hidden and also cause their own set of problems because of the potential overlap with other technology. But wait, maybe there’s life in the old dog just yet…
Let the User Decide
I have an idea, or rather I had an idea, about the way it might work. I actually used this approach a couple of years ago when I re-built accessify.com, providing a method for the user to set their own accesskeys. They are not forced upon anyone – it’s a total opt-in. But in all honesty, it was more of an experiment on a live site than anything else, and it’s not transferable to other sites unfortunately. The solution was built using PHP, but I always thought that it could be converted to a JavaScript solution. It just took me a couple of years to get around to it (and documenting it!).
The JavaScript Approach
In the JavaScript solution, the end result is exactly the same as the version used on Accessify, just the mechanics have changed. Rather than go into all the lines of code and explain everything line-by-line, I’ll summarise how it works in plain old English.
- There are a number of links on the example page (the links that we offer up as potential accesskey candidates) By default, they have no
accesskey
assigned, nor anytitle
attribute:
<h3>Navigation</h3>
<ul>
<li><a href="/" id="homelink">Home</a></li>
<li><a href="/search/" id="searchlink">Search</a></li>
…
</ul>
- There’s a warning on the page that says "you need Javascript to set your own accesskeys" – this is set to display on screen by default
Finally, there’s a form that allows you to set the characters you want for the related sections on the page. This is hidden by default (using CSS)
<p id="warning">Cookies are used to save these preferences, but you have either disabled JavaScript, set your browser not to accept cookies, or your browser supports neither. The site will work perfectly well without these preference options.</p>
#warning
{
color:red;
}function hideWarning()
{
var elwarn = document.getElementById(’warning’);
elwarn.style.display="none";
var elsetter = document.getElementById(’setter’);
elsetter.style.display="block";
}
If the user gets to the page with JavaScript disabled (or with the scripts not properly downloaded – perhaps blocked by a firewall), they will essentially get the default page that says "You can’t do this, you need JavaScript to set this stuff" and no facility to set it is displayed.
If JavaScript is available, though, it’s a slightly different scenario:
- The warning message that’s set to display by default gets suppressed (after page load, by having the CSS
display
property set tonone
) - The form that accepts the user’s desired
accesskey
assignments is made visible (again, using JavaScript to change the CSSdisplay
property)
Now that we know that the user has JavaScript enabled and was able to get all the source files correctly, they can then go ahead and save their accesskeys.
Saving the Accesskey Choices
The process of saving the choices made by the user are fairly standard JavaScript/cookie methods – one long string is saved that has a number of property:value pairings (one for each link or button that can potentially be assigned an acccesskey). For example:
<form action="set-access-keys.htm" method="post" name="frmAccessKeys">
<fieldset>
<legend>Set Accesskeys for … </legend>
<div>
<label for="txthomelink">Home link</label>
<input value="" name="txthomelink" id="txthomelink" type="text" size="2" maxlength="1" />
</div>
<div>
<label for="txtsearchlink">Search Box</label>
<input value="" name="txtsearchlink" id="txtsearchlink" type="text" size="2" maxlength="1" />
</div>
...
</fieldset>
</form>
strKeyVals += "homelink=" + document.forms['frmAccessKeys'].txthomelink.value + "@@";
strKeyVals += "searchlink=" + document.forms[’frmAccessKeys’].txtsearchlink.value + "@@";
The @@
is simply there to make it easier to identify where to split the string when retrieving the data from the saved cookie later.
We also provide an option for the user to get a hint of the accesskey
for each link or button with the use of a simple checkbox:
<div>
<input type="checkbox" name="chkshowhint" id="chkshowhint" />
<label for="chkshowhint" class="check">Show accesskeys in links and buttons (displayed after link in brackets)</label>
</div>
strKeyVals += "showhint=" + document.forms['frmAccessKeys'].chkshowhint.checked + "@@";
The process for capturing the information is initiated by an onclick
event attached to the submit button, which passes it through to an addevent
function:
addEvent(document.getElementById('cmdSubmit'), 'click', accessKeySetter, false);
(The function accessKeySetter is where the JavaScript code snippets above appear)
Remembering the Choices and Updating the Display on Page
Assuming the user has entered some values and also chosen to have the accesskeys showing in the links or buttons, once the page has reloaded following the submit, this is where the DOM really takes over.
Remember, we start with a page that has a number of links that have neither default accesskey
or title
attributes present, then we use JavaScript to present the option to manipulate/store accesskey
s (if JavaScript is not available for whatever reason, the default page display is to warn them that they can’t do this and need to get their JS in order, or words to that effect). So, already, we’re using JavaScript in a nice progressive enhancing kinda way. The final stage is to use JavaScript and the DOM to update the page display depending on what’s found in the cookie. The steps to do this are as follows:
- Firstly, look for the presence of the
accesskey
cookie - Assuming it’s found, take the content of that string and split it up into the individual links/buttons that it repesents (separated by the
@@
characters that were shown earlier
//get the cookie
var strAccessKeys = readCookie("accesskeys");
//split up the values
var arrAccesskeys = strAccessKeys.split("@@"); - Then, each value found is split between the
id
of the link or button it represents and the value stored against each (theaccesskey
the user wants to assign)
for (i=0;i<(arrAccesskeys.length-2);i++)
{
var thisAccessKey = arrAccesskeys[i].split("=");
var accessKayEl = thisAccessKey[0];
var accessKayAttrib = thisAccessKey[1];
… - Then it’s a case of running through the array of
id
s in the cookie that have values assigned and matching them up to theid
s of elements on the page and then:- adding the accesskey value to the element
if (accessKayAttrib.length>0)
{
//set the attribute
document.getElementById(accessKayEl).setAttribute(’accesskey’, accessKayAttrib); - and updating the content of link or value of the button text to display the accesskey (if the user has requested this), and adding a title attribute too:
if (document.getElementById(accessKayEl).tagName=="A")
{
var strLinkPhrase = document.getElementById(accessKayEl).childNodes[0].nodeValue;
}
if ((document.getElementById(accessKayEl).tagName=="INPUT") && ((document.getElementById(accessKayEl).type=="submit")||
(document.getElementById(accessKayEl).type=="button")))
{
var strLinkPhrase = document.getElementById(accessKayEl).value;
}
document.getElementById(accessKayEl).setAttribute(’title’, strLinkPhrase + ‘, access key = ‘ + accessKayAttrib);
//display the accesskey hint, if that’s been chosen
if (blnShowHints)
{
strLinkPhrase = strLinkPhrase + " [" + accessKayAttrib + "]";
if (document.getElementById(accessKayEl).tagName=="A")
{
document.getElementById(accessKayEl).childNodes[0].nodeValue = strLinkPhrase;
}
if (document.getElementById(accessKayEl).tagName=="INPUT")
{
document.getElementById(accessKayEl).value = strLinkPhrase;
}
- adding the accesskey value to the element
- One final step, while traversing through the page, is to add the value chosen in to the form fields too, so they’re remembered, likewise the state of the checkbox.
The final result is a completely unobtrusive method for setting and remembering accesskey attributes which doesn’t enforce itself on the user – it’s completely opt-in.
[download the zipped version with all files required here.]
Possible Improvements
The biggest improvement that could happen with this script is to have it centralized somewhere, or some variant thereof, so that it could be re-used in some way. My thinking was that if this mechanism were possible to re-use across sites, then a user could potentially save some accesskey choices that would be usable for a number of different sites, but then there’s one fatal flaw in this idea – a cookie can only be read back by the same domain, thus if I were to set my choice for site whateverxyz.com, when I try to do the same for abcwhatever.com, it won’t be able to read back the same data. So I’m definitely open to suggestions as to how that might be made possible at some time in the future.
Outside Reading
This isn’t the first time someone has come up with a method for dealing with this, so here are a few other takes on how to solve the issue:
And if you want to to learn more about the background to the problem, here are a couple of recommended reads:
- Dave Shea: Keyboards and Chaos
- Derek Featherstone: Accesskey Conflicts
thanks admin good post