Techniques for WCAG 2.0

Skip to Content (Press Enter)

-

FLASH17: Providing keyboard access to a Flash object and avoiding a keyboard trap

Applicability

This technique relates to:

User Agent and Assistive Technology Support Notes

See User Agent Support for Flash for general information on user agent support.

The problem targeted by this technique only occurs in browsers other than Internet Explorer. Currently however, this technique only works in Firefox. In Firefox, the focus always enters the Flash content at the start of the tab order, even when entering the Flash object by shift-tabbing backward through the tab order. Additionally, JavaScript needs to be enabled for this technique to work.

Description

The objective of this technique is to allow keyboard focus to move to and from Flash content embedded in a web page. In browsers other than Internet Explorer, there is a problem related to keyboard accessibility of embedded Flash content. The problem is that, while both the Flash content and the HTML content around it may be keyboard accessible, it is not possible to move keyboard focus between the Flash content and HTML content without using a mouse. Once focus is placed inside the Flash movie, a keyboard user will be trapped there. Similarly, when focus is placed somewhere else on the HTML content (outside the Flash movie), it will be impossible to move focus into the movie.

This issue has been around for a long time, and is related to the way browsers implement embedded plug-ins. Until this problem is fixed, it is up to the Flash developer to come up with a work around. This technique is one of those workarounds. The approach behind this technique is the following:

When the SWFFocus class is imported into a Flash project, the following will happen:

As indicated above, there are two ways in which this technique can be used:

  1. Letting the SWFFocus class generate neighboring focusable elements in the HTML tab order for each Flash movie (demonstrated in example 1 below)

    By default, the SWFFocus class will create a hidden link element before and after an embedded Flash movie. These elements are needed as 'anchor' to move focus to when (shift) tabbing out of the Flash movie. This approach is the easiest to implement, as it does not require any additional work by the developer. The downside is that the hidden links will clutter the HTML tab order with meaningless elements (although these elements are only used as tab stops when tabbing _out of_ the Flash movie, not when tabbing _into_ it). Because of this, it is recommended to use the following approach instead:

  2. Explicitly identifying focusable HTML elements that come before and after the a Flash movie in the HTML tab order (demonstrated in example 2 below)

    With this approach, the developer can use ID values to identify the elements that come before and after the Flash movie in the HTML tab order. This is done by setting special class names on the Flash movie's <object> element. This is the preferred approach, as it does not cause an unnecessary cluttering of the tab order. However, it does require more work and awareness by the developer (who has to manually set ID values). Also, in some scenarios there simply may not be a next or previous focusable element for a Flash movie.

Examples

The two examples below are shown in the working example of Preventing a keyboard trap in Flash content. The example html file has two Flash movies embedded in it. The first Flash movie is embedded with the approach described in example 1. The second example is embedded with the approach described in example 2. The source of Preventing a keyboard trap in Flash content is available. The source zip file contains the SWFFocus class.

Note: To run the example from a local drive (as opposed to running it from a web server), the local directory needs to be added to Flash Player's security settings.

Example 1: Using automatically generated links

In this example, the SWFFocus class is used without explicitly identifying focusable HTML elements. This will cause SWFFocus to dynamically insert hidden links before and after the Flash movie.

Loading the Flash Movie

The Flash object in this example is added using SWFObject's dynamic publishing method, which means that the object tag is created dynamically by JavaScript in a way that the browser supports. While this is the recommended approach, it is not a requirement for using this technique. The SWFFocus class will also work when the object tag is hardcoded into the HTML document.

The sample code below shows how to load the movie dynamically with SWFObject.

HTML and Javascript Code Sample for Example 1

Example Code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Keyboard Trap Fix Example</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
    <script src="swfobject_2_1.js" type="text/javascript"/>
    <script type="text/javascript">
      var flashvars = {};
      var params = {};
      params.scale = "noscale";
      var attributes = {};
      attributes.id = "FlashSample1SWF";
      attributes.name = "FlashSample1SWF";
      swfobject.embedSWF("keyboard_trap_fix_custom_as3.swf", "flashSample1", \
          "150", "200", "9.0.0", "expressInstall.swf", flashvars, params, attributes);
</script>
  </head>
  <body>
    <p>The following Flash movie automatically generates invisible
      links before and after the flash movie, allowing keyboard focus
      to move out of the Flash content.</p>
    <div id="flashSample1">
      <a href="http://www.adobe.com/go/getflashplayer">
        <img alt="Get Adobe Flash player"
          src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"
        />
      </a>
    </div>
  </body>
</html>

Importing and Initializing the SWFFocus class in Flash

The SWFFocus class needs to be added to a Flash project's source path. The easiest way to achieve this is to copy the com/swffocus/SWFFocus.as file (including the nested directory structure) to the project's root directory.

When the SWFFocus class is added to the movie's source path, it needs to be initialized with the following code:

Example Code:

import com.swffocus.SWFFocus;
SWFFocus.init(this);

The code for the class itself can be found in the source files.

Example 2: Explicitly identifying existing focusable html element

For a large part, this technique is the same as example 1 :

For more details about these steps, see example 1.

In this case however, special class names are added to the Flash movie object. These class names indicate the ID values of the elements previous and next of the movie in the HTML tab order. The class names are:

For example, the HTML code could look like this (notice the added class names on the object tag):

Example Code:

<a href="http://www.lipsum.com/" id="focus1">test 1</a>
<object class="swfPrev-focus1 swfNext-focus2"
  data="keyboard_trap_fix_as3.swf" tabindex="0"
  type="application/x-shockwave-flash"/>
<a href="http://www.lipsum.com/" id="focus2">test 2</a>

Since this example uses SWFObject's dynamic loading, the class names will have to be specified as attribute when SWFObject is initialized. This is demonstrated in the code example below.

HTML and Javascript Code Sample for Example 2

Example Code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Keyboard Trap Fix Example </title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
    <script src="swfobject_2_1.js" type="text/javascript"/>

    <script type="text/javascript">
      var flashvars = {};
      var params = {};
      params.scale = "noscale";
      var attributes = {};
      attributes.id = "FlashSample2SWF";
      attributes.name = "FlashSample2SWF";
      attributes["class"] = "swfPrev-focus1 swfNext-focus2";
      swfobject.embedSWF("keyboard_trap_fix_as3.swf", "flashSample1", "150", 
        "200", "9.0.0", "expressInstall.swf", flashvars, params, attributes);
    </script>
  </head>
  <body>
    <a href="http://www.lipsum.com/" id="focus1">lorem</a>
    <p>The following Flash movie uses existing links in the document
      to move focus to when (shift) tabbing out of the Flash content.
      The existing links are defined by placing special classnames on
      the Flash object.</p>
    <div id="flashSample2">
      <a href="http://www.adobe.com/go/getflashplayer">
        <img alt="Get Adobe Flash player"
          src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"
        />
      </a>
    </div>
    <a href="http://www.lipsum.com/">lorem</a>
  </body>
</html>

Note: this example assumes that the focusable HTML elements exist and have an ID value at the time SWFObject is called to insert the Flash movie. However, in some situations it is also possible that these elements do not yet exist when the Flash movie is created, or that the elements will be deleted dynamically at a later point. If this happens, it is possible to reassign ID values for previous and next focusable elements. To do this, call the SWFsetFocusIds() method on the Flash movie object, like so:

Example Code:

var o = document.getElementById("FlashSample1SWF");
o.SWFsetFocusIds('prevId', 'nextId');

From that point on the updated IDs will be used to move focus to when tabbing out of the Flash movie.

Resources

Resources are for information purposes only, no endorsement implied.

Tests

Procedure

For a Flash movie on a web page:

  1. If possible, confirm that the source of the Flash movie imports and initializes the SWFFocus class

  2. Press the tab key to move through tabbable items on the page

  3. Confirm that it is possible to tab into the Flash content

  4. Continue tabbing and confirm that it is possible to tab out of the flash content

Expected Results

If this is a sufficient technique for a success criterion, failing this test procedure does not necessarily mean that the success criterion has not been satisfied in some other way, only that this technique has not been successfully implemented and can not be used to claim conformance.

Technique Information

The main component used in this technique is an external ActionScript class called "SWFFocus". This class was created by Michael Jordan (inspired by the previous work of John Norgaard of Sonokids,), and later modified by Hans Hillen from The Paciello Group.