RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Restoring Conventional Browser Navigation to AJAX Applications : Page 3

Find out how to give AJAX applications better browser navigation functionality and allow users to set bookmarks.

The Search Application
Here's an example that shows how to apply Dojo's history features to the search application problem mentioned earlier. Figure 1 shows the Search application directory structure:

Figure 1. Search Application Directory Structure: The sample search application uses these folders.
Figure 2. Simple Search Form: Users enter some search text and click the Search button, which sends a background request to the server.
The main page (searchMain.jsp, from which users can trigger a search) resides in the application's root folder (see Figure 2). The dojo folder contains the standard Dojo files such as dojo.js. The script folder contains special JavaScript files for the search application, including HistoryTracker.js, which defines the application state implementation, and dojoUtility.js, which defines JavaScript utility functions such as the body onload handler function and the function for firing the search.

Author's Note: This sample application uses JSP, but the example would work equally well with any server-side technology (PHP, ASP, etc.).

Here's the HTML for the <form> tag shown in Figure 2:

   <form name="searchForm" action="#">
      <input type="text" name="searchTextElement"></input>
      <input type="button" name="Search" value="Search" 
Note that the HTML uses the input type of "button" (rather than using "submit") to avoid automatic form submission. The goal is to send an asynchronous background request to fetch the search result. Therefore, the button's onclick event calls the performSearch() method, which triggers search operation.

The performSearch() function code shown below is in a separate dojoUtility.js file:

   function performSearch(searchTxt, pageNumber) {
      var bindUrl = "/dojoapp/doSearch.jsp";
      if(searchTxt) {
         bindUrl += "?searchTxt=" + searchTxt ;
         if(pageNumber) {
            bindUrl += "&pageNumber=" + pageNumber;
            url: bindUrl,
            load: function(type, data, evt){
                  new HistoryTracker(data, searchTxt, 
                  pageNumber, "searchContent"));
               dojo.byId("searchContent").innerHTML = data;
Figure 3. Dummy Search Result: The elements of the search results appear at the bottom of the page.
}); } }
The performSearch() method accepts two parameters—searchTxt and pageNumber—that correspond respectively to the search text entered in the text box and the search page to which the user wants to navigate. The performSearch() function sends an asynchronous request to doSearch.jsp, which retrieves the search result. You can see a dummy search result at the bottom of Figure 3:

The code that produces the search results is:

   You have searched for: 
      <%= request.getParameter("searchTxt") %>
   Showing page number: 
      <%= (request.getParameter(
      "pageNumber") == null)  ? 
      "1" : request.getParameter(
      "pageNumber") %>
   <a href="javascript:performSearch(
      '<%= request.getParameter("searchTxt") %>', 
      '<%= (request.getParameter("pageNumber") == null)  ?  "2" : 
      "pageNumber") ) + 1) %>');">View next set of results</a>
This is a dummy page printing only the page number and search text. The doSearch.jsp page provides the anchor tag for fetching the next set of search results. The javascript:performSearch() function is the href location for that tag. It takes the search text and the next page number as parameter.

The performSearch() function uses the HistoryTracker object. You register the application state change by calling dojo.undo.browser.addToHistory(). To make that work, though, you need to remember to register the initial application state, which usually happens in the body onload event:

The handleBodyLoad() function is defined as:

   function handleBodyLoad() {
      var state = new HistoryTracker(null, null, null, "searchContent");
The handleBodyLoad() function creates a state object that has null values for both searchTxt and pageNumber. Then it registers the initial application state by passing that state object in the line dojo.undo.browser.setInitialState(state). Finally, it calls handleUrlHash(), which parses the URL hash and restores application state depending on the value of hash:

   function  handleUrlHash() {
      var urlHash = location.hash.substring(1);
      var searchText, pageNumber;
      if(urlHash && urlHash != '') {
         var hashParams = urlHash.split(";");
         for (i = 0; i < hashParams.length; i++) {
            var temp = hashParams[i].split("=");
            if(temp && temp.length > 0) {
               switch(temp[0]) {
                  case 'searchTxt': 
                     searchText = temp[1];
                  case 'pageNumber': 
                     pageNumber = temp[1];
      if(searchText) {
         if(pageNumber) {
            performSearch(searchText, pageNumber);
         else {
            performSearch(searchText, 1);
Figure 4. AJAX Search Results: The search results appear on the same page as the search form.
The handleUrlHash() method parses the URL hash to retrieve the search text and page number and then calls performSearch() with the interpreted search text and page number. The performSearch() method shown earlier is responsible for firing the search. It calls doSearch.jsp using searchText and pageNmuber as parameters, and then displays the search results.

That completes the search application; now you can launch the search page by browsing to the URL http://yourdomain/searchMain.jsp.

When you see the main form, enter some search text (for example, "What is Dojo") and you'll see the search results appear on the same page, (see Figure 4).

Although the page doesn't change, you'll see that the application appended a URL hash to the original URL, for example:

The URL hash contains semicolon-separated values for searchTxt and pageNumber. If you click the "View next set of results" link, you'll see a second search results page.

As you can see, Dojo can make your AJAX applications respect bookmarks and the Back and Forward buttons. As illustrated in the sample application, you assign a distinct URL hash to each page, which updates the browser history. Using this technique, the Back and Forward buttons work correctly, so users can easily bookmark any search page. The downloadable code contains the ready-to-use sample application described in this article. You can reuse the ideas it exemplifies as the basis of your own navigation-aware AJAX applications.

Gautam Kumar Singh is a Software Engineer with more than four years of professional experience in developing large enterprise web applications. He currently works as Lead Engineer for HCL Technologies, India.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date