
			// ============================================================================================
			//
			//          A j a x   S u b s :   In conjunction with the zXML routines that handle XHR requests,
			//				  these subroutines handle common asynchronous Javascript calls.
			//
			//
			//    Original author unknown; modified & enhanced for secure, flexible callbacks at the KSU Educational Communications Center
			//
			//    David Noel Pedergnana, Multimedia Designer
			//
			//    www.ksu.edu/ecc       *       dnp@ksu.edu
			//
			//    © MMVII D.N.B. Pedergnana
			//    
			// ============================================================================================


function encodedPair(param, val) {				// URI Encodes a single parameter/value pair for use in 
								//   an array: ("this param", 3) becomes "this%20param=3"
	var encParam = encodeURIComponent(param);		//   Called by the method getReqBody
	encParam += "=";
	encParam += encodeURIComponent(val);			// * Using an array instead of combining strings avoids memory leaks
	return encParam;
}


function simplePair(param, val) {				// For Perl POST commands, does simple pairing: param=val

	encParam = param + "=" + val;
	return encParam;
}


//function submitOnReturn(e, formID, sendReqTarget, hideID) {		// Accepts a keypress event, formID, and sendReq targetID (or method) as input, and submits the form if [RETURN] or [ENTER] were pressed
//	var keynum;														//	If sendReqTarget = 'e' : Interpret the formID as javascript on pressing [ENTER]
//																	//	hideID: optional dialog box to hide when [ESC] is pressed
//
//	if (window.event) {			// IE
//		  keynum = e.keyCode;
//	} else if (e.which) {		// Netscape/Firefox/Opera
// 		  keynum = e.which;
//	}
//
//	if (keynum == 13 || keynum == 3) {
//		if (sendReqTarget == 'e') {			// Evaluate the code as javascript
//			eval(formID);
//		} else {
//			sendReq(formID, sendReqTarget);
//		}
//	
//	}
//
//	if (keynum == 27) {						// [ESC] : Hide the dialog
//		if (hideID) {
//			top.hideObject(hideID);	
//		}
//	}
//}

function submitOnReturn(e, formID, sendReqTarget, hideID) {		// Accepts a keypress event, formID, and sendReq targetID (or method) as input, and submits the form if [RETURN] or [ENTER] were pressed
	var keynum;														//	If sendReqTarget = 'e' : Interpret the formID as javascript on pressing [ENTER]
	var Esc;																//	hideID: optional dialog box to hide when [ESC] is pressed
	
		// Capture the keypress value and define the Esc key code


 	var keynum  = (window.event) ? event.keyCode : e.keyCode;
 
    var Esc = (window.event) ? 27 : e.DOM_VK_ESCAPE;	 // Capture keypress event for either MSIE : Firefox
	
	if (keynum == Esc) {								// [ESC] : Hide the dialog
		if (hideID) {
			hideObject(hideID);	
		}
	}

	if (keynum == 13 || keynum == 3) {
		if (sendReqTarget == 'e') {			// Evaluate the code as javascript
			eval(formID);
		} else {
			sendReq(formID, sendReqTarget);
		}
	
	}
}



function getReqFormBody(formID) {				// Accepts formID reference as input and outputs a 
												//    URI-encoded parameter string that can be sent
	var paramList = new Array();				//    via XHR post. Called by the method sendReq
	var formObj = getObjectByID(formID);

	// Get selected form element types and append them to the parameter list:

	for(var i=0; i < formObj.elements.length; i++) {

		var fieldObj = formObj.elements[i];		// Get the current field object

		switch (fieldObj.type) {

			case "button":			// omit buttons
			case "submit":
			case "reset":
				break;

			case "checkbox":		// include checkboxes and radio buttons only if selected
			case "radio":
				if (!fieldObj.checked) {
					break;
				}

			case "text":			// include text and hidden fields
			case "hidden":
				paramList.push(encodedPair(fieldObj.name, fieldObj.value));
				break;

			case "password":		// dpEncode any password fields (note: 16 character limit!)
				paramList.push(encodedPair(fieldObj.name, dpEncode(fieldObj.value) ));
				break;

			default:			// handle dropLists, multiline lists, and other form objects

				switch(fieldObj.tagName.toLowerCase()) {

					case "select":
						paramList.push(encodedPair(fieldObj.name, 
							fieldObj.options[fieldObj.selectedIndex].value));
						break;

					default:
						paramList.push(encodedPair(fieldObj.name, fieldObj.value));
						break;			
				}
		}
	}
	return paramList.join("&");
}


function sendReq(formID, targetID, syncReqFlag) {				// Accepts formID and a targetID as input and:
																//	syncReqFlag: if true, sends a synchronous request (i.e., halts javascript execution while waiting for a response)
	if (syncReqFlag) {
		var async = false;
	} else {
		var async = true;
	}
	
	var formObj = getObjectByID(formID);			//   (1) submits the designated form
	var params = getReqFormBody(formID);			//   (2) displays the resulting XHR response via targetID,
													//       which is usually a <span>, <div>, or form object
	var xhrObj = zXmlHttp.createRequest();			//       (assuming one is returned)
	xhrObj.open("post", formObj.action, async);
	
	xhrObj.setRequestHeader("Content-Type", "application/x-www-form-urelencoded");

	xhrObj.onreadystatechange = function () {

		if (xhrObj.readyState == 4) {							 // xhr task complete

			if (xhrObj.status == 200 || xhrObj.status == 304) {	 	// Status OK: 200 = response not cached
										 							//            304 = reply cached from browser
				if (targetID) {	
										 // write result to target span, div or obj

					updatePage(targetID, xhrObj.responseText);
				}
			} else {
				updatePage(targetID, 'Error: ' + xhrObj.statusText);
			}
		}
	}
	xhrObj.send(params);
}

function updatePage(targetID, text) {				// Accepts targetID and xhrObj response text as input
								//   and displays the response through the target object
								//   (a div, span, or form object)
	
		// Check to see if javascript has been returned against expectations:

	var jsFlag        = /<js> = /;
	var jsFlagPos     = text.search(jsFlag);

	if (jsFlagPos > -1) {

		var lastChar = text.length - 4;							// Expects to find 4 extra space or garbage chars at the end & removes them
		var js = text.substring(jsFlagPos + 7, lastChar);		// <js>[space]=[space]  is the unique opening delimiter required for <js> = statements
		text   = text.substring(0, jsFlagPos - 1);
	}

	switch (targetID) {

		case 'eval':

			eval(text);
			break;

		case 'href':
			window.location = text;
			break;

		case 'js':
			// eval(js);
			break;

		case 'refresh':
			location.reload(true);
			break;		

		default:
			var targetObj = getObjectByID(targetID);
			if (targetObj != null) {				// Target object exists: update it

				targetObj.innerHTML = text;			// Is it a span or div?

			} else {								// There is no target object: is it 'href,' 'script,' or 'do nothing'?
				return text;
			}
			break;
	}
	
		// Try executing callbacks last
		
	if (js && js != 1) {

		eval(js);
	}
}



		// ============================================================================================

		// 	Revised Core Ajax Functions 04/02/09 (As first implemented at www.hsidea.org)
		
		// ============================================================================================
		
		
function submitOnReturn2(e, formID, sendFormTarget, hideID) {		// Accepts a keypress event, formID, and sendFormTarget ID (or
																	// callback method) as input, and submits the form if [RETURN]
																	// or [ENTER] are pressed
	var keynum;														//	If sendFormTarget = 'e' : Interpret the formID as javascript
																	// on pressing [ENTER]
	var Esc;														//	hideID: optional dialog box to hide when [ESC] is pressed
	
		// Capture the keypress value and define the Esc key code


 	keynum  = (window.event) ? event.keyCode : e.keyCode;
    Esc = (window.event) ? 27 : e.DOM_VK_ESCAPE;	 				// Capture keypress event for either MSIE : Firefox
	
	if (keynum == Esc) {								// if pressed key = [ESC] : Hide the dialog
		if (hideID) {
			hideObject(hideID);	
		}
	}

	if (keynum == 13 || keynum == 3) {
		if (sendFormTarget == 'e') {					// Treat the sendFormTarget as javascript
			eval(formID);
		} else {
			sendForm(formID, sendFormTarget);
		}
	
	}
}


function getReqFormBody2(formID) {				// Accepts formID reference as input and outputs a URI-encoded parameter string
												//    that can be sent via XHR post. Called by sendForm()

	var paramList = new Array();				// * Using an array instead of combining strings avoids memory leaks
	var formObj = getObjectByID(formID);

	if (formObj == '') { alert('* getReqFormBody2 Error: No '+formID); }	// TEMPORARY ERROR MSG


	// Get selected form element types and append them to the parameter list:

	for(var i=0; i < formObj.elements.length; i++) {

		var fieldObj = formObj.elements[i];		// Get the current field object

		switch (fieldObj.type) {

			case "button":			// omit buttons
			case "submit":
			case "reset":
				break;

			case "checkbox":		// include checkboxes and radio buttons only if selected
			case "radio":
				if (!fieldObj.checked) {
					break;
				}

			case "text":			// include text, hidden, and password fields
			case "hidden":
			case "password":
				paramList.push(encodedPair(fieldObj.name, fieldObj.value));
				break;

			default:			// handle dropLists, multiline lists, and other form objects

				switch(fieldObj.tagName.toLowerCase()) {

					case "select":
						paramList.push(encodedPair(fieldObj.name, 
							fieldObj.options[fieldObj.selectedIndex].value));
						break;

					default:
						paramList.push(encodedPair(fieldObj.name, fieldObj.value));
						break;			
				}
		}
	}
	return paramList.join("&");
}


function sendForm(formID, targetID, callbackFunc, syncReqFlag) {	// Ajax call that submits a specified form and:

																	//  	(1) displays the resulting XHR response via targetID
																	//		    --an optional <span>, <div>, or form object-- OR

																	//		(2) does the requested action and executes a callback

			//	callbackFunc: the name of a client-side function to send echoed parameters to
			//	syncReqFlag: if true, sends a synchronous request (i.e., halts javascript execution while waiting for a response)

	if (syncReqFlag) {
		var async = false;
	} else {
		var async = true;
	}

	var formObj = getObjectByID(formID);			
	var params = getReqFormBody2(formID);

	var xhrObj = zXmlHttp.createRequest();
	xhrObj.open("post", formObj.action, async);
	
	xhrObj.setRequestHeader("Content-Type", "application/x-www-form-urelencoded");
	xhrObj.onreadystatechange = function () {

		if (xhrObj.readyState == 4) {							 // xhr task complete

			if (xhrObj.status == 200 || xhrObj.status == 304) {						// Status OK: 200 = response not cached
										 											//            304 = reply cached from browser
					processResponse(targetID, callbackFunc, xhrObj.responseText);
			} else {
				alert('sendForm Error: ' + xhrObj.statusText );
			}
		}
	};
	xhrObj.send(params);
}

function encodeData(oData) {	// Loops through an object array and creates a URL-encoded string

	var paramList = new Array();

	for (var key in oData) {
		paramList.push( encodedPair(key, oData[key]) );
	}

	return paramList.join("&");
}


function sendData(url, targetID, callbackFunc, oData, syncReqFlag) {		// Accepts a url, targetID, and data object as input 
																//	Sends the data via post to the specified script (url) and
																// displays the resulting XHR response via targetID

			//	syncReqFlag: if true, sends a synchronous request (i.e., halts javascript execution while waiting for a response)

	if (syncReqFlag) {
		var async = false;
	} else {
		var async = true;
	}

	var params = encodeData(oData);	

	var xhrObj = zXmlHttp.createRequest();
	xhrObj.open("post", url, async);
	
	xhrObj.setRequestHeader("Content-Type", "application/x-www-form-urelencoded");
	xhrObj.onreadystatechange = function () {

		if (xhrObj.readyState == 4) {							 // xhr task complete

			if (xhrObj.status == 200 || xhrObj.status == 304) {	 // Status OK: 200 = response not cached
																 //            304 = reply cached from browser
					processResponse(targetID, callbackFunc, xhrObj.responseText);
			} else {
				alert('sendData Error: ' + xhrObj.statusText );
			}
		}
	};
	xhrObj.send(params);
}

function processResponse(targetID, callbackFunc, text) {		// Accepts targetID, a function name, and xhrObj response text
																//   and puts the response in a target div, span, or other object.

									// Response text has two parts: HTML |,| Callback Parameter 1 |,| Callback Parameter 2...
									// If callbackFunc is named and parameters are returned, sends data via the specified callback

	var codeStart = text.indexOf('var js = ');
	if ( codeStart > -1 ) {												// response text includes a callback

		var lastChar          = text.length - 1;
		if (codeStart > 0 && targetID) {								// 		the callback is precdeded by HTML

			var HTML              = text.substring(0, codeStart-1);
			var responseArguments = text.substring(codeStart);
		} else {														//		the callback isn't preceded by HTML
			var responseArguments = text;
		}
		
	} else {
		var HTML = text;												// no callback in response text
	}

	if (HTML && targetID) {
		
			// Handle special cases: targetID = 'refresh' or 'refreshData'
	
		if (targetID == 'refresh') {
			location.reload(true);
		} else if (targetID == 'refreshData') {
			top.getObjectByID('dataFrame').contentWindow.location.reload(true);
		} else {
		
			setText(targetID, HTML);		// Populate the target object with HTML received from the server
		}
	}

	if (responseArguments) {				// Send responseArguments to the callbackFunc or handle the callback

		var js = responseArguments;

		var codeHeader = /var js = /;

		if (js.search(codeHeader) == 0) {		// Valid header: start parsing code

			var lastChar = js.length - 4;		// Remove garbage chars
			js = js.substring(13, lastChar);	// Strip the opening delimiter required for interpreted statements

			if(callbackFunc) {				// Perform the callback (if any)

				var callback = callbackFunc + "(" + responseArguments + ");"
				eval( callback );

			} else {												// No callbackFunc specified: interpret the responseArgument
				eval( js );
			}
		}
	}
}



	// ============================================================================================

	// 	Common Ajax Calls to PHP Scripts 04/02/09 (As implemented at www.hsidea.org)
	
	// ============================================================================================


//function fetch(type, id, dialog, focusField, targetID, param1, param2) {	// Ajax call to retrieve data for a form or display
//														// 	dialog:   optional dialog to show after populating form fields
//														// 	focusField: optional field to place cursor in after populating
//														//	targetID:   optional div or span to populate with returned text 
//														//	param1:     optional custom parameter to send additional data
//														//	param2:     optional custom parameter #2
//	var url          = 'subs-fetch.php';
//	var callbackFunc = '';
//	var syncReqFlag  = '';
//	var oData = {
//		fetchID     : id,
//		fetchType   : type,
//		fetchDialog : dialog,
//		fetchFocus  : focusField,
//		param1      : param1,
//		param2      : param2
//	};
//
//	sendData(url, targetID, callbackFunc, oData, syncReqFlag);
//}

function fetch(type, id, dialog, focusOn, target) {		// Performs an Ajax call using the fetchForm to retrieve data
													// fetchDialog: optional dialog to show after populating the form fields
													// fetchFocus:  optional field to place cursor in after populating
													// target:      if set, checks to see that this ID exists before trying to fetch

	if (getValue('fetchType')) {	// Possible request conflict (simultaneous fetch attempts): delay this request
	
		var cmd = "fetch('" + type + "', " + id + ", '" + dialog + "', '" + focusOn + "', '" + target + "');" ;
		setTimeout(cmd, 150);
	}
	
	if (target) {			// Confirm that ID exists before attempting fetch

		if (!getObjectByID(target) ) {
			var cmd = "fetch('" + type + "', " + id + ", '" + dialog + "', '" + focusOn + "', '" + target + "');" ;
			setTimeout(cmd, 150);
			return;
		}
	}
	setValue('fetchType', type);
	setValue('fetchID', id);
	setValue('fetchDialog', dialog);
	setValue('fetchFocus', focusOn);
	sendReq('fetchForm', 'js');
}


function update(type, id, fieldList, dialog, doRefresh) {		// Ajax call to update the database via updateForm
										// 	type:      identifies which table and columns to update on the server
										// 	id:        id of the row to update
										// 	fieldList: a series of field ids to send for updating
										//	dialog:    optional dialog to hide after updating
										//	doRefresh: optional flag to specify page refresh after updating (values: 'refresh', '')
	setValue('updateType', type);
	setValue('updateID', id);

		// Refer to the enclosing form when getting radio button values

	if (type == 'student' || type == 'gender') {
		var radioForm = 'studentListForm';	
	} else {

		var radioForm = '';	
	}
	
	
	var valueList = joinValues(fieldList, radioForm);

	setValue('updateV', valueList);
	sendReq('updateForm', doRefresh);
	
	if (dialog) {
		hideObject(dialog);
	}
}


function del(type, id) {			// Ajax call to delete an item. Only valid types will be deleted by users of admin or partner status

	setValue('deleteType', type);
	setValue('deleteID', id);
	sendReq('deleteForm', 'js');
}

function simpleFetch(type, focusField, targetID, param1, param2) {	// Ajax call to retrieve data for display... has fewer parameters
														// 	focusField: optional field to place cursor in after populating
														//	targetID:   optional div or span to populate with returned text 
														//	param1:     optional custom parameter to send additional data
														//	param2:     optional custom parameter #2
	var url          = 'subs-adminSimpleFetch.php';
	var callbackFunc = '';
	var syncReqFlag  = '';
	var oData = {
		fetchType   : type,
		fetchFocus  : focusField,
		param1      : param1,
		param2      : param2
	};

	sendData(url, targetID, callbackFunc, oData, syncReqFlag);
}

function dpEncode(inputString) {

	if (inputString.length > 16) {
		inputString = inputString.substr(0, 16);
	}

	var keyString = 'givhPo65ymXSzuW';
	var legalChars = 'vWhPo65yzugmXSiRC.1D80@ZepGMIqUOQB7Ear-fYlA 2tksbnw9Vxd4KN3Tj_FcHLJ';
	
	var thisChar, thisCharIndex, codedChar, keyChar, keyCharIndex
	var keyCharPos = 0;
	var charCount = 0;		// Counter that notes the output string length. Result is always 16 chars + one char that stores the actual string length (outputString is padded to 16 chars)
	var outputString = '';


		// Encode each character of the inputString

	for (var n=0; n < inputString.length; n++) {

		thisChar = inputString.charAt(n);
		thisCharIndex = legalChars.indexOf(thisChar);

		keyChar = keyString.charAt(keyCharPos);
		keyCharIndex = legalChars.indexOf(keyChar);

		codedChar = thisCharIndex + keyCharIndex + 33;

		outputString += String.fromCharCode(codedChar);		

		keyCharPos = keyCharPos + 1;

		if (keyCharPos >= keyString.length) {
			keyCharPos = 0;
		}
	}

		// Pad with random characters until string length = 16 chars

	var stringLength = inputString.length;
	var randIndex;

	for (n = stringLength+1; n < 17; n++) {
		randIndex = Math.floor(Math.random()*legalChars.length);
		outputString += legalChars.charAt(randIndex);
	}

		// Encode the length of the original string and append it to the encrypted string

	keyChar = keyString.charAt(0);
	keyCharIndex = legalChars.indexOf(keyChar);

	var codedStringLength = stringLength + 97;
	outputString = outputString + String.fromCharCode(codedStringLength);

	return outputString;
}

