Web Accessibility Properties and Actions (WAPA) Explainer

Note: The name of this functionality is still an open question

Unofficial Draft 24 October 2014

Editors:
Cynthia C. Shelly, Microsoft, cyns@microsoft.com

Abstract

This document is a non-normative reference, which provides an overview of a set of User Intention Events that build on ARIA to extend accessibility functionality to complex, scripted web applications in use cases where markup-based solutions have proven impossible, difficult or costly to implement.

Status of This Document

This document is a draft of a proposal to the w3c. Our hope is that it would be incorporated into the PF ARIA taskforce, DOM or WebApps work. It is an early draft and has no normative standing.

Table of Conents

1 Introduction

Web Accessibility Properties and Actions (WAPA) allows more direct communication between web applications and platform accessibility APIs. It includes three pieces

  1. A way for web authors to provide ARIA name-value pairs (properties) to accessibility APIs from script, without requiring an element with those aria properties in the Document object.
  2. A way for web authors to react in script to method calls from accessibility APIs (actions)
  3. A mechanism for handling accessibility information for virtualized content, where the DOM is only a subset of the actual dataset or document.
Question: Should virtualization be a separate spec?

2 Web Accessibility Properties

AT Request for Accessible node property via accessibility API

Swimlane flowchart of ariarequest object
  1. AT calls Accessibility API via OS requesting the value of a property on the Accessible node
  2. Accessibility API queries browser
  3. Browser gets the DOM element assosicated with the Accessible node
  4. Browser checks whether the attribute exists on the element
  5. If no
    1. Browser sends DOM event ariarequest
    2. Javascript catches ariarequest event
    3. Javascript sets attributeValue for the attributeName
    4. If cancel default, end
  6. If yes (or fall through)
    1. Browser gets aria name-value pair from dom
  7. Browser updates accessibility API with name-value pair
  8. Accessibility API returns name-value pair to calling AT

IDL


            [Constructor(DOMString type, optional AriaRequestEventInit eventInitDict)]
            interface AriaRequestEvent : Event {
                readonly attribute DOMString attributeName;
                attribute DOMString attributeValue;
            };
            dictionary AriaRequestEventInit : EventInit {
                DOMString attributeName = null;
                DOMString attributeValue = null;
            };
        

3 Web Accessibility Actions

AT Action taken by user

Swimlane flowchart of command event initiated by AT"
  1. User takes action on an element using an AT
  2. AT calls accessibility API method on that element
  3. Accessibility API runs that method against browser
  4. Browser sends User Intention Event on that element with the commandType for the action from the accessibility API (See Mapping Table below for example of UIA to CommandType mappings)
  5. Javascript catches User Intention Event
  6. Javascript modifies DOM attributes and/or script representation of object
  7. If canceldefault, end
  8. browser does action on element using default mechanisms
How do you know if you were successful? UIA methods have return values. Do the other AAPIs?

IDL


            [Constructor(DOMString type, optional CommandEventInit eventInitDict)]
            interface CommandEvent : Event {
                readonly attribute DOMString commandType;
                readonly attribute DOMString detail;
            };
            dictionary CommandEventInit : EventInit {
                DOMString commandName = null;
                DOMString detail = null;
            };
        

4 Mapping to Accessibility APIS

Example: CommandTypes to UIA methods

NOTE: Other APIs need to be fleshed out. Most of these would be default action in MSAA.
NOTE: CommandType naming needs to be updated to sync better with User Intentions, ARIA and IndieUI. It is currently based on the closely related UIA methods.

commandType UIA method
Toggle IToggleProvider::Toggle
Expand IExpandCollapseProvider::Expand
collapse IExpandCollapseProvider::Collapse
scrollIntoView IScrollItemProvider::ScrollIntoView
Select ISelectionItemProvider::Select
addToSelection ISelectionItemProvider::AddToSelection
removeFromSelection ISelectionItemProvider::RemoveFromSelection
setValue IValueProvider::SetValue
scrollHorizontal IScrollProvider::Scroll
scrollVertical IScrollProvider::Scroll
setHorizontalScrollPercent IScrollProvider::SetScrollPercent
setVerticalScrollPercent IScrollProvider::SetScrollPercent

5 Use Cases

5.1 Performance improvement with Just-in-Time loading of accessibility information

The developer wants to provide accessibility information only when it is requested by AT via the Accessibility API, and not at the time the DOM is filled in.

This mechanism works with the @role attribute and any @aria- attribute.

JavaScript Sample


        <div id="listbox1" role="listbox" onariarequest="HandleRequest(event);">
            <div role="listitem">Item 1</div>
            <div role="listitem">Item 2</div>
            <div role="listitem">Item 3</div>
                …
            <div role="listitem">Item 100</div>
        </div>
        <script>
            function manageList(event) {
                var listbox = document.getElementById('listbox1');
                if (event.target.parentNode == listbox) {
                    if (event.attributeName === "posinset") {
                        event.attributeValue = GetChildId(event.target);
                    }
                    else if (event.attributeName === "setsize") {
                        event.attributeValue = "100";
                    }
                }
            }
      </script>
                

TODO: Add another example with a different attributename

5.2 Accessibility information Stored outside DOM

An application uses javascript objects to store all of its state (accessibility and other state), and only uses the DOM as a drawing surface. The goal is to treat accessibility state the same way as other state, and to manage it directly from script.

element.onariarequest is a new event that gets fired when an AT requests makes an Accessibility API request that maps to aria information

element.oncommand is a User Intention Event

TODO: update to match API naming changes in User Intention Events

event.attributeName is the attribute that changed as part of the event. This is a new attribute we are proposing to add to the DOM Event Object

event.preventDefault(); stops the default processing of the event.

element.NotifyAriaStateChange(string) toggles a boolean aria state. It is equivalent to element.setAttribute("aria-"+string, true) or element.setAttribute("aria-"+string, false)

TODO: what about non-bolean aria attributes?

NOTE: I'm not positive this is necessary. Thoughts?

JavaScript Sample


        <script>
            var toggleState = false;
            function HandleRequest(event) {
                var myCheckbox = document.getElementById("myDiv");
                if (event.attributeName === "checked" && event.target === myCheckbox) {
                    event.attributeValue = (toggleState ? "true" : "false";
                }
            }
            function HandleCommand(event) {
                var myCheckbox = document.getElementById("myDiv");
                if (event.target === myCheckbox && event.commandName === "toggle") {
                    toggleState = !toggleState;
                    UpdateUI();
                    event.preventDefault();
                }
                function ToggleMe(){
                    toggleState = !toggleState;
                    var myCheckbox = document.getElementById("myDiv");
                    myCheckbox.NotifyAriaStateChange("checked");
                }
            }
        </script>
        <div id="myDiv" role="checkbox" oncommand="HandleCommand(event)" onariarequest="HandleRequest(event);" onclick="ToggleMe();">
        
Double check calling syntax

5.3 Virtualized Content

A user opens a large document in the Word web app. Word adds the first page or two to the DOM, but not the whole document. When the user reaches the end of the loaded portion of the document, more content is loaded.

How will a screen-reader user know:

How will an AT product signal to the app that it needs to load more content?

How will an app let AT products know that more content is loading and that focus should not move out of the content container?

Not all content is in the DOM, or the DOM contains little actual meaning for the content (the DOM is just a view). Requiring that the information be available on the DOM objects is hard to impossible depending on the app. This is used by apps like Office Online, where the content is stored in the backend and only a specific view (such as the current page of a document) is actually available in the DOM.

JavaScript Sample


            <script>
            function HandleCommand(event) {
                var myContainer = document.getElementById(" content");
                if (event.target == myContainer && event.commandname == "contentLoaded" ) {
                appendcontent(mycontainer);
                event.preventdefault();
            }
            function handlecommand(event) {
                var mycontainer=document.getElementById("content");
                if (event.target == myContainer && event.commandname == "contentRequested" ) {
                mycontainer.setattribute("aria-busy","true");
                event.preventdefault();
            }
            function handlecommand(event) {
                var mycontainer=document.getElementById("content");
                if (event.target == myContainer && event.commandname == "contentTimeout" ) {
                displayerror();
                event.preventdefault(); />
            }
            function HandleCommand(event) {
                var myContainer = document.getElementById("content");
                if (event.target == myContainer && event.commandName == "contentEnd") {
                    //do Nothing
                    event.preventDefault();
                }
        </script>
<body>
<div id=toolbar>
                <!-- some UI for the page, which is not virtualized -->
            </div>
            <!--
             This area is the content of the page, only part of which is loaded.
             More will be loaded when the user reaches the bottom of the page.
             aria-async is a proposed new aria attribute that marks the area that
             contains virtualized content
            -->
<div id=content aria-async="true" oncommand="HandleCommand(event);">
                <!-- the first 'chunk' of content.  A page, a set of images, etc. -->
            </div>
<div id=sidebar>
                <!-- content which is not virtualized -->
            </div>
        </body>
        
            

aria-async is new aria-attribute which means that the content is may be virtualized.

TODO: Think about naming, and relationship with aria-busy and other live region features

Four new User Intentation Events:

How does the server indicate this? Is that something we need to define, or up to the app?

TODO: Add where the requestcontent comes from

5.4 Custom Elements (Future)

A developer encapsulates functionality in a control that can be called using a custom element tag. Using DARIA, the developer can define default ARIA roles, states and properties, so that those will be mapped to UIA (and other accessibility APIs) in the same way that the default roles, states and properties of native HTML elements are mapped.

Custom Elements

WAPA allows more direct communication with accessibility APIS via script, including the ability to intercept accessibility API actions. We believe that this can be used to hook up custom elements to web accessibility APIs and allow AT products to interact with them.

5.5 WebDriver testing of accessibility (Future)

Because WAPA is an in-browser javascript API, rather than a platform accessibility API, we may be able to simulate the effect of an AT acting on content by sending the same command events that the browser would send based on AT action. This would allow WebDriver to exercise accessibility functionality in web apps.

6 Relationship to Other work

6.1 Relationship to User Intention Events

WAPA is a set of User Intention Events. It builds on that work to hook into the accessibility layer, and has a dependency on that work.

A User Intention event will be fired whenever an action is taking place, such as toggling a checkbox, to allow authors to hook the action and perform any specific actions they need to, such as updating state and UI, with the option to prevent the default behavior (a simulated click, if applicable). For this, a new event will be added:


        [Constructor(DOMString type, optional CommandEventInit eventInitDict)]
        interface CommandEvent : Event {
            readonly attribute DOMString commandName;
            readonly attribute DOMString detail;
        };
        dictionary CommandEventInit : EventInit {
            DOMString commandName = null;
            DOMString detail = null;
        };
        

The 'detail' payload part of this event is an extra piece of information defining the event, if necessary, such as the value for a SetValue command.

A User Intention event will fire whenever an AT invokes an action via the accessibility APIs:

Swimlane diagram of command events.  First the Accessibiltiy Tool sends a command to the browser to toggle the checkbox.  Next, the browser fires the onCommand event.  Next, javascript catches that event, runs application script, and returns to the browser. The browser then runs the default behavior if it has not been cancelled. Finally, the browser returns to the accessibility tool.

6.2 Relationship to ARIA

WAPA is intended to extend the functionality of ARIA to situations where it will be easier or more performant to manage accessibility in script rather than in markup. It allows web authors to provide ARIA name-value pairs to the Accessibility API via javascript functions without the need for an element with those name-value pairs to be present in the document object.

6.3 Relationship to IndieUI

IndieUI Events List has some overlap with this functionality. Our goal is to harmonize with IndieUI and User Intention Events