Julian Jelfs’ Blog

jQuery keyboard control plug-in

Posted in Javascript, jQuery by julianjelfs on September 11, 2010

I had a requirement to come up with some keyboard control mechanism for our web app which I would like to be able to handle some peculiar requirements. Most tricky is that we do not know what the labels are in advance because they are configurable by the user. In the past this has led to a lot of duplicate access keys because we derive them on the fly.

I though maybe we could use something along the lines of the google chrome mouseless browsing extension which creates a little floating div with a number in it for each “clickable” thing. So I created a simple jQuery plug-in which does just that:

   1: (function($){

   2:  

   3: $.fn.keyboard = function(selector){

   4:     if(!selector || selector.length == 0)

   5:         return this;

   6:     

   7:     var shortcutsShowing = false;

   8:     var timer = null;

   9:     function hideShortcuts(){

  10:         $("div.kb-shortcut").remove();

  11:         target.unbind("keydown.kb");

  12:         target.unbind("keydown", "esc");

  13:         shortcutsShowing = false;

  14:         if(timer){

  15:             clearTimeout(timer);

  16:         }

  17:     }

  18:  

  19:     target.bind("keyup", "alt", function(){

  20:         if(!shortcutsShowing){

  21:             shortcutsShowing = true;

  22:             var kb =  $(selector, target);

  23:             var targets = {};

  24:             kb.each(function(i){

  25:                 targets[i] = $(this);

  26:                 var pos = $(this).offset();

  27:                 $("<div class='kb-shortcut'>" + i + "</div>")

  28:                     .appendTo("body")

  29:                     .css({

  30:                         top : pos.top + 5,

  31:                         left : pos.left + 5,

  32:                         opacity : 0.8

  33:                     });

  34:             });

  35:  

  36:             var buffer = [];

  37:             var timer = null;

  38:             target.bind("keydown.kb", function(e){

  39:                 if(timer){

  40:                     clearTimeout(timer);

  41:                     timer = null;

  42:                 }

  43:  

  44:                 buffer.push(String.fromCharCode(e.which));

  45:  

  46:                 timer = setTimeout(function(){

  47:                     var key = buffer.join("");

  48:                     buffer = [];

  49:                     var target = targets[key];

  50:                     if(target != null){

  51:                         $("div.tree").blur();

  52:                         target.click()

  53:                         hideShortcuts();

  54:                     }

  55:                 }, 500);

  56:             }).bind("keydown", "esc", function(){

  57:                 hideShortcuts();

  58:             }).one("click", function(){

  59:                 hideShortcuts();

  60:             });

  61:         } else {

  62:             hideShortcuts();

  63:         }

  64:     });

  65:     

  66:     return this;

  67: };

  68: })(jQuery);

So basically you call it on the container that you want to provide the scope for the event capture e.g. $(“body”) and you pass it a selector which will identify all the elements which you want it to highlight. So if you want it to highlight buttons you’d do this:

   1: $("body").keyboard(":button");

Having done that, when the user hits the alt key, all buttons will be marked with a little square with a number in it. The user types the number they want and that element gets clicked. Simple. It will also work with numbers of more than one digit, because the key presses are recorded in a buffer and then joined together after a brief pause (the duration of which could easily be made configurable). It has the advantage of being very easy to drop into an existing page without really having to rewrite anything. Don’t know whether we’ll use it – everyone might hate it, but I quite like it.

The little highlight squares have the class “kb-shortcut” attached to them, so you can style them how you like (again that could easily be passed in as an option).

One thing to note, this is currently dependent on the jquery.hotkeys plugin to capture the alt and escape key presses. This could easily be refactored to just use standard jquery functionality only.