function xhr(){};
xhr.lastResponseText = null;

xhr.encodeFormValues = function(formID){
	var outStr = "";
	var delimVal = "";
	//set f = a form with the ID or NAME of the formID argument - else return
	var f = $(formID)? $(formID) : document.forms[formID] ? document.forms[formID] : null;
	if (!f){return;}
	for (var i=0; i<f.length; i++){
		var el = f[i];
		
		//console.info("working on: " + el.id);
		if ((el.name || el.id) && !el.disabled && el.type){
			var elVal = null;
			var noAdd = false;
			switch(el.type.toLowerCase()){
				case "hidden": case "text": case "password": case "textarea":
					//console.info("adding: " + el.id + "::" + el.value);
					elVal = el.value;
					break;
				case "select-one":
					if (el.selectedIndex >=0){ elVal = el.options[el.selectedIndex].value }else{noAdd=true;};
					break;
				case "radio": case "checkbox":
					if (el.checked){elVal = el.value;}else{noAdd = true;}
					break;
			}
			//filter out null values
			if (!noAdd){
				outStr += delimVal + (el.name || el.id) + "=" + encodeURIComponent(elVal);
			}
		}
		if (outStr){ delimVal = "&"; }
	}
	return outStr;
};

xhr.unencode = function (s){
	if (typeof s == "string"){
		s = s.replace(/\+/g," ");
		return unescape(s);
	}else{
		return null;
	}
};

xhr.connect = function(requestURL,requestMethod,successFunc,argAry,formName,debugObjName){
	//alert(requestURL);
	var fValues = "";
	var xmlhttp;
	try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
	catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e) { try { xmlhttp = new XMLHttpRequest(); }
	catch (e) { xmlhttp = false; }}}
 	if (!xmlhttp) return null;
	
	if (formName){
		fValues = xhr.encodeFormValues(formName);
	}
		
	if (requestMethod.toUpperCase() == "POST" && formName){
		sendVal = fValues;
	}else{
		if (formName){
			requestURL = requestURL + "?" + fValues;
		}
		sendVal = null
	}
	// add an arbitrary random value
	requestURL = requestURL + (requestURL.indexOf("?") > -1 ?"&":"?") + "rndval=" + xhr.rnd();

	xmlhttp.open(requestMethod.toUpperCase(), requestURL, true);
	if (requestMethod.toUpperCase() == "POST"){
		xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
	}
	xmlhttp.onreadystatechange = function(){
		if (xmlhttp.readyState == 4){
		    xhr.lastResponseText = xmlhttp.responseText;
			if (debugObjName) {
				if (dom){ dom.alert(xmlhttp.responseText, debugObjName,true); }
			}

			if (successFunc){
				if (argAry){
					argAry[argAry.length] = xmlhttp.responseXML;
					//argAry[argAry.length] = xmlhttp.responseText;
					successFunc.apply(this,argAry);
				}else{
					successFunc.call(this,xmlhttp.responseXML);
				}
			}
		}
	}
	if (debugObjName) {
		if (dom){ dom.alert("requestURL:<br>" + requestURL + "<br>sendVal:<br>" + sendVal, debugObjName,false,true);}
	}
	xmlhttp.send(sendVal);
};
	
//extract a row of data across a matrix recordset rotation
xhr.getDataRow = function(jsonRSObj,rowPos){
	var outObj = {};
	for (var p in jsonRSObj){
		outObj[p] = jsonRSObj[p][rowPos];
	}
	return outObj;
}

xhr.json = function(requestURL,requestMethod,successFunc,argAry,formName,debugObjName){
	//alert(requestURL);
	var fValues = "";
	var xmlhttp;
	try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
	catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e) { try { xmlhttp = new XMLHttpRequest(); }
	catch (e) { xmlhttp = false; }}}
	if (!xmlhttp) return null;

	
	if (formName){
		fValues = xhr.encodeFormValues(formName);
	}
		
	if (requestMethod.toUpperCase() == "POST" && formName){
		sendVal = fValues;
	}else{
		if (formName){
			requestURL = requestURL + "?" + fValues;
		}
		sendVal = null
	}
	// add an arbitrary random value
	requestURL = requestURL + (requestURL.indexOf("?") > -1 ?"&":"?") + "rndval=" + xhr.rnd();

	xmlhttp.open(requestMethod.toUpperCase(), requestURL, true);
	if (requestMethod.toUpperCase() == "POST"){
		xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
	}
	xmlhttp.onreadystatechange = function(){
		if (xmlhttp.readyState == 4){
			if (debugObjName) {
				if (dom){ dom.alert(xmlhttp.responseText, debugObjName,true); }
			}

			if (successFunc){
				var returnObj = eval("(" + xmlhttp.responseText + ")");
				if (argAry){
					argAry[argAry.length] = returnObj;
					successFunc.apply(this,argAry);
				}else{
					successFunc.call(this,returnObj);
				}
			}
		}
	}
	if (debugObjName) {
		if (dom){ dom.alert("requestURL:<br>" + requestURL + "<br>sendVal:<br>" + sendVal, debugObjName,false,true);}
	}
	xmlhttp.send(sendVal);
};
	
//==========================================================	
xhr.rnd = function(){
	return Math.round(Math.random()*99999);
};
	
xhr.xmlFormPopulate = function(formName, domObj){
	//grab the attributes of the root as possible form values
	for (var i=0;i<domObj.attributes.length;i++){
		dom.setFormValue(formName,domObj.attributes[i].name,domObj.attributes[i].value);
	}

	//loop though all childnodes of the root
	//var domChild = domObj.childNodes;
	for (var i=0;i<domObj.childNodes.length;i++){
		var elName = domObj.childNodes[i].tagName;
		if (elName){
			var elValue = decodeURIComponent(domObj.childNodes[i].firstChild.nodeValue);
			dom.setFormValue(formName,elName,elValue); //set the node value
			if($(elName + '_checkbox')){
				if (elValue.toLowerCase() == "true" || parseInt(elValue)==1 ){
					$(elName + '_checkbox').checked=true;
				}else{
					$(elName + '_checkbox').checked=false;
				}
			}
			//dom.alert("<br>" + i + " Found " + elName + " = " + elValue);
		}
	}
};
	
	
xhr.XMLtoObj_old = function(nodeObj){
	var retObj = {};
	//check for and create 
	if (nodeObj.attributes && nodeObj.attributes.length){ 
		retObj.attributes = {}; 
		for (var i=0;i<nodeObj.attributes.length;i++){
			var aName = nodeObj.attributes[i].name;
			var aValue = nodeObj.attributes[i].value;
			retObj.attributes[aName] = aValue;
		}
	}
	
	//loop though all childnodes
	if (nodeObj.childNodes.length > 0) {		
		for (var i=0;i<nodeObj.childNodes.length;i++){
			var elName = nodeObj.childNodes[i].tagName;
			if (elName){				
				if (nodeObj.childNodes[i].nodeType == 1 && nodeObj.childNodes[i].firstChild){
					//console.info("solo entry: " + elName);
					if (nodeObj.childNodes[i].childNodes.length == 1){
						var elValue = xhr.unencode(nodeObj.childNodes[i].firstChild.nodeValue);
						retObj[elName] = elValue;
						
					}else{ //this has childnodes - adding them as an object or array
						//console.info("multiple childNodes: " + elName);
						retObj[elName] = {};
						for (var j=0;j<nodeObj.childNodes[i].childNodes.length;j++){
							var no = nodeObj.childNodes[i].childNodes[j];
							if (no.nodeType == 1 && no.firstChild){ //is valid to add?
								//console.info("adding: " + no.tagName);
								if (retObj[elName][no.tagName]){ //identical tag name in the childNodes
									//console.info(no.tagName + " -- already entered");
									if (!retObj[elName][no.tagName].length){  //- create an array
										//console.info("creating an array for: " + no.tagName );
										var copyNode = retObj[elName][no.tagName];
										retObj[elName][no.tagName] = [];
										retObj[elName][no.tagName].push(copyNode); //add the first entry
									}
									retObj[elName][no.tagName].push(xhr.XMLtoObj(nodeObj.childNodes[i].childNodes[j]));
								
								}else{
									//console.info(no.tagName + " -- first entry");
									if (nodeObj.childNodes[i].childNodes[j].childNodes.length == 1){
										//console.info("data only: " + no.tagName);
										retObj[elName][no.tagName] = nodeObj.childNodes[i].childNodes[j].firstChild.nodeValue;
									}else{
										//console.info("has childNodes: " + no.tagName);
										retObj[elName][no.tagName] = xhr.XMLtoObj(nodeObj.childNodes[i].childNodes[j]);
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return retObj;
};

xhr.XMLtoObj = function(nodeObj){
	var retObj = {};	
	for (var i=0;i<nodeObj.childNodes.length;i++){ //main loop
		var no = nodeObj.childNodes[i];
		if (no.tagName != undefined){ //make sure it's valid node type
			var isNodeArray = false;
			if (retObj[no.tagName]){ //same nodename already here
					//console.info(no.tagName + " -- exists as a " + typeof retObj[no.tagName]);
					if (!retObj[no.tagName].length || typeof retObj[no.tagName] == "string"){  //- create an array
						//console.info("creating an array for: " + no.tagName );
						var copyNode = retObj[no.tagName];
						retObj[no.tagName] = [];
						retObj[no.tagName].push(copyNode); //add the first entry
					}
					isNodeArray = true;
			}

			if (isNodeArray){
				if (no.childNodes.length == 1){
					retObj[no.tagName].push(no.firstChild.nodeValue);
				}else if (no.childNodes.length > 1){
					retObj[no.tagName].push(xhr.XMLtoObj(nodeObj.childNodes[i]));
				}		
			}else{
				if (no.childNodes.length == 1){
					retObj[no.tagName] = no.firstChild.nodeValue;					
				}else if (no.childNodes.length > 1){
					retObj[no.tagName] = xhr.XMLtoObj(nodeObj.childNodes[i]);
				}			
			}	
			//handle node attributes
			/*
			if (no.attributes && no.attributes.length){
				retObj[no.tagName].attributes = {};
				for (var i=0;i<no.attributes.length;i++){
					var aName = no.attributes[i].name;
					var aValue = no.attributes[i].value;
					retObj[no.tagName].attributes["@" + aName] = aValue;
				}
			}*/					
		}
	}
	return retObj;
}

//return an object from a table schema with all attributes and values as properties
xhr.getTableSchema = function(nodeObj){
	var ts = new Object();
	for (var t=0;t<nodeObj.childNodes.length;t++){
		var n = nodeObj.childNodes[t];
		if(n.tagName){
			
			if (n.attributes.length){
				ts[n.tagName] = new Object;
				ts[n.tagName].dbFieldName = n.tagName;
				for (var i=0;i<n.attributes.length;i++){
					var aName = n.attributes[i].name;
					var aValue = n.attributes[i].value;					
					ts[n.tagName][aName] = aValue;
					if(aName == "dbFieldDescripton"){
						var ft = /\[([^\]]+?)\]/.test(aValue)?RegExp.$1:null;
						if (ft){
							if (ft.search(/::/) > -1){
								var ftDict = parseDict(ft,"||","::");
								for (var d in ftDict){
									ts[n.tagName][d] = ftDict[d];							
								}
							}else{
								ts[n.tagName].dbFormType = ft;
							}
							ts[n.tagName].dbFieldDescripton = ts[n.tagName].dbFieldDescripton.replace("["+ft+"]","");
						}
					}
				}				
			}
			//alert(ts[n.tagName].dbFormType);			
		}
		
	}
	return ts;
};

xhr.viewAsTable = function(nodeList,parentObj,reportParams,fieldMods){
	var rp = reportParams?reportParams:{};
	var fm = fieldMods?fieldMods:{};
	rp.hide = (rp.hide?rp.hide + ",":"") + "attributes";
	if (rp && rp.nocleanparent){parentObj.innerHTML = "";}
	if (nodeList.length > 0){
		var newTableID =  xhr.rnd();
		var newTbl = "tbl" + newTableID;
		var newTB = "tblTB" + newTableID;
		var newTitleRow = "tblTitle" + newTableID;
		var newColHdr = "tblColHeader" + newTableID;
		var colCnt = 0;
		dom.addNode("",parentObj,"table",{id:newTbl,"className":"reportTable"});		
		dom.addNode("",newTbl,"tbody",{id:newTB});
		dom.addNode("",newTB,"tr",{"id":newTitleRow});
		dom.addNode("",newTB,"tr",{"id":newColHdr});
		
		for (var i=0;i<nodeList.length;i++){
			//add a new row
			var newRowID = "tbl" + newTableID + "_row" + i;
			var styleOpt = (i%2==0)?{"backgroundColor":"#FFC"}:null; 
			dom.addNode("",newTB,"tr",{id:newRowID},styleOpt);
			var curRow = xhr.XMLtoObj(nodeList[i]);
			for (var fld in curRow){
				if (rp.hide.indexOf(fld) < 0){
					//console.info(rp.hide.indexOf(fld));
					if (i==0){ //add a to the colHeader row
						dom.addNode(fld,newColHdr,"td");
						colCnt++;
					}
					var newTD = dom.addNode("",newRowID,"td");
					var curVal = fm[fld]?(fm[fld](curRow[fld],curRow,newTD)):curRow[fld];
					newTD.innerHTML = curVal
				}
			}
		}
		if (rp.title){ dom.addNode(rp.title,newTitleRow,"td",{colSpan:colCnt}) };
		return $(newTbl);
	}else{
		dom.addNode("No records found",parentObj,"div",{id:"emptyReport"});
	}
};

