Skip to content

Instantly share code, notes, and snippets.

@mmun
Last active December 29, 2015 07:19
Show Gist options
  • Save mmun/7635747 to your computer and use it in GitHub Desktop.
Save mmun/7635747 to your computer and use it in GitHub Desktop.

Add keyboard shortcuts to Ember

  • Routes and Views can subscribe to shortcuts via some API to be determined. Fundamentally it will map key sequences (eg. esc, g i, ctrl+x ctrl+c) to actions on that object. The parsing and implementation of the key sequence can be left to an external library. Ember could ship with a basic one, ie. only length one sequences.

  • The keyboard shortcuts service would register a listener on the document object (or the ApplicationView, but Firefox has some weird focus behaviour when not using tab indices).

  • When a key event is caught, Ember inspects event.target for the nearest containing view (if any) and begins walking up the view tree, until it matches a shortcut on some view. If one matches then the associated action is called and the process stops.

  • If no view has a matching shortcut, then Ember checks to see if any global shortcuts are registered by a route.

  • Because the event is caught on the document event.stopPropagation is not needed. Typically, a shortcut will want to call event.preventDefault so this is the default behaviour. It can be overriden by passing in default: true. A distinction could be made for key up events as well by passing keyUp: true.

App.ApplicationRoute = Ember.Route.Extend({
  shortcuts: {
    // Call the action on the route
    'cmr+r': 'refresh',

    // Call the action on the route's controller
    '?': { action: 'toggleHelpModal', target: 'controller' },
    // or...
    '?': { action: 'toggleHelpModal', controller: true },

    // Call the action on another controller
    'ctrl+q': { action: 'logout', controller: 'session' }
  }
})
App.CommentView = Ember.View.Extend({
  shortcuts: {
    // Call the action on the view
    'esc': 'cancel',

    // Call the action on a different target such as controller or parentView
    'shift+enter': { action: 'submit', target: 'controller' },

    // Don't call `preventDefault`
    'x': { action: 'userTypedX', default: true }
  }
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment