Я как то себе писал, можете под себя доработать. Вообще таких штук много.
<script>
var KeyBoard = (function () {
function KeyBoard() {
this.activeKeys = [];
this.events = {};
this.onKeyDown = this.onKeyDown.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.dropKeys = this.dropKeys.bind(this);
this.initialize();
}
KeyBoard.prototype.on = function (command, handler, context) {
var keys = KeyBoard.getKeys(command);
var eventName = KeyBoard.getEventName(keys);
if (!this.hasEvent(eventName)) {
this.events[eventName] = [];
}
this.events[eventName].push({
originCommand: command,
eventName: eventName,
handler: handler,
context: context || window,
keys: keys
});
return this;
};
KeyBoard.prototype.off = function (command, handler) {
if (!command) {
this.events = {};
return this;
}
if (!handler) {
delete this.events[KeyBoard.getEventName(KeyBoard.getKeys(command))];
return this;
}
var eventName = KeyBoard.getEventName(KeyBoard.getKeys(command));
if (this.hasEvent(eventName)) {
this.events[eventName] = this.events[eventName].filter(function (binned) { return (binned.handler !== handler); });
if (!this.events[eventName].length) {
delete this.events[eventName];
}
}
return this;
};
KeyBoard.prototype.trigger = function (command) {
var eventName = KeyBoard.getEventName(KeyBoard.getKeys(command));
if (this.hasEvent(eventName)) {
this.triggerNumberEvent(eventName);
}
};
KeyBoard.prototype.destroy = function () {
this.activeKeys = [];
this.off();
document.removeEventListener('keydown', this.onKeyDown);
document.removeEventListener('keyup', this.onKeyUp);
window.removeEventListener('focus', this.dropKeys);
window.removeEventListener('blur', this.dropKeys);
};
KeyBoard.prototype.dropKeys = function () {
this.activeKeys = [];
};
KeyBoard.prototype.triggerNumberEvent = function (eventName) {
this.events[eventName].forEach(function (binned) {
binned.handler.call(binned.context, binned);
});
};
KeyBoard.prototype.initialize = function () {
KeyBoard.createValidateKeuMap();
this.setHandlers();
};
KeyBoard.prototype.hasEvent = function (eventname) {
return !!(this.events[eventname] && this.events[eventname].length);
};
KeyBoard.prototype.setHandlers = function () {
document.addEventListener('keydown', this.onKeyDown, false);
document.addEventListener('keyup', this.onKeyUp, false);
window.addEventListener('focus', this.dropKeys, false);
window.addEventListener('blur', this.dropKeys, false);
};
KeyBoard.prototype.onKeyDown = function (event) {
this.addActiveKey(event.keyCode);
var eventName = KeyBoard.getEventName(this.activeKeys);
if (this.hasEvent(eventName)) {
event.preventDefault();
this.triggerNumberEvent(eventName);
}
};
KeyBoard.prototype.addActiveKey = function (keyCode) {
if (this.activeKeys.indexOf(keyCode) !== -1) {
console.warn('duplicate key! ' + keyCode);
}
else {
if (KeyBoard.validKeys.indexOf(keyCode) != -1) {
this.activeKeys.push(keyCode);
this.activeKeys.sort(KeyBoard.sort);
}
}
};
KeyBoard.prototype.onKeyUp = function (event) {
this.activeKeys = this.activeKeys.filter(function (code) { return (event.keyCode !== code); });
};
KeyBoard.getKeys = function (command) {
return command.split("+").map(function (char) {
var key = char.toLowerCase();
if (key in KeyBoard.keyMap) {
return KeyBoard.keyMap[key];
}
else {
console.error('Неизвестная клавиша! ' + char);
throw new Error('Неизвестная клавиша! ' + char);
}
}).sort(KeyBoard.sort);
};
KeyBoard.getEventName = function (keys) {
return keys.join('+');
};
KeyBoard.sort = function (a, b) {
return a - b;
};
KeyBoard.createValidateKeuMap = function () {
for (var key in this.keyMap) {
if (this.keyMap.hasOwnProperty(key)) {
this.validKeys.push(this.keyMap[key]);
}
}
};
KeyBoard.keyMap = {
'backspace': 8,
'tab': 9,
'enter': 13,
'shift': 16,
'ctrl': 17,
'alt': 18,
'pause_break': 19,
'caps_lock': 20,
'escape': 27,
'page_up': 33,
'page_down': 34,
'end': 35,
'home': 36,
'left': 37,
'up': 38,
'right': 39,
'down': 40,
'insert': 45,
'delete': 46,
'0': 48,
'1': 49,
'2': 50,
'3': 51,
'4': 52,
'5': 53,
'6': 54,
'7': 55,
'8': 56,
'9': 57,
'a': 65,
'b': 66,
'c': 67,
'd': 68,
'e': 69,
'f': 70,
'g': 71,
'h': 72,
'i': 73,
'j': 74,
'k': 75,
'l': 76,
'm': 77,
'n': 78,
'o': 79,
'p': 80,
'q': 81,
'r': 82,
's': 83,
't': 84,
'u': 85,
'v': 86,
'w': 87,
'x': 88,
'y': 89,
'z': 90
};
KeyBoard.validKeys = [];
return KeyBoard;
})();
new KeyBoard().on('ctrl+e', function () {
alert('ctrl+e')
});
</script>