- or check tests in browser
- Simple language for defining bindings
- Key sequences (a-la Emacs chords)
- Nested scopes
- Default modifier (
defmodkey which is
commandon OS X and
- Ability to prevent defaults for whole sequence
keymage.min.js in your page:
There are no dependencies. It is possible to use library as a simple JS module, as an AMD module or as CommonJS module.
It worth to note that Keymage is on cdnjs which enables you to use it without downloading.
Plus, of course, it's on NPM.
Keymage exposes a single function,
// bind on 'a';// returning false prevents default browser reaction (you can always use// e.preventDefault(), of course);// binding on 'defmod' binds on Command key on OS X and on Control key in other// systems;
Handler function receives two arguments: the original event and the context so you can understand what and why was fired.
The context contains those properties:
shortcutis a string you've originally provided for binding
scopeis a scope which is currently active
definitionScopeis a scope where this shortcut was defined
;// -> "alt-c", "", ""
Keymage supports key sequences:
For this to fire you have to first press both
j, and then
k. Here's the catch though:
ctrl-j in most browsers means "open
downloads". Which will break your sequence obviously.
And while I encourage you to not override browser hotkeys, let's imagine you
have to do that. For this, you can pass an option object as last parameter,
having 'preventDefault' property set to
This option will prevent default on every key press which looks like a valid
part of a bound sequence (including the one triggering your handler). And in
this case it's perfectly legitimate - you're overriding
ctrl-j in the middle
of sequence, so common browser hotkey will still work.
Keymage support nested scopes. This means that your application can have few areas where you can gradually have more and more specific shortcuts. It works like this:
// You can skip scope argument if you want global work-always shortcut;// This will fire after "keymage.setScope('chat')";// This will fire after "keymage.setScope('chat.input')";
You can control scopes with helpful
popScope methods. This way
your nested view (or whatever is enabling nested scope) doesn't need to know
about parent scope:
keymage // scope is 'chat'keymage // scope is 'chat.input'keymage // scope is 'chat'keymagekeymage // scope is 'chat.deep.deeper'// way to jump out of deep scopingkeymage // scope is ''
pushScope returns resulting scope and
popScope returns topmost scope it
removed (so with parameters it's the one you've asked to remove).
Note that calling
popScope with name of a scope which is repeated few times
will pop topmost one, i.e.:
keymagekeymage // scope is 'this'
Last and optional argument to
keymage function is an option object. Here is a
list of possible options:
event.preventDefault()on every key press which looks like a part of defined sequence.
context: binding handler will be called with provided object as a context.
And if you ever need to unbind a handler, use this:
keymage(...) returns a function, which unbinds this shortcut when called:
var unbinder = ;;