function valueForTag(xmlDoc, tag) {
	var matchingElements = xmlDoc.getElementsByTagName(tag);
	if (matchingElements.length == 0)
		return null;
	return matchingElements[0].firstChild.data;
}

function ajaxReq(url) {
	ajaxReq(url, null);
}

function ajaxReq(url, progressElement) {
	ajaxReq(url, progressElement, null);
}

function ajaxReq(url, progressElement, postData) {

	// we use a javascript feature here called "inner functions"
	// using these means the local variables retain their values after the outer function
	// has returned. this is useful for thread safety, so 
	// reassigning the onreadystatechange function doesn't stomp over earlier requests.
	// http://www.xml.com/cs/user/view/cs_msg/2815

	function ajaxBindCallback() {
		if (ajaxRequest.readyState == 4) {
			if (ajaxRequest.status == 200) {
				var responseXML = ajaxRequest.responseXML;
				if (responseXML == null)
					alert("There was a problem retrieving the XML data:\n" + ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" + ajaxRequest.responseText);
				var responseRoot = responseXML.documentElement;
				
				if (ajaxSpinner != null) {
					var status = valueForTag(responseRoot, "status");
					if (status == "valid")
						ajaxSpinner.src = "/global/images/SpinnerValid.gif";
					else if (status == "invalid")
						ajaxSpinner.src = "/global/images/SpinnerInvalid.gif";
					else
						ajaxSpinner.src = "/global/images/SpinnerBlank.gif";
				}
				
				var ajaxCallback = valueForTag(responseRoot, "callback");
				if (ajaxCallback != null && ajaxCallback != "")
					eval(ajaxCallback+"(responseRoot);");
				else
					alert("No AJAX callback defined");
			} else {
				alert("There was a problem retrieving the XML data:\n" + ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" + ajaxRequest.responseText);
			}
		}
	}
	
	
	// use a local variable to hold our request until the inner function is called...
	var ajaxRequest = null;
	var ajaxSpinner = null;
	if (progressElement != null) {
		if (typeof(progressElement) == "string")
			ajaxSpinner = document.getElementById(progressElement);
		else
			ajaxSpinner = progressElement;
	}
	
	if (ajaxSpinner != null)
		ajaxSpinner.src = "/global/images/Spinner.gif";
		
	var isPOST = (postData != null && postData.length > 0);
	
	// bind our callback then hit the server...
	if (window.XMLHttpRequest) {
		// moz et al
		ajaxRequest = new XMLHttpRequest();
		ajaxRequest.onreadystatechange = ajaxBindCallback;
		if (isPOST) {
			ajaxRequest.open("POST", url, true);
			ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			ajaxRequest.setRequestHeader("Content-length", postData.length);
			ajaxRequest.setRequestHeader("Connection", "close");
			ajaxRequest.send(postData);
		}
		else {
			ajaxRequest.open("GET", url, true);
			ajaxRequest.send(null);
		}
	} else if (window.ActiveXObject) {
		// ie
		ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
		if (ajaxRequest) {
			ajaxRequest.onreadystatechange = ajaxBindCallback;
			if (isPOST) {
				ajaxRequest.open("POST", url, true);
				ajaxRequest.send(postData);
			}
			else {
				ajaxRequest.open("GET", url, true);
				ajaxRequest.send();
			}
		}
	}
}
