Reference: Accessibility Global Link Functional UI Pattern

This topic contains the following sections:

Overview

It is required by law that software applications meet accessibility standards to sell to education and government customers. The commercial sector is also impacted by discrimination laws.

Laws and regulations about accessibility include: Section 508 of the U.S. Rehabilitation Act of 1973, individual US state laws, Americans with Disabilities Act (ADA) of 1990, and the Disability Discrimination Act of 1995 in the U.K.

In the absolute simplest of terms, meeting accessibility standards involves the following:

  • the product must be usable without a mouse (i.e., keyboard only).
  • the product must be usable by a blind user (e.g., with a screen reader or braille reader).
  • sole reliance can not exist on sound, color, animation, or timing to communicate to the user.

All functionality, other than install and initial configuration ('one-time' events), meet the standards of Section 508.

Development is responsible for ensuring the accessibility of their products. JDeveloper/ADF provides technologies to assist development to meet required standards of accessibility. ADF Faces user interface components have built-in accessibility support for visually and physically impaired users. User agents, such as a Web browser rendering to nonvisual media such as a screen reader, can read component text descriptions to provide useful information to impaired users. Access key support provides an alternative method to access components and links using only the keyboard.

While ADF Faces provides accessibility technologies to assist development to meet required standards of accessibility, it is not a substitute for familiarity with accessibility standards and performing accessibility testing with assistive technology. In concert, UX Designers are responsible for ensuring the accessibility of their designs and for reading and adhering to the applicable accessibility usage guideline.

Problem Description

Optimally, the application should allow the individual user to set an accessibility level.

One option is to provide a means for users to set the accessibility level preferred at sign in. With that option, not only is the preferred level set, but it can persist across authentications as the initial setting is stored as a user preference.

The limitation with that solution is that it requires the user to authenticate. There are frequent use cases, popular with users, where application features are available for the anonymous user. Frequent examples are eCommerce sites. Unauthenticated, users can browse product catalogs, comparison shop, and in some cases add items to a "shopping cart." It is only at the time of purchase (e.g., check out) that the user is required to authenticate or create an account to authenticate.

The challenge for an ADF application, is to support the unauthenticated use case with accessible pages.

Technical Pattern Description

The Accessibility Global Link Functional UI Pattern provides a means for all users, whether users of assistive technologies or not, to select the desired accessibility level for an ADF application without authenticating first. In other to accomplish this, the initial point of an ADF page visited must be accessible at the default level to all users.

Part of the solution lies in the fact that the default mode for ADF is accessible to disabled users. It is the user of a screen reader where the focus of this Functional UI Pattern lies. However, not all ADF components are inaccessible to screen readers at the default ADF accessibility level. The initial application page visited by all users should be composed of those components.

One means of overcoming this is to realize that many, if not virtually all, web sites and applications have boilerplate UI or chrome. This boilerplate is used to provide the user with a sense of place; that is, "I am browsing eCommerce.com vs. DMV.gov." Chrome or boilerplate UI is also a means by which providers brand their service.

Chrome is generally at the top and bottom of a page if not consuming the entire perimeter. Users of screen readers advance through a page, using keyboard navigation (e.g., Tab key) by passing through the chrome. If the UI control by which the user could select a preferred accessibility level was placed in the chrome, then there is no need to constrain a entire page or all potential initial pages of an application with a few ADF accessible pages -- just the chrome.

The number of ADF components available for constructing the chrome is sufficient enough to create a compelling boiler plate UI accessible to all users, including those of screen readers.

Since users can visit a site or application with an unauthenticated user experience, at a number of pages, the chrome, as well as the accessibility control embedded within it, must be ubiquitous. The ADF page template is a feature specifically designed to support this use case. Templates provide a convenient and consistent method for laying out a page. Thus, all pages using that template would have the same layout (e.g., one column, two column, three column). Further, UI control/display components (e.g., company logo, link to shopping cart) can be placed into that template layout. All pages using that template would have the same layout and UI control/display components.

Constructing pages based on an ADF template with an accessibility control placed within it, not only assures a consistent chrome for all pages, it also ensures that all such pages will have the accessibility control. Layout and display components placed within a template also cannot be modified by the DT using that template. So there is virtually, no means of inadvertently removing those elements.

The solution provided here is placing an accessibility control within the chrome of an ADF page template.

The User Experience

The boiler plate or chrome of an application typically has UI controls at what is some times referred to as the global level. These are UI controls (e.g., links) placed along either the top or bottom of page. Examples include the link to the shopping cart, authentication page, help, about, and so on. Since these global controls are along the top border of a page, they would be among the first UI elements a user of a screen reader would traverse. One of those global controls should be a link to an accessibility page where in a user could set the preferred accessibility level.

Illustration of example Accessibility Global Link

A user of a screen reader would use the keyboard to tab through the chrome at the top of the page (e.g., branding area) to reach the Accessibility global link. That link could also contain descriptive text communicated by the screen reader to further inform the user to follow this link to set accessibility to a preferred level. Once the user follows that link, the resulting UI could be one of two types.

 

  • A "plain" accessibility preference page (e.g., no chrome) that lists selectable options.
  • An accessibility preference page based on the same template as the previous page (i.e., application chrome) but utilizes the ADF skipLink feature whereby the user of the screen reader or keyboard navigation could skip through the balance of the chrome and all other UI content to the list of selectable options that are accessible, by default, to a screen reader.

Illustration of plain page for setting accessibility

Illustration of template page for setting accessibility

Plain Accessibility Preference Page

The advantage of the plain ADF page is the high probability of success the user of the screen reader would have navigating to and setting the desired accessibility level. This list of acceptable ADF layout, display, and control components are more than sufficient for this UI design. It is also true that users with other preferences (e.g., high contrast, large fonts) would have little difficulty with such a simple page. It might be the one page in the entire application that would not be based on the template.

Accessibility Preference Page Based on the Application Template

One of the key advantages of the plain ADF page may also be its disadvantage. Without the chrome otherwise seen within the application, the user may experience a sudden lack of context. The page would not appear as part of the application and apart from divining the context from any information visible in the browser location bar, the user may wonder if this is the same application/site.

Maintaining the chrome and the context it provide, while at the same time increasing the probability that the user of a screen reader would be able to set the accessibility level, perhaps is the better solution. This may be accomplished with the ADF skipLink component. When the user lands on this page, the first tab of the keyboard advances to a control that once activated by the user (i.e., clicks the Enter key), vectors the user to anywhere on the page the page designer desired. In this example, that would be at the UI controls for setting accessibility. Because this feature skips over all other content (as well as other ADF components), the concern need only be that the UI control where the user lands are accessible to the screen reader.

Although this page is using the same template as the calling page, the Accessibility Link is not shown in the chrome -- as that would invite needlessly recursive.

Accessibility Options

The accessibility options presented to the user would be:

  • Screen reader
  • High contrast
  • Large fonts

It would be best to allow a user to select one or more of these options (e.g., high contrast and large fonts). Check boxes supports that. Leaving all of the options unselected would return or leave the accessibility level at the default value.

Pressing the OK button sets the level and redirects the user to the calling page.

Persistence

Given that the user is unauthenticated, there is no reliable means to persist the setting beyond the browser session. So instructional text informing the user of this limitation is warranted. The application could be written to forward the setting into a persistent store once the user authenticates with an account. However that is beyond the scope of this functional UI pattern.

Artifacts

The following is a list of artifacts used in this pattern.

Java Beans

 

  • AccessibilityPreferenceHolder
    • This is a request-scope bean that temporarily holds the accessibility preference(s) while the user selects them in the accessibility preferences page. The values stored in this temporary object are only pushed into the AccessibilityPreferences instance when the user commits the changes by clicking the OK button on the accessibility preferences page. When leaving the page via any other means (e.g., Cancel, other command components), any changes stored in the AccessibilityPreferencesHolder are discarded.
  • AccessibilityPreferences
    • This is a session-scope bean used to store the selected accessibility preferences. This object is exposed with the name accessibility in faces-config.xml. It can be accessed via the EL expression #{accessibility}.

User Interface Elements

 

  • ExampleTemplate4AccessibilityPatternDef1
    • An ADF template file upon which the jspx files created to demonstrate this pattern are based. It demonstrates the use of the global Accessibility link, the af:skipLink, and binding the value of the render property of the global Accessibility link to avoid inviting recursion. It also contains an ADF best practice UI design and ADF components to use for the chrome at the top of the page.
  • faces-config
    • In the faces-config file redirect when navigating to the accessibility preferences page to ensure that screen reader users get a fresh page load. Otherwise, a ppr-navigation to the accessibility preferences page may not be ideal for screen reader users running in the default accessibility mode (e.g., no virtual buffer flush).
  • ShowAccessibility.jspx
    • Example jspx page based on the ExampleTemplate4AccessibilityPatternDef1 template that demonstrates the initial page accessed by the user. It shows the selected accessibility mode.
  • SetAccessibility.jspx
    • Example jspx page based on the ExampleTemplate4AccessibilityPatternDef1 template that demonstrates the setting of an accessibility preference. It also shows an ADF best practice UI for presenting the accessibility options.

Pattern Implementation

This sample implementation of the UI pattern depends on 2 java beans available in the release version of the adfdemo war. The design time implementation of this pattern is divided into 5 major steps.

 

  1. Create the template used by the application to contain the Accessibility Global Link and the ADF skipLink component.
  2. Create java beans.
  3. Edit trindidad-config to specify the default skin, accessibility mode and profile.
  4. Specify the navigation rules between the calling page and the accessibility preference page in faces-config.xml.
  5. Create the jspx pages and task flows for showing and setting the accessibility preference.

Note Not all steps sufficient for a well designed UI (e.g., use of Spacer component) or even an accessible UI (e.g., adding text for the ShortDesc property ) are given in the steps below. Suffice it to say, they are necessary. The goal here was to limit the steps to the germane.

Create the Template for the Accessibility Global Link

  1. Click the New Application icon button in the Application Navigator to create a new application workspace.

    The Model project is not used in this sample app.

  2. In the Create Application wizard, type GuestAccessibility or other appropriate name for the Application Name.
  3. Click Fusion Web Application (ADF) from the Application Template.
  4. Click Next
  5. For project names, type guestAccessModel and guestAccessViewController for the Model and ViewController respectively, or other appropriate names.
  6. For Application Package Prefix, type oracle.adfdemo.view.
  7. Click Finish.
  8. Open the context menu on guestAccessViewController.
  9. Select New.
  10. In the New Gallery under Web Tier, select JSF.
  11. Under JSF, select JSF Page Template.
  12. In the Create JSF Page Template dialog, type ExampleTemplate4AccessibilityPatternDef1.jspx or other appropriate name for the template.
  13. In the Directory field, append the path to read:
    • C:\JDeveloper\mywork\AccessibilityGlobalLink\guestAccessViewController\public_html\WEB-INF\template

      This is a convenience to improve the workspace organization.

  14. Select the check box to use a Quick Start Layout.
  15. Click Browse.
  16. Click the 3 column layout icon in the left side navigator.

    Illustration of three column layout icon in Quick Start Layout dialog

  17. Within the 3 column layout category, select the icon that shows all partitions locked.

    Illustration of three column layout icon showing all partitions locked

    The locks simply mean that this selected layout does not come with pre-inserted splitters. In other words, its a Panel Stretch Layout.

    Optionally, user defined names can be given for each of the facets (i.e., the locked partitions of the layout).

  18. Select the Attribute tab at the bottom of the Create JSF Page Template dialog.
  19. Click the Add icon(i.e., green plus symbol) five times.
  20. Type the following attribute names: type, default values, and required state.
    Attribute Name Type
    Default Value*
    Required
    globalBrandingSize int 55
    false
    regionalSplitterSize int 255
    false
    contextualSplitterSize int 30
    false
    mode java.lang.String ableGuest
    false
    brandingTitle java.lang.String UI Pattern
    false

    * These can be any appropriate value for the chosen layout and context.

  21. Click OK
  22. In the Structure Window, select the panelStretchLayout.
  23. Select the Center facet of the panelStretchLayout in the Visual Editor.
  24. From the Layout accordion of the Component Palette, select the Panel Splitter to add it to the facet.

    The Panel Splitter will be used to partition the branding and global controls area from the bottom content of the page. This component is also acceptable in the default accessibility mode for screen readers.

  25. In the Common section of the Property Inspector, set the Orientation to vertical.
  26. In the Behavior section of the Property Inspector, set the Disabled property to true. This will prevent the user from resizing or hiding the branding area.

Designing the Branding Bar

  1. In the Visual Editor, select the First facet of the Panel Splitter.
  2. From the Layout accordion of the Component Palette, select the Panel Group Layout to add it to the facet.
  3. In the Common section of the Property Inspector, set the Layout to scroll.
  4. With input focus on the panelGroupLayout, select the Panel Border Layout from the Layout accordion of the Component Palette.
  5. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  6. In the Property Menu, select Edit.
  7. In the Edit Property: StyleClass, shuttle AFBrandingBar from Available Classes to Selected Classes.
  8. Click OK.
  9. With input focus on the panelBorderLayout, select another Panel Border Layout from the Layout accordion of the Component Palette.
  10. With input focus on the nested panelBorderLayout, select Image from the Common accordion of the Component Palette.
  11. In the Common section of the Property Inspector, type the following expression in the Source property:
    • #{requestContext.rightToLeft?'/afr/gradient-none-white.png':'/afr/gradient-white-none.png'}
  12. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  13. In the Property Menu, select Edit.
  14. In the Edit Property: StyleClass, shuttle AFBrandingBarItem and AFStretchWidth from Available Classes to Selected Classes.
  15. Click OK.
  16. In the Structure Window, expand the panelBorderLayout Facets of the nested panelBorderLayout.
  17. Select the End facet.
  18. With input focus on the End facet, select Panel Group Layout from the Layout accordion of the Component Palette.
  19. In the Common section of the Property Inspector, set the Orientation to vertical.
  20. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  21. In the Property Menu, select Edit.
  22. In the Edit Property: StyleClass, shuttle AFBrandingBarItem from Available Classes to Selected Classes.

Adding the Accessibility Global Link

  1. With input focus on the nested panelGroupLayout, select Navigation Pane from the Layout accordion of the Component Palette.
  2. In the Common section of the Property Inspector, set the Hint to buttons.

    This will display the global controls as links with vertical separators between them.

  3. With input focus on the navigationPane, click twice on the Navigation Item from the Common accordion of the Component Palette.
  4. In the Common section of the Property Inspector for the first commandNavigationItem (i.e., the Accessibility Global Link), type the following expression for the Rendered property:
    • #{attrs.mode != 'accessibility'}

      This binding will provide for the hiding of the Accessibility global link when on the Accessibility Preference page. Remember, the default value for the mode attribute set in the template is ableGuest.

  5. Type Accessibility for the Text property value.
  6. In the Navigation Item Action subsection of the Common section of the Property Inspector, type the following expression for the Action property:
    • #{accessibility.goToPreferences}

      Whichever jspx page is listed as the Accessibility Preference page later in faces-config, this action will navigate to that page when the Accessibility global link is selected.

  7. In the Text subsection of the Appearance section of the Property Inspector, type the following or other appropriate text for the ShortDesc property:
    • Edit accessibility preferences that are in effect for this HTTP session.

      It is important to also add descriptive text for all controls particularly this one such that the screen reader can tell the user what it does.

Adding other Global Links

  1. Select the second commandNavigationItem
  2. In the Common section of the Property Inspector, type Help for the Text property value.
  3. In the Text subsection of the Appearance section of the Property Inspector, type the following or other appropriate text for the ShortDesc property: Guest User Help.

     

Completing the Design of the Branding Bar

  1. In the Structure Window, select the parent panelBorderLayout in the First facet of the panelSplitter.
  2. In the Structure Window, expand the panelBorderLayout facets.
  3. Select the End facet.
  4. With input focus on the End facet, select Panel Group Layout from the Layout accordion of the Component Palette.
  5. In the Common section of the Property Inspector, set the Orientation to horizontal.
  6. With input focus on the panelGroupLayout, select Progress Indicator from the Common accordion of the Component Palette.
  7. In the Structure Window, select the innerEnd facet.
  8. With input focus on the innerEnd facet, select Spacer from the Layout accordion of the Component Palette.
  9. In the Structure Window, select the innerStart facet.
  10. With input focus on the innerStart facet, select Panel Group Layout from the Layout accordion of the Component Palette.
  11. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  12. In the Property Menu, select Edit.
  13. In the Edit Property: StyleClass, shuttle AFBrandingBarItem from Available Classes to Selected Classes.
  14. Click OK.
  15. For the InlineStyle property, type the following: background-color: white;
  16. With input focus on the panelGroupLayout, select Output Text from the Common accordion of the Component Palette.
  17. In the Common section of the Property Inspector, type the following expression for the Value property:
    • #{attrs.brandingTitle}
  18. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  19. In the Property Menu, select Edit.
  20. In the Edit Property: StyleClass, shuttle AFBrandingBarTitle from Available Classes to Selected Classes.
  21. Click OK.
  22. In the Structure Window, select the Start facet.
  23. With input focus on the Start facet, select Panel Group Layout from the Layout accordion of the Component Palette.
  24. In the Style section of the Property Inspector, select the Property Menu of the StyleClass property.
  25. In the Property Menu, select Edit.
  26. In the Edit Property: StyleClass, shuttle AFBrandingBarItem from Available Classes to Selected Classes.
  27. Click OK.
  28. For the InlineStyle property, type the following: background-color: white;
  29. With input focus on the panelGroupLayout, select Spacer from the Layout accordion of the Component Palette.
  30. In the Appearance section of the Property Inspector, type the following or other appropriate text for the ShortDesc property: Oracle

     

    This is the term used for the Logo or any present graphic insignia that the screen reader would communicate to the user.

Creating Facets for the Application Page Content

The following steps are not germane to the Accessibility Global Link UI pattern. They are given primarily to provide a facet within the created template for application content. In practice, these steps would be replaced with those more specific to the application. The primary purpose of the facets given here are to show and set the accessibility settings. Only the necessary steps for adding a facet for this demonstration are enumerated. The exact replica of the illustrated example is given in the sample download associated with this functional UI pattern.

Example illustration of template page with empty facets for application content

  1. In the Visual Editor, select the Second facet of the Panel Splitter.

    This would be the lower half of the page template.

  2. From the Layout accordion of the Component Palette, select Panel Stretch Layout to add it to the facet.
  3. In the Common section of the PI, set the:
    • StartWidth to 3
    • EndWidth to 3
    • TopHeight to 1em
  4. From the Layout accordion of the Component Palette, drag and drop a Panel Splitter into the Center facet of the Panel Stretch Layout.
  5. In the Common section of the Property Inspector, set the Orientation to horizontal.

    This will split the lower half of the template into two horizontal sections with a splitter control between them. The leftmost of the two will be referred to as the Regional Area.

  6. In the Visual Editor, select the first facet of the Panel Splitter.

    This is the leftmost section of the lower half referred to earlier.

  7. From the Layout accordion of the Component Palette, select Panel Stretch Layout to add it to the first facet.
  8. In the Common section of the PI, set the:
    • StartWidth to 1px
    • BottomHeight to 1px
  9. In the Visual Editor, select the Center facet of the Panel Stretch Layout
  10. From the Common accordion of the Component Palette, drag and drop a Facet Ref to add it to the Center facet.
  11. In the Property Inspector, type RegionalArea for the FacetName.
  12. In the Visual Editor, select the Second facet of the Panel Splitter.

    This would be the right half of the lower portion of the page template.

    This will eventually be the facet area to which task flows will be added to show and set the accessibility preference.

  13. From the Layout accordion of the Component Palette, select Panel Stretch Layout to add it to the second facet.
  14. In the Common section of the Property Inspector, set the StartWidth to 1px.
  15. In the Visual Editor, select the Center facet of the Panel Stretch Layout.
  16. From the Layout accordion of the Component Palette, drag and drop a Panel Splitter into the Center facet of the Panel Stretch Layout.

    This will divide the right half of the lower portion of the page template into two sections.

    These two sections, left to right, will be referred to as the Local Area and the Contextual Area, respectively.

  17. In the Common section of the Property Inspector, type the following expression for the SplitterPosition value:
    • #{attrs.contextualSplitterSize}
  18. In the Visual Editor, select the first facet of the Panel Splitter.

    This will be the Local Area section of the lower half referred to earlier.

  19. From the Common accordion of the Component Palette, drag and drop a Facet Ref to add it to the first facet.
  20. In the Property Inspector, type LocalArea for the FacetName.
  21. In the Visual Editor, select the second facet of the Panel Splitter.

    This will be the Contextual Area section of the lower half referred to earlier.

  22. From the Common accordion of the Component Palette, drag and drop a Facet Ref to add it to the second facet.
  23. In the Property Inspector, type ContextuallArea for the FacetName.

Adding Optional Facets for the Template Footer

The facets added here are optional. They may be used to display optional output text and links. In this example, they will be used for copyright, about, and privacy notices.

  1. In the Structure Window, select the outermost (i.e., parent) panelStretchLayout
  2. Select the Bottom facet of the panelStretchLayout.
  3. From the Layout accordion of the Component Palette, select the Panel Group Layout to add it to the facet.
  4. With input focus on the panelGroupLayout, select Panel Border Layout from the Layout accordion of the Component Palette.
  5. In the Structure Window, expand the Panel Border Layout facets.
  6. From the Component Palette, drag and drop the Panel Group Layout onto the End facet within the Panel Border Layout Facets.
  7. From the Common accordion of the Component Palette, drag and drop a Facet Ref onto the panelGroupLayout component in the Structure Window
  8. In the Property Inspector, type appAboutappPrivacy for the FacetName.
  9. From the Component Palette, drag and drop the Panel Group Layout onto the Start facet within the Panel Border Layout Facets.
  10. From the Common accordion of the Component Palette, drag and drop a Facet Ref onto the panelGroupLayout component in the Structure Window.
  11. In the Property Inspector, type appCopyright for the FacetName.

Unless components are added to these facets (e.g., Links), they will not show when the template is used at runtime. In any event, the essential portion of the template is completed.

Now is a good time to save the application workspace.

Create Java Beans

In this section, the two Java beans will be created: AccessibilityPreferencesHolder.java and AccessibilityPreferences.java; respectively.

  1. Open the context menu on guestAccessViewController.
  2. Select New.
  3. In the Create Java Class, type AccessibilityPreferencesHolder.
  4. Type sample.accessibility for the Package name or other appropriate package name.
  5. Click OK.

The following is taken from the 11.1.1.2.0 release of the ADF Demo war.

/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */
package sample.accessibility;

import org.apache.myfaces.trinidad.context.AccessibilityProfile;
import org.apache.myfaces.trinidad.context.RequestContext;

/**
 * AccessibilityPreferencesHolder is a request-scope managed bean that
 * temporarily holds on to accessibility preferences while the end user is
 * editing them in the accessibility preferences page.  While interacting
 * with the accessibility page, we avoid pushing values directly into
 * the AccessibilityPreferences instance, since it is possible that the
 * end user may leave the page without accepting these changes.
 *
 * The values stored in this temporary object are only pushed into the
 * AccessibilityPreferences instance when the user commits the changes by
 * clicking the "OK" button on the accessibility preferences page.  When
 * leaving the page via any other means (Cancel button, or other command
 * components), any changes stored in the AccessibilityPreferencesHolder
 * are discarded.
 *
 * This object is exposed as a rqeuest-scope managed bean with the name
 * "accessibilityHolder" (see faces-config.xml).  It can be accessed via the EL
 * expression "#{accessibilityHolder}".
 */
public class AccessibilityPreferencesHolder
{
  /**
   * Tests whether the user prefers screen reader-optimized content.
   */
  public boolean isScreenReader()
  {
    return _screenReader;
  }
 
  /**
   * Tests whether the user prefers high contrast-optimized content.
   */
  public boolean isHighContrast()
  {
    return _highContrast;
  }
 
  /**
   * Tests whether the user prefers content optimized for large fonts.
   */
  public boolean isLargeFonts()
  {
    return _largeFonts;
  }

  /**
   * Stores the screen reader preference.
   */
  public void setScreenReader(boolean screenReader)
  {
    _screenReader = screenReader;
  }
 
  /**
   * Stores the high contrast preference.
   */
  public void setHighContrast(boolean highContrast)
  {
    _highContrast = highContrast;
  }

  /**
   * Stores the large fonts preference.
   */
  public void setLargeFonts(boolean largeFonts)
  {
    _largeFonts = largeFonts;
  }

  /**
   * Setter for injecting the AccessibilityPreferences managed-property.
   *
   * The managed-bean definition specifies that the AccessibilityPreferences
   * instance should be injected into this object via the
   * setAccessibilityPreferences() method.  (See faces-config.xml.)
   */
  public void setAccessibilityPreferences(AccessibilityPreferences preferences)
  {
    // Use the session-scoped AccessibilityPreferences to initialize our
    // values to the user's current preferences.   
    _largeFonts = preferences.isLargeFonts();
    _highContrast = preferences.isHighContrast();
    _screenReader = preferences.isScreenReader();

    // Keep a reference to the AccessibilityPreferences instance.  We'll need
    // access to this object in order to commit the user's new preferences.
    _preferences = preferences;
  }

  /**
   * Handles OK button clicks.
   */
  public void ok()
  {
    // Store the user's new preferences, making them active.     
    _preferences.setScreenReader(isScreenReader());
    _preferences.setHighContrast(isHighContrast());
    _preferences.setLargeFonts(isLargeFonts());

    // Let the AccessibilityPreferences bean figure out where to navigate to next.
    _preferences.returnFromPreferences();
  }

  /**
   * Handles cancel button clicks.
   */
  public void cancel()
  {
    // Don't save any new values - just return.
    _preferences.returnFromPreferences();
  }

  // User's current preferences.
  private boolean _largeFonts;
  private boolean _highContrast;
  private boolean _screenReader;

  // Injected AccessbilityPreferences instance.
  private AccessibilityPreferences _preferences;
}
  1. Select New.
  2. In the New Gallery, select the Java Class from the Java category.
  3. In the Create Java Class, type AccessibilityPreferences.
  4. Type sample.accessibility for the Package name.
  5. Click OK.
  6. The following is taken from the 11.1.1.2.0 release of the ADF Demo war
/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */
package sample.accessibility;

import java.io.IOException;
import java.io.Serializable;

import java.util.logging.Logger;

import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import oracle.adf.share.logging.ADFLogger;

import org.apache.myfaces.trinidad.context.AccessibilityProfile;

/**
 * Bean used to store user/session-specific accessibility preferences.
 *
 * This object is exposed as a session-scope managed bean with the name
 * "accessibility" (see faces-config.xml).  It can be accessed via the EL
 * expression "#{accessibility}".
 */
public class AccessibilityPreferences implements Serializable
{
  /**
   * Returns the user's preferred accessibility mode.
   *
   * The trinidad-config.xml's accessibility-mode setting
   * is bound to this value (ie. "#{accessibility.accessibilityMode}").
   */
  public String getAccessibilityMode()
  {
    return _screenReader ? "screenReader" : "default";
  }

  /**
   * Returns the user's preferred accessibility profile.
   *
   * The trinidad-config.xml's accessibility-profile setting
   * is bound to this value (ie. "#{accessibility.accessibilityProfile}").
   */
  public AccessibilityProfile getAccessibilityProfile()
  {

    // Use safe double-check locking just in case we have
    // multiple threads coming through.
    if (_profile == null)
    {
      synchronized (this)
      {
        if (_profile == null)
          _profile = _createAccessibilityProfile();
      }
    }

    return _profile;
  }

  /**
   * Tests whether the user prefers screen reader-optimized content.
   */
  public boolean isScreenReader()
  {
    return _screenReader;
  }
 
  /**
   * Tests whether the user prefers high contrast-optimized content.
   */
  public boolean isHighContrast()
  {
    return _highContrast;
  }
 
  /**
   * Tests whether the user prefers content optimized for large fonts.
   */
  public boolean isLargeFonts()
  {
    return _largeFonts;
  }

  /**
   * Stores the screen reader preference.
   */
  public void setScreenReader(boolean screenReader)
  {
    _screenReader = screenReader;
  }
 
  /**
   * Stores the high contrast preference.
   */
  public synchronized void setHighContrast(boolean highContrast)
  {
    _highContrast = highContrast;

    // We need to re-create the AccessibilityProfile instance
    // if any of the profile properties change.  Null out our
    // old cached copy.  It will be re-created the next time
    // that getAccessibilityProfile() is called.
    _profile = null;
  }

  /**
   * Stores the large fonts preference.
   */
  public synchronized void setLargeFonts(boolean largeFonts)
  {
    _largeFonts = largeFonts;

    // We need to re-create the AccessibilityProfile instance
    // if any of the profile properties change.  Null out our
    // old cached copy.  It will be re-created the next time
    // that getAccessibilityProfile() is called.
    _profile = null;

  }

  /**
   * Action method that navigates to the accessibility preferences page.
   *
   */
  public String goToPreferences()
  {
    // Store away the current view id so that we can return
    // to the referring page later.
    FacesContext context = FacesContext.getCurrentInstance();
    UIViewRoot root = context.getViewRoot();
    _returnViewId = root.getViewId();
   
    return "accessibility";
  }
 
  /**
   * Action  method that navigates back to the previous page when we
   * are done with the accessibility preferences page.
   */
  public void returnFromPreferences()
  {
    if (_returnViewId == null)
      return;

    // Convert the view id into an URL suitable for redirect.
    // Note that we redirect to ensure that the user gets a
    // completely fresh page, rendered with the proper renderers
    // and JavaScript libraries.
    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext external = context.getExternalContext();
    Application application = context.getApplication();
    ViewHandler viewHandler = application.getViewHandler();
   
    String actionURL = viewHandler.getActionURL(context, _returnViewId);
    actionURL = external.encodeActionURL(actionURL);
   
    try
    {
      external.redirect(actionURL);
    }
    catch (IOException e)
    {
      _LOG.warning(e);
    }
  }

  // Creates the AccessibilityProfile instance based on the user's
  // current accessibility preferences.
  private AccessibilityProfile _createAccessibilityProfile()
  {
    AccessibilityProfile.ColorContrast colorContrast = isHighContrast() ?
      AccessibilityProfile.ColorContrast.HIGH :
      AccessibilityProfile.ColorContrast.STANDARD;
   
    AccessibilityProfile.FontSize fontSize = isLargeFonts() ?
      AccessibilityProfile.FontSize.LARGE :
      AccessibilityProfile.FontSize.MEDIUM;
   
    return AccessibilityProfile.getInstance(colorContrast, fontSize);
  }


  // We hold a reference to a cached copy of the AccessibilityProfile
  // so that we do not need to re-create this object each time
  // getAccessibilityProfile() is called.
  // Note that we mark this as volatile so that we can safely perform
  // double-checked locking on this variable.
  private volatile AccessibilityProfile _profile;

  // User's current preferences.
  private boolean _screenReader;
  private boolean _highContrast;
  private boolean _largeFonts;

  // The view id that we should return to when we have finished
  // editing the accessibility preferences.
  private String _returnViewId;

  private static final ADFLogger _LOG =
    ADFLogger.createADFLogger(AccessibilityPreferences.class);

  private static final long serialVersionUID = 2L;
}

Now is a good time to save the application workspace for the java files.

Edit Trinidad Configuration

ADF Faces provides two levels of application accessibility support, configured in the trinidad-config.xml file using the <accessibility-mode> element. The acceptable values for <accessibility-mode> are:

  • default: By default, ADF Faces generates HTML code that is accessible to disabled users.
  • screenReader: ADF Faces generates HTML code that is optimized for the use of screen readers. The screenReader mode facilitates disabled users, but may degrade the output for non-disabled users or users with only some physical limitations. For example, access keys are disabled in screenReader mode in order to prevent conflicts with keys used by assistive technology.

You can also use the accessibility-profile element to define finer grain accessibility preferences in the style sheet or you can specify the accessibility profile options in the trinidad-config.xml file. The options are high-contrast, large-fonts, or both.

These elements can be used in any combination of screen reader mode, high-contrast, and large-fonts.

Configure Accessibility Support in trinidad-config.xml

  1. In the Application Navigator, double click trinidad.xml to open the file in the XML editor.
  2. Type the element name <accessibility-mode>.
  3. For this element, type the following expression which will hold the accessibility support value (e.g., default, screenReader) passed from the AccessibilityModeBean. In this demonstration, that specifically would be:
    • <accessibility-mode>#{accessibility.accessibilityMode}</accessibility-mode>
  4. Type the element name <accessibility-profile>.
  5. For this element, type the following expression which will hold the accessibility profile value (e.g., high-contrast, large-font) passed from the AccessibilityModeBean. In this demonstration, that specifically would be:
    • <accessibility-profile>#{accessibility.accessibilityProfile}/accessibility-profile>
  6. The default value blafplus-rich for the element name <skin-family> should already exist in the file.

A skin is a style sheet based on the CSS 3.0 syntax specified in trinidad-config.xml for the entire application. Instead of providing a style sheet for each component, or inserting a style sheet on each page, one skin is created for the entire application. Every component automatically uses the styles as described by the skin. No design time code changes are required. In this demo a skin provided by Oracle ADF Faces blafplus-rich is used. Oracle ADF Faces provided skins can be extended to provide a custom skin. For example, a custom skin for large font UIs.

Specify Navigation Rules

Add the following to the faces-config.xml file.

<navigation-rule>
    <navigation-case>
      <from-outcome>accessibility</from-outcome>
      <to-view-id>/SetAccessibility.jspx</to-view-id>
     
      <!--
        Note that we always redirect when navigating to the
        accessibility preferences page to ensure that screen
        reader users get a fresh page load.  Otherwise, we
        may ppr-nav to the accessibility preferences page,
        which may not be ideal for screen reader users
        running in the default accessibility mode (eg. no
        virtual buffer flush).
      -->
      <redirect/>
    </navigation-case>
  </navigation-rule>
    <!-- A managed bean that we use to track accessibility mode preference. -->
  <managed-bean>
    <managed-bean-name>accessibility</managed-bean-name>
    <managed-bean-class>sample.accessibility.AccessibilityPreferences</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>

  <!--
    A managed bean that holds onto the user's accessibility preferences while
    editing these value on the Accessibility Preferences page.  Note that unlike
    the session-scoped AccessibilityPreferences bean, this bean only requires
    request-scope, since it is only holding the values for a short time (for
    the life of one request).
  -->
  <managed-bean>
    <managed-bean-name>accessibilityHolder</managed-bean-name>
    <managed-bean-class>sample.accessibility.AccessibilityPreferencesHolder</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>

    <!--
      We use a managed-property to inject the AccessibilityPreferences
      instance into our holder.  This allows the holder both to determine
      its initial values as well as apply back any changes.
    -->
   
    <managed-property>
      <property-name>accessibilityPreferences</property-name>
      <value>#{accessibility}</value>
    </managed-property>
  </managed-bean>
  <application>
    <default-render-kit-id>oracle.adf.rich</default-render-kit-id>
  </application>

Create Task Flows and JSP Files

Two ADF jsp files (i.e., jspx) based on the template created earlier will be added to the application workspace. One will represent, for demonstration purposes only, any ADF application page an unauthenticated user is allowed to visit. The second, will represent the accessibility preference page navigated to by the Accessibility Global link. Two ADF task flows will be created. One will show the default accessibility mode when the application is visited and the updated values to the accessibility mode once set by the user. The other will allow the user to set the accessibility mode. These will be added to the landing page and the accessibility preference page, respectively.

Creating the "Landing" Page for the Unauthenticated User

  1. Open the context menu on guestAccessViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select JSF.
  4. From the JSF category, select JSF Page.
  5. Type ShowAccessibility.jspx for the File Name.
  6. Leave Create as XML Document (*.jspx) checked.
  7. Select the Page Template radio control.
  8. The ExampleTemplate4AccessibilityPatternDef1.jspx file should show in the drop down. Select it.
  9. Click OK.
  10. In the Structure Window, expand the tree to reveal the document node. Select it.
  11. In the Style and Theme section of the Property Inspector, type or select dark for the Theme property.
  12. Save the file.

Create the Accessibility Preference Page for the Unauthenticated User

  1. Open the context menu on guestAccessViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select JSF.
  4. From the JSF category, select JSF Page.
  5. Type SetAccessibility.jspx for the File Name.
  6. Leave Create as XML Document (*.jspx) checked.
  7. Select the Page Template radio control.
  8. The ExampleTemplate4AccessibilityPatternDef1.jspx file should show in the drop down. Select it.
  9. Click OK.
  10. In the Structure Window, expand the tree to reveal the document node. Select it.
  11. In the Style and Theme section of the Property Inspector, type or select dark for the Theme property.
  12. Save the file.

Create the Show Accessibility Mode Task Flow

  1. Open the context menu on guestAccessViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select JSF.
  4. From the JSF category, select JSF Page Fragment.
  5. Type ShowAccessibilityMode.jsff for the File Name.
  6. In the Directory field, append the path to read:
    • C:\JDeveloper\mywork\AccessibilityGlobalLink\guestAccessViewController\public_html\WEB-INF\fragments

      This is a convenience to improve the workspace organization.

  7. Leave Blank Page checked.
  8. Click OK.
  9. From the Component Palette, drag and drop a Panel Group Layout into the page
  10. In the Common Area of the Property Inspector, set the Layout property of the Panel Group Layout component to Scroll.
  11. In the Visual Editor, drop a Panel Header layout component inside the Panel Group Layout component.
  12. In the common section of the Property Inspector, change the Text field from panelHeader 1 to Show Accessibility Mode.
  13. In the Visual Editor, drop a Panel Box inside the Panel Group Layout.
  14. In the Property Inspector change the Text field from PanelBox1 to Settings.
  15. In the Visual Editor, drop a Panel Form Layout inside the Panel Box
  16. While input focus remains inside of the Panel Form Layout, click on the Input Text component in the Component Palette 3 times.
  17. Select the first Input Text component and change its Label to Screen Reader.
  18. In the Property Inspector, type the following expression for the Value property: #{accessibilityHolder.screenReader}
  19. In the Behavior section, set ReadOnly to true.
  20. Select the second Input Text component and change its Label to High Contrast Colors.
  21. In the Property Inspector, type the following expression for the Value property: #{accessibilityHolder.highContrast}
  22. In the Behavior section, set ReadOnly to true.
  23. Select the third Input Text component and change its Label to Large Font.
  24. In the Property Inspector, type the following expression for the Value property: #{accessibilityHolder.largeFonts}
  25. In the Behavior section, set ReadOnly to true.
  26. Save the file.
  27. Open the context menu on guestAccessViewController.
  28. Select New.
  29. In the New Gallery under Web Tier, select JSF.
  30. From the JSF category, select ADF Task Flow.
  31. Type ShowAccessibilityModeTF for the File Name.
  32. In the Directory field, append the path to read:
    • C:\JDeveloper\mywork\AccessibilityGlobalLink\guestAccessViewController\public_html\WEB-INF\taskflows

      This is a convenience to improve the workspace organization.

  33. Leave both Create as Bounded Task Flow and Create with Page Fragments checked.
  34. Click OK.
  35. From the Application Navigator, drag and drop the ShowAccessibilityMode.jsff file into the ShowAccessibilityModeTF diagram.

    The fragment should display as the default activity.

  36. Save and close the file.

Create the Set Accessibility Preference Task Flow

  1. Open the context menu on guestAccessViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select JSF.
  4. From the JSF category, select JSF Page Fragment.
  5. Type accessibilityPref.jsff for the File Name.
  6. In the Directory field, append the path to read:
    • C:\JDeveloper\mywork\AccessibilityGlobalLink\guestAccessViewController\public_html\WEB-INF\fragments

      This is a convenience to improve the workspace organization.

  7. Leave Blank Page checked.
  8. Click OK.
  9. From the Component Palette, drag and drop a Panel Group Layout into the page
  10. In the Common Area of the Property Inspector, set the Layout property of the Panel Group Layout component to Scroll.
  11. In the Visual Editor, drop a Panel Header layout component inside the Panel Group Layout component.
  12. In the common section of the Property Inspector, change the Text field from panelHeader 1 to Accessibility Preferences.
  13. From the Operations Accordion of the Component Palette, drag and drop a Skip Link Target inside the Panel Header layout
    • Simply place the af:skipLinkTarget tag inside of an ADF Faces component somewhere after the repeated contents. ADF Faces automatically generates a 'skip link' at the start of the page. Using the Tab key to begin navigation reveals this tag in the page. Activating this link skips over any contents before the skipLinkTarget.

      In this case, activating this component would vector that user to the first input component within the Panel Header.

  14. In the Property Inspector type the following into the AccessibilityHint field: Activate this link to skip to content.

    The value of this property would be accessible to the user of a screen reader. This provides additional encouragement to the user to activate the link. Sighted users would see the default, "Skip to Content." text.

  15. In the Visual Editor, drop a Panel Box inside the Panel Header layout.
  16. In the Property Inspector change the Text field from PanelBox1 to Edit Accessibility Settings.
  17. In the Visual Editor, drop a Panel Form Layout inside the Panel Box.
  18. From the Component Palette, drag and drop a Output Formatted into the page.
  19. In the Common section of the Property Inspector type: Any setting must be made for each browser session. or any other appropriate language to inform the user that the duration of any settings made here is for the current browser session.
  20. Select instruction for StyleUsage in the Property Inspector.
  21. In the Component Palette, select the Spacer component once.
  22. In the common section of the Property Inspector, type 5, in the Height field.
  23. In the Component Palette, select the Select Boolean Check box component three times.
  24. Select the first Select Boolean Check box component in the Form Layout.
  25. In the Common section of the Property Inspector, type the following in the Value field:
    • #{accessibilityHolder.screenReader}.
  26. In the Appearance section of the Property Inspector, type Screen reader for the Text property.
  27. Select the second Select Boolean Check box component in the Form Layout.
  28. In the Common section of the Property Inspector, type the following in the Value field:
    • #{accessibilityHolder.highContrast}.
  29. In the Appearance section of the Property Inspector, type High contrast for the Text property.
  30. Select the third Select Boolean Check box component in the Form Layout.
  31. In the Common section of the Property Inspector, type the following in the Value field:
    • #{accessibilityHolder.largeFonts}.
  32. In the Appearance section , type the following for Text: Large fonts.
  33. From the Component Palette, drag and drop a Panel Group Layout into the Form Layout footer facet.
  34. Set the Layout property to horizontal.
  35. In the Component Palette, select the Button component twice.
  36. Select the left button.
  37. Type OK for the Text property.
  38. In the Button Action subsection of the Common section, select #{accessibilityHolder.ok} for the Action property.
  39. Select the right button.
  40. Type Cancel for the Text property.
  41. In the Button Action subsection of the Common section, select #{accessibilityHolder.cancel} for the Action property.
  42. Save the file.
  43. Open the context menu on guestAccessViewController.
  44. Select New.
  45. In the New Gallery under Web Tier, select JSF.
  46. From the JSF category, select ADF Task Flow.
  47. Type accessibilityPrefTF for the File Name.
  48. In the Directory field, append the path to read:
    • C:\JDeveloper\mywork\AccessibilityGlobalLink\guestAccessViewController\public_html\WEB-INF\taskflow

      This is a convenience to improve the workspace organization.

  49. Leave both Create as Bounded Task Flow and Create with Page Fragments checked.
  50. Click OK.
  51. From the Application Navigator, drag and drop the accessibilityPref.jsff file into the accessibilityPrefTF diagram.

    The fragment should display as the default activity.

  52. Save and close the file.

Add Taskflows as Regions to Pages

  1. In the Editor pane of the IDE, select the tab for the page SetAccessibility.jspx.
    • Check that the Property Inspector has focus on the SetAccessibility.jspx page template.

      The title bar of the Property Inspector should display: /template/ExampleTemplate4Set AccessibilityPatternDef1.jspx

  2. In the Other section of the Property Inspector, type the following in the mode field: accessibility.

    The Property Inspector displays the template attributes and their default values in the Other section of the Property Inspector.

    By setting the mode attribure to accessibility, the Accessibility global link will not appear in the page. This avoids potential recursive calls to the page by the user and a confusing UI.

  3. From the Application Navigator, drag and drop the accessibilityPrefTF into the Local Area facet of SetAccessibility.jspx.
  4. In the Create popup, select Region.

    The UI for accessibilityPref.jsff should appear.

  5. Save the file.
  6. In the Editor pane of the IDE, select the tab for the page ShowAccessibility.jspx.
  7. From the Application Navigator, drag and drop the ShowAccessibilityModeTF into the Local Area facet of ShowAccessibility.jspx.
  8. In the Create popup, select Region.

    The UI for ShowAccessibilityMode.jsff should appear.

  9. Save the application workspace.
  10. Open a context menu on the ShowAccessibility.jspx page within the Visual Editor or or on its node in the Structure Window.
  11. Select Run.

Instead of completing these step, an ADF sample application on OTN called GuestAccessibilityImplementation is available at http://www.oracle.com/technetwork/developer-tools/adf/guestaccessibilityimplementation-128452.zip can be unzipped into the designated JDeveloper work area. Open GuestAccessibility.jws with JDeveloper.


Related Topics

Oracle Accessibility Program at http://www.oracle.com/accessibility

Section 508 at http://www.section508.gov

W3C Web Content Accessibility Guidelines at http://www.w3.org/TR/WAI-WEBCONTENT/

 

Copyright © 1997, 2010, Oracle. All rights reserved.