AccDC Technical Style Guide

The AccDC Technical Style Guide is designed to provide reliable and consistent interaction designs that are accessible to the highest percentage of people possible, and to establish a baseline for Functional Accessibility that can be utilized, built upon, studied, and tested against.

Supported by the Royal Society of Arts AccDC was awarded the "Above and Beyond Accessibility Award" from the United States Department of Labor, and was presented at the Developing with Accessibility Event, hosted by the Federal Communications Commission in Washington DC in 2012.

Functional Accessibility means that each component is fully accessible from the keyboard, with or without a screen reader running.

All of the AccDC Technical Style Guide design patterns have been fully tested for maximum accessibility using all of the following combinations:

  • Strictly from the keyboard with no mouse and no screen reader running.
  • Using NVDA and JAWS 11+> in IE8 with Win XP.
  • Using NVDA and JAWS 12+> in IE 9 and 10 with Win7.
  • Using NVDA and JAWS 14+> in IE 10 with Win8.
  • Using NVDA and JAWS 12+> in FF with Win XP, Win7, and Win8.
  • Using VoiceOver in Safari with iOS on the iPhone/iPad.
  • Using Dragon Naturally Speaking in IE and FF with Win7 and Win8 via standard keyboard interaction commands.

AccDC Technical Style Guide Mirrors:

Please address any direct questions to Bryan Garaventa, or to the Accessible Innovators Group for community support.

AccDC API

Downloads
AccDC Details

AccDC is a JavaScript based Application Programming Interface (API) that can be used with other libraries and frameworks, or by itself, to create new or enhance pre-existing web technologies with accessible features.

This is accomplished by utilizing the AccDC API properties and methods, and by leveraging the features that are available within all instantiated AccDC Objects.

AccDC Objects

The primary purpose of the AccDC API, is to recursively process AccDC Objects, which are rendered as encapsulated dynamic content components.

The majority of AccDC API properties and methods are prototyped within every AccDC Object, making every AccDC Object fully autonomous and programmatically configurable using JavaScript.

This is how AccDC Objects can dynamically control the behaviors of other AccDC Objects at runtime.

An AccDC Object is literally an instantiated JavaScript Object, which stores all relevant data and AccDC API properties and methods within it.

The shell construct of an AccDC Object declaration is as follows:

var myObjArray = [
{
id: 'uniqueObjectId',
role: 'Object Role Name'
// Other AccDC API property and method declarations go here...
}
];

The array of AccDC Object declarations is passed as a parameter to the $A() function, which instantiates them as registered AccDC Objects.

$A(myObjArray);

All instantiated AccDC Objects are then registered within the $A.reg associative array, which can be queried directly using the ID of each AccDC Object in order to reference, configure, and control specific objects using JavaScript.

Example:

var dc = $A.reg['uniqueObjectId'];

Or

var dc = $A.reg.uniqueObjectId;

An instantiated AccDC Object can then be programmatically configured by modifying or invoking properties and methods within the object instance.

Examples:

// Set literal content to be rendered

dc.source = 'Hello World';

// Set the body as the container insertion point

dc.isStatic = 'body';

// Prepend the rendered content to the body content instead of replacing

dc.prepend = true;

// Set a top level class name for the newly rendered container Div  element

dc.className = 'banner';

dc.runAfter = function(dc){
// Do something after the content finishes loading
};

// Render the new content

dc.open();

Alternatively, all of the above property and method declarations can be included within the object literal declaration, before the object array is passed to the $A() function.

Example:

var myObjArray = [
{
id: 'uniqueObjectId',
role: 'Object Role Name',
source: 'Hello World',
isStatic: 'body',
prepend: true,
className: 'banner',
runAfter: function(dc){
// Do something after the content finishes loading
},
runAfterClose: function(dc){
// Do something after the content finishes closing
},
// Render the object immediately
autoStart: true,
// Automatically announce the rendered textual content for screen reader users
announce: true
}
];

// Then register the object array

$A(myObjArray);

All AccDC API properties and methods are applicable to AccDC Objects, and are confined within the scope of that object.

To learn about sibling and global overrides for AccDC Objects, view the details about the $A() function within the AccDC Core API documentation.

AccDC Objects can also be used to store specific data that relates only to that object, which can then be accessed by other AccDC Objects.

Example:

// Save data within one AccDC Object

dc.tmp = {
form: formElement
};

// Then access the data from another AccDC Object or process

var dataString = serialize( $A.reg.uniqueObjectId.tmp.form.elements );

All data stored within an AccDC Object remains within the object, even after the "close()" method is used to close the object and remove its content from the DOM.

Only the "$A.destroy()" method will completely destroy an AccDC Object and all of its stored data.

All of the Accessible Component Modules tap into this functionality by interfacing with the AccDC API.

Debugging Mode

If, for some reason an AccDC Object is not rendering properly when the open() method is invoked, Debugging Mode can be used to diagnose the cause of the issue.

Example:

// Enable Debugging Mode

$A.fn.debug = true;

When set to true, this will throw an alert with specific instructions if the issue is caused by a lack of or improper combination of AccDC API properties.

Debugging Mode is set to false by default.

Loading AccDC

Currently there are four versions of the AccDC API available:

  1. The Standalone version, which requires no third party dependencies and is compatible with all JavaScript libraries and frameworks without conflict.
  2. The jQuery extension, which requires jQuery 1.8.3 or greater.
  3. The Dojo module, which uses the Dojo AMD Loader.
  4. The MooTools extension, which requires MooTools 1.4.5 or greater.

Since all Accessible Component Modules plug into the AccDC API, the same module code will work correctly in all AccDC API versions equally.

Example using the Standalone, jQuery, or MooTools AccDC versions:

<head>

<!-- If using the AccDC jQuery or MooTools extension, load jQuery or MooTools here first. -->

<script type="text/javascript" src="Acc.DC.API.js">
// Load AccDC, which will create the $A namespace
</script>

<script type="text/javascript" src="module_name.js">
// Load as many of the Accessible Component Modules as desired,
// which will add them to the $A namespace.
</script>

<script type="text/javascript" src="setup.js">
// Then load the setup script to invoke module functionality after the page finishes loading.
</script>

</head>

Example using Dojo:

<head>

<script type="text/javascript" src="dojo/dojo.js" data-dojo-config="async:true">
// Load Dojo asynchronously.
</script>

<script type="text/javascript">

// Configure AccDC modules and scripts to be loaded synchronously for flow control
InitAccDC = [
'module1.js',
'module2.js'
];

// Now load the AccDC API using the Dojo AMD Loader
// The referenced AccDC API file is located at dojo/acc.dc.api.js
require(['dojo/acc.dc.api']);

</script>

</head>

This will set up AccDC, and load all of the declared modules into the $A namespace, ready for use within your web application.

AccDC Bootstrap

If the AccDC Bootstrap module is also loaded, then there is no need to include a setup script.

All configurations are controlled through HTML5 attributes within the markup and by editing the "accdc_bootstrap.js" file as desired to customize functionality.

When the Bootstrap Module is executed, it parses the newly loaded DOM, recognizes class names that correspond with specific Accessible Component Modules, then configures and invokes the specified module using HTML5 attributes within the markup to customize both output and behavior.

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

To enable this functionality, simply load the AccDC Bootstrap module after all of the desired Accessible Component Modules have been loaded.

Example using the Standalone, jQuery, or MooTools AccDC API versions:

<head>

<!-- If using the AccDC jQuery or MooTools extension, load jQuery or MooTools here first. -->

<script type="text/javascript" src="Acc.DC.API.js">
// Load AccDC, which will create the $A namespace
</script>

<script type="text/javascript" src="module_name.js">
// Load as many of the Accessible Component Modules as desired,
// which will add them to the $A namespace.
</script>

<script type="text/javascript" src="accdc_bootstrap.js">
// Then load AccDC Bootstrap to parse the DOM automatically
</script>

</head>

Example using Dojo:

<head>

<script type="text/javascript" src="dojo/dojo.js" data-dojo-config="async:true">
// Load Dojo asynchronously.
</script>

<script type="text/javascript">

// Configure AccDC modules and scripts to be loaded synchronously for flow control
InitAccDC = [
'module1.js',
'module2.js',
// Then load AccDC Bootstrap to parse the DOM automatically
'accdc_bootstrap.js'
];

// Now load the AccDC API using the Dojo AMD Loader
// The referenced AccDC API file is located at dojo/acc.dc.api.js
require(['dojo/acc.dc.api']);

</script>

</head>
Offscreen Text

Some modules refer to offscreen text, which can be used to provide textual information for screen reader users that is not displayed visually and has no impact on visual layout.

The following CSS class has been proven to work well for this purpose, which is the same that is built into AccDC as the "$A.sraCSS" object.

.offscreenText {
position: absolute;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px; 
width: 1px; 
overflow: hidden;
z-index: -1000;
}

This styling configuration is based on the research done by Thierry Koblentz, which is more fully described at
http://developer.yahoo.com/blogs/ydn/posts/2012/10/clip-your-hidden-content-for-better-accessibility/

Accessible Component Modules

Accordions

Accordions are a fairly simple control type that are easy to make accessible.

Though similar in both concept and execution to Tab Controls, they are not the same.

A Tab Control has a series of grouped triggering elements that expand and collapse, the rendered content of which is inserted directly after the triggering element group when opened. The container element insertion point for all Tab Control triggering elements is shared between them. Also, the group of triggering elements in a Tab Control has only one tab stop. The arrow keys are then used to switch focus between each Tab, and the Enter or Space key is used to expand the desired Tab content panel.

In contrast, an Accordion has a series of triggering elements that expand and collapse, the rendered content of which is inserted directly after the triggering element when opened. The container element insertion points for Accordions are not shared. Also, all Accordion links appear in the tab order. The reason why ARIA attributes such as role="tablist" and role="tab" are not included within accordions, is because the insertion of inline content would place dynamic content sections within the same Tablist container, making it impossible to determine the order of nested Tab controls when present within the inserted content.

The chosen implementation should always match the UI that it's being applied to, to prevent confusion.

The Accordion Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

Referencing external content:

<div class="accordionGroup">
<a href="#" class="accAccordion" data-src="files/accordions.html#containerId1" data-insert="sectId1" data-defaultopen="true"  id="accordionId1">
Triggering Element One Name
</a>
<div id="sectId1"><!--
(accordionId1 content will be inserted here when opened)
--></div>
<a href="#" class="accAccordion" data-src="files/accordions.html#containerId2" data-insert="sectId2" id="accordionId2">
Triggering Element Two Name
</a>
<div id="sectId2"><!--
(accordionId2 content will be inserted here when opened)
--></div>
</div>

Or referencing internal content:

<div class="accordionGroup2">
<a href="#" class="accAccordion" data-internal="containerId1" data-insert="x-sectId1" data-defaultopen="true"  id="x-accordionId1">
Triggering Element One Name
</a>
<div id="x-sectId1"><!--
(x-accordionId1 content will be inserted here when opened)
--></div>
<a href="#" class="accAccordion" data-internal="containerId2" data-insert="x-sectId2" id="x-accordionId2">
Triggering Element Two Name
</a>
<div id="x-sectId2"><!--
(x-accordionId2 content will be inserted here when opened)
--></div>
</div>

HTML5 "data-" attributes are used to configure specific functionality for each accordion expand/collapse link. These include the following:

  • data-src : The resource path and pointer to the ID attribute of the accordion content container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the accordion content container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-insert : The ID attribute of the container element where the accordion content will be inserted when rendered. (This must not be inside the triggering element)
  • data-defaultopen="true" : Specifies that the referenced accordion node will open automatically. Only one accordion node per group should include this attribute.

Required attributes:

  • All accordion triggering elements must include unique ID attribute values.

Important: The insertion point where accordion content is rendered must be inline with (meaning directly after) the triggering element, to ensure accessibility for screen reader and keyboard only users. (No other active elements or page content should separate them.)

The examples above use DIV tags as container elements, but it doesn't really matter what the container element is, as long as the IDs match up. For instance, the interactive samples in the Coding Arena use DL tags as the main container, DTs to hold the triggering element, and DDs to act as the insertion points, which works well and is easy to format.

Container Element HTML Syntax

<div id="containerId1">
Accordion panel 1 content goes here.
</div>

<div id="containerId2">
Accordion panel 2 content goes here.
</div>

JavaScript

$A.generateAccordion( 'div.accordionGroup a.accAccordion' , {
// Configuration key / value mappings
}, document , callbackFunction(dc){
// Run every time an accordion expand/collapse link is toggled
// 'dc' is the registered Accordion AccDC Object
// dc.triggerObj is the triggering element
// dc.containerDiv is the DOM node where all accordion panel content is rendered
// dc.loaded reflects whether the accordion panel is currently open
} );

Parameters

  1. The first parameter is a CSS Selector that specifies all accordion expand/collapse links that are part of the same accordion group.

    If multiple accordions are present on the same page, each accordion should be declared separately using the above statement, and the CSS Selector should only reference the expand/collapse node links that apply to that particular accordion, and to no other.

    The reason for this is simple. When an accordion is active, it will close all open accordion nodes when an expand link is activated. So if you don't want all of the nodes of every other accordion on the page to be closed at the same time as well, then you should separate them using unique CSS Selectors for each group.

  2. The second parameter is used to configure accordion functionality using key / value map overrides.

    Example:

    {
    
    // Set the hidden text role and state that will be added to the triggering element for screen reader users
    accordionRole: 'Accordion',
    accordionState: 'Expanded',
    
    // Set the accordion AccDC Object to render literal content
    // (only when pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Preload HTML markup to speed rendering
    // (only when pulling content from an external page, remove otherwise)
    preload: true,
    
    // Preload images to speed rendering
    // (only when pulling content from an external page, remove otherwise)
    preloadImages: true,
    
    // Set the class name that will be added to the triggering element of the currently open accordion
    toggleClass: 'open',
    
    // Choose whether or not to make accordion expand/collapse links toggles as well
    isToggle: false
    
    // Additional AccDC API properties and methods may be applied here as well if desired.
    
    }
    
  3. The third parameter (contextDOM_Node) specifies the container DOM node where the accordion is contained, which confines the CSS Selector to the contents of this node. This can also be used to reference accordion groups contained within iFrame documents.

  4. The fourth parameter is a callback function that can be used to configure additional functionality whenever an accordion is opened or closed.

Programmatic Control

Every accordion node is registered as an AccDC Object, the ID of which matches the ID attribute value on the accordion expand/collapse link. For this reason, all accordion expand/collapse links must have unique ID attribute values.

This means that you can programmatically control each accordion node using JavaScript if desired, like so:

// Get a reference to the accordion AccDC Object for the accordion expand/collapse link with id="uniqueId"
var dc = $A.reg['uniqueId'];

// Now invoke the object
dc.open();

// Or close it
dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

Regarding the triggering element for expand/collapse links, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the Coding Arena samples, these are standard links (A tags with an Href attribute), which includes a SPAN tag with a changeable background image. However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling. There must be an active element as a triggering element though, to ensure accessibility.

Styling

The sample accordions in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the accordion. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled accordion will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The accordions within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accAccordion", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-src : The resource path and pointer to the ID attribute of the accordion content container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the accordion content container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-defaultopen="true" : Specifies that the referenced accordion node will open automatically. Only one accordion node per group should include this attribute.
  • data-role : The role name that is conveyed to screen reader users within the accordion link. "Accordion" is set by default if no value is specified.
  • data-openstate : The open state text that is conveyed to screen reader users within the accordion link when open. "Expanded" is set by default if no value is specified.
  • data-insert : The ID attribute of the container element where accordion node content will be inserted. The referenced container element must not be included within the accordion link node.
  • data-group : The shared group name for all related nodes within an accordion. This is used to differentiate separate accordion groups within the same document.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes for the triggering element:

  • class="accAccordion" : The bootstrap class name that specifies an accessible accordion node.
  • id : The unique ID of the element. This value is also registered as the ID of the individual accordion node AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.
ARIA Tabs

Tabs are a fairly simple control type that are easy to make accessible.

Though similar in both concept and execution to Accordions, they are not the same.

An Accordion has a series of triggering elements that expand and collapse, the rendered content of which is inserted directly after the triggering element when opened. The container element insertion points for Accordions are not shared. Also, all Accordion links appear in the tab order. The reason why ARIA attributes such as role="tablist" and role="tab" are not included within accordions, is because the insertion of inline content would place dynamic content sections within the same Tablist container, making it impossible to determine the order of nested Tab controls when present within the inserted content.

In contrast, a Tab Control has a series of grouped triggering elements that expand and collapse, the rendered content of which is inserted directly after the triggering element group when opened. The container element insertion point for all Tab Control triggering elements is shared between them. Also, the group of triggering elements in a Tab Control has only one tab stop. The arrow keys are then used to switch focus between each Tab, and the Enter or Space key is used to expand the desired Tab content panel.

The chosen implementation should always match the UI that it's being applied to, to prevent confusion.

The Tab Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

Referencing external content:

<div role="tablist" id="tabList1">
<div>
<a href="#" class="accTab" data-src="files/tabs.html#containerId1" data-insert="tabPanelId" data-defaultopen="true"  id="tabId1" role="tab">
<span>Triggering Element One Name</span>
</a>
</div>
<div>
<a href="#" class="accTab" data-src="files/tabs.html#containerId2" data-insert="tabPanelId" id="tabId2" role="tab">
<span>Triggering Element Two Name</span>
</a>
</div>
</div>

<div id="tabPanelId"><!--
(All Tab panel content will be inserted here when a Tab is opened)
--></div>

Or referencing internal content:

<div role="tablist" id="tabList2">
<div>
<a href="#" class="accTab" data-internal="containerId1" data-insert="tabPanelId2" data-defaultopen="true"  id="x-tabId1" role="tab">
<span>Triggering Element One Name</span>
</a>
</div>
<div>
<a href="#" class="accTab" data-internal="containerId2" data-insert="tabPanelId2" id="x-tabId2" role="tab">
<span>Triggering Element Two Name</span>
</a>
</div>
</div>

<div id="tabPanelId2"><!--
(All Tab panel content will be inserted here when a Tab is opened)
--></div>

HTML5 "data-" attributes are used to configure specific functionality for each Tab expand/collapse link. These include the following:

  • data-src : The resource path and pointer to the ID attribute of the Tab content container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the Tab content container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-insert : The ID attribute of the container element where the Tab content will be inserted when rendered. (This must not be inside the triggering element, and must be the same for all Tab links within the same group)
  • data-defaultopen="true" : Specifies that the referenced Tab panel will open automatically. (Only one Tab link per group should include this attribute.)

Required attributes:

  • role="tablist" must be included within the container element (where all Tab links are contained).
  • role="tab" must be included within all Tab links.
  • Both the Tablist container element (with role="tablist") and all Tab links (with role="tab") must include unique ID attribute values.

Important: The insertion point where Tab panel content is rendered must be inline with (meaning directly after) the Tablist group, to ensure accessibility for screen reader and keyboard only users. (No other active elements or page content should separate them.)

The examples above use DIV tags as container elements, but it doesn't really matter what the container element is, as long as the IDs match up. For instance, the interactive samples use standard list markup to group related Tab links, which works well and is easy to format.

Container Element HTML Syntax

<div id="containerId1">
Tab panel 1 content goes here.
</div>

<div id="containerId2">
Tab panel 2 content goes here.
</div>

The following attributes are handled automatically by the Tab Module:

  • tabindex
  • aria-label
  • aria-owns
  • aria-selected
  • aria-expanded
  • aria-posinset
  • aria-setsize

JavaScript

$A.setTabs( 'div.tabGroup a.accTab' , {
// Configuration key / value mappings
}, useARIA? , document ,
function(dc){
// Optional callback to execute after a Tab panel opens
// 'this' is the same as dc.triggerObj, and is the DOM node for the triggering element
// dc.containerDiv is the DOM container node that contains the newly loaded Tab panel content.
} );

Parameters

  1. The first parameter is a CSS Selector that specifies all Tab expand/collapse links that are part of the same Tablist group.

    If multiple Tablist groups are present on the same page, each Tablist should be declared separately using the above statement, and the CSS Selector should only reference the expand/collapse node links that apply to that particular Tablist, and to no other.

    The reason for this is simple. When a Tab panel is opened, it will close all other Tab panels when an expand link is activated. So if you don't want all of the nodes of every other Tablist group on the page to be closed at the same time as well, then you should separate them using unique CSS Selectors for each group.

  2. The second parameter is used to configure Tab functionality using key / value map overrides.

    Example:

    {
    
    // Set the Tab panel boundary text that will be conveyed to screen reader users
    role: 'Tab',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set the Tab AccDC Object to render literal content
    // (only when pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Preload HTML markup to speed rendering
    // (only when pulling content from an external page, remove otherwise)
    preload: true,
    
    // Preload images to speed rendering
    // (only when pulling content from an external page, remove otherwise)
    preloadImages: true,
    
    // Set a className that will be added to the triggering element for the currently active tab
    toggleClass: 'active',
    
    // Choose whether or not to make Tab expand/collapse links toggles as well
    isToggle: false
    
    // Additional AccDC API properties and methods may be applied here as well if desired.
    
    }
    
  3. The third parameter (useARIA?) is a Boolean (true or false), that specifies whether the Tab Control will be configured as an ARIA Tab widget.
    If true, role="tablist" and role="tab" must be present within the markup in the correct locations.
    If false, role="tablist" and role="tab" must not be included within the markup.

    Important: The ARIA attributes role="tablist" and role="tab" must only be used on client side widgets that don't require a page refresh or navigate to another page.
    The reasons why are fully discussed in the article at http://lnkd.in/5nPudh

  4. The fourth parameter (contextDOM_Node) specifies the container DOM node where the Tablist markup is contained, which confines the CSS Selector to the contents of this node. This can also be used to reference Tab groups contained within iFrame documents.

  5. The fifth parameter is a callback function that can be used to configure additional functionality whenever a Tab panel finishes rendering.

Programmatic Control

Every Tab panel is registered as an AccDC Object, the ID of which matches the ID attribute value on the Tab expand/collapse link. For this reason, all Tab expand/collapse links must have unique ID attribute values.

This means that you can programmatically control each Tab panel using JavaScript if desired, like so:

// Get a reference to the Tab AccDC Object for the Tab expand/collapse link with id="uniqueId"
var dc = $A.reg['uniqueId'];

// Now invoke the object
dc.open();

// Or close it
dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

Regarding the triggering element for expand/collapse links, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the Coding Arena samples, these are standard links (A tags with an Href attribute). However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling. There must be an active element as a triggering element though, to ensure accessibility.

If using an image link however, the IMG tag must have a null Alt attribute (alt="") to hide it from screen reader users, and offscreen text must be included if no visible screen text is present. This will ensure the highest level of accessibility for the highest percentage of screen reader users across all platforms.

Styling

The sample Tabs in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the Tablist. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled Tablist will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The Tablists within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accTab", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-src : The resource path and pointer to the ID attribute of the tab content container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the tab panel container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-defaultopen="true" : Specifies that the referenced tab will open automatically. Only one tab per group should include this attribute.
  • data-role : The role name that is conveyed to screen reader users as beginning and ending boundary text for the tab panel content. "Tab" is set by default if no value is specified.
  • data-insert : The ID attribute of the container element where tab panel content will be inserted.
  • data-group : The shared group name for all related tabs. This is used to differentiate separate tab groups within the same document.
  • data-headinglvl : The heading level of the tab panel section for screen reader users. This should reflect proper nesting. If the tab panel content is inserted within an H1, data-headinglvl should be set to '2', and so on. If no value is specified, and if no override is set within accdc_bootstrap.js via ariaLevel:#, '3' will be set by default.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes for the triggering element:

  • role="tablist" : The ARIA role that specifies a group of tab controls. This must only be included within the element that contains all individual tabs.
  • role="tab" : The ARIA role that specifies an individual tab control. To ensure accessibility, this element must not contain any other active elements.
  • class="accTab" : The bootstrap class name that specifies an accessible Tab link.
  • id : The unique ID of the element. This value is also registered as the ID of the individual Tab AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.

Implementation Notes

As an ARIA widget implementation, the Tablist container element must include the attribute role="tablist", and all Tab item links must include the attribute role="tab" to ensure accessibility for screen reader users.

Both the Tablist container element and all Tab item links must include unique ID attribute values.

The innerHTML for each Tab item link must contain a textual label, which may be positioned offscreen to hide it visually if desired. (This textual label is necessary so that screen reader users will be able to identify the purpose of the node, and also to ensure proper feedback in iOS devices when using VoiceOver.)

Images may also be used within Tab item links if desired, however, they must include the attribute alt="" to hide them from screen reader users.

To add tooltips for sighted users, use the Title attribute instead, and make sure that the tooltip text matches the text contained within the textual label if positioned offscreen to hide it visually.

ARIA Data Grids

An ARIA Data Grid is one of the most complicated of ARIA Widget types to make accessible, since it involves many different types of user interaction.

Expected behaviors: The entire grid should have only one tab stop, one cell should be focusable at a time, the arrow keys should move focus between cells, Home and End should move focus to the beginning or end of a row, PageUp and PageDown should open the previous or next page of the grid, Alt+PageUp and Alt+PageDown should move focus to the first or last page in the grid, Space and Enter should activate the current cell or row, and textual equivalents should indicate the role and state of each interactive control type for screen reader users.

The Data Grid Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

<div id="gridContainerId" ></div>

The following attributes are handled automatically by the Data Grid Module:

  • tabindex
  • aria-owns
  • role=grid
  • role=rowgroup
  • role=row
  • role=gridcell
  • role=columnheader
  • role=rowheader
  • aria-rowindex
  • aria-colindex
  • aria-labelledby
  • aria-describedby
  • aria-selected
  • title
  • aria-hidden

JavaScript

var grid = new $A.DataGrid( ContainerNodeOrID );

Parameters

  1. The first parameter specifies the container element where the data grid will be rendered, and may be a DOM node or an ID string.

Programmatic Control

// Set the registered columns including unique IDs and label text
// The order of items in the array will dictate the default column ordering when rendered

grid.mapColumnNames([
{
// ID that is associated with all cells in the column
id: 'col1id',
// The text that will be rendered as the column header
lbl: 'User Name',
// Set an optional class to be added to all cells within the column
colClass: 'col1'
},
{
id: 'col2id',
lbl: 'Email Address',
colClass: 'col2'
},
{
id: 'col3id',
lbl: 'Publish Record',
colClass: 'col3'
}
]);

// Programmatically change the order of rendered columns
// This method rearanges the array order of the objects passed to grid.mapColumnNames(ObjArray)
// Which is used to determine rendering order
// This must be followed by grid.open() to rerender the grid after a change is made

// E.G Change the third column to the first column
grid.changeColumnOrder(2, 0);

// Enable row headers and specify the column ID to be used for this purpose
// This must be followed by grid.open() to rerender the grid after a change is made

grid.enableRowHeaders(true, 'col1id');
// Or disable
grid.enableRowHeaders(false);

// Set a maximum number of rows to render before pagination is applied
// If set to 0, all records will render and no pagination will occur
// This must be followed by grid.open() to rerender the grid after a change is made

grid.setRowMax(25);

// Enable or disable editability for grid cells
// This will render an edit field for strings or handle toggle events for buttons.
// This must be followed by grid.open() to rerender the grid after a change is made

grid.editable(true);
// Or to disable
grid.editable(false);

// Add rows to a grid instance

grid.add(rowObject_or_rowObjectArray);

// Each row must adhere to the following object literal format:

{

id: 'uniqueRowId',

cells: {

'col1id': {
// Set the cell type, may be either 'text' or 'toggle'
// Defaults to 'text' if omitted
type: 'text',
// Set an optional readonly flag to disable editability if the grid is editable
// Defaults to false if omitted
readonly: true,
// Set the initial value of the cell
value: 'My User Name'
},

'col2id': {
value: 'email_address@whatever.com'
},

'col3id': {
type: 'toggle',
readonly: false,
value: true,
// For toggles, set the name property to specify a visual textual label
name: 'Published',
// For toggles, specify an optional class to be added when the toggle is set to true
// This will override the general toggle class specified within grid.setStaticClasses
toggleClass: 'toggle-button-pressed'
}

}

}

// Set a value changed listener for handling serverside posting when cell values change

grid.setChangeListener(function(originalCellObject, newValue, rowObject, gridInstance){
// rowObject reflects the same object passed to grid.add
// so that rowObject.id reflects the original unique row ID
// originalCellObject reflects the cell object instance passed within 'cells' when passed to grid.add
// and cellObject.id reflects the column ID, so that rowObject.id and cellObject.id can be used as X Y coordinates to identify the correct cell in the grid.
// Compare originalCellObject.value with newValue to perform input validation or other processes.
// To prevent rendering the changed input or new toggle state, simply return false
});

// Enable or disable double click or single click mouse interaction for selectable rows and editable cells
// This must be followed by grid.open() to rerender the grid after a change is made
// When set to false, a single mouse click will toggle selectability or trigger an edit action

grid.useDblClick(false);

// Enable or disable row selectability
// This must be followed by grid.open() to rerender the grid after a change is made
// When set to true, editability will automatically be set to false to prevent functionality and keyboard accessibility conflicts

grid.setSelect({
enable: true,
// Set a class to be added to the TR node every time a row is selected
toggleClass: 'selected',
// Set single or multiSelect
multiSelect: false,
// Use ARIA for selection or cross-platform offscreen text instead
// Important: The use of aria-selected for row selection is not well supported by screen readers at this time
ariaSelect: false,
// Choose whether rendering another page will automatically unselect previously selected rows
// Set to false to unselect rows automatically, or true to keep selection active
preserve: false,
// Set a callback to execute every time a row is toggled
callback: function(rowObject, state, prevSelectedRowsArray, gridInstance){
// rowObject is the activated row object.
// rowObject.rowNode is the TR DOM node for the toggled row.
// 'state' reflects the proposed state change, which is the opposite of rowObject.selected.
// prevSelectedRowsArray is an array of all previously selected rowObjects, not counting the current rowObject.
// To cancel the toggle action, return false
}
});

// Or pass single properties to set functionality

grid.setSelect({
enable: false
});

// Unselect all previously selected rows

grid.unselectAll();

// Select all rows on the currently rendered page

grid.selectAll();

// Get an array of all currently selected rowObjects
// Each rowObject reflects the same object literal passed in grid.add()

// Get an array of selected rowObjects
var selected = grid.getSelected(),
// Get the row ID for the first selected row
rowId = selected[0].id,
// Or get the TR DOM node of the first selected row
rowNode = selected[0].rowNode;

// Programmatically select one or more rows using an array of row IDs

grid.select(['rowId1', 'rowId2']);

// Enable or disable row deletion
// This must be followed by grid.open() to rerender the grid after a change is made
// When enabled, the Delete key will delete all currently selected rows from the grid and destroy their rowObjects in the cache
// Selectability must be set to true for this functionality to be used

grid.setDelete({
enable: true,
// Set a function to execute prior to deletion
runBefore: function(selectedRowIDs_array){
// Return false to cancel deletion
},
// Set a callback to execute on every row that is deleted
callback: function(rowObject, gridInstance){
// rowObject.id is the table row ID that is being deleted
// alert(rowObject.id);
// return false to cancel deletion from the grid
},
// Set a function to execute after deletion is completed
runAfter: function(deletedRowIDs_array){
// Do something
}
});

// Or to disable

grid.setDelete({
enable: false
});

// Programmatically delete all currently selected rows and destroy their rowObjects in the cache

grid.deleteRows();

// Programmatically delete one or more rows and destroy their rowObjects in the cache using an array of row IDs

grid.deleteRows(['rowId1', 'rowId2']);

// Programmatically delete all rows in the grid instance and destroy their rowObjects in the cache

grid.deleteAllRows();

// set accessible text for screen reader users

grid.setAccessibleText({
// Set offscreen and tooltip text for toggle cells
toggleButtonRole: 'Toggle Button',
toggleButtonState: 'Pressed',
disabledText: 'Disabled',
// Set the page text to be announced to screen reader users during infinite scrolling. E.G "Page 2", "Page 3", etc.
pageRole: 'Page',
// Set the active state and help tooltip text for mouse users
selectState: 'Selected',
editLinkAction: 'Editable',
dblClickTitle: 'Click to activate',
// Set the title text for the edit field
editFieldTitle: 'Press Enter to save, or Escape to cancel.'
});

// Set static classes

grid.setStaticClasses({
// General Table element class for the grid
gridClass: 'data-grid',
// Additional Table element class when the grid is set to Readonly
gridReadOnlyClass: 'data-grid-readonly',
// Additional Table element class when the grid is set to Editable
gridEditableClass: 'data-grid-editable',
// Additional Table element class when the grid is set to Selectable
gridSelectableClass: 'data-grid-selectable',
// General TR element class for the grid
gridRowClass: 'data-grid-row',
// Additional TR element class when a grid row has focus
gridRowFocusedClass: 'data-grid-row-focused',
// General TH and TD element class for the grid
gridCellClass: 'data-grid-cell',
// Additional TD element class when a grid cell is set to Readonly
cellReadOnlyClass: 'data-grid-cell-readonly',
// Additional TD element class when a grid cell has focus
gridCellFocusedClass: 'data-grid-cell-focused',
// General STRONG element class for grid text cells
gridCellLinkClass: 'data-grid-cell-link',
// General STRONG element class for grid toggle cells
gridCellToggleClass: 'data-grid-cell-toggle',
// Additional STRONG element class for grid toggle cells when set to True
gridCellTogglePressedClass: 'data-grid-cell-toggle-pressed',
// General DIV and INPUT element class for grid edit field popups
editFieldClass: 'data-grid-cell-link-edit'
});

// Get the total number of rows in the grid instance

grid.totalRows();

// Pagination: Get the current page number

grid.currentPage();

// Pagination: Get the total number of pages in the grid instance

grid.totalPages();

// Set a page index changed listener to execute every time the current or total number of pages changes within the grid instance

grid.setPageIndexChangeListener(function(currentPage, totalPages, gridInstance){
// Do something
});

// Open a specific page without rerendering the parent grid

grid.openPage(number);

// Open the first page in the grid

grid.firstPage();

// Open the previous page in the grid

grid.prevPage();

// Open the next page in the grid

grid.nextPage();

// Open the last page in the grid

grid.lastPage();

// Execute listener every time a grid object is opened in the DOM

grid.setOpenListener(function(container, dc, gridInstance){
// 'dc' is the grid AccDC Object
});

// Execute listener every time a grid object is closed in the DOM

grid.setCloseListener(function(container, dc, gridInstance){
// 'dc' is the grid AccDC Object
});

// Execute listener every time a grid TR object is rendered in the DOM

grid.setAddListener(function(rowObject, dc, gridInstance){
// rowObject.id is the unique row ID as passed in grid.add()
// rowObject.rowNode is the rendered TR DOM node
// 'dc' is the grid AccDC Object
});

// Execute listener every time a grid TR object is removed from the DOM

grid.setRemoveListener(function(rowObject, dc, gridInstance){
// rowObject.id is the unique row ID as passed in grid.add()
// rowObject.rowNode is the rendered TR DOM node
// 'dc' is the grid AccDC Object
});

// Execute listener every time a grid TD node receives focus

grid.setMoveListener(function(newCell, oldCell, dc, gridInstance){
// 'newCell' is the TD DOM node that has been given focus
// 'oldCell' is the TD DOM node that used to have focus
// 'dc' is the grid AccDC Object
});

// Assign a character maxLength value for the edit text popup

grid.setEditMaxLength(255);

// Set a positioning override for the placement of the edit text popup
// Must return an object literal that contains the following properties: top, left, width, height

grid.setEditOffset(function(cellObject){
// cellObject.cellNode is the DOM node for the TD element that has focus
// cellObject.cellNodeA is the DOM node for the STRONG element contained within the TD element that has focus
var o = $A.xOffset(cellObject.cellNodeA); // Get top and left properties
o.height = $A.xHeight(cellObject.cellNodeA); // Add height
o.width = $A.xWidth(cellObject.cellNodeA); // Add width
return o;
});

// Set an edit field load listener to execute every time the string edit field is opened for a cell

grid.setEditLoadListener(function(editFieldNode, cellObject){
// editFieldNode is the rendered edit Input element
// cellObject is the cellObject that was triggered, providing access to all data associated with that cell
// E.G
// cellObject.cellNode is the actionable TD node that was activated
// cellObject.value is the original value of the cell
// cellObject.id is the column id for that cell
// cellObject.rowObject.id is the unique row ID for that row
// cellObject.rowObject.rowNode is the TR node for that row
});

// Set the value of a specific cell in the grid using its unique row ID and column ID as X Y coordinates
// Row ID refers to the same value stored within rowObject.id, and col ID refers to the same value stored within cellObject.id

grid.setValue('rowID', 'colID', value);

// Get the value of a specific cell in the grid using its unique row ID and column ID as X Y coordinates
// Row ID refers to the same value stored within rowObject.id, and col ID refers to the same value stored within cellObject.id

grid.getValue('rowID', 'colID');

// Programmatically store data within a specific cell in the grid using its unique row ID and column ID as X Y coordinates
// Row ID refers to the same value stored within rowObject.id, and col ID refers to the same value stored within cellObject.id
// When set, the data is alternatively available within the cellObject via cellObject.data['keyname']

grid.setData('rowID', 'colID', 'keyname', data);

// Programmatically retrieve data within a specific cell in the grid using its unique row ID and column ID as X Y coordinates
// Row ID refers to the same value stored within rowObject.id, and col ID refers to the same value stored within cellObject.id

grid.getData('rowID', 'colID', 'keyname');

// Open a grid instance and render a page within the DOM
// If no page number is passed as the first parameter, then 1 is inferred by default

grid.open();
// Or to open a specific page
grid.open(number);

// Close a grid instance and remove it from the DOM
// This will not delete any of the cached rowObjects that were added via grid.add()

grid.close();

// Programmatically set focus to the grid
// This always references the TD node that is currently active

grid.focus();

// Access the grid AccDC Object instance for optional modification

var dc = getAccDCObject();

// Access the container DOM node

var myContainer = grid.container;

Styling

The sample data grids in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

You can change the styling however you wish to fit the layout of any UI, and the data grids will still be accessible to both screen reader and keyboard only users regardless.

Simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled data grid will be accessible.

Implementation Notes

Notes about keyboard interactivity

A focusable ARIA Grid is a complicated concept, and there are only a certain number of keyboard commands available that don't directly conflict with the screen reader or browser. The following keyboard commands should not be used for this reason:

  • Control+PageUp/PageDown: Is automatically intercepted by JAWS and never gets passed through to the grid.
  • Control+Up/Down: Is automatically intercepted by JAWS and never gets passed through to the grid.
  • Alt+Home: Automatically loads the home page in the browser.
  • Alt+Left/Right: Automatically activates the Back and Forward buttons in the browser.

Notes about mouse interactivity

When activating a selectable row or editable cell using the mouse, double click must be used. If a single click is used to invoke this functionality, it will conflict with screen reader behavior. For example, when browsing the page using JAWS in Virtual Cursor mode, it is necessary to press Enter on the desired grid cell to enter Applications Mode. When JAWS does this, it automatically activates the click event, which automatically invokes selection or editing for that cell. When double click is used instead, this conflict does not occur. Single tapping of a selectable or editable cell using a touch screen device however, works using one click.

ARIA Date Pickers

The ARIA Date Picker is a complex control type with a simple implementation.

Expected behaviors: The associated INPUT field should not include readonly, an external triggering element should activate the date picker, the arrow keys should move between calendar cells and the calendar should scroll automatically between months, PageUp/PageDown should switch between months, Alt+PageUp/PageDown should switch between years, Enter should activate the selected date, and pressing Escape or Tab should close the calendar and return focus to the triggering element.

The Calendar Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

<input type="text" id="dateInputId" title="Label text if no Label element is associated" />

<a href="#" id="datePickerId"> Calendar Icon Name </a>

Form field HTML markup requirements:

  • The INPUT field must not be set to readonly, so that users can manually edit date string entries.
  • Form field constraints, such as the desired date string format, must also be included with the form field label to maximize clarity. E.G "MM/DD/YYYY"

JavaScript

$A.setCalendar( 'UniqueCalendarId' , $A.getEl('datePickerId'), $A.getEl('dateInputId'), EnableComments<true/false> ,
clickHandlerCallbackFunction(ev, dc, targetElementObj){
// Configure date string and save it within targetElementObj
targetElementObj.value = dc.range.wDays[dc.range.current.wDay].lng + ' ' + dc.range[dc.range.current.month].name + ' '
+ dc.range.current.mDay + ', ' + dc.range.current.year;
// Then close the calendar
dc.close();
}, {
// Configuration key / value map overrides
});

Parameters

  1. The first parameter must be unique for every calendar declaration, since this is registered as the ID of the Calendar AccDC Object when instantiated.

  2. The second parameter is the DOM object for the triggering element.

  3. The third parameter is the DOM object for the target INPUT element.

  4. The fourth parameter is a Boolean that determines whether comments will be displayed when associated with dates.
    False is set by default if no value is specified.

  5. The fifth parameter specifies a callback function where the returned date string can be customized.

  6. The sixth parameter is a key / value map where overrides can be declared to further customize functionality.

    Example:

    {
    
    // Configure optional overrides
    
    // If not included, all of the below values are set by default
    
    // Set role name text for screen reader users
    role: 'Calendar',
    
    // Set boundary text wording for screen reader users
    accStart: 'Start',
    accEnd: 'End',
    
    // Set tooltip text
    tooltipTxt: 'Press Escape to cancel',
    disabledTxt: 'Disabled',
    commentedTxt: 'Has Comment',
    prevTxt: 'Previous',
    nextTxt: 'Next',
    monthTxt: 'Month',
    yearTxt: 'Year',
    
    // Set month names
    months:
    [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
    ],
    
    // Set short and long weekday names
    days:
    [
    {
    s: 'S',
    l: 'Sunday'
    },
    {
    s: 'M',
    l: 'Monday'
    },
    {
    s: 'T',
    l: 'Tuesday'
    },
    {
    s: 'W',
    l: 'Wednesday'
    },
    {
    s: 'T',
    l: 'Thursday'
    },
    {
    s: 'F',
    l: 'Friday'
    },
    {
    s: 'S',
    l: 'Saturday'
    }
    ],
    
    // Set positive or negative offset for differing column arrangements, or 0 for none
    wdOffset: 0,
    
    // Set CSS positioning calculation for the calendar
    autoPosition: 9,
    // Customize with positive or negative offsets
    offsetTop: 0,
    offsetLeft: 0,
    // Set class for the calendar container
    className: 'calendar',
    
    // Choose a different insertion point in the DOM; must be a DOM node; defaults to the triggering element if not specified.
    targetObj: null,
    
    // Choose a different focus element in the DOM for CSS autoPositioning; may be a DOM node or CSS Selector; defaults to the triggering element if not specified.
    posAnchor: '',
    
    // Configure the Comments tooltip pane
    comments:
    {
    role: 'Comment',
    autoPosition: 1,
    offsetTop: 0,
    offsetLeft: 0,
    className: 'commentTooltip'
    },
    
    // Configure the editor form pane
    editor:
    {
    // Choose to show the form, defaults to false
    show: false,
    // Set the section name, and the Edit button text
    role: 'Edit',
    autoPosition: 6,
    offsetTop: 0,
    offsetLeft: 0,
    className: 'commentAdd',
    // Set the Save button text
    action1: 'Save'
    },
    
    // Manually configure the calendar using AJAX or a customization script
    ajax: function(dc, save){
    // 'save' is true when closing the Editor, false otherwise for fetching content when the calendar is opened.
    
    // If save is false, execute load script
    if (!save){
    
    // Optionally load custom values into the dc.range associative array.
    
    // And optionally prevent this script from running again
    // dc.stopAjax = true;
    
    // Then open the calendar after processing is finished
    dc.open();
    }
    
    else{
    // Otherwise do something with the newly saved values within the dc.range associative array.
    }
    }
    
    }
    

Programmatic Control

Every Date Picker is registered as an AccDC Object, the ID of which matches the ID string declared in the first parameter of the invocation statement.

This also makes it possible to control the calendar programmatically using JavaScript, like so:

var dc = $A.reg['UniqueCalendarId'];

// Which you can then open

dc.open();

// Or close

dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

Regarding the triggering element, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the Coding Arena samples, these are standard image links (A tags with an Href attribute and an embedded IMG tag with an informative Alt attribute). However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling. There must be an active element as a triggering element though, to ensure accessibility.

Styling

The sample calendars in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

You can change the styling however you wish to fit the layout of any UI, and the calendars will still be accessible to both screen reader and keyboard only users regardless.

Simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled calendar will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The calendars within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accCalendar", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-name : The name value for the calendar picker. The Name attribute of the accompanying text field must match the data-name attribute value. The selected date will then be inserted into the text field. (Must be on the triggering element.)

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes:

  • name="whatever" : The Input field name attribute that matches the value of data-name. (Must be on the Input field with type="text")
  • class="accCalendar" : The bootstrap class name that specifies an accessible calendar picker. (Must be on the triggering element.)
  • id : The unique ID of the element. This value is also registered as the ID of the calendar AccDC Object, making it possible to invoke the object programmatically. (Must be on the triggering element.)

Implementation Notes

The date string format is configurable within the callback function, or within the "accdc_bootstrap.js" module if bootstrapped.

The variables to reference are as follows:

var weekDay = dc.range.wDays[dc.range.current.wDay].lng; // 'Friday'

var monthName = dc.range[dc.range.current.month].name; // 'November'
// or
(dc.range.current.month+1) = numerical month string

var monthDay = dc.range.current.mDay; // '30'

var year = dc.range.current.year; // '2012'

The returned values will reflect the date selected.

ARIA Listboxes

The ARIA Listbox is a simple concept, turned into a powerful component.

Expected behaviors: ARIA Listboxes should only receive one tab stop, the Up/Down/Home/End keys should move focus appropriately, and every listbox and listbox option should be explicitly labeled.

The Listbox Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

<ul role="listbox" id="uniqueId1" >
<li>
<a href="#" role="option" id="uniqueId2" >
<span class="lbl"> Option One Name </span>
</a>
</li>
<li>
<a href="#" role="option" id="uniqueId3" >
<span class="lbl"> Option Two Name </span>
</a>
</li>
<li>
<a href="#" role="option" id="uniqueId4" >
<span class="lbl"> Option Three Name </span>
</a>
</li>
</ul>

Required attributes:

  • role="listbox" : Specifies a Listbox group container for screen reader users. (Must be on the container element that surrounds the list items.)
  • role="option" : Specifies a Listbox Option node for screen reader users. (Must be on the keyboard focusable link elements that comprise the listbox option elements.)
  • ID : Specifies unique ID attribute values for both the listbox container element and all list option links.
  • Href : Included within every list option A tag, this ensures keyboard accessibility.

The following attributes are handled automatically by the Listbox Module:

  • tabindex
  • aria-label
  • aria-owns
  • aria-setsize
  • aria-posinset
  • aria-selected
  • aria-checked (if applicable)
  • aria-grabbed (if applicable)
  • aria-dropeffect (if applicable)

JavaScript

var myListbox = new $A.Listbox( $A.getEl('uniqueId1'), {
// Configuration key / value mappings
});

Parameters

  1. The first parameter is the DOM node for the listbox container element that includes role="listbox".

  2. The second parameter is the object literal used to configure listbox functionality using key / value map overrides.

    Example:

    {
    
    // Set the initial list option node to be selected
    defaultIndex: 0,
    
    // Set a label for screen reader users
    label: 'Unique field label text',
    
    // Choose whether the Listbox is single or multiselect (multiselect is ignored when isSortable=true)
    isMultiselect: false,
    
    // Choose whether the Listbox is sortable
    isSortable: false,
    
    // Choose whether the Delete key can be used to remove list option nodes
    allowDelete: false,
    
    // Help messages that are announced to screen reader users when isSortable=true
    grabInstruct: 'Press Space to grab',
    dropInstruct: 'Press Space to drop',
    grabMsg: 'Grabbed',
    dropMsg: 'Moved',
    cancelDrop: 'Grab canceled',
    
    // Do stuff whenever the selection changes
    callback: function(optionNode, optionsArray){
    // this.val() returns the current value of the Listbox control, a string if single-select or an array of strings if multiselect
    }
    
    }
    

Programmatic Control

Since the Listbox control is an instantiated object, all of the following public properties and methods are available:

myListbox.container; // The Listbox DOM node for the element with role="listbox"

myListbox.options; // The array of list option DOM nodes that contain role="option"

myListbox.index; // The array index number for the currently selected list option element (relative to myListbox.options)

myListbox.grabbed; // The ID string value of the currently grabbed list option DOM node (when isSortable=true)

myListbox.val(); // Returns the current value of the Listbox control: An ID string when the listbox is single-select; an array of ID strings when the Listbox is a multiselect.

myListbox.val(indexValue); // Sets the current Listbox selection to the specified array index value (relative to myListbox.options)

myListbox.val('IdString'); // Sets the current Listbox selection to the specified list option DOM node that matches this ID (contained within myListbox.options)

myListbox.val(['IdString1', 'IdString2']); // Sets the current Listbox selection to all of the list option DOM nodes that match the ID strings in the array (when isMultiselect=true and contained within myListbox.options)

myListbox.val([]); // Clears all previously 'grabbed' or 'checked' list options if either isSortable or isMultiselect is set to True.

myListbox.rem(indexValue); // Removes the list option DOM node from myListbox.options at the specified array index value, and returns the removed A tag DOM node.

myListbox.rem('IdString'); // Removes the list option DOM node from myListbox.options by matching the ID, and returns the removed A tag DOM node.

myListbox.rem(['IdString1', 'IdString2']); // Removes the array of list option DOM nodes from myListbox.options by matching the IDs, and returns the removed A tag DOM nodes in an array.

myListbox.add(A-TagDOM-Node); // Adds a new list option to the Listbox. (Must be an A tag DOM node that includes a unique ID attribute value, an Href attribute for keyboard accessibility, and innerText to set the screen reader accessible label text)

myListbox.add([A-TagDOM-Node1, A-TagDOM-Node2]); // Adds an array of new list options to the Listbox. (Must include A tag DOM nodes that include a unique ID attribute value, an Href attribute for keyboard accessibility, and innerText to set the screen reader accessible label text)

myListbox.activate.apply(listOptionDOM-Node); // Programmatically activate the 'grab' or 'check' functionality for a specific list option DOM node (within myListbox.options when either isSortable or isMultiselect is set to True). The single parameter for this statement must consist of the A tag DOM node for the list option that you wish to activate. This simply performs a toggle action on the specified option, and does not specify a particular state.

Styling

The sample listboxes in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the listbox. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled listbox will be accessible.

Implementation Notes

All list option elements must be marked up as links (A tags with an Href attribute) to ensure backwards compatibility and graceful degradation. These are the only elements that will receive keyboard focus.

All list option elements, as well as the listbox container, must include unique ID attribute values.

In the case of the list option elements, the ID is used as the value of the Listbox control, so when an item is activated, the value of the Listbox will be returned as the ID value for the active A tag. For standard Listboxes, this is the ID of the currently selected list option as a string. E.G "uniqueId2" For Multiselect Listboxes, This is an array of the ID strings of the currently checked list options. E.G ["uniqueId2", "uniqueId4"]

An innerText label for each A tag must be included to ensure accessibility for screen reader users, though you may position this text offscreen to hide it visually if desired.

Alternatively, you may also include IMG tags within the A tags to form image links. When an IMG tag includes an informative Alt attribute, this text is also included as part of the list option label for screen reader users.

If a background image is used instead however, then there must be an innerText label, even if positioned offscreen, to ensure accessibility for screen reader users.

All list option label text must be unique, to prevent confusion for screen reader users.

ARIA Menus

An ARIA Menu is a simple control type that can easily be made accessible.

Expected behaviors: A keyboard accessible triggering element opens the menu, the arrow keys are used to browse available menu items or open and close submenus, pressing Tab will close all open menus, and pressing Escape will close the currently open menu.

ARIA menus can be implemented in two ways, horizontally or vertically.

This has nothing to do with what they look like, since the CSS styling can be set to whatever you like, but rather, refers to the keyboard interaction model for each menu.

A vertical menu is navigated using the Up and Down arrow keys to scroll through menu items, and Left and Right are used to close or open submenus.

A horizontal menu is navigated using the Left and Right arrow keys to scroll through menu items, and Up and Down are used to close or open submenus.

You can optionally set different interaction models for specific menus or submenus depending on how the menu is visually presented, so that the behavior properly fits the UI design.

The Menu Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

Basic menu structure with no submenus:

<ol class="menu" id="uniqueId1">
<li>
<a href="#" class="link" id="uniqueId2">
Menu Item One Name
</a>
</li>
<li>
<a href="#" class="link" id="uniqueId3">
Menu Item Two Name
</a>
</li>
<li>
<a href="#" class="link" id="uniqueId4">
Menu Item Three Name
</a>
</li>
</ol>

Basic menu structure with nested submenus:

<ol class="menu" id="uniqueId1">
<li>

<a href="#" class="submenu" id="-uniqueId2">
Subfolder Menu Item One Name (Level 1)
</a>

<ol class="menu" id="uniqueId1-uniqueId2">
<li>

<a href="#" class="submenu" id="-uniqueId2-1">
Subfolder Submenu Item One Name (Level 2)
</a>

<ol class="menu" id="uniqueId1-uniqueId2-uniqueId2-1">
<li>

<a href="#" class="link" id="uniqueId2-1-1">
Submenu Item One Name (Level 3)
</a>

</li>
</ol>

</li>
<li>

<a href="#" class="link" id="uniqueId2-2">
Submenu Item Two Name (Level 2)
</a>

</li>
</ol>

</li>
<li>

<a href="#" class="link" id="uniqueId3">
Menu Item Two Name (Level 1)
</a>

</li>
</ol>

The HTML menu syntax is flexible, and may consist of UL tags, OL tags, DIV tags, or any other combination, as long as the container element includes a unique ID, as well as each menu item tag.

For simplicity, these have been marked up as list elements, which is generally preferable since it includes native screen reader support for nested lists. Also, the use of standard A tags with an Href attribute ensures keyboard accessibility across all Assistive Technologies for graceful degradation.

You may also use additional HTML markup within the menu item links for formatting purposes (such as SPAN tags), as long as you don't add additional active elements such as clickable images. The only actionable element should be the menu item link, and nothing else.

Submenus are mapped by combining the ID attribute value of the container element, with the ID attribute value of the submenu link. The two combined point to the full ID attribute value of the associated submenu container element.

For example, notice the ID value on the top level menu OL tag above is id="uniqueId1", and the ID of the first Subfolder A tag within that structure is id="-uniqueId2".

When you combine the two ("uniqueId1-uniqueId2"), notice that this directly points to the submenu OL tag as its ID attribute value.

You can experiment with this in the Coding Arena "Shell" folders, where the same code is used.

Important: Don't add any ARIA attributes to the markup, and don't add tabindex attributes. All of these are handled automatically when the menus are rendered.

If the menu constructs are contained within the same page, they must be contained within a container element that has an ID attribute. This is used by the setup function to confine the parsing query to this node only.

Example:

<div id="hiddenDivId" class="hidden">

<ol class="menu" id="uniqueId1">
...
</ol>

</div>

The following attributes are handled automatically by the Menu Module:

  • role="menubar"
  • role="menu"
  • aria-owns
  • tabindex
  • role="menuitem"
  • aria-selected
  • aria-posinset
  • aria-setsize

HTML5 attributes that can optionally be added to the menu list container markup:

  • data-horizontal="true"/"false" : Sets or unsets a horizontal flyout menu where the Left and Right arrow keys will be used to navigate menu item nodes, and Up and Down will be used to close or open submenus. This temporarily overrides the interaction model set within the JavaScript declaration statement.
  • data-offsetleft="number" : Specifies a positive or negative offsetLeft value that will be applied to the menu after it is rendered.
  • data-offsettop="number" : Specifies a positive or negative offsetTop value that will be applied to the menu after it is rendered.
  • data-autoposition="number between 0 and 12" : Specifies a custom autoPosition value that will control where the menu is visually positioned relative to the triggering element.

    Value Definitions:

    • 0: Disabled
    • 1: Above/Center/Left Edge Aligned
    • 2: Above/Right/Right Edge Aligned
    • 3: Level/Right/Right Edge Aligned
    • 4: Below/Right/Right Edge Aligned
    • 5: Below/Center/Left Edge Aligned
    • 6: Below/Left/Left Edge Aligned
    • 7: Level/Left/Left Edge Aligned
    • 8: Above/Left/Left Edge Aligned
    • 9: Level/Center/Left Edge Aligned
    • 10: Above/Center/Right Edge Aligned
    • 11: Level/Center/Right Edge Aligned
    • 12: Below/Center/Right Edge Aligned

Example:

<ol class="menu" id="uniqueId1-uniqueId2-uniqueId2-1" data-horizontal="true" data-offsetleft="10" data-offsettop="-20" data-autoposition="3">
...
</ol>

JavaScript

$A.setMenu( 'CSS-SelectorForTriggeringElement' , 'LocalePathOrContainerID' , 'TopLevelMenuID' ,
callbackFunction(ev, dc){
// Do something every time a menu item link node is clicked
} , areMenusInTheSameDoc? , contextDOM-Node , {
// Configure key / value mapping overrides
});

Parameters

  1. Parameter 1: The triggering element CSS Selector :
    This points to the triggering element link or button that you want to use as the menu triggering element. For instance, the CSS Selector "a.button" points to the A tag with class="button" for this purpose.

  2. Parameter 2: The Locale Path or Container ID :
    When menus are contained within an external HTML file, this string value is the relative file path, such as "files/menus.html".
    When menus are contained within the same page, this string value is the ID attribute of the container element where all of the menu tags are located, such as "hiddenDivId".

  3. Parameter 3: Top Level Menu ID:
    This string is the top level menu ID attribute value, such as "uniqueId1", which is used to specify which menu will be opened first when the triggering element is activated.

  4. Parameter 4: The Callback Function:
    This is where you can set specific functionality to occur whenever a menu item link is activated, whether this is to navigate to another page, or to perform another client side action.
    When declared, two arguments are passed to the function, first is the event object, and the second is the AccDC Object for the currently open menu object.
    Using 'this' within the function will reference the DOM node for the activated element, which is useful if mapping the ID attribute to a particular action.

  5. Parameter 5: Are Menus within the Same Doc:
    A Boolean (true or false), that specifies whether the script should process the Locale parameter as an internal or external resource locator.
    If menu markup is contained within an external HTML file, set this to false, otherwise set to true.

  6. Parameter 6: The Context DOM Node:
    This is the DOM node that will be used to confine the parsing query.
    Typically this is set to document, since all of the IDs are relative to this location.
    However, this parameter gives you the ability to reference iFrame documents instead if desired.

  7. Parameter 7: The Config Object:
    This is a key / value mapping of overrides that can be used to customize the element types of menu container and menu item elements, the class names for each, the boundary text that is conveyed to screen reader users, the menu heading level, the default keyboard interaction model, the default auto positioning if desired, plus additional AccDC API overrides if desired.

    Example:

    {
    
    // Assign a role name for screen reader users
    role: 'Menu',
    // Assign beginning and ending text to be appended to the role name for screen reader users
    accStart: 'Start',
    accEnd: 'End',
    // Assign the state text, which will be appended to the triggering element when a menu is open for screen reader users
    openState: 'Open',
    
    // Set the initial menu heading level
    ariaLevel: 3,
    
    // Set the main container class, (which will surround the menu as a Div tag when rendered)
    containerClass: 'menu',
    
    // Specify the menu tag name in the markup
    menuTag: 'ol',
    // Specify the menu class name on the above tag in the markup
    menuClass: 'menu',
    
    // Specify the active element that will be used as each menu node
    // Important, if nesting A tags within LIs, only the A tag should be used for this purpose
    // Active elements should never be nested.
    // The following tag will receive keyboard focus within the menu structure when using the arrow keys to navigate
    // Event bindings are also tied to this tag
    itemTag: 'a',
    
    // Specify the class name that indicates when a menu item opens a submenu
    folderClass: 'submenu',
    // Specify the class name that indicates when a menu item is to be triggered directly
    // This should not be the same as the folderClass declaration
    linkClass: 'link',
    
    // Specify if the menu is a flyout menu
    // If true, the Left and Right arrow keys will scroll the open menu
    // If false, the Up and Down arrow keys will scroll the open menu instead
    horizontal: false,
    
    // Set a default autoPosition value between 0 (disabled) and 12
    autoPosition: 0,
    
    // Set custom offset values to adjust the positioning calculation
    // May return a positive or negative number
    offsetLeft: function(dc){
    return 0;
    },
    offsetTop: function(dc){
    return 0;
    },
    
    overrides: {
    // Additional AccDC API properties and methods can be applied here if desired.
    }
    
    }
    

Programmatic Control

Every menu instance is registered as an AccDC Object, the ID of which matches the ID attribute value on the menu container element.

This means that you can programmatically control each menu using JavaScript if desired, like so:

// Get a reference to the top level Menu AccDC Object for the menu container with id="uniqueId"
var dc = $A.reg['uniqueId'];

// Now invoke the object
dc.open();

// Or close it
dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

Regarding the triggering element for opening menus, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the Coding Arena samples, these are standard links (A tags with an Href attribute). However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling. There must be an active element as a triggering element though, to ensure accessibility.

Styling

The sample menus in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the menu. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled menu will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The menus within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accMenu", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-src : The resource path and pointer to the ID attribute of the top level menu list. If pointing to a menu list within the same document, only the ID attribute should be included here.
  • data-internal : The ID attribute of the container element for all menu lists within the same document. If data-src is set to an external source, data-internal should be blank or not included.
  • data-role : The role name that is conveyed to screen reader users at the beginning and end of each menu section. "Menu" is set by default if no value is specified.
  • data-starttext : The role state that is conveyed to screen reader users at the beginning of each menu section. "Start" is set by default if no value is specified.
  • data-endtext : The role state that is conveyed to screen reader users at the end of each menu section. "End" is set by default if no value is specified.
  • data-openstate : The open state text that is conveyed to screen reader users within the triggering link when open. "Open" is set by default if no value is specified.
  • data-containerclass : The class name that will be added dynamically to the surrounding Div tag for each menu group when rendered. "menu" is set by default if no value is specified.
  • data-menutag : The tag name for the container element that contains all menu item tags. All menu item tags must be contained within this container element, even if they are not first level child nodes. "ol" is set by default if no value is specified.
  • data-menuclass : The shared class name that is contained within every menu container element. All menu tags specified by data-menutag must include this class name. "menu" is set by default if no value is specified.
  • data-menuitemtag : The shared tag name that specifies all menu item tags. All menu item tags must be contained within the container element specified by data-menutag, even if they are not first level child nodes. "a" is set by default if no value is specified.
  • data-menufolderclass : The shared class name that is contained within every menu tag that opens a submenu. "submenu" is set by default if no value is specified.
  • data-menulinkclass : The shared class name that is contained within every menu tag that does not open a submenu. "link" is set by default if no value is specified.
  • data-flyout="true" : Specifies a horizontal flyout menu where the Left and Right arrow keys will be used to navigate menu item nodes, and Up and Down will be used to close or open submenus. If data-flyout is not included within the markup, the default vertically oriented keyboard assignments will be applied automatically.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes for the triggering element:

  • class="accMenu" : The bootstrap class name that specifies an accessible menu triggering element.

Implementation Notes

The lists can be set to any tag, such as OL, UL, etc, as long as this is specified in the menuTag property within the JavaScript declaration statement or within the data-menutag attribute on the triggering element if Bootstrapped.

The same is true for the menu item nodes, which is specified using the menuItemTag property in the JavaScript declaration statement, or within the data-menuitemtag attribute on the triggering element if Bootstrapped.

Menus and submenus may be nested or broken out into separate lists within the markup if desired, as long as they are all contained within the same top level container element specified by ID within the JavaScript invocation statement, or within the data-internal attribute on the triggering element if Bootstrapped.

All menu container elements and menu item nodes must include unique ID attributes.

Submenus are mapped by combining the ID attribute of the top level menu container ID and the submenu pointer link ID, which, when combined, points to the ID of the referenced submenu container.

All menu item nodes must include innerText to ensure accessibility for screen reader users.

Don't include any ARIA attributes within the menu markup, since this is handled automatically by the Menu module.

ARIA Radio Buttons

ARIA Radio buttons provide a means for rendering standard links as a radio button group.

Expected behaviors: Only one radio button should receive focus in the tab order, regardless whether one or no radio button in the group is selected. If a radio button is selected, only the currently selected radio button should appear in the tab order. The arrow keys should move focus to the next or previous radio button in the group, and the act of moving to that radio button should automatically select it.

The Radio Button Module automates these processes by adding all related event handlers and managing keyboard focus appropriately.

HTML Syntax

<ul id="radiogroupId" role="radiogroup">
<li>
<a href="#" role="radio" class="accRadio" id="rOpt1" aria-labelledby="rOpt1Lbl">
<span id="rOpt1Lbl"> Radio One Label Text </span>
</a>
</li>
<li>
<a href="#" role="radio" class="accRadio" id="rOpt2" aria-labelledby="rOpt2Lbl">
<span id="rOpt2Lbl"> Radio Two Label Text </span>
</a>
</li>
<li>
<a href="#" role="radio" class="accRadio" id="rOpt3" aria-labelledby="rOpt3Lbl">
<span id="rOpt3Lbl"> Radio Three Label Text </span>
</a>
</li>
</ul>

Markup requirements:

  • The Radio container element must include the attribute role="radiogroup".
  • All radio option nodes must include the attribute role="radio".
  • Both the Radio container element and all radio option nodes must include unique ID values.
    The current value for a Radio Control is the ID attribute of the currently selected radio button.
  • The innerHTML for each radio option node must contain a textual label, which may be positioned offscreen to hide it visually if desired.
    This textual label is critical so that screen reader users will be able to identify the purpose of the radio button.
    If the textual label is included within another tag (such as a Span tag) for formatting purposes, aria-labelledby must be used to explicitly associate the label text with the element that includes role="radio" by referencing its ID.
    Additionally, the textual label must be included within the opening and closing tags of the element with role="radio".
  • If using an A tag, an href attribute is required to ensure keyboard accessibility.
  • Images may also be used within radio option nodes if desired.
    If an image is present however, it should include the attribute alt="" to hide it from screen reader users.
    An image with a textual Alt value won't be reliably announced as the radio button label in all browsers, which is why alt="" is used to hide it from screen reader users.
    A textual label must be used instead to ensure the highest level of accessibility for the highest percentage of people.
    To add a tooltip for sighted mouse users, use the Title attribute on the IMG tag instead.
    The value within the Title attribute must match the text contained within the textual label however, especially when the textual label is positioned off screen to hide it visually. (This will ensure equal accessibility for all user types)

The following attributes are handled automatically by the Radio Button Module:

  • tabindex
  • aria-owns
  • aria-setsize
  • aria-posinset
  • aria-selected
  • aria-checked

JavaScript

var myRadioGroup = new $A.RadioGroup( 'radiogroupId' , 'CSS Selector for All Radio Elements' , DefaultIndexValue , 'Optional Legend Text' ,
callbackFunction(selectedRadioNode, radiosArray){
// Do something whenever a radio is selected
// this.value is the ID value of the newly selected radio element
} );

Parameters

  1. Parameter 1: The ID attribute of the radio group container. (This is the element with role="radiogroup")

  2. Parameter 2: The CSS Selector that identifies all elements with role="option" (all of which must be contained within the container specified in parameter 1)

  3. Parameter 3: The array index of the radio button that you want to be selected by default when instantiated.
    (Simply pass -1 to specify that no radio button should be selected by default)

  4. Parameter 4: The shared legend text that will be announced to screen reader users whenever a radio button group receives initial focus.
    The legend text will be announced in addition to the textual label for the radio button.
    To use a visually displayed legend instead (as demonstrated within the Coding Arena samples), use aria-labelledby on the element with role="radiogroup", and pass "" to this parameter to skip it.

  5. Parameter 5: The callback function that will be executed whenever a new radio button is activated.

Programmatic Control

When a radio button grouping is instantiated as a new Radio Group Control, all of the following public properties and methods are available:
('myRadiogroup' refers to the variable instance name)

myRadiogroup.radios; // The array of all radio option DOM nodes

myRadiogroup.index; // The array index of the currently selected radio option

myRadiogroup.value; // The string ID attribute value of the currently selected radio option

myRadiogroup.set('radioId'); // Sets the radio option with id="radioId"

myRadiogroup.set(arrayIndex); // Sets the radio option at the specified array index (relative to myRadiogroup.radios)

Styling

The sample radios in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the radio group. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled radio group will be accessible.

ARIA Sliders

ARIA Sliders are used to present adjustable values for users, and can easily be made accessible.

Expected behaviors: The slider should have only one tab stop in the tab order, the arrow keys should move the slider in single value increments, PageUp/PageDown should move the slider in 10% increments, Home/End should move the slider to the beginning or end, and the slider should be draggable using the mouse as usual.

The Slider Module automates these processes by adding all related event handlers and managing keyboard focus appropriately.

HTML Syntax

<div class="slider">

<div class="min" aria-hidden="true">
<span>0%</span>
</div>

<div class="slideWrapper">

<div class="slide clearfix">

<div class="nub" id="handleId"><!--
This is the slider thumb icon
--></div>

</div>

</div>

<div class="max" aria-hidden="true">
<span>100%</span>
</div>

</div>

Important: The first parentNode container of the draggable slide element must be relatively positioned to set this as the offsetParent. In the above markup, this is the Div tag with class="slide clearfix".

Also, notice that aria-hidden="true" is used on the Min and Max container tags. Since these values will be provided to screen reader users as part of the ARIA Slider Control, having them announced during navigation would only repeat the same information twice, which is unnecessary. So aria-hidden is used to remove them from the Virtual Buffer for screen reader users.

The next step is to use CSS to set the width and height of the slider, which you can see examples of in the Coding Arena samples. This is important, because when the Slider Control is instantiated, it will use these offsets to configure the positioning calculations and map them to related keyboard commands.

The following attributes are handled automatically by the Slider Module:

  • tabindex
  • aria-label
  • role="slider"
  • aria-valuemin
  • aria-valuemax
  • aria-valuenow
  • aria-valuetext
  • aria-orientation

JavaScript

$A.setSlider('handleId', {
// Configure key / value mappings
});

Parameters

  1. The first parameter is the ID of the element that will be made draggable, which will then be morphed into an AccDC Object. E.G "handleId" The markup structure will slightly change at this point, since an extra DIV will then surround the element with id="handleId".

  2. The second parameter is where all of the slider configuration is set.

    Example:

    {
    
    // Set the role text that is conveyed to screen reader users
    role: 'Slider',
    
    // Set a minimum value
    min: 0,
    
    // Set a maximum value
    max: 100,
    
    // Set the start value
    now: 50,
    
    // Is a vertical slider?
    vertical: false,
    
    // Set the hidden link text for graceful degradation
    // This should reflect the purpose of the slider
    degradeLbl: 'Manually choose a percentage',
    
    // Return the string that will act as the ARIA Slider label for screen reader users
    // This should reflect the purpose of the slider
    ariaLabel: function(dc){
    return 'Choose a percentage between 0 and 100';
    },
    
    // Return the string that will act as the textual notification for screen reader users
    // This is automatically announced every time the slider is moved
    valueText: function(dc, val){
    return val + '%';
    },
    
    // Set the action to occur whenever the value changes
    onDrag: function(ev, dd, dc, val){
    // ev is the standard event object
    // dd is the custom drag event object
    // dc is the AccDC Object for the Slider
    // val is the current value of the slider
    },
    
    // Set the class name for the surrounding Div, which automatically surrounds the drag handle element
    className: 'handleWrapper'
    
    }
    

Programmatic Control

After a Slider Control is instantiated, it can be controlled programmatically using its ID, which matches the ID attribute value of the drag handle (passed as the first parameter in the invocation statement).

Example:

// Get a reference to the Slider AccDC Object using its ID, which matches the handle elements ID attribute
var dc = $A.reg['handleId'];

// Get the current slider value
var currentVal = dc.config.now;

// Assign a new slider value
dc.config.now = currentVal + 10;

// Apply the change
dc.set.apply(dc);

Styling

The sample sliders in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled sliders will be accessible.

Implementation Notes

Simply use CSS to set the size of the slider, and the height and width of the container element, and then the slider will configure itself using these offsets.

Since repetitive labels are used, and the textual slider icon has no value for screen reader users, aria-hidden="true" is used to hide them from screen reader users.

Don't include any other ARIA attributes however, the Slider module handles this automatically.

The slide icon can be changed to anything, or an image or CSS background image can be used instead, and the styling can be configured for any layout, and it will still be accessible for screen reader and keyboard only users.

VoiceOver instructions for use on iOS touch screen devices:

When VoiceOver is used on iOS touch screen devices, VoiceOver instructs the user to swipe up and down with one finger to adjust the slider value, which is incorrect. (Last verified on 04/07/2013)

Instead, do the following:

  1. Use one finger and double tap the slide icon, and keep your finger pressed down on the second tap.
  2. Wait until you hear a slight noise, then slide your finger in the direction that you wish to move the slider.
  3. Then lift your finger to release the slider.

(Credit goes to David Hilbert Poehlman for providing VoiceOver pass-through technique instructions.)

ARIA Toggles and Checkboxes

The Toggle Control is a multipurpose control type, that covers checkboxes, toggle buttons, and even simulated links and buttons.

Expected behaviors: The general behavior of a Toggle control is to receive keyboard focus in the tab order regardless of the active select state, to be toggleable or actionable by pressing the Spacebar or by pressing Enter on the control, and to be toggleable or actionable by clicking it as usual.

The Toggle Module automates these processes by adding all related event handlers.

HTML Syntax

The HTML syntax varies depending on which type of implementation is desired, and each type has specific rules that must be observed in order to ensure the highest level of accessibility for screen reader users.

IMG

For IMG tags, the following attributes are required to ensure accessibility for the widest range of screen readers:

  1. aria-label : Specifies a textual label for screen reader users. (The Alt alone won't work for this purpose)
  2. alt="" : Hides the image from screen reader users when no tooltip is desired for mouse users.
    To add a tooltip for sighted mouse users, use both the Alt and Title attributes. The text for both must match the text contained within the aria-label attribute, so that all three are the same. This will also maximize accessibility in iOS devices using VoiceOver.
  3. role="button" must be added for toggles, or role="checkbox" must be added for checkboxes.
  4. A unique ID must be added for proper event binding.

Examples:

<img role="button"
aria-label="Toggle Button Label"
alt="Toggle Button Label"
title="Toggle Button Label"
id="uniqueId1"
src="icon.png"
/>

<img role="checkbox"
aria-label="Checkbox Label"
alt="Checkbox Label"
title="Checkbox Label"
id="uniqueId2"
src="icon.png"
/>

INPUT

For INPUT tags with type="image", the following attributes are required to ensure accessibility for the widest range of screen readers:

  1. aria-label : Specifies a textual label for screen reader users. (The Alt alone won't work for this purpose)
  2. Title : Specifies a textual label for screen reader users. This must match the text contained within the aria-label attribute.
    (Both the Title and aria-label attributes are required to correct differing screen reader feedback when tabbing versus arrowing down the page using JAWS.)
  3. To add a tooltip for sighted mouse users, use both the Alt and Title attributes. The text for both must match the text contained within the aria-label attribute, so that all three are the same.
  4. role="button" must be added for toggles, or role="checkbox" must be added for checkboxes.
  5. A unique ID must be added for proper event binding.

Examples:

<input type="image"
role="button"
aria-label="Toggle Button Label"
alt="Toggle Button Label"
title="Toggle Button Label"
id="uniqueId3"
src="icon.png"
/>

<input type="image"
role="checkbox"
aria-label="Checkbox Label"
alt="Checkbox Label"
title="Checkbox Label"
id="uniqueId4"
src="icon.png"
/>

Container Elements

For all other container elements that support innerHTML such as DIVs and SPANs, the following attributes and rules are required to ensure accessibility for the widest range of screen readers:

  1. Inner Text : Specifies a textual label for screen reader users. This may be visible or positioned using offscreenText. OffscreenText is required to ensure the same level of accessibility for iOS devices using VoiceOver.
  2. No Embedded Active Elements : Don't embed any other active elements, including mouse clickable images, links, or anything else that needs to be activated separately. (The only actionable element should be the element with role="button" or role="checkbox".)
  3. To add a tooltip for sighted mouse users, use the Title attribute. This must match the text contained within the innerText label.
  4. role="button" must be added for toggles, or role="checkbox" must be added for checkboxes.
  5. A unique ID must be added for proper event binding.

Examples:

<div role="button"
title="Toggle Button Label"
id="uniqueId5">
<span class="lbl">
Toggle Button Label
</span>
</div>

<div role="checkbox"
title="Checkbox Label"
id="uniqueId6">
<span class="lbl">
Checkbox Label
</span>
</div>

The following attributes are handled automatically by the Toggle Module:

  • tabindex
  • aria-checked (if applicable)
  • aria-pressed (if applicable)

JavaScript

var myToggle = new $A.Toggle('uniqueId', {
// Configure key / value mappings
});

Parameters

  1. The first parameter is the ID attribute value of the element that will become actionable.

  2. The second parameter is the key / value map that configures specific functionality.

    Example:

    {
    
    // Disable ARIA
    // (only for simulated Checkboxes and Toggle Buttons, leave out otherwise)
    noARIA: true,
    
    // Disable toggling
    // (only for ARIA Links and Buttons, leave out otherwise)
    noToggle: true,
    
    // Set the initial state
    // (only for simulated Checkboxes and Toggle Buttons, leave out otherwise)
    state: false,
    
    // Declare a callback to run every time the state changes
    callback: function(state){
    // 'state' is the proposed state change, true or false
    // 'this' is the triggering element
    // Return true to accept the ARIA state change, or false to prevent
    return true;
    }
    
    }
    

Programmatic Control

After a Toggle control is instantiated, the following public properties and methods are available:

myToggle.state; // Reflects the current select state of the toggle (true or false)

myToggle.set(Boolean); // Set the Toggle with the specified state (true or false)

Styling

The samples in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled checkbox or button will be accessible.

ARIA Trees

An ARIA Tree is a complex control type that requires a lot of synchronizing to make accessible.

The reasons why: If the right ARIA attributes are not applied to the correct DOM nodes that receive keyboard focus, and if the parent child ID associations are not properly mapped and maintained, and if tree nodes are not labeled properly using the correct ARIA attributes, and if the tree contains any other active elements that are not part of the ARIA Tree structure, then the ARIA Tree and its contents will not be accessible for screen reader users.

Currently, a large part of this is the result of unequal support by screen reader manufacturers. For example, even though the ARIA specification states that role="document" can be used to embed additional content panels within specific widgets such as this, doing so will result in content panels that are inaccessible using JAWS in both IE and Firefox. (Verified in JAWS 12, 13, and 14)

Nevertheless, the Tree Module automates these processes accessibly by adding all related event handlers and managing all related rendering procedures using an external XML file for configuration.

HTML Syntax

<div id="myTreeId"></div>

XML Syntax

<?xml version="1.0" encoding="UTF-8" ?>
<tree>
<branch id="uniqueId0-1" name="Branch Link Name for id=uniqueId0-1">
<leaf id="uniqueId0-1-1" name="Leaf Link Name for id=uniqueId0-1-1"></leaf>
</branch>
<leaf id="uniqueId0-2" name="Leaf Link Name for id=uniqueId0-2"></leaf>
</tree>

The above XML markup results in the following HTML structure when rendered:

<div class="TreeView">
<div>
<ul role="tree" aria-owns="uniqueId0-1 uniqueId0-2" aria-label="Informative Field Name">
<li>
<a class="branch" aria-expanded="true" id="uniqueId0-1" aria-level="1" role="treeitem" aria-posinset="1" tabIndex="0" aria-selected="true" aria-owns="aria1363672754457" aria-setsize="2" href="#" aria-label="Branch Link Name for id=uniqueId0-1">
<SPAN>Branch Link Name for id=uniqueId0-1</SPAN>
</a>
<div class="TreeView">
<div>
<ul id="aria1363672754457" role="group" aria-owns="uniqueId0-1-1">
<li>
<a class="leaf" id="uniqueId0-1-1" aria-level="2" role="treeitem" aria-posinset="1" tabIndex="-1" aria-selected="false" aria-setsize="1" href="#" aria-label="Leaf Link Name for id=uniqueId0-1-1">
<SPAN>Leaf Link Name for id=uniqueId0-1-1</SPAN>
</a>
</li>
</ul>
</div>
</div>
</li>
<li>
<a class="leaf" id="uniqueId0-2" aria-level="1" role="treeitem" aria-posinset="2" tabIndex="-1" aria-selected="false" aria-setsize="2" href="#" aria-label="Leaf Link Name for id=uniqueId0-2">
<SPAN>Leaf Link Name for id=uniqueId0-2</SPAN>
</a>
</li>
</ul>
</div>
</div>

Required XML attributes:

  • id : The unique ID of the node. This will automatically be converted into the ID attribute of the relevant tree item link when rendered. (All IDs must be unique)
  • name : The textual name of the node, which will automatically be converted into the textual label for the tree item link when rendered.
    (All name attribute values at the same logical node level must be unique to ensure accessibility for screen reader users)

The following attributes are handled automatically by the ARIA Tree Module:

  • aria-label
  • role="tree"
  • role="group"
  • aria-owns
  • tabindex
  • role="treeitem"
  • aria-setsize
  • aria-posinset
  • aria-selected
  • aria-expanded

JavaScript

var treeId = $A.setTree({
// Configuration key / value map
});

Parameters

  1. The first parameter is used to configure ARIA Tree functionality using a key / value map.

    Example:

    {
    
    // Set the XML file to parse
    path: 'files/tree.xml',
    
    // Set the label that will be announced to screen reader users
    title: 'Informative Field Name',
    
    // Specify the container element where the tree nodes will be inserted
    container: 'div#myTree',
    
    // Set the class name shared by all tree AccDC Objects when rendered
    topClass: 'TreeView',
    
    // Set the container tree node type
    treeTag: 'ul',
    
    // Set the divider node type that will be appended to the treeTag node
    dividerTag: 'li',
    
    // Set the focusable tree item node type that will be inserted within dividerTag node
    treeItemTag: 'a',
    
    // Set the shared class name for all tree items that expand into subfolders
    treeClass: 'branch',
    
    // Set the shared class name for all tree items that do not expand into subfolders
    treeItemClass: 'leaf',
    
    // Set the class name that is only set on the tree item node that has focus
    selectClass: 'selected',
    
    // Set the handler type that will trigger the callback
    bind: 'click',
    
    // Declare a callback function
    callback: function(ev, dc){
    
    // Get the XML node that matches the ID attribute of the currently triggered element
    var xmlNode = $A.query('#' + this.id, dc.top.xmlDocument)[0];
    
    // To learn more about the XML DOM and supported properties and methods,
    // and how to access custom attributes on each node, visit
    // http://www.w3schools.com/dom/default.asp
    
    }
    }
    

Programmatic Control

The invocation statement returns the top level ID of the newly instantiated ARIA Tree control, which is now registered as an AccDC Object.

You can use this ID to programmatically change or invoke AccDC API properties and methods within the ARIA Tree structure, and to traverse the parent / child relationship of tree node objects.

Example:

// Get the Tree AccDC Object using the ID stored in the variable treeId
var dc = $A.reg[treeId];

Now, you can traverse the expandable branches in the tree using dc.siblings, dc.children, dc.parent, and dc.top, and apply changes, store and retrieve data, or invoke AccDC API commands as desired.

Example:

// Close the Tree AccDC Object and remove it from the DOM.
dc.top.close();

// All other AccDC API properties and methods are similarly available.

Styling

The sample trees in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the tree. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled tree will be accessible.

Banners

A Banner is a simple control type, which can easily be made accessible.

Expected behaviors: Ensure that the content of the banner appears at the top of the page, ensure that the beginning and ending boundaries are conveyed to screen reader users, and make sure the banner can be closed from the keyboard (if applicable).

The Banner Module automates these processes by instantiating banner content as an AccDC Object.

HTML Syntax

<div id="bannerContainerElementId">
Banner content goes here.
</div>

JavaScript

var bannerId = $A.setBanner({
// Configure functionality key / value map
});

Parameters

  1. The first parameter configures banner functionality using a key / value map.

    Example:

    {
    
    // Set a unique ID for the Banner AccDC Object
    id: 'myBannerId',
    
    // Set the boundary text for screen reader users
    role: 'Banner',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set the Banner AccDC Object to render literal content
    // (Only if pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Set the content to be rendered by pulling it from within the same page
    // 'removeChild' is important here, so no duplicate ID conflicts can occur when the object is opened and closed
    // (Only if pulling content from within the same page, remove otherwise)
    source: $A.getEl('bannerContainerElementId').parentNode.removeChild($A.getEl('bannerContainerElementId')),
    
    // Specify the path and ID of the banner content to be loaded
    // (Only if pulling content from an external page, remove otherwise)
    source: 'files/overlays.html #bannerContainerElementId',
    
    // Disable automatic positioning if wishing to use a Style Sheet instead
    autoFix: 0,
    
    // Specify that the banner should open as soon as the page loads
    autoStart: true,
    
    // Set a class name for the banner top level container element
    className: 'banner',
    
    // Specify that the textual content of the banner should automatically be announced to screen reader users when opened
    announce: true,
    
    // Choose the container element where the banner will be inserted
    isStatic: 'body',
    // Choose to prepend the banner instead of replacing the content within the container element
    // (This places the banner content at the top of the page in the reading order for screen readers)
    prepend: true,
    
    // Set a hidden close link to appear for screen reader users
    showHiddenClose: true,
    
    // Remove the hidden close link from the tab order so it doesn't appear when tabbing
    displayHiddenClose: false,
    
    // Set the heading level that will be accessible for screen reader users
    ariaLevel: 2,
    
    // Run a script after the banner finishes loading
    runAfter: function(dc){
    // Optionally do stuff
    // 'dc' is the Banner AccDC Object
    // dc.containerDiv is the DOM node where all banner content is rendered
    }
    
    // Other AccDC API properties and methods can go here as well if desired.
    
    }
    

Programmatic Control

The invocation statement returns the ID of the newly instantiated Banner AccDC Object, which can be used to programmatically control each banner using JavaScript if desired.

Example:

// Get a reference to the Banner AccDC Object
var dc = $A.reg[bannerId];

// Which you can then open

dc.open();

// Or close

dc.close();

// All other AccDC API properties and methods can be applied here as well.

Styling

The sample banners in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the banner. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled banner will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The banners within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accBanner", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes:

  • data-src : The resource path and pointer to the ID attribute of the banner container element.
  • data-role : The role name that is conveyed to screen reader users as beginning and ending boundary text for the new content. "Banner" is set by default if no value is specified.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes:

  • class="accBanner" : The bootstrap class name that specifies a banner insertion point container.
  • id : The unique ID of the element. This value is also registered as the ID of the banner AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.
Carousels, Slideshows, and Wizards

A Carousel is a complex control type that is easy to make accessible.

Expected behaviors: The beginning and ending boundaries should be conveyed to screen reader users, content changes should be announced to screen reader users only when a navigation button is manually activated, all navigation buttons should be keyboard accessible and include unique accesskeys for screen reader users, auto cycling should pause when an element within the carousel receives focus or when the mouse is moved into the region, auto cycling should resume when focus moves out of the carousel or when the mouse moves out of the region, and auto cycling should be stoppable from anywhere on the page using the keyboard.

The Carousel Module automates these processes by adding all related event handlers and managing all related rendering procedures using an external XML file for configuration.

HTML Syntax

<div id="myCarousel"></div>

XML Syntax

An external XML file is used to configure and populate each slide of the carousel.

Flat:

<?xml version="1.0" encoding="UTF-8" ?>
<carousel
role="Slideshow" accStart="Start" accEnd="End"
height="170" width="280"
className="carouselCls"
prevTitle="Previous" nextTitle="Next" slideName="Slide" groupName=""
showGroup="" groupPosTop=""
btnPText="↑" btnNText="↓" btnPGText="" btnNGText=""
isGrouped="no"
btnPAccesskey="1" btnNAccesskey="2" btnPGAccesskey="" btnNGAccesskey=""
direction="tb" cycle="yes" timer="0" animDelay="1250" forward="yes"
hiddenMsg="" >
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
</carousel>

Grouped:

<?xml version="1.0" encoding="UTF-8" ?>
<carousel
role="Carousel" accStart="Start" accEnd="End"
height="170" width="280"
className="carouselCls"
prevTitle="Previous" nextTitle="Next" slideName="Slide" groupName="Group"
showGroup="yes" groupPosTop="yes"
btnPText="←" btnNText="→" btnPGText="⇐" btnNGText="⇒"
isGrouped="yes"
btnPAccesskey="1" btnNAccesskey="2" btnPGAccesskey="3" btnNGAccesskey="4"
direction="lr" cycle="yes" timer="5000" animDelay="2000" forward="yes"
hiddenMsg="Press Escape to stop automatic cycling" >
<group name="Unique Group Name" >
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
</group>
<group name="Unique Group Name" >
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
<slide announce="Unique Slide Name" ><![CDATA[
HTML content to render goes here
]]></slide>
</group>
</carousel>

Important: All attributes must remain within the XML markup. Attributes that are not required may be set to null. E.G. attributeName=""

Carousel attribute definitions:

  • role : Hidden text role for screen reader users
  • accStart : Hidden text start keyword for screen reader users
  • accEnd : Hidden text end keyword for screen reader users
  • height : Total height of control (must be greater than the CSS height of the left/center/right content panels)
  • width : Total width of control (must be greater than the combined CSS height of the left+center+right content panels)
  • className : The class name for styling the top level AccDC Object container
  • prevTitle : Title and screen reader text for the previous button (Must be unique)
  • nextTitle : Title and screen reader text for the next button (Must be unique)
  • slideName : Shared name for a slide, appended to prevTitle and nextTitle for Next Slide and Previous Slide button labeling
  • isGrouped : Must be 'yes' or 'no': Must match the syntax of the XML markup (whether or not the group tag is present)
  • groupName : Shared name for a group, appended to prevTitle and nextTitle for Next Group and Previous Group button labeling
  • showGroup : If 'yes', group names will be displayed above or below the carousel (depending on the value of groupPosTop)
  • groupPosTop : If 'yes', group names are displayed above the carousel, if not, then they are displayed below (only if showGroup='yes')
  • btnPText : Visible textual label for the Previous Slide button; uses innerHTML to insert
  • btnNText : Visible textual label for the Next Slide button; uses innerHTML to insert
  • btnPGText : Visible textual label for the Previous Group button; uses innerHTML to insert
  • btnNGText : Visible textual label for the Next Group button; uses innerHTML to insert
  • btnPAccesskey : AccessKey for the Previous Slide button (for screen reader users)
  • btnNAccesskey : AccessKey for the Next Slide button (for screen reader users)
  • btnPGAccesskey : AccessKey for the Previous Group button (for screen reader users)
  • btnNGAccesskey : AccessKey for the Next Group button (for screen reader users)
  • direction : Must be either 'lr' (left to right), or 'tb' (top to bottom)
  • cycle : Must be either 'yes' or 'no' to set the behavior of infinite looping
  • timer : Set to '0' to disable auto rotation, or set a positive integer for N milliseconds
  • animDelay : Slide animation length in N milliseconds; set to '0' for instant rendering
  • forward : Set to 'yes' or 'no' to configure auto rotation to move backwards or forwards (relative to direction)
  • hiddenMsg : Hidden text message for screen reader users to convey supplementary information

Group attribute definitions:

  • name : The shared name of the group, which will be displayed visually if showGroup='yes'

Slide attribute definitions:

  • announce : The text that will be announced to screen reader users when a slide is manually changed using the navigation buttons.
    If the group tag 'name' attribute value matches the slide tag 'announce' attribute value, then set announce to "" to prevent redundancy for screen reader users.

JavaScript

$A.setCarousel( $A.getEl('myCarousel') , 'path/file.xml' , defaultIndexValue , {
// Configure optional key / value mapping overrides
});

Parameters

  1. The first parameter is the DOM node container element where the carousel will be inserted.

  2. The second parameter is the file path for the associated XML file.

  3. The third parameter is the default slide index value when the carousel is rendered.

    When using a flat carousel, this should be of type 'number', such as 0
    When using a grouped carousel, this should be of type 'string', such as '0,0'

  4. The fourth parameter is a key / value map of optional overrides to customize functionality.

    Example:

    {
    
    // Set the classes for the three floating Div panels that comprise the carousel
    
    // The left Div where the Prev Slide and Prev Group buttons are rendered
    lNavCls: 'lNav',
    // The center Div where the slides are cycled within a relatively positioned container
    contentCls: 'centerContent',
    // The right Div where the Next Slide and Next Group buttons are rendered
    rNavCls: 'rNav',
    
    // Set the nav button element type
    // ('button' is recommended so that the action is automatically triggered when accesskeys are pressed, which doesn't happen for other element types
    btnTag: 'button',
    
    // Set the shared class name for all nav buttons
    btnCls: 'navButton',
    
    // Set the class name for the Next and Previous Slide buttons
    btnSlideCls: 'navSlideButton',
    
    // Set the class name for the Next and Previous Group buttons (if applicable)
    btnGroupCls: 'navGroupButton',
    
    // Set the class name for the Group Name container element (Div tag), which is optionally rendered above or below the center slide container
    groupNameCls: 'groupName',
    
    // Set the hidden heading level for screen reader users (defaults to 3 if omitted)
    ariaLevel: 2,
    
    // Set optional callbacks for the slide rendering action
    handlers: {
    
    // Runs every time a new slide completes rendering
    complete: function(dc){
    
    // 'this' is the Carousel AccDC Object, and is the same as the 'dc' argument
    // The content of the new slide is contained within the DOM node dc.containerDiv
    // E.G alert(dc.containerDiv.innerHTML);
    // dc.top is the top level AccDC Object for the carousel, which can be used to share data between handler functions.
    
    // Other DOM node properties that are available here
    // dc.top.btn.P : The Prev Button DOM node
    // dc.top.btn.N : The Next Button DOM node
    // dc.top.btn.PG : The Prev Group Button DOM node
    // dc.top.btn.NG : The Next Group Button DOM node
    
    // Available state and index values
    // dc.groupVal : the current index value of the currently active Group (if applicable)
    // dc.groupMax : the maximum number of Groups within the carousel
    // dc.slideVal : the current index value of the newly loaded slide (relative to siblings if contained within a Group)
    // dc.slideMax : the maximum number of Slides within the Group or carousel (if contained within a flat list)
    
    },
    
    // Runs every time the Previous Slide button is clicked
    btnPrev: function(ev, dc){
    
    // 'this' is the button element DOM node
    // 'dc' is the Carousel AccDC Object
    // dc.top is the top level AccDC Object for the carousel, which can be used to share data between handler functions.
    
    // Other DOM node properties that are available here
    // dc.btn.P : The Prev Button DOM node
    // dc.btn.N : The Next Button DOM node
    // dc.btn.PG : The Prev Group Button DOM node
    // dc.btn.NG : The Next Group Button DOM node
    
    // Available state and index values
    // dc.groupVal : the current index value of the currently active Group (if applicable)
    // dc.slideVal : the current index value of the newly loaded slide (relative to siblings if contained within a Group)
    
    // Return false to prevent the previous slide from rendering
    },
    
    // Runs every time the Next Slide button is clicked
    btnNext: function(ev, dc){
    
    // 'this' is the button element DOM node
    // 'dc' is the Carousel AccDC Object
    // dc.top is the top level AccDC Object for the carousel, which can be used to share data between handler functions.
    
    // Other DOM node properties that are available here
    // dc.btn.P : The Prev Button DOM node
    // dc.btn.N : The Next Button DOM node
    // dc.btn.PG : The Prev Group Button DOM node
    // dc.btn.NG : The Next Group Button DOM node
    
    // Available state and index values
    // dc.groupVal : the current index value of the currently active Group (if applicable)
    // dc.slideVal : the current index value of the newly loaded slide (relative to siblings if contained within a Group)
    
    // Return false to prevent the next slide from rendering
    },
    
    // Runs every time the Previous Group button is clicked
    btnPrevG: function(ev, dc){
    
    // 'this' is the button element DOM node
    // 'dc' is the Carousel AccDC Object
    // dc.top is the top level AccDC Object for the carousel, which can be used to share data between handler functions.
    
    // Other DOM node properties that are available here
    // dc.btn.P : The Prev Button DOM node
    // dc.btn.N : The Next Button DOM node
    // dc.btn.PG : The Prev Group Button DOM node
    // dc.btn.NG : The Next Group Button DOM node
    
    // Available state and index values
    // dc.groupVal : the current index value of the currently active Group (if applicable)
    // dc.slideVal : the current index value of the newly loaded slide (relative to siblings if contained within a Group)
    
    // Return false to prevent the previous group from rendering
    },
    
    // Runs every time the Next Group button is clicked
    btnNextG: function(ev, dc){
    
    // 'this' is the button element DOM node
    // 'dc' is the Carousel AccDC Object
    // dc.top is the top level AccDC Object for the carousel, which can be used to share data between handler functions.
    
    // Other DOM node properties that are available here
    // dc.btn.P : The Prev Button DOM node
    // dc.btn.N : The Next Button DOM node
    // dc.btn.PG : The Prev Group Button DOM node
    // dc.btn.NG : The Next Group Button DOM node
    
    // Available state and index values
    // dc.groupVal : the current index value of the currently active Group (if applicable)
    // dc.slideVal : the current index value of the newly loaded slide (relative to siblings if contained within a Group)
    
    // Return false to prevent the next group from rendering
    }
    
    }
    
    }
    

Programmatic Control

When the carousel is instantiated, it includes many nested AccDC Objects that are bound using parent / child relationships.

The top level ID for the carousel matches the ID attribute value of the insertion point container element, making it possible to control the carousel programmatically if desired.

Example:

// If the insertion point DIV tag includes id="myCarousel":
// Get a reference to the Carousel AccDC Object
var dc = $A.reg['myCarousel'];

// Which you can then use to access stored data
var data = serialize(dc.form);

// Or close the carousel and remove it from the DOM
dc.close();

// All other AccDC API properties and methods are similarly available if desired.

Important: The Carousel AccDC Object consists of many nested AccDC Objects which act as moving parts, similar to cogwheels within the construct.
So when dc.close() is used to close the carousel, it, including all of its nested objects, are destroyed completely.
(This means that stored data will no longer be available programmatically after a carousel is closed.)
This is done to ensure that duplication and scheduling conflicts don't arise when dynamic content panels are swapped, causing the same carousel structure to be reloaded.

Styling

The sample carousels in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled carousel will be accessible.

Drag and Drop

Drag and Drop isn't called for much as part of a general feature set, but it's good to know how to make this functionality accessible for both screen reader and keyboard only users.

Expected behaviors: All draggable objects must be accessible from the keyboard with or without a screen reader running, and hidden links should be used to identify draggable objects and the location of drop zones.

The Drag and Drop Module automates these processes by adding all related event handlers and managing all related rendering procedures.

JavaScript

$A.setDragAndDrop({
// Configure functionality using a key / value map
});

Parameters

  1. The first parameter configures drag and drop functionality using a key / value map.

    Example:

    {
    
    // Specify the draggable objects using a CSS Selector
    setDrag: 'ul#options li > img',
    
    // Specify the initial drop zone
    setDrop: 'div.chosenBooks',
    
    // CSS Selector or DOM node that specifies an optional strategic focus point where programmatic focus will return after a drop action completes
    returnFocusTo: 'div.chosenBooks h3',
    
    // Set the context node
    root: document,
    
    // Now, since the hidden links need custom link text for each draggable item,
    // we're going to recursively query the data-label attribute for every image and return it
    setName: function(obj){
    // 'obj' is the object that matches the CSS Selector above in 'setDrag'
    return $A.getAttr(obj, 'data-label');
    },
    
    // Set the initial styles for the morphed AccDC Object, which will need absolute positioning
    cssObj:
    {
    position: 'absolute',
    zIndex: 1
    },
    
    // Prevent block formatting when surrounding divs are added
    displayInline: true,
    
    // Run script before the AccDC Object opens
    runBefore: function(dc){
    
    // Do stuff
    
    },
    
    // Run script after the AccDC Object opens
    runAfter: function(dc){
    
    // Do stuff
    
    },
    
    // Configure drag and drop event handlers
    on: {
    
    // Fire when the mouse moves a minimum distance.        
    dragStart: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    },
    
    // Fire every time the mouse moves when dragging.  
    drag: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    },
    
    // Fire when the dragged element moves within the tolerance of a drop target element.  
    dropStart: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    },
    
    // Fire when the dragged element is dropped within the tolerance of a drop target element.  
    drop: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    },
    
    // Fire when the dragged element moves out of the tolerance of a drop target element.  
    dropEnd: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    },
    
    // Fire after all other drag and drop handlers have fired.  
    dragEnd: function(ev, dd, dc){
    // 'ev' is the event object
    // 'dd' is the Drag and Drop custom event object
    // 'dc' is the AccDC Object for the draggable object
    }
    
    },
    
    // Restrict draggability, since there's no point in having stuff wiz around everywhere...
    confineTo: 'div.booksWrapper',
    
    // Set the drop animation time length for keyboard users in milliseconds
    duration: 2000,
    
    // Set keywords for screen reader and keyboard only users
    dragText: 'Move',
    toText: 'to',
    
    // IMPORTANT: All dropTarget elements must include a data-label attribute to specify a unique name for the drop region for screen reader and keyboard only users.
    // View the Coding Arena HTML markup for examples.
    
    actionText: 'Dragging',
    
    // Override default relative positioning to use absolute instead
    // Effects only the hidden drag links when they receive focus
    ddCSS:
    {
    position: 'absolute',
    zIndex: 10
    },
    
    // Set class names for the drag links
    dragClassName: 'ddLink'
    
    }
    

DD Object Properties

The properties and methods of the 'dd' drag and drop custom event object are as follows:

For drag events:

  • target (DOM Node) : The drag element to which the event handler has been bound. (Always the same as "this" within a drag event handler)
  • drag (DOM Node) : The dragged element to which the drag event has been bound.
  • proxy (DOM Node) : The dragged element which determines the drop target tolerance.
  • drop (Array) : An array of all active drop targets for the current drag instance.
  • available (Array) : An array of all available drop targets for the current instance.
  • update (Method) : Helper function that updates the locations of all available drop targets in the current drag instance.
  • startX (Number) : The horizontal location of the "mousedown" event.
  • startY (Number) : The vertical location of the "mousedown" event.
  • deltaX (Number) : The horizontal distance moved from "startX".
  • deltaY (Number) : The vertical distance moved from "startX".
  • originalX (Number) : The starting horizontal position of the dragged element.
  • originalY (Number) : The starting vertical position of the dragged element.
  • offsetX (Number) : The moved horizontal position of the dragged element.
  • offsetY (Number) : The moved vertical position of the dragged element.

For drop events:

  • target (DOM Node) : The drop element to which the event handler has been bound. (Always the same as "this" within an event handler)
  • drag (DOM Node) : The dragged element to which the drag event has been bound.
  • proxy (DOM Node) : The dragged element, which determines the drop target tolerance.
  • drop (Array) : Array of all active drop targets for the current drag instance.
  • available (Array) : Array of all available drop targets for the current drag instance.
  • update (Method) : Helper function that updates the locations of all available drop targets in the current drag instance.
  • startX (Number) : The horizontal location of the "mousedown" event.
  • startY (Number) : The vertical location of the "mousedown" event.
  • deltaX (Number) : The horizontal distance moved from "startX".
  • deltaY (Number) : The vertical distance moved from "startX".
  • originalX (Number) : The starting horizontal position of the dragged element.
  • originalY (Number) : The starting vertical position of the dragged element.
  • offsetX (Number) : The moved horizontal position of the dragged element.
  • offsetY (Number) : The moved vertical position of the dragged element.
Footnotes

Footnotes are simple control types that are easy to make accessible.

Expected behaviors: Provide a link as the footnote that jumps to the footnote text, provide a link at the footnote text that returns focus back to the triggering element (and account for multiple footnote links that lead to the same footnote text), and provide meaningful textual equivalents for screen reader users.

The Footnotes Module automates these processes by creating all necessary anchor elements, adding all related event handlers, and managing keyboard focus appropriately.

HTML Syntax

Footnote text in the body:

<span class="accFootnote" data-footnote="footnotePointer1">My body text</span>

A SPAN tag should be used to surround the word or phrase that you want to designate as a footnote within the body content.

Required attributes for Footnote SPANs in the body:

  • class="accFootnote" : The class name that specifies a footnote link section to be bound. (All footnote tags should share the same class name.)
  • data-footnote : Contains the ID attribute value that points to the specified footnote text at the bottom of the page. (More than one footnote may point to the same footnote text by using the same ID value if multiple footnotes reference the same text)

Important: When the footnotes are parsed using the class name, a numerical index link is generated and appended to the footnote SPAN tag.

Footnote Text nodes in the footer:

<span id="footnotePointer1"></span>

An empty SPAN tag should be used to set the focus point of the Footnote Text node in the footer, which is where focus will be moved to when the footnote link in the body is activated.

The Footnote Text SPAN tag must be placed just before the footnote text in the source code order, since this is where the Footnote Back Link will be inserted.
(This is also where focus is moved to when a footnote link in the body is activated, which must be before the relevant footnote text, and not after.)

The Footnote Text SPAN tag must be empty, and must not surround the footnote text. Doing so will cause the inserted Back Link to appear after the footnote text, instead of before it, as expected.

Required attributes for Footnote Text SPANs in the footer:

  • id="uniqueId" : The unique ID of the Footnote Text node.
    (This must match the value of data-footnote so that each associated footnote link in the body will be properly bound to this focusable node in the footer.)

The following attributes are handled automatically by the Footnotes Module:

  • aria-label

JavaScript

$A.setFootnotes('.accFootnote', document, {
// Configure functionality key / value mappings
});

Parameters

  1. The first parameter is a CSS Selector that specifies all footnote SPAN tags in the body.

  2. The second parameter is the context DOM node where footnote SPANs will be queried using the CSS Selector declared in parameter one. (This makes it possible to query footnotes contained within iFrame documents)

  3. The third parameter configures footnote functionality using a key / value map.

    Example:

    {
    
    // Set the tooltip text for the footnote (this will also be the accessible name for screen reader users)
    fnText: 'Footnote',
    
    // Set the footnote character or text that will comprise the visual link text for returning footnotes
    fnChar: '†',
    
    // Set the tooltip text for the footnote back links (this will also be the accessible name for screen reader users)
    backText: 'Back to Footnote'
    
    }
    

Styling

The sample footnotes in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled footnotes will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The footnotes within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accFootnote", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for footnote SPANs in the body:

  • data-footnote : The ID attribute value of the matching footnote text anchor tag elsewhere in the document (Focus will be moved to this anchor tag when the footnote link is activated)
  • data-fntext : The tooltip text for the footnote (this will also be the accessible name for screen reader users)
  • data-fnchar : The footnote character or text that will comprise the visual link text for returning footnotes
  • data-backtext : The tooltip text for the footnote back links (this will also be the accessible name for screen reader users)

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes:

  • class="accFootnote" : The bootstrap class name that specifies a footnote link to be bound. (Must only be on footnote links in the body, and not upon footnote text anchors in the footer)
  • id : The unique ID of the footnote text anchor tag. (Must only be on footnote text anchors, and must match the data-footnote attribute values for associated footnote links within the body)
Inline Form Field Validation

Error Tooltips provide a simple way to validate user input prior to server side interaction.

Dynamic Help Tooltips work in a similar fashion, by suggesting responses that must also pass validation.

Both fulfill the same role, but on opposite spectrums.

Error Tooltips occur after a form field loses focus, which is when validation occurs.

Dynamic Help Tooltips validate user input as the interaction occurs, so that responses can be adjusted before focus is moved to the next field.

The Form Field Validation Module automates these processes by adding all related event handlers and managing all related rendering procedures.

HTML Syntax

Any standard form field.

Examples:

<label for="field1"> My Text Field: </label>
<input type="text" id="field1" name="whatever1" />

<label for="field2"> My Select : </label>
<select id="field2" name="whatever2">
<option value="v0"> Option One </option>
<option value="v1"> Option Two </option>
</select>

<input type="checkbox" id="field3" name="whatever3" />
<label for="field3"> My Checkbox </label>

<input type="radio" id="field4" name="whatever4" />
<label for="field4"> My Radio Button </label>

The following attributes are handled automatically by the Form Field Validation Module:

  • aria-required

JavaScript

$A.setFormFields( FormElementDOM-Node , {

'formFieldId1': {
// Configure error handling for the form field with id="formFieldId1"
},

'formFieldId2': {
// Configure error handling for the form field with id="formFieldId2"
}

}, function(ev){
// 'ev' is the onSubmit event object for the form element passed in parameter one
// 'this' is the form element
// Optionally do stuff before the form is submitted
// use ev.preventDefault() to cancel if desired
});

Parameters

  1. The first parameter is the form element where the onSubmit event is attached.

  2. The second parameter configures form field bindings using a key / value map.

    Example:

    {
    
    // Configure an error handling tooltip for a form field with a specific ID attribute value
    'formFieldId1': {
    
    errorText: 'Initial error text to be displayed',
    
    // Fire every time the field loses focus
    validate: function(ev, dc){
    // 'this' is the form field to be validated
    // 'dc' is the Tooltip AccDC Object
    // All other AccDC API properties and methods apply to the 'dc' object as well
    // return true to pass validation, or false to fail
    },
    
    // Optionally choose to hide or show the tooltip visually
    // false is set by default if omitted
    hideError: false,
    
    // Set a class to be toggled when an error is detected
    // This will be bound to the dc.triggerObj DOM node, or optionally to the dc.targetObj or dc.classObj DOM node instead if declared.
    // 'validateError' is set by default if omitted
    toggleClass: 'validateError',
    
    overrides: {
    
    // Change the beginning and ending boundary text for screen reader users
    role: 'Error',
    accStart: 'Start',
    accEnd: 'End',
    
    // Change the heading level for screen reader users
    // 3 is set by default if omitted
    ariaLevel: 4,
    
    // Set a class for the tooltip container
    className: 'errorTooltip',
    
    // Change the DOM insertion point to another DOM node by setting targetObj.
    // The triggering Input field is used by default if omitted
    targetObj: DOM-Node,
    
    // Set a node where the toggleClass property value will be toggled when validation fails
    // The triggering Input field or targetObj element is used by default if omitted
    classObj: DOM-Node,
    
    // Optionally set the element where visual positioning calculations will be bound to
    posAnchor: DOM-Node
    
    // Additional AccDC API properties and methods to set as functionality and behavior overrides go here as well
    
    }
    
    },
    
    // Configure a dynamic help tooltip for a form field with a specific ID attribute value
    'formFieldId2': {
    
    helpText: 'Initial help text to be displayed',
    
    // Fire every time the value changes
    validate: function(ev, dc){
    // 'this' is the form field to be validated
    // 'dc' is the Tooltip AccDC Object
    // dc.source can be used to dynamically change the tooltip content (HTML markup is accepted)
    // dc.open() will reopen the tooltip and display the updated content
    // dc.close() will close the tooltip if desired
    // All other AccDC API properties and methods apply to the 'dc' object as well
    // return true to pass validation, or false to fail
    },
    
    // Assign a class to be toggled
    toggleClass: 'passedValidation',
    
    // Set the above class to be toggled only when validation is true, and not when false
    togglePassed: true,
    
    overrides: {
    
    // Change the beginning and ending boundary text for screen reader users
    role: 'Help',
    accStart: 'Start',
    accEnd: 'End',
    
    // Change the heading level for screen reader users
    // 3 is set by default if omitted
    ariaLevel: 4,
    
    // Set a class for the tooltip container
    className: 'helpTooltip',
    
    // Change the DOM insertion point to another DOM node by setting targetObj.
    // The triggering Input field is used by default if omitted
    targetObj: DOM-Node,
    
    // Set a node where the toggleClass property value will be toggled when validation passes or fails
    // (Depends whether 'togglePassed' is set to true or false)
    // The triggering Input field or targetObj element is used by default if omitted
    classObj: DOM-Node,
    
    // Optionally set the element where visual positioning calculations will be bound to
    posAnchor: DOM-Node
    
    // Additional AccDC API properties and methods to set as functionality and behavior overrides go here as well
    
    }
    
    }
    
    }
    
  3. The third parameter is an optional onSubmit handler that will run just before the form is submitted after validation passes.

Styling

The sample tooltips in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled tooltips will be accessible.

Implementation Notes

All form fields must be explicitly labeled to ensure accessibility for the highest percentage of people.

Explicit labelling can be achieved using the LABEL and INPUT elements, by matching the LABEL tag's For attribute with the INPUT tag's Id attribute,
or by setting the Title attribute on the INPUT tag with an informative label,
or by setting the aria-label attribute on the INPUT tag with an informative label,
or by setting the aria-labelledby attribute on the INPUT tag that references the ID of an informative label.

The advantage of using an explicitly associated LABEL element and INPUT tag, is that mouse users can click the label text and automatically activate the form field that it applies to. Voice navigation software also uses explicit LABEL/INPUT tag associations to aid navigation.

This type of functionality does not occur when using the Title attribute or ARIA to explicitly associate a label.

When an INPUT element has an explicitly associated LABEL tag, a Title attribute should not be included. Screen readers often use an order of precedence when reading form field labels, and will often announce one or the other, but not both.

When a form field has an explicit LABEL, additional information can also be associated with the form field using aria-describedby, which will automatically be announced to screen reader users when focus is set to that field.

Example:

<label for="field1"> My Text Field: </label>
<input type="text" id="field1" aria-describedby="additional1" name="whatever" />
<span id="additional1"> Supplementary Text </span>

Important: When implementing supplementary text to be announced for screen reader users, never use "display:none" or "visibility:hidden" to hide the text that is being announced. Doing so will make it impossible for screen reader users to browse the supplementary text using the arrow keys if clarification is needed. If you wish to hide the supplementary text from sighted users, use offscreenText instead.

Modals

A Modal is a relatively simple control type, and can easily be made accessible.

Expected behaviors: Ensure that the background content is hidden from screen reader users, ensure that the beginning and ending boundaries are conveyed to screen reader users, make sure the modal can be closed from the keyboard, and ensure that circular tabbing confines keyboard focus within the modal content.

The Modal Module automates these processes by instantiating the content as a Modal AccDC Object, which can be configured and controlled programmatically if desired to enhance functionality.

HTML Syntax

For the triggering element:

<a href="#" id="modalTrigger"> Triggering Element </a>

(A triggering element is not actually required)

For the modal container element:

<div id="modalContainerId">
Modal content goes here.
</div>

Required HTML5 attributes for the modal container element:

  • data-first="true" : Must be added to the first focusable active element within the modal to control circular tabbing and shift+tabbing.
  • data-last="true" : Must be added to the last focusable active element within the modal to control circular tabbing and shift+tabbing.

Also, when Implementing a Close link or button, the className must match the "closeClassName" property within the JavaScript invocation statement. (If not explicitly set, the default value "lbClose" will be set by default, and should be used for all Close links or buttons) Doing so will automatically bind the AccDC Close Methods with this element, and return keyboard focus properly when the AccDC Object is closed.

The following attributes are handled automatically by the Modal Module:

  • aria-hidden

JavaScript

var modalId = $A.setModal({
// Configure functionality key / value mappings
});

Parameters

  1. The first parameter configures modal functionality using a key / value map.

    Example:

    {
    
    // Set a unique ID for the modal AccDC Object, which can be referenced through $A.reg['uniqueId']
    id: 'uniqueId',
    
    // Set the screen reader accessible boundary text values
    role: 'Modal',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set a triggering element using either the DOM node or a CSS Selector
    // (Only if a triggering element is present, remove otherwise)
    trigger: '#modalTrigger',
    
    // Prevent focus from returning to a triggering element
    // (Only if a triggering element is not present, remove otherwise)
    returnFocus: false,
    
    // Specify that literal content is to be rendered
    // (Only if pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Use removeChild to grab the desired modal content from within the document
    // This is important to prevent ID attribute conflicts later
    // (Only if pulling content from within the same page, remove otherwise)
    source: $A.getEl('modalContainerId').parentNode.removeChild($A.getEl('modalContainerId')),
    
    // Specify the file path and ID attribute of the modal container element
    // (Only if pulling content from an external page, remove otherwise)
    source: 'files/modal.html #modalContainerId',
    
    // Set the class name for the top level container element
    className: 'modal',
    
    // Set the class name for the screen reader accessible close link
    // This must match the class name for any close links or buttons within the modal content, which will cause Close Method Binding to automatically occur when the content is rendered.
    closeClassName: 'lbClose',
    
    // Set the heading level that will be accessible for screen reader users
    // This is set to 1, since a modal constitutes an independent content section equal to a standalone page
    ariaLevel: 1,
    
    // Run script after the Modal AccDC Object finishes loading
    runAfter: function(dc){
    
    // 'dc' is the Modal AccDC Object
    
    // Set a background Div for the modal, so it will appear as a lightbox
    dc.backdrop = $A.createEl('div', null, null, 'modalBackdrop', document.createTextNode(' '));
    // Now insert the backdrop Div before the Modal AccDC Object top level container
    dc.accDCObj.parentNode.insertBefore(dc.backdrop, dc.accDCObj);
    
    // Now configure content bindings within the modal
    // dc.containerDiv is the DOM node where the newly rendered modal content is contained
    
    // All other AccDC API properties and methods are similarly available for the 'dc' object
    
    },
    
    // Run script after the Modal AccDC Object finishes closing
    runAfterClose: function(dc){
    // Remove the backdrop Div
    if (dc.backdrop)
    dc.backdrop.parentNode.removeChild(dc.backdrop);
    }
    
    // (Other AccDC API properties and methods can be declared here also to customize functionality and behavior)
    
    }
    

Programmatic Control

Every modal is registered as an AccDC Object, the ID of which is returned by the JavaScript invocation statement.

This means that you can programmatically control each modal using JavaScript.

Example:

// Get a reference to the Modal AccDC Object using the ID  stored in the modalId variable
var dc = $A.reg[modalId];

// Now invoke the modal
dc.open();

// Or close the modal
dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

A triggering element for a modal is not required, but when one is present, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the Coding Arena samples, these are standard links (A tags with an Href attribute). However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling.

Styling

The sample modals in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the modal. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled modal will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The modals within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accModal", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-src : The resource path and pointer to the ID attribute of the modal container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the modal container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-role : The role name that is conveyed to screen reader users as beginning and ending boundary text for the new content. "Modal" is set by default if no value is specified.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes for the triggering element:

  • class="accModal" : The bootstrap class name that specifies an accessible modal.
  • id : The unique ID of the element. This value is also registered as the ID of the modal AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.

Implementation Notes

Do not use aria-haspopup.

It might sound like a good idea to notify screen reader users that a 'Popup' is attached by adding the attribute aria-haspopup="true" to the triggering element, but this is not a good idea.

Screen readers announce different feedback based on the various combinations of element types and ARIA roles in the markup, which can lead to confusion and misrepresent the purpose of the feature altogether.

Examples:

<!-- Triggering Element One
JAWS 13 and 14 announces as "Has Popup"
NVDA2013 announces as "SubMenu"
-->

<a href="#" aria-haspopup="true"> Triggering Element One </a>

<!-- Triggering Element Two
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<a href="#" role="button" aria-haspopup="true"> Triggering Element Two </a>

<!-- Triggering Element Three
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<button aria-haspopup="true"> Triggering Element Three </button>

In short, don't use aria-haspopup unless you are triggering a menu.

Popups

A Popup is a relatively simple control type, and can easily be made accessible.

Expected behaviors: Ensure that the beginning and ending boundaries are conveyed to screen reader users, make sure the popup can be closed from the keyboard, and ensure that focus moves appropriately when the popup opens and closes.

The Popup Module automates these processes by instantiating the content as a Popup AccDC Object, which can be configured and controlled programmatically if desired to enhance functionality.

HTML Syntax

For the triggering element:

<a href="#" id="popupTrigger"> Triggering Element </a>

For the popup container element:

<div id="popupContainerId">
Popup content goes here.
</div>

When Implementing a Close link or button, the className must match the "closeClassName" property within the JavaScript invocation statement. (If not explicitly set, the default value "popupClose" will be set by default, and should be used for all Close links or buttons) Doing so will automatically bind the AccDC Close Methods with this element, and return keyboard focus properly when the AccDC Object is closed.

JavaScript

var popupId = $A.setPopup({
// Configure functionality key / value mappings
});

Parameters

  1. The first parameter configures popup functionality using a key / value map.

    Example:

    {
    
    // Set a unique ID for the Popup AccDC Object, which can be referenced through $A.reg['uniqueId']
    id: 'uniqueId',
    
    // Set the screen reader accessible boundary text values
    role: 'Popup',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set a triggering element using either the DOM node or a CSS Selector
    trigger: '#popupTrigger',
    
    // Specify that literal content is to be rendered
    // (Only if pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Use removeChild to grab the desired popup content from within the document
    // This is important to prevent ID attribute conflicts later
    // (Only if pulling content from within the same page, remove otherwise)
    source: $A.getEl('popupContainerId').parentNode.removeChild($A.getEl('popupContainerId')),
    
    // Specify the file path and ID attribute of the popup container element
    // (Only if pulling content from an external page, remove otherwise)
    source: 'files/popup.html #popupContainerId',
    
    // Position the popup on the right of the triggering element
    autoPosition: 3,
    
    // Move the Popup AccDC Object 10px to the right, and 20px up when opened
    offsetLeft: 10,
    offsetTop: -20,
    
    // Set the class name for the top level container element
    className: 'popup',
    
    // Set the class name for the screen reader accessible close link
    // This must match the class name for any close links or buttons within the popup content, which will cause Close Method Binding to automatically occur when the content is rendered.
    closeClassName: 'popupClose',
    
    // Set a visually hidden close link for screen reader users to appear at the end of the popup content
    showHiddenClose: true,
    
    // Set the visually hidden close link to appear onFocus (required for 508 compliance if no other keyboard accessible close method is available)
    displayHiddenClose: true,
    
    // Set the heading level that will be accessible for screen reader users
    ariaLevel: 2,
    
    // Run script after the Popup AccDC Object finishes loading
    runAfter: function(dc){
    // 'dc' is the Popup AccDC Object
    // dc.containerDiv is the DOM node where the newly rendered popup content is contained
    // All other AccDC API properties and methods are similarly available for the 'dc' object
    },
    
    // Run script after the Popup AccDC Object finishes closing
    runAfterClose: function(dc){
    // Optionally do stuff
    }
    
    // (Other AccDC API properties and methods can be declared here also to customize functionality and behavior)
    
    }
    

Programmatic Control

Every popup is registered as an AccDC Object, the ID of which is returned by the JavaScript invocation statement.

This means that you can programmatically control each popup using JavaScript.

Example:

// Get a reference to the Popup AccDC Object using the ID  stored in the popupId variable
var dc = $A.reg[popupId];

// Now invoke the popup
dc.open();

// Or close the popup
dc.close();

// All other AccDC API properties and methods can be applied here as well.

Triggering Element Requirements

Regarding the triggering element, you should always use an active element for this purpose to ensure accessibility for both screen reader and keyboard only users.

Within the samples, these are standard links (A tags with an Href attribute). However, you can use whatever type of triggering element you wish, a standard link, button, or image link, with any type of styling. There must be an active element as a triggering element though, to ensure accessibility.

Styling

The sample popups in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like. This is demonstrated within the "Shell" folders, where there is no CSS styling for the popup. This is also useful as a practice template for trying out different styling designs with custom content.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled popup will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The popups within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accPopup", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes for the triggering element:

  • data-src : The resource path and pointer to the ID attribute of the popup container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the popup container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-role : The role name that is conveyed to screen reader users as beginning and ending boundary text for the new content. "Popup" is set by default if no value is specified.
  • data-autoposition : The autoPosition override, which dynamically positions the new content relative to the triggering element. This reflects the autoPosition property documented within AccDC, and may be a value between 0 and 12. The default is 3 if left blank or not included.
  • data-offsetleft : The offsetLeft override, which dynamically positions the new content relative to the triggering element. The default is 10 if left blank or not included.
  • data-offsettop : The offsetTop override, which dynamically positions the new content relative to the triggering element. The default is -20 if left blank or not included.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes for the triggering element:

  • class="accPopup" : The bootstrap class name that specifies an accessible popup.
  • id : The unique ID of the element. This value is also registered as the ID of the Popup AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.

Implementation Notes

Do not use aria-haspopup.

It might sound like a good idea to notify screen reader users that a 'Popup' is attached by adding the attribute aria-haspopup="true" to the triggering element, but this is not a good idea.

Screen readers announce different feedback based on the various combinations of element types and ARIA roles in the markup, which can lead to confusion and misrepresent the purpose of the feature altogether.

Examples:

<!-- Triggering Element One
JAWS 13 and 14 announces as "Has Popup"
NVDA2013 announces as "SubMenu"
-->

<a href="#" aria-haspopup="true"> Triggering Element One </a>

<!-- Triggering Element Two
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<a href="#" role="button" aria-haspopup="true"> Triggering Element Two </a>

<!-- Triggering Element Three
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<button aria-haspopup="true"> Triggering Element Three </button>

In short, don't use aria-haspopup unless you are triggering a menu.

Progress Bars

A Progress Bar control is a relatively simple HTML5 control that, nevertheless, does require a specific implementation in order to work correctly in a backwards compatible manner with Internet Explorer 8.

The Progress Bar module automates this process by instantiating a Progress Bar control that can be programmatically set at runtime as values change.

HTML Syntax

Unobtrusive:

(No HTML markup is needed)

Inline:

<div id="pbTargetZone"></div>

The following attributes are handled automatically by the Progress Bar Module:

  • value
  • aria-valuetext

JavaScript

var myProgressBar = $A.setProgressBar({
// Configure functionality using a key / value map
});

Parameters

  1. The first parameter configures Progress Bar functionality using a key / value map.

    Example:

    {
    
    // Set a unique ID, which will also be the ID attribute value for the 'progress' element when rendered
    id: 'progressbar1',
    
    // Set the boundary text for screen reader users
    role: 'Download',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set initial values for the progress bar, values may be of type Int or Float
    config: {
    value: 0,
    max: 100
    },
    
    // Specify the container element where the Progress Bar AccDC Object will be inserted
    // (Only if pointing to the ID of a target zone container element, remove otherwise)
    isStatic: '#pbTargetZone',
    
    // Specify the container element where the unobtrusive Progress Bar AccDC Object will be inserted
    // (Only if no target zone container tag is present, remove otherwise)
    isStatic: 'body',
    // Also, prepend the progress bar content to the content already contained within the body element
    // This also places it at the top of the page for screen reader users
    prepend: true,
    
    // Set the class name for the top level container Div that surrounds the 'progress' element
    className: 'progressBar',
    
    // Load the Progress Polyfill script after the progress bar is rendered for cross-browser compatibility
    // (The accompanying CSS file must also be included in the header of the page)
    runJSAfter: ['js/progress-polyfill.min.js'],
    
    // Run script after the progress bar finishes rendering
    runAfter: function(dc){
    // Optionally do something
    // dc.source is the DOM node for the rendered 'progress' element
    },
    
    // Run script after the progress bar finishes closing
    runAfterClose: function(dc){
    // Optionally do something
    }
    
    // Other AccDC API properties and methods can be applied here as well if desired
    
    }
    

Programmatic Control

The function "$A.setProgressBar" returns the instantiated AccDC Object for the progress bar, which can then be controlled as follows:

// Render the Progress Bar
myProgressBar.open();

// Update the Progress Bar with a new value
myProgressBar.set(50);

// Then close the Progress Bar after the process has completed
myProgressBar.close();

Styling

The sample Progress Bars in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

Instructions for changing the visual appearance of the 'progress' element are discussed in the article "Cross Browser HTML5 Progress Bars In Depth".

Implementation Notes

To ensure proper rendering across various browsers, the Progress Bar Module requires the following dependencies:

Scrollable Divs

A Scrollable Div is a very simple control type, which can easily be made accessible.

Expected behaviors: Ensure that the scrollable container element receives keyboard focus, and ensure that the Up/Down/Left/Right arrow keys and the PageUp/PageDown and the Home/End keys scroll content appropriately.

The Scrollable Div Module automates these processes by making the scrollable container keyboard accessible.

HTML Syntax

<div id="scrollableDivId">
<div>
Scrollable content goes here.
</div>
</div>

The following attributes are handled automatically by the Scrollable Div Module:

  • tabindex

JavaScript

$A.makeScrollable(scrollableDivDOM_Node, 'textMessageForScreenReaderUsers');

Parameters

  1. The first parameter is the DOM node of the scrollable div container (with 'overflow:auto' in the CSS).

  2. The second parameter is the text string that will be announced to screen reader users the first time that focus moves into the Scrollable Div. (This message alerts VoiceOver users that the region is scrollable.) 'Scrollable Region' is set by default if no value is specified.

Styling

The sample Scrollable Divs in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled Scrollable Div will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The Scrollable Divs within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accScrollable", then configures the same module declaration as previously described using these HTML5 attributes.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes:

  • class="accScrollable" : The bootstrap class name that specifies an accessible Scrollable Div.

Implementation Notes

Do not use aria-haspopup.

It might sound like a good idea to notify screen reader users that a 'popup' is attached by adding the attribute aria-haspopup="true" to the triggering element (if applicable), but this is not a good idea.

Screen readers announce different feedback based on the various combinations of element types and ARIA roles in the markup, which can lead to confusion and misrepresent the purpose of the feature altogether.

Examples:

<!-- Triggering Element One
JAWS 13 and 14 announces as "Has Popup"
NVDA2013 announces as "SubMenu"
-->

<a href="#" aria-haspopup="true"> Triggering Element One </a>

<!-- Triggering Element Two
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<a href="#" role="button" aria-haspopup="true"> Triggering Element Two </a>

<!-- Triggering Element Three
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<button aria-haspopup="true"> Triggering Element Three </button>

In short, don't use aria-haspopup unless you are triggering a menu.

Additionally, no ARIA attributes are necessary to make a Scrollable Div accessible for screen reader users.

VoiceOver instructions for use on iOS touch screen devices:

To navigate the content of a Scrollable Div using VoiceOver, use the Rotator (turn three fingers like turning a knob) to select Line Mode, then use one finger to swipe up and down within the scrollable content to navigate.

(Credit goes to David Hilbert Poehlman for providing VoiceOver rotator navigation technique instructions.)

Tooltips

A Tooltip is a relatively simple control type, which can easily be made accessible.

Expected behaviors: Ensure that the beginning and ending boundaries are conveyed to screen reader users, and make sure the Tooltip is accessible from the keyboard.

The Tooltip Module automates these processes by instantiating the content as a Tooltip AccDC Object, which can be configured and controlled programmatically if desired to enhance functionality.

HTML Syntax

For the triggering element:

<a href="#" id="tooltipTrigger1"> Triggering Element </a>

Or

<input type="..." id="tooltipTrigger2" title="Field name if no Label tag is associated" />

Or

<select id="tooltipTrigger3" title="Field name if no Label tag is associated">
<option value="0"> Option One </option>
<option value="1"> Option Two </option>
</select>

For the tooltip container element:

<div id="tooltipContainerId">
Tooltip content goes here.
</div>

JavaScript

var tooltipId = $A.setTooltip({
// Configure functionality key / value mappings
});

Parameters

  1. The first parameter configures tooltip functionality using a key / value map.

    Example:

    {
    
    // Set a unique ID for the Tooltip AccDC Object, which can be referenced through $A.reg['uniqueId']
    id: 'uniqueId',
    
    // Set the screen reader accessible boundary text values
    role: 'Tooltip',
    accStart: 'Start',
    accEnd: 'End',
    
    // Set the triggering element using a DOM node or a CSS Selector
    trigger: '#tooltipTrigger1',
    
    // Specify that literal content is to be rendered
    // (Only if pulling content from within the same page, remove otherwise)
    mode: 0,
    
    // Use removeChild to grab the desired Tooltip content from within the document
    // This is important to prevent ID attribute conflicts later
    // (Only if pulling content from within the same page, remove otherwise)
    source: $A.getEl('tooltipContainerId').parentNode.removeChild($A.getEl('tooltipContainerId')),
    
    // Set a file path to pull the Tooltip content from and reference the container element ID
    // (Only if pulling content from an external page, remove otherwise)
    source: 'files/tooltip.html #tooltipContainerId',
    
    // Position the Tooltip on the right of the triggering element
    autoPosition: 3,
    
    // Move the Tooltip AccDC Object 10px to the right when opened
    offsetLeft: 10,
    
    // Set the class name for the top level container element
    className: 'tooltip',
    
    // Set the heading level that will be accessible for screen reader users
    ariaLevel: 2
    
    // (Other AccDC API properties and methods can be declared here also to customize functionality and behavior)
    
    }
    

Programmatic Control

Every tooltip is registered as an AccDC Object, the ID of which is returned by the JavaScript invocation statement.

This means that you can programmatically control each tooltip using JavaScript.

Example:

// Get a reference to the Tooltip AccDC Object using the ID  stored in the tooltipId variable
var dc = $A.reg[tooltipId];

// Now change the content of the tooltip
dc.source = 'Hello World';

// All other AccDC API properties and methods can be applied here as well.

Styling

The sample tooltips in the Coding Arena are styled to look a certain way for the demo, but it doesn't actually matter what they look like.

When applying new styles, simply ensure that sufficient color contrast is observed for low vision users, and a focus outline clearly shows which elements have focus, and your newly styled tooltip will be accessible.

Bootstrapping

Bootstrapping is designed to handle common control types that span multiple pages with similar setup configurations.

The tooltips within the Bootstrap folders are configured using HTML5 "data-" attributes within the HTML markup.

When the Bootstrap Module ("accdc_bootstrap.js") is executed, it parses the newly loaded DOM, recognizes the class "accTooltip", then configures the same module declaration as previously described using these HTML5 attributes.

Available HTML5 attributes:

  • data-src : The resource path and pointer to the ID attribute of the tooltip container element. If set, data-internal should be blank or not included.
  • data-internal : The ID attribute of the tooltip container element within the same document. If data-internal is set, data-src should be blank or not included.
  • data-role : The role name that is conveyed to screen reader users as beginning and ending boundary text for the new content. "Tooltip" is set by default if no value is specified.
  • data-autoposition : The autoPosition override, which dynamically positions the new content relative to the triggering element. This reflects the autoPosition property documented within AccDC, and may be a value between 0 and 12. The default is 3 if left blank or not included.
  • data-offsetleft : The offsetLeft override, which dynamically positions the new content relative to the triggering element. The default is 10 if left blank or not included.
  • data-offsettop : The offsetTop override, which dynamically positions the new content relative to the triggering element. The default is 0 if left blank or not included.

Additional HTML5 attributes can be added to enhance functionality by editing the file "accdc_bootstrap.js".

Required attributes:

  • class="accTooltip" : The bootstrap class name that specifies an accessible tooltip.
  • id : The unique ID of the element. This value is also registered as the ID of the Tooltip AccDC Object, making it possible to invoke the object programmatically.
    E.G $A.reg.uniqueID.open();
    // All other AccDC API properties and methods are similarly available.

Implementation Notes

When an A tag is used as the triggering element, it must adhere to the following:

  1. If the element contains no link text and no Img element, then the link should include an informative Title attribute. (This is only valid if there is no link text at all)
  2. If the element contains an Img tag and no link text, then the Img tag should include an informative Alt attribute and Title attribute, both of which should match.
  3. The A tag must include an Href attribute, to ensure keyboard accessibility.

Do not use aria-haspopup.

It might sound like a good idea to notify screen reader users that a 'Popup' is attached by adding the attribute aria-haspopup="true" to the triggering element, but this is not a good idea.

Screen readers announce different feedback based on the various combinations of element types and ARIA roles in the markup, which can lead to confusion and misrepresent the purpose of the feature altogether.

Examples:

<!-- Triggering Element One
JAWS 13 and 14 announces as "Has Popup"
NVDA2013 announces as "SubMenu"
-->

<a href="#" aria-haspopup="true"> Triggering Element One </a>

<!-- Triggering Element Two
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<a href="#" role="button" aria-haspopup="true"> Triggering Element Two </a>

<!-- Triggering Element Three
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<button aria-haspopup="true"> Triggering Element Three </button>

In short, don't use aria-haspopup unless you are triggering a menu.

Web Chat

The concept of Web Chat seems complicated, but it's actually quite easy to make accessible for screen reader and keyboard only users.

This may not be readily apparent by reading the JavaScript code for the chat demo in the Coding Arena however, so I'll outline the concepts that make it accessible here, to simplify things.

  1. When the chat popup loads in the DOM, the content is appended to the 'body' element, so that it appears at the bottom of the page for screen reader users. This is important, because as new messages are received, the Virtual Buffer line numbers within the body content won't change. This is often what causes focus reading issues when trying to navigate within body content if nodes higher up in the DOM tree continually update themselves, which quickly becomes an accessibility issue.
  2. After the chat popup is rendered, focus is automatically moved into the message field. To aid with this, the surrounding Div tag for the message field, includes the ARIA attribute role="application". This forces JAWS 14 to automatically enter Applications Mode when the field receives focus in both IE and Firefox.
  3. The message field consists of a Textarea element. This is important, since this allows screen reader users to press Enter to submit new messages without automatically exiting Forms Mode, which would occur if an Input element was used instead.
  4. The scrollable chat window is keyboard accessible, so that keyboard only users can simply Shift+Tab into the message field and use the Up/Down arrow keys and the PageUp/PageDown/Home/End keys to read through previously posted messages.
  5. The Close icon is keyboard accessible, and pressing Escape will alternately close the Chat Popup.
  6. Now, here is where the magic is for screen reader users. Whenever new messages arrive, they are automatically announced. This is accomplished using the $A.announce() method, which automatically queues incoming messages using Unobtrusive Announcement to prevent speech interruption. It also can be set to ignore repetitive messages by passing true as the second parameter.

    Example:

    $A.announce(LastMSG-DOM-Node, true);
    

The $A.announce() method is also prototyped to the String object, so it can be invoked by returning strings as well for storage if desired.

Example:

var msgHistory = [],
msgTextString = 'Howdy!';

msgHistory.push( msgTextString.announce() );

Which will both store the string contained in the variable msgTextString and announce it to screen reader users at the same time.

When a chat dialog is closed, the following method may be invoked:

String.announce.clear();

This will clear the queue so that message announcement does not continue to occur after the chat dialog is closed.

Announce Method Details

The AccDC Announce method has been tested successfully using JAWS 11-14, NVDA, and VoiceOver, in Internet Explorer 8-9, Firefox, Chrome, and Safari with applicable screen readers.

JavaScript

$A.announce( StringOrDOMNode , SuppressRepeat?<true/false> , isAggressive?<true/false> );

Or

var myString = anotherString.announce();

$A.announce() Parameters

  1. The first parameter is a DOM node or text string to be announced. (Repetitive messages will automatically be queued for announcement.)

  2. The second parameter is a Boolean value that specifies whether the announcement of repeat message text is automatically suppressed.
    If set to true, repetitive text will not be announced to screen reader users.
    False is set by default if no value is specified.

  3. The third parameter is a Boolean value that specifies whether aggressive announcement will be used to announce text.
    If set to true, prior speech output will be interrupted and the latest text message will be forcibly announced. This will occur regardless which window currently has focus, and is not desirable in most cases.
    False is set by default if no value is specified.

Programmatic Control

Manually clear the message queue

String.announce.clear();

Access the last message that was announced

var last = String.announce.lastMsg;

Adjust the initial delay in milliseconds when the "$A.announce()" method queues messages to be announced sequentially

String.announce.baseDelay = 2000;

Adjust the delay in milliseconds when a message using "$A.announce()" contains two or more words including punctuation.

String.announce.charMultiplier = 160;

Implementation Notes

Important: Unobtrusive Announcement should only be used sparingly, and not for everything.

When too many things are announced on the same page, it is difficult for screen reader users to differentiate between what is being announced, and what is being navigated using the arrow keys. This is because the same voice is used for both, with no distinction.

ARIA Warnings

Improper Use of ARIA

Even though ARIA stands for Accessible Rich Internet Applications, the improper use of ARIA will actually cause accessibility issues for screen reader users.

Important things to be aware of:

  • Strict care and comprehensive screen reader testing must always be applied whenever implementing ARIA within HTML markup.
  • Don't ever assume, just because it's documented in the ARIA specification, that it will be accessible.
  • If the component or feature is not accessible to screen reader users, it is not accessible, no matter what the specification says.
  • Adherence to the ARIA specification cannot be used as an excuse for components and features that are not accessible to screen reader users.

Improper use of ARIA examples:

Example 1: Phantom form fields

<form>
<div id="lgnd">
Contact Details
</div>
<div role="textbox" aria-label="Your full name" aria-required="true" aria-describedby="lgnd">
<input type="text" name="full_name" />
</div>
<div role="textbox" aria-label="Your email address" aria-required="true" aria-describedby="lgnd">
<input type="text" name="email_address" />
</div>
</form>

Since the use of role="textbox" is used to surround a native form field, JAWS sees two form fields when using the Arrow keys to navigate up and down the page, causing confusion for screen reader users.

Similarly, since all supporting attributes such as aria-label, aria-describedby, and aria-required are applied to the wrong elements, they are not accessible as a result.

Example 2: Unreadable content

<table role="tree">
<tr role="treeitem">
<td>
Name:
</td>
<td>
Bryan Garaventa
</td>
</tr>
<tr role="treeitem">
<td>
Title:
</td>
<td>
Bryan Garaventa - Resume
</td>
</tr>
<tr role="treeitem">
<td>
File Type:
</td>
<td>
PDF
</td>
</tr>
</table>

The use of role="tree" and role="treeitem" on this table, literally makes it impossible to read the table content using JAWS.

Example 3: Mixing roles

<div role="tablist">
<div role="tab">
<h2>
<a href="#"> Link One </a>
</h2>
</div>
<div role="tab">
<h2>
<a href="#"> Link Two </a>
</h2>
</div>
<div role="tab">
<h2>
<a href="#"> Link Three </a>
</h2>
</div>
</div>

Since screen readers convey certain role types (such as Tabs) as form controls, the nesting of additional active elements confuses screen reader output.

Example 4: Confusing feedback

<textarea title="Status" aria-haspopup="true"></textarea>

<textarea title="Comment" aria-expanded="true"></textarea>

In the case of aria-haspopup on the edit field, only "Has Popup" is announced by JAWS, which is confusing. "Has Popup" does not convey what the purpose of the popup is, nor does it indicate how to invoke it. NVDA announces "Edit SubMenu", which is even more confusing.

In the case of aria-expanded on the edit field, "Edit Expanded" is announced by screen readers, which is superfluous. The content of all edit fields, even when scrolled off screen visually, is always visible to screen reader users, so announcing expanded means nothing to screen reader users.

Conclusion

Whenever ARIA is applied, it must be thoroughly tested using JAWS in Internet Explorer and using NVDA in Firefox. These are the two most widely used Windows based screen readers in the world. JAWS is hard coded to work best in Internet Explorer, and NVDA is hard coded to work best in Firefox.

If mobile support is needed, VoiceOver on iOS devices is the most widely used screen reader that should be used for testing. TalkBack on the Android is the second most widely used.

Important: Even when ARIA is implemented correctly and precisely according to the specification, if adding certain ARIA attributes causes accessibility issues for screen reader users to occur, then they should not be used.

aria-haspopup

The attribute aria-haspopup should only be used on triggering elements that open menus. Otherwise, the presence of the attribute will only misrepresent the popup type to screen reader users.

Examples:

<!-- Triggering Element One
JAWS 13 and 14 announces as "Has Popup"
NVDA2013 announces as "SubMenu"
-->

<a href="#" aria-haspopup="true"> Triggering Element One </a>

<!-- Triggering Element Two
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<a href="#" role="button" aria-haspopup="true"> Triggering Element Two </a>

<!-- Triggering Element Three
JAWS 13 and 14 announces as "Menu"
NVDA2013 announces as "Menu Button SubMenu"
-->

<button aria-haspopup="true"> Triggering Element Three </button>
role="presentation"

The attribute role="presentation" should only be used in very limited circumstances, and only when it is desirable to suppress the role of an element for screen reader users.

Many element types have particular roles that are automatically conveyed to screen reader users.

Examples include headings, links, buttons, images, lists, frames, tables, form fields, and many others. All of which have specific relevance for screen reader users, who depend on the identification of these roles to navigate reliably within web pages.

When role="presentation" is added to the markup of such an element, it manually overrides this role mapping in the browser, and prevents the screen reader from identifying or even interacting with the element in the expected manner.

Example 1: Headings

<h2 role="presentation"> Key Section Heading </h2>

It is now impossible for screen reader users to navigate to the heading using the H and Shift+H key commands, nor is the text identified as a heading while browsing down the page using the arrow keys.

Example 2: Links and Buttons

<a href="#" role="presentation"> Triggering Element </a>

<button role="presentation"> Triggering Element </button>

It is now impossible for screen reader users to identify these elements as actionable elements during navigation.

Example 3: Tables

<table role="presentation">
<tr>
<th scope="col">
Product
</th>
<th scope="col">
Quantity
</th>
</tr>
<tr>
<td>
Doorknob
</td>
<td>
2000
</td>
</tr>
</table>

It is now impossible for screen reader users to navigate the data table using table navigation commands.

Whenever role="presentation" is added to HTML markup, it must always be tested using JAWS, NVDA, and VoiceOver (if applicable) to ensure that the element type remains accessible for screen reader users.

Event Model Differences

onFocus

When JAWS interacts with the Virtual Buffer, making it possible for screen reader users to navigate from the top of the page to the bottom using the Down arrow key, it will not automatically trigger the onFocus handler.

When you do the same using NVDA however, it will automatically trigger the onFocus handler.

This means that, any elements that cause specific actions to occur, such as simulated Tab controls, simulated Radio Button controls, or any other control type that uses onFocus to invoke selection, will automatically be triggered by NVDA in both IE and Firefox when using the arrow keys to navigate page content.

Example 1: Tabs

<div role="tablist">
<div role="tab" tabindex="0" onfocus="alert('Switch content 1');"> Label One </div>
<div role="tab" tabindex="-1" onfocus="alert('Switch content 2');"> Label Two </div>
<div role="tab" tabindex="-1" onfocus="alert('Switch content 3');"> Label Three </div>
</div>

In JAWS, you can use the arrow keys to navigate between tabs and press Enter on the announced tab to activate it.

In NVDA however, using the arrow keys to announce each tab will automatically activate it.

Example 2: Implied form field labels

<input type="text" value="Street Address 1" onfocus="this.value=''" /><br />
<input type="text" value="Street Address 2" onfocus="this.value=''" /><br />
<input type="text" value="City" onfocus="this.value=''" /><br />
<input type="text" value="State" onfocus="this.value=''" />

In JAWS, setting focus to the Input field will cause the value to be cleared.

In NVDA however, using the arrow keys to navigate down the page will cause the form fields to be cleared.

Important: This method of form field labeling should never be used.

onClick vs onKeypress

The events that are triggered for certain elements depend on the type of element that is being activated.

For example, adding an onClick handler to a natively active element such as an A tag with an Href attribute, or a BUTTON element, will be accessible for both mouse and keyboard users, regardless whether a screen reader is running or not.

However, if you do the same for a natively non-active element, such as a DIV or SPAN tag, it will not be accessible from the keyboard without a screen reader running.

Example 1: Standard link

<a href="#" onclick="alert('Clicked');" > Triggering Element </a>

This link is actionable from the keyboard with or without a screen reader running, and can be activated using the mouse.

Example 2: Simulated link with no onKeypress

<span role="link" tabindex="0" onclick="alert('Clicked');" > Triggering Element </span>

This simulated link is actionable from the mouse, and for screen reader users in Virtual Buffer Mode. However, it is not actionable for keyboard only users that have no screen reader running, nor is it actionable for screen reader users in Applications Mode.

Example 3: Simulated link with both onClick and onKeypress

<span role="link" tabindex="0" onkeypress="kpHandler(this, event);"
onclick="alert('Clicked');" > Triggering Element </span>
<script type="text/javascript">
function kpHandler(obj, ev){var k = ev.which || ev.keyCode; if (k == 13)alert('Pressed');}
</script>

This simulated link is actionable from the mouse and from the keyboard with or without a screen reader running. However, the onKeypress is only activated for screen reader users in Applications Mode, and for keyboard only users,
and the onClick is only activated for mouse users, and for screen reader users in Virtual Buffer Mode.

Event Propagation

Many accessibility issues arise when nesting active elements, which directly effects event propagation.

Example: Nested active elements

<div role="link" tabindex="0" onkeypress="kpHandler(this, event);"
onclick="alert('DIV clicked');" >
<img
alt="Triggering element"
src="icon.png"
onclick="alert('IMG clicked');"
/>
</div>
<script type="text/javascript">
function kpHandler(obj, ev){var k = ev.which || ev.keyCode; if (k == 13)alert('DIV pressed');}
</script>

This simulated image link performs different actions depending on the action mode (mouse or keyboard), and also depending on the browse mode for screen reader users.

  • Mouse users will trigger the onClick for both the IMG and DIV, but not the onKeypress.
  • Keyboard only users without a screen reader will trigger the DIV onKeypress, but neither of the onClicks.
  • Screen reader users in Virtual Buffer Mode will trigger the onClick for both the IMG and DIV, but not the onKeypress.
  • Screen reader users in Applications Mode will trigger the DIV onKeypress, but neither of the onClicks.

It is, therefore, very important to ensure that nested active elements are not used to perform different actions.