Yesterday we had a workshop titled: Ajax, What’s the buzz? During this workshop, we discussed AJAX – Asynchronous JavaScript and XML, notable examples of Ajax implementations, the repercussions Ajax can have for the application we develop, challenges we will face when adopting Ajax and of course ways to implement Ajax. During the hands-on session, we implemented the Ajax equivalent of HelloWorld, implemented cross-domain Ajax-requests and used the RICO framework for creating an Accordion effect (Outlook style). We also implemented client-side server based validation and a tooltip/suggestion like feature.
The driving forces behind Ajax and most of the appications, next to the obvious JavaScript and the XmlHttpRequest object, are the (DHTML) ability to directly write to the DOM. For some of us, this was a first introduction to the node manipulation features in DHTML as well as the innerHtml property that we can so easily use with container elements like DIV and TD.
You can find the presentation for this workshop here: AjaxWhatsTheBuzz_30maart2006.ppt Note that the slides contain some Dutch words. Also note that the slides have hyperlinks, some of them to websites on the internet – those will function – some of them to demos that you will not have. Those same demonstrations can be found later in this article. Also see Installment 2 – more in depth examples and discussions.
Introduction to AJAX
Of course thousands of articles have been written about AJAX ever since the term was coined in February 2005, inspired by what Google Labs had published with the Google Suggest feature. Long before the term AJAX was thought up, applications were using AJAX mechanisms. At AMIS – quite a while before my time – people like Erwin, Ate, Ton, Hans and Leon had implemented AJAX like features in the JAA and CBE applications (early 2000s). In 1998/1999 I had implemented (I)FRAME based AJAX in the Oracle Designer Web Assistant. However, AJAX really has taken off early 2005.
In the presentation, we discussed a number of well known examples of AJAX:
(note: you clicik on these images to go to the examples themselves)
Each of these examples make use of the Ajax design pattern: asynchronous communication (behind the scenes, without apparent interruption of the application for the user) followed by dynamic updates of the document in the browser (DOM manpipulation aka DHTML).
AJAX can be seen as the standards based way of creating RIAs (Rich Internet Applications), as opposed to proprietary technology or very poorly supported standards-to-be such as Flash (Flex, OpenLaszlo), XUL, XAML and HTC, XAMJ, XForms and even Java Applets. AJAX is supported in standard browsers (IE 5.0+, Mozilla 1.0+, Safari 1.2+- available since 1999, 2002 and 2004) using standard technologies like HTML, JavaScript, DOM manipulation through JavaScript and CSS. FRAME based Ajax has been available in far older browsers at least since 1997.
AJAX: without, old style and modern
Let’s take a brief look at a situation where Ajax may improve a Web Application. We have a web page where an Employee can be selected. Let’s assume that we have a collection of thousands of Employees, distributed over dozens of departments. In our interface, we can select a Department from a Select List as well as an Employee from another List. (in the demo that follows, we have only 25 employees but general idea is the same of course).
There are several ways of implementing this situation. These incluse:
1. Load all employees when the page is loaded and include all of them in the Employee Select List. Go to LoadAllIntoSelect to inspect this approach. It should be clear that this approach, while simple to implement, has two major drawbacks: loading the page can take quite long as all employees are loaded; only after all have been loaded will the hourglass disappear and will the user have control over the application. Furthermore, the user must try to find the employee he wants to select in a list that contains all of them. First selecting a Department has no (filtering) effect on the list of employees
2. Load all employees when the page is loaded into a JavaScript array and populate the Employee List in client side JavaScript code every time the Department selection changes. See LoadAllAndFilterClientSide to see this implementation. This implementation still suffers from a long load time – the user has to wait for all employees to be downloaded to the browser. However, this time the list of employees is filtered by the selected Department. This means that we now have a much shorter list to pick the employee from.
We have implemented this with an array of Employee objects that are populated during the loading of the page:
var empstore = new Array(); function Employee(deptno, empno, ename){ this.deptno=deptno; this.empno=empno; this.ename=ename; } empstore.push( new Employee('10', '1','Tom Bomer')); empstore.push( new Employee('10', '2','Ramses Shaffy')); ...
The DepartmentList has an onChange event defined: onChange=”populateEmpForDept(this.value);” . The function that is invoked here looks like this:
function populateEmpForDept(deptno) { var empList = document.deptempform.emp; empList.options.length = 0; for(i=0;i<empstore.length;i++) { if (empstore[i].deptno == deptno) { empList.options[empList.options.length] = new Option(empstore[i].ename, empstore[i].empno); }//if }//for empList.disabled=false; }//populateEmpForDept
3. Refresh page when the Department selection changes and rebuild with the proper list of Employees. This solution is seen here: ChooseDeptThenSubmit. This implementation offers two improvements over the first listed here: the page can load fast a
s no employees are initially loaded at all and the u
ser will be able to select employees from a short list, with only the employees in the selected department. However, now we will have a full page refresh every time the department selection changes. The form is submitted from the onchange event: onChange=”document.location.href=’ChooseEmpDept’+document.deptempform.dept.value+’.html’;”. It is then up to the webserver to dynamically recreate the page with only the employees for the selected department. Note that we have simulated this with five different static html documents with each a subset of the employees. While this seems a good approach, there is still the annoying full page refresh whenever the department selection changes.
4. AJAX old style – using IFRAMES. Here we discuss an approach that is programmatic, asynchronous and basically almost everything that the hyped-up AJAX is. And it has been around since 1998 at least. It uses a (hidden) (I)FRAME to asynchronously communicatie with the server. The results of this background communication can be used to update the main document. And example of this AJAX-old-style can be seen ‘live’ here: ChooseDeptRefreshEmpIframeBasedAjax.
When the Department is selected, the onChange event fires. At that point, a hidden IFRAME is refreshed and a static document is loaded. For each department, a different document is loaded into the IFRAME. When the IFRAME has completed loading the document, a JavaScript function in the parent window – the main document – is invoked and the employee data is handed over:
The IFRAME is refreshed whenever the Department selection changes:
<select size="5" name="dept" onChange="retrieveEmps(this.value);">
function retrieveEmps(deptno) {
top.frames[‘getemps’].location.href = ‘dept’+deptno+’.html’;
}
The department specific documents that are loaded in the IFRAME each look like:
var empstore = new Array(); function Employee(deptno, empno, ename){ this.deptno=deptno; this.empno=empno; this.ename=ename; } empstore.push( new Employee('10', '1','Tom Bomer')); empstore.push( new Employee('10', '2','Ramses Shaffy')); empstore.push( new Employee('10', '3','George W. Bush')); empstore.push( new Employee('10', '4','Muahmmed Ali')); empstore.push( new Employee('10', '5','Anna Vink')); empstore.push( new Employee('10', '6','Pepper Kreunen')); function callParent() { window.parent.populateEmpList( empstore); } //callParent </script> </head> <body onload="callParent()"> </body> </html>
In this example, they are static. Typically of course they would be dynamically generated by a JSP, ASP.NET, Perl, PHP etc. program.
The populateEmpList function that is called from the IFRAME is the same as before:
function populateEmpList( empstore) { var empList = document.deptempform.emp; empList.options.length = 0; for(i=0;i<empstore.length;i++) { empList.options[empList.options.length] = new Option(empstore[i].ename, empstore[i].empno); }//for empList.disabled=false; }//populateEmpList
This IFRAME based implementation of the AJAX design pattern has a number of benefits: Broad browser support, Even in very old browsers; Fewer issues with cross domain resources (the IFRAME can load its resource from any URL, not just resources on the same domain the main document was loaded from); Support for file upload (when the IFRAME is submitted, it can upload a file, something modern AJAX does not support). IFRAME based AJAX is used in Oracle UIX and ADF Faces, exactly because of these benefits.
However, there are some drawbacks: The document to be loaded in the IFRAME needs to be aware of the context – Loaded page must invoke a JavaScript function in the parent. Only the IFRAME’s onLoad can tell when the document is loaded. Furthermore, browser security restrictions raise some barriers over accessing contents in the IFRAME from the parent document. This means we cannot load ‘dumb’ content like plain text files, XML documents etc. in the IFRAME, whatever we load has to be our own stuff that knows how to tell the parent window it is loaded. For our very own applications that may not be such an issue – even though it means every resource loaded AJAX style needs to have a piece of JavaScript – but it certainly limits our ability to access non-application resources. Smaller disadvantages are that IFRAME based Ajax is not what the Ajax hype is all about. Books, tools, frameworks and code libraries do not address nor support this type of Ajax. And we could argue that it is less elegant than what we dupe ‘real’ AJAX.
5. AJAX new style – using the XmlHttpRequest object At last we have arrived by the hype: AJAX new style, fully programmatic and using the XmlHtppRequest object. For a live demonstration, see ChooseDeptRefreshEmpModernAjax.
Modern AJAX uses the programmatic XmlHttpRequest object to communicate with web servers. In our example, when the Department Selection changes, the onChange event executes:
<select size="5" name="dept" onChange="loadEmployees(this.value);">
The function loadEmployees that is invoked will submit an Ajax request – asynchronously and invisible to the user – that will retrieve an XML document with the Employee-data for the selected department.
var xmlHttpRequest; /** * Load the Employee data in the select object */ function loadEmployees(deptno) { var file = "empsInDept"+ deptno+".xml" // create the object, careful to the MSFT/Other method if (window.XMLHttpRequest) { xmlHttpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } // executing the request, passing the targetted object xmlHttpRequest.onreadystatechange = processRequestChange; xmlHttpRequest.open("GET", file, true); xmlHttpRequest.send(null); }//loadEmployees /** * Handle the events of the XMLHttpRequest Object */ function processRequestChange() { if (xmlHttpRequest.readyState == 4) { if(xmlHttpRequest.status == 200) { copyEmployeeData(); } else { alert("Error loading pagen"+ xmlHttpRequest.status +":"+ xmlHttpRequest.statusText); } } }
Note that in this example we use static XML documents per department; a real application would make use of dynamic server side components that would generate the XML content based on the department selection:
<EMP> <ROW> <EMPNO>20</EMPNO> <ENAME>Tante Trix</ENAME> <DEPTNO>40</DEPTNO> </ROW> <ROW> <EMPNO>19</EMPNO> <ENAME>Jeffrey Wammes</ENAME> <DEPTNO>40</DEPTNO> </ROW> </EMP>
When the request-cycle is complete and the response has been received, the processRequestChange function calls the copyEmployeeData() function. This function reads the responseXML property
from t
he xmlHttpRequest object. This property contains the XML document that was received as response to the AJAX request. The XML Document is examined – the collection of all ROW nodes is retrieved. Each ROW represents an Employee. Next we create entries in the Employees Select list for each Employee in the XML Document:
/** * Populate the list with the data from the request * (Could be done in a generic manner depending of the XML...) */ function copyEmployeeData() { var list = document.deptempform.emp; list.disabled = false; var items = xmlHttpRequest.responseXML.getElementsByTagName("ROW"); clearList(list); if (items.length > 0) { for (var i=0; i<items.length; i++) { var node = items[i]; var empno = node.getElementsByTagName("EMPNO")[0].firstChild.nodeValue; var ename = node.getElementsByTagName("ENAME")[0].firstChild.nodeValue; addElementToList(list, empno, ename ); }// for }// if else { list.disabled='true'; alert("No Employee for this department"); } }// copyEmployeeData /** * remove the content of te list */ function clearList(list) { while (list.length > 0) { list.remove(0); } } /** * Add a new element to a selection list */ function addElementToList(list, value, label) { var option = document.createElement("option"); option.value = value; var labelNode = document.createTextNode(label); option.appendChild(labelNode ); list.appendChild(option); }
This example is but brief introduction to AJAX Modern Style. In a subsequent article, we will discuss the more advanced labs we worked on in this workshop. These include parallel Ajax requests, cross domain Ajax requests, repetitive (polling) requests and different ways of processing the AJAX request response.
The benefits of using AJAX for this problem is mainly that there is no full page refresh. Option 3 eliminates the need for long load times, as it only loads the employees you actually need. Of course this depends somewhat on the page that contains the list of Employees – if other parts of that page take long to load, we now take that hit twice.
Full page refresh is often regarded as annoying, especially if it takes a noticeable period of time. Otherwise it is only the flickering and the annoyance factor of that is very personal.
For this example, I can certainly see how option 3 can be quite sufficient, especially as it is a simpler implementation than an AJAX based one.
Lukas,
you provided interesting comparison of available options to develop the solution.
Could you be a little more specific about your statement “While this seems a good approach, there is still the annoying full page refresh ” for option #3. What are the drawbacks of this approach (speed of execution, visual effects like flickering, etc.) ?
It is not clear what benefits we can gain by using AJAX for this problem.
Thanks.
See the article
AJAX – What’s The Buzz – part two (slightly more in depth, on challenges and solutions) for more on AJAX including a step by step introduction of the key programming approaches and a discussion of the main challenges. Well, at least some of them.
Hi Lucas, for working out the details you can always contact me. Details at http://www.WaldoSmeets.com
You are correct that Flex requires the Flash Player to run properly, that’s an additional requirement but on the other hand is already installed by almost anyone on the web; I think we reach an equal amount of end-users as the current AJAX frameworks allow you to reach out to (Flash Player 7 is at 95% penetration). Obviously, you get something additional for using the plugin so it might (or night) be worth it for your team. Especially for applications that are working with complex data structures I think we have an interesting offer.
Anyway, thanks for clearing up the scope. Looking forward to hear from you.
Regards,
Waldo
Waldo,
Thanks for your comment and especially for your offer of hosting a similar session. We are most definitely interested, so let’s see how we can work out the details.
In the presentation, we discussed the concept of RIAs. How dynamic, interactive interfaces, no disruption of services caused by synchronous request cycles and visual attractiveness (not directly related to AJAX of course) are all part of the RIAs. AJAX was positioned a way to achieve RIA-like features using standard technologies, both client side and server side – such as bare browsers (no plugins), HTML and JavaScript on the Client side and basically any type of Server Side technology such as .NET, PHP, CGI and the one of most interest to us: Java/J2EE. We can make use of AJAX without having to acquire any new components in our application development tool-stack.
The other RIA technologies that were listed, of which Flex is one, all require – at least that was my assumption – some sort of special Client and/or Server side provision, compared to our current stack.
Please correct me on that account if I am wrong!
best regards,
Lucas
Nice preso. I see that you guys also listed ‘alternatives’ to AJAX and that Adobe Flex was on the list. However, it wasn’t clear to me how exactly you positioned Flex compared to AJAX?
I actually don’t see Flex as a one-on-one alternative to AJAX; it can be, but Flex and AJAX can also be very nicely used together and integrated with each other through some of the Flash-AJAX bridges that Adobe has created. With Flex Adobe tries to address the full spectrum of Rich Internet Application development and thus fill in some specific gabs that AJAX doesn’t or can’t address, because of the limitations that browsers tradionally have had. Of course Adobe tries to combine this with AJAX integration, advanced development tools, optimized backend integration for more advanced data messaging and last but not least a fluent designer – developer workflow.
From the presentation I couldn’t analyze how aware you guys are about this or not. I’d love to host a semiliar sesssion for you guys to give you more insight in using AJAX and Flex together and create more awereness of what value Flex can add for Rich Internet Application development.
Regards,
Waldo Smeets
Adobe Systems
http://www.WaldoSmeets.com