SlideShare ist ein Scribd-Unternehmen logo
1 von 106
Keyboard Access


              Todd Kloots
                  @todd
Goals

1. Understand the essential APIs for providing
   keyboard access for custom widgets
2. Understand the common, expected patterns
   for widgets
Configuring the Mac




http://yaccessibilityblog.com/library/full-keyboard-access-mac.html
OS X Preferences
OS X Preferences
Safari Preferences
Chrome Preferences
Who benefits?
* Users of screen readers
http://youtu.be/ReED-LpciYI
http://youtu.be/tdEaeULKkLQ
Who Benefits

Users who prefer/love the keyboard
Users who are blind
Users with physical disabilities
Widget Keyboard Patterns

  Atomic widgets
  (e.g. buttons, links, text boxes)

  Container widgets
  (e.g. listboxes, toolbars, trees)

  Overlay widgets
  (e.g. dialogs, menus, tooltips)
tabIndex
Screen Readers
Read the code (HTML)
Read the focused element
What is read:
  Element/Control type
  Label
  Properties
  State changes
Focusable Elements
<a>
<area>
<button>
<input>
<select>
<textarea>
<object>
tabIndex
<li tabindex="-1" />

<li tabindex="0" />

<li tabindex="1" />
Natively Focusable Elements
<a href="#">Label</a>
<button type="button">Label</button>
<input type="button" value="Label">



Convey interactivity
In the default tab flow
Fire click event in response to the mouse
and keyboard
Using tabIndex
<li tabindex="0" />

Convey interactivity
Focusable
Can be in placed in the tab flow
Fire click event in response to the mouse
BUT NOT the keyboard
<span class="btn" tabindex="0">OK</span>

// Native DOM
node.tabIndex = 0;

// jQuery
node.attr("tabIndex", 0);

// YUI
node.set("tabIndex", 0);
tabIndex=0
tabIndex=0 Use Case
<span class="btn" tabindex="0">OK</span>


$(".btn").on("keydown", function (e) {
    var keyCode = e.keyCode;

      if (keyCode === 13 || keyCode === 32) {
          $(this).trigger($.Event("click"));
      }
});
tabIndex=0 Review

Places the element in the default tab flow
Focusable via keyboard, mouse or JavaScript
Default browser focus outline onFocus
Click not fired via Enter or Spacebar
tabIndex=-1
tabIndex=-1

Removes the element from the tab flow
Focusable via the mouse or JavaScript
No browser focus outline in IE
Click not fired via Enter or Spacebar
tabIndex=-1 Use Cases

Popup Menus
Stateless Container Widgets
Stateful Container Widgets
Popup Menu Use Case
<ul class="menu hidden" tabindex="-1">
    <li tabindex="-1">Inbox</li>
    <li tabindex="-1">Archive</li>
    <li tabindex="-1">Trash</li>
</ul>
Explicit tabIndex Use Case

    4

        1
            2


3
tabIndex Review

tabIndex=0
tabIndex=-1
tabIndex=1
focus() and blur()
Use Cases

Overlay Widgets
Stateless Container Widgets
Stateful Container Widgets
Stateless Containers
Web vs. Desktop
Web vs. Desktop
Initial Focus
Right/Left Arrows
Blur
Subsequent Focus
0         -1      -1     -1       -1




<div class="toolbar">
  <button type="button"   tabindex="0" class="prnt">Print</button>
  <button type="button"   tabindex="-1" class="find">Find</button>
  <button type="button"   tabindex="-1" class="save">Save</button>
  <button type="button"   tabindex="-1" class="sets">Settings</
button>
  <button type="button"   tabindex="-1" class="info">Info</button>
</div>
toolbar.on("keydown", "button", function (e) {

      var keyCode = e.keyCode,
          button = $(this),
          next;

      if (keyCode === 37) { // Left
          next = "prev";
      }
      else if (keyCode === 39) { // Right
          next = "next";
      }

      if (next) {
          button[next]().focus();
      }

});
Toolbar Exercise
Stateless Container Pattern
Use with the following ARIA widget roles



     toolbar
     menubar
Stateful Containers
Initial State: No Selection
Initial Focus
Up/Down Arrows
Blur
Subsequent Focus
<ul id="listbox">
    <li tabindex="0">Activism</li>
    <li tabindex="-1">Baking</li>
    <li tabindex="-1">Cooking</li>
    <li tabindex="-1">Dancing</li>
    <li tabindex="-1">Fine Art</li>
    <li tabindex="-1">Ice Skating</li>
    <li tabindex="-1">Music</li>
    <li tabindex="-1">Politics</li>
    <li tabindex="-1">Sports</li>
    <li tabindex="-1">Travel</li>
    <li tabindex="-1">Technology</li>
</ul>
Up/Down Arrows
listbox.on("keydown", "li", function (e) {
    var keyCode = e.keyCode,
        li = $(this),
        next,
        nextItem;

      if (keyCode === 38) { // UP
          next = "prev";
      }
      else if (keyCode === 40) { // DOWN
          next = "next";
      }

      if (next) {
          // On initial arrow key press, don't advance focus,
          // just synchronize focus and selection
          if (!li.hasClass('selected')) {
              li.addClass("selected");
          }
          else if ((nextItem = li[next]()) && nextItem[0]) {
              makeSelection(nextItem);
              nextItem.focus();
          }
      }
});
Roving tabIndex

function makeSelection(li) {
    listbox.find("li.selected").attr('tabIndex', -1).removeClass("selected");
    li.attr('tabIndex', 0).addClass("selected");
}




 http://www.w3.org/TR/2009/WD-wai-aria-practices-20090224/#focus_tabindex
Roving tabIndex Demo
Roving tabIndex Pattern
Use with the following ARIA widget roles
     listbox
     grid
     tree & treegrid
     tablist
     radiogroup
Review

One tab stop per widget
Two patterns
  Stateless Container
  Stateful Container / Roving tabIndex
Menus
Initial Focus: No Selection
Initial Up/Down Arrow
Up/Down Arrows
-1
                         -1
                         -1
                         -1



<ul class="menu hidden" tabindex="-1">
    <li tabindex="-1">Inbox</li>
    <li tabindex="-1">Archive</li>
    <li tabindex="-1">Trash</li>
</ul>
Initial Focus
function showMenu() {

    menu.find(".selected").removeClass("selected");
    menu.removeClass("hidden");

    var position = button.position();

    menu.css({
        top: (position.top + button.outerHeight()),
        left: position.left
    });

    menu.focus();
}
Initial Up/Down Arrow
if (target === menu[0]) {
    if ((selected = menu.find(".selected")) && selected[0]) {
        event = $.Event("keydown", { keyCode: keyCode });
        selected.trigger(event);
    }
    else {
        if (keyCode === 38) { // UP
            selector = "li:last-child";
        }
        else if (keyCode === 40) { // DOWN
            selector = "li:first-child";
        }
        menu.find(selector).addClass("selected").focus();
    }
}
Up/Down Arrows
switch (e.keyCode) {
    case 38: // UP
        next = "prev";
        break;

    case 40: // Down
        next = "next";
        break;

    case 13: // Enter
    case 32: // Space
        selected.trigger($.Event("click"));
        selected.blur();
        break;
}

if (next && (nextItem = li[next]()) && nextItem[0]) {
    li.removeClass("selected");
    nextItem.addClass("selected").focus();
}
Dialogs
Initial Focus
Tab or Shift + Tab
Cancel
Initial Focus
function showDialog() {

    var activeEl = document.activeElement;

    dialog.removeClass("hidden");

    createModalMask();
    positionDialog();

    $('#ok-button').focus();

}
What About?


Modality?
Canceling?
document.activeElement
contains()
onFocus & onBlur
document.activeElement
function showDialog() {

    var activeEl = document.activeElement;

    dialog.removeClass("hidden");

    createModalMask();
    positionDialog();

    $('#ok-button').focus();

    $(document).on("focusin.dialog", enforceModality);

    $(window).on('resize.dialog', function () {
        sizeModalMask();
        positionDialog();
    });

    dialog.on("click.dialog", "input", activeEl, hideDialog);

    ...

}
dialog.on("keydown.dialog", function (e) {
    var keyCode = e.keyCode;

      if (keyCode === 27) {   // Esc
          hideDialog(activeEl);
      }
      else if (keyCode === 9 && !e.shiftKey &&
        e.target === $("#cancel-button")[0]) {
          e.preventDefault();
      }
});
function hideDialog(activeEl) {
    dialog.addClass("hidden");
    removeModalMask();

    dialog.off(".dialog");
    $(window).off(".dialog");

    activeEl.focus();
}
contains(haystack, needle)



http://api.jquery.com/jQuery.contains/

http://yuilibrary.com/yui/docs/api/classes/Node.html
$(document).on("focusin", onDocFocus);
$(document).on("focusout", onDocFocus);

$(dialog).on("focus", "input", onDialogFocus);
$(dialog).on("blur", "input", onDialogFocus);
function enforceModality(e) {
    if (!$.contains(dialog[0], e.target)) {
        dialog.find('#ok-button').focus();
    }
}

$(document).on("focusin.dialog", enforceModality);
Hiding Menus

menu.on("focusout", function (e) {
    setTimeout(function () {
        if (!$.contains(menu[0], document.activeElement)) {
            menu.addClass("hidden");
        }
    }, 0);
});
:focus
:focus


Device independent
All browsers implement a default
focus outline
:focus Limitations in IE

Not supported in IE < 8
IE < 8 does provide :active, but only for links
IE doesn't render default outline when
tabIndex is set to -1
Cannot remove default outline using CSS in
IE < 8
Supplementing :focus In IE

if (browser.msie && browser.version < 8) {
    toolbar.on("focus", "button", function () {
        $(this).addClass("focus");
    });

    toolbar.on("blur", "button", function () {
        $(this).removeClass("focus");
    });
}
:focus {
    outline: none;
}
Recommendation
/* BAD:
   Don't globally remove the outline property. */
:focus {
    outline: none;
}

/* GOOD:
   Instead, selectively remove outline in rules
   that provide an alternative. */
.tab:focus {
    outline: none;
    background-color: blue;
}
Useful Properties
Outline
Background
Text color
Box Shadow
Underline
Custom Focus in Y! Mail

          IE 6 and 7



          IE 8+
:active
:active

Also device independent
Precedes :focus
keydown state/mousedown state
:focus Use Cases


Atomic controls
(e.g. buttons and links)
:focus Not Useful With
Serving Two Masters

                Keyboard


Mouse
Initial Up/Down Arrow
if (target === menu[0]) {
    if ((selected = menu.find(".selected")) && selected[0]) {
        event = $.Event("keydown", { keyCode: keyCode });
        selected.trigger(event);
    }
    else {
        if (keyCode === 38) { // UP
            selector = "li:last-child";
        }
        else if (keyCode === 40) { // DOWN
            selector = "li:first-child";
        }
        menu.find(selector).addClass("selected").focus();
    }
}
Up/Down Arrows
switch (e.keyCode) {
    case 38: // UP
        next = "prev";
        break;

    case 40: // Down
        next = "next";
        break;

    case 13: // Enter
    case 32: // Space
        selected.trigger($.Event("click"));
        selected.blur();
        break;
}

if (next && (nextItem = li[next]()) && nextItem[0]) {
    li.removeClass("selected");
    nextItem.addClass("selected").focus();
}
Maintaining State
listbox.on("keydown", "li", function (e) {
    var keyCode = e.keyCode,
        li = $(this),
        next,
        nextItem;

      if (keyCode === 38) { // UP
          next = "prev";
      }
      else if (keyCode === 40) { // DOWN
          next = "next";
      }

      if (next) {
          // On initial arrow key press, don't advance focus,
          // just synchronize focus and selection
          if (!li.hasClass('aria-selected')) {
              li.addClass("selected");
          }
          else if ((nextItem = li[next]()) && nextItem[0]) {
              makeSelection(nextItem);
              nextItem.focus();
          }
      }
});
function makeSelection(li) {
    listbox.find("li.selected").attr('tabIndex', -1).removeClass("selected");
    li.attr('tabIndex', 0).addClass("selected");
}
listbox.on("focusin", function (e) {
    if (!listbox.hasClass("focus")) {
        listbox.addClass("focus");
    }
});


listbox.on("focusout", function (e) {
  setTimeout(function () {
      if (!$.contains(listbox[0], document.activeElement)) {
          listbox.removeClass("focus");
      }
  }, 0);
});
li.selected {
    background: #ccc;
}

li:focus {
    outline: none;
}

ul.focus {
    border-color: #3875D7;
}

ul.focus li.selected {
    background: #3875D7;
    color: #fff;
}
Review
APIs
tabIndex
focus(), blur()
document.activeElement
contains()
focus and blur events
:focus, :active
Widget Keyboard Patterns
Task                     Key
Focus Next or Previous   Tab / Shift + Tab / Arrows
Change selection         →, ←, ↑, ↓
Expand / Collapse        →, ←, ↑, ↓
Exit                     Esc
Click                    Spacebar
Default Action           Enter
Code Examples


https://gist.github.com/kloots

Weitere ähnliche Inhalte

Was ist angesagt?

JavaScript Code Organizations, Patterns Slides - Zach Dennis
JavaScript Code Organizations, Patterns Slides - Zach DennisJavaScript Code Organizations, Patterns Slides - Zach Dennis
JavaScript Code Organizations, Patterns Slides - Zach DennisZach Dennis
 
Oracle helpdesk database shema
Oracle helpdesk database shemaOracle helpdesk database shema
Oracle helpdesk database shemaMurat Gülci
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine PerformanceCatalin Dumitru
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In RailsLouie Zhao
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your appsJuan C Catalan
 
Возможности, особенности и проблемы AR::Relation
Возможности, особенности и проблемы AR::RelationВозможности, особенности и проблемы AR::Relation
Возможности, особенности и проблемы AR::RelationАлександр Ежов
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»e-Legion
 
Php Security - OWASP
Php  Security - OWASPPhp  Security - OWASP
Php Security - OWASPMizno Kruge
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
Константин Чернухо_Popups, alerts and windows
Константин Чернухо_Popups, alerts and windowsКонстантин Чернухо_Popups, alerts and windows
Константин Чернухо_Popups, alerts and windowsGeeksLab Odessa
 
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Francois Marier
 
A brief history of Django model syntax
A brief history of Django model syntaxA brief history of Django model syntax
A brief history of Django model syntaxJacob Kaplan-Moss
 
Exemple de création de base
Exemple de création de baseExemple de création de base
Exemple de création de baseSaber LAJILI
 

Was ist angesagt? (20)

JavaScript Code Organizations, Patterns Slides - Zach Dennis
JavaScript Code Organizations, Patterns Slides - Zach DennisJavaScript Code Organizations, Patterns Slides - Zach Dennis
JavaScript Code Organizations, Patterns Slides - Zach Dennis
 
Oracle helpdesk database shema
Oracle helpdesk database shemaOracle helpdesk database shema
Oracle helpdesk database shema
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
 
Sql commands
Sql commandsSql commands
Sql commands
 
10. view one record
10. view one record10. view one record
10. view one record
 
11. delete record
11. delete record11. delete record
11. delete record
 
Symfony day 2016
Symfony day 2016Symfony day 2016
Symfony day 2016
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your apps
 
Возможности, особенности и проблемы AR::Relation
Возможности, особенности и проблемы AR::RelationВозможности, особенности и проблемы AR::Relation
Возможности, особенности и проблемы AR::Relation
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
 
Php Security - OWASP
Php  Security - OWASPPhp  Security - OWASP
Php Security - OWASP
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
12. edit record
12. edit record12. edit record
12. edit record
 
Константин Чернухо_Popups, alerts and windows
Константин Чернухо_Popups, alerts and windowsКонстантин Чернухо_Popups, alerts and windows
Константин Чернухо_Popups, alerts and windows
 
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
 
A brief history of Django model syntax
A brief history of Django model syntaxA brief history of Django model syntax
A brief history of Django model syntax
 
Videogiochi in PHP 👾
Videogiochi in PHP 👾Videogiochi in PHP 👾
Videogiochi in PHP 👾
 
Exemple de création de base
Exemple de création de baseExemple de création de base
Exemple de création de base
 

Andere mochten auch

TRATADO DE GINEBRA
TRATADO DE GINEBRATRATADO DE GINEBRA
TRATADO DE GINEBRAguest605b6fd
 
The Influence of Ethnic Identity on Consumer Behaviour
The Influence of Ethnic Identity on Consumer BehaviourThe Influence of Ethnic Identity on Consumer Behaviour
The Influence of Ethnic Identity on Consumer BehaviourThe Added Value Group
 
Am j physiol heart circ physiol 2000-matsubara-h1534-9
Am j physiol heart circ physiol 2000-matsubara-h1534-9Am j physiol heart circ physiol 2000-matsubara-h1534-9
Am j physiol heart circ physiol 2000-matsubara-h1534-9Natasha Xavier
 
Llenguatge ciències
Llenguatge ciènciesLlenguatge ciències
Llenguatge ciènciesArnau Cerdà
 
Conexión hyperterminal
Conexión hyperterminalConexión hyperterminal
Conexión hyperterminalRaul Remache
 
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...Jarno M. Koponen
 
PreparacióN De Unas Vacaciones
PreparacióN De Unas VacacionesPreparacióN De Unas Vacaciones
PreparacióN De Unas VacacionesMartaRomeral
 
RedFusion Capabilities
RedFusion CapabilitiesRedFusion Capabilities
RedFusion Capabilitiescadcammike
 
Ps and Qs of Interviews
Ps and Qs of InterviewsPs and Qs of Interviews
Ps and Qs of Interviewsguestbb68232
 
Insider trading_in_turkey
Insider trading_in_turkeyInsider trading_in_turkey
Insider trading_in_turkeyguest0437b8
 
91009103910 Am1252571950753
91009103910 Am125257195075391009103910 Am1252571950753
91009103910 Am1252571950753Arnau Cerdà
 

Andere mochten auch (20)

TRATADO DE GINEBRA
TRATADO DE GINEBRATRATADO DE GINEBRA
TRATADO DE GINEBRA
 
What Is Social Media[1]
What Is Social Media[1]What Is Social Media[1]
What Is Social Media[1]
 
The Influence of Ethnic Identity on Consumer Behaviour
The Influence of Ethnic Identity on Consumer BehaviourThe Influence of Ethnic Identity on Consumer Behaviour
The Influence of Ethnic Identity on Consumer Behaviour
 
Am j physiol heart circ physiol 2000-matsubara-h1534-9
Am j physiol heart circ physiol 2000-matsubara-h1534-9Am j physiol heart circ physiol 2000-matsubara-h1534-9
Am j physiol heart circ physiol 2000-matsubara-h1534-9
 
Llenguatge ciències
Llenguatge ciènciesLlenguatge ciències
Llenguatge ciències
 
Conexión hyperterminal
Conexión hyperterminalConexión hyperterminal
Conexión hyperterminal
 
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...
Vuorovaikutteinen viestintä ja läsnäolo käytännössä - huomioita ja vinkkejä (...
 
Taiwan2009
Taiwan2009Taiwan2009
Taiwan2009
 
PreparacióN De Unas Vacaciones
PreparacióN De Unas VacacionesPreparacióN De Unas Vacaciones
PreparacióN De Unas Vacaciones
 
Innevento
InneventoInnevento
Innevento
 
RedFusion Capabilities
RedFusion CapabilitiesRedFusion Capabilities
RedFusion Capabilities
 
Ps and Qs of Interviews
Ps and Qs of InterviewsPs and Qs of Interviews
Ps and Qs of Interviews
 
Lateralus - Tool
Lateralus - ToolLateralus - Tool
Lateralus - Tool
 
Iss
IssIss
Iss
 
Lt13
Lt13Lt13
Lt13
 
Rekonstrukce šaten
Rekonstrukce šatenRekonstrukce šaten
Rekonstrukce šaten
 
Insider trading_in_turkey
Insider trading_in_turkeyInsider trading_in_turkey
Insider trading_in_turkey
 
91009103910 Am1252571950753
91009103910 Am125257195075391009103910 Am1252571950753
91009103910 Am1252571950753
 
Birthday Celebrants
Birthday  CelebrantsBirthday  Celebrants
Birthday Celebrants
 
College Medema 1
College Medema 1College Medema 1
College Medema 1
 

Ähnlich wie Keyboard Access APIs

Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptjonathanfmills
 
Academy PRO: React native - navigation
Academy PRO: React native - navigationAcademy PRO: React native - navigation
Academy PRO: React native - navigationBinary Studio
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 
Clickable DIVs and other icebergs
Clickable DIVs and other icebergsClickable DIVs and other icebergs
Clickable DIVs and other icebergsBen Buchanan
 
Voices That Matter: JavaScript Events
Voices That Matter: JavaScript EventsVoices That Matter: JavaScript Events
Voices That Matter: JavaScript EventsPeter-Paul Koch
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Fabio Biondi
 
Working With JQuery Part1
Working With JQuery Part1Working With JQuery Part1
Working With JQuery Part1saydin_soft
 
Introduction to Web Components
Introduction to Web ComponentsIntroduction to Web Components
Introduction to Web ComponentsFelix Arntz
 
Given the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfGiven the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfillyasraja7
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android DevelopmentJussi Pohjolainen
 
Introduzione JQuery
Introduzione JQueryIntroduzione JQuery
Introduzione JQueryorestJump
 
Zero to Hero, a jQuery Primer
Zero to Hero, a jQuery PrimerZero to Hero, a jQuery Primer
Zero to Hero, a jQuery PrimerMatthew Buchanan
 
Strategies for Mitigating Complexity in React Based Redux Applicaitons
Strategies for Mitigating Complexity in React Based Redux ApplicaitonsStrategies for Mitigating Complexity in React Based Redux Applicaitons
Strategies for Mitigating Complexity in React Based Redux Applicaitonsgarbles
 
Rich Internet Applications - How to Make them Accessible
Rich Internet Applications - How to Make them AccessibleRich Internet Applications - How to Make them Accessible
Rich Internet Applications - How to Make them AccessibleDylan Barrell
 
Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Kuldeep Jain
 

Ähnlich wie Keyboard Access APIs (20)

Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Jquery 3
Jquery 3Jquery 3
Jquery 3
 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascript
 
Academy PRO: React native - navigation
Academy PRO: React native - navigationAcademy PRO: React native - navigation
Academy PRO: React native - navigation
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Clickable DIVs and other icebergs
Clickable DIVs and other icebergsClickable DIVs and other icebergs
Clickable DIVs and other icebergs
 
Voices That Matter: JavaScript Events
Voices That Matter: JavaScript EventsVoices That Matter: JavaScript Events
Voices That Matter: JavaScript Events
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)
 
Working With JQuery Part1
Working With JQuery Part1Working With JQuery Part1
Working With JQuery Part1
 
Introduction to Web Components
Introduction to Web ComponentsIntroduction to Web Components
Introduction to Web Components
 
Given the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfGiven the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdf
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android Development
 
jQuery Presentasion
jQuery PresentasionjQuery Presentasion
jQuery Presentasion
 
Introduzione JQuery
Introduzione JQueryIntroduzione JQuery
Introduzione JQuery
 
Zero to Hero, a jQuery Primer
Zero to Hero, a jQuery PrimerZero to Hero, a jQuery Primer
Zero to Hero, a jQuery Primer
 
Backbone - TDC 2011 Floripa
Backbone - TDC 2011 FloripaBackbone - TDC 2011 Floripa
Backbone - TDC 2011 Floripa
 
jQuery introduction
jQuery introductionjQuery introduction
jQuery introduction
 
Strategies for Mitigating Complexity in React Based Redux Applicaitons
Strategies for Mitigating Complexity in React Based Redux ApplicaitonsStrategies for Mitigating Complexity in React Based Redux Applicaitons
Strategies for Mitigating Complexity in React Based Redux Applicaitons
 
Rich Internet Applications - How to Make them Accessible
Rich Internet Applications - How to Make them AccessibleRich Internet Applications - How to Make them Accessible
Rich Internet Applications - How to Make them Accessible
 
Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.
 

Kürzlich hochgeladen

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 

Kürzlich hochgeladen (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 

Keyboard Access APIs

Hinweis der Redaktion

  1. \n
  2. \n
  3. First things first. If you are on a Mac, you&amp;#x2019;ll want to configure it for full keyboard access.\n
  4. Use Ctrl + F7 to enable keyboard access for all controls across OS X. This will also enable full keyboard access for Firefox on the Mac.\n
  5. Personally, I also like my function keys to operate as standard function keys. To set this go to System Preferences &gt; Keyboard\n
  6. In Safari go to Preferences &gt; Advanced and check &amp;#x201C;Press Tab to highlight each item on a webpage&amp;#x201D;\n
  7. Chrome has a similar preference in &amp;#x201C;Under the Hood&amp;#x201D;\n
  8. Before we talk about providing keyboard access, let&amp;#x2019;s begin by understanding who benefits from good keyboard access.\n
  9. Users who prefer the keyboard. One example would be software engineers, but many users realize that keyboard shortcuts can greatly improve their efficiency.\n
  10. Users who are blind completely rely on the keyboard both to navigate as well as to enter information.\n
  11. Users with physical disabilities may not be able to type with a physical keyboard, but can use voice recognition software to speak keyboard shortcuts.\n
  12. Similarly, users with physical disabilities can use software keyboards to press keyboard shortcuts.\n
  13. \n
  14. The more I have studied keyboard shortcuts for widgets, I find widgets fall into three categories. Throughout this presentation we&amp;#x2019;ll talk about these patterns and how to implement them.\n
  15. The first API essential to keyboard access is the tabIndex attribute. tabIndex can be used to make any element in the DOM focusable, and controls how it can be focused. If an element isn&amp;#x2019;t focusable it can&amp;#x2019;t fire key-related events.\n
  16. Another reason focusability is important for widgets: Screen readers read the currently focused element. So, if a widget isn&amp;#x2019;t focusable, it will be less discoverable and very likely inoperable to users of screen readers.\n
  17. HTML provides a limited set of natively focusable elements&amp;#x2014;mostly form controls, buttons and links.\n
  18. Using tabIndex, any element in the DOM can be focusable and fire key events. tabIndex can be set to one of three values: -1, 0 and an explicit positive index.\n\nA tabIndex of -1 enables an element to be focusable via JavaScript or the mouse. Elements with a tabIndex of -1 are not in the tab flow.\n\nA tabIndex of 0 places the element in the default tab flow; the element is also focusable via JavaScript or the mouse.\n\nLastly, tabIndex can be set to an explicit value.\n
  19. \n
  20. \n
  21. tabIndex can be set declaratively in the markup, or programmatically using JavaScript.\n
  22. \n
  23. One simple use case for tabIndex 0 is to make custom buttons focusable via the keyboard. JavaScript can be used to enable users to click the button by pressing either the Spacebar or Enter key.\n
  24. \n
  25. \n
  26. \n
  27. \n
  28. Popup menus are a good use case for tabIndex=-1 because they aren&amp;#x2019;t in the tab flow but need to be focusable.\n\nHere&amp;#x2019;s how to set tabIndex on the various elements that compose a popup menu.\n
  29. One use for explicitly declaring tabIndex would be to balance visual and functional requirements. For example, in GMail the &amp;#x201C;Send&amp;#x201D; button appears before the To, Subject and message body fields. However, when composing an email you&amp;#x2019;d likely want to tab first to the To field, then Subject, then the message body, and then finally the Send button.\n
  30. \n
  31. The second piece of API are the focus() and blur() methods.\n
  32. \n
  33. Stateless containers: widgets like menubars and toolbars. Both manage a collection of like descendant controls, and both maintain a visual focus/selection as the user is navigating. However that selection is not maintained after the control loses focus.\n
  34. On the desktop menubar and toolbars are often not in the tab flow; the user moves focus to them via a keyboard shortcut.\n\nOn the web, these controls ARE generally in the tab flow for two reasons:\n\n1) Discoverability&amp;#x2014;expectation would be that you can use Tab or Shift + Tab to move focus to a control\n\n2) Implementing a keyboard shortcut to move focus to a toolbar might use up a shortcut you need for another user action\n
  35. \n
  36. Consider a toolbar. When you first move focus to it, the first button is selected.\n
  37. As you navigate through the toolbar the currently focused button is highlighted.\n
  38. When the toolbar loses focus, the visualization of focus is cleared.\n
  39. When the toolbar is re-focused, the user does not resume where they left off, but rather starts back at the beginning.\n
  40. To implement this functionality, use tabIndex to remove all but the first button from the tab flow. This will allow the user to use the Tab key to move focus to/from the toolbar in a single keystroke.\n
  41. Then, bind a delegated keydown event listener that moves focus to the next or previous button in the toolbar as the user presses the left or right arrow keys.\n
  42. \n
  43. \n
  44. Stateful containers: these are widgets like treeviews, tablists, or listboxes. These widgets manage a collection of like descendant controls, and maintain selection even when they have lost focus.\n
  45. Consider a listbox control. The initial state is no selection.\n
  46. When a stateful container control initially receives focus, it has no selection, but focus is often indicated by an outline or change of color on the root element. Sometimes an outline around the first item, indicating it is focused but not selected.\n
  47. When the user presses the up and down arrow keys, the selection is advanced.\n
  48. When the control loses focus, the current selection is maintained, but often grayed out to indicate that it is not active.\n
  49. If the control regains focus, the up and down arrow keys should allow the user to pickup where they last left off.\n
  50. To implement this pattern, begin by setting the tabIndex of the first element to 0, the rest to -1.\n
  51. As the user presses the arrow keys to make a selection, update the tabIndex of the currently selected item to 0 and set the tabIndex of the previously selected item to -1. This will allow there to be a functional representation of the selection; if the control regains focus, the focused item will be the last selected item&amp;#x2014;allowing the user to pickup where they left off.\n
  52. This technique is referred to as the &amp;#x201C;Roving TabIndex Technique&amp;#x201D; in the W3C&amp;#x2019;s ARIA Authoring Practices specification.\n
  53. \n
  54. \n
  55. \n
  56. \n
  57. When a menu opens, focus should be moved to the menu. It has no initial selection.\n
  58. On initial press of the up or down arrow keys, focus is moved into the menu. If the user pressed the down arrow, the first menuitem is selected. If the user pressed the up arrow, the last menuitem is selected.\n
  59. On subsequent key press, selection follows the arrow keys.\n
  60. Implementing this behavior is easy. The menu container and all of the elements used to create menuitems are given a tabIndex of -1 to make them focusable.\n
  61. Focus is set to the menu&amp;#x2019;s container when the menu is made visible.\n
  62. On initial up/down arrow key press, use the :last-child and :first-child selectors are used to select either the first or last menuitem, depending on the key that was pressed.\n
  63. On subsequent arrow key presses, just advance the selection using a class name, and then focus the next menuitem.\n
  64. \n
  65. When a dialog is made visible, focus should be moved into the dialog&amp;#x2014;to control that represents the next action the user is likely to want to take. This saves keyboard users the work of having to use the Tab key to move focus into the dialog.\n
  66. For modal dialogs, modality should be enforced for both the keyboard and the mouse; the user shouldn&amp;#x2019;t be able to move focus outside of the dialog using Tab or Shift + Tab.\n
  67. If the user cancels the dialog (by pressing the Esc key, the close, or Cancel button), focus should be sent back to the element in the DOM that had focus prior to the dialog&amp;#x2019;s display. This helps keyboard users pickup where they left off.\n
  68. Implementing this behavior is easy. When the dialog is made visible, use focus() to move focus to the desired control inside the dialog.\n
  69. What about the other behaviors? Like enforcing modality for the keyboard? And, if the dialog is cancelled, moving focus back to the element in the DOM that had focus prior to the dialog&amp;#x2019;s display?\n\nFor these behaviors we&amp;#x2019;ll use three other APIs: document.activeElement, the contains() method and the focus and blur events.\n
  70. \n
  71. \n
  72. \n
  73. activeElement returns a reference to the currently focused DOM element.\n
  74. Use activeElement to capture a reference to the element that had focus prior to a dialog&amp;#x2019;s display. In this example, the showDialog() function passes the activeElement as a reference to the event listener used to hide the dialog.\n
  75. \n
  76. This makes it really easy for the event listener to return focus back to the element that had focus prior to the dialog&amp;#x2019;s display.\n
  77. Both jQuery and YUI provide a contains() method&amp;#x2014;an easy means of determining if one DOM element contains another. This is useful for enforcing modality.\n
  78. jQuery and YUI also provide ways to listen for delegated focus and blur events. These are useful as standard DOM focus and blur events do not bubble.\n\nIn jQuery you can use event delegation with the &amp;#x201C;focus&amp;#x201D; and &amp;#x201C;blur&amp;#x201D; events either by specifying &amp;#x201C;focusin&amp;#x201D; and &amp;#x201C;focusout&amp;#x201D;, or by using on() with either &amp;#x201C;focus&amp;#x201D; and &amp;#x201C;blur&amp;#x201D; and providing a delegation selector.\n
  79. Putting the two together: To enforce modality, simply bind a document-level, delegated focus event listener. That listener will then use contains() to determine if focus has left the dialog, and restore focus to the dialog if it does lose focus.\n
  80. A similar technique can be used to hide popup menus if focus is moved outside of the menu.\n
  81. The final API essential for keyboard access is the :focus pseudo class.\n
  82. \n
  83. Unfortunately IE 6 and 7 do not support the :focus pseudo class.\n
  84. \n
  85. It easy to supplement the lack of support for the :focus pseudo class in IE using JavaScript.\n
  86. Setting the CSS &quot;outline&quot; property to &quot;none&quot; is the primary reason that focus isn&apos;t visible in many web sites and applications.\n
  87. As it turns out, there is actually a website dedicated being mindful of not setting the CSS &quot;outline&quot; property to &quot;none&quot;.\n
  88. If you are looking to provide custom focus styles for your site or application, I would recommend not globally removing the browser&amp;#x2019;s default outline because it is likely there are going to be instances now, and especially later, where you might forget to define a focus style&amp;#x2014;leaving the user without a visualization of focus.\n\nRather than globally removing the browser&amp;#x2019;s focus outline, selectively remove it for instances where you are providing custom styles. This will help ensure you have some visualization of focus.\n
  89. All of these CSS properties are useful for styling focus as they don&apos;t affect box size and therefore the content around the focused element won&apos;t reflow.\n
  90. Custom focus styling is not possible in IE &lt; 8. But IE does provide a default focus style. In Yahoo! Mail, custom focus styles are considered a Progressive Enhancement.\n
  91. In addition to the :focus pseudo class, there is also :active.\n
  92. \n
  93. Practically speaking the :focus pseudo class is most useful when it comes to styling focus for atomic controls like buttons or links. For all other widgets, :focus isn&amp;#x2019;t enough as we&amp;#x2019;ll see in the follow examples.\n
  94. For example, consider popup menus and listboxes.\n
  95. A popup menu needs to be able to move selection in response to both the keyboard and the mouse. As the user switches between either input mechanism, the selection needs to be able to stay in sync.\n\nThere are two reasons we cannot rely on :focus and :hover:\n\n1) Lack of reliable support in older IE versions.\n\n2) Even if old IE support isn&amp;#x2019;t an issue, if we were to rely on :focus and :hover alone the user might see two menuitems selected simultaneously if they start with one device (mouse), then move to anounce (keyboard).\n
  96. For this reason, using a class is more robust than relying on :focus and :hover. As the user switches between the keyboard and the mouse, the corresponding event listener can stay in sync with the selection made via the previous input method.\n
  97. \n
  98. Another example: being able to persist selection when a control has lost focus. For example, the selected item in a listbox should still be rendered even when the control has lost focus.\n
  99. The currently selected item is marked with a class of &amp;#x201C;selected&amp;#x201D; as the user presses the up and down arrow keys.\n
  100. \n
  101. contains() is used to determine if the listbox has focus. When the listbox has focus, a class of &amp;#x201C;focus&amp;#x201D; is added to the root element.\n
  102. With a class of &amp;#x201C;focus&amp;#x201D; on the root element, the CSS can be structured so that the selected item in the list is rendered blue when the widget has focus, and gray when it does not.\n
  103. \n
  104. \n
  105. As we&amp;#x2019;ve seen, implementing keyboard navigation across all of the various widget types involves handling a very few number of keys. \n
  106. Working examples of all of the widgets from this presentation are available on github.\n