/**

------------
Installation
------------

Call jaxFormRegister() during your document's onLoad() event to trigger use
of this script for populating form fields.

The advantage to using jaxForm is you can use regular html for your forms
and have a separate xml feed fill in values.  So instead of having your server
side code generate:
	<input type="text" name="firstname" id="firstname" value="Bob" />
you instead would send down
	<input type="text" name="firstname" id="firstname" value="" />
including
	<root><controls_input><key>firstname</key><value>Bob</value></controls_input></root>

Yes, this is more code, but again you get clean separation on the server,
with much improved form templating.

One other big benefit is jaxForm allows us to easily transform various fields
on-the-fly.  For example, any text input with the word "date" in the name
is transformed by javascript here into a set of drop down boxes.  Values selected
in the drop downs (<select> tags) are used to repopulate the hidden textbox,
and the text value is what's sent back to the server on form submit.

Some steps you'll need to follow to get jaxForm working properly:

	1) include jax-form.js in your html (via <script> tag),
	2) include common/jax-xmlhttprequest.js  in your html (via <script> tag),
	3) in the body of your html have a tag with an id (preferably a <div> tag),
	4) call jaxFormRegister() on document load,
	5) write a server-side response script that gathers stored content (like
	   from a database) and returns it.

Parameter descriptions for jaxFormRegister():

	contentURL: url that returns an xml feed to populate the slideshow
	
-------
Credits
-------

Authored by Dan Juliano in August of 2005.

*/

var jaxFormCallBack = null;
var YEAR_START = 2005;
var YEAR_COUNT = 10;

function jaxFormRegister(url) {
	jaxFormConvertDateFields();
	xmlRequest(url, null, jaxFormHandleRequest);
}

function jaxFormHandleRequest(xml) {
	var root = xml.getElementsByTagName("root")[0];
	var children = root.childNodes;
	var controls_input = null;
	var controls_select = null;
	var controls_id = null;
	
	for (var i = 0; i < children.length; i++) {
		if (children[i].nodeType == 1) {
			switch (children[i].nodeName) {
				case "controls_input":  controls_input = children[i]; break;
				case "controls_select": controls_select = children[i]; break;
				case "controls_id":     controls_id = children[i]; break;
			}
		}
	}
	
	jaxFormMatchInput(controls_input);
	jaxFormMatchSelect(controls_select);
	jaxFormMatchId(controls_id);
	
	jaxFormUpdateDates();
	
	if (jaxFormCallBack != null) jaxFormCallBack();
}

function jaxFormMatchInput(controls_input) {

	if (controls_input == null) return;
	
	var keys = new Array();
	var values = new Array();
	
	var xmlKeys = controls_input.getElementsByTagName("key");
	var xmlValues = controls_input.getElementsByTagName("value");
	
	if (xmlKeys.length == 0) return;
	
	// Read the xml into a pair of arrays.
	var counter = 0;
	for (var i = 0; i < xmlKeys.length; i++) {
		if (xmlValues[i].childNodes.length > 0) {
			keys[counter] = xmlKeys[i].childNodes[0].nodeValue;
			values[counter] = xmlValues[i].childNodes[0].nodeValue;
			counter++;
		}
	}
	
	// Get the arrays for each type of form input.
	var controls = new Array();
	var inputs = document.getElementsByTagName("INPUT");
	var textareas = document.getElementsByTagName("TEXTAREA");
	var selects = document.getElementsByTagName("SELECT");
	
	// Add tags to the input list.
	var marker = 0;
	for (var i = 0; i < inputs.length; i++) {
		controls[marker++] = inputs[i];
	}
	for (var i = 0; i < textareas.length; i++) {
		controls[marker++] = textareas[i];
	}
	for (var i = 0; i < selects.length; i++) {
		controls[marker++] = selects[i];
	}
	
	// Search for keys that match form <input> and <textarea> tags.
	for (var i = 0; i < controls.length; i++) {
		for (var j = 0; j < keys.length; j++) {
			if (controls[i].name.toLowerCase() == keys[j].toLowerCase()) {
				if (controls[i].nodeName == "TEXTAREA") {
					jaxFormSetTextareaValue(controls[i], values[j]);
					break;
				}
				if (controls[i].type == "text" || controls[i].type == "hidden") {
					controls[i].value = values[j];
					break;
				}
				if (controls[i].type == "radio") {
					if (controls[i].value == values[j]) {
						controls[i].checked = true;
						break;
					}
				}
				if (controls[i].type == "checkbox") {
					if (values[j] == 'Y') {
						controls[i].checked = true;
						break;
					}
				}
				if (controls[i].type == "select-one") {
					var options = controls[i].getElementsByTagName("OPTION");
					for (var k = 0; k < options.length; k++) {
						if (options[k].value == values[j]) {
							options[k].selected = true;
							break;
						}
					}
					break;
				}
			}
		}
	}
}

function jaxFormMatchSelect(controls_select) {
	
	if (controls_select == null) return;
	
	var keys = new Array();
	var values = new Array();
	var captions = new Array();
	var choices = new Array();
	
	var xmlKeys = controls_select.getElementsByTagName("key");
	var xmlValues = controls_select.getElementsByTagName("value");
	var xmlCaptions = controls_select.getElementsByTagName("captions");
	var xmlChoices = controls_select.getElementsByTagName("choices");
	
	if (xmlKeys.length == 0) return;
	
	// Read the xml into a set of arrays.
	counter = 0;
	for (var i = 0; i < xmlKeys.length; i++) {
		keys[counter] = xmlKeys[i].childNodes[0].nodeValue;
		values[counter] = xmlValues[i].childNodes.length > 0 ? xmlValues[i].childNodes[0].nodeValue : -1;
		if (xmlCaptions[i].childNodes.length > 0) {
			captions[counter] = xmlCaptions[i].childNodes[0].nodeValue;
			choices[counter] = xmlChoices[i].childNodes[0].nodeValue;
		} else {
			captions[counter] = "";
			choices[counter] = "";
		}
		counter++;
	}
	
	// Search for keys that match form <select> tags.
	var selects = document.getElementsByTagName("SELECT");
	var option = null;
	var text = null;
	var value = null;
	for (var i = 0; i < selects.length; i++) {
		for (var j = 0; j < keys.length; j++) {
			if (selects[i].name.toLowerCase() == keys[j].toLowerCase()) {
				
				// Create the option drop down list.
				if (captions[j] != "") {

					// Wipe out previous options.
					selects[i].innerHTML = "";
					
					text = captions[j].split("|");
					value = choices[j].split("|");
					for (var k = 0; k < text.length; k++) {
						if ((k == text.length - 1) && text[k] == '' && value[k] == '') break;
						option = document.createElement("OPTION");
						selects[i].options.add(option);
						option.innerHTML = text[k];
						option.value = value[k];
					}
				}
				
				selects[i].value = values[j];
				break;
			}
		}
	}
}

function jaxFormMatchId(controls_id) {
	
	if (controls_id == null) return;
	
	var keys = new Array();
	var values = new Array();
	
	var xmlKeys = controls_id.getElementsByTagName("key");
	var xmlValues = controls_id.getElementsByTagName("value");
	
	if (xmlKeys.length == 0) return;
	
	// Read the xml into a pair of arrays.
	var counter = 0;
	for (var i = 0; i < xmlKeys.length; i++) {
		if (xmlValues[i].childNodes.length > 0) {
			keys[counter] = xmlKeys[i].childNodes[0].nodeValue;
			values[counter] = xmlValues[i].childNodes[0].nodeValue;
			counter++;
		}
	}
	
	// For each key, find a matching element.
	for (var i = 0; i < keys.length; i++) {
		var element = document.getElementById(keys[i]);
		if (element != null) {
			if (element.nodeName == "IFRAME") {
				element.contentWindow.document.body.innerHTML = values[i];
			} else if (element.nodeName == "TEXTAREA") {
				jaxFormSetTextareaValue(element, values[i]);
			} else {
				element.innerHTML = values[i];
			}
		}
	}
}

function jaxFormSetCallBack(onCompletion) {
	jaxFormCallBack = onCompletion;
}

// Date related functions
function jaxFormConvertDateFields() {
	
	var elementDate = null;
	var id = "";
	var name = "";
	var className = "";
	var months = ",January,February,March,April,May,June,July,August,September,October,November,December".split(",");
	var value = "";
	var description = "";
	
	var dates = document.getElementsByTagName("INPUT");
	
	for (var i = 0; i < dates.length; i++) {
		if (dates[i].name.indexOf("date") > -1) {
		
			elementDate = dates[i];
			elementDate.style.visibility = "hidden";
			elementDate.style.display = "none";
			
			name = elementDate.name;
			id = name;
			elementDate.id = name;
			className = elementDate.className;
			
			var html = "\n";
			
			// Create the <select> for month.
			html += "<select id='" + id + "_month' name='" + name + "_month'>";
			for (var j = 1; j < months.length; j++) {
				value = j.toString();
				if (value.length == 1) value = "0" + value;
				html += "<option value='" + value + "'>" + months[j] + "</option>";
			}
			html += "</select>\n";
			
			// Create the <select> for day.
			html += "<select id='" + id + "_day' name='" + name + "_day'>";
			for (var j = 1; j < 32; j++) {
				value = j.toString();
				switch (j) {
					case 1:  description = "1st"; break;
					case 21: description = "21st"; break;
					case 31: description = "31st"; break;
					case 2:  description = "2nd"; break;
					case 22: description = "22nd"; break;
					case 3:  description = "3rd"; break;
					case 23: description = "23rd"; break;
					default: description = j + "th";
				}
				if (value.length == 1) value = "0" + value;
				html += "<option value='" + value + "'>" + description + "</option>";
			}
			html += "</select>\n";
			
			html += ", \n";
			
			// Create the <select> for year.
			html += "<select id='" + id + "_year' name='" + name + "_year'>";
			for (var j = YEAR_START; j < (YEAR_START + YEAR_COUNT); j++) {
				html += "<option value='" + j + "'>" + j + "</option>";
			}
			html += "</select>\n";
			
			html += " at \n";
			
			// Create the <select> for hour.
			html += "<select id='" + id + "_hour' name='" + name + "_hour'>";
			for (var j = 1; j <= 12; j++) {
				value = j.toString();
				if (value.length == 1) value = "0" + value;
				html += "<option value='" + value + "'>" + j + "</option>";
			}
			html += "</select>\n";

			html += " : \n";
			
			// Create the <select> for minute.
			html += "<select id='" + id + "_minute' name='" + name + "_minute'>";
			for (var j = 0; j <= 60; j += 5) {
				value = j.toString();
				if (value.length == 1) value = "0" + value;
				html += "<option value='" + value + "'>" + value + "</option>";
			}
			html += "</select>\n";
			
			// Create the <select> for am / pm.
			html += "<select id='" + id + "_ampm' name='" + name + "_ampm'>";
			html += "<option value='AM'>AM</option>";
			html += "<option value='PM'>PM</option>";
			html += "</select>\n";
			
			var elementNew = document.createElement("SPAN");
			elementNew.className = className;
			elementNew.innerHTML = html;
			elementDate.parentNode.insertBefore(elementNew, elementDate);

			jaxFormDateFieldTrigger(id);
			
			break; // not yet tested with multiple date fields.
		}
	}
}

function jaxFormDateFieldTrigger(id) {
	document.getElementById(id).onchange             = function() { jaxFormUpdateDateSelect(id); };
	document.getElementById(id + "_year").onchange   = function() { jaxFormUpdateDateText(id); };
	document.getElementById(id + "_month").onchange  = function() { jaxFormUpdateDateText(id); };
	document.getElementById(id + "_day").onchange    = function() { jaxFormUpdateDateText(id); };
	document.getElementById(id + "_hour").onchange   = function() { jaxFormUpdateDateText(id); };
	document.getElementById(id + "_minute").onchange = function() { jaxFormUpdateDateText(id); };
	document.getElementById(id + "_ampm").onchange   = function() { jaxFormUpdateDateText(id); };
}

function jaxFormUpdateDateText(id) {
	var year = document.getElementById(id + "_year").value;
	var month = document.getElementById(id + "_month").value;
	var day = document.getElementById(id + "_day").value;
	var hour = document.getElementById(id + "_hour").value;
	var minute = document.getElementById(id + "_minute").value;
	var ampm = document.getElementById(id + "_ampm").value;
	
	if (month.length == 1) month = "0" + month;
	if (day.length == 1) day = "0" + day;
	if (hour.length == 1) hour = "0" + hour;
	if (minute.length == 1) minute = "0" + minute;
	
	document.getElementById(id).value = year + "-" + month + "-" + day + " " + hour + ":" + minute + " " + ampm;
}
function jaxFormUpdateDateSelect(id) {

	// If element does not exist, exit early.
	var element = document.getElementById(id);
	if (!element) {
		return;
	}
			
	var year = 0;
	var month = 0;
	var day = 0;
	var hour = 0;
	var minute = 0;
	var ampm = "";
	
	// If element holds no value (creating a record from scratch) populate date fields with current day.
	if (element.value == "") {
		var today = new Date();
		
		year = today.getFullYear().toString();
		month = (today.getMonth() + 1).toString();
		day = today.getDate().toString();
		hour = "12";
		minute = "00";
		ampm = "PM";
		
		if (month.length == 1) month = "0" + month;
		if (day.length == 1) day = "0" + day;
		
		element.value = year + "-" + month + "-" + day + " " + hour + ":" + minute + " " + ampm;
		
	// If element holds value, parse its value out so we can force the new selects to match it.
	} else {
		var today = element.value;
		year = today.substring(0, 4);
		month = today.substring(5, 7);
		day = today.substring(8, 10);
		hour = today.substring(11, 13);
		minute = today.substring(14, 16);
		ampm = today.substring(17);
	}
	jaxFormMatchOption(id + "_year", year);
	jaxFormMatchOption(id + "_month", month);
	jaxFormMatchOption(id + "_day", day);
	jaxFormMatchOption(id + "_hour", hour);
	jaxFormMatchOption(id + "_minute", minute);
	jaxFormMatchOption(id + "_ampm", ampm);
}

function jaxFormMatchOption(id, match) {
	var element = document.getElementById(id);
	if (element == null) return;
	
	for (var i = 0; i < element.options.length; i++) {
		if (match == element.options[i].value) {
			element.selectedIndex = i;
			break;
		}
	}
}

function jaxFormUpdateDates() {
	var dates = document.getElementsByTagName("INPUT");
	
	for (var i = 0; i < dates.length; i++) {
		if (dates[i].name.indexOf("_date") > -1) {
			jaxFormUpdateDateSelect(dates[i].id);
		}
	}
}

// Some browsers like 'innerHTML', some like 'value'.
function jaxFormSetTextareaValue(textarea, value) {
	
	try {
		textarea.value = value;
		return;
	} catch(e) { }
	
	try {
		textarea.innerText = value;
		return;
	} catch(e) { }
	
	try {
		textarea.innerHTML = value;
		return;
	} catch(e) { }

	try {
		textarea.textContent = value;
		return;
	} catch(e) { }
	
}
