2 Replies Latest reply on Jul 20, 2012 8:12 PM by BlindFlashDeveloperJM

    JAWS accessibility questions

    BlindFlashDeveloperJM

      A couple of the defects noted by our testing team regarding accessibility of our Flex 4.5 application are centered around the JAWS screen reader not automatically speaking text such as column heading and status bar information.  Does anyone have experience in how to make JAWS automatically speak text from a Flash screen?  Being a JAWS user myself as well as a developer, my personal preference would be to have JAWS speak certain text like headers or status bar info on demand if I press a certain key combination. However, this still involves the question of how to make JAWS speak text on demand whether it is caused by an event such as a focus move or text update or if it is via a keyboard event. 

       

      Any feedback would be appreciated.

        • 1. Re: JAWS accessibility questions
          Michael Jordan (a11y)

          It can be done using Accessibility.sendEvent to send events from an object you want to announce to to MSAA clients, but it's not easy and requires a lot of trial and error and testing.

           

          It's important to remember that accessibility in the FlashPlayer depends on the display list; a DisplayObject must be present on the stage in order for an MSAA client to retrieve information from it.

           

          Below is an example method I worked up to add to the PanelAccImpl so that the Panel or TitleWindow will announce itself when it is used a popup.

           

          It's kind of wacky in that it relies on a setInterval loop to stagger the accessibility event calls.

           

          When the Panel opens, we wait 400ms to make sure it and its descendants have been added to the stage. Then I send the accessibility events to indicate a dialog opening from the accImplSprite, which is a child Sprite that holds the Panel's accessibilityImplementation so that Panel's descendants aren't hidden from screen readers.

           

          In the same loop, I send AccConst.EVENT_OBJECT_NAMECHANGE and AccConst.EVENT_OBJECT_FOCUS events from the titleDisplay label which announces the title of the Panel. This is a workaround for JAWS only announcing the accImplSprite as a "grouping," and not including its name.

           

          In the second loop, I send the  AccConst.EVENT_OBJECT_NAMECHANGE and AccConst.EVENT_OBJECT_FOCUS events from the accImplSprite, which causes JAWS to announce the Panel as a "grouping" and restores the JAWS's virtual cursor focus to the grouping.

           

          In the final loop, I hide the titleDisplay from the MSAA tree or else, with no tabindex, it will either show up as an orphaned text field at the end of the MSAA tree, or worse, corrupt the read order of our Flex application.

           

          I hope this helps.

           

          Cheers,

            Michael Jordan

           

          /**

               * @private

               * Sends appropritate accessibility event constants

               * to announce the Panel when it is opened as a pop up.

               */

              mx_internal function sendPopUpAccessibilityEvents():void

              {

                  if (!master.isPopUp) return;

                    

                  var panel:Panel = Panel(master),

                      titleDisplay:InteractiveObject = Panel(master).titleDisplay as InteractiveObject,

                      intId:uint,

                      loop:uint=0,

                      /* we modify the title so that the screen reader

                          believes it has changed and will announce it. */

                      cachedTitle:String = panel.title;

                  panel.title+="\u200B";

                 

                 

                  /* Here we create a setInterval loop to dispatch accessibility events in a particular order */

                  intId = setInterval(function():void

                  {

                      loop++;

                      switch (loop)

                      {

                          case 1:

                          {

                              if (titleDisplay && titleDisplayAccImpl)

                              {

                                  /* We don't really want the title to show up in the accessibility tree,

                                  because it creates a redundant text element that has no tabindex so it can disrupt the read order,

                                  so it's accessibilityImplementation has been cached and it's accessibilityEnabled property

                                  is set to true. However, screen readers, and JAWS in particular, have trouble announcing

                                  the newly created popup's accessibilityName, so to work around it we display the titleDisplay temporarily,

                                  until it can be announced by sending the AccConst.EVENT_OBJECT_FOCUS event. */

                                  titleDisplay.accessibilityImplementation = titleDisplayAccImpl;

                                  titleDisplay.accessibilityProperties.silent = false;

                              }

                             

                              Accessibility.updateProperties();

                             

                              /* First we sent the accessibility events for the dialog opening */

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_SYSTEM_DIALOGSTART);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_REORDER);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_CREATE);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_LOCATIONCHANGE);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_PARENTCHANGE);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_SHOW);

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_SYSTEM_FOREGROUND);

                              if (titleDisplay && titleDisplay.accessibilityImplementation)

                              {

                                  /* If we have a titleDisplay, we send an AccConst.EVENT_OBJECT_NAMECHANGE accessibility event,

                                   followed by an AccConst.EVENT_OBJECT_FOCUS accessibility event which

                                   should prompt the screen reader to announce the titleDisplay text. */

                                  Accessibility.sendEvent(titleDisplay, 0, AccConst.EVENT_OBJECT_NAMECHANGE);

                                  Accessibility.sendEvent(titleDisplay, 0, AccConst.EVENT_OBJECT_FOCUS);

                              }

                              break;

                          }

                          case 2:           

                          {

                              /* With the second loop, we send an AccConst.EVENT_OBJECT_FOCUS event from the accImplSprite,

                               which represents the dialog or panel grouping. */

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_NAMECHANGE);   

                              Accessibility.sendEvent(accImplSprite, 0, AccConst.EVENT_OBJECT_FOCUS);   

                              break;

                          }

                          case 3:

                          {

                              /* Finally, we stop looping, silence the titleDisplay and

                               remove its accessibilityImplementation and restore the cachedTitle. */

                              clearInterval(intId);

                              if (titleDisplay && titleDisplay.accessibilityImplementation)

                              {

                                  titleDisplay.accessibilityImplementation = null;

                                  titleDisplay.accessibilityProperties.silent = true;

                              }

                              panel.title = cachedTitle;

                              break;

                          }

                      }

                  }, 400);

              }

          • 2. Re: JAWS accessibility questions
            BlindFlashDeveloperJM Level 1

            This is excellent; thanks so much!  I’ll give this a try.