// this object is used to validate form fields


/*

v1.75
	form name fix

v1.74
	fix for response.js.execute

v1.73
	response.js.execute check added
	on error response now accepts redirect

v1.72
	reset previous submit button added to saveCallback
	autosubmit added


v1.71
	"required" fix

v1.70
	if form has no "name" - add unique

v1.69
	added hook "Form_Init_{tagName}_{type}"

v1.68
	pack select values as array

v1.67
	safari BUTTON fix

v1.66
	added support for multiple select

v1.65
	fields will remain disabled if redirect specified

v1.64
	__noload added

v1.63
	- added 2nd parameter to alt attribute

v1.62
	- bLockSubmit argument added to pack function

v1.61
	- fix for single checkbox

v1.6
	- function pack added

v1.5
	- fixed work of multi checkbox
	- form.action replaced with form.getAttribute('name')
	- fix for field.disabled = false

*/


// form management class
var Form = {

	submits: {},
	submit_onclick: {},

	meta: {},

	// initialize forms on page
	init: function(){
		var i, j, a, form, name, field;

		// walk through forms
		for(i=0; i<document.forms.length; i++)
		{
			form = document.forms[i];
			name = form.getAttribute('name');

			// skip forms with "onsubmit" defined
			if(!form.onsubmit && (form.className.indexOf('noinit')<0))
			{
				if(!name)
				{
					name = uid();
					form.setAttribute('name', name);
				}

				Form.submits[name] = null;


				for(var onclick in Form.submit_onclick)
				{
					if(onclick.match('^'+name+'__.*'))
					{
						Form.submit_onclick[onclick] = null;
					}
				}


				// add "onsubmit" handler
				form.onsubmit = Form.save;
				form.onreset = Form.reset;

				// walk through all fields on form
				for(j=0; j<form.elements.length; j++)
				{
					field = form.elements[j];

					if(field.name)
					{
						a = field.alt ? field.alt.split('|') : [''];
						Form.meta[name+'_'+field.name] = a;
						field.alt = a[0];
					}

					// and initialize them
					Form.Field.init(field);
					Hook.Exec('Form_Init_'+field.tagName.toLowerCase()+(field.type?'_'+field.type.toLowerCase():''), false, field);
				}

				// safari BUTTON fix
				if(_safari)
				{
					a = _GT('BUTTON');
					for(j=0; j<a.length; j++)
					{
						if(a[j].form.name == name)
						{
							Form.Field.init(a[j]);
						}
					}
				}
			}

			if(form.className.indexOf('autosubmit') > 0)
			{
				if(form.onsubmit)
				{
					form.onsubmit();
				}else{
					form.submit();
				}
			}
		}
	},



	// pack form data and send to server via RPC
	save: function(){
		var data;

		data = Form.pack(this, true);

		data['__form'] = this.attributes ? this.attributes['name'].value : this.getAttribute('name');

		// send data to server
		rpc.send(data, Form.saveCallback, this.getAttribute('action'), false, this.method.toUpperCase()=='GET'?true:false);

		// prevent normal form submit
		return false;
	},



	// pack form field values into hash
	pack: function(form, bLockSubmit){
		var i, j, bAdd, data = [], value, field, multi = {}, tag;


		for(i=0; i<form.elements.length; i++)
		{
			bAdd = true;

			field = form.elements[i];

			if(!field.name)
			{
				continue;
			}

			var multi_count = form.elements[field.name].length;

			// check if this is valid element
			if(field.name && field.tagName)
			{
				value = field.value;
				tag = field.tagName.toUpperCase();

				// get value of more complex fields
				switch(tag)
				{
					case 'SELECT':
						value = '';
						value = [];

						for(j=0; j<form.elements[field.name].options.length; j++)
						{
							if(form.elements[field.name].options[j].selected)
							{
								value[value.length] = form.elements[field.name].options[j].value;
//								value += (value?',':'') + form.elements[field.name].options[j].value;
							}
						}
						break;

					case 'TEXTAREA':
						break;

					case 'BUTTON':
					case 'INPUT':
						switch(field.type.toUpperCase())
						{
							case 'RADIO':
								value = '';
								for(j=0; j<form.elements[field.name].length; j++)
								{
									if(form.elements[field.name][j].checked)
									{
										value = form.elements[field.name][j].value;
									}
								}
								break;

							case 'CHECKBOX':
								if(multi[field.name])
								{
									bAdd = false;
								}else{
									value = '';

									if(!form.elements[field.name].length)
									{
										if(form.elements[field.name].checked)
										{
											value += (value?',':'') + form.elements[field.name].value;
										}
									}else{
										for(j=0; j<form.elements[field.name].length; j++)
										{
											if(form.elements[field.name][j].checked)
											{
												value += (value?',':'') + form.elements[field.name][j].value;
											}
										}
									}

									multi[field.name] = true;
								}
								break;

							case 'SUBMIT':
								bAdd = false;

								if(Form.submits[form.getAttribute('name')])
								{
									if(Form.submits[form.getAttribute('name')].name == field.name)
									{
										bAdd = true;
									}
								}

								if((tag == 'BUTTON') && !value){
									value = field.innerHTML;
								}

								if(bLockSubmit)
								{
									field.disabled = true;
								}
								break;

							default:
								if(field.alt == value)
								{
									value = '';
								}
						}
						break;

					default:
						alert('Unknown form element: '+ form.elements[i].tagName);
				}

				// store as object member
				if(bAdd)
				{
					data[field.name] = value;
				}
			}
		}

		// safari BUTTON fix
		if(_safari)
		{
			var field = Form.submits[form.getAttribute('name')];
			if(field)
			{
				if(field.tagName.toUpperCase() == 'BUTTON')
				{
					data[field.name] = field.innerHTML;
				}
			}
		}

		return data;
	},


	// this function called when response data received
	saveCallback: function(response){

		if(!response.js.__form)
		{
			alert("RPC error: Invalid response from server\n\n"+response.text);
			return;
		}


		// __form contains form name
		var form = document.forms[response.js.__form];
		if(form)
		{
			// reset previous submit button
			Form.submits[form.getAttribute('name')] = null;

			// remove "required" class from all elements
			for(var i=0; i<form.elements.length; i++)
			{
				field = form.elements[i];

				// check if this is valid element
				if(field.tagName)
				{
					field.className = field.className.replace(/\s*required/ig, '');
					var oError = _G('fde-'+ field.name);
					if(oError)
					{
						oError.innerHTML = '';
						oError.className = oError.className.replace(/\s*show/ig, '');
					}
				}
			}
		}

		if(response.js.execute)
		{
            var fn = eval(response.js.execute);
            if(typeof fn == 'function')
            {
                fn(response);
            }
		}

		// check if we got some error reports from server
		if(response.js.errors)
		{
			var text = '', oError, bAlert = true;

			if(typeof response.js.errors == 'string')
			{
				text += response.js.errors +"\n";
			}else{
				// convert list of errors into string
				for(var fieldName in response.js.errors)
				{
					text += response.js.errors[fieldName] +"\n";

					// if form exists
					if(form)
					{
						// and field exists
						if(form.elements[fieldName])
						{
							form.elements[fieldName].className += ' required';
						}
					}

					// check if field error box exists
					oError = _G('fde-'+ fieldName);
					if(oError)
					{
						bAlert = false;
						oError.innerHTML = response.js.errors[fieldName];
						oError.className += ' show';
					}
				}
			}

			// show errors
			if(bAlert)
			{
				alert(text);

				// redirect if required
				if(response.js.redirect)
				{
					if(response.js.__inline)
					{
						// request for new page
						rpc.send({'__inline':true, '__form':form.getAttribute('name')}, Form.saveCallback, response.js.redirect, true);
					}else{
						// change location location
						window.location = response.js.redirect;
					}
				}

			}else{
				oError = _G('fme-'+ response.js.__form);
				if(oError && response.js.errors_summary)
				{
					oError.innerHTML = response.js.errors_summary;
					oError.className += ' show';
				}
			}

		}else if(response.js.confirm){ // confirm dialog

			if(confirm(response.js.confirm))
			{
				response.js.__action = response.js.confirm_ok;
			}else{
				response.js.__action = response.js.confirm_cancel;

			}
			rpc.send(response.js, Form.saveCallback, response.js.__location, true);

		}else{// no errors, no confirmations
			// check if page should be redirected
			if(response.js.redirect)
			{
				if(response.js.__inline)
				{
					// request for new page
					rpc.send({'__inline':true, '__form':form.getAttribute('name')}, Form.saveCallback, response.js.redirect, true);
				}else{
					// change location location
					window.location = response.js.redirect;
				}

			}else{

				// inline form
				if(response.js.__inline)
				{
					if(form)
					{
						form.parentNode.innerHTML = response.js.html;
						Form.init();

						Hook.Exec('Form_Init');
					}
				}

			}

			if(!response.js.__noload)
			{
				Hook.Exec('Form_'+response.js.__form+'_OnLoad');
				Hook.Exec('Form_OnLoad', false, response.js.__form, response.js.redirect, response.js);
			}
		}


		if(!response.js.redirect)
		{
			for(var i=0; i<form.elements.length; i++)
			{
				var field = form.elements[i];

				if((field.tagName.toUpperCase() == 'INPUT') || (field.tagName.toUpperCase() == 'BUTTON'))
				{
					if(field.type.toUpperCase() == 'SUBMIT')
					{
						field.disabled = false;
					}
				}
			}
		}
	},



	// reset form
	reset: function(){
		// we have return path defined
		if(this.elements['__return'])
		{
			if(this.elements['__inline'])
			{
				rpc.send({'__inline':true, '__form':this.getAttribute('name')}, Form.saveCallback, this.elements['__return'].value, true);
			}else{
				window.location = this.elements['__return'];
			}

			return false;
		}else{
			// just reset form
			return true;
		}
	},





	// field management class
	Field: {
		// initialize form field
		init: function(field){

			// if "alt" attribute is not blank - place it inside value
			if(field.alt && (field.value.replace(/\s*/g,'') == ''))
			{
				field.value = field.alt;
			}


			if((field.type+'').toUpperCase()=='SUBMIT' && field.name)
			{
				Form.submit_onclick[field.form.name+'__'+field.name] = field.onclick;
				field.onclick = Form.Field.onSubmitClick;
			}


			// add event handlers
			field.onfocus = Form.Field.onFocus;
			field.onblur  = Form.Field.onBlur;
		},


		// form may contain many submit buttons
		// we should transfer only clicked one
		onSubmitClick: function(){
			var form;

			var fieldName, formName;
			try{formName=this.form.getAttribute('name');}catch(e){};
			try{fieldName=this.getAttribute('name');}catch(e){};

			var onclick = Form.submit_onclick[formName+'__'+fieldName];

			if(typeof onclick == 'function')
			{
				if(onclick() == false)
				{
					return false;
				}
			}

			Form.submits[formName] = this;
/*
			var fn; eval('fn=function(){document.forms["'+this.form.name+'"].onsubmit();}');
			setTimeout(fn, 100);

			return false;
*/
		},


		// this fuction called when field gains focus
		onFocus: function(){
			// remove ALT text if not changed
			if(this.alt && (this.alt == this.value))
			{
				this.value = '';
			}

			var field2, params = Form.meta[this.form.getAttribute('name')+'_'+this.name];
			if(params)
			{
				if(params.length >= 1)
				{
					field2 = this.form[params[1]];
					if(field2)
					{
						if(field2.alt && (field2.alt == field2.value))
						{
							field2.value = '';
						}
					}
				}
			}

			this.className += ' focus';
		},


		// this fuction called when field loose focus
		onBlur: function(){
			var bClear = true;

			// if "alt" attribute is not blank - place it inside value
			if(this.alt && (this.value.replace(/\s*/g,'') == ''))
			{
//				this.value = this.alt;
			}else{
				bClear = false;
			}



			var field2, params;

			if(this.form)
			{
				params = Form.meta[this.form.getAttribute('name')+'_'+this.name];
				if(params)
				{
					if(params.length >= 1)
					{
						field2 = this.form[params[1]];
						if(field2)
						{
							if(field2.alt && (field2.value.replace(/\s*/g,'') == ''))
							{
//								field2.value = field2.alt;
							}else{
								bClear = false;
							}
						}
					}
				}
			}else{
// alert(this.tagName);
			}


			if(bClear)
			{
				this.value = this.alt;

				if(field2)
				{
					field2.value = field2.alt;
				}
			}

			this.className = this.className.replace(/\s*focus/ig,'');
		}
	}
}

// add Form class to window.onload event
Hook.Add('Window_OnLoad', 'Form.init');
