Professional Documents
Culture Documents
Asynchronous JavaScript* and XML (AJAX) feels like another great step toward the promised land of
user interfaces for Web developers who didn’t learn to program on character-based displays. Its ease of
use flows like Mountain Dew down a parched throat, and productivity abounds like a Super Size fry
spilling over on your tray at McDonald’s. I don’t want to take away from AJAX’s time in the spotlight,
but it’s disheartening to see something that declares a better user experience without recognizing that’s
been around for decades with character-based systems like RPG. Sure, we don’t have graphics or
“Punch the monkey and win $100” banner ads on our green-screen apps, but darn it, we get’r done
when it comes to business applications. With that said, I’m a proponent for GUI; I just wish IBM would
come out with one that didn’t have Java* intermingled.
The reason I say AJAX is repeating what we’ve had with RPG on the IBM* System i* platform for
years is because the Web has been steadily replacing traditional business green screens over the past 10
years and has had inevitable growth pains trying to offer a useful, productive user experience.
Eventually, we’ll get to a place where the browser works exactly like a green screen (only prettier).
Apart from the full circle and the hype surrounding AJAX, its possibilities really are quite intriguing.
Seeing full-fledged products like Google Docs (http://docs.google.com) showing off AJAX’s muscle
signals that it’s only a matter of time before more Web-site authors embrace the technology.
In this article, I intend to keep RPG programmers in the loop and away from the french-fry machines at
their local burger joints by providing a useful example of how to employ AJAX when building a simple
Web form. This will be in conjunction with a straightforward RPG CGI program doing validation
against a DB2* database. But first things first: What is AJAX?
What is AJAX?
AJAX is a collection of technologies—JavaScript, cascading style sheets (CSS) and the HTML
document object model (DOM)—used to make program calls from the browser to a server-side
resource (e.g., an RPG CGI program) and use the server’s response to modify the contents of what the
user sees on the Web page. What makes this special is when it’s used to do incremental changes to the
Web page versus doing a full refresh, which requires the browser to re-render information that hasn’t
changed. When the browser only has to update portions of the page it’s obviously processing less and,
by getting rid of that split second where the browser goes white, improving the user experience with
less waiting and more productivity. Let’s examine an example to relate AJAX to a day in the life of an
RPG green-screen programmer.
In green-screen programming, it’s necessary to validate user input to ensure, for example, that valid
item numbers are being placed in the order-entry physical files. If a CHAIN produces a “not found”
when a user enters item number “XYZ,” that must be relayed back to the user. The process of telling
the user an error occurred usually means an attribute of a field is going to have an indicator turned *ON
to change the color of that field or highlight it to make it jump off the page. That’s exactly what we’ll
accomplish in the following AJAX example, except we’ll operate in a browser instead of a terminal
emulator, and instead of DDS field definitions and indicators we’ll have HTML <input/> fields. HTML
has no indicators or DDS field keywords. Instead we’ll use CSS to alter a field’s appearance when an
invalid entry is made.
Code Sample 1 is the HTML form into which the user will enter an item number. It’ll look like Figure 1
when displayed in the browser. Viewing the HTML behind this page reveals a form named “form1”
with two fields—“fld_itm” and “fld_anotherfield.” The objective is to change the border of “fld_itm”
to red when an invalid item number is entered (see Figure 2). To do that, a call will be made to a
System i RPG program to see whether the item entered is valid. The “onblur” attribute indicated that
the call to the System i platform will be made when the user exits the field. When the user exits
“fld_itm” the “vldItm” JavaScript function will be called. This is really no different from calling an
RPG program from the command line and passing in literal parameters to it. The value that’s in single
quotes is what’s being passed to function “vldItm.” In this case it’s the same value in the ID attribute of
this input tag. More about that parm being passed later. The “fld_anotherfield” field simply exists so we
have someplace to tab to.
The final thing to note is the class attributes value, which is set to “input.” This is telling the field that it
should look for a CSS named “input” and apply it to itself. If the field’s in error, we’ll use JavaScript to
dynamically change the class-attributes value from “input” to “input_error.”
Code Sample 2 shows the CSS definition used in this example. I won’t go into syntax but will point out
that the third parameter for the “border:” definition is different for “input” versus “input_error.” The
value #999999 is the hex value for a grayish color, and #FF0033 is red. These are the two different
style sheets that’ll be used to alter the appearance of field “fld_itm.”
Testing the VLDITM RPG program can be done easily from the browser by composing a
URL emulating exactly what the JavaScript is concatenating.
Useful References
XMLHttpRequest Valid Responses
0 = Uninitialized
1 = Loading
2 = Loaded
3 = Interactive
4 = Complete
To see this application in action on a live System i platform, visit: http://red.rpg-xml.com/ajax.html.
For a deeper understanding of these concepts and tools, here are some useful links:
• http://en.wikipedia.org/wiki/ajax
• http://en.wikipedia.org/wiki/document_object_model
• http://en.wikipedia.org/wiki/cascading_style_sheets
• http://en.wikipedia.org/wiki/web_colors
• http://en.wikipedia.org/wiki/javascript
Binding directory CGI has the following entry in it:
H bnddir('*LIBL/CGI') dftactgrp(*no)
D getUrlVar pr 32767A varying
D pCmdStr 300A value
D toBrowser pr extproc('QtmhWrStout')
D Data like(outXml)
D Length 10I 0 const
D Error like(gError)
D qzhbcgiparse pr extproc('QzhbCgiParse')
D cmdStr 300A
D outputFmt 8A
D tgtBuffer 32767A options(*varsize)
D tgtBufferLen 9B 0
D respLen 9B 0
D apiError LikeDS(gError)
D gError ds qualified
D bytesP 10I 0 INZ(56)
D bytesA 10I 0
D msgID 7
D reserverd 1
D data 40
D outXml s 256a
D itm s 20a
D fldName s 20a
/free
itm = getUrlVar('-value itm');
fldName = getUrlVar('-value fldName');
if itm = 'HAT';
outXml = %trim(fldName) + '|FOUND';
else;
outXml = %trim(fldName) + '|NOT_FOUND';
endif;
D EOL C X'25'
D output S 32767A
D tgtBuf S 32767A
D outputFmt S 8A INZ('CGII0200')
D respLen S 9B 0
D tgtBufLen S 9B 0 INZ(%Size(TgtBuf))
D position S 5I 0
D error DS LikeDS(gError)
/Free
return output;
/end-free
CODE SAMPLE 1
<form name="form1">
Enter item:
<input class="input" type="text" id="fld_itm" onblur="vldItm('fld_itm');" />
<br/>
<br/>
Another Field:
<input class="input" type="text" name="fld_anotherfield"/>
</form>
CODE SAMPLE 2
<style>
.input {
border: 2px solid #999999;
}
.input_error {
border: 2px solid #FF0033;
}
</style>
CODE SAMPLE 3
var http = crtReqObj();
function crtReqObj() {
var reqObj;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
reqObj = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
reqObj = new ActiveXObject("Microsoft.XMLHTTP");
}
return reqObj;
}
CODE SAMPLE 4
function vldItm(fldName) {
var fld = document.getElementById(fldName);
http.open('post',
'http://172.29.134.41/cgi-bin/vlditm?itm=' +
fld.value + "&fldName=" + fldName);
http.onreadystatechange = vldItmResponse;
http.send(null);
}
CODE SAMPLE 5
D outXml s 256a
D itm s 20a
D fldName s 20a
/free
*inlr = *on;
/end-free
CODE SAMPLE 6
function vldItmResponse() {
if(http.readyState == 4 && http.status == 200){
var response = http.responseText;
var cmp = new Array();
cmp = response.split('|');
CODE SAMPLE 7
Binding directory CGI has the following entry in it:
H bnddir('*LIBL/CGI') dftactgrp(*no)
D toBrowser pr extproc('QtmhWrStout')
D Data like(outXml)
D Length 10I 0 const
D Error like(gError)
D qzhbcgiparse pr extproc('QzhbCgiParse')
D cmdStr 300A
D outputFmt 8A
D tgtBufferLen 9B 0
D respLen 9B 0
D apiError LikeDS(gError)
D gError ds qualified
D bytesA 10I 0
D msgID 7
D reserverd 1
D data 40
D outXml s 256a
D itm s 20a
D fldName s 20a
/free
if itm = 'HAT';
else;
outXml = %trim(fldName) + '|NOT_FOUND';
endif;
*inlr = *on;
/end-free
//-----------------------------------------------------------------------
// @Modified:
//-----------------------------------------------------------------------
P getUrlVar B Export
D EOL C X'25'
D output S 32767A
D tgtBuf S 32767A
D outputFmt S 8A INZ('CGII0200')
D respLen S 9B 0
D tgtBufLen S 9B 0 INZ(%Size(TgtBuf))
D position S 5I 0
D error DS LikeDS(gError)
/Free
tgtBuf = '';
position += 1;
else;
position = 0;
endif;
respLen = respLen - 1;
endif;
endif;
if respLen > 0;
else;
output = '';
endif;
return output;
/end-free
P E