Introduction
This article presents a simplified AJAX library written in JavaScript, hopefully many developers will find it useful.
AJAX is an exciting new technology and will change the way we develop our web applications.
Basically the library comprises of two methods, no classes or anything fancy, (I said it was simple). These two methods were designed with ease of use in mind. One allows flexibility by being able to pass the response to a JavaScript function, which allows you to do anything JavaScript can do with the returned data/response. The other sets the innerHTML
property of the passed object.
Background
I had heard a lot about this new AJAX technology and seen some examples on the web which looked really cool, so I thought I'd do some R&D on the subject.
The first thing I do when researching new technologies is look around the web for some libraries or code, and read, read, and read some code. As usual some are useful, a lot are overly complicated. So I take the useful and overly complicated code, and re-work it into something simple and easy to use.
My background is PHP and Linux, but now I'm a Microsoft .NET developer. Because of this .NET developers may or may not notice that I use more traditional techniques than the new ASP.NET way. This example uses ASP.NET and JavaScript.
The library itself can be used with multiple server side languages. Prepare to be amazed by the jaw-dropping simplicity of this code.
Using the code
Well let's get down to it...
The first thing to do is include the ajax.js JavaScript file in your web page like this:
<script language="javascript" src="ajax.js"></script>
Now we can use the two JavaScript functions in the ajax.js file.
The first function in the library, and the one that I use most, is SetInnerHTMLFromAjaxResponse(url, obj_id)
. Here is an example of how to use it in a web page:
<input type="button"
onclick="SetInnerHTMLFromAjaxResponse('?button=1','div_to_put_html')"
value="Get Some Html From The Server" ID="Button1" NAME="Button1" />
<div id="div_to_put_html"></div>
The first argument '?button=1' is the URL to send the request. Seasoned web developers will know that this is submitting the variable "button" with a value of "1" to the current page. You can of course submit the request to anywhere on the internet, but essentially to a server that will know what to do with the request and return some HTML. The function will place the returned HTML/response and place it in the div
we specified.
You can call this function from anywhere in the JavaScript.
function GetFilteredCustomerTable() {
var name = document.getElementById('cust_surname').value;
var country = document.getElementById('cust_country').value;
var min_orders = document.getElementById('min_orders').value;
SetInnerHTMLFromAjaxResponse('?action=get_customers_table&name='+name+
'&country='+country+'&min_orders='+min_orders,'div_to_put_html')
}
You can see that we are passing more parameters to the page in this example. These parameters can be used in the server side script to select/filter records from a database, create some HTML from the results and return it.
Now onto the second JavaScript function: PassAjaxResponseToFunction(url, callbackFunction, params)
. This will pass the response to the callback function. The params
argument is optional. The JavaScript to use would look something like this:
<input type="button"
onclick="PassAjaxResponseToFunction('?getsomecsvdata=1',
'FunctionToHandleTheResponse',
'\'div_0\',\'div_1\',\'div_2\'');"
value="Pass The Response To A Function" ID="Button2" NAME="Button2" />
function FunctionToHandleTheResponse(response, d0, d1, d2){
var data = response.split(',');
document.getElementById(d0).innerHTML = data[0];
document.getElementById(d1).innerHTML = data[1];
document.getElementById(d2).innerHTML = data[2];
}
Again the call to PassAjaxResponseToFunction()
can be called from a JavaScript event or another JavaScript function. The FunctionToHandleTheResponse(response, d0, d1, d2)
is a JavaScript function written to handle the returned response when it has been successfully received from the server. I think that only constants (strings, ints, etc.) and globals will actually be in scope when being passed in the params
string.
Passing the optional param argument is not necessary as the same result could be achieved by doing this:
<input type="button"
onclick="PassAjaxResponseToFunction('?getsomecsvdata=1',
'FunctionToHandleTheResponse');"
value="Pass The Response To A Function" ID="Button3" NAME="Button3" />
function FunctionToHandleTheResponse(r){
var data = r.split(',');
for(var i=0;i<data.length;i++){
document.getElementById('div_'+i).innerHTML = data[i];
}
}
Although, passing 'div_
' as a parameter may be useful for code re-usability.
And that's all there is to it. Hopefully you can see how easy this will be to use.
The JavaScript Source Code
I'm not going to spend much time explaining the source. I will point out that setting debug = true;
is helpful for seeing errors and seeing the response before it is rendered. Viewing the source in the browser will only show you the empty div
s and not the source that has been returned.
There's not much to the ajax.js JavaScript file, so here is the code:
var debug = false;
function GetXmlHttp() {
var xmlhttp = false;
if (window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP")
} catch (e) {
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
} catch (E) {
xmlhttp=false
}
}
}
return xmlhttp;
}
function PassAjaxResponseToFunction(url, callbackFunction, params)
{
var xmlhttp = new GetXmlHttp();
if (xmlhttp)
{
xmlhttp.onreadystatechange =
function ()
{
if (xmlhttp && xmlhttp.readyState==4)
{
if (xmlhttp.status==200)
{
var response = xmlhttp.responseText;
var functionToCall = callbackFunction +
'(response,'+params+')';
if(debug)
{
alert(response);
alert(functionToCall);
}
eval(functionToCall);
} else if(debug){
document.write(xmlhttp.responseText);
}
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
}
function SetInnerHTMLFromAjaxResponse(url, obj_id)
{
var xmlhttp = new GetXmlHttp();
if (xmlhttp)
{
xmlhttp.onreadystatechange =
function ()
{
if (xmlhttp && xmlhttp.readyState==4)
{
if (xmlhttp.status==200)
{
if(debug)
{
alert(xmlhttp.responseText);
}
if(typeof obj_id == 'object')
{
obj_id.innerHTML = xmlhttp.responseText;
} else {
document.getElementById(obj_id).innerHTML =
xmlhttp.responseText;
}
} else if(debug){
document.Write(xmlhttp.responseText);
}
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
}
ASP.NET - Using the code, the server side
For ASPX pages, I will create a method to check if the request is an AJAX request, then only return what is needed in the response. It is important to call Response.End();
when we have finished returning what we need.
private void Page_Load(object sender, System.EventArgs e)
{
HandleAjaxEvent();
}
private void HandleAjaxEvent()
{
string bNum = Request.QueryString["button"];
if(bNum != null && bNum.Length > 0)
{
switch (bNum)
{
case "1":
Label l = new Label();
l.Text = "Ajax is hot!";
l.BackColor = Color.Honeydew;
l.BorderWidth = 6;
l.BorderStyle = BorderStyle.Groove;
l.BorderColor = Color.Goldenrod;
Response.Write(GetHtml(l));
Response.End();
break;
case "2":
string name=Request.QueryString["name"];
Response.Write(GetCustomerDetailsByName(name));
Response.End();
break;
case "3": Return a Filtered DataGrid
DataGrid dg = new DataGrid();
dg.AutoGenerateColumns = true;
string min_orders=Request.QueryString["min_orders"];
DataTable dt = GetCustomersDataTable();
DataView dv = new DataView(dt);
dv.RowFilter="Orders > "+min_orders;
dg.DataSource = dv;
dg.DataBind();
Response.Write(GetHtml(dg));
Response.End();
break;
}
}
}
public string GetCustomerDetailsByName(string name)
{
return "Nigel,Liefrink,27";
}
public DataTable GetCustomersDataTable()
{
return new DataTable();
}
private string GetHtml(Control c)
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter tw = new HtmlTextWriter(new StringWriter(sb));
try
{
c.RenderControl(tw);
}
finally
{
tw.Close();
}
return sb.ToString();
}
Take note of the use of the GetHtml(Control c)
function and how you can get controls to render only themselves and return the HTML to the page. This function should either be in a BasePage
class or in a helper/utility class if you plan to render controls in this way.
Getting the demo project working
To get the demo project working, unzip the sal_demo.zip file to an appropriate location like wwwroot, but anywhere will do. Create a virtual directory in Information Services Manager/IIS under the 'Default Web Site' with an alias of 'sal_demo' and the directory path referencing the sal_demo folder you unzipped. Opening the project in Visual Studio, you should now be able to compile/debug/run the demo project.
Points of Interest
- View state etc. is not taken into account for controls when they are rendered by the server by
GetHtml(Control c)
. Take a look at this article: AJAX Was Here - Part 1: Client Side Framework or Instant AJAX: Applying AJAX to your existing Web Pages, if that is an issue for you.
- JavaScript doesn't support threading (someone please tell me I'm wrong). If an AJAX request takes a long time to complete, no other AJAX request can complete until the first one finishes. This can be seen in the example project if you click on the LongAjaxRequest button, and try clicking on another button. (I've tried
setInterval
/Timeout
.)
- This is my first article, hope you like it.