Skip to content


JavaScript library to help modern web applications with accessibility concerns by making accessibility simpler

# ally.when.key

Executes a callback when a given key has been pressed.

# Description

This is a convenience API to avoid adding and removing keyboard event handlers and having to filter for specific keys in application code. Callbacks are executed synchronously while handling keydown events to maintain the ability to event.preventDefault().

Keyboard events are dispatched to the currently focused element (document.activeElement). This allows us to handle keyboard events only when the user is engaged in a particular widget.

# Key binding syntax

In order to easily register keyboard events including modifier keys, ally.when.key understands the following <key-binding> syntax:

<key-binding> primary key keyCode alt ctrl meta shift
space Space 32 no no no no
*+space Space 32 ? ? ? ?
shift+space Space 32 no no no yes
shift+*+enter Enter 13 ? ? ? yes
!shift+*+enter Enter 13 ? ? ? no
?shift+ctrl+enter Enter 13 no yes no ?
enter shift+8 Enter 13 no no no no
(continued) Backspace 8 no no no yes

Legend: no means the modifier key is not pressed, yes means the modifier key is pressed, ? means the state of the modifier key is ignored.

The <key-binding> syntax is defined by the following EBNF grammar, with property of map/keycode referring to the property names of

token-list    = token, { " ", token } ;
token         = { modifier, "+" }, key ;
key           = named-key | keycode ;
named-key     = ? property of ? ;
keycode       = ? /[0-9]+/ ? ;
modifier      = ( [ "!" | "?" ], modifier-name ) | "*" ;
modifier-name = "alt" | "ctrl" | "meta" | "shift" ;

# Modifier keys

The modifier keys may have different names/symbols depending on operating system and physical keyboard:

modifier key name physical key on keyboard
alt Alt, Option or on Mac)
ctrl Ctrl, on Mac
meta Meta, or or Command on Mac, or Windows on Windows
shift Shift, on Mac

# Usage

var handle = ally.when.key({
  enter: function(event, disengage) {
    // react to <kbd>Enter</kbd>
    console.log('enter pressed on',;
  32: function(event, disengage) {
    // react to <kbd>Space</kbd>
    console.log('space pressed on',;


# Arguments

Name Type Default Description
context <selector> documentElement The scope of the DOM in which keyboard events will be processed. The first element of a collection is used.
filter <selector> null The elements and descendants to exclude when processing keyboard events.
<key-binding> function required Mapping of <key-binding> to callback function. See Callback Signature for details. This argument is expected one or more times.

# Returns

A <service> interface, providing the handle.disengage() method to stop the service.

# Throws

# Callback signature

Name Type Default Description
event KeyboardEvent required The original keydown event.
disengage function required The service's handle.disengage() method.

The callback is executed in the context of context (that's where this inside the callback points to). The callback is passed the handle.disengage() method to allow simplified "execute once" behaviors. The callback's return value is ignored.

# Examples

# ally.when.key Example

ally.when.key Example on

play with ally.when.key Example on or open the document of ally.when.key Example

# Changes

# Notes

Firefox has a long standing issue with keyboard events propagating to the document while browser UI like autocomplete is being interacted with Gecko 286933.

The callback for the <key-binding> space only executes if no modifier key was pressed. In order to make the callback execute regardless of modifier keys, use the <key-binding> *+space.

The modifiers alt, ctrl, meta usually engage system-level or browser-level functionality. Do not use these modifiers lightly. For example alt+a prints the letter å on a Mac with German keyboard layout, meta+q exits the application and meta+space engages Spotlight.

# Contributing