Adding Keyboard Input to Dojo Select Controls (dijit.form.select)
Posted By: Alex.Cottner on November 15th, 2012 in Dojo, General, Javascript
No Gravatar

I ran into a situation yesterday where I needed to extend the functionality of the dijit.form.select control so it could have proper keyboard input. Power users want to be able to tab through their forms and use the keyboard to get work done quickly. The stock select control from dojo only allows for use with a mouse and some pretty basic keyboard input. To change this, I just needed to override a couple methods on my controls and setup a new property.

Here is an example creating a new select control.

var select = new dijit.form.Select({
  id : 'Select',
  _onKey: selectOnKey,
  keysPressed: "",
  _onBlur: function() {
    this.keysPressed = "";
  }
});

I’m overriding the stock onKey event with my own so I get to decide what our keyboard input does. The keysPressed attribute will be used to track what keys the user has pressed while the control has focus. And once the control loses focus we reset our keysPressed property. Below is my selectOnKey function.

function selectOnKey(e) {
  if (e.charCode == 0 && e.keyCode == 38) // key up
  {
    for(var i = 0; i < this.options.length; i++)
        if(this.options[i].selected && i > 0)
        {
          this.setValue(this.options[i-1].value);
          return;
        }  
  }
  else if (e.charCode == 0 && e.keyCode == 40) // key down
  {
    for(var i = 0; i < this.options.length; i++)
        if(this.options[i].selected && i < this.options.length - 1)
        {
          this.setValue(this.options[i+1].value);
          return;
        }  
  }
  else if (e.charCode > 0)
  {
    this.keysPressed += String.fromCharCode(e.charCode).toLowerCase();
    for (var i = 0; i < this.options.length; i++)
      if (this.options[i].label && this.options[i].label.toLowerCase().indexOf(this.keysPressed) == 0)
      {
        this.setValue(this.options[i].value);
        return;
      }
  }
}

I only care about three situations. If the user hits up or down, move up or down in the list. If the user hits a character, add that character to our keysPressed string and move to the first match in the list.

This is a simple solution to the problem I needed, yours may need be more complicated. Perhaps you need to have an idle timeout so if the user stops typing for 4 seconds the keysPressed attribute gets reset. The nice thing about dojo is how easy it is to override and customize all of these things. Hopefully this will help somebody else.


Leave a Reply