Validator=Class.create();
Validator.Handle=Class.create();
Validator.Handle.prototype={
	_list:{'cnt':1,'items':new Array()},
	_states:{'isValid':true,'controlsInited':false},
	_feature:{'errorImages':true},
	initialize:function(){},
	getNextID:function(){
		return ++this._list['cnt'];
	},
	getIsValid:function(){
		return this._states['isValid'];
	},
	setIsValid:function(param){
		this._states['isValid']=param;
	},
	getErrorImageDisplay:function(){
		return this._feature['errorImages'];
	},
	setErrorImageDisplay:function(param){
		this._feature['errorImages']=param;
	},
	getControlsIsInitiated:function(){
		return this._states['controlsInited'];
	},
	setControlsIsInitiated:function(param){
		this._states['controlsInited']=param;
	},
	visibleValidatorMessageByID:function(ValidatorID, message){
		$O(ValidatorID).innerHTML = '&nbsp;'+message;
		if (message != '') {
			this.setIsValid(false);
			if (this.getErrorImageDisplay()==true) {
				$O(ValidatorID).className = 'error-fail-message';
			}
		} else {
			if (this.getErrorImageDisplay()==true) {
				$O(ValidatorID).className = 'error-success-message';
			}
		}
	}
}
ValidatorHandle=new Validator.Handle();

/*
	params:
		*to:
		*type:
		*message:
		compareTo:
		regexp:
		function:
		minLength:
		maxLength:
		minValue:
		maxValue:
		cssClass:
		group:
		event:
		focusOnError:
	*:required param
*/
Validator.prototype={
	initialize:function(params){
		this._params=params;
		this._handle=ValidatorHandle;
		this.create();
	},
	create:function(){
		if(this._params['containerID']==undefined){
			this.createTextContainer();
		} else {
			this._params['validatorID']=this._params['containerID'];
		}
		this._handle._list['items'].push(this._params);
	},
	createTextContainer:function(){
		if(this._params['view']=='block'){
			var container=$Ce('div');
		}
		else{
			var container=$Ce('span');
		}
		container.id='validator$'+this._params['to']+'$'+this._params['type']+'$'+this._handle.getNextID();
		if(this._params['cssClass']==undefined){
			container.className='color-warning';
		}
		$O(this._params['to']).parentNode.insertBefore(container,$O(this._params['to']).nextSibling);
		this._params['validatorID']=container.id;
	}
}

ValidatorEvent=Class.create();
ValidatorEvent.prototype={
	initialize:function(params){
		this._params=params;
		this._handle=ValidatorHandle;
		this.create();
	},
	create:function(){
		MyEvent.attachEvent(new MyEventRecord($O(this._params['to']), (this._params['event']==undefined)?'click':this._params['event'], this.validate,this));
	},
	initControls:function(ValidatorInstance){
		var inputs=document.getElementsByTagName('input');
		var selects=document.getElementsByTagName('select');
		for(i in inputs){
			if(inputs[i].id!=ValidatorInstance._params['to']){
				MyEvent.add(inputs[i],'change',ValidatorInstance.validate,ValidatorInstance);
			}
		}
		for(i in selects){
			if(selects[i].id!=ValidatorInstance._params['to']){
				MyEvent.add(selects[i],'change',ValidatorInstance.validate,ValidatorInstance);
			}
		}
	},
	validate:function(Sender,Event,ValidatorInstance){
		if(!ValidatorInstance._handle.getControlsIsInitiated()){
			ValidatorInstance.initControls(ValidatorInstance);
			ValidatorInstance._handle.setControlsIsInitiated(true);
		}
		ValidatorInstance._handle.setIsValid(true);
		var items=ValidatorInstance._handle._list['items'];
		var ItemFocused=false;
		var messagesToShow = new Array();
		for(var i=0;i<items.length;i++){
			if(
				ValidatorInstance._params['group']!=undefined &&
				items[i]['group']!=undefined &&
				items[i]['group']!=ValidatorInstance._params['group'] &&
				items[i]['subgroup']!=ValidatorInstance._params['group'] &&
				items[i]['to']!=ValidatorInstance._params['group']
			){
				// if item group same
				continue;
			}
			ValidatorItemIsValid=true;
			
			// when items collection contains the validator, but validator not exists in DOM
			if($O(items[i]['validatorID'])==null){
				continue;
			}	
			switch(items[i]['type']){
				case 'required':
					if($Ov(items[i]['to'])==''){
						ValidatorItemIsValid=false;
					}
					break;
				case 'dataType':
					switch(items[i]['dataType']){
						case 'number':
							if(isNaN($Ov(items[i]['to']))){
								var currentValue = $Ov(items[i]['to']);
								currentValue = currentValue.replace(',', '.');
								if(isNaN(currentValue)){
									ValidatorItemIsValid=false;
								} else {
									$j('#'+items[i]['to']).val(currentValue);
								}
							}
							break;
						case 'nonumber':
							if ($Ov(items[i]['to']).match(/\d/)) {
								ValidatorItemIsValid=false;
							}
							break;
					}
					break;
				case 'compare':
					if($Ov(items[i]['to'])!=$Ov(items[i]['compareTo'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'regexp':
					if(!$Ov(items[i]['to']).match(items[i]['regexp'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'custom':
					if((typeof items[i]['function'])=='string'){
						if(!eval(items[i]['function']+'();')){
							ValidatorItemIsValid=false;
						}
					}
					else{
						if(!items[i]['function'](items[i])){
							ValidatorItemIsValid=false;
						}
					}
					break;
				case 'minLength':
					if($Ov(items[i]['to']).length<items[i]['minLength']){
						ValidatorItemIsValid=false;
					}
					break;
				case 'maxLength':
					if($Ov(items[i]['to']).length>items[i]['maxLength']){
						ValidatorItemIsValid=false;
					}
					break;
				case 'email':
					if($Ov(items[i]['to']).match(/^[a-z0-9.-_]+@([a-z0-9-_]{1,}.){0,8}[a-z]{3,}.[a-z]{2,4}$/gi)==null){
						ValidatorItemIsValid=false;
					}
					break;
				case 'maximum':
					if(parseInt($Ov(items[i]['to']))>parseInt(items[i]['maxValue'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'minimum':
					if(parseInt($Ov(items[i]['to']))<parseInt(items[i]['minValue'])){
						ValidatorItemIsValid=false;
					}
					break;
				case 'between':
					if($Ov(items[i]['to'])=='' || parseInt($Ov(items[i]['to']))>parseInt(items[i]['maxValue']) || parseInt($Ov(items[i]['to']))<parseInt(items[i]['minValue'])){
						ValidatorItemIsValid=false;
					}
					break;
			}
			
			if($O(items[i]['to']).disabled){
				ValidatorItemIsValid=true;
			}
			if(!ValidatorItemIsValid){
				if(
					ItemFocused==false&&
					Sender.id==ValidatorInstance._params['to']&&
					items[i]['focusOnError']==true
				){
					$O(items[i]['to']).focus();
					ItemFocused=true;
				}
				messagesToShow.push({ValidatorID:items[i]['validatorID'], message:items[i]['message']});
			}
			ValidatorInstance._handle.visibleValidatorMessageByID(items[i]['validatorID'], '');
		}
		for (var i=0; i<=messagesToShow.length-1; i++) {
			ValidatorInstance._handle.visibleValidatorMessageByID(messagesToShow[i].ValidatorID, messagesToShow[i].message);
		}
		if(!ValidatorInstance._handle.getIsValid()){
			MyEvent.stop(Event);
			return false;
		}
		if(ValidatorInstance._params['confirmText']!=undefined&&Sender.id==ValidatorInstance._params['to']){
			if(!confirm(ValidatorInstance._params['confirmText'])){
				MyEvent.stop(Event);
				return false;
			}
		}
	}
}

