Skip to content

Commit

Permalink
Menu Button Examples: Remove space activation key for menuitems (pull #…
Browse files Browse the repository at this point in the history
…478)

For issue #403, this removes space as a way to activate a menu item. We chose to remove because @jongund believes there is a bug in Firefox that was triggering a click on the button after the menuitem was activated. Space did not exhibit this behavior in other browsers.
  • Loading branch information
jongund authored and mcking65 committed Oct 13, 2017
1 parent 9714cf4 commit bc0416e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 59 deletions.
82 changes: 36 additions & 46 deletions examples/menu-button/js/MenuItemAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
* The object that is a wrapper for the PopupMenu DOM element that
* contains the menu item DOM element. See PopupMenuAction.js
*/
var MenuItem = function (domNode, menuObj) {
var PopupMenuItem = function (domNode, popupMenuObj) {

this.domNode = domNode;
this.menu = menuObj;
this.domNode = domNode;
this.popupMenu = popupMenuObj;

this.keyCode = Object.freeze({
'TAB': 9,
Expand All @@ -45,7 +45,7 @@ var MenuItem = function (domNode, menuObj) {
});
};

MenuItem.prototype.init = function () {
PopupMenuItem.prototype.init = function () {
this.domNode.tabIndex = -1;

if (!this.domNode.getAttribute('role')) {
Expand All @@ -63,7 +63,7 @@ MenuItem.prototype.init = function () {

/* EVENT HANDLERS */

MenuItem.prototype.handleKeydown = function (event) {
PopupMenuItem.prototype.handleKeydown = function (event) {
var tgt = event.currentTarget,
flag = false,
char = event.key,
Expand All @@ -79,70 +79,57 @@ MenuItem.prototype.handleKeydown = function (event) {

if (event.shiftKey) {
if (isPrintableCharacter(char)) {
this.menu.setFocusByFirstCharacter(this, char);
this.popupMenu.setFocusByFirstCharacter(this, char);
}
}
else {

switch (event.keyCode) {
case this.keyCode.SPACE:
flag = true;
break;

case this.keyCode.RETURN:
// Create simulated mouse event to mimic the behavior of ATs
// and let the event handler handleClick do the housekeeping.
try {
clickEvent = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
}
catch (err) {
if (document.createEvent) {
// DOM Level 3 for IE 9+
clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('click', true, true);
}
}
tgt.dispatchEvent(clickEvent);
this.handleClick(event);
flag = true;
break;

case this.keyCode.ESC:
this.menu.setFocusToController();
this.menu.close(true);
this.popupMenu.setFocusToController();
this.popupMenu.close(true);
flag = true;
break;

case this.keyCode.UP:
this.menu.setFocusToPreviousItem(this);
this.popupMenu.setFocusToPreviousItem(this);
flag = true;
break;

case this.keyCode.DOWN:
this.menu.setFocusToNextItem(this);
this.popupMenu.setFocusToNextItem(this);
flag = true;
break;

case this.keyCode.HOME:
case this.keyCode.PAGEUP:
this.menu.setFocusToFirstItem();
this.popupMenu.setFocusToFirstItem();
flag = true;
break;

case this.keyCode.END:
case this.keyCode.PAGEDOWN:
this.menu.setFocusToLastItem();
this.popupMenu.setFocusToLastItem();
flag = true;
break;

case this.keyCode.TAB:
this.menu.setFocusToController();
this.menu.close(true);
this.popupMenu.setFocusToController();
this.popupMenu.close(true);
break;

default:
if (isPrintableCharacter(char)) {
this.menu.setFocusByFirstCharacter(this, char);
this.popupMenu.setFocusByFirstCharacter(this, char);
}
break;
}
Expand All @@ -154,27 +141,30 @@ MenuItem.prototype.handleKeydown = function (event) {
}
};

MenuItem.prototype.handleClick = function (event) {
this.menu.setFocusToController();
this.menu.close(true);
PopupMenuItem.prototype.handleClick = function (event) {
if (menuAction) {
menuAction(event);
}
this.popupMenu.setFocusToController();
this.popupMenu.close(true);
};

MenuItem.prototype.handleFocus = function (event) {
this.menu.hasFocus = true;
PopupMenuItem.prototype.handleFocus = function (event) {
this.popupMenu.hasFocus = true;
};

MenuItem.prototype.handleBlur = function (event) {
this.menu.hasFocus = false;
setTimeout(this.menu.close.bind(this.menu, false), 300);
PopupMenuItem.prototype.handleBlur = function (event) {
this.popupMenu.hasFocus = false;
setTimeout(this.popupMenu.close.bind(this.popupMenu, false), 300);
};

MenuItem.prototype.handleMouseover = function (event) {
this.menu.hasHover = true;
this.menu.open();
PopupMenuItem.prototype.handleMouseover = function (event) {
this.popupMenu.hasHover = true;
this.popupMenu.open();

};

MenuItem.prototype.handleMouseout = function (event) {
this.menu.hasHover = false;
setTimeout(this.menu.close.bind(this.menu, false), 300);
PopupMenuItem.prototype.handleMouseout = function (event) {
this.popupMenu.hasHover = false;
setTimeout(this.popupMenu.close.bind(this.popupMenu, false), 300);
};
4 changes: 4 additions & 0 deletions examples/menu-button/js/MenuItemLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ MenuItemLinks.prototype.handleKeydown = function (event) {
else {
switch (event.keyCode) {

case this.keyCode.SPACE:
flag = true;
break;

case this.keyCode.ESC:
this.menu.setFocusToController();
this.menu.close(true);
Expand Down
3 changes: 1 addition & 2 deletions examples/menu-button/js/PopupMenuAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ PopupMenuAction.prototype.init = function () {
menuElement = menuElements[i];

if (!menuElement.firstElementChild && menuElement.getAttribute('role') != 'separator') {
menuItem = new MenuItem(menuElement, this);
menuItem = new PopupMenuItem(menuElement, this);
menuItem.init();
this.menuitems.push(menuItem);
textContent = menuElement.textContent.trim();
Expand Down Expand Up @@ -230,7 +230,6 @@ PopupMenuAction.prototype.open = function () {
};

PopupMenuAction.prototype.close = function (force) {

if (typeof force !== 'boolean') {
force = false;
}
Expand Down
4 changes: 4 additions & 0 deletions examples/menu-button/js/PopupMenuActionActivedescendant.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,11 @@ PopupMenuActionActivedescendant.prototype.handleKeydown = function (event) {
}
else {
switch (event.keyCode) {

case this.keyCode.SPACE:
flag = true;
break;

case this.keyCode.RETURN:
// Create simulated mouse event to mimic the behavior of ATs
// and let the event handler handleClick do the housekeeping.
Expand Down
22 changes: 11 additions & 11 deletions examples/menu-button/menu-button-actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
<main>
<h1>Actions Menu Button Example Using <code>element.focus()</code></h1>
<p>
This example demonstrates how the
This example demonstrates how the
<a href="../../#menubutton">menu button design pattern</a>
can be used to create a button that opens an actions menu.
In this example, choosing an action from the menu will cause the chosen action to be displayed in the <q>Last Action</q> edit box.
</p>
<p>
In this implementation, each item in the menu is made focusable by setting <code>tabindex=&quot;-1&quot;</code> so the JavaScript can use <code>element.focus()</code> to set focus in response to events that trigger focus movement inside the menu.
An alternative technique for managing focus movement among menu items is demonstrated in
An alternative technique for managing focus movement among menu items is demonstrated in
<a href="menu-button-actions-active-descendant.html">the action menu button example that uses aria-activedescendant.</a>
</p>
<p>Similar examples include: </p>
Expand All @@ -49,10 +49,10 @@ <h2 id="ex_label">Example</h2>
</button>

<ul id="menu1" role="menu" aria-labelledby="menubutton1">
<li role="menuitem" onclick="updateLastAction(event)">Action 1</li>
<li role="menuitem" onclick="updateLastAction(event)">Action 2</li>
<li role="menuitem" onclick="updateLastAction(event)">Action 3</li>
<li role="menuitem" onclick="updateLastAction(event)">Action 4</li>
<li role="menuitem">Action 1</li>
<li role="menuitem">Action 2</li>
<li role="menuitem">Action 3</li>
<li role="menuitem">Action 4</li>
</ul>
</div>
<p>
Expand All @@ -62,7 +62,7 @@ <h2 id="ex_label">Example</h2>
<script type="text/javascript">
document.getElementById("action_output").value = "none";

function updateLastAction(event) {
function menuAction(event) {
document.getElementById("action_output").value = event.currentTarget.innerHTML;
}

Expand All @@ -76,7 +76,7 @@ <h2 id="ex_label">Example</h2>
</div>
<div role="separator" id="ex_end_sep" aria-labelledby="ex_end_sep ex_label" aria-label="End of"></div>
</section>

<section>
<h2 id="kbd_label">Keyboard Support</h2>
<h3 id="kbd1_label">Menu Button</h3>
Expand Down Expand Up @@ -164,7 +164,7 @@ <h3 id="kbd2_label" class="widget">Menu</h3>
</tbody>
</table>
</section>

<section>
<h2 id="rps_label">Role, Property, State, and Tabindex Attributes</h2>
<h3 id="rps1_label">Menu Button</h3>
Expand Down Expand Up @@ -216,7 +216,7 @@ <h3 id="rps1_label">Menu Button</h3>
<li>Added when the menu is open.</li>
<li>Indicates that the menu is displayed and that activating the menu button closes the menu.</li>
<li>The <code>aria-expanded</code> attribute is removed when the menu is closed.</li>
<li>Included to support touch devices where screen reader users can touch the menu button when the menu is displayed. Keyboard users cannot focus the menu button when the menu is open.</li>
<li>Included to support touch devices where screen reader users can touch the menu button when the menu is displayed. Keyboard users cannot focus the menu button when the menu is open.</li>
</ul>
</td>
</tr>
Expand Down Expand Up @@ -316,7 +316,7 @@ <h2 id="sc1_label">HTML Source Code</h2>
sourceCode.make();
</script>
</section>

</main>
<nav>
<a href="../../#menubutton">Menu Button Design Pattern in WAI-ARIA Authoring Practices 1.1</a>
Expand Down

0 comments on commit bc0416e

Please sign in to comment.