So I was playing around with keyboard interface possibilities a couple of years ago, and eventually got the go ahead at OkCupid to implement keyboard shortcuts for navigating the site. The condition was it had to be minimally invasive and not eat up overhead tracking keystrokes. I also wanted to be able to track modifier keys sensibly, and have a simple interface for setting shortcuts.
kbind’s sole purpose is to track key strokes and keep an internal representation. To add a keyboard shortcut, you just write:
kbind["CTRL+A"] = function () { alert("Hiya"); };
… and it adds it to the kbind object as a method. You can also add stacked combinations, like
kbind["CTRL+ABIDE"] = function () { alert("Yeah, well, you know, that's\ just, like, your opinion, man"); };
… which I programmed largely so I could put easter eggs in the okcupid interface (never got around to it). It also includes a built in toggle mechanism, which you can set like this:
kbind["T"] = { toggle : { toggleState: false, on:function() { alert("I'm on!"); }, off:function() { alert("I'm off!"); } } }
Finally, you can switch it on and off with kbind.enable() and kbind.disable().
The code is below, do as you please with it. This one’s based on the jQuery library; you can find the original, Prototype.js version at OkCupid.
/* kbind.js - because I hate reaching for my mouse Quietly keeps track of key combinations and allows interface for event binding. */ var kbind = { ctrl : false, shift : false, opt : false, stack : "", clamp : false, extant : false, hardclear : false, translations:{ //Enter _13:"ENTER", //Numpad _96:"0", _97:"1", _98:"2", _99:"3", _100:"4", _101:"5", _102:"6", _103:"7", _104:"8", _105:"9", _107:"+",_61:"+",_187:"+", //unify keys _109:"-",_189:"-" }, init:function(hardclear) { this.hardclear = (hardclear?true:false); if(this.extant) return; this.extant = true; var pass = this; $(window).bind( "keyup", function(e) { if(pass.clamp) return; // Unlink modifier keys if(e.keyCode == 17) { pass.ctrl = false; pass.stack = ""; } else if(e.keyCode == 16) { pass.shift = false; pass.stack = ""; } else if(e.keyCode == 18) { pass.opt = false; pass.stack = ""; } else if(pass.hardclear) { pass.stack = ""; } pass.state(); return; } ); $(window).bind( "keydown", function(e) { if(pass.clamp) return; // Add modifier keys if(e.keyCode == 17) pass.ctrl = true; else if(e.keyCode == 16) pass.shift = true; else if(e.keyCode == 18) pass.opt = true; else { // Translate and add to the stack if(pass.translations["_" + e.keyCode]) pass.stack += pass.translations["_" + e.keyCode]; else pass.stack += String.fromCharCode(e.keyCode).toUpperCase(); } pass.state(); return; } ); // This addition prevents the ctrl key from // getting stuck on ctrl+click $(window).bind( "mousedown", function(e) { if(pass.clamp) return; pass.ctrl = false; pass.state(); } ); }, disable:function() { this.clamp = true; }, enable:function() { this.clamp = false; }, state:function() { if(this.ctrl) ctr_text = "CTRL+"; else ctr_text = ""; if(this.shift) sft_text = "SHIFT+"; else sft_text = ""; if(this.opt) opt_text = "OPT+"; else opt_text = ""; if(this.stack) act_text = this.stack; else act_text = ""; pressed = ctr_text + sft_text + opt_text + act_text; if(this[pressed]) { if(this[pressed].toggle) { if(!this[pressed].toggleState) { this[pressed].toggleState = true; this[pressed].toggle.on(); } else { this[pressed].toggleState = false; this[pressed].toggle.off(); } } else { this[pressed](); } this.stack = ""; } } }; kbind.init();
Tags: Code, javascript, keyboard, keyboard shortcuts, shortcuts, snippet