The obligatory “My Ajax Tutorial” Post
Posted on January 8, 2006
4 Comments
[Major help from "dutch" at work and all the other's who have "gone before" me...]
I posted about my battle with trying out "Ajax" last week. I learned some stuff. While there are tons of Ajax Primers out there, I figured I could have one too, since I didn't find one that would teach me quite what I wanted to do (granted, I'm *not* a Javascript expert).
Some context here. I consider myself a pretty decent coder. In one language or another I have over 20 years under my belt. (not that you'll guess that from the below samples!). But javascript is not a forte of mine, by any stretch of the mind. And this XMLHTTPRequest stuff is very new to me. But I like it!
Here's some silly/simple stuff that I cobbled together while I was doing some of my troubleshooting.
First off, I needed a simple little "client" page. All this page had was the bare minimum html and a form with one checkbox. I called this page xmlhttp_client.asp. Here's the form, with one wrinkle:
-
<form action="post" name="test">
-
<input type="checkbox" name="chkTest" onclick="submitTest(event);" />
-
<%
-
httpSetting = request.ServerVariables("HTTPS")
-
if httpSetting = "on" then
-
httpPrefix = "https://"
-
else
-
httpPrefix = "http://"
-
end if
-
fullPathInfo = httpPrefix & request.ServerVariables("Server_Name") & Request.ServerVariables("Path_Info")
-
pathInfo = mid(fullPathInfo, 1, (InStrRev(fullPathInfo, "/")))
-
%>
-
<input type="hidden" name="root" value="<%=pathInfo%>" />
-
</form>
See the wrinkle? Yeah, that big chunk of vbscript embedded in there. Gotta make sure the url's match coming and going from the server so I just build it up, stuff it in a form field and grab it from the javascript routines before I make my call (you'll see that next). If your goal isn't to be able to run your stuff on any old server without touching code, you can leave all that ASP/vbscript gunk out, of course.
Note this line, it is where all the magic really starts:
-
<input type="checkbox" name="chkTest" onclick="submitTest(event);">
Click the box, fire SubmitTest(). What does SubmitTest() look like? Funny you should ask.
-
function submitTest(evt){
-
var buff
-
// process event here, handles both IE and Mozilla event models
-
evt = (evt) ? evt : ((window.event) ? window.event : "")
-
if (evt) {
-
elem = (evt.target) ? evt.target : evt.srcElement;
-
URLString = document.test.root.value + "xmlhttp.asp";
-
//alert(URLString);
-
-
http.open("POST", URLString, true);
-
http.onreadystatechange = processReqChange;
-
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-
http.send("action=submitTest");
-
}
-
}
Remember that goofy ASP logic in the HTML? You can see it actually means something now -- here's where it gets used:
-
URLString = document.test.root.value + "xmlhttp.asp";
xmlhttp.asp is, of course, the name of the file that contains all the server processing logic. Now, I'm insulated against moving my code from one server to another. Presumably, I won't be renaming xmlhttp.asp, of course.
Thing is, that function isn't quite as clear as it could be. You see an object named "http" referenced frequently, but I haven't showed where it came from yet! Oops. Well, easily remedied... This next bit just lives in the same block as all the rest:
-
function getHTTPObject()
-
{
-
var xmlhttp;
-
/*@cc_on
-
@if (@_jscript_version>= 5)
-
try {
-
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
-
} catch (e) {
-
try {
-
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
-
} catch (E) {
-
xmlhttp = false;
-
}
-
}
-
@else
-
xmlhttp = false;
-
@end @*/
-
-
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
-
try {
-
xmlhttp = new XMLHttpRequest();
-
xmlhttp.overrideMimeType('text/xml');
-
} catch (e) {
-
xmlhttp = false;
-
}
-
}
-
return xmlhttp;
-
}
-
-
var http = getHTTPObject(); // We create the HTTP Object
That code was cheerfully lifted from about a dozen other tutorial pages. I like it and it seems to work well. It is the epitome of a "cut, paste and don't overthink it" piece of code.
Look back to the SubmitTest() function and the use of that http object:
-
...
-
http.open("POST", URLString, true);
-
http.onreadystatechange = processReqChange;
-
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-
http.send("action=submitTest");
-
...
I'm doing a POST, to URLString (my server stuff in xmlhttp.asp) and, by setting "true" I indicate that it will be an async call. Thus, the next line. It sets my "callback" function -- processReqChange() in this case.
Because I'm doing this as a POST, I need to set the content-type (which was my personal waterloo for a day...). And finally, send it with whatever I care to post. If there are multiple vars to post, just format as if they're in a querystring (this=that&foo=bar&do=doot).
If I was doing this as a sync call, it gets a bit simpler. Just toss all my logic after that send to catch the response. But suppose there's some network issues? Or [insert hand-waving here to explain why I want this to be async besides "because it is neat-o"!]?
Our callback function doesn't do much:
-
function processReqChange()
-
{
-
var response;
-
var result;
-
-
// only if http shows "complete"
-
if (http.readyState==4) {
-
if (http.status==200) {
-
//alert("success");
-
response = http.responseXML.documentElement;
-
result = response.getElementsByTagName('result')[0].firstChild.data;
-
alert(result);
-
}
-
else {
-
alert("Failed: " +http.status);
-
}
-
}
-
}
Very light weight. Originally, it solely existed to pop an alert message so I knew I just got that far. In the real world, I actually fill a <div> tag set with some user feedback so that my user knows something happened. In this case though, I just wanted to throw an alert either with what my server function sent back or what the http error might be. What about this readyState thing? There are 4 values:
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
[source]
In this case (most?) we really aren't all that interested until it is complete... but our callback will get called on each (change it, put in some alerts and watch each one roll by = exercise for the reader).
And there's the client.
----------
What does the server stuff look like? I have that all in a file called xmlhttp.asp (such clever names, I know). For this sample/testing, all I wanted to do was hit a specific row in the database, retrieve the boolean value and flip it. True to False. False to True. Then I could not only check my http response, and the xml I returned, but also independently just query that database.
-
<!-- #include File="db.asp" -->
-
<%
-
-
dim action, sSQL, rsRecord, responseString
-
-
'Get query string variables
-
action = request.querystring("action")
-
if action = "" then action = request.Form("action")
-
-
Select Case action
-
-
Case "submitTest"
-
set rsRecord = Server.CreateObject("ADODB.Recordset")
-
sSQL = "SELECT * FROM PARTY_EXTENSION where PRTY_ID = 9999"
-
rsRecord.Open sSQL,cnSM,1,3
-
if rsRecord("extension_value") = "true" then
-
rsRecord("extension_value") = "false"
-
else
-
rsRecord("extension_value") = "true"
-
end if
-
rsRecord.Update
-
responseString = "<?xml version=""1.0"" encoding=""UTF-8"" ?><response><result>Updated "&rsRecord("extension_value")&"</result></response>"
-
rsRecord.Close
-
-
-
Case Else
-
'No action
-
responseString = "<?xml version=""1.0"" encoding=""UTF-8"" ?><response><result>Error - No Such Action Exists-"&action&"</result></response>"
-
End Select
-
-
Response.ContentType ="text/xml"
-
response.Write responseString
Nothing too fancy. Again, I just wanted to make sure the server was doing something and that I could independently verify it.
Summary
User loads up xmlhttp_client.asp and is presented with a single checkbox.
User clicks that checkbox, this firing the onChange event which calls...
... SubmitTest() so it lights up and makes the call to the server.
Server looks up the value in the database, flips the boolean and tosses it into an xml string and ...
... ProcessChangeRequest catches the xml and displays what just happened on/to the client.
Neat-o.
Tags: ajax, programming, tutorial
Possibly Related Posts
Comments
4 Responses to “The obligatory “My Ajax Tutorial” Post”
Leave a Reply



Hello,
This tutorial was really good and I stumbled across your site because I was having the same 411 Problem in FF. Even with adding the content-type it still wouldn’t work. I then noticed I was using the following code:
xmlHttp.send(null);
and null doesn’t have a length, so changing it to:
xmlHttp.send(”");
Made the error go away
Many Thanks
GK
Hello,
This tutorial was really good.
I was having the length required. 411 Problem
I then noticed I was using the following code:
AjaxXmlHttp.send(null);
and null doesn’t have a length, so changing it to:
AjaxXmlHttp.send(”");
Made the error go away
Many Thanks
amit
Hi,
I am also having the same problem. “POST” method is working fine in IE6/IE7. Even in firefox/WinXP. Its not working in firefox/WinNT and firefox/Win98…
I gone through some other topics also in this site. And tried every thing. But its of no use.
FYI: My server is APACHE.
Here is my code.
var repa = “re=” + escape(window.location.href);
request.open(”POST”, uri, true);
request.setRequestHeader(’Content-Type’, ‘application/x-www-form-urlencoded’);
request.setRequestHeader(’Date’, new Date().getTime());
request.setRequestHeader(’Content-length’, repa.length);
request.setRequestHeader(”Connection”, “close”);
request.send(repa);
Help me to fix this.
Thanks in advance