Skip to content


Adding keyboard shortcuts with jQuery

I was privileged to spend a yesterday at OSCON with everyone at Twilio, and I managed to catch a few talks. I heard Sigurd Magnusson (of Silverstripe fame) give the talk “10 Usability Epiphanies for your Open-Source Web App” which focused on how to improve usability. Point 10 was “Keyboard”, and one suggestion was to allow enter and escape to proceed and cancel just like native dialog boxes. It just so happens that the web app I’m working on uses a non-native confirm dialog box with “yes” and “no” buttons, so on the plane home I changed the behavior to implement this small but crucial usability enhancement. You know, I like it. Small details like this will really improve the overall experience, and I thought I’d share the essentials of my now-enhanced jQuery dialog function here.

Here’s how it works. The script first adds some temporary HTML to the page to build the dialog box but hides it until it’s all set up. Next, we temporarily bind to the window’s keydown event (which is needed to capture escape and enter) and fire the associated button click event for key presses that we care about, including the “y” and “n”. For the button click events, we unbind the keydown event, destroy the dialog, and run the yes or no functions if they exist. As for the structure of the HTML and the CSS, I’ve only provided a bare minimum here to make it work, but the idea is that the div with the “modal” class fills the whole screen and prevents clicks and actions. In our app it has a semi-transparent PNG to grey out the rest of the screen. The Y and N of the yes and no buttons are also underlined to give the clue that they are keyboard shortcuts. I’m not sure how to hint that “enter” and “esc” also work, but I think in this case these behaviors are like good special effects in movies: they are best when they are so natural that they are unnoticed. A good enhancement would be to allow an arbitrary number of buttons besides “yes” and “no”, such as “Save” and “Cancel” and bind to the first unique character there. Also the best functions are jQuery plugins not in the global namespace, but this has been debated elsewhere for similar plugins.

JavaScript

function jConfirm(message, yesFn, noFn)
{
	var confHtml = '<div class="modal"><div class="confirm"><div class="message">(message here)</div>' +
	'<button class="yes_btn"><u>Y</u>es</button><button class="no_btn"><u>N</u>o</button></div></div>';
	var dialog = $(confHtml).appendTo('body').hide();

	// keyboard shortcuts
	$(document).bind('keydown', function(evt) {
		switch(evt.which) {
			case 27:	// escape
			case 78:	// letter 'n'
				$('div.confirm button.no_btn').click();
				break;
			case 13:	// enter
			case 89:	// letter 'y'
				$('div.confirm button.yes_btn').click();
				break;
		}
	});

	$('div.message', dialog).html(message);
	$('button', dialog).click(function(event){
		$(document).unbind('keydown');
		dialog.fadeOut(function() { dialog.remove(); });

		if($(this).hasClass('yes_btn')) {
			if(typeof yesFn == 'function') return yesFn(event);
		} else {
			if(typeof noFn == 'function') return noFn(event);
		}
	});
	dialog.fadeIn();
}

CSS

div.modal {
	position:absolute;
	left:0;
	top:0;
	width:100%;
	height:100%;
	z-index:100;
}

div.confirm {
	background-color:#fff;
	border: 2px solid #666;
	margin:auto;
	padding: 10px;
	position:relative;
	top: 200px;
	width: 300px;
}

div.message {
	color: #000;
	padding:10px 0px;
	text-align:left;
}

Posted in Uncategorized.