Ajax calling script

We are going to look at how to create an ajax calling script with javascript, php and xml.

To start off I am going to add 2 global variables, one to store the loading status and the other for our XML request instance.

var req;
var progmsg;

In this script we shall have 3 functions

  • Load the XML document (loadXMLDoc)
  • call the ajax script (ajaxCallback)
  • end the ajax script (closeProgress)

In loadXMLDoc we will have 3 parameters

  • The requested URL.
  • Request the script asynchronous or synchronous.
  • Loading message

We are also going to use a very useful API called XMLHttpRequest which is used to send HTTP requests directly to a web server and load the server response data directly back into the script.

IE does not fully support XMLHttpRequest so we will use the ActiveXObject to load the XML document.

lets create our function.

function loadXMLDoc(url,async,message) {
progmsg=message;
if (window.XMLHttpRequest) {
req=new XMLHttpRequest();
req.onreadystatechange=ajaxCallback;
req.open("GET",url,async);
req.send(null);
} else if (window.ActiveXObject) {
req=new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange=ajaxCallback;
req.open("GET",url,async);
req.send();
}}}

We have created an instance called req and then onreadystatechange is fired when the object has changed and calls ajaxCallback. Then we assign a method, url and whether the request is synchronous or asynchronous (‘true’ will return the call immediately). Finally a request is sent to the server and the client receives a response.

In the ajaxCallback function we check to see the status of the HTTP request. The property we shall use is readyState. There are 5 values that determine what state your request is in.

0 The object has been created but not initialized. The open method needs to be called.

1 We have a created object but still to call the send method

2 send method has been called, waiting for response

3 receiving data

4 Loaded

We are going to only use readyState 1 and 2. 1 to load the loading message and 4 to retrieve all the response data.
Now to create our function

function ajaxCallback() {
if (req.readyState==1 && progmsg!='') { // Loading
var progress=document.getElementById('progress_id');
progress.innerHTML=progmsg;
longEnough=false;
setTimeout("longEnough=true",1000);
}
if (req.readyState==4) {
if (req.status==200) {
var result=req.responseXML;
if (result.xml=='') alert(req.responseText);
var actionElements=result.getElementsByTagName('action');
for (var i=0; i<actionElements.length; i++) {
var actionElement=actionElements[i];
var method=actionElement.getElementsByTagName('method')[0].firstChild.nodeValue;
if (method=='script') {
var code=actionElement.getElementsByTagName('code')[0].firstChild.nodeValue;
eval(code);
} else if (method=='nodeRewrite') {
target=actionElement.getElementsByTagName('target')[0].firstChild.nodeValue;
html=actionElement.getElementsByTagName('html')[0].firstChild.nodeValue;
document.getElementById(target).innerHTML=html;
}
}
}
if (progmsg!='') closeProgress();
}
}

I have another variable which you will need to add to the top of your script ‘var longEnough;’, this closes this progress if the ajax call is more than a second.

The status property checks to see if the HTTP request is OK, and then we retrieve the xml data with responseXML and check to see if data was passed through.

We then retrieve the elements data. The way I have the elements set out are as follows

<actions>
<action>
<method></method>
</action>
</actions>

Depending on the method. Elements will be different after the method element. There are 2 methods which can be used in this example, script and nodeRewrite. Script is used to run javascript within this document and nodeRewrite changes the HTML within the element.

so we can have…

<method>script</method>
<code><![CDATA[alert("hello world!");]]></code>

or….

<method>nodeRewrite></method>
<target>elementid</target>
<html>hello world</html>

all we need to do now is add the closeProgress function

function closeProgress() {
if (longEnough) {
document.getElementById('progress_id').style.display='none';
return;
}
setTimeout("closeProgress()",100);
}

here is an example of running the loadXMLDoc using PHP. You will need to create 2 files test.htm and test.php.

in test.html add this

<!--DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script language="javascript">
var req;
var longEnough;
var progmsg;

function loadXMLDoc(url,async,message) {
progmsg=message;
if (window.XMLHttpRequest) {
req=new XMLHttpRequest();
req.onreadystatechange=ajaxCallback;
req.open("GET",url,async);
req.send(null);
} else if (window.ActiveXObject) {
req=new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange=ajaxCallback;
req.open("GET",url,async);
req.send();
}
}
}

function ajaxCallback() {
if (req.readyState==1 && progmsg!='') { // Loading
var progress=document.getElementById('progress_id');
progress.innerHTML=progmsg;
longEnough=false;
setTimeout("longEnough=true",1000);
}
if (req.readyState==4) {
if (req.status==200) {
var result=req.responseXML;
if (result.xml=='') alert(req.responseText);
var actionElements=result.getElementsByTagName('action');
for (var i=0; i<actionElements.length; i++) {
var actionElement=actionElements[i];
var method=actionElement.getElementsByTagName('method')[0].firstChild.nodeValue;
if (method=='script') {
var code=actionElement.getElementsByTagName('code')[0].firstChild.nodeValue;
eval(code);
} else if (method=='nodeRewrite') {
target=actionElement.getElementsByTagName('target')[0].firstChild.nodeValue;
html=actionElement.getElementsByTagName('html')[0].firstChild.nodeValue;
document.getElementById(target).innerHTML=html;
}
}
}
if (progmsg!='') closeProgress();
}
}

function closeProgress() {
if (longEnough) {
document.getElementById('progress_id').style.display='none';
return;
}
setTimeout("closeProgress()",100);
}
</script>
</head>
<body>
<div id="progress_id"></div>
<input id="text"><input type="button" value="change" onclick="loadXMLDoc('test.php?t='+escape(document.getElementById('text').value), true, 'loading..');"><br />
<div id="changetext">text</div>
</body>
</html>

and the following in test.php

<?php

$t = $_GET['t'];

header("Content-Type: text/xml");

echo <<<EOT
<actions>
<action>
<method>nodeRewrite</method>
<target>changetext</target>
<html>$t</html>
</action>
</actions>
EOT;

?>

and run test.htm

techfind.co.uk


About this entry