/**
* @version		$Id: XForms.js 6188 2007-07-17 22:49:47Z facedancer $
* @package		Forms
* @copyright	Copyright (C) 2005 - 2007 Open Source Matters. All rights reserved.
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.txt
* iForms! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.txt for copyright notices and details.
*/

/**
 * Unobtrusive Form Validation library
 *
 * Inspired by: Sergey Bernikoff <www.bernikoff.com>
 *
 * @author		Timur Junussov <timur.junussov@homeshop.kz>
 * @package		Forms.Framework
 * @subpackage	Forms
 * @since		1.5
 */



XForms = {
	elements : new Array(),
	setup : function (params){
		var uEl = null;
		
		switch(params.type.toUpperCase()){
			case "NUMBER" : 	uEl = new UITextField(params.input,new XToIntegerConvertor()); break;
			case "DATE" : 		uEl = new UITextField(params.input,new XToDateConvertor()); break;
			case "TEXT" : 		uEl = new UITextField(params.input); break;
			case "LOOKUP" : 	uEl = new UIDropDown(params.input); break;
			case "MULTILINE" : 	uEl = new UIMemo(params.input); break;
			case "CHECK" : 		uEl = new UICheck(params.input,new XToBooleanConvertor()); break;
			case "HTML" :	 	uEl = new UIHtml(params.input); break;
			case "RADIO" :	 	uEl = new UIRadio(params.input); break;
			default : 			throw {description:"Unknown XForm datatype " + params.type};
		};
		
		if(params.required) uEl.addValidator({type:"NOTNULL"});
		if(params.validators) uEl.setValidators(params.validators);
		if(params.formatters) uEl.setFormatters(params.formatters);

		this.elements.push(uEl);
	},
	submit : function(button){
		var BUT = document.getElementById(button);
			BUT.onclick = XForms.validate;
	},
	validate : function (){
		for(var i=0, length = XForms.elements.length; i < length; i++ )
		{
			try {
				XForms.elements[i].validate();
			} catch(e){ 
				alert(e.description); 
				XForms.elements[i].focus(); 
				return false; 
			}
		}
	}
}


// -- ************ -- /
function UIElement(){
	this.element = null;
	this.convertor = null;
	this.validators =null;
	this.formatters = null;
	this.type = null;
	this.name = null;
	this.title = null;
};
UIElement.prototype.init = function(element,convertor){
	this.name = element;
	this.element = document.getElementById(element) || document.getElementsByName(element)[0]; // For Mozilla
	this.title = this.element.title ? this.element.title : this.name;
	this.convertor = convertor ? convertor : new XConvertor();
	this.validators = new Array();
	this.formatters = new Array();
};
UIElement.prototype.getRawValue = function(){	
	return this.element.value;
};
UIElement.prototype.getElement = function(){
	return this.element;
};
UIElement.prototype.getValue = function(){
	try { return this.convertor.convert(this.getRawValue()); }
	catch(e){ this.clearValue(); throw e; }
};
UIElement.prototype.clearValue = function(){
	this.element.value = "";
};
UIElement.prototype.getType = function(){
	return this.type;
};
UIElement.prototype.getName = function(){
	return this.name;
};
UIElement.prototype.getTitle = function(){
	return this.title;
};
UIElement.prototype.focus = function(){
	this.element.focus();
};
UIElement.prototype.addValidator = function(validator){
	//this.validators.push(new XValidator(this,validator));
	switch(validator.type){
			case "NOTNULL" : 	vl = new XNotNullValidator(this); break;
			case "LENGTH" : 	vl = new XLengthValidator(this,validator.value); break;
			case "MIN" : 		vl = new XMinValidator(this,validator.value); break;
			case "MAX" : 		vl = new XMaxValidator(this,validator.value); break;
			case "EMAIL" : 		vl = new XEmailValidator(this); break;
			case "REGEXP" : 	vl = new XRegExpValidator(this,validator.value); break;
			default : alert("Unknown XForm datatype " + validator.type); //throw {description:"Unknown XForm datatype " + validator.type};
		};
	this.validators.push(vl);
};
UIElement.prototype.addFormatter = function(formatter){
	this.formatters.push(new XFormatter(this,formatter));
};
UIElement.prototype.setValidators = function(validators){
	for (var i=0; i < validators.length; i++ )	this.addValidator(validators[i]);
};
UIElement.prototype.setFormatters = function(formatters){
	for (var i=0; i < formatters.length; i++ )	this.addFormatter(formatters[i]);
};
UIElement.prototype.validate = function(){
	for (var i=0; i < this.validators.length; i++ )	this.validators[i].validate(this.getValue());
};
// ------------------------------
function UITextField(element,convertor){
	this.type = "UITextField";
	this.init(element,convertor);
};
UITextField.prototype = new UIElement();
// ------------------------------
function UIDropDown(element,convertor){
	this.type = "UIDropDown";
	this.init(element,convertor);
};
UIDropDown.prototype = new UIElement();
UIDropDown.prototype.getElement = function(){
	return this.element.options[this.element.selectedIndex];
};
// ------------------------------
function UIMemo(element,convertor){
	this.type = "UIMemo";
	this.init(element,convertor);
};
UIMemo.prototype = new UIElement();
// ------------------------------
function UICheck(element,convertor){
	this.type = "UICheck";
	this.init(element,convertor);
};
UICheck.prototype = new UIElement();
UICheck.prototype.getRawValue = function(){
	return this.element.checked;
};
// ------------------------------
function UIRadio(element,convertor){
	this.type = "UIRadio";
	this.name = element;
	this.validators = new Array();
	this.element = document.getElementsByName(element);
	this.convertor = convertor ? convertor : new XConvertor();
};
UIRadio.prototype = new UIElement();
UIRadio.prototype.getRawValue = function(){
	return this.getElement().value;
};
UIRadio.prototype.getElement = function(){
	for (var i=0; i < this.element.length; i++ )
		if(this.element[i].checked) return this.element[i];
	return null;
};
UIRadio.prototype.focus = function(){
	this.element[0].focus();
};
// ------------------------------
function UIHtml(element,convertor){
	this.type = "UIHtml";
	this.init(element,convertor);
};
UIHtml.prototype = new UIElement();
UIHtml.prototype.getRawValue = function(){
	return this.element.innerHTML;
};










// ---------
function XConvertorException(convertor,description){
	this.convertor = convertor;
	this.description = description;
};
// ---------
function XConvertor(){
	this.type = "STRING";
};
XConvertor.prototype.convert = function(string){
	return string.toString();
};
// ---------
function XToIntegerConvertor(){
	this.type = "INTEGER";
};
XToIntegerConvertor.prototype = new XConvertor();
XToIntegerConvertor.prototype.convert = function(string){
	if(isNaN(string)) throw new XConvertorException(this,"Ошибка преобразования ( "+string+" ) в Число");
	return Number(string);
};
// ---------
function XToDateConvertor(){
	this.type = "DATE";
};
XToDateConvertor.prototype = new XConvertor();
XToDateConvertor.prototype.convert = function(string){
	if(!string) return "";
	
	var cD = Number(string.substr(0, 2));	var cM = Number(string.substr(3, 2));
	var cY = Number(string.substr(6, 4));	var separator1 = string.substr(2, 1);
	var separator2 = string.substr(5, 1);
	
	date = new Date();	date.setDate(1); date.setMonth(cM-1); date.setFullYear(cY);	date.setTime(date.getTime() + (cD-1)*24*60*60*1000);
	
	if(separator1 != "." || separator2 != "." || cD != date.getDate() || cM-1 != date.getMonth() || cY != date.getFullYear() ) 
	throw new XConvertorException(this,"Ошибка преобразования ( "+string+" ) в Дату");
	
	return date;
};
// ---------
function XToBooleanConvertor(){
	this.type = "BOOLEAN";
};
XToBooleanConvertor.prototype = new XConvertor();
XToBooleanConvertor.prototype.convert = function(string){
	if(string == true || string == "checked" || string == "TRUE" || string == 1 || string == "C_YES" ) return true;
	else if(string == false || string == "" || string == "FALSE" || string == 0 || string == "C_NO") return false;
	else throw new XConvertorException(this,"Ошибка преобразования ( "+string+" ) в Boolean");
};




// ---------
// UPPERCASE, LOWWERCASE, NUMBER, PHONE, CYR2LAT, ABS, DATE, FCAP
function XFormatter(UIElement,param){
	this.UIElement = UIElement;
};
// ---------
// NOTNULL, LENGTH, MIN, MAX, REGEXP, GT, LT, PHH, CARD, ZIP, 
function XValidatorException(validator,description){
	this.description = description;
	this.validator = validator;
};
function XValidator(UIElement,param){
	this.UIElement = UIElement;
};
// ------------------------------
function XNotNullValidator(UIElement){
	this.UIElement = UIElement;
};
XNotNullValidator.prototype = new XValidator();
XNotNullValidator.prototype.validate = function(value){
	switch(this.UIElement.convertor.type){
		case "INTEGER" : if(value != "") return; break;
		case "BOOLEAN" : if(value) return; break;
		case "DATE" : if(value) return; break;
		case "STRING" : if(value.length > 0) return; break;
		default : return;
	}
	throw new XValidatorException(this,"Поле \""+this.UIElement.getTitle()+"\" обязательное для заполнения !!!");
};
// ------------------------------
function XLengthValidator(UIElement,length){
	this.UIElement = UIElement;
	this.length = length;
};
XLengthValidator.prototype = new XValidator();
XLengthValidator.prototype.validate = function(value){
	switch(this.UIElement.convertor.type){
		case "INTEGER" : if(String(value).length == this.length) return; break;
		case "STRING" : if(String(value).length == this.length) return; break;
		default : return;
	}
	throw new XValidatorException(this,"Длина поля \""+this.UIElement.getTitle()+"\" ( "+String(value).length+" ) не соответствует длине " + this.length);
};
// ------------------------------
function XMinValidator(UIElement,minval){
	this.UIElement = UIElement;
	this.minval = minval;
};
XMinValidator.prototype = new XValidator();
XMinValidator.prototype.validate = function(value){
	switch(this.UIElement.convertor.type){
		case "INTEGER" : if(Number(value) >= this.minval) return; break;
		//case "DATE" : if(String(value).length == this.length) return; break;
		default : return;
	}
	throw {description:"value ( "+value+" )  ("+this.length+") for "+this.UIElement.getTitle()};
};
// ------------------------------
function XMaxValidator(UIElement,maxval){
	this.UIElement = UIElement;
	this.maxval = maxval;
};
XMaxValidator.prototype = new XValidator();
XMaxValidator.prototype.validate = function(value){
	switch(this.UIElement.convertor.type){
		case "INTEGER" : if(Number(value) <= this.maxval) return; break;
		//case "DATE" : if(String(value).length == this.length) return; break;
		default : return;
	}
	throw {description:"value ( "+value+" )  ("+this.maxval+") for "+this.UIElement.getTitle()};
};
// ------------------------------
function XRegExpValidator(UIElement,expr){
	this.UIElement = UIElement;
	this.expr = expr;
};
XRegExpValidator.prototype = new XValidator();
XRegExpValidator.prototype.validate = function(value){
	switch(this.UIElement.convertor.type){
		case "STRING" : if(true) return; break;
		default : return;
	}
	throw {description:"value \" "+value+" \" ("+this.expr+") for "+this.UIElement.getTitle()};
};
// ------------------------------
function XEmailValidator(UIElement){
	this.UIElement = UIElement;
};
XEmailValidator.prototype = new XValidator();
XEmailValidator.prototype.validate = function(value){
	if(value != '' && !RegExp(/^[\.\-_A-Za-z0-9]+?@[\.\-A-Za-z0-9]+?\.[A-Za-z0-9]{2,6}$/).test(value))
	throw new XValidatorException(this,"В поле \""+this.UIElement.getTitle()+"\" введен ( "+value+" ) неправельный email ");
};