Skip to content

Instantly share code, notes, and snippets.

@twalker
Last active September 20, 2015 21:22
Show Gist options
  • Save twalker/9733811 to your computer and use it in GitHub Desktop.
Save twalker/9733811 to your computer and use it in GitHub Desktop.
Backbone View mixin to handle keyboard events.
/**
* View mixin to handle keyboard events.
* It requires patching for method overrides.
*
* @example
* var KeyedView = Backbone.View.extend({});
* mixer.patch(KeyedView.prototype, keyable);
*
* var keyedView = new KeyedView({
* keyboardEvents: {
* 'mod+s': function(e){ console.log('Save!')}
* },
* ...
* });
*
* Borrowed heavily from:
* https://github.com/elasticsales/backbone.mousetrap/blob/master/backbone.mousetrap.js
*
* Modified/Forked to support:
* - AMD
* - mixer.patch instead of direct monkey patching
*
**/
define(function(require){
var Mousetrap = require('mousetrap')
, lodash = require('underscore');
// Map from keyboard commands to the View instance that most recently bound each one.
// so we can avoid accidentally unbinding keys when a view replaced a previous view's keybinding.
var lastBound = {};
return {
keyboardEvents: {},
bindKeyboardEvents: function(events){
if (!(events || (events = lodash.result(this, 'keyboardEvents')))) return;
for (var key in events) {
var method = events[key];
if (!lodash.isFunction(method)) method = this[events[key]];
if (!method) throw new Error('Method "' + events[key] + '" does not exist');
method = lodash.bind(method, this);
// Use global-bind plugin when appropriate
// https://github.com/ccampbell/mousetrap/tree/master/plugins/global-bind
if ('bindGlobal' in Mousetrap && (key.indexOf('mod') !== -1 || key.indexOf('command') !== -1 || key.indexOf('ctrl') !== -1)) {
Mousetrap.bindGlobal(key, method);
} else {
Mousetrap.bind(key, method);
}
lastBound[key] = this;
}
return this;
},
unbindKeyboardEvents: function() {
for (var keys in this.keyboardEvents) {
if (lastBound[keys] === this) {
Mousetrap.unbind(keys);
delete lastBound[keys];
}
}
return this;
},
delegateEvents: function() {
return this.bindKeyboardEvents();
},
undelegateEvents: function() {
return this.unbindKeyboardEvents();
},
remove: function() {
return this.unbindKeyboardEvents();
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment