I’ve been doing some work for the National Park Service recently, and it’s gotten me into Flash accessibility. Accessibility is a big deal for government clients because all “.gov” websites mandate 508 compliance – which requires that all content be visible to screen readers, like JAWS.
While it’s pretty easy to get Flash content exposed to a screen reader, it’s fairly tedious to get the presentation flowing nicely with both with visual controls and accessibility controls. It doesn’t help that Flash’s accessibility documentation is fairly slim and there aren’t a lot of developers discussing it. So, after a few days worth of development and testing on the subject, I’ll share my findings.
1) Make DisplayObjects accessible.
Start by giving each button an “AccessibilityProperties” object. The AccessibilityProperties object can have a name and description assigned to it. From what I can tell, the “name” field is the key piece of content given that it’s automatically read when the button gets focus. I never found a way to access the “description” field through my screen reader (but then I’m not a JAWS power user either). Also, enable “forceSimple” on the AccessibilityProperties object so that none of the object’s children are read. Otherwise, the screen reader will read a button’s text content.
2) Restrict tab ranges
Flash will, by default, step through all buttons on stage. However, chances are that you won’t want every single control included within the accessible presentation. So, use “tabEnabled” and “tabIndex” (properties of InteractiveObject) to control which buttons are allowed to receive tab focus. Set “tabEnabled” to false on all buttons that are not part of the accessible presentation, or just set “tabChildren” (property of Sprite) to false on a high-level display container to completely disable tabbing within that display branch. Finally, manually assign a numeric “tabIndex” value for each accessible button to guarantee the order in which the buttons will be tabbed.
After setting accessibility properties and limiting tab order, you should be well on your way to having a decent accessibility presentation.
3) Synchronizing accessible and visual presentations.
Tabbing is great for an accessibility presentation, although it has the potential to get out of synch with the visual presentation (which is probably controlled by mouse clicks). So, it’s important to have both aspects of the presentation work together. This means that tabs need to simulate mouse clicks, and vice versa.
Simulating a mouse click to a button upon tabbing to it is easy. Just have the button listen for FocusEvent.FOCUS_IN, and have that trigger the button’s click action. Works like a charm.
Making a button obtain tab focus upon click is also simple, given that Flash automatically gives focus to an object when its clicked. In the event that you need to manually give a button focus, use the “stage.focus” display property.
4) Forcing a screen reader to read an item.
In practice, the screen reader will read any new content that is set to the “stage.focus” property. So if you have a single object with changing content, you can trick a re-reading of the object by changing its accessibility properties, calling Accessibility.updateProperties(), and then nullify and reset the “stage.focus” property.
5) Buttons off stage don’t get read.
This was driving me nuts: I made a scrolling row of thumbnail images that you can flip through using the keyboard (tab/arrows). While flipping through thumbnails, the active thumbnail would slide into view if it was accessed outside of the scroll area. The solution worked great, visually. However, while Flash could tab to a button off of stage, JAWS wouldn’t read it. Once I deduced that stage bounds were the issue, I solved the problem by creating a second set of 1×1 pixel buttons hidden on stage that proxied the main buttons’ tab behavior. It seemed clunky, but it worked. However, it revealed another advantage: Flash has native support for intelligent arrow key controls based on tabEnabled buttons’ proximity to one another. When you line up a bunch of tabable button in a horizontal row, the left/right arrow keys are automatically set up to flip through them. Same goes for a vertical column: up/down arrow will be enabled for you. So, this tab proxy trick allows the tabEnabled buttons to be arranged in a horizontal or vertical fashion, regardless of the layout of the main visual buttons.
So, hopefully someone else will find this helpful. If any readers have other tips or tricks, please feel free to post them in comments!