Skip to content

An Ember.js addon for the painless support of keyboard events

License

Notifications You must be signed in to change notification settings

vladimir-e/ember-keyboard

 
 

Repository files navigation

npm version Build Status Code Climate Test Coverage

ember-keyboard

ember-keyboard, an Ember addon for the painless support of keyboard events.

Features

  • Dynamic priority levels allow you to specify which components respond first to key events and under what circumstances. (Thanks to ember-key-responder for the inspiration)
  • Human-readable key-mappings. (Thanks to ember-keyboard-service for the inspiration)
  • Support for both keyUp and keyDown, as well as the modifier keys: ctrl, alt, shift, and meta.
  • Conventional Ember architecture and service-based injection.
  • Compatible with both Ember 1.13 and 2.0+.

Installation

ember install ember-keyboard

Usage

First, inject ember-keyboard into your component:

export default Ember.Component.extend({
  keyboard: Ember.inject.service()
});

Once the keyboard service is injected, you need to activate it.

activateKeyboard: on('didInsertElement', function() {
  this.get('keyboard').activate(this);
})

This will place the component in the eventStack, meaning it'll be able to respond to key events. Let's say you want your component to respond to the key a as well as ctrl+shift+a. You could do so with:

import { keyUp } from 'ember-keyboard';

. . . .

aFunction: on(keyUp('a'), function() {
  console.log('`a` was pressed');
}),

anotherFunction: on(keyUp('ctrl+shift+a'), function() {
  console.log('`ctrl+shift+a` was pressed');
})

The modifier keys include ctrl, shift, alt, and meta. For a full list of the primary keys (such as a, 1, , Escape, and ArrowLeft), look here.

Finally, when you're ready for a component to leave the eventStack you can deactivate it:

deactivateKeyboard: on('arbitraryTrigger', function() {
  this.get('keyboard').deactivate(this);
})

Note that components will automatically be deactivated on willDestroyElement.

keyboardPriority

By default, all activated components are treated as equal. If you have two components that respond to ctrl+a, then both will get triggered when there's a ctrl+a event. However, this behavior is undesirable in some scenarios. What if you have a modal open, and you only want it and its child components to respond to key events. You can get this behavior by assigning a priority to the modal and its children:

noPriorityComponent; // priority defaults to 0
lowPriorityComponent.set('keyboardPriority', 0);

modal.set('keyboardPriority', 1);
modalChild.set('keyboardPriority', 1);

In this scenario, when a key is pressed both modal and modalChild will have a chance to respond to it, while the remaining components will not. Once modal and modalChild are deactivated or their priority is removed, then lowPriorityComponent and noPriorityComponent will respond to key events.

Perhaps more convenientally, this property can be passed in through your template:

{{my-component keyboardPriority=1}}
{{my-dynamic-component keyboardPriority=dynamicPriority}}

Note that priority is descending, so higher numbers have precedence.

Mixins

To reduce boilerplate, ember-keyboard includes several mixins with common patterns.

EKOnInsertMixin

import { EKOnInsertMixin } from 'ember-keyboard';

This mixin will activate the component on didInsertElement, and as per normal, it will deactivate on willDestroyElement.

EKOnFocusMixin

import { EKOnFocusMixin } from 'ember-keyboard';

This mixin will activate the component whenever it receives focus and deactivate it when it loses focus.

Note that to ensure that the component is focusable, this mixin sets the component's tabindex to 0.

EKFirstResponderMixin

import { EKFirstResponderMixin } from 'ember-keyboard';

This mixin does not activate or deactivate the component. Instead, it allows you to make a component the first and only responder, regardless of its initial keyboardPriority. This can be useful if you want a low-priority component to temporarily gain precedence over everything else. When it resigns its first responder status, it automatically returns to its previous priority. Note that if you assign a second component first responder status, the first one will in turn lose first responder status.

To make this possible, this mixin adds two functions to the component:

becomeFirstResponder

// from within the component
this.becomeFirstResponder();

Makes the component the first responder. It will be activated (ember-keyboard.activate()) if it has not yet been.

Note: This is accomplished by assigning the component a ridiculously high keyboardPriority (9999999999999). If you manually change its priority after it becomes first responder, it will lose first responder status.

resignFirstResponder

// from within the component
this.resignFirstResponder();

Resigns first responder status, in the process returning to its previous priority.

EKFirstResponderOnFocusMixin

import { EKFirstResponderOnFocusMixin } from 'ember-keyboard';

This mixin grants the component first responder status while it is focused. When it loses focus, it resigns its status.

Note that to ensure that the component is focusable, this mixin sets the component's tabindex to 0.

Special Cases & Advanced Usage

Ember.TextField && Ember.TextArea

To prevent ember-keyboard from responding to key strokes while an input/textarea is focused, we've included an initializer that reopens Ember.TextField and Ember.TextArea and applies the ActivateKeyboardOnInsertMixin and KeyboardEKFirstResponderOnFocusMixinMixin. Effectively, this means that anytime an input is focused, it will be first responder, preventing other events from firing. So for instance, if you've registered a high-priority listener to keyUp('a'), it won't fire every time the user presses 'a' while an input is focused. Nevertheless, if you've created a component extending from either Ember.TextField or Ember.TextArea, you can assign key listeners to it like any other component and it will respond as expected. This allows, for instance, for rich text editors to italicize text with keyUp('ctrl+i').

You get all this for free when you use the input and textarea helpers:

{{input}}
{{textarea}}

keyUp and keyDown

If you'd like to dynamically add and remove key listeners on a component, you can do so with the standard on and off functions. To ensure that the listener is formatted correctly, we encourage you to use the keyUp and keyDown functions:

import { keyUp, keyDown } from 'ember-keyboard';

. . . .

component.on(keyUp('ctrl+s'), someFunction);
component.off(keyUp('ctrl+s'), someFunction);

These functions create standardized names for the listeners that look like keyup:ctrl+s. The provided key and modifier keys are sorted alphabetically, so: keyUp('b+ctrl+alt') becomes keyup:alt+b+ctrl.

About

An Ember.js addon for the painless support of keyboard events

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 83.0%
  • HTML 14.6%
  • CSS 2.4%