/** 
* Copyright 2006 massimocorner.com
* @author      Massimo Foti (massimo@massimocorner.com)
* @version     0.2.0, 2006-06-18
* @require     tmt_core.js
*/

if(typeof(tmt) == "undefined"){
	alert("Error: tmt.core JavaScript library missing");
}

function tmt_formFactory(){
	var obj = new Object();	

	// Check a set of form fields (radio or checkboxes)
	obj.checkFields = function(){
		tmt.setNodeAttribute(arguments, "checked", true);
	}

	// Uncheck a set of form fields (radio or checkboxes)
	obj.uncheckFields = function(){
		tmt.setNodeAttribute(arguments, "checked", false);
	}

	// Toggle the checked attribute on a set of form fields. If it's true it set it to false and viceversa
	obj.toggleCheckFields = function(){
		for(var i=0; i<arguments.length; i++){
			var fieldNode = tmt.get(arguments[i]);
			if(fieldNode){
				fieldNode.checked ? fieldNode.checked = false : fieldNode.checked = true;
			}
		}
	}

	// Disable a set of form fields
	obj.disableFields = function(){
		tmt.setNodeAttribute(arguments, "disabled", true);
	}

	// Enable a set of form fields
	obj.enableFields = function(){
		tmt.setNodeAttribute(arguments, "disabled", false);
	}

	// Toggle the disabled attribute on a set of form fields. If it's true it set it to false and viceversa
	obj.toggleEnableFields = function(){
		for(var i=0; i<arguments.length; i++){
			var fieldNode = tmt.get(arguments[i]);
			if(fieldNode){
				fieldNode.disabled ? fieldNode.disabled = false : fieldNode.disabled = true;
			}
		}
	}

	// Return the container <form> of a given node. Return false if the node isn't contained inside a form
	obj.getParentForm = function(startNode){
		var parentObj = startNode.parentNode;
		while(parentObj){
			if(parentObj.tagName.toLowerCase() == "form"){
				return parentObj;
			}
			else{
				parentObj = parentObj.parentNode;
				continue;
			}
		}
		// The field is outside of a form
		return false; 
	}

	// Given an option node, return its value. If no value is available, return its text
	obj.getOptionNodeValue = function(optionNode){
		var optionValue = optionNode.value;
		if(!optionValue){
			optionValue = optionNode.text;
		}
		return optionValue;
	}

	// Return an array of submit button nodes contained inside a given node
	obj.getSubmitNodes = function(startNode){
		var submitArray = new Array();
		var inputNodes = startNode.getElementsByTagName("input");
		for(var i=0; i<inputNodes.length; i++){
			if(inputNodes[i].getAttribute("type").toLowerCase() == "submit"){
				submitArray[submitArray.length] = inputNodes[i];
			}
		}
		return submitArray;
	}

	// Assembles form name/value pairs and return them inside an encoded string
	obj.serializeForm = function(formNode, demoronize){
		var values = new Array();
		for(var i = 0; i < formNode.elements.length; i++){
			var fieldNode = formNode.elements[i];
			// Skip fieldsets and field without name attribute
			if(!fieldNode || !fieldNode.name || fieldNode.tagName.toLowerCase() == "fieldset"){
				continue;
			}
			var fieldName = encodeURIComponent(fieldNode.name);
			var fieldType = fieldNode.type.toLowerCase();
			// Handle different kind of fields
			switch(fieldType){
				case "select-multiple":
					for(var j = 0; j < fieldNode.options.length; j++){
						if(fieldNode.options[j].selected){
							values.push(fieldName + "=" + encodeURIComponent(obj.getOptionNodeValue(fieldNode.options[j])));
						}
					}
					break;
				case "select-one":
					for(var k = 0; k < fieldNode.options.length; k++){
						if(fieldNode.options[k].selected){
							values.push(fieldName + "=" + encodeURIComponent(obj.getOptionNodeValue(fieldNode.options[k])));
							break;
						}
					}
					break;
				// Radio and checkboxes get handled the same way
				case "radio":
				case "checkbox":
					if(fieldNode.checked){
						values.push(fieldName + "=" + encodeURIComponent(fieldNode.value));
					}
					break;
				// Skip reset
				case "reset":
					break;
				// Skip buttons
				case "button":
					break;
				// default handles all the text fields
				default:
					var fieldValue = fieldNode.value;
					// Get rid of Word's garbage if required
					if(demoronize){
						fieldValue = obj.stringDemoronizer(fieldNode.value);
					}
					values.push(fieldName + "=" + encodeURIComponent(fieldValue));
					break;
			}
		}
		return values.join("&");
	}

	// Replace MS Word's non-ISO characters with plausible substitutes
	obj.stringDemoronizer = function stringDemoronizer(str){
		str = str.replace(new RegExp(String.fromCharCode(710), "g"), "^");
		str = str.replace(new RegExp(String.fromCharCode(732), "g"), "~");
		// Evil "smarty" quotes
		str = str.replace(new RegExp(String.fromCharCode(8216), "g"), "'");
		str = str.replace(new RegExp(String.fromCharCode(8217), "g"), "'");
		str = str.replace(new RegExp(String.fromCharCode(8220), "g"), '"');
		str = str.replace(new RegExp(String.fromCharCode(8221), "g"), '"');
		// More garbage
		str = str.replace(new RegExp(String.fromCharCode(8211), "g"), "-");
		str = str.replace(new RegExp(String.fromCharCode(8212), "g"), "--");
		str = str.replace(new RegExp(String.fromCharCode(8218), "g"), ",");
		str = str.replace(new RegExp(String.fromCharCode(8222), "g"), ",,");
		str = str.replace(new RegExp(String.fromCharCode(8226), "g"), "*");
		str = str.replace(new RegExp(String.fromCharCode(8230), "g"), "...");
		str = str.replace(new RegExp(String.fromCharCode(8364), "g"), "€");
		return str;
	}

	return obj;
}

tmt.form = {};

// Global object storing API methods
tmt.form = tmt_formFactory();