// This javascript object will extract the name/value pairs for form elements on the page
// If name='xxx'	is not coded for a given item, then it is ignored.
// If value='xxx'	is not coded for a given item, then it is ignored.
// If the item is disabled, it is ignored.
// Items:
//	checkbox
//	radio buttons
//	text
//	textarea
//	select
//
// Buttons are NOT returned.
//
// public methods 
//	addForm			- takes a form name and adds it to the list of forms to process
//	addForms		- takes a comma delimited string of form names to process
//	addElement		- takes an element name and adds it to the list of elements to process
//	genQueryString	- returns a list of name=value pairs in querystring format
//	processForms	- handles all forms on the page
//	processForm		- handles a single form (eg. document.getElementById("formname"))
//
// example usage:
//		var formObj = new FormProcessor();
//		formObj.processForms();
//		alert(formObj.genQueryString());

function FormProcessor() {
	// private members
	var arRBs		= new Array();	// array of RBs already handled
	var oForm;						// current form being processed

	var arNames1	= new Array();	// element names/values in associative array
	var arNames2	= new Array();	// element names/values in indexed array
	
	var arFormsIn	= new Array();	// form name filter (include forms)
	var arFormsEx	= new Array();	// form name filter (exclude forms)
	var arElements	= new Array();	// element name filter


	// public method pointers
	this.getElement		= getElement;
	this.getElements	= getElements;
	this.addForm		= addForm;
	this.setForms		= setForms;
	this.addElement		= addElement;
	this.genQueryString = genQueryString;
	this.processForms	= processForms;
	this.processForm	= processForm;

	// ************************************
	// public methods
	// ************************************
	function getElement(elName, elDefault) {
		var value=arNames1[elName];
		if (value==null){value=elDefault;}
	
		return value;
	}

	function getElements() {
		return(arNames2);
	}
	
	function addForm(pForm, pInclude) {		// Add a formname to be processed
		if (pInclude)	{	arFormsIn.push(pForm); }
		else			{	arFormsEx.push(pForm); }
	}

	function setForms(pForms) {		// Add multiple formnames to be processed
		arForms = pForms.split(",");
	}

	function addElement(pEl) {		// Add specific elements to be processed
		arElements.push(pEl);
	}

	function genQueryString() {		// Generate a querystring based on the extracted name=value pairs
		var qstr = "";
		for (var i=0; i<arNames2.length; i++) {
			qstr += "&" + arNames2[i][0] + "=" + arNames2[i][1];
		}
		return(encodeURI(qstr));
	}

	function processForms() {
		arRBs.length = 0;
		var docforms = document.forms;
		var formstr = "";
		for (var form=0; form<docforms.length; form++ )	{
			processForm(docforms[form]);
		}
	}

	function processForm(form) {
		oForm = form;							// remember the form we are processing
	
		if (!formnameOK(form.id)) return;

		var formstr = "";
		var els = form.elements;

		for (var el=0; el<els.length; el++)	{
			processElement(els[el]);
		}
	}


	// ************************************
	// private methods
	// ************************************
	function formnameOK(formName) {
		// Include list has priority over Exclude list
		// The caller should only every Include or Exclude forms... not both.

		// Check if formname is in the include list
		if (arFormsIn.length != 0) {
			var OK = false;
			for (var form=0; form<arFormsIn.length; form++ ) {
				if (arFormsIn[form] == formName)	{
					OK = true;
					break;
				}
			}
			return(OK);
		}
		// Include list is empty...

		// Check if formname is in the exclude list
		if (arFormsEx.length != 0) {
			var OK = true;
			for (var form=0; form<arFormsEx.length; form++ ) {
				if (arFormsEx[form] == formName)	{
					OK = false;
					break;
				}
			}
			return(OK);
		}

		// Both Include and Exclude lists are empty... OK
		return(true);
	}

	function elementOK(elementName) {
		if (arElements.length == 0) return(true);
		
		var found = false;
		for (var el=0; el<arElements.length; el++ )	{
			if (arElements[el] == elementName)	{
				found = true;
				break;
			}
		}
		return(found);
	}

	function rbnameProcessed(rbName) {
		if (arRBs.length == 0) return(false);
		
		var found = false;
		for (var rb=0; rb<arRBs.length; rb++ )	{
			if (arRBs[rb] == rbName) {
				found = true;
				break;
			}
		}
		return(found);
	}


	function processElement(pEl) {
		//alert(els[i].name + els[i].getAttribute("type"));
		if (!pEl.name) return;			//Must have a name...
		if (!elementOK(pEl.name)) return;
		
		var eltype = pEl.getAttribute("type");
		//alert(eltype);
		if		(eltype == "radio")				{ handleRB(pEl.name); }
		else if (eltype == "checkbox")			{ handleCB(pEl);	}
		else if (eltype == "select-multiple")	{ handleSM(pEl); }
		else if (eltype == "button" || eltype == "submit") {} // don't capture buttons 
		else {
			if (pEl.value) {
				saveNameValuePair(pEl.name, pEl.value);
			}
		}
	}

	function handleCB(el) {
		// netscape does not have a default value for a checkbox
		// ie default value is 'on'
		// therefore.... always code value='xxx' on a checkbox
		if (el.checked) {
			saveNameValuePair(el.name, el.value);
		}
	}

	function handleRB(rbName) {
		if (rbnameProcessed(rbName)) return;		// already processed?.... exit

		var evalstr = "oForm." + rbName + ".length";
		var numOpts = eval(evalstr);
		var j;
		for (j=0; j<numOpts; j++) {
			evalstr = "oForm." + rbName + "[j].checked";
			if (eval(evalstr)) { 
				evalstr = "oForm." + rbName + "[j].value";
				if (eval(evalstr)) 
					lValue = eval(evalstr);
				else
					lValue = j;
				break; 
			}
		}
		arRBs.push(rbName);		//Add name to processed array

		saveNameValuePair(rbName, lValue);
	}

	function handleSM(el) {
		// A select multiple must build a CSV list of selected items as the VALUE
		var i;
		var val = "";

		for (i=0; i<el.childNodes.length; i++) {
			if (el.childNodes[i].selected) {
				if (val!="") { val += ","; }
				val += el.childNodes[i].value;
			}
		}

		saveNameValuePair(el.name, val);
	}

	function saveNameValuePair(pName, pValue) {
		var lName = pName.toLowerCase();

		// Save to associative array for direct (name) access
		arNames1[lName] = pValue;

		// Save to indexed array for iterative access
		arNames2.length += 1;
		arNames2[arNames2.length-1] = new Array(2);	
		arNames2[arNames2.length-1][0] = lName;
		arNames2[arNames2.length-1][1] = pValue;
	}
}