Developer's guide to accessibility APIs

Developer's guide to accessibility APIs

FrontFest, Moscow 2017

Léonie Watson ~ The Paciello Group

Screen readers

Software that translates on-screen content into synthetic speech

Jaws NVDA Voiceover Narrator

Screen reader demo: text

Screen reader demo: headings

HTML checkbox

<input type="checkbox" id="bold">
<label for="bold">Bold</label>

DOM tree

DOM information for an HTML checkbox

Rendered view

Bold checkbox

Accessibility tree

Accessibility tree information for an HTML checkbox

Accessibility APIs

Windows
UI Automation (UIA)
MS Active Accessibility (MSAA)
IAccessible2 (IA2)
Mac OS
OSX Accessibility Protocol (AXAPI)
Linux
Accessibility Toolkit (ATK)
AT Service Provider Interface (AT-SPI)

Accessibility mechanics

Accessibility API mappings (AAM)

Define how role, state, properties, and keyboard focus for native elements are handled in the browser

Accessibility supported

Browsers may support an element, but not accessibility support it

The details and summary elements

<details>
<summary>Tequila...</summary>
Makes me happy!
</details>

Edge: not implemented

details/summary elements in Edge

Firefox: implemented

Accessibility information

Role
button
State
focusable
focused
expandable
collapsed

Screen reader demo

Using ARIA

Attributes that polyfill missing role, name, and state information for screen readers

The role attribute

70+ roles, including:

The aria- attributes

45+ states and properties, including:

The details and summary elements

<details>
<summary id="button">Tequila...</summary>
<div id="content">Makes me happy!</div>
</details>

Create DOM node references

var button = document.getElementById('button');
var content = document.getElementById('content');

Set role="button"

button.setAttribute('role', 'button');

Set tabindex="0"

button.setAttribute('tabindex', 0);

Set aria-expanded="false"

button.setAttribute('aria-expanded', 'false');

Set hidden attribute

content.setAttribute('hidden', 'true');

Rendered code

<details>
    <summary id="button" role="button" tabindex="0" aria-expanded="false">
        Tequila...
    </summary>
    <div id="content" hidden>Makes me happy!</div>Makes me happy!
</details>

Add functionality

    function disclose(event) {
        if (content.hasAttribute('hidden')) {
            button.setAttribute('aria-expanded', 'true');
            content.removeAttribute('hidden');
        }
        else {
            button.setAttribute('aria-expanded', 'false');
            content.setAttribute('hidden', 'true');
        }
    }

Add event listeners

    button.addEventListener('click', disclose, false);

	button.addEventListener('keydown', function(event) {
        if (event.keyCode == 13 || event.keyCode ==32) {
            disclose();
        }
	});

Screen reader demo

Accessibility Object Model (AOM)

Experimental JavaScript API that enables developers to modify the accessibility tree

Chrome Safari Firefox

AOM phases

  1. Modify the semantic properties of the accessibility node associated with a DOM node;
  2. Directly respond to events or actions from AT;
  3. Create virtual accessibility nodes (not associated with DOM nodes);
  4. Programmatically explore the accessibility tree, and access the computed properties of accessibility nodes.

AOM Phase 1

Has landed in Chrome Canary behind the flag:

--enable-blink-features=AccessibilityObjectModel

The details and summary elements

<details>
<summary id="button">Tequila...</summary>
<div id="content">Makes me happy!</div>
</details>

Create DOM node references

var button = document.getElementById('button');
var content = document.getElementById('content');

Modify DOM node properties

button.setAttribute('tabindex', 0);
content.setAttribute('hidden', true);

Set AOM button property

button.accessibleNode.role = "button";

Set AOM expanded property

button.accessibleNode.expanded = false;

Create AccessibleNodeList

var references = new AccessibleNodeList();

Add AccessibleNode to array

references.add(content.accessibleNode);

Create the function

    function disclose(event) {
        if(content.getAttribute('hidden')) {
            button.accessibleNode.expanded = true;
            button.accessibleNode.controls = content;
            content.removeAttribute('hidden');
        }
        else {
            button.accessibleNode.expanded = false;
            button.accessibleNode.controls = null;
            content.setAttribute('hidden', true);
        }
    }

Add event listeners

    button.addEventListener('click', disclose, false);
    button.addEventListener('keydown', function(event) {
        if (event.keyCode == 13 || event.keyCode ==32) {
            disclose();
        }
    });

Screen reader demo: AOM disclosure

Thank you!

Léonie Watson ~ The Paciello Group