February 5, 2006
AJAX Design Patterns
By now the entire World has heard about AJAX, even those who don’t care about Web-Development have seen the potential of this new technology. Everybody is tired of endless introductions on how cool AJAX is and those endless lists of good examples like Google Suggest, GMail and alike, so I decided to cut a long story short and jump right into the real tutorial.
Is this tutorial any different from the others? Well yes and no, it is different in being a tutorial on how to design and build a complete site and not just some fancy little details like how to turn caching in AJAX off or how to create a fancy widget. To keep the tutorial readable, and to avoid having to implement low level functionality, I’m using the dojo toolkit, I tried prototype too and really enjoyed working with being a really nice and easy to use Library, but dojo provides much more functionality bundled with it. For both frameworks one thing is true: documentation is scarse, and I spent alot time debugging and reading posts on the newsgroups.
For debugging I suggest using Firefox Venkman and the really nice Firebug extension, which make AJAX a lot easier to understand, especially FireBug’s "Log each Request" Feature.
In this tutorial we will try to design a community portal as it has a wide range of different components that give a good overview of what is archievable with AJAX, also it should provide you with the basic tools that will help you in more complex applications.
What we want
As developers we need to know where we want to go, before starting right away. The requirements analysis is not part of this tutorial so I’ll just write down the basic functionality for our Portal:- Pages: Load and show simple HTML Formatted content.
- User: we want to be a community so the possibility for users to register themselfs, create a Profile and communicate with others is fundamental.
- Messages: some sort of messaging center is nice too, and not too difficult to implement, it allows private communication between the users.
- Forum: talking about communications, what could be better than a Forum to let the Users talk about whatever they want?
The Layout
Although the focus should be on the development of the functionality, the layout is still as important as the application itself. It gets even more important because the application can be good but without an interface that is functional it is useless. We’ll use a layout that is easy yet functional:- The content area.
- A sidebar for context related options.
- The main menu (basically this just selects between modules).
- The title, nothing fancy here
- A list with the online users.
Modules
Basically with AJAx we step away from the classic one page-at-a-time view of doing things, and we have to start talking about a more Event Driven architecture, or MVC-Model if you prefer.We’ll define an API that abstracts from the actual page so that we can then create modules that do more complex tasks.
To get back to this tutorial we will have several small modules that represent parts on the site, along with real modules we will have some virtual modules that take care of some functionality, but more on this later. Modules in this tutorial include:
- Page: this will be the first module we will be implementing, it allows to simply display the contents of a file in the contents area of the site, it does nothing fancy.
- User: this module is used for several different tasks:
- Register: register a new User
- Login
- Profile: show the profile of a User
- Online: once we have users we can easily implement a component that allows us to show which users are online, and with AJAX this is possible almost in realtime. It is a nice effect and very easy to implement.
- Forum: what would a community site be without a Forum?
The implementation
We will encapsulate all of our functionality in JavaScript variables, this is similar to static classes in Java and makes it possible to have some sort of clean namespace division between the modules. First of all we will have to create the engine. The engine is the part that handles loading of all the other modules and gives them abstract ways to interact with the page. The idea behind this is that the page interface (layout, stylesheet, …) and Engine build an abstraction layer so that it is easier to implement the functionality easier, without having to bother about representational issues. In other words we build an API.The first and morst important thing the engine has to do is initialize everything.
var Engine = {
bootstrap: function(){
this.setStatus("Loading...");
dojo.require("dojo.io.*");
dojo.hostenv.writeIncludes();
if((""+document.location).indexOf('#') < 0){
Engine.loadPage("#Page/Welcome");
}else{
Engine.loadPage("" + document.location);
}
},
This part is easy to understand it does nothing else than set the status to "Loading…", then include some dojo packages and then display a page using Engine.loadPage() as is shown later on. As you can see everything is bundled into a variable named "Engine" thus making it easy to reference it from outside. The bootstrap function is called by the following code in the page:<body onload="Engine.bootstrap()"></body>
The next thing to do is to give the Engine the ability to load modules, this is done by downloading a JavaScript file that contains the Module (again encapsulated in its own namespace) and then calling init() of the Module which will initialize the module: loadedModules: new Array(),
modules: new Array(),
loadModule: function(module){
if(Engine.loadedModules[module])
return;
dojo.io.bind({
url: "javascript/" + module + ".js",
sync: true,
error: function(type, evaldObj){Engine.showError("Error while loading module.");},
load: function(type, data, evt){
eval(data);
Engine.modules[module].execute(uri);
}
});
},
For performance issues we don’t want to download the modules more than once, that’s why we use the two arrays in the first two lines: loadedModules[] is an array of booleans which to every modulename tells us if it was loaded or is yet to be loaded, the second array contains references to the Modules themselfs (being variables they can be referenced like this). loadModules() itself does nothing fancy, it just issues a Synchronous XMLHTTPRequest to download the Module’s source code. It’s synchronous because we don’t want anything to happen at this stage, a call to a function that is not yet loaded for example, this gives us a certain security. Notice that the code is evaluated using eval().Now we move on to the real magic: loadPage(). It will get a URI as input and it will then load the correct module and pass control to the module, which will then take care of the rest:
uri: "/",
loadPage: function(url){
Engine.setStatus("Loading...");
if(!url)
url = "" + document.location;
var hashIndex = url.indexOf('#');
if(hashIndex < 0 || hashIndex <= url.length-2)
return Engine.hideStatus;
uri = url.substring(hashIndex + 1);
var moduleLength;
if(uri.indexOf('/') > 0)
moduleLength = uri.indexOf('/');
else
moduleLength = uri.length;
var module = uri.substring(0,moduleLength);
uri = uri.substring(uri.indexOf('/'));
if(Engine.loadedModules[module] && ! dojo.lang.isUndefined(Engine.modules[module])){
Engine.modules[module].execute(uri);
}else{
Engine.loadModule(module);
}
},
The URI is there so other modules and function get work with it easily without having to parse it over again. As you can see loadPage() mainly interprets the URL. Determining the module to load is fairly easy being the first part of the Query string. Some may ask why we’re using URLs like "http://www.example.com/Page#This/is/a/long/string". This is because we don’t want to break the ability to bookmark the pages. AJAX itself does break the bookmarkability because everythin happens in a single page, whereas without AJAX every URL identified a single resource. We use the part behind the ‘#’ because the browser does not issue another request to the webserver, which would unload the entire AJAX application, yet we assign a resouce to a unique URL. bootstrap() also loads the requested page from the URL using loadPage(). Cutting a long story short: a user can browse through our site then copy&paste the URL somewhere and when he returns to the URL he will see exaclty the page he left.The URL is interpreted in the following way:
- Everything in front of the ‘#’ is discarded as it is only the location of the application.
- The part between the ‘#’ and the first ‘/’ is the module name which will be loaded if it isn’t yet.
- Everything from the ‘/’ to the end of the URL is the argument that is passed to the Module’s execute() function (see the Page module below as an example).
All that is left now to do is implementing some helper functions that will later be used by the modules:
setStatus: function(message){
if($('status') != null){
$('status').parentNode.removeChild($('status'));
}
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
div.style.position = "absolute";
div.style.top = "50%";
div.style.left = "50%";
div.style.width = "200px";
div.style.margin = "-12px 0 0 -100px";
div.style.border = "0px";
div.style.padding = "20px";
div.style.opacity = "0.85";
div.style.backgroundColor = "#353555";
div.style.border = "1px solid #CFCFFF";
div.style.color = "#CFCFFF";
div.style.fontSize = "25px";
div.style.textAlign = "center";
div.id = 'status';
body.appendChild(div);
div.innerHTML = message;
},
hideStatus: function(){
Engine.opacityDown($('status'));
},
opacityDown: function(theElement){
if(theElement == null)
return;
var opacity = parseFloat(theElement.style.opacity);
if (opacity < 0.08){
theElement.parentNode.removeChild(theElement);
}else{
opacity -= 0.07;
theElement.style.opacity = opacity;
setTimeout(function(){Engine.opacityDown(theElement);}, 50);
}
return true;
},
setContent: function(content){
$('content').innerHTML = content;
},
showError: function(message){
Engine.setStatus(message);
setTimeout("Engine.hideStatus()",10000);
}
}
This completes the engine. You can find the full script here.The first module
Now we’ll move on to implement our first real module. It’s task is to load an external resource (an HTML page in this specific case) asynchronously and then display it in the content area.var Page = {
init: function(){
Engine.modules["Page"] = Page;
Engine.loadedModules["Page"] = true;
},
execute: function(uri){
try{
dojo.io.bind({
url: "resources" + uri + ".php",
sync: false,
error: function(type, evaldObj){
Engine.showError("Error while loading Content.");},
load: function(type, data, evt){
Engine.setContent(data);
Engine.hideStatus();
});
}catch(e){
alert(e);
}
}
}
Page.init();
When the module is loaded it will register itself to the Engine (see the init() function) and the Engine will then call execute() which does nothing else than to load the page in the background and then display it in the content area. Easy isn’t it?But you can already see that we can create really complex modules too as will be shown in a later part of this tutorial when we’ll create a Forum as a Module.
The source of the Page module can be found here.
Putting it all together
You can take a look at the running version of this application or download the entire source code and analyse it. I hope this tutorial was usefull and helped you understand how to design your application. See you all in the next part discussing an Online display.- Site design using Prototype
- A Designer’s Guide to Prototyping Ajax
- Build an RSS Feed Reader using Ajax and PHP
- Ajax Activity Indicators - Make Them Global and Unobtrusive
- Ajax, CSS, DOM and JS-related resources
February 6th, 2006 at 12:45:42
February 6th, 2006 at 15:08:27
February 7th, 2006 at 01:03:14
February 7th, 2006 at 04:18:49
February 7th, 2006 at 04:30:24
February 7th, 2006 at 06:19:50
February 7th, 2006 at 08:18:26
February 7th, 2006 at 09:16:50
February 7th, 2006 at 14:14:50
February 7th, 2006 at 16:21:46
February 7th, 2006 at 21:19:00
February 7th, 2006 at 22:17:42
February 8th, 2006 at 13:25:17
February 11th, 2006 at 16:17:55
February 13th, 2006 at 21:53:53
February 16th, 2006 at 16:12:58
March 16th, 2006 at 03:45:46
March 17th, 2006 at 16:44:33
March 18th, 2006 at 13:29:19
Edit this document
If JS is enabled Engine will execute event (pass whatever params you want) and return false. If not we are using the good old application to handle the request with refresh.
Or I’m missing something important here
March 18th, 2006 at 13:31:54
March 18th, 2006 at 13:43:51
You’d have to duplicate the AJAX detection for every URL…
March 18th, 2006 at 17:04:20
Ajax ç½‘æ‘˜åŠæ•™ç¨‹…
March 18th, 2006 at 17:56:23
March 18th, 2006 at 20:51:02
With the method I’m suggesting you can’t replicate the page if your coming with bookmarked link, but it works really well because routing of such request is easier and it works without JS enabled.
March 18th, 2006 at 23:33:19
Thank you for pointing me out this option
March 19th, 2006 at 06:26:26
March 19th, 2006 at 23:37:57
March 20th, 2006 at 19:57:22
March 28th, 2006 at 12:47:14
March 29th, 2006 at 01:43:16
There are quite a few AJAX demos and examples on the web right now. While these are invaluable to learning AJAX, some people need a bit more information than just a raw piece of code. In todays environment there are many ways to learn AJAX including, b…
April 8th, 2006 at 00:24:16
April 8th, 2006 at 23:06:06
In this tutorial we will try to design a community portal as it has a wide range of different components that give a good overview of what is archievable with AJAX, also it should provide you with the basic tools that will help you in more complex appl…
April 11th, 2006 at 13:44:31
April 12th, 2006 at 09:39:51
April 30th, 2006 at 15:49:40
May 16th, 2006 at 06:25:18
May 28th, 2006 at 14:10:40
June 11th, 2006 at 00:37:38
June 11th, 2006 at 00:59:19
June 11th, 2006 at 01:03:46
June 11th, 2006 at 01:07:32
June 11th, 2006 at 01:09:22
å—¨,,,干嘛è¦è¿™æ ·çš„哦,,,æ°”æ»äº†,
June 11th, 2006 at 01:10:06
June 14th, 2006 at 09:06:47
June 22nd, 2006 at 07:11:27
July 4th, 2006 at 16:19:00
July 14th, 2006 at 08:48:16
As I am a newbie, what tools to be used for Ajax development?
July 20th, 2006 at 18:16:07
Buuuut, Whats about URL Parameters for php scripts i.e.?
July 20th, 2006 at 18:17:47
August 23rd, 2006 at 12:08:36
August 30th, 2006 at 19:46:41
August 30th, 2006 at 22:31:44
September 2nd, 2006 at 23:24:38
September 18th, 2006 at 14:05:43
Unfortunately it does not cover the issue, where javascript is not available and thus the developed site will not work!
If you have to use AJAX, ensure that your site will work the same with and without javascript!
And before you ask :D, yes, I am developing a site that does exactly that.
Best wishes,
John, Latvia
September 18th, 2006 at 19:22:35
Downgradability has been a big issue with Ajax applications and I think the nicest solution until now is the behaviour library of Ben Nolan. It helps keeping the Javascript side separated from the actual HTML code and allows you to dynamically change the behaviour (thus the name ^^) of elements.
Give it a try, it will help ^^
September 20th, 2006 at 07:04:52
September 26th, 2006 at 17:31:56
October 2nd, 2006 at 10:32:10
October 2nd, 2006 at 16:52:55
October 7th, 2006 at 08:01:03
October 7th, 2006 at 22:50:37
October 15th, 2006 at 12:08:21
October 17th, 2006 at 01:33:35
October 25th, 2006 at 02:11:37
October 25th, 2006 at 10:59:39
Its a good help…
Will get back with some Ajax related issues
October 26th, 2006 at 20:00:31
November 10th, 2006 at 22:30:26
November 15th, 2006 at 02:48:38
November 15th, 2006 at 02:53:05
Thanks so much, dude.
:o]
November 21st, 2006 at 22:09:54
I want to use AJAX (Asynchronous JAVA script with XML ). How can i Optimize the site SEO.
as Java script and flash is not recommended by search engines. Any suggestion or help is welcomed. With Regards.
November 24th, 2006 at 04:18:11
November 24th, 2006 at 07:22:49
November 25th, 2006 at 11:26:44
November 26th, 2006 at 07:22:15
Thanks
November 26th, 2006 at 12:33:58
November 27th, 2006 at 01:38:32
December 3rd, 2006 at 18:47:40
when is the next part of your tutorial going to be released.
December 6th, 2006 at 11:11:33
December 7th, 2006 at 00:57:25
December 18th, 2006 at 05:01:51
December 29th, 2006 at 04:22:19
February 5th, 2007 at 20:04:21
February 5th, 2007 at 20:58:32
February 11th, 2007 at 14:51:43
February 13th, 2007 at 16:37:14
February 17th, 2007 at 07:02:35
March 13th, 2007 at 01:07:31
March 18th, 2007 at 18:23:23
March 20th, 2007 at 17:18:59
March 24th, 2007 at 03:10:03
April 8th, 2007 at 20:42:51
April 12th, 2007 at 04:55:10
April 18th, 2007 at 14:25:39
May 3rd, 2007 at 06:28:26
May 12th, 2007 at 13:33:26
May 25th, 2007 at 20:21:50
June 8th, 2007 at 09:15:35
August 3rd, 2007 at 08:48:40
is there any possibility to translate this tutorial to Polish?
let me know.
thx in advance!
September 4th, 2007 at 21:36:55
September 14th, 2007 at 22:55:34
October 7th, 2007 at 11:25:21
October 17th, 2007 at 08:16:22
November 5th, 2007 at 09:41:18
November 5th, 2007 at 12:07:37
November 6th, 2007 at 01:54:06
Thanks for your respond, I am very new at this and at programming and I would really appreciate it if you can take the example below and show me how will it work with your script.
Search Word
Photo
Regards,
Eri
November 6th, 2007 at 01:58:40
name=”basicsearch”
method=”GET”
action=”search.php”
onSubmit=”return validatebasicsearch();”
there is also a text field/input box and a button with
type=”button”
value=”go”
class=”button”
onClick=”submitbasicsearch();”
title=”go”
November 29th, 2007 at 00:12:11
Good design, who make it?
November 29th, 2007 at 13:29:49
February 20th, 2008 at 07:00:02
But, In contrast to Ajax features, the incompatible browsers affecting high performance applications. I am facing lot of problems during the implemention of complex Ajax Components. I am expecting one highly ajax compatible and standard browser, lets hope.
Thanks!
Veeresh
http://drveresh.googlepages.com/veeresh
March 11th, 2008 at 19:40:50
Tatyana’s last blog post..????????? ??????
March 18th, 2008 at 12:32:44
I think this try.