Building great site navigation with jQuery and key listeners

Friday, 22 January 2010


Good navigation is essential to any site. Gone are the days when everything should appear above the fold, users now want and expect a rich internet experience from the sites you build. A vital part of this is experience is a good layout and good navigation, especially if there are a large number of elements on the page.

On top of this it is also worthwhile to consider users with accessability issues and who are constantly stuck with using the tab key to navigate around often poorly designed web pages.


With jQuery it is possible and easy to improve keyboard site navigation by binding listeners to certain keys. In this post I will go over some of the basics to give you some ideas of how you can challenge your own designs and think about including a more clever way to navigate around the elements on your page.

In my sample application I will have nine boxes in a 3 x 3 square. Allowing us to navigate left, right, up and down and performing some function when the enter is pressed. My navigation will be indicated by switching the class on the currently selected item.



A working example of this code can be found here

You can download the actual code from here

Let's begin by looking at a simple function to getting your site to listen to key presses:

$("document").ready(function() {
 
 $(document).keydown(function(e) {
  switch (e.keyCode) {
  }
 }
});

Here we have our jQuery document ready function and a document level listener for the keydown event. The last piece is the switch statement which will determine what action is performed whenever a key is pressed. As we are looking at navigating around our site, let's bind some listeners to the arrow keys. Here are the codes that we will need:

37 Left arrow
38 Up arrow
39 Right arrow
40 Down arrow

I'm also going to add the enter key (code 13) to perform an action on the currently selected item.

You can find a full list of keycodes here

Let's look at some pseudocode to see how our navigation will work:

$("document").ready(function() {
 
 $(document).keydown(function(e) {
  switch (e.keyCode) {
   case 13:
    // Perform some action when enter is placed
    return;
   case 37:
    // Navigate left
    break;
   case 38:
    // Navigate up
    break;
   case 39:
    // Navigate right
    break; 
   case 40:
    // Navigate down
    break;   
  }
 }
});

Now let's look at the full code to see how it all holds together:

<body>
 <div id="container">
  <div class='item'>0</div>
  <div class='item'>1</div>
  <div class='item'>2</div>
  <div class='item'>3</div>
  <div class='item'>4</div>
  <div class='item'>5</div>
  <div class='item'>6</div>
  <div class='item'>7</div>
  <div class='item'>8</div>
  <div style='clear:both;'></div>
 </div>
 <div style='clear:both;'></div>
 <div id="debug"></div>
</body>

We can see our nine boxes all floated left in a containing div and all having the item class. Here is the javascript:

$("document").ready(function() {
 $(".item:first").addClass("selected");
 
 $(document).keydown(function(e) {
  // Current index
  var cur_idx = $(".item").index($(".selected"));
  var max_idx = $(".item").length - 1;
  var row_length = 3;
  
  switch (e.keyCode) {
   case 13:
    $(".item").eq(cur_idx).effect("explode", {}, 500, function() {$(this).remove();});
    $(".item:first").addClass("selected");
    return;
   case 37:
    // Get index of current item, if 1 then nothing, else move one back
    if (cur_idx == 0) {
     var next_idx = 0;
    } else {
     var next_idx = cur_idx - 1;
    }
    break;
   case 38:
    if ((cur_idx - row_length) <= 0) {
     var next_idx = 0;
    } else {
     var next_idx = (cur_idx - row_length);
    }
    break;
   case 39:
    // Get index of current item, if max then nothing, else move one forward
    if (cur_idx == max_idx) {
     var next_idx = cur_idx;
    } else {
     var next_idx = cur_idx + 1;
    }
    break; 
   case 40:
    if ((cur_idx + row_length) >= max_idx) {
     var next_idx = max_idx;
    } else {
     var next_idx = (cur_idx + row_length);
    }
    break;   
  }
  
  if (typeof next_idx != 'undefined') {
   $(".item.selected").removeClass("selected");
   $(".item").eq(next_idx).addClass("selected");
  }
 }); 
 
});

We begin by setting the selected class on the first of our boxes.

Next we set the keydown listener to the document. When the function is called we begin by getting the index of the currently selected item and also the number of items. The row_length variable is used to navigate up and down to the item above or below.

Next comes our keyCode swtich statement. For each of the arrow keys codes 37, 38, 39 and 40 we calculate whether we are going to go outside the item at index 0 or the last iem and we navigate accordingly by removing the class for the currently selected item and applying it to the item at the next_idx index by using the jquery eq() function to target the item at index next_idx.

If the enter key is pressed (code 13) we call the jQuery UI effect "explode" and then remove the item and reset the selected class back to the first item.

This is just the tip of the iceburg of what can be achieved using jQuery and key listeners but it should give you a glimpse of the possibilities for building a responsive, interactive web page.

If you have some good examples of sites with outstanding keyboard navigation share it with us with a comment below.




blog comments powered by Disqus