Creating Accessible Components in Flash and Flex (Part 2)

Posted in "Articles, Flash, Flex, General, accessibility" at 5:54 am on January 12, 2009 by Alaric Cole | 5 comments

In this article, I’ll go over the steps needed to enable accessibility for a custom component. While it takes a bit of getting used to, I think you’ll find that enabling accessibility for your components is not only beneficial to the many users who would like to interact with your component, but helps you to fine-tune and further enhance your components in general. To enable use with screen readers, follow these three (simple?) steps:

  1. Determine object role
  2. Create the Accessibility Implementation class for component
  3. Add accessibility tie-ins to component class
    a) Create a placeholder for the static createAccessibilityImplementation() method
    b) Override initializeAccessibility() method
    c) (Flex only) Add AccessibilityClass metadata

Determine object role

In order for the JAWS screen reader to inform the user about a particular component, it needs to know a few things about the component. Most importantly, it needs to know what the type of the component is. It does this using a predefined set of types, called Object Roles in MSAA terminology. These object roles are simply numerical values, standing for control types such as push buttons and list boxes. I like to define them as constants in my accessibility implementations, to make them more identifiable. So the first step is determining the type, which also allows you to see if you need to extend a current accessibility implementation, or start from scratch. The second step is to actually create the implementation (*whew*).

Create the Accessibility Implementation class

To create an accessibility implementation, you need to extend from a base implementation class. For Flash components this will extend fl.accessibility.AccImpl or the component’s superclass’s implementation. For Flex components this will extend mx.accessibility.AccImpl or the component’s superclass’s implementation. For instance, with Astra Carousel, I extended fl.accessibilitySelectableListAccImpl, the implementation used for SelectableList; for Astra Charts, I created an implementation from scratch, extending fl.accessibility.AccImpl.

Generally, you can pair the superclass of your implementation with the component’s superclass. And if one’s not available, start at AccImpl. The main thing to remember is that, for Flash CS3/CS4 components, you need to create the hooks in your implementation that pair it up with its corresponding component. You do this by creating a static variable and a static method:

private static var accessibilityHooked:Boolean=hookAccessibility();
 
private static function hookAccessibility():Boolean
{
     YourComponentClass.createAccessibilityImplementation =
          createAccessibilityImplementation;
     return true;
}

Notice in the hookAccessibility function, that it refers to a static variable of your component’s class. In order for this to work, you’ll need to add that static variable to your component’s class, which we’ll go over later in this article. Remember that the above code is for Flash CS3/CS4 components only–Flex will create the necessary hooks itself through the mxmlc compiler.

Once you’re hooked up, the next task is to actually set the object role you decided on. To do that, you simply set the variable role to that numerical value within the constructor of the implementation class.

Next is the hard part. All implementations will use the following methods to communicate with the screen reader, and you’ll find you need many of them to make your implementation work. However, you may not need to write custom code for all of them, as you may be able to inherit a perfectly usable method from the superclass:

• accLocation(childID:uint):* – specifies the bounding box of a child element.
• accSelect(selFlag:uint, childID:uint):void-altering the selection in the component .
• get_accDefaultAction(childID:uint):String-returns the default action of the component or of one of its child elements.
• get_accFocus():uint-returns the unsigned integer ID of the child element, if any, that has child focus within the component.
• get_accName(childID:uint):String-returns the name for the component or for one of its child elements.
• get_accRole(childID:uint):uint-returns the system role for the component or for one of its child elements.
• get_accSelection():Array-returns an array containing the IDs of all child elements that are selected.
• get_accState(childID:uint):uint-returns the current runtime state of the component or of one of its child elements.
• get_accValue(childID:uint):String-returns the runtime value of the component or of one of its child elements.
• getChildIDArray():Array-returns an array containing the unsigned integer IDs of all child elements in the AccessibilityImplementation.
• eventHandler(event:Event):void-Handles events from the master component. This essentially listens for events, and the developer must create a switch statement to call an Accessibility.sendEvent with the appropriate parameters.
• getName(childID:uint):String-returns the name of the accessible component or the name of one of its child elements.
• getState(childID:uint):uint-returns the state of the accessible component.

It’s important to note that there may be a number of other methods that need to be created for such things as telling the screenreader which child items are focused or what items are selected. Read on for some real-world examples of creating these.

Add accessibility tie-ins to component class

The last step is telling your component class to use this accessibility implementation. Actually, this is a step you can do on your components before you finalize your implementation class, because it doesn’t point to the accessibility class by name. Add these few lines of code to your class:

public static var createAccessibilityImplementation:Function;
 
override protected function initializeAccessibility():void
{
     if (YourComponentClass.createAccessibilityImplementation!=null)
          YourComponentClass.createAccessibilityImplementation(this);
}

This tells UIComponent that there may be an implementation in use, and lets your implementation class mix in with its hookAccessibility() method. If you’re using Flex, it’s a good idea to add AccessibilityClass metadata in your component class. For example, with mx.controls.Button, the following metadata is added, pointing to the implementation class:

[AccessibilityClass(implementation="mx.accessibility.ButtonAccImpl")]

Examples

Talking about what you should do is one thing, but giving you a play-by-play of my own development experience should prove more helpful.

Carousel

To create an accessibility implementation for Carousel, I determined that, because Carousel extends SelectableList, my accessibility implementation would extend SelectableListAccImpl. This saved some of the grunt work, as a few of the necessary methods were already created for me. Even the role did not need to be set, as there is no specific designation for a carousel in MSAA. Carousel is essentially a list, so I was able to keep its role as ROLE_SYSTEM_LIST (0×00000021 for the numerically-inclined). I did have to override the get_accValue method to return the value of the current item in the Carousel. Also, because a Carousel can be horizontal as well as vertical, I had to override get_accState to return the proper state information whether the Carousel was a vertical or horizontal list.

Tree

For Tree, I at first decided to create an accessibility implementation from scratch, probably because I was being stubborn. While Tree extends List, the typical ListAccImple class wasn’t going to cut it for Tree, which has a very different interaction model. However, I later realized that had to reimplement getChildIDArray, accLocation, and get_accFocus, which were already present and suitable in SelectableListAccImpl. So I decided in the end to extend that. However, there was a lot left to be written for this implementation. Tree, while it inherits from List, has its own designation in MSAA land. It is called, interestingly enough, an Outline control, designated by the constant ROLE_SYSTEM_OUTLINE. So that was the role I gave it. I reworked the get_accValue method to return the value of the current item as well as their location in the tree structure. So when the item is selected, the screen reader will read something like “Item 4 of 10″. Other things I had to do with Tree:

  • get_accState was overridden to provide additional information about tree items being collapsed or open.
  • get_accDefaultAction had to show additional actions of a node being collapsed or expanded.
  • accDoDefaultAction needed to be reworked in order to open or close the items.
  • getName was overridden to add, like get_accValue, info about the current location of the item in the tree structure.

I also found in my development that proper keyboard navigation wasn’t in place. So I added that in. That’s the great part about creating these implementations–it allows you to really test the usability of the component, not to mention helps you to find bugs.

Share: on Yahoo! My Web | on del.icio.us | digg it! | reddit!

5 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Great post, Aleric.

    Comment by Michael Jordan — February 3, 2009 #

  2. This is a great post – very helpful, thanks! I’m working on an accessible tree control for AS2 – after hunting around, I discovered there’s a ‘magic’ _accImpl object that can be attached to any movieclip – it supports a subset of the methods available in AS3, including getChildIdArray(). The problem is, getChildIdArray() is only being called for the first level in the tree hierarchy. Sure enough, AccExplorer.exe shows only the top level of hierarchy.

    This may be a limitation of Flash 8/AS2. Did you have a similar issue with your tree control, or id getChildIdArray() called for each level in the hierarchy?

    Thanks again!

    Comment by Max Carlson — March 5, 2009 #

  3. Max, getChildIdArray() is only supposed to be called once for the top level component–this then allows you to determine which child of that component initiated some action. For instance, in my implementation of accessibility for the Astra Tree, I can determine which item in the Tree was clicked via the ChildID passed in, and I build this list of ID via the getChildIdArray() method.

    Comment by Alaric Cole — March 13, 2009 #

  4. [...] what they sound like basically just a mix of code bases. There is a really good post over on the yahoo flash blog about accessibility and the way in which Flex uses [...]

    Pingback by BetaDesigns( Blog ).toString( ); » Mixin’s in ActionScript 3 — July 8, 2009 #

  5. Alaric, thanks for the great article! My remaining hair thanks you. ;-)

    Comment by aut0poietic — August 5, 2009 #

Leave a comment

Note: Comments are moderated for first-timers. Spam deleted.

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Hosted by Yahoo!

Copyright © 2007 Yahoo! Inc. All rights reserved. Privacy Policy - Terms of Service

Powered by WordPress on Yahoo! Web Hosting.