aria a11ycamp-bay-2015

52
Accessible Rich Internet Applications: Beyond the Basics

Upload: dylan-barrell

Post on 14-Jul-2015

96 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Aria a11ycamp-bay-2015

Accessible Rich Internet

Applications:

Beyond the Basics

Page 2: Aria a11ycamp-bay-2015

Dylan Barrell

Twitter: @dylanbarrell

GitHub: dylanb

http://unobfuscated.blogspot.com/

http://www.deque.com/

Page 3: Aria a11ycamp-bay-2015
Page 4: Aria a11ycamp-bay-2015

8 trillion

Page 5: Aria a11ycamp-bay-2015

$8 trillion

Page 6: Aria a11ycamp-bay-2015

15%

Page 7: Aria a11ycamp-bay-2015

1 billion

Page 8: Aria a11ycamp-bay-2015

P

O

U

R

Page 9: Aria a11ycamp-bay-2015

Perceivable

Operable

Understandable

Robust

Page 10: Aria a11ycamp-bay-2015

Role

Name

State(s)

Value

Page 11: Aria a11ycamp-bay-2015

Keyboard (and gestures) – add graphic of a Braille keyboard

Page 12: Aria a11ycamp-bay-2015
Page 13: Aria a11ycamp-bay-2015
Page 14: Aria a11ycamp-bay-2015
Page 15: Aria a11ycamp-bay-2015
Page 16: Aria a11ycamp-bay-2015
Page 17: Aria a11ycamp-bay-2015
Page 18: Aria a11ycamp-bay-2015

• Accessibility and the DOM

– DOM tree• Semantic structure

• Styled with CSS

• Mouse and Keyboard behavior implemented by browser

• Default mapping to the accessibility tree

– Accessibility tree• Representation of the accessibility information

• Each element has a name, a role, a value and a state

• Interpreted by Assistive technology

• Used in combination with the Accessibility API

– Composed Tree (web components)

Page 19: Aria a11ycamp-bay-2015
Page 20: Aria a11ycamp-bay-2015
Page 21: Aria a11ycamp-bay-2015

Insert periodic table of ARIA roles

Page 22: Aria a11ycamp-bay-2015

• ARIA roles:

– Provide the ability to control the transition

between application (forms) mode and

document mode

– Provide more native announcments for

widgets like menus, tabs, sliders etc.

– Provide for the ability to control

announcements when updates occur away

from the focus

– Provide much more control over the structure

of the document and how someone navigates

around it

Page 23: Aria a11ycamp-bay-2015
Page 24: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-valuemax="100”

aria-valuenow="0" aria-valuetext="0%”>

</button>

</div>

Page 25: Aria a11ycamp-bay-2015

• Adding role:

– Changes the mapping to the accessibility API

– Does not change the behavior

• Focussability

• Keyboard interaction

• Mouse interaction

– Does not change the appearance

Page 26: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-valuemax="100”

aria-valuenow="0" aria-valuetext="0%”>

</button>

</div>

Page 27: Aria a11ycamp-bay-2015

Insert periodic table of ARIA attributes

Page 28: Aria a11ycamp-bay-2015

• ARIA attributes:

– Solve the problem of multiple labels and

descriptions through the addition of finer-

grained labeling attributes

– Enhance the ARIA roles through the addition

of standard state, value and role-specifying

attributes

– Add some attributes for better control of what

is spoken by the screen reader versus what is

simply there for presentational purposes

Page 29: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-valuemax="100”

aria-valuenow="0" aria-valuetext="0%”>

</button>

</div>

Page 30: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-

valuemax="100”

aria-valuenow="0" aria-

valuetext="0%”>

</button>

</div>

Page 31: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-

valuemax="100”

aria-valuenow="0" aria-

valuetext="0%”>

</button>

</div>

Page 32: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-

valuemax="100”

aria-valuenow="0" aria-

valuetext="0%”>

</button>

</div>

Page 33: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-

valuemax="100”

aria-valuenow="0" aria-

valuetext="0%”>

</button>

</div>

Page 34: Aria a11ycamp-bay-2015

<div id=”myId" class=”…”>

<button class=”…” id=”…”

role="slider”

aria-labelledby=”sliderLabelID”

aria-valuemin="0" aria-

valuemax="100”

aria-valuenow="0" aria-

valuetext="0%”>

</button>

</div>

Page 35: Aria a11ycamp-bay-2015
Page 36: Aria a11ycamp-bay-2015

handled = false,

$this = jQuery(this);

if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) {

// not interested

return;

}

/*

* Open a sub-menu and place focus on the first menuitemwithin it

*/

function openMenu() {

if($this.hasClass("a11yfy-has-submenu")) {

$this.addClass("open").attr("aria-expanded", "true").find(">ul>li:visible").first().attr("tabindex", "0").focus();

$this.attr("tabindex", "-1");

}

}

/*

* Move the focus to the menuitem preceding the current menuitem

*/

function prevInMenu() {

var $context = $this;

$this.attr("tabindex", "-1");

while (true) {

if ($context.prev().is(':visible')) {

$context.prev().attr("tabindex", "0").focus();

return

}

$context = $context.prev();

if (!$context.prev().length) {

$context = $this.parent().find(">li").last();

if ($context.is(':visible')) {

$context.attr("tabindex", "0").focus();

return

}

}

if ($context[0] === $this[0]) {

$this.attr("tabindex", "0")

break;

}

}

}

/*

* Move the focus to the next menuitem after the currently focussed menuitem

*/

function nextInMenu() {

var $context = $this;

$this.attr("tabindex", "-1");

while (true) {

if ($context.next().is(':visible')) {

$context.next().attr("tabindex", "0").focus(

/*

* This implements the WAI-ARIA-PRACTICES keyboard functionality where

* pressing the key, corresponding to the first letter of a VISIBLE element

* will move the focus to the first such element after the currently focussed

* element

*/

var keyCode = e.charCode || e.which || e.keyCode,

keyString = String.fromCharCode(keyCode).toLowerCase(),

ourIndex = -1,

currentItem = this,

$this = jQuery(this),

$nextItem, $prevItem,

$menuitems = $menu.find("li[role=\"menuitem\"]:visible");

if (keyCode === 9) {

return true;

}

$menuitems.each(function(index, value) {

if (value === currentItem) {

ourIndex = index;

}

if (index > ourIndex && !$nextItem) {

if (jQuery(value).text().trim().toLowerCase().indexOf(keyString) === 0) {

if (ourIndex !== -1) {

$nextItem = jQuery(value);

} else if (!$prevItem) {

$prevItem = jQuery(value);

}

}

}

});

if (!$nextItem && $prevItem) {

$nextItem = $prevItem;

}

if ($nextItem) {

$nextItem.attr("tabindex", "0").focus();

$this.attr("tabindex", "-1");

if ($nextItem.parent().get(0) !== $this.parent().get(0)) {

$this.parent().parent("li").removeClass("open").attr("aria-expanded", "false");

}

}

e.stopPropagation();

}).on("keydown", function(e) {

/*

* This implements the WAI-ARIA-PRACTICES keyboard navigation functionality

*/

var keyCode = e.which || e.keyCode,

Page 37: Aria a11ycamp-bay-2015

} else {

/* If in sub-menu, open sub-sub-menu */

openMenu();

}

break;

case 40: //down

handled = true;

if ($this.parent().hasClass("a11yfy-top-level-menu")) {

/* If in menubar, open sub-menu */

openMenu();

} else {

/* If in sub-menu, move to the next menuitem */

nextInMenu();

}

break;

}

if (handled) {

e.preventDefault();

e.stopPropagation();

}

return true;

);return

}$context = $context.next();if (!$context.next().length) {

$context = $this.parent().find(">li").first();if ($context.is(':visible')) {

$context.attr("tabindex", "0").focus();return

}}if ($context[0] === $this[0]) {

$this.attr("tabindex", "0")break;

}}

}switch(keyCode) {

case 32: // spacecase 13: // enter

handled = true;if ($this.find(">a").length) {

if ($this.find(">a")[0].click) {/* If this is a leaf node, activate it*/$this.find(">a")[0].click();

} else {// This is a hack for PhantomJS$this.find(">a").first().trigger("click");

}} else {

/* If it has a sub-menu, open the sub-menu */openMenu();

}break;

case 37: //leftcase 27: //esc

handled = true;if (keyCode === 37 && $this.parent().hasClass("a11yfy-

top-level-menu")) {/* If in the menubar, then simply move to the previous

menuitem */prevInMenu();

} else {if ($this.parent().attr("role") === "menu") {

// this is part of a submenu, set focus on containing li$this.parent().parent().attr("tabindex", "0").focus()

.removeClass("open").attr("aria-expanded", "false");

$this.attr("tabindex", "-1");}

}break;

case 38: //uphandled = true;if ($this.parent().hasClass("a11yfy-top-level-menu")) {

/* If in the menubar, then open the sub-menu */openMenu();

} else {/* If in sub-menu, move to previous element */prevInMenu();

}break;

case 39: //righthandled = true;if ($this.parent().hasClass("a11yfy-top-level-menu")) {

/* If in menubar, move to next menuitem */nextInMenu();

Page 38: Aria a11ycamp-bay-2015
Page 39: Aria a11ycamp-bay-2015
Page 40: Aria a11ycamp-bay-2015

First ARIA Best Practice – If there is a native HTML element that does the

job, use that

Examples

1. Use <button> and <input type=“submit”> NOT <a role=“button”>

2. Use <ul>, <ol> and <li> NOT <span role=“list”> etc.

Page 41: Aria a11ycamp-bay-2015

Compelling ARIA roles

• Landmark Roles– main, search, navigation, contentinfo, complementary,

banner

– region in combination with aria-label

• Live Region Roles– log, status, alert

• Some Widget Roles– tabpanel and tab

– slider

– menu, menubar, menuitem and associated attributes

– dialog – in combination with the document role to get it to work in NVDA

– tree and treeitem – a bit tricky to get to work reliably

• Some form roles– button, textbox, checkbox, radio, radiogroup

• presentation role

Page 42: Aria a11ycamp-bay-2015

Second ARIA Best Practice – test it

on all YOUR platforms with the

assistive technology YOU must

support

All platforms have problems, most

have workarounds, iOS is the

most problematic and Android is

not quite ready for prime time yet

Page 43: Aria a11ycamp-bay-2015

ARIA holes

• Tables, tables, tables

– Use the a11yfy library

• Arrow keys on iOS

– Insert dynamic modal content in line

– Use gestures

• Gestures

– Think hard about your mapping to the

portable gestures

– add on screen controls where possible

Page 44: Aria a11ycamp-bay-2015

Accessible Gesture Calendar Example

https://github.com/dylanb/gestura11y

http://dylanb.github.io/datepicker/datepicker.html

• Shows use of tabindex to control focus

• Shows use of role=“application” to force application mode

• Shows use of aria-live regions to announce the current date as the user moves around

• Shows use of aria-hidden to hide presentation markup from the screen reader

• Shows use of keyboard handler and mapping to gestures

• Shows how to ensure that gestures are consistent regardless of zoom level

Page 45: Aria a11ycamp-bay-2015

Accessible Gesture Calendar Example

https://github.com/dylanb/gestura11y

Page 46: Aria a11ycamp-bay-2015
Page 47: Aria a11ycamp-bay-2015
Page 48: Aria a11ycamp-bay-2015
Page 49: Aria a11ycamp-bay-2015

Third ARIA Best Practice – Always

attach your event handlers to the

same element that has the role

and the focus

If you stick to this rule, you will avoid

events not being delivered

consistently

Page 50: Aria a11ycamp-bay-2015

Fourth ARIA Best Practice – In

complex widgets like menubars,

tabpanels etc. always make all

interim structures presentational

Page 51: Aria a11ycamp-bay-2015

Fifth ARIA Best Practice – in a

complex widget where you are

managing focus, disable all

naturally focusable elements with

tabindex=“-1”

Example is the a11yfy menu

examples where the anchors are

given tabindex=“-1”

Page 52: Aria a11ycamp-bay-2015

Finally

There is a wealth or resources including

The ARIA specification (recommendation, normative)

http://www.w3.org/TR/wai-aria/

The Authoring Practices (draft) http://www.w3.org/TR/wai-aria-practices/

Using ARIA in HTML (draft, informative)

http://www.w3.org/TR/aria-in-html/

The WAI Web Site http://www.w3.org/WAI/intro/aria

Mozilla Developer Network https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA