Open main menu

CDOT Wiki β

BigBlueButton Accessibility Instructions

Revision as of 16:41, 2 March 2013 by JTRobinson (talk | contribs)
Bigbluebutton.png


How to develop accessible extensions, modules, and plugins for the BigBlueButton Flash client

Accessibility is an important part of the BigBlueButton application. Not only does it allow users with disabilities to run and participate in meetings, it's also mandated by law that if we CAN make it accessible, we HAVE to. For our purposes, disabilities fall into three main categories: Visual, Auditory, and Motor. This guide focuses mostly on Visual and Motor, simply because of the nature of BigBlueButton and what the CDOT team has run into so far.

With Visual and Motor disabilities there is a common concern of the user being able to navigate through the application, since use of a mouse may not be possible. You'll accommodate this by including your code in the tab order, and also by providing shortcut keys for all user functionality in your code. The rule is, if you can do it with a mouse, you need to be able to do it with a keyboard.

Some Visual disabilities require the user to have a screen reader, which is what it sounds like: an application that reads out the content of the screen to the user. In Flash, this is done mainly through the accessibilityDescription property. The rule here is, all relevant data on the screen must have an accessibilityDescription.

Tab Order

This guide will start with the assumption that you are building an entirely new module.

Linking in your module

BigBlueButton already has an established core tab order, with each module given a baseTabIndex property. The convention is to establish your module's baseTabIndex in an Options class. For an example, examine the ChatOptions class at dev\bigbluebutton\bigbluebutton-client\src\org\bigbluebutton\modules\chat\model\ChatOptions.as.

Within the Options class, declare the baseTabIndex instance variable like so:

[Bindable] public var baseTabIndex:int;

In the constructor, make a link to your module's entry in BigBlueButton's config.xml. You can add a baseTabIndex property to the config entry if you want, to allow customization later. This code includes a default value in the event that baseTabIndex is not defined in your module config:

public function ChatOptions() {
   var cxml:XML =     BBB.getConfigForModule("ChatModule");
   if (cxml != null) {
      if (cxml.@baseTabIndex != undefined) {
         baseTabIndex = cxml.@baseTabIndex;
      }
      else{
         baseTabIndex = 701;
      }
   }
}
       
public function getBaseIndex():int{
   return baseTabIndex;
}

The core BigBlueButton modules have baseTabIndex values 100 elements apart, to accommodate future growth. Replace 701 in the else clause with another, more suitable number that reflects a logical place for your module.

For the existing default baseTabIndex values of the core BigBlueButton client, check \dev\bigbluebutton\bigbluebutton-client\README.

Lastly, determine which MXML file in your module is the "main" file. Continuing with the example of the Chat module, this is dev\bigbluebutton\bigbluebutton-client\src\org\bigbluebutton\modules\chat\views\ChatWindow.mxml. Import your Options class into that MXML with a standard import statement, and declare a baseIndex instance variable just as you did in your Options class, as well as an instance of your Options class, like so:

[Bindable] private var baseIndex:int;
[Bindable] public var chatOptions:ChatOptions;

If your MXML does not already call a method on initialization, add an initialize property to the MDIWindow tag like so:

<MDIWindow xmlns="flexlib.mdi.containers.*"
           xmlns:mx="http://www.adobe.com/2006/mxml"
           initialize="init()"
           >

Your MDIWindow will likely have far more properties than shown, these have been removed for clarity's sake.

In your initialize method (in this example, init()) initialize baseIndex with the getBaseTabIndex() method from your Options class:

private function init():void{
   baseIndex = chatOptions.baseTabIndex;
}

Establishing internal tab order

Your module now "knows" where it should sit in the general tab order; you now have to give each Flash component within your module a tabIndex property. This is based on the baseIndex variable in the MXML, so if the file you're working in does not have one, either re-read "Linking in your module" above or find a way to pass the baseIndex from the "main" MXML into the file you're working with.

Adding the main controls

If the MDIWindow you are working in doesn't have a creationComplete method, add one:

<MDIWindow xmlns="flexlib.mdi.containers.*"
           xmlns:mx="http://www.adobe.com/2006/mxml"
           creationComplete="onCreationComplete()"
           >

Your MDIWindow will likely have far more properties than shown, these have been removed for clarity's sake.

Each MDIWindow has a titlebar overlay, also known as the "main bar" of the window, showing the window's title. Generally, there is also a minimize button, maximize button, and close button. These items will come first in the internal tab order of the module, so in the creationComplete method, give each of them a tabIndex property:

private function onCreationComplete():void {
   titleBarOverlay.tabIndex = baseIndex;
   minimizeBtn.tabIndex = baseIndex+1;
   maximizeRestoreBtn.tabIndex = baseIndex+2;
   closeBtn.tabIndex = baseIndex+3;
}

You'll also want to add the accessibilityDescriptions to each item here, but ignore that for now.

All other Flash elements

Now that you have put the titlebar and control buttons into the tab order, continue through each element in the module and continue assigning tabIndex properties based on the baseIndex. The tab order within the module is up to your discretion, as long as the order is as sensible to a user who cannot see the screen as it is to a fully-sighted user.

You have already seen how to assign a tabIndex dynamically above. To assign a static tabIndex within the Flash component itself, write the property like so:

tabIndex="{baseIndex+4}"

Testing

Testing the tab order is very easy, simply focus into the application and continue pressing the Tab key until you see the focus indicator in the general vicinity of your contribution. Continue tabbing, and observe how the movement of the indicator lines up with how you expected it to move.

Screen Reader Compatibility

According to CDOT's research, there are two main screen-reader applications to be aware of: JAWS and NVDA. JAWS is proprietary software available for a fee; use your own judgement as far as acquiring a license for the software or ignoring it in your testing. NVDA, on the other hand, is the leading open-source screen-reader and completely free to download, use, and test with.

Before you can get any meaningful results from the screen-reader, you'll need to have your tab order sorted out. If you have not done so, please refer to the previous part of this guide.

Adding screen-reader compatibility is relatively simple, and revolves around the accessibilityName property, or in some cases the toolTip property. However, not all Flash components are compatible; for example, Labels are not accessible. Adobe has released a comprehensive guide on the subject; we will focus on BigBlueButton here.

One last thing to consider, is localization. All of your accessibilityNames must be in the locale file, so that the community can translate them to other languages and your module can be used worldwide.

The titlebar component of your MDIWindow needs an accessibilityName, as do the control buttons. See the Tab Order section above for the section were titleBarOverlay is given a tabIndex. In the same place, add this code:

titleBarOverlay.accessibilityName = ResourceUtil.getInstance().getString('bbb.exampleModule.titleBar.accessName');
minimizeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.exampleModule.minBtn.accessName');
maximizeRestoreBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.exampleModule.maxBtn.accessName');
closeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.exampleModule.closeBtn.accessName');

Dynamic accessibilityNames can be assigned the same way. For static components, the accessibilityName can be set within the component itself:

accessibilityName="{ResourceUtil.getInstance().getString('bbb.exampleModule.exampleComponent.accessName')}"

If you change an accessibilityName dynamically, be sure to call Accessibility.updateProperties() to force the screen-reader to update it's cached version of the application. The operation is fairly memory-intensive, so use it efficiently.

Testing

Testing can be done in a very similar manner to testing the tab order. Open your screen-reader of choice, start up the BigBlueButton application, and use the Tab key to navigate to your module. Listen to the reader's description of what is on the screen, and try to put yourself in the position of a blind or partially-sighted user. Turn your monitor off, if it helps. Also listen to the descriptions of established BigBlueButton core modules, and mimic the conventions there in your own accessiblityNames.

Shortcut Keys

Global Shortcuts

Testing

Local Shortcuts

Testing