Last week I posted a tutorial that demonstrated using a simple application how to implement progressive enhancement into your Ajax projects. The one major flaw in the final Ajax-driven page from that tutorial is the lack of deep linking when JavaScript is enabled.
Although the resulting code is clean, works well, and is easy to maintain, the lack of deep linking is enough to cause a client to balk at the use of progressive enhancement in such a circumstance. So, in this brief tutorial, I’ll describe how to incorporate deep linking into that page.
If you haven’t already gone through the previous tutorial, doing so might help you get up to speed — but it’s not absolutely necessary, since the code we’ll be using is pretty straightforward.
Step 1: Review the Primary Function From the Previous Tutorial
The final JavaScript code from the previous tutorial included a function called getEmployeeInfo
, which is the primary piece of code we’ll be working with in this tutorial. Here is that function:
function getEmployeeInfo() { var myLinksCollection = document.getElementsByTagName("a"); for (i=0;i<myLinksCollection.length;i++) { myLinksCollection[i].onclick = function() { if (this.href.indexOf("view=") !== -1) { var clickedHREF = this.href; var clickedView = clickedHREF.split("view="); ajaxInitiate(clickedView[1]+'.html'); return false; } } } }
We’ll be adding a few lines of code to the above function in order to implement deep linking into this application.
Step 2: Add the Hash Character to the URL
In order to deep link to a particular state in the application, we want to utilize the hash character (#), using it to append an identifier to the URL of the page. JavaScript lets us access the current hash using the following line of code:
location.hash = "identifier";
That line can be added anywhere inside the anonymous function, and that will add a hash to the current URL, followed by the word “identifier”, without reloading the page. If a hash already exists, the text following the hash will be changed to “identifier”. The hash character makes the link internal, preventing a page refresh, the same way this would occur in an href
value of an anchor tag. Of course, we don’t want to just put any old text in there, but place some text that will help us identify the state of the Ajax application.
In the anonymous function, the current state is identified by the clickedView
array, so we can use that to append an identifier to the current URL, like this:
location.hash = clickedView[1];
Let’s take a look at how the page works after adding that line to the code:
Now the content is loading correctly, and each time a link is clicked, the value following the hash character in the URL is changed, helping us identify what state the application is in.
Step 3: Change Content According to the Current State
Now that the application is appending a state identifier to the current URL, we need to check to see if that identifier exists, and display the correct information. Here’s the code that will accomplish this:
if (location.hash) { ajaxInitiate(location.hash.replace("#","")+'.html'); }
It’s pretty simple: We check to see if the “hash” character exists. If it does, then we call the ajaxInitiate
function with the hash text as the file name that’s passed as an argument. Since the location.hash
property includes the actual hash symbol (#), we’re using the replace
method to strip out the hash and get a clean file name.
The above code is added before the loop in the getEmployeeInfo
function, so the complete function now looks like this:
function getEmployeeInfo() { if (location.hash) { ajaxInitiate(location.hash.replace("#","")+'.html'); } var myLinksCollection = document.getElementsByTagName("a"); for (i=0;i<myLinksCollection.length;i++) { myLinksCollection[i].onclick = function() { if (this.href.indexOf("view=") !== -1) { var clickedHREF = this.href; var clickedView = clickedHREF.split("view="); ajaxInitiate(clickedView[1]+'.html'); location.hash = clickedView[1]; return false; } } } }
Drawbacks to this Method
There are two drawbacks to this method. One small drawback is that the content does not change if the URL is manually altered after the initial page view. The hash character will only affect the page’s content on the first page view, when the entire page is initially loaded. But that’s not a big deal, since the content can easily be changed by clicking any of the links after the initial page view. The only time we’re really concerned about the state of the hash tag is on the initial page load, so it works fine in that respect.
The other drawback is that this method does not preserve the back button. You’ll notice that if you use the back button to try to visit a previous state, the URL will change, but the content is not affected. This happens because the URL change is only internal, and does not initiate a full page refresh. Preserving the back button in Ajax applications is a more complicated process that is beyond the scope of this simple tutorial.
Conclusion
And that’s it, our application now has deep linking, and works in virtually the same way as the PHP-only version, aside from the drawbacks mentioned above.
Use the links below to view the final demo page, or download the complete code, including the code from the previous tutorial. The link to the demo page includes a hash identifier, so you can see how the code works.
Thanks for the tutorial..
I’d like to add shed some light into the drawbacks presented in your tutorial , I’ve been using deep linking for quite some time now, i was stuck at first with these problems, but eventually found a plugin ( for jQuery ) called jQuery.history that would solve both drawbacks of your code ..
I know this is a jQuery plugin, but the functionality itself can be ported to a normal independent JS code to be used with your code.
You can check a website using the deep linking and history saving techniques at http://www.ayb-sd.org
Hope i helped!
Thanks for that example site and the plugin. From my examination of that site, and the jQuery plugin, it seems that in both cases the code that’s used is creating a full page refresh, or else an inner page refresh through an iframe, which kind of defeats the purpose of using ajax/js in the first place.
I’ll have to examine the code more closely, but it does look like an interesting plugin, thank you.
A good explanation of the jquery.history plugin is found here:
http://www.overset.com/2008/06/18/jquery-history-plugin/
It actually looks like a very good method to use to preserve history and allow back-button use in a JS/Ajax application. And although it seems to use an iframe, it does seem to work fast and without a full page refresh. Although technically I think it’s still reloading the entire page that’s served inside the iframe, so it may not be ideal in some circumstances.
yes you have really engraving ideas. One of the biggest benefits of Ajax is that it is based on open standards which are sustained by a multiplicity of platforms and browsers. This eases the programmer with enhance accessibility and flexibility to exploit what they entail across browsers. A good web designer deploys Ajax on the client’s web pages to improve the user experience.
Thanks for your blog.
I am new to javascript and I was wondering if anyone could shed some light on adding this history method to links within an xsl document. I really just want the browser to record a page change in the browser cache and I am really not concerned with form data, I am having trouble adding the history to the various links in my document because of the way they are formatted. Here is an example;
<a href=”doAjaxDualAction2(‘reportlist’,{psITPWorkArea/@role});”>DATANETWORK</a>
basically this is a link in the root xsl document that will take the user to a another xsl stylesheet that is loaded within a frame. I really only wanted to add an anchor to the link and have it recorded by jquery.history.
Any help would be much appreciated.
Truly i agree with your point , my blog has 44 post but only 10 of them are popular and driving more pageviews while the other are not getting enough pageviews , i will try your tips listed above , hope it helps me getting good result
Thank you
what is the point of a deeplink that does not load the content based on the url (changed by the user, or clicked in anywhere, emails, social networks, etc)
I mean that is the only goal of deeplinks, if you strip that feature from it then it’s not a useful link anymore.
Is there any tutorials about implementing deep-linking in DOJO ?