Last week a friend of mine was claiming that you can’t easily capture keyboard events on non-input HTML elements such as div or span. The fact is: it is easy.
See this demo:

You can use the arrow down / up keys to move the selection down or up. Find a working demo here.
The HTML:
<ul id="list"> <li class="list-item" tabindex="0">test 1</li> <li class="list-item" tabindex="1">test 2</li> <li class="list-item" tabindex="2">test 3</li> <li class="list-item" tabindex="3">test 4</li> <li class="list-item" tabindex="4">test 5</li> <li class="list-item" tabindex="5">test 6</li> <li class="list-item" tabindex="6">test 7</li> </ul>
Really the only trick here is to add a tabindex attribute to each list element. This way it can receive the focus and starts to capture keyboard events.
The JavaScript:
$(".list-item").bind({ keydown: function(e) { var key = e.keyCode; var target = $(e.currentTarget); switch(key) { case 38: // arrow up target.prev().focus(); break; case 40: // arrow down target.next().focus(); break; } }, focusin: function(e) { $(e.currentTarget).addClass("selected"); }, focusout: function(e) { $(e.currentTarget).removeClass("selected"); } }); $("li").first().focus();
The keydown event figures out which key was pressed. If it was the arrow up key it selects the previous element and sets the focus on it. For the arrow down key the following element gets the focus. The focusin and focusout events add or remove a css class in order to make the selection more visible.
You can find the complete code of the example here: http://gist.github.com/410789 or by clicking view source in the demo.
I'm a Software Developer, currently working at
Thank you, this was really useful. I was building a “Yes – No” dialog pop up and wanted to catch Escape and Enter keystrokes; tried some really hideous methods before coming on here. I wasn’t really happy with the Safari glow around my div when the element was focused but removed it with CSS “outline: none;”.
Thanks for this awesome snippet! It`s exactly what I was looking for :). Just one small issues, any idea why focusin/focusout don`t work in IE?
Try this:
focus: function(e) {
$(“.list-item”).removeClass(“selected”);
$(e.currentTarget).addClass(“selected”);
},
instead of the focusout and focusin. See http://jsfiddle.net/4D3xe/