On chrome, 'ctrl-[' triggers a key event with .which, .keyCode, and .charCode all set to 27. 27 is DOM_VK_ESCAPE [1]. On firefox, 'esc' sets .keyCode to 27 [2]. Firefox's 'ctrl-[' sets .which and .charCode to 91 (codepoint for '['), but .keyCode to 0. On both firefox and chrome, plain '[' sets .charCode to 91, as does firefox's 'alt-['. But not 'ctrl-[' on chrome.
It's one example out of many, but how do you distinguish such cases, short of enumerating the behavior of every browser (and I guess keyboard layout too)?
They have a big advantage, you know! When you create a jQuery plugin, you can show everyone - instantly. I feel like desktop applications (and even websites, to a degree) don't have that luxury.
It doesn't do modifier key event generation correctly. On a US keyboard, hold down shift and 4 (i.e. type "$"). The second item highlights. Now release shift. The first item highlights, incorrectly, because the library apparently generated a keydown event for "4" when the shift key was released. That's wrong by all standard conventions. Modifier key releases should never synthesize presses.
Also affects the "* a" combo if you release shift before releasing 8 then release 8 and press "a" it doesn't recognize the combination (presumably because its reading a key press of 8 in between them)
It's a mess (the core problem is that the X server automatically generates release/press event pairs to implement key repeat which can't affirmatively be detected as "synthetic"). But it's handlable heuristically.
The way I've seen it done it via a timeout on "release after a long press". If the key has been down for more than ~1 second, then hold off on interpreting a release event to see if there's a matching press already queued in the pipe or not. The timeout can be very short (the X server sends them both synchronously down the socket with no delay).
One small suggestion is to return Mousetrap from the various methods, so method calls can be chained.
Also, +1 for a reset() command. I recently patched radio.js to do this, and I think it's something many Ajax-style apps need. However, I'm seeing there might be a need to whitelist some bindings as being durable (survive a reset).
For most websites, I will leave. But for web "apps" like Google Docs, or GMail, or my company's internal apps, I want to use application-style keyboard shortcuts like Ctrl+S and Ctrl+T and Ctrl+N. I want Ctrl+N to create a new document inside my application, not a new browser window.
The best solution would be to ask users to give permission to a webpage to overwrite native keyboard shortcuts for their own uses.
Agree, probably the best example where it's okay to offer 'tip' type dialogs on opening the app "We've setup keyboard shortcuts for you, would you like to use them? (examples)". (Saving preferences for future visits).
The thing is, this isn't a problem space that's unique to web apps. I find nothing more frustrating than native OS X apps that bind over system-wide shortcuts (I'm looking at you, Adobe products). Web apps have a slightly trickier turf to navigate due to also having to watch out for web browser default shortcuts, but that doesn't suddenly make the problem unsolvable.
The problem isn't that keyboard shortcuts for web apps are inherently bad. The problem is application designers who choose their keyboard shortcuts poorly.
On the other hand, this is crucial for things like javascript terminal emulators (which are nice for avoiding the long load time of a java terminal emulator).
Nice, but could do with a bit of preventDefault love, at least for the examples. Firefox on Linux has Ctrl+Shift+K as Web Console, Ctrl+K as (seemingly) Goto Google.
Dear Asana, Evernote and all other text editing web apps: Can you please use this library to add ctrl + s = save support. I hit it so frequently during writing out of habit and every time I do so Chrome asks me to save the website out as a html file. Thanks! :)
This offers a few additional things such as supporting Gmail style key sequences, binding keyup events, supporting keys that require the shift modifier using their key name "?", triggering key commands programmatically, etc.
Awesome! I'm super excited about this. I've been using keymaster for my Chrome extension for custom key bindings [1] but it's suffering from two issues:
- Lack of "key-sequences" ala Gmail
- Bug where focusing on a page having already pushed down a modifier doesn't tell keymaster that the modifier is pushed. For example if you ctrl+tab to a page and keep the control key pushed, then hit an action key (say "f"), then what you really want is to trigger ctrl+f but keymaster doesn't recognize it because it doesn't see ctrl as having been pressed since it was already held down before the page had focus.
Looks like Mousetrap fixes both of these issues. Thanks a ton!
Keymaster has stagnated a bit, that's correct, but it's still a pretty quality piece of work. I'm using it for my own keyboard shortcut (jquery) plugin here : http://joeloliveira.com/chaves.js/demo/defaults.html
The goal of my plugin isn't to just bind keys but to provide sensible defaults and an easy interface to either override the defaults or create your own, as well as have a built-in mechanism to display a "help" modal window. After all, what good are keyboard shortcuts if you don't know what they are.
Check it out. Would love any feedback
(sorry, Craig, for me-too'ing / "hey look at me too"'ing your post).
It would be nice to see an ongoing project for this, with keyboard shortcuts becoming more popular (in use at Twitter, GitHub, and Google Plus for example). I'm planning to add the functionality on my own app soon and will take a look at this.
I don't know if this is on purpose, but the "Cmd+Shift+K" binding is not activated by "Ctrl+Shift+K" or "Alt+Shift+K" on non-Macs. Seems to work great otherwise, though.
Thanks! Command is bound to e.metaKey so whatever that works out to on PC, but you can specify multiple keys like in the next example, by passing an array.
If you really do want fine-grained control, for example, so that Cmd works on OS X, but it maps to something else entirely on other platforms, you can still use Ctrl and Cmd.
This might make more sense as a object model rather than class model. There is a lot of state behind the scenes (bind, trigger, reset), which would be natural for an object. Instead it is dumped into global state.
The use case might be to support multiple sets of key bindings, e.g., default, user specific, app specific, view specific. When you don't need one set anymore you just "reset" that set instead of resetting everything.
You know a library (or whatever) is awesome when you're initial reaction is "I can't believe this didn't exist already". I'll definitely be using this!
I checked out of curiosity: jquery.hotkeys is about 1.4kb minified, coincidentally the same size as this library. Of course you'd have to add jquery itself to get the total size, if you weren't already using it.
Very nice. I was about to hand roll my own implementation of this, but this just saved me some time :-)
I like how there's a working demo right there on the page - it's nothing groundbreaking but it definitely adds a bit more polish.
Something I'm wondering about - would it pay to have some sort of "variable" key binding whose value would differ depending on the user's OS (if this is even possible)? For example, instead of binding both command+k and ctrl+k, I would bind one combination that would work both on Mac and Windows systems. This isn't a deal breaker or major issue by any means, but I'd be interested to know if it can be done.
Hi craigc, I'd be interested in using this, but (and yeah, this is terrible) I need some sort of "scoping", i.e. hotkeys would dispatch differently based on what element is highlighted.
I realize I could achieve this by making my bound function aware of the scoping, but it would be much nicer to have first class library support (in a library with an already kickass-ly simple API). Any thoughts on this?
This looks really useful, and the API looks simple.
Just a quick reminder for those using any library like this; screenreader users (typically blind people) rely heavily on the keyboard to use their web browser. Adding your own shortcuts can really screw them over. It's usually best to make your custom shortcuts a feature that the user opts in to, off by default.
Nice hack -- I've been going this as inside of backbone.js app. I have a asset management app that uses keyboard shortcuts to quickly tag, choose, and manage photos.
Had I know about this I might have used it rather than bundling it into my views.
Dealing with keyboard-shortcuts and international keyboard is hard, I don't think I've ever gotten an app using ctrl-[ to work right.
edit: $ highlights when I type shift-4, while that's actually supposed to produce €