// Javascript form functions

// Include the namespace tests until we've ensured that all pages including this script also
// include /codelib/js/ilr/ilr.js and /codelib/js/ilr/util/scriptLoader.js
// RY 9/17/07 Script loading strategy completely bombs in IE6
/*
if (typeof ILR != "undefined") {
	var requiredScripts = [
		ILR.js.ilr + "dom/dom.js",
		ILR.js.ilr + "util/array.js"
	];	


	if (typeof ILR.util != "undefined" && typeof ILR.util.scriptLoader != "undefined") {
		ILR.util.scriptLoader.loadScriptsOnce(requiredScripts);
	}
}
*/

// Return the selected option element of a single select element
// el = element or element id
function getSelected(el) {

	return getElement(el).options[el.selectedIndex];
}

// Return the text of the selected option element of a single select element
// el = element or element id
function getSelectedText(el) {
	
	return getSelected(el).text;
}

// Set radio buttons/checkboxes to their default checked state. 
function setDefaultChecked(el) {

	if (el.length !== undefined) {
		for (var i = 0 ; i < el.length; i++) {
			el[i].checked = el[i].defaultChecked;
		}	
	}
	// A single checkbox
	else {
		el.checked = el.defaultChecked;
	}
}

// Return an array of all form fields inside divs
// divs is a single div element, the id of a single div element, or an array of div elements/ids
function getFormFields(divs) {

	var div, 
		fields = [],
		i;
	
	divs = toArray(divs);
	
	for (i = 0; i < divs.length; i++) {
		div = getElement(divs[i]);		
		// Get all the form fields inside div
		fields = joinNodeLists(fields, div.getElementsByTagName("input"), div.getElementsByTagName("select"), div.getElementsByTagName("textarea"));
	}
	return fields;
}

var resetForms = function() {
		
	var i, j, el, forms;
	
	for (i = 0; i < arguments.length; i++) {
		el = getElement(arguments[i]);
		forms = el.getElementsByTagName("form");
		for (j = 0; j < forms.length; j++) {
			forms[j].reset();
		}
		// This function does its own loop on the forms inside the element passed in.
		if (typeof ILR.form.validation.clearErrors != "undefined") {
			ILR.form.validation.clearErrors(arguments[i]);
		}
	}	
};

/* Remove the following functions and use Form.reset() and resetForms() instead. */

// Reset form element e to its default value
function reset(e) {

	// Text input and textareas, file input
	if (/^(text|file)/.test(e.type)) {
		e.value = e.defaultValue;
	}
	else if (e.type == "select-one") {
		// If defaultSelected not set explicitly, it's 0
		e.selectedIndex = e.defaultSelected;
	}
	/* TO DO
	else if (e.type == "select-multiple") {
	
	} */
	else if (e.type == "radio" || e.type == "checkbox") {
		setDefaultChecked(e);
	}
	
}

// Clear input in form div(s) divs
function clearInput(divs) {

	clearFields(getFormFields(divs));	
}

// Clear all form values. Used, for example, for links that go "back" in an Ajax app 
// where previous form input should be cleared - e.g., "New Search."
function clearForm(formId) {

	clearFields(document.getElementById(formId).elements);
}

function clearFields(fields) {

	for (var i = 0; i < fields.length; i++) {
		reset(fields[i]);
	}
}

/** @description Clear all form fields contained in element el of their input, and clear any
 * error divs. Used, for example, for links that go "back" in an Ajax app when previous
 * input and/or error messages should be cleared from the form(s).
 * @method resetFormFields
 * @param {HTMLElement|String} el A list of containing elements
 * @ return {void}
 */
var resetFormFields = function(){
	
	var i;
	for (i = 0; i < arguments.length; i++) {
		clearFields(getFormFields(arguments[i]));
		if (typeof ILR.form.validation.clearErrors != "undefined") {
			ILR.form.validation.clearErrors(arguments[i]);
		}
	}		
};
/******************************** end remove functions **/

// Set property p of form element f to value v for validation routine,
// where properties of radio buttons/checkboxes are defined on the 0th element.
function setFormFieldProperty(f, p, v) {

	// Radio buttons/checkboxes with multiple elements. Single-element
	// checkboxes go to second case. Note that we still need the test
	// of f.type because select elements also have a 0th element.
	if ( (f.type == "radio" || f.type == "checkbox") && f[0] ) {
		f[0][p] = v;   
	}
	else {
		f[p] = v;
	}
}

/**
 * @description Determines whether a member of a form elements array is a true input element: 
 * text input, radio button, checkbox, textarea, or select. Form.element[] also includes
 * fieldsets, submit inputs, and button inputs, and we want to exclude those in looping
 * over true input elements for purposes of form validation, etc.
 * @param {HTMLElement} f
 * @return {Boolean}
 */
function isFormField(e) {
	
	return ( (e.tagName == "INPUT" && 
				(e.type == "text" || e.type == "radio" || e.type == "checkbox" || e.type == "file")) ||
			  e.tagName == "SELECT" ||
		      e.tagName == "TEXTAREA" 
		   );
}

/**
 * @description Return an array of true input elements in a form, using the definition of
 * "true input element" as isFormField() above.
 * @param {String|HTMLElement} f
 * @return {Array}
 */
function getFormInputFields(f) {
	
	var el,
		fields = [], 
		i;
		
	f = getElement(f);
	el = f.elements;
		
	for (i = 0; i < el.length; i++) {
		if (isFormField(el[i])) {
			fields.push(el[i]);
		}
	}
	
	return fields;
}

/**
 * @description Define two mutually exclusive fields which cannot both have a non-empty value. 
 * When one value becomes non-empty, the other is emptied. A more general function would define a set
 * of mutually exlusive values, but requires a loop to clear all other values, so from an implementation
 * point of view this function is distinct: we can eliminate the loop to achieve a small performance gain.
 * @method defineTwoMutuallyExclusiveFields
 * @param {Array} arr An array of exactly two form input, textarea, or select elements
 * @return {void}
 */
function defineTwoMutuallyExclusiveFields(arr) {
	
	var i; 
	
	if (arr.length != 2) {
		return;
	}			
	
	for (i = 0; i < 2; i++) {
		YAHOO.util.Event.addListener(arr[i], "change", function(event, args) {
			
			var arr = args.array,
				index = args.index;
				
			if (arr[index].value) {
				arr[(index+1) % 2].value = '';
			}
			
		}, { array : arr, index :i });
	}
}

/**
 * @description Return number of checkbox elements selected
 * @method countCheckedOptions
 * @param {HTMLElement|String} form The form containing the radio/checkbox elements
 * @param {String} elementName The name of the checkbox elements
 * @return {Integer} The number of checkboxes selected
 */
function countCheckedOptions(form, elementName) {
	
	var i, 
		checkboxCount,
		checkedCount = 0;
	
	if (YAHOO.lang.isString(form))	{
		form = YAHOO.Util.Dom.get(form);
	}
		
	checkboxCount = form[elementName].length;
	
	for (i = 0; i < checkboxCount; i++) {
		// return i + 1, not i, since i == 0 if the first element is selected
		if (form[elementName][i].checked) {
			checkedCount++;
		}
	}
	
	return checkedCount;
}

/**
 * @description Return index of radio button selected, or -1 if none selected
 * @method getSelectedRadio
 * @param {HTMLElement|String} form The form containing the radio elements
 * @param {String} elementName The name of the radio elements
 * @return {Integer} The index of the selected radio button; -1 if none selected
 */
function getSelectedRadio(form, elementName) {

	var i,
		selectedRadio = -1;

	if (YAHOO.lang.isString(form))	{
		form = YAHOO.Util.Dom.get(form);
	}
				
	radioCount	= form[elementName].length;
	
	for (i = 0; i < radioCount; i++) {
		if (form[elementName][i].checked) {
			selectedRadio = i;
			break;
		}
	}
	
	return selectedRadio;	
}
