A simple Ajax dblookup simulator

I don’t normally open myself up to this sort of criticism, but after looking all around and not really finding a good example, I came up with this and thought it might save others some time (or at least get them started.)

Enjoy :slight_smile:

// Threadsafe Ajax callback example.

// Obtained from http://www.xml.com/cs/user/view/cs_msg/2815

// Author: brockweaver

// This function can be stored in a script library or wherever

// Makes use of Javascript Closures

// Not sure if this will cause an IE memory leak yet.

function ajaxSend(url,callback) {

function ajaxBindCallback() {

	if (ajaxRequest.readyState == 4) {

		if (ajaxRequest.status == 200) {

			if (ajaxCallback){

				ajaxCallback(ajaxRequest.response.XML);

			}else{

				alert("no callback defined");

			}

		}else{

			alert("There was a problem retrieving the xml data:\n" + 

			ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" +

			ajaxRequest.responseText);

		}

	}

}



var ajaxRequest = null;

var ajaxCallback = callback;



if (window.XMLHttpRequest){

	//mozilla, etc

	ajaxRequest = new XMLHttpRequest();

	ajaxRequest.onreadystatechange = ajaxBindCallback;

	ajaxRequest.open("GET",url,true);

	ajaxRequest.send(null);

}else if(window.ActiveXObject) {

	//internet explorer

	ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");

	if (ajaxRequest) {

		ajaxRequest.onreadystatechange = ajaxBindCallback;

		ajaxRequest.open("GET",url,true);

		ajaxRequest.send();

	}

}

}

/*

Author: Matt Rakestraw



Description:



	- Example dblookup simulator for web, called via: ajaxSend(urlStr,lookupLocation);

	- The XML processing function is the callback parameter to ajaxSend

	- End result is to populate the full name, phone number, and region fields for 

	the selected store



Lookup field:

	Loc - drop down, single selection list



The three target fields on the form are: 

	LocName - text

	LocRegion - text

	LocPhone - text



The view is just a lookup view with columns available to return the desired values. In this

example, sorting doesn't matter, and the key must be unique. count=-1 returns all rows.



	currNode.childNodes.item(0).text; is the first column value

	currNode.childNodes.item(5).text; is the sixth column value

*/

// onchange event of the “Loc” field

urlStr = “/carmax/cmstores.nsf/LStorebyName?ReadViewEntries&count=-1”;

var fld = document.forms[0].Loc;

storeLocStr = fld.options[fld.selectedIndex].text;

function lookupLocation(responseXML) {

this.$storeLocStr = storeLocStr;

if (responseXML) {

	//alert("Got some data via ajaxSend.");

}

var response = responseXML.documentElement;



//This seems to work ok as a brute force method...Matt Rakestraw



//obtain handle to the first top level node

var currNode = response.childNodes.item(0);



//search through all the nodes looking for the correct store location

while ((currNode != null) && 

		(this.$storeLocStr != currNode.childNodes.item(3).text)) {

	currNode = currNode.nextSibling;

}



//process the found node for the matching store information

if (currNode != null) {

	this.$storeNameStr = currNode.childNodes.item(0).text;

	this.$storeRegionStr = currNode.childNodes.item(5).text;

	this.$storePhoneStr = currNode.childNodes.item(6).text;

}else{

	this.$storeNameStr = "";

	this.$storeRegionStr = "";

	this.$storePhoneStr = "";

}



//assign to the correct fields

document.forms[0].LocName.value = this.$storeNameStr;

document.forms[0].LocRegion.value = this.$storeRegionStr;

document.forms[0].LocPhone.value = this.$storePhoneStr;

}

// Call ajaxSend

ajaxSend(urlStr,lookupLocation);

Subject: A simple Ajax dblookup simulator

You bozo! Well, you said you were opening yourself up for … never mind ;o)

Good post, Matt – anything that helps people improve the performance, scalability and responsiveness of their web apps is more than welcome.

You might want to take a look at some of these utility functions on Richard Schwartz’ site, too:

http://smokey.rhs.com/web/blog/PowerOfTheSchwartz.nsf/plinks/RSCZ-6CJNE2

They make pretty decent wrappers, and get around the whitespace “nodes” that sometimes come between parents and children. There’s also this refinement:

http://smokey.rhs.com/web/blog/PowerOfTheSchwartz.nsf/plinks/RSCZ-6CEQAR

which gets around the standard hard-coding of request objects so you can create multiple asynchronous requests on the fly.

Subject: RE: A simple Ajax dblookup simulator

Hey Stan, was hoping you’d see that :slight_smile:

My assumption is the ajaxSend function gets around the second point you made. I.e. It’s threadsafe. Thus, you can call ajaxSend over and over again with no ill effects.

I love the wrappers, but I don’t see (and I haven’t experimented enough obviously) what Rich’s code is doing that solves the “nodes between the nodes” issue you mentioned. Is it fixed by checking for the nodeType first?

  • Matt

Subject: RE: A simple Ajax dblookup simulator

Yes. The problem is when you want to iterate through siblings under a parent – some of the siblings might not be what you’d instictively expect. Different interpretations of the DOM can see zero-length data nodes between elements (in particular, between a parent and what you think should be the first child). Putting a wrapper function around the iteration just means that you don’t need to concern yourself with the empties in the main body of the “does stuff” code.

Rich’s code pattern gets around one problem that seems to be in your code (as well as all of the code I wrote before Rich woke me up). There’s a single global AjaxRequest object, so you need to queue the requests. Creating the request objects at runtime gives you something approaching true asynchronicity – request1 sends and listens, request2 sends and listens, request2 gets a response and handles it while request1 is still listening, request1 receives and handles a response. On a complex dynamic page, that can make a big difference in perceived performance. (Not that I’ve gotten that far – my day job these days has me stuck in R5 and mostly for Notes. <sigh…/>)