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.
Create the template used by the application to
contain the Accessibility Global Link and the ADF skipLink component.
Create
java beans.
Edit trindidad-config to specify the default
skin, accessibility mode and profile.
Specify the navigation rules between the
calling page and the accessibility preference page in faces-config.xml.
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
Select the New
icon to create a new application workspace.
There will be no need for the Model project
in this sample.
In the New Gallery dialog, select Fusion Web
Application (ADF) from the Application Category.
Press Ok
In the Create Fusion Web Application wizard,
type GuestAccessibility
or other appropriate name for the Application Name.
For project names, type guestAccessModel
and guestAccessViewController
for the
Model and ViewController respectively, or other appropriate names.
For Application Package Prefix, type oracle.adfdemo.view.
Press Finish.
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
Under JSF select JSF
Page Template.
In the Create
JSF Page Template dialog, type ExampleTemplate4AccessibilityPatternDef1.jspx
or other appropriate name for the template.
Select the check box to use a Quick Start Layout.
Press Browse.
Select the 3
column layout icon in the left side navigator.
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.
Optionally, user defined names can be given for
each of the facets (i.e., the locked partitions of the layout).
Select the Attribute tab at the bottom of the Create JSF Page Template
dialog.
Press the Add
icon (i.e., green plus symbol)
five times.
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.
Press OK
In the Structure Pane (SP), select the panelStretchLayout.
Select the Center
facet of the
panelStretchLayout in the Visual Editor (VE)
From the Layout accordion of the Component
Palette (CP), 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.
In the Common section of the PI, set the
Orientation to vertical.
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
In the VE, select the First
facet of the
Panel Splitter.
From the Layout accordion of the Component
Palette (CP), select the Panel
Group Layout to add it to the
facet.
In the Common section of the PI, set the Layout
to scroll.
With input focus on the panelGroupLayout,
select the Panel Border
Layout
from the Layout accordion of the CP.
In the Style section of the PI, select the Property Menu
control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBar
from Available Classes to Selected Classes.
Press OK.
With input focus on the panelBorderLayout,
select another Panel
Border Layout
from the Layout accordion of the CP.
With input focus on the nested
panelBorderLayout, select
Image
from the Common accordion of the CP.
In the Common section of the PI, type the
following expression in the Source property:
In the Style section of the PI, select the
Property Menu control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBarItem and AFStretchWidth
from Available Classes to Selected Classes.
Press OK.
In the SP, expand the panelBorderLayout Facets
of the nested panelBorderLayout.
Select the End
facet.
With input focus on the End facet, select Panel Group
Layout from the Layout accordion of the CP.
In the Common section of the PI, set the
Orientation to vertical.
In the Style section of the PI, select the Property Menu
control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBarItem
from Available Classes to Selected Classes.
Adding the Accessibility
Global Link
With input focus on the nested panelGroupLayout
, select Navigation Pane
from
the Layout accordion of the CP.
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.
With input focus on the navigationPane, press
twice on the Navigation
Item
from the Common accordion of the CP.
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.
Type Accessibility
for the Text property value.
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.
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
Select the second commandNavigationItem
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
In the SP, select the parent panelBorderLayout
in the First facet of the panelSplitter.
In the SP, expand the panelBorderLayout facets.
Select the End
facet.
With input focus on the End facet , select Panel Group
Layout from the Layout accordion of the CP.
In the Common section of the PI, set the Orientation to horizontal.
With input focus on the panelGroupLayout ,
select Progress Indicator
from
the Common accordion of the CP.
In the SP, select the innerEnd
facet.
With input focus on the innerEnd facet , select Spacer
from the Layout accordion of the CP.
In the SP, select the innerStart
facet.
With input focus on the innerStart facet ,
select Panel Group Layout
from
the Layout accordion of the CP.
In the Style section of the PI, select the
Property Menu control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBarItem
from Available Classes to Selected Classes.
Press OK.
For the InlineStyle property, type the
following:
background-color: white;
With input focus on the panelGroupLayout, select Output Text from
the Common
accordion of the CP.
In the Common section of the PI, type the
following expression for the Value property:
#{attrs.brandingTitle}
In the Style section of the PI, select the Property Menu
control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBarTitle
from Available Classes to Selected Classes.
Press OK.
In the SP, select the Start
facet.
With input focus on the Start
facet , select Panel
Group Layout from the Layout
accordion of the CP.
In the Style section of the PI, select the Property Menu
control (V) of the StyleClass property.
In the Property Menu, select Edit.
In the Edit
Property: StyleClass, shuttle AFBrandingBarItem
from Available Classes to Selected Classes.
Press OK.
For the InlineStyle property, type the
following: background-color:
white;
With input focus on the panelGroupLayout, select Spacer from the
Layout accordion of
the CP.
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
In the VE, select the Second
facet of the Panel
Splitter.
This would be the lower half of the page
template
From the Layout accordion of the CP,
select Panel
Stretch Layout
to add it to the facet.
In the Common section of the PI. set the:
StartWidth to 3
EndWidth to 3
TopHeight to 1em
From the Layout accordion of the CP, drag and
drop a Panel Splitter
into the Center facet
of the Panel Stretch
Layout.
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.
In the VE, select the first
facet of the Panel
Splitter.
This is the leftmost section of the lower
half referred to earlier.
From the Layout accordion of the CP,
select Panel
Stretch Layout
to add it to the first facet.
In the Common section of the PI. set the:
StartWidth to 0px
BottomHeight to 0px
In the VE, select the Center
facet of the Panel
Stretch Layout
From the Common accordion of the CP, drag and
drop a Facet Ref
to add it to
the Center facet.
In the PI, type RegionalArea
for the FacetName.
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.
From the Layout accordion of the CP,
select Panel
Stretch Layout
to add it to the second facet.
In the Common section of the PI, set the
StartWidth to 0px.
In the VE, select the Center
facet of the Panel
Stretch Layout.
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.
In the Common section of the PI, type the
following expression for the SplitterPosition value:
#{attrs.contextualSplitterSize}
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.
From the Common accordion of the CP, drag and
drop a Facet Ref
to add it to
the first facet.
In the PI, type LocalArea
for the FacetName.
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.
From the Common accordion of the CP, drag and
drop a Facet Ref
to add it to
the second facet.
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.
In the SP, select the outermost (i.e., parent)
panelStretchLayout
Select the Bottom
facet of the
panelStretchLayout.
From the Layout accordion of the Component
Palette (CP), select the Panel
Group Layout to add it to the
facet.
With input focus on the panelGroupLayout ,
select Panel Border
Layout
from the Layout accordion of the CP.
In the SP, expand the Panel
Border Layout
facets.
From the CP, drag and drop the Panel Group
Layout onto the End
facet
within the Panel Border Layout Facets.
From the Common accordion of the CP, drag and
drop a Facet Ref
onto the
panelGroupLayout component in the SP
In the PI, type appAboutappPrivacy
for the
FacetName.
From the CP, drag and drop the Panel Group
Layout onto the Start
facet
within the Panel Border Layout Facets.
From the Common accordion of the CP, drag and
drop a Facet Ref
onto the
panelGroupLayout component in the SP.
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.
Open the context menu on guestAccessViewController.
Select New.
In the Create Java Class, type AccessibilityPreferencesHolder.
Type sample.accessibility
for the Package name or other appropriate package name.
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. */
/**
* 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();
}
/**
* 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();
// 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;
// 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;
// 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
In the Application Navigator, double click
trinidad.xml to open the file in the XML editor.
Type the element name <accessibility-mode>.
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:
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:
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.
<!--
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.
-->
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
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select JSF Page.
Type ShowAccessibility.jspx
for the File Name.
Leave Create
as XML Document (*.jspx) checked.
Select the Page
Template radio control.
The
ExampleTemplate4AccessibilityPatternDef1.jspx file should
show
in the drop down. Select it.
Press OK.
In the SP, expand the tree to reveal the document
node. Select it.
In the Style and Theme section of the PI, type dark for the Theme
property.
Save the file.
Create the
Accessibility Preference Page for the Unauthenticated User
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select JSF Page.
Type SetAccessibility.jspx
for the File Name.
Leave Create
as XML Document (*.jspx) checked.
Select the Page
Template radio control.
The
ExampleTemplate4AccessibilityPatternDef1.jspx file should
show
in the drop down. Select it.
Press OK.
In the SP, expand the tree to reveal the document
node. Select it.
In the Style and Theme section of the PI, type dark for the Theme
property.
Save the file.
Create the Show
Accessibility Mode Task Flow
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select JSF Page Fragment.
Type ShowAccessibilityMode.jsff
for the File Name.
Leave Blank
Page checked.
Press OK.
From the Component Palette, drag and drop a Panel Group
Layout into the page
In the Common Area of the PI, set the Layout
property of the Panel Group Layout component to Scroll.
In the Visual Editor, drop a Panel Header
layout component inside the Panel Group Layout component.
In the common section of the PI, change the
Text field from panelHeader 1 to Show
Accessibility Mode.
In the Visual Editor, drop a Panel Box inside
the Panel Group Layout.
In the PI change the Text field from PanelBox1
to Settings.
In the Visual Editor, drop a Panel Form Layout
inside the Panel Box
While input focus remains inside of the Panel
Form Layout, click on the Input
Text
component in the Component Palette
3 times.
Select the first Input
Text component and
change its Label to Screen
Reader.
In the PI, type the following expression for
the Value property: #{accessibilityHolder.screenReader}
In
the
Behavior section, set ReadOnly
to true.
Select the second Input
Text component and
change its Label to High
Contrast
Colors.
In the PI, type the following expression for
the Value property: #{accessibilityHolder.highContrast}
In
the
Behavior section, set ReadOnly
to true.
Select the third Input
Text component and
change its Label to Large
Font.
In the PI, type the following expression for
the Value property:
#{accessibilityHolder.largeFonts}
In
the
Behavior section, set ReadOnly
to true.
Save the file.
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select ADF Task Flow.
Type ShowAccessibilityModeTF
for the File Name.
Leave both
Create as Bounded Task Flow and Create with Page Fragments
checked.
Press OK.
From the Application Navigator, drag and drop
the ShowAccessibilityMode.jsff
file
into the ShowAccessibilityModeTF
diagram.
The fragment should display as the default
activity.
Save and close the file.
Create the Set
Accessibility Preference Task Flow
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select JSF Page Fragment.
Type accessibilityPref.jsff
for the File Name.
Leave Blank
Page checked.
Press OK.
From the Component Palette, drag and drop a Panel Group
Layout into the page
In the Common Area of the PI, set the Layout
property of the Panel Group Layout component to Scroll.
In the Visual Editor, drop a Panel Header
layout component inside the Panel Group Layout component.
In the common section of the PI, change the
Text field from panelHeader 1 to Accessibility
Preferences.
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.
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.
In the Visual Editor, drop a Panel Box inside
the Panel Header layout.
In the PI change the Text field from PanelBox1
to Edit Accessibility
Settings.
In the Visual Editor, drop a Panel Form Layout
inside the Panel Box.
From the Component Palette, drag and drop a Output Formatted
into the page.
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.
Select instruction
as the StyleUsage in the PI.
In the Component Palette, select the Spacer
component once.
Type 5,
in the Height field
In the Component Palette, select the Select
Boolean Check box component three times.
Select the first Select
Boolean Check box
component in the Form Layout.
In the Common section of the PI, type the
following in the Value field: #{accessibilityHolder.screenReader}.
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."
Select the second Select
Boolean Check box
component in the Form Layout.
In the Common section of the PI, type the
following in the Value field: #{accessibilityHolder.highContrast}.
In the Appearance section , type the following
for Text: High contrast.
Select the third Select
Boolean Check box
component in the Form Layout.
In the Common section of the PI, type the
following in the Value field: #{accessibilityHolder.largeFonts}.
In the Appearance section , type the following
for Text: Large fonts.
From the Component Palette, drag and drop a Panel Group Layout
into the
Form Layout footer facet.
Set the Layout property to horizontal.
In the Component Palette, select the Button
component twice.
Select the left button.
Type OK for
the Text property.
In the Button Action subsection of the Common
section, select #{accessibilityHolder.ok}.
Select the right button.
Type Cancel for
the Text property.
In the Button Action subsection of the Common
section, select #{accessibilityHolder.cancel}.
Save the file.
Open the context menu on guestAccessViewController.
Select New.
In the New Gallery under Web Tier, select JSF.
From the JSF category, select ADF Task Flow.
Type accessibilityPrefTF
for the File Name.
Leave both
Create as Bounded Task Flow and Create with Page Fragments
checked.
Press OK.
From the Application Navigator, drag and drop
the accessibilityPref.jsff
file
into the accessibilityPrefTF
diagram.
The fragment should display as the default
activity.
Save and close the file.
Add Taskflows as
Regions to Pages
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
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.
From the Application Navigator, drag and drop
the accessibilityPrefTF
into the Local Area
facet of SetAccessibility.jspx
.
In the Create popup, select Region.
The UI for accessibilityPref.jsff should
appear.
Save the file.
In the Editor pane of the IDE, select the tab
for the page ShowAccessibility.jspx.
From the Application Navigator, drag and drop
the ShowAccessibilityModeTF
into the Local Area
facet of ShowAccessibility.jspx.
In the Create popup, select Region.
The UI for ShowAccessibilityMode.jsff should
appear.
In order to test this pattern out,
included is a JDeveloper 11g application called GuestAccessibilitythat
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.