BigBlueButton Accessibility Instructions
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+5}"