Roll up your sleeves and start coding!
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
Response from AJAX call goes in here ),
then the value of obj would be "ajaxresponse". ● 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:
function Receive_AJAX_Response(mydiv, response ) { 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:
function Receive_AJAX_Response(mydiv, response ) { 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:
Response from AJAX call goes in here
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
|