In recent months, many web designers have been asking the question, “How can I make my dynamic site accessible?” Unfortunately, good answers have been slow in coming from the accessibility community. While some articles have touched on the problem, not many have gone into details. Here is our first attempt at rectifying this situation.
Why is it so difficult for us to come up with some simple recommendations like we did for web 1.0?
This article is by no means the final word. We are just beginning to scratch the surface. Much more research is needed.
How Screen Readers Read Web Pages
The name screen reader is a misnomer since they do not read the screen. Screen readers load the page content from the browser’s document object model (DOM) into a virtual buffer. The user is then able to review this virtual buffer at will, using numerous hotkeys. Items such as links, form fields, and some other elements are identified when they are read. When the user finds a link or other clickable element that they wish to activate, they simply press Enter, and the screen reader tells the browser where they “clicked”.
Form controls are handled differently. When a user encounters a form control they wish to manipulate, they press Enter, causing the screen reader to enter Forms Mode. When in forms mode, the user is only able to “see” the form control that has focus. They cannot read the page content until they leave Forms Mode and return to Virtual Mode. The user can press tab and shift+tab to iterate through the form controls, and, depending on the control type, use the arrow keys, or enter text to modify the control that has focus. Note however, that just because a particular control has focus in the virtual buffer, it does not necessarily have it in the browser. (This last point will hopefully become clearer in a moment.)
Earlier versions of screen readers would sometimes show the user a page that was out of date, because the page would change, but the virtual buffer wouldn’t get updated. Fortunately, this problem seems to have been resolved in more recent versions, and the virtual buffer is refreshed from the DOM every few seconds.
Alerting the User
Fortunately, the situation described above isn’t totally hopeless. The user has clicked something, so they are probably expecting something to have changed. Whether their screen reader says anything or not. You can give the user a hand in locating the new or updated information by directing the user’s focus to the help text via an anchor tag, or the text could simply be displayed at the user’s current point of focus. Obviously these solutions aren’t perfect, but they are certainly better than nothing.
Ways to alert the user is an area in need of much more research, and we hope to bring you articles in the future which address this problem in greater depth.
<span onclick="someFunction()"> or
element.onclick = someFunction;) and the advanced model (
element.attachEvent(...); depending on which browser you are coding for).
Of course, it shouldn’t matter which model is used, right? Wrong. For some reason, both Jaws and Window Eyes will not tell the user that an item is clickable if the click event was registered via the advanced registration model.
In Jaws, if the user happens to press Enter on a part of the page which is not reported as being clickable, a click on that portion of the page is passed to the browser anyway, so if there is a click event attached to that portion of the page, then it will fire. Of course, this is rather improbable, as the user isn’t likely to try to “click” places which aren’t reported as being clickable. Also, in Window Eyes, any press of the Enter key on a portion of the page with no link, form control, or element which is not reported as being clickable is ignored.
Fortunately, there is a simple hack which will force Jaws and Window Eyes to recognize that a given element is clickable when you use the advanced registration model. Simply register an empty click event using the traditional model (
element.onclick = "").
It appears that the user can fire traditionally registered click events by pressing Enter on any non-form element in both screen readers. However, in Jaws, only click events attached to checkboxes and radio buttons can fire, and in Window Eyes, it does not seem to be possible to easily fire click events on any form controls.
Neither screen reader reports when the dblclick event is attached to any element, and this event is not easily fired in Window Eyes. In Jaws, it is possible, but again, rather improbable. If a user presses Enter twice quickly on a non-form element with this event attached, it will fire. There does not seem to be a way to get it to fire with Jaws when attached to a form control.
Neither screen reader reports when the mousedown and mouseup events are attached to any element, and these events are not easily fired in Window Eyes. In Jaws, they will fire if the user presses Enter on a non-form element where either of them are attached. There does not seem to be a way to get either to fire with Jaws when attached to a form control.
Window Eyes does not support the mouseover event, and there is no way to make it fire with that screen reader. On the other hand, Jaws seems to offer surprisingly good support for this event, though again that support breaks down somewhat when the event is registered via the advanced registration model.
Jaws will alert the user when a mouseover event is attached to an element via the traditional model, and it can be fired by use of the Jaws Mouseover hotkey (Insert+Ctrl+Enter). Here again, if the event is registered via the advanced model, Jaws will not alert the user that they can mouseover that particular element. However, if the user guesses that they can, the hotkey will still work. Pressing Enter on an element with mouseover attached will also cause the event to fire, but will additionally tell the browser that the user clicked there, which may cause other events to fire if attached.
In addition, the same hack that works on the click event also works with the mouseover event. If you attach an event using the advanced model, you can get Jaws to recognize that the mouseover event is attached by adding an empty event to the element via the traditional model.
In Jaws, there are two primary ways to navigate a web page. The first is by reading everything from top to bottom, and the second is by tabbing through all the focusable elements (links and form controls). Confusingly, this results in the user having two cursors, a reading cursor and a mouse cursor. The reading cursor exists only for the screenreader (think of it as the virtual buffer cursor), and it has no effect on the browser. The mouse cursor, of course, is just the mouse pointer. Jaws doesn’t generally move the mouse cursor unless it needs to. If the user reads through a page, and stops on a link or form control, the reading cursor is on the element but the mouse cursor is probably not. When the user presses Enter on that link or control, the mouse is then moved to the same position as the reading cursor, so it can be clicked. On the other hand, if the user tabs through the page, the mouse cursor is moved with the reading cursor, and each element gets focus by both cursors.
The end result is that if a user tabs from form control to form control, the current control gets focus and the preceding control is blurred. However, if the user just reads each control with the reading cursor, then no controls get focus and no controls are blurred.
Like Jaws, Window Eyes also has two cursors, but pressing the tab key or reading through the page will focus the mouse on each link as it is reached, and blur it as it is passed. Form controls, on the other hand, will only receive focus if they are modified or given focus when in forms mode.
With these limitations in mind, the blur and focus work as expected: before a form control is changed and before a link is clicked, it receives focus, so the focus event is fired on the current control, and if applicable, the blur event is fired on the previous control.
Works as expected in both Jaws and Window Eyes.
keydown, keyup, keypress
When in forms mode, works as expected in both Jaws and Window Eyes. When not in forms mode, the events can’t be made to fire, because Jaws and Window Eyes capture most keypresses.
When in forms mode, works as expected in both Jaws and Window Eyes. When not in forms mode, text can be selected and copied to the clipboard without firing the event. This is likely due to the fact that text is being selected and copied from the virtual buffer, and not directly from the browser.
In Jaws, this event is fired at seemingly random times, including sometimes on page load.
In Window Eyes, on the other hand, it fires at much more logical times—after the user has read several lines of text. However, keep in mind that all scrolling, as such, is taken care of by the screen reader. From the user’s perspective, there is no such thing as below the fold, as everything on the page is all in one big buffer, and screen readers give no indication to the user when they scroll the screen.
Works as expected in both Jaws and Window Eyes.
For a nice all in one spot reference, here is a compatibility table after the manner of the great Quirksmode Compatibility Tables by PPK.
|event||Jaws 9.0||Window Eyes 7.0 b1|
|select||incomplete *||incomplete *|
* = Only works in forms mode
Thanks to PPK for his permission to let us use the compatibility table design, to Kurt Hills for playing the part of editor and to all the others who gave it a proof-reading.