/*
 * Project:     VistaCMS: form
 * File:        form.js
 * 
 * Copyright (c): 2006-2007 VistaSolutions.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *  
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @link http://www.vistacms.ru/
 * @author Sergey Vinogradov <vinogradov@vistacms.ru>
 * @author Sergey Belyakov <sergei@vistacms.ru>
 * @version 1.0
 * @copyright 2006-2007 VistaSolutions.
 * @package form
 * 
 */
 
function Form(attr)
{
	this.attr 				= attr;
	this.error				= false;
	this.formName	 		= false;
	this.formObj			= false;
	this.formClassValid 	= false;
	this.formClassInvalid 	= false;
	this.formErrorObject	= false;
	this.formErrorMessage	= false;
	this.formError			= false;
	
	this.pass1				= false;
	this.pass2				= false;
	
	// Объекты
	this.formElements 	= new Object();
	this.radios			= new Object();
	this.masks 			= new Object();
	
	// Регулярные выражения
	this.masks.email 	= /^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;	// Email
	this.masks.numeric 	= /^[0-9]+$/i;									// Numeric
	this.masks.letter 	= /^[A-Zжше]+$/i;								// Letteric
	this.masks.path 	= /^(https?\:\/\/)?[a-zA-Z0-9]+([a-zA-Z0-9\-\.]+)?\.(com|org|net|mil|edu|info|a[cdfgilmnoqrstuwxz]|b[abdefghijmnorstwyz]|c[acdfghiklmnoruvxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[adefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnrwyz]|l[abcikrstuvy]|m[acdghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eouw]|s[abcdeghiklmnrtvyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[etu]|z[amw])+([\/])+([a-zA-Z0-9\-\.\/]+)$/i;
	
	this.init = function()
	{
		// Подгружаем настройки
		this.initPros();
		
		// Определяем объекты
		this.formObj   = document.getElementById(this.formName);
		this.formError = document.getElementById(this.formErrorObject);
		
		// Определяем элементы формы
		this.initForm();
	}
	
	// Загружаем элементы формы
	this.initForm = function()
	{
		for(i = 0; i < this.formObj.length; i++)
		{
			var el = this.formObj[i];
			
			if(this.hasValidate(el))
			{
				this.formElements[el.name] 			= new Array();
				this.formElements[el.name].element	= el;
				this.formElements[el.name].select 	= false;
				this.formElements[el.name].label	= this.hasLabel(el);
				this.formElements[el.name].error	= false;
				
				if(el.type.toLowerCase() == 'radio' || el.type.toLowerCase() == 'checkbox')
				{
					this.addRadios(el);	
				}	
				
				// Добавляем событие на элемент
				this.addEvent(el);
			}
		}
		
		// Проверяем элементы формы
		this.validateFields();
	}
	
	// Проверяем элементы формы
	this.validateFields = function()
	{
		for(var prop in this.formElements)
		{
			var elem = this.formElements[prop].element;
			
			this.validateInput(elem);		
		}
	}
	
	this.validateInput = function(elem)
	{
		var index = elem.name;
		
		if(this.inputValid(elem)) 
		{
			this.formElements[index].result = true;
			this.toggleInput(elem,'valid');
		} 
		else 
		{
			this.formElements[index].result = false;
			this.toggleInput(elem,'invalid');
		}
	}
	
	this.toggleInput = function(elem, type)
	{
		if(this.formClassValid && this.formClassInvalid)
		{
			elem.className = (type == 'valid') ? this.formClassValid : this.formClassInvalid;
		}
	}
	
	this.inputValid = function(elem)
	{
		var elType = 'select';
		
		if((elem.tagName.toLowerCase() == 'input' && elem.type.toLowerCase() == 'text') || elem.tagName.toLowerCase() == 'textarea') elType = 'text';
		if(elem.tagName.toLowerCase() == 'input' && elem.type.toLowerCase() == 'radio') elType = 'radio';
		if(elem.tagName.toLowerCase() == 'input' && elem.type.toLowerCase() == 'checkbox') elType = 'checkbox';
		if(elem.tagName.toLowerCase() == 'input' && elem.type.toLowerCase() == 'password') elType = 'password';
		
		if(elType == 'text')
		{
			if(elem.value && elem.value != 0)
			{
				var mask = elem.getAttribute('mask');
				
				if(mask)
				{
					if(!this.masks[mask].test(elem.value)) 
					{
						this.setError(elem, 'mask');
						return false;
					}
				}
				
				return true;
			}
			else
				this.setError(elem, elType);
		}
		
		if(elType == 'select')
		{
			if(elem.options[elem.selectedIndex].value)
				return true;
			else
				this.setError(elem, elType);
		}

		if(elType == 'radio' || elType == 'checkbox')
		{
			var name = elem.name;
			
			var elChecked = false;
			
			for(var no = 0; no < this.radios[name].length; no++)
			{
				if(this.radios[name][no].checked)
				{
					elChecked = true;
				}	
			}
			
			if(elChecked)
			{
				return true;
			}
			else
				this.setError(elem, elType);
		}
		
		if(elType == 'password')
		{
			if(elem.name == 'password')
			{
				if(elem.value && elem.value != 0)
					return true;
				else
				{
					this.setError(elem, 'password');
					return false;
				}
			}
			else
			{
				if(elem.value && elem.value != 0)
				{
					if(this.formElements['password'].element.value != this.formElements['password_retype'].element.value)
					{
						this.setError(elem, 'password_wrong');
						return false;
					}
					else
						return true;
				}
				else
				{
					this.setError(elem, 'password_retype');
					return false;
				}
			}
		}
		
		/*		
		if(elem.name == 'password_retype' && elem.value == '')
			{
				this.setError(elem, 'password_retype');
				return false;
			}
			else if(this.formElements['password'].element.value != this.formElements['password_retype'].element.value)
			{
				this.setError(this.formElements['password_retype'].element, 'password_wrong');
				return false;
			}
			else
				return true;
		}*/
		
		return false;
	}
	
	// Парсим настройки формы
	this.initPros = function() 
	{
		if(this.attr.formName) this.formName 					= this.attr.formName;
		if(this.attr.formClassValid) this.formClassValid 		= this.attr.formClassValid;
		if(this.attr.formClassInvalid) this.formClassInvalid 	= this.attr.formClassInvalid;
		if(this.attr.formErrorObject) this.formErrorObject 		= this.attr.formErrorObject;
		if(this.attr.formErrorMessage) this.formErrorMessage 	= this.attr.formErrorMessage;
	}
	
	// Добавляем события к элементам
	this.addEvent = function(elem)
	{
		var _this = this;
		
		elem.onchange 	= function() { _this.validateInput(elem); };
		elem.onpaste 	= function() { _this.validateInput(elem); };
		elem.onblur 	= function() { _this.validateInput(elem); };
		elem.onkeyup 	= function() { _this.validateInput(elem); };
		elem.onkeydown 	= function() { _this.validateInput(elem); };
		elem.onkeypress = function() { _this.validateInput(elem); };
		elem.onclick 	= function() { _this.validateInput(elem); };
	}
	
	// Парсим элементы формы на radio и checkbox
	this.addRadios = function(el)
	{
		if(!this.radios[el.name])
		{
			this.radios[el.name] = new Array();
			
			for(var no = 0; no < this.form.elements.length; no++)
			{
				var formEl = this.form.elements[no];
				
				if(formEl.name == el.name)
				{
					this.radios[el.name][this.radios[el.name].length] = formEl;
				}
			}
		}		
	}
	
	// Проверяем элемент на требуемость проверки
	this.hasValidate = function(el)
	{
		var req = el.getAttribute('required');
		
		if(req || req === '') return true;
		
		return false;	
	}
	
	// Проверяем элемент на наличие описания
	this.hasLabel = function(el)
	{
		var req = el.getAttribute('label');
		
		if(req || req === '') return req;
		
		return false;	
	}
	
	// Устанавливаем ошибку
	this.setError = function(elem, type)
	{
		var index = elem.name;

		switch(type)
		{
			case "text":
			case "textarea":
				this.formElements[index].error = 'Не заполнено поле "' + elem.label + '"';
			break;
			
			case "radio":
			case "checkbox":
				this.formElements[index].error = 'Не отмечено поле "' + elem.label + '"';
			break;
			
			case "select":
				this.formElements[index].error = 'Не выбрано поле "' + elem.label + '"';
			break;
			
			case "mask":
				this.formElements[index].error = 'Не правильно заполнено поле "' + elem.label + '"';
			break;
			
			case "password":
				this.formElements[index].error = 'Вы не выбрали пароль';
			break;
			
			case "password_retype":
				this.formElements[index].error = 'Вы не повторили пароль';
			break;
			
			case "password_wrong":
				this.formElements[index].error = 'Введенные пароли не совпадают';
			break;
		}
	}
	
	// Проверяем и отправляем форму
	this.check = function()
	{
		for(var no in this.formElements)
		{
			var elem = this.formElements[no];
			
			if(!elem.result)
			{
				if(this.formErrorObject)
					this.formError.innerHTML = elem.error;
				
				elem.element.focus();
				return false;
			}
		}
		
		this.formObj.submit();
	}
	
	this.init();	
}
