// <!--


	/**
	AJAX "Grail" project
	Jonathan Guthrie, April 2005
	jono@xserve.co.nz
	
	If you use this library please let me know for my own ego's sake.
	If you change / improve this library please do me the courtesy of sharing improvements or fixes 
	with me in the same vein as this is being shared with you!
	
	This library is meant as a general interpreter.
	The goal is that an html page utilizing AJAX methods for forms 
	doesn't have to have it's own massively customized AJAX stuff built in,
	that a general library can be used instead.
	The routine can be triggered by select list onChange, or an onBlur, or anything, even a link.
	The server then creates an XML response that is specific to the situation and contains all the 
	information that is needed for this library to change the page data.
		
	To do:
		- extend the url submission side of the engine
		- finish processing instructions for all planned data types.
		- solicit ideas for further data types / situations
		- test the crap out of it in the real world.	
	
	Data types:
		textarea 				- done
		text, hidden				- done
		select					- done (* bug)
		select multiple			- done
		password					- NOT DOING for obvious reasons
		checkbox					- done
		radio					- done

		submit, reset, button		- these 3 are addressed the same. type=button (name/value only)
		
		file						- not done, I can't see a reason you'd want to change the only configurable option!
		image					- done
									properties supported:
									STD IMAGE: name, alt, width, height, src, border
									IMAGE BUTTON: src, name (w/h/alt supported in MSIE Win)
		
		html div support			- done
		
		
		BUGS:
			* MSIE (win): Select boxes not honouring selected = true
			* Radio buttons cannot be addressed as an object of ID, 
				so, an extra config option of formname must be specified, dammit!
		
		ChangeLog:
		1 August 2005: Adding POST routines
	*/



// global flag
var isIE = false;

// global request and XML document objects
var req;
var postSub = 0;

// retrieve XML document
function loadXMLDoc(url) {
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = processReqChange;
        req.open("GET", url, true);
        req.send(null);
    // branch for IE/Windows ActiveX version
    } else if (window.ActiveXObject) {
        isIE = true;
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = processReqChange;
            req.open("GET", url, true);
            req.send();
        }
    }
}

// handle onreadystatechange event of req object
function processReqChange() {
    // only if req shows "loaded"
    if (req.readyState == 4) {
        // only if "OK"
        if (req.status == 200) {
        	postSub = 0;
            setTargetData();
         } else {
            alert("There was a problem retrieving the XML data:\n" +
                req.statusText);
         }
    }
}

// loads chosen XML document
function loadDocData(url) {
	if (url) {
		try {
			loadXMLDoc(url);
		}
		catch(e) {
			var msg = (typeof e == "string") ? e : ((e.message) ? e.message : "Unknown Error");
			alert("Unable to get XML data:\n" + msg);
			return;
		}
	}
}


// POST SUB addition start;
function loadDocDataPOST(url,fFunct) {
	if(postSub == 0){
		postSub = 1;
		// eval string here
		var fStr = "";
		var cmd = fFunct + "()";
		var fieldList = eval(cmd); // GETS LIST OF FIELDS TO BE INCLUDING IN POST DIRECTIVE
		for(var i = 0;i < fieldList.length;i++) {
			var thisItem = fieldList[i];
			var thisObj = document.getElementById(thisItem);
			switch(thisObj.type) {
		       case "text":
		            fStr += thisItem +
		             "=" + escape(thisObj.value) + "&";
		             break;
		       case "hidden":
		            fStr += thisItem +
		             "=" + escape(thisObj.value) + "&";
		             break;
		       case "select-one":
		            fStr += thisItem +
		            "=" + thisObj.options[thisObj.selectedIndex].value + "&";
		            break;
		       }		
		}
		if (url) {
			try {
				loadXMLDocPOST(url,fStr);
			}
			catch(e) {
				var msg = (typeof e == "string") ? e : ((e.message) ? e.message : "Unknown Error");
				alert("Unable to get XML data:\n" + msg);
				return;
			}
		}
	}
	else {
		alert('Please wait while your request has finished processing before trying again.');
	}
}

function loadXMLDocPOST(url,fStr) {
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = processReqChange;
        req.open("POST", url, true);
        req.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
        req.send(fStr);
    // branch for IE/Windows ActiveX version
    } else if (window.ActiveXObject) {
        isIE = true;
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = processReqChange;
            req.open("POST", url, true);
	        req.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
	        req.send(fStr);
        }
    }
}

// POST SUB addition end;



// retrieve text of an XML document element, including
// elements using namespaces
function getElementTextNS(prefix, local, parentElem, index) {
    var result = "";
    if (prefix && isIE) {
        // IE/Windows way of handling namespaces
        result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
    } else {
        // the namespace versions of this method
        // (getElementsByTagNameNS()) operate
        // differently in Safari and Mozilla, but both
        // return value with just local name, provided
        // there aren't conflicts with non-namespace element
        // names
        result = parentElem.getElementsByTagName(local)[index];
    }
    if (result) {
        // get text, accounting for possible
        // whitespace (carriage return) text nodes
        if (result.childNodes.length > 1) {
            return result.childNodes[1].nodeValue;
        } else {
            return result.firstChild.nodeValue;
        }
    } else {
        return "n/a";
    }
}
// retrieve text of an XML document element, including
// elements using namespaces
function getElementDataNS(prefix, local, parentElem, index) {
    var result = "";
    if (prefix && isIE) {
        // IE/Windows way of handling namespaces
        result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
    } else {
        // the namespace versions of this method
        // (getElementsByTagNameNS()) operate
        // differently in Safari and Mozilla, but both
        // return value with just local name, provided
        // there aren't conflicts with non-namespace element
        // names
        result = parentElem.getElementsByTagName(local)[index];
    }
    if (result) {
        // get text, accounting for possible
        // whitespace (carriage return) text nodes
        if (result.childNodes.length > 1) {
            return result.childNodes[1].attributes;
        } else {
            return result.firstChild.attributes;
        }
    } else {
        return "n/a";
    }
}

function setTargetData() {
	var feedbackis = '';
	
	for (var i = 0; i < req.responseXML.getElementsByTagName("item").length; i++) {
		var item = req.responseXML.getElementsByTagName("item")[i];

		for (var n = 0; n < item.attributes.length; n++) {
			if(item.attributes[n].nodeName.toLowerCase() == 'otype' ) {
				thistype = item.attributes[n].nodeValue;
	        }
			if(item.attributes[n].nodeName.toLowerCase() == 'oid' ) {
				thisid = item.attributes[n].nodeValue;
	        }
        }
	
		if(thistype == "jsexe") {
//			alert('x');
		}
		else{
			obj = document.getElementById(thisid);
		}
		
		switch(thistype){
			case "div":
				obj.innerHTML = "";
				obj.innerHTML = getElementTextNS("","odata",item,0);
				break;
				
				
			case "select":
				lines = item.getElementsByTagName("element");
				clearList();
				buildSelect();
				break;
				
				
			case "selectmulti":
				lines = item.getElementsByTagName("element");
				clearList();
				buildSelect();
				break;


			case "checkbox":
				box = item.getElementsByTagName("odata");
				for (var j = 0; j < box.length; j++) {
					oChecked = "no";
					for (var n = 0; n < box[j].attributes.length; n++) {
						if(box[j].attributes[n].nodeName.toLowerCase() == 'checked' ) {
							oChecked = box[j].attributes[n].nodeValue;
				        }
						if(box[j].attributes[n].nodeName.toLowerCase() == 'val' ) {
							obj.value = box[j].attributes[n].nodeValue;
				        }
			        }
					if (oChecked == "yes") {
						obj.checked = true;
					} else {
						obj.checked = false;
					}
				}
				break;


			case "radio":
				formname = getElementTextNS("","formname",item,0);
				obj = eval('document.'+formname+'.'+thisid);
				button = item.getElementsByTagName("element");
				
				for (var j = 0; j < button.length; j++) {
					oChecked = "no";
					for (var n = 0; n < button[j].attributes.length; n++) {
						if(button[j].attributes[n].nodeName.toLowerCase() == 'checked' ) {
							oChecked = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'val' ) {
							obj[j].value = button[j].attributes[n].nodeValue;
				        }
			        }
					if (oChecked == "yes") {
						obj[j].checked = true;
					} else {
						obj[j].checked = false;
					}
				}
				break;


			case "button":
				button = item.getElementsByTagName("odata");
				for (var j = 0; j < button.length; j++) {
					for (var n = 0; n < button[j].attributes.length; n++) {
						if(button[j].attributes[n].nodeName.toLowerCase() == 'name' ) {
							obj.name = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'val' ) {
							obj.value = button[j].attributes[n].nodeValue;
				        }
			        }
				}
				break;


			case "image":

				button = item.getElementsByTagName("odata");
				for (var j = 0; j < button.length; j++) {
					for (var n = 0; n < button[j].attributes.length; n++) {
						if(button[j].attributes[n].nodeName.toLowerCase() == 'name' ) {
							obj.name = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'src' ) {
							obj.src = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'alt' ) {
							obj.alt = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'w' ) {
							obj.width = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'h' ) {
							obj.height = button[j].attributes[n].nodeValue;
				        }
						if(button[j].attributes[n].nodeName.toLowerCase() == 'border' ) {
							obj.border = button[j].attributes[n].nodeValue;
				        }
			        }
				}
				break;


			case "js":
				eval(getElementTextNS("","odata",item,0));
				break;
				
				
			case "jsexe":
				eval(getElementTextNS("","odata",item,0));
				//var cmd = thisid + "()";
				//eval(cmd);						
				break;
				
				
			default:		// default is standard input box
				obj.value = "";
				obj.value = getElementTextNS("","odata",item,0);
		}
	}
}

// empty select list content
function clearList() {
    while (obj.length > 0) {
        obj.remove(0);
    }
}


function buildSelect() {
	for (var j = 0; j < lines.length; j++) {
		oDisplay = lines[j].firstChild.nodeValue;
		oData = "x"+j;
		oSelected = false;
		for (var n = 0; n < lines[j].attributes.length; n++) {
			if(lines[j].attributes[n].nodeName.toLowerCase() == 'val' ) {
				oData = lines[j].attributes[n].nodeValue;
	        }
			if(lines[j].attributes[n].nodeName.toLowerCase() == 'selected' ) {
				oSelected = lines[j].attributes[n].nodeValue;
	        }
        }
		obj.options[obj.options.length] = new Option(oDisplay, oData, false, oSelected);		
	}
}


// -->
