Accessibility Global Link

An Oracle JDeveloper Best Practices Document
September, 2009

Best Practices

Accessibility Global Link

Best Practices  Revision

1.4

Technologies

JDeveloper, ADF, ADF Faces

Keywords

Sign In, Login, Accessibility, Branding, Global Link, Accessible Guest Browsing, ADF Version

Forum

Functional UI Pattern Team

Publish date

September, 2009

Contents

Overview

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

Laws and regulations that 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 (keyboard only)
  • the product must be usable by a blind user (with a screen reader or braille reader)
  • there must be no reliance on sound
  • there must be no reliance on color
  • there must be no reliance on animation or timing

All functionality, other than install and initial configuration ('one-time' events), meets 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 following provided ADF Faces accessibility guidelines for component specific, and page and navigation structures is useful, it is not a substitute for familiarity with accessibility standards and performing accessibility testing with assistive technology. In concert, UI 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 the accessibility level. The thorny UI question is how -- particularly for users of screen readers?  Setting the ADF default to screenReader would degrade the output for non-disabled users and disable access keys used by other assistive technology. The ADF default as is does not fully support users of screen readers which means ADF pages would be inaccessible.

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 (i.e., guest) user. A frequent example are eCommerce sites. Unauthenticated, users can browse product catalogs, comparison shop, and in some cases even 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.

Another possible solution is to write the unauthenticated portion of the application in HTML and the authenticated portion in ADF. The two major issues with that approach is the limitation on the use of compelling ADF UI features in the unauthenticated experience. The other is the much higher development cost, maintenance costs, and cost of ownership.

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

Technical Pattern Description

The Accessibility Global Link UI Functional 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 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 is accessible to disabled users. It is the user of a screen reader where the focus lies. However, not all ADF components are inaccessible to screen readers at the default accessibility level. The initial application page visited by all users should be composed of those components. Selecting the correct components is part of the challenge. The balance is the task of writing an effective UI with a limited set of components.


This constraint could result in highly deprived user experience among rich client solutions. Attempting to constrain access to the application to a single, "stripped down" page dedicated to this role is of itself highly challenging and annoying to users. One means of overcoming this is to realize that many, if not virtually all, web sites and applications have boilerplate UI or chrome -- used to provide the user with a sense of context and 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 points or pages, the chrome, as well as the accessibility control embedded within it, must be ubiquitous. ADF page templates 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 have 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. In our solution, one of those global controls would be a link to an accessibility page where in a user could set the preferred accessibility level. See Example Template Chrome.

Example Template Chrome

A user of a screen reader would use the keyboard to tab through the branding to reach the Accessibility global link. That link could also contain descriptive text communicated by the screen reder 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 chrome and all other UI content to the list of selectable options. See examples below.
Example of Set Accessibility without Chrome


Example of Set Accessibility with Chrome


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 HTML 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, the context it provides for users, while at the same time increasing the probability that the user of a screen reader will 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 focus from the branding, in this example, to a control that once activated by the user (i.e., presses 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 ADF components), the concern need only be that the UI control are those 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 be 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 are best. 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 returns 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 UI functional 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 button, 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 as a session-scope managed bean with the name "accessibility" in faces-config.xml (see below). It can be accessed via the EL expression #{accessibility}.
User Interface Elements
  • ExampleTemplate4AccessibilityPatternDef1
    • An ADF template file upon which the jsp 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. It also contains best practice UI design and ADF components to use for the chrome at the top of the page. The template is made available to the demonstration application through an ADF Library jar.
  • 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 jsp page based on the ExampleTemplate4AccessibilityPatternDef1 template that demonstrates the initial page accessed by the user. It shows the selected accessibility mode.
  • SetAccessibility.jspx
    • Example jsp page based on the ExampleTemplate4AccessibilityPatternDef1 template that demonstrates setting the accessibility preference. It also shows 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 jsp pages and task flows for showing and setting the accessibility preference.

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. Select the New icon to create a new application workspace.
    • There will be no need for the Model project in this sample.
  2. In the New Gallery dialog, select Fusion Web Application (ADF) from the Application Category.
  3. Press Ok
  4. In the Create Fusion Web Application wizard, type GuestAccessibility or other appropriate name for the Application Name.
  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. Press 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. Select the check box to use a Quick Start Layout.
  14. Press Browse.
  15. Select the 3 column layout icon in the left side navigator.
  1. Within the 3 column layout category, select the icon that shows all partitions locked.
    • The locks simply mean that this selected layout does not come with pre-inserted Splitters. In other words, a Panel Stretch Layout.
  1. Optionally, user defined names can be given for each of the facets (i.e., the locked partitions of the layout).
  2. Select the Attribute tab at the bottom of the Create JSF Page Template dialog.
  3. Press the Add icon (i.e., green plus symbol) five times.
  4. Type the following attribute names: type, default values, and required state.
    • Attribute Name Type Default Value* Required
      globalBrandingSize int 55 false
      regionalBrandingSize 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.
  1. Press OK
  2. In the Structure Pane (SP), select the panelStretchLayout.
  3. Select the Center facet of the panelStretchLayout in the Visual Editor (VE)
  4. From the Layout accordion of the Component Palette (CP), select  the Panel Splitter to add it to the facet.
    1. 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.
  5. In the Common section of the PI, set the Orientation to vertical.
  6. In the Behavior section of the PI, 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 VE, select the First facet of the Panel Splitter.
  2. From the Layout accordion of the Component Palette (CP), select  the Panel Group Layout to add it to the facet.
  3. In the Common section of the PI, set the Layout to scroll.
  4. With input focus on the panelGroupLayout, select the Panel Border Layout from the Layout accordion of the CP.
  5. In the Style section of the PI, select the Property Menu control (V) 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. Press OK.
  9. With input focus on the panelBorderLayout, select another Panel Border Layout from the Layout accordion of the CP.
  10. With input focus on the nested panelBorderLayout, select Image from the Common accordion of the CP.
  11. In the Common section of the PI, 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 PI, select the Property Menu control (V) 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. Press OK.
  16. In the SP, 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 CP.
  19. In the Common section of the PI, set the Orientation to vertical.
  20. In the Style section of the PI, select the Property Menu control (V) 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 CP.
  2. In the Common section of the PI, 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, press twice on the Navigation Item from the Common accordion of the CP.
  4. In the Common section of the PI 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 PI, 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. 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.
    • In the Text subsection of the Appearance section of the PI, type the following or other appropriate text for the ShortDesc property:
      • Edit accessibility preferences that are in effect for this HTTP session.
Adding other Global Links
  1. Select the second commandNavigationItem
  2. In the Common section of the PI, type Help for the Text property value.
    • In the Text subsection of the Appearance section of the PI, type the following or other appropriate text for the ShortDesc property:
      • Guest User Help
Completing the Design of the Branding Bar
  1. In the SP, select the parent panelBorderLayout in the First facet of the panelSplitter.
  2. In the SP, 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 CP.
  5. In the Common section of the PI, set the Orientation to horizontal.
  6. With input focus on the panelGroupLayout , select Progress Indicator from the Common accordion of the CP.
  7. In the SP, select the innerEnd facet.
  8. With input focus on the innerEnd facet , select Spacer from the Layout accordion of the CP.
  9. In the SP, select the innerStart facet.
  10. With input focus on the innerStart facet , select Panel Group Layout from the Layout accordion of the CP.
  11. In the Style section of the PI, select the Property Menu control (V) 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. Press 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 CP.
  17. In the Common section of the PI, type the following expression for the Value property:
    • #{attrs.brandingTitle}
  18. In the Style section of the PI, select the Property Menu control (V) 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. Press OK.
  22. In the SP, select the Start facet.
  23. With input focus on the Start facet , select Panel Group Layout from the Layout accordion of the CP.
  24. In the Style section of the PI, select the Property Menu control (V) 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. Press 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 CP.
  30. In the Appearance section of the PI, 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 your case. 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. The downloadable template will look as follows.

Example Content Areas of Application Template with Accessibility Global Link

  1. In the VE, 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 CP, 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 CP, drag and drop a Panel Splitter into the Center facet of the Panel Stretch Layout.
  5. In the Common section of the PI, 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 VE, 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 CP, select  Panel Stretch Layout to add it to the first facet.
  8. In the Common section of the PI. set the:
    • StartWidth to 0px
    • BottomHeight to 0px
  9. In the VE, select the Center facet of the Panel Stretch Layout
  10. From the Common accordion of the CP, drag and drop a Facet Ref to add it to the Center facet.
  11. In the PI, type RegionalArea for the FacetName.
  12. In the VE, 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 CP, select  Panel Stretch Layout to add it to the second facet.
  14. In the Common section of the PI, set the StartWidth to 0px.
  15. In the VE, select the Center facet of the Panel Stretch Layout.
  16. From the Layout accordion of the CP, 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 PI, type the following expression for the SplitterPosition value:
    • #{attrs.contextualSplitterSize}
  18. In the VE, 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 CP, drag and drop a Facet Ref to add it to the first facet.
  20. In the PI, type LocalArea for the FacetName.
  21. In the VE, 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 CP, drag and drop a Facet Ref to add it to the second facet.
  23. In the PI, 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 SP, select the outermost (i.e., parent) panelStretchLayout
  2. Select the Bottom facet of the panelStretchLayout.
  3. From the Layout accordion of the Component Palette (CP), 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 CP.
  5. In the SP, expand the Panel Border Layout facets.
  6. From the CP, drag and drop the Panel Group Layout onto the End facet within the Panel Border Layout Facets.
  7. From the Common accordion of the CP, drag and drop a Facet Ref onto the panelGroupLayout component in the SP
  8. In the PI, type appAboutappPrivacy for the FacetName.
  9. From the CP, drag and drop the Panel Group Layout onto the Start facet within the Panel Border Layout Facets.
  10. From the Common accordion of the CP, drag and drop a Facet Ref onto the panelGroupLayout component in the SP.
  11. In the PI, type appCopyright for the FacetName.

Unless components are added to these facets (e.g., Links), they will not show specifically when the template is used. 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. Press OK.

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

AccessibilityPreferencesHolder.java
/* Copyright (c) 2009, 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. Press OK.
  6. The following is taken from the 11.1.1.1.0 release of the ADF Demo war
AccessibilityPreferences.java
/* Copyright (c) 2008, 2009, 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.

faces-config.xml
<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. Press OK.
  10. In the SP, expand the tree to reveal the document node. Select it.
  11. In the Style and Theme section of the PI, type 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. Press OK.
  10. In the SP, expand the tree to reveal the document node. Select it.
  11. In the Style and Theme section of the PI, type 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. Leave Blank Page checked.
  7. Press OK.
  8. From the Component Palette, drag and drop a Panel Group Layout into the page
  9. In the Common Area of the PI, set the Layout property of the Panel Group Layout component to Scroll.
  10. In the Visual Editor, drop a Panel Header layout component inside the Panel Group Layout component.
  11. In the common section of the PI, change the Text field from panelHeader 1 to Show Accessibility Mode.
  12. In the Visual Editor, drop a Panel Box inside the Panel Group Layout.
  13. In the PI change the Text field from PanelBox1 to Settings.
  14. In the Visual Editor, drop a Panel Form Layout inside the Panel Box
  15. While input focus remains inside of the Panel Form Layout, click on the Input Text component in the Component Palette 3 times.
  16. Select the first Input Text component and change its Label to Screen Reader.
  17. In the PI, type the following expression for the Value property: #{accessibilityHolder.screenReader}
  18. In the Behavior section, set ReadOnly to true.
  19. Select the second Input Text component and change its Label to High Contrast Colors.
  20. In the PI, type the following expression for the Value property: #{accessibilityHolder.highContrast}
  21. In the Behavior section, set ReadOnly to true.
  22. Select the third Input Text component and change its Label to Large Font.
  23. In the PI, type the following expression for the Value property: #{accessibilityHolder.largeFonts}
  24. In the Behavior section, set ReadOnly to true.
  25. Save the file.
  26. Open the context menu on guestAccessViewController.
  27. Select New.
  28. In the New Gallery under Web Tier, select JSF.
  29. From the JSF category, select ADF Task Flow.
  30. Type ShowAccessibilityModeTF for the File Name.
  31. Leave both  Create as Bounded Task Flow and Create with Page Fragments checked.
  32. Press OK.
  33. From the Application Navigator, drag and drop the ShowAccessibilityMode.jsff file into the ShowAccessibilityModeTF diagram.
    • The fragment should display as the default activity.
  34. 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. Leave Blank Page checked.
  7. Press OK.
  8. From the Component Palette, drag and drop a Panel Group Layout into the page
  9. In the Common Area of the PI, set the Layout property of the Panel Group Layout component to Scroll.
  10. In the Visual Editor, drop a Panel Header layout component inside the Panel Group Layout component.
  11. In the common section of the PI, change the Text field from panelHeader 1 to Accessibility Preferences.
  12. From the Operations Accordion of the CP, 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.
  13. In the PI 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.
  14. In the Visual Editor, drop a Panel Box inside the Panel Header layout.
  15. In the PI change the Text field from PanelBox1 to Edit Accessibility Settings.
  16. In the Visual Editor, drop a Panel Form Layout inside the Panel Box.
  17. From the Component Palette, drag and drop a Output Formatted  into the page.
  18. In the Common section of the PI 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.
  19. Select instruction as the StyleUsage in the PI.
  20. In the Component Palette, select the Spacer component once.
  21. Type 5, in the Height field
  22. In the Component Palette, select the Select Boolean Check box component three times.
  23. Select the first Select Boolean Check box component in the Form Layout.
  24. In the Common section of the PI,  type the following in the Value field: #{accessibilityHolder.screenReader}.
  25. In the Appearance section , type the following for Text: Screen reader.
    • As with all other such components, it is important to also provide text for the ShortDesc property in the Appearance section that would be accessible to the screen reader user in the default accessibility mode. For example, "Toggle screen reader mode."
  26. Select the second Select Boolean Check box component in the Form Layout.
  27. In the Common section of the PI,  type the following in the Value field: #{accessibilityHolder.highContrast}.
  28. In the Appearance section , type the following for Text: High contrast.
  29. Select the third Select Boolean Check box component in the Form Layout.
  30. In the Common section of the PI,  type the following in the Value field: #{accessibilityHolder.largeFonts}.
  31. In the Appearance section , type the following for Text: Large fonts.
  32. From the Component Palette, drag and drop a Panel Group Layout  into the Form Layout footer facet.
  33. Set the Layout property to horizontal.
  34. In the Component Palette, select the Button component twice.
  35. Select the left button.
  36. Type OK for the Text property.
  37. In the Button Action subsection of the Common section, select #{accessibilityHolder.ok}.
  38. Select the right button.
  39. Type Cancel for the Text property.
  40. In the Button Action subsection of the Common section, select #{accessibilityHolder.cancel}.
  41. Save the file.
  42. Open the context menu on guestAccessViewController.
  43. Select New.
  44. In the New Gallery under Web Tier, select JSF.
  45. From the JSF category, select ADF Task Flow.
  46. Type accessibilityPrefTF for the File Name.
  47. Leave both  Create as Bounded Task Flow and Create with Page Fragments checked.
  48. Press OK.
  49. From the Application Navigator, drag and drop the accessibilityPref.jsff file into the accessibilityPrefTF diagram.
    • The fragment should display as the default activity.
  50. 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 PI has focus on the SetAccessibility.jspx page template.
      • The title bar of the PI should display: /template/ExampleTemplate4SetAccessibilityPatternDef1.jspx
  2. In the Other section of the PI,  type the following in the mode field: accessibility.
    • The PI displays the template attributes and their default values in the Other section of the PI.
    • 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.

Known Issues

  • None

Related Documentation

External resources on Accessibility

Appendix

In order to test this pattern out, included is a JDeveloper 11g application called GuestAccessibility that can be unzipped into the designated work area and opened from within JDeveloper, Simply download GuestAccessibility.zip, unzip the archive, open the GuestAccessibility.jws with JDeveloper.

E-mail this page
Printer View Printer View
Software. Hardware. Complete. About Oracle | Oracle and Sun| Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy