In my previous article, I explained how AJAX is transforming Web applications by providing a much richer and more responsive user experience. We looked at how Google and other major players are effectively using AJAX to provide functionality and ease-of-use not previously found in Web applications.
In this article, I'll help you tap into the power of AJAX by providing you with the code necessary to create the essential communications link between client (browser) and server (iSeries, etc.) that is the heart of any AJAX application.
Implement AJAX Today!
Once you have written the initial code to use an AJAX object, AJAX is very simple to implement. As I stated in the last article, since it requires only changes to the way you write client-side code, you can easily include AJAX in iSeries-based Web applications (CGIs or Java-based). In addition, all the browser infrastructure needed to implement AJAX is already available in just about every modern browser. Here's what I'll do in this article in order to help you implement AJAX right away:
- Explain the core AJAX object
- Walk through code for using it
- Show you how to wrap that code in a self-contained "black box"
- Show sample uses of that black box
These steps assume some degree of familiarity with writing server-side code for Web applications using any Web server language, such as CGIDEV2 (RPG CGI), PHP, ASP, JSP, or Java servlets. My server-side code is written using WebSmart, which runs on the AS/400 or iSeries as RPG CGI code. By way of acknowledgment, some of the code in this article is derived from code at Apple's Developer's site. I've improved on it by making it more generic so that it's easy to use in several different ways on any given page.
The Core AJAX Object
The core AJAX object is a JavaScript object called XMLHttpRequest. So, in order to implement AJAX, you'll need some JavaScript. Don't worry if you don't know how to code JavaScript; the basic syntax is fairly straightforward. (For more information about what JavaScript is, see the sidebar at the end of this article.) And I've provided links to a downloadable zip file that contains complete code you can plug in to your applications, along with a sample implementation Web page.
Figure 1 shows an example conversation using an AJAX object embedded in a Web page to provide the kind of auto-complete feature used by Google's Gmail. Usually, browser content is sent from the server to the client in entire pages. In the AJAX model, it's sent as content fragments that you can use to update portions of a page without reloading the entire thing.
Figure 1: Here's an example of a conversation.
Internet Explorer (IE) browsers implement the XMLHttpRequest object differently than Mozilla-based browsers (such as Firefox). IE implements it as a native ActiveX (one that is automatically included in the browser code base), while Firefox implements it as a JavaScript native object. The differences are purely cosmetic, but any robust script that uses AJAX needs to take the different browser implementations into account. Fortunately, this is fairly easy. You can check for the existence of the object by using a browser-feature detection technique. Note that this technique is now much preferred over examining a variable that describes the browser, as it is much more reliable and not subject to changes in browser names or release levels. Here's the initial JavaScript code:
var _ms_AJAX_Request_ActiveX = ""; // global variable: holds type of ActiveX to
instantiate
// code for Mozilla, etc.
if (window.XMLHttpRequest) {
var xmlhttp=new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject) {
// Instantiate the latest MS ActiveX Objects
if (_ms_AJAX_Request_ActiveX) {
xmlhttp = new ActiveXObject(_ms_AJAX_Request_ActiveX);
}
else {
// loops through the various versions of XMLHTTP to ensure we're using
the latest
var versions = ["Msxml2.XMLHTTP.7.0", "Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
for (var i = 0; i < versions.length ; i++) {
try {
// Try to create the object. If it doesn't work, we'll try again
// if it does work, we'll save a reference to the proper one to speed
up future instantiations
xmlhttp = new ActiveXObject(versions[i]);
if (xmlhttp) {
_ms_AJAX_Request_ActiveX = versions[i];
break;
}
}
catch (objException) {
// trap - try next one
}
}
}
}
Explanation of Code
We will eventually embed this script in a function that is easily called. Here's what it does: First, it checks for support for the XMLHttpRequest native object. If this succeeds (returns true), then the browser is Mozilla-based, and we create a new instance of the object, named xmlhttp. If that check fails, it checks for an IE ActiveX version. (Microsoft has deployed different versions over time, which is why the code loops through an array to find the correct one.) Once the correct version is found, we instantiate a new object instance with the same name, xmlhttp.
So in either case, Mozilla or IE, we create an object called xmlhttp. This object is the core AJAX component. It has several properties and methods, all well-documented at the aforementioned Apple Web page and at Microsoft's developer site. Fortunately, most of the important methods and properties are shared by both the Mozilla and IE implementations, so we don't have to worry about writing a lot of branched code to handle different browsers.
Walkthrough of Code Fragments for Using the AJAX Object
OK, now we have an instance of our core AJAX object, xmlhttp. The next piece of code is a complete function that includes the above fragment and makes an AJAX call to the server:
1 function AJAX_Update(url, obj, func)
{
2 if (!url) return false; // Don't run if missing the url parm.
// ... earlier code to instantiate xmlhttp goes here
if (!xmlhttp) return false;
3 if (func)
xmlhttp.onreadystatechange = function(){
4 if (xmlhttp.readyState != 4) return;
5 if (xmlhttp.status == 200)
func(obj, xmlhttp.responseText);
else
alert("An error occurred" + http.status);
};
else
6 xmlhttp.onreadystatechange = function() { return; }
7 xmlhttp.open('GET', url, true);
xmlhttp.send(null);
return false;
}
Explanation of Code
Point 1
The entire AJAX interface is encapsulated in a function called AJAX_Update, which uses three mandatory parameters:
● url—The string that contains the URL of the server-side program to call. For example, custsearch.pgm?task=search&searchval=FRED
● obj—The object reference to an HTML element on the page. This is the section of the page that will be updated by the AJAX request. For example, if we have an HTML element with an ID of "ajaxresponse" (like this
● func—The name of a JavaScript function in our page that will update the page contents with the AJAX response. For example, AJAX_Update(myurl, mydiv, Receive_AJAX_Response); would call this function:
{
document.getElementById(mydiv).innerHTML = response;
}
This last parameter might be a little strange to RPG programmers. JavaScript allows us to reference a function through the contents of a variable, rather than as a hard-coded value. This means we can invoke our function (AJAX_Update) any number of times in the page and have it call different functions to update page content. This is like using procedure pointers in RPG. We'll see how this is used in the description of point 5 in the code.
Point 2
Since the URL parameter is mandatory, its absence will cause the function to exit gracefully. After point 2, we insert our code to instantiate the AJAX (xmlhttp) object described earlier.
Point 3
The third parameter is the function that handles the response. If present, we assign an "anonymous" function (an ad hoc one, with no name) to an event handler for the AJAX object for when the "ready" state of the object changes. The ready state will change as a result of a server call , which actually takes place in point 7.
Point 4
This point assigns an event handler to the AJAX object's ready state. The event indicating that the state is changed is fired when the code has done a server call and gotten a response from the server (initiated in step 7). If the new state is not 4, we exit (4 is a valid ready state; any other is not).
Point 5
If the returned status from the server is 200, then we have a valid response from the server and we can continue. If not, we send an alert box notifying the user that an error occurred. In production code, we might want to handle this more gracefully. Possible return codes are ones such as the infamous "404 — page not found." This could happen if the URL you attempt to reference is incorrect, for example. These are standard responses according to the HTTP protocol. The key line of code at this point is func(obj, xmlhttp.responseText);
This invokes the function we passed as the third parameter in point 1 in this case: Receive_AJAX_Response. Note that it requires two parameters: the AJAX response data and the ID of some HTML element on the page that is to be updated. In our example, the code looks like this:
{
document.getElementById(mydiv).innerHTML = response;
}
This function takes the contents of the variable response (the server's response from the AJAX call) and updates the inner contents of the HTML element identified by variable mydiv. So, if mydiv = ajaxresponse, then this div's inner HTML contents will get replaced with whatever HTML or text was returned by the server:
Point 6
This is the graceful exit if no parameter for the receiving function was passed.
Point 7
The "open" method of the AJAX object prepares for the actual call to the server, while the "send" method actually does it. You can think of this as being the invisible squirrel in your browser who is clicking on a hidden link or form button behind the scenes.
The first parameter of the open method determines whether to use 'GET' or 'PUT' to make the request. This equates to the ACTION keyword on the HTML
LATEST COMMENTS
MC Press Online