aria a11ycamp-bay-2015
TRANSCRIPT
![Page 1: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/1.jpg)
Accessible Rich Internet
Applications:
Beyond the Basics
![Page 2: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/2.jpg)
Dylan Barrell
Twitter: @dylanbarrell
GitHub: dylanb
http://unobfuscated.blogspot.com/
http://www.deque.com/
![Page 3: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/3.jpg)
![Page 4: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/4.jpg)
8 trillion
![Page 5: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/5.jpg)
$8 trillion
![Page 6: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/6.jpg)
15%
![Page 7: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/7.jpg)
1 billion
![Page 8: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/8.jpg)
P
O
U
R
![Page 9: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/9.jpg)
Perceivable
Operable
Understandable
Robust
![Page 10: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/10.jpg)
Role
Name
State(s)
Value
![Page 11: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/11.jpg)
Keyboard (and gestures) – add graphic of a Braille keyboard
![Page 12: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/12.jpg)
![Page 13: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/13.jpg)
![Page 14: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/14.jpg)
![Page 15: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/15.jpg)
![Page 16: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/16.jpg)
![Page 17: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/17.jpg)
![Page 18: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/18.jpg)
• 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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/19.jpg)
![Page 20: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/20.jpg)
![Page 21: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/21.jpg)
Insert periodic table of ARIA roles
![Page 22: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/22.jpg)
• 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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/23.jpg)
![Page 24: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/24.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/25.jpg)
• 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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/26.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/27.jpg)
Insert periodic table of ARIA attributes
![Page 28: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/28.jpg)
• 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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/29.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/30.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/31.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/32.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/33.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/34.jpg)
<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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/35.jpg)
![Page 36: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/36.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/37.jpg)
} 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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/38.jpg)
![Page 39: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/39.jpg)
![Page 40: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/40.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/41.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/42.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/43.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/44.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/45.jpg)
Accessible Gesture Calendar Example
https://github.com/dylanb/gestura11y
![Page 46: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/46.jpg)
![Page 47: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/47.jpg)
![Page 48: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/48.jpg)
![Page 49: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/49.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/50.jpg)
Fourth ARIA Best Practice – In
complex widgets like menubars,
tabpanels etc. always make all
interim structures presentational
![Page 51: Aria a11ycamp-bay-2015](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/51.jpg)
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](https://reader034.vdocuments.us/reader034/viewer/2022051617/55a5250b1a28abe50e8b461c/html5/thumbnails/52.jpg)
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