Hijax: Progressive Enhancement with Ajax
- ,
Ajax
The problem
Most of the big Ajax apps out there today treat the technology as an "all or nothing" requirement. Either your user-agent supports Ajax (and therefore you can use the application) or it doesn't (so you can't).
If a fallback solution is provided (and quite often, one isn't), it takes a lot of time and resources to create a "separate but equal" non-Ajax version.
The solution
Progressive Enhancement to the rescue. [SC]
Progressive Enhancement
Progressive Enhancement in theory
Begin with your content. Content, after all, is king. Then, mark up your content in a semantically meaningful way. Describe what the content is, not how it should look or how it should behave.
Then, you can apply a presentation layer and/or a behaviour layer.
If the presentation layer or behaviour layer is stripped away, the semantically meaningful content is still available.
Progressive Enhancement in practice
Use (X)HTML to mark up your content.
Use CSS to describe how it should look.
Use DOM Scripting (JavaScript and the Document Object Model) to describe how it should behave.
CSS: inline vs. external
The most prevalent example of Progressive Enhancement is the application of CSS. The separation of style and content ensures that both are easier to update.
Inline styles increase page size and make for a more a laborious editing process:
<p style="font-weight: bold">This is an introductory paragraph.</p>
Keeping styles external allows for easier updates:
<p class="introduction">This is an introductory paragraph.</p>
p.introduction { font-weight: bold; }
JavaScript: inline vs. external
The same idea can be applied to the behaviour layer. Unfortunately, when JavaScript is added to a web page, it is often inline.
There's the javascript: pseudo-protocol. What the hell is a pseudo-protocol anyway? It's nothing like HTTP.
<a href="javascript:window.open('help.html')">contextual help</a>
Another common technique is to apply a useless empty internal link pointer as the value of the href attribute:
<a href="#" onclick="window.open('help.html'); return false;">contextual help</a>
Don't have JavaScript? Tough luck... you get nuthin'.
Using the DOM with a genuine href value is good:
<a href="help.html" onclick="window.open(this.getAttribute('href')); return false;">contextual help</a>
But the behavioural instructions are still intermingled with the structural markup. The best solution is to remove these event handlers from the markup completely:
<a href="help.html" class="help">contextual help</a>
External JavaScript function
You can then write a function in an external JavaScript file to add the desired behaviour:
function doPopups() {
if (document.getElementsByTagName) {
var links = document.getElementsByTagName("a");
for (var i=0; i < links.length; i++) {
if (links[i].className.match("help")) {
links[i].onclick = function() {
window.open(this.getAttribute("href"));
return false;
};
}
}
}
}
This application of Progressive Enhancement to the behaviour layer is known as Unobtrusive JavaScript. [CH]
Unobtrusive JavaScript
Some general rules of thumb when it comes to Unobtrusive JavaScript:
Avoid using <a href="#">
Avoid using <a href="javascript:...">
Avoid using inline event handlers.
Applying Progressive Enhancement to Ajax
While most developers see the advantages of Progressive Enhancement as it applies to CSS and DOM Scripting, many have an allergic reaction to the suggestion that the same principle can be applied to Ajax applications.
Common rebuttals proffered include:
"But it's a whole different paradigm - the old rules don't apply."
Or:
"But it's not a website anymore - it's more like a desktop application."
These protestations can be best summarised as being, frankly, bollocks.
Why it matters
Describing the difficulty in accessing Ajax applications from mobile devices, Thomas Vander Wal wrote:
"It must degrade well. It must still be accessible. It must be usable. If not, it is a cool useless piece of rubbish for some or many people." [TVW]
For the sake of completeness, here's the obligatory quote from Sir Tim Berners-Lee:
"The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect." [TBL]
Hijax
The Hijax approach
If the success of Ajax has shown us anything, it's that a snappy buzzword will get you far. I'd like to propose my own buzzword, Hijax, to describe a methodology for applying Progressive Enhancement to Ajax. [JK]
Begin by creating web pages that use traditional non-Ajax page refreshes. Data is sent to the server using hyperlinks (perhaps with query strings) or through form submissions. The server then returns updated versions of entire pages.
Now, intercept (or hijack) those same links and forms using (hopefully unobtrusive) JavaScript. Send the same to data to an instance of the XMLHttpRequest object instead of sending it all the way back to the server.
The server returns only the information that's required instead of sending back an entire page.
Server-side requirements
For the Hijax approach to work successfully, your back-end architecture should be built in a modular fashion.
Your web pages are then constructed by joining individual modules together. For example, you would have one module for your navigation elements, another for a log-in form, yet another for a shopping cart, etc.
Incidentally, creating an API (Application Programming Interface) is the logical extension of this approach.
The paradox
On the one hand, I'm suggesting that, in order to create an Ajax application, you should begin by creating a non-Ajax application.
On the other hand, I'm suggesting that, in order to create a successful Ajax application, you need to think about your server-side architecture from the start.
This paradox can be resolved thusly:
Plan for Ajax from the start... implement Ajax at the end.
Pattern recognition
Think of situations that fit this pattern:
A web page includes a form. When this form is submitted, the very same page reloads, but with just part of the page updated.
Some examples would be blog comment forms or registration forms.
More pattern recognition
Think of similar situations that involve hyperlinks:
Clicking a link on a web page reloads the very same page, but with just part of the page updated.
Examples include quick product ratings (like Amazon's), filtering or ordering a table of results, or navigating the archives of a blog.
Choosing a data format
The X in Ajax ostensibly stands for XML, but you actually have a range of options in your choice of data delivery format.
You can receive XML (in the responseXML property) which can then be parsed using DOM methods.
You could also receive data written in JSON (JavaScript Object Notation) which can be parsed using eval(). [DC]
Alternatively, you could simply have the server send back chunks of HTML in the responseText property. These HTML fragments can be quickly and easily inserted into your web page using the read/write innerHTML property.
Much as it pains me as a Standardista to say this, the innerHTML property is faster and easier than using the W3C DOM and enjoys great cross-browser support.
If you need to update many different parts of the same page, use XML or JSON, but if you need to just update one part of a page, innerHTML might be the way to go.
This design pattern is so simple and straightforward, it is now a microformat called AHAH: Asynchronous HTML and HTTP. [AH]
Keep It Simple Stupid
Hijax fulfils the KISS philosophy. The XMLHttpRequest object acts as a dumbwaiter, ferrying information backwards and forwards between the client and the server, without performing any complex tasks. Client-side processing is kept to an absolute minimum. All the heavy lifting occurs on the server.
Benefits of Hijax
There is no need to spend time and resources building a non-Ajax version of your application. Using Hijax, your Ajax version and your non-Ajax version are one and the same. The application will degrade gracefully.
You don't need to duplicate any logic. For instance, if you want to validate a form using Hijax, all the validation logic remains on the server.
Because the browser isn't being asked to do anything clever, you can keep your JavaScript file sizes to a minimum. If your server-side code logic is long and complex, that's okay: it sits on the server (a more predictable environment than the client). But if your client-side code is big and bloated, the user is penalised with long download times. Using Hijax, download times are reduced.
Most importantly, Hijax ensures that your links are spiderable and potentially bookmarkable.
Bibliography
[AH] David Hansson, Kevin Marks and Ernest Prabhakar, AHAH: Asynchronous HTML and HTTP http://microformats.org/wiki/rest/ahah
[CH] Christian Heilmann, Unobtrusive JavaScript http://www.onlinetools.org/articles/unobtrusivejavascript/
[DC] Douglas Crockford, Introducing JSON http://www.json.org/
[JK] Jeremy Keith, Hijax http://domscripting.com/blog/display/41
[SC] Steve Champeon, Progressive Enhancement: Paving the Way for Future Web Design http://hesketh.com/publications/progressive_enhancement_paving_way_for_future.html
[TBL] Tim Berners-Lee, Web Accessibility Initiative http://www.w3.org/WAI/
[TVW] Thomas Vander Wal, For Many, Ajax is Not Degrading, But it Must http://vanderwal.net/random/entrysel.php?blog=1770




