Building a Single Page Webapp with jQuery

In a typical single page web app, you load a html page and keep updating it by requesting data from the server either periodically or whenever the user asks for. Such an application is well suited for data driven systems. For example, if you already have a REST API, you can easily create a single page web client for it. The best way of understanding what a single page web app is by looking at the web interface of Gmail

So let us define what we want to achieve in the end with our application:

  • We should be able to load different views on the same page.
  • We should be able to translate user intentions (clicks) into appropriate javascript function calls.
  • The url shown in the address bar of the browser should represent the state of the application. That is, when the user refreshes the browser, it should have the same content as prior to refresh.

The Root Page

So let us begin by defining the basic structure of our application. index.html is our application page that will be modified during the lifetime of our application. For the sake of simplicity, let us assume that we will be making changes to #application div only.

Intercepting link clicks

Now we need to intercept all the click actions on the links and change the url hash accordingly. For handling the url hashes, we are using the Jquery BBQ plugin. Intercepting the link clicks will help us in preventing the default navigation to other pages. Also, as this is the required behaviour for all the links, we will setup the interceptor at global level. If required you can change the scope of this interception by modifying the jQuery selector where we define the interception.

Defining the Routes

Next, we need to define the routes that are mapped to url hash. Also, since each hashchange represents an action on part of user, we will also define what function to execute for each hashchange. We do this by listening for haschange event and firing the appropriate js function.

Initialization

Even though, we have proper routes and actions defined now, our index page is still empty. We now need to initialize the app. This is done by setting the default hash, which will fire the hashchange event when the page loads or in case the user has refreshed the page, just triggering the hashchange event manually.

Sample Action

Now that we have the skeleton for our application ready, lets have a look at a sample action. Suppose the default action, is showing a list of users [#/users]. We have mapped this hash to the function showUserList. Now there are several ways of combining the html structure and the json data for userList, but we will be using the simplest of methods. First we will get the html fragment representing the userList using the $.load function, and then we will populate it with actual data that we get from the REST api.

var showUserList = function(){
	$('#app').load('/html/users.html #userListDiv', function() {
		$.getJSON('/users', function(data) {
			
			// create the user list
			var items = [ '<ul>'];
			$.each(data, function(index, item) {
				items.push('<li><a href="/users/"' + item.id + '">'
						+ item.name + '</a></li>');
			});
			items.push('</ul>');
			
			var result = items.join('');
			
			// clear current user list
			$('#userListDiv').html('');
			
			// add new user list
			$(result).appendTo('#userListDiv');
		});
	}
};

If you find all the string concatenation going on in above snippet a bit sloppy, you can always use your favourite template plugin for jQuery.

Note: The Object.extended function in above snippets comes from the wonderful Sugar.js library that makes working with native javascript objects a breeze.