Adding keyboard navigation to a client-side application

Ok, so warning, this isn’t exactly rocket science level JavaScript here. For a while now I’ve been wanting to build a simple demo of adding keyboard navigation to a client-side application and today I finally got off my lazy rear and wrote one up. As I said, this isn’t exactly difficult to do, but I thought it might be helpful for others to see a simple example of how it can be used.

To begin, I create an incredibly simple slide show demo. I began by simply defining slides in div tags:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="app.js"></script>
<link type="text/css" rel="stylesheet" href="app.css"></link>
</head>
<body>

<div id="slideshow" class="slideshow">
	<h2>Slides</h2>
    <div>
        Slide one
    </div>
    <div>
        Slide two
    </div>
    <div>
        Slide three
    </div>
	<p>
	<a id="prevLink" href="">Previous</a> / <a id="nextLink" href="">Next</a>
	</p>
</div>

</body>
</html>

I used a bit of CSS to hide the divs initially:

.slideshow div {
	display:none;
}

And super simple JavaScript to handle responding to the Previous/Next clicks:

$(document).ready(function() {
	"use strict";
	
	//first, cache the div holding our slide show
	var $slideshow = $("#slideshow");
	
	//now, let's get our slides, represented by divs
	var $slides = $("div", $slideshow);

	//current slide
	var currentSlide = 0;
	//max
	var maxSlides = $slides.length;
	
	//now, show the first one
	$slides.eq(0).show();
	
	//respond to clicks on the links
	$("#nextLink").on("click", function(e) {
		e.preventDefault();
		if(currentSlide+1 === maxSlides) return false;
		$slides.eq(currentSlide).hide();
		currentSlide++;
		$slides.eq(currentSlide).show();
	});

	$("#prevLink").on("click", function(e) {
		e.preventDefault();
		if(currentSlide === 0) return false;
		$slides.eq(currentSlide).hide();
		currentSlide--;
		$slides.eq(currentSlide).show();
	});

});

Just to be absolutely clear, there are approximately 932 thousand jQuery plugins out there that handle slide shows better than this. I just wanted something simple to start off. (And I was spurred to finally write this post after looking at someone’s slide deck embedded in a web page recently.) Since it is simple, I assume the code all makes sense so far. (If not, ask me in the comments below and I’ll explain anything that isn’t clear.)

Ok, so, how can we add keyboard navigation? The simplest way is to listen for a keyboard related events. There’s keydown, keypress, and keyup. Keyup “felt” appropriate to me so I used that. Since we want to respond to the event at the page level, I added my listener to the document object. (Would window have been more appropriate? Let me know below.)

$(document).on("keyup", function(e) {

});

The next step is to respond intelligently to the event. What keys you care about depends on what you’re building. For a slide show, it seemed to make sense to respond to the left and right arrows and move the current slide accordingly. (Maybe an up arrow could be used to return to slide 1 and down to the end.) All I had to do then was figure out what key code represented those values. According to the MDN docs for keyboard events, keyCode is deprecated and key should be used instead, but in my testing, key did not work in Chrome and keyCode worked in both Chrome and Firefox. Instead of Googling for a table of keyCode values, I quickly added a console.log and just typed left and right. This gave me a value of 37 for the left arrow and 39 for the right.

To make those work, I needed to decouple my “go back” and “go forward” code from the event handlers I had used before. Here is how I did that:

function prevSlide() {
	if(currentSlide === 0) return false;
	$slides.eq(currentSlide).hide();
	currentSlide--;
	$slides.eq(currentSlide).show();		
}
	
function nextSlide() {
	if(currentSlide+1 === maxSlides) return false;
	$slides.eq(currentSlide).hide();
	currentSlide++;
	$slides.eq(currentSlide).show();		
}
	
//respond to clicks on the links
$("#nextLink").on("click", function(e) {
	e.preventDefault();
	nextSlide();
});

$("#prevLink").on("click", function(e) {
	e.preventDefault();
	prevSlide();
});

And then I simply added calls to these new functions within my keyboard listening code.

	//listen for keyboard events
$(document).on("keyup", function(e) {
	if(e.keyCode === 37) {
		prevSlide();
	} else if(e.keyCode === 39) {
		nextSlide();
	}

});

This seems to work well, and is relatively simple, but I haven’t tested with Internet Explorer yet. Want to take it for a spin? Hit up the demo here: https://static.raymondcamden.com/demos/2015/feb/16/test2.html.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate looking for his next gig. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

Lafayette, LA https://www.raymondcamden.com

Comments