ARIA Menus

Expected behaviors

Move focus into the menu when it is rendered, ensure that each menu has only one tab stop and that available menu items can be navigated using the arrow keys, make sure the menu can be closed from the keyboard, and move focus back to the triggering element after the menu is removed.

The 4X ARIA Menu module automatically configures all required ARIA attributes and focus handling, in strict accordance with the ARIA specification.

The following attributes are handled automatically by the Menu module:

  • role=menu
  • role=menuitem/menuitemcheckbox/menuitemradio
  • aria-checked
  • aria-haspopup
  • aria-orientation
  • tabindex

Available attributes for the triggering element:

  • menu : The resource path and pointer to the ID attribute of the menu container element.

Available attributes for menu item links:

  • data-menu : The resource path and pointer to the ID attribute of the submenu container element.
  • data-radio : May be set to "false" or "true" to set the current state of a radio menu item when rendered.
  • data-check : May be set to "false", "true", or "mixed" to set the current state of a checkbox menu item when rendered.

HTML syntax

Standard Menu

<ul id="menuId">
  <li>
    <a href=" ... " >
      Accessible name and markup.
    </a>
  </li>
</ul>

Standard Menu Including Submenu

<ul id="menuId">
  <li>
    <a href=" ... " >
      Accessible name and markup.
    </a>
    <ul>
      <li>
        <a href=" ... " >
          Accessible name and markup.
        </a>
      </li>
    </ul>
  </li>
</ul>

Standard Menu Including Checkable Items

<ul id="menuId">
  <li>
    <a data-check="false" href=" ... " >
      Accessible name and markup.
    </a>
  </li>
</ul>

Standard Menu Including Checkable Radios

<ul id="menuId">
  <li>
    <a data-radio href=" ... " >
      Accessible name and markup.
    </a>
  </li>
  <li>
    <a data-radio="true" href=" ... " >
      Accessible name and markup.
    </a>
  </li>
</ul>

IMPORTANT: An ARIA Menu must never include any other active elements other than those specified as menu items. Otherwise, all such additional active elements will be undiscoverable and inaccessible to non-sighted screen reader users.

JavaScript syntax

var myMenuDC = $A.setMenu( domNodeOrCSSSelectorForTriggeringElement , {
// Configure functionality key / value mappings
});

Parameters

  1. A DOM element or CSS selector to specify the triggering element
  2. A configuration map to customize behaviors and options

Configuration

{

// Optionally set a unique ID for the menu DC object, which can be referenced through $A('uniqueId')
// If not specified, the id of the triggering element will be used instead.
id: 'uniqueId',

// Optionally specify the content to be rendered when referencing internal content.
// May be a DOM node or CSS selector.
// Not necessary if menu is set on the triggering element.
content: "#uniqueId",

// Specifies that the referenced content for rendering should not be dynamically inserted into the DOM, but will instead toggle the hidden attribute.
toggleHide: true,

// Optionally specify the content to be rendered when referencing external content.
// Not necessary if menu is set on the triggering element.
// If set, the content property will be auto-populated with the returned content.
fetch: {
url: "path/file.htm",
data: {
selector: "#uniqueId"
}
},

// Choose the type of mouse interaction for the triggering element.
// When rightClick is true, pressing Shift+F10 or the Applications key will perform the same action as right clicking.
leftClick: true,
rightClick: false,

// Specify the tag names for the parent and child elements that will be matched against when building the menu structure.
tag: {
parent: "ul", // Will become the container with role="menu"
child: "a" // Will become the focusable active element with role="menuitem", "menuitemcheckbox", or "menuitemradio"
},

// Set a custom event handler to process every time a menu item is activated.
onActivate: function(event, triggerNode, RTI, boundElement, currentState, set) {
// If triggerNode opens a submenu, boundElement will reference the associated submenu DC object.
// Otherwise, if triggerNode is checkable, boundElement will reference the hidden checkbox or radio element if present.
// If the menu item is checkable, currentState will include a number from 0 to 2.
// (0 = "false", 1 = "true", 2 = "mixed".)
// The set function can be used to set a new state for the option.
// E.G. set("false"), set("true"), or set("mixed") for checkbox menu items only.
},

// Set the class name for the top level container element
className: 'menu',

// 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 menu content, which will cause close event binding to automatically occur when the content is rendered.
closeClassName: "CloseDC",

// Preload markup in the background when using the Fetch API to load external content.
// For examples, view files within "Templates/Menus".
preload: true,

// Preload images in the background when using the Fetch API to load external content.
// For examples, view files within "Templates/Menus".
preloadImages: true,

// Optionally run a script after the menu finishes rendering.
afterRender: function(DC) {
// DC.container includes the rendered menu content.
},

// Optionally run a script after the menu is removed.
afterRemove: function(DC) {
// Do something.
},

// Optionally specify a render and remove animation effect for the menu.
// Requires the "Animate" module import to function, which is powered by Velocity.js.
// To ignore animation effects, delete the animate object declaration entirely from the setup script.
// View implementations within "Templates/Menus" for practical animation usage examples.

style: { display: "none" }, // Set the initial state to hidden in prep for animation.

animate: {

onRender: function(dc, wrapper, next) {

// Specify the render animation effect, including the callback function statement to execute when the animation effect completes.
Velocity(wrapper, "transition.TYPE", {
// Velocity options here, plus the callback declaration after the animation completes.
complete: function() {
next(); // REQUIRED: next() must be executed so control is passed back to 4X for rendering.
}
});

},

onRemove: function(dc, wrapper, next) {

// Specify the removal animation effect, including the callback function statement to execute when the animation effect completes.
Velocity(wrapper, "transition.TYPE", {
// Velocity options here, plus the callback declaration after the animation completes.
complete: function() {
next(); // REQUIRED: next() must be executed so control is passed back to 4X for removal.
}
});

}

},

// Optionally extend the RTI instance with custom event handlers.
// For available options, view the RovingTabIndex help doc at "Help/Module Imports/Actions/RovingTabIndex".
extendRTI: {
// Optional event handlers.
}

// Additional DC API properties and methods can be declared here also to customize functionality and behavior.
// To view available options, reference the help docs located at: "Help/DC API/DC Object Configuration"

}

Programmatic control

// Get the DC object for the top level menu using its id.
var DC = $A("menuTriggerId");

// Open the menu manually.
DC.render(function() {
// Optionally do something after rendering completes.
});

// Close the menu manually.
DC.remove(function() {
// Optionally do something after removal completes.
});

// Additional DC API properties and methods can be applied here as well.
// To view available options, reference the help docs located at: "Help/DC API/DC Object Properties and Methods"