// threadsafe asynchronous XMLHTTPRequest code
function ajaxSend(url, callback, meth, args, cmpRef){
	// 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.
	err = cmpRef.errors;//reference to errors array of component object
	function ajaxBindCallback(){
		if (ajaxRequest.readyState == 4) { //4 = completed
			if (ajaxRequest.status == 200) { //200 = ok
				if (ajaxCallback){
					ajaxCallback(ajaxRequest);
				} else {
					err[err.length]="No callback defined for component "+cmpRef['name']+", id "+cmpRef['id'];//throw an error if no callback defined
				}
			} else {
				err[err.length]="There was a problem retrieving the xml data:\n" + ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" + ajaxRequest.responseText;//throw an error if status is not ok
			}
		}
	}
	// use a local variable to hold our request and callback until the inner function is called...
	var ajaxRequest = null;
	var ajaxCallback = callback;
	// bind our callback then hit the server...
	if (window.XMLHttpRequest) {
		// mozilla et al
		ajaxRequest = new XMLHttpRequest();
		ajaxRequest.onreadystatechange = ajaxBindCallback;
		if (meth=="POST") {
			//pass POST arguments
			ajaxRequest.open(meth, url, true);
			ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			ajaxRequest.send(parseArgs(args));
		}
		else if (meth=="GET") {
			//assign get arguments to url
			url+="?"+parseArgs(args);
			alert(url);
			ajaxRequest.open(meth, url, true);
			ajaxRequest.send(null);
		}
	} else if (window.ActiveXObject) {
		// ie
		ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");//this is the VERSION INDEPENDENT reference to the XMLhttprequest for MS (any version of IE)
		if (ajaxRequest) {
			ajaxRequest.onreadystatechange = ajaxBindCallback;
			if (meth=="POST") {
				//pass POST arguments
				ajaxRequest.open(meth, url, true);
				ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
				ajaxRequest.send(parseArgs(args));
			}
			else if (meth=="GET") {
				//add get arguments to url
				url+="?"+parseArgs(args);
				ajaxRequest.open(meth, url, true);
				ajaxRequest.send(null);
			}
		}
	}
	else {
		//no ajax object, default to load from backend
	}
}

function checkObj(obj) {
	//function to pass to ajaxSend.callback
	xmlstr = obj.responseText;
	window.document.myStr = xmlstr;
	window.document.getElementsByTagName('BODY')[0].innerHTML+=xmlstr;
}

function rep(str,num) {
	//repeat a string num times
	outp = "";
	for (i=0;i<num;i++) {
		outp+=str;
	}
	return outp;
}

function parseArgs(arrArgs) {
	//parse argument array into URL-encoded format
	out="";
	amp=false;
	for(m in arrArgs) {
		if(amp) {
			out+="&";
		}
		out+=m+"="+arrArgs[m];
		amp=true;
	}
	return out;
}

function makeTree(xmlobj,num) {
	//iteratively traverse a node tree and return a listing - debug
	var out = "";
	var itr = 0;
	out+=rep(" ",num+itr)+"NODE: element:"+xmlobj.tagName+" name:"+xmlobj.nodeName+" type:"+xmlobj.nodeType+" value:"+xmlobj.nodeValue+" inner:"+xmlobj.innerHTML+"\n";
	if (xmlobj.hasChildNodes) {
		itr++;
		for(aNode in xmlobj.childNodes) {
			//add the node to the arrobj
			out+=makeTree(aNode,num+itr);
		}
	}
	return out;
}

//SunAjaxComponent prototype
function SunAjaxComponent(cmptype,cmpname,cmpid) {
	//definition for SunAjaxComponent
	this.type = cmptype;//type field for component
	this.name = cmpname;//component name (reference to construtor object)
	this.id = cmpid;//component id
	this.relay = ajaxSend;//function which takes care fo the actual data transfer
	this.defaultBack = "";//URL to default backend script to load content as js vars
	this.errors = new Array;//array of errors for the component - string array
}

components = new Array();//define an array for all components on the page
