formValidator=function(formId,debug){

	this.addRule = function( elementName, ruleSet, reaction ) {
		this.rules[elementName]=ruleSet;
		this.reactions[elementName]=reaction;
	}
	
	this.remRule = function( elementName ) {
		delete this.rules[elementName];
		delete this.reactions[elementName];
	}

	this.deleteAllRules = function(){
		this.rules={};
		this.reactions={};
	}

	this.makeElementsArray=function() {
 		var tags=Array('INPUT','SELECT','TEXTAREA');
		for (var t in tags) {
			var elements=this.form.getElementsByTagName(tags[t]);
			for (var n=0; n<elements.length; n++){
				var currentElement=elements[n]; 
				if (typeof(currentElement=='object') && currentElement.name && typeof(currentElement.value)!='undefined'){
					if (currentElement.type!='radio' || (currentElement.type=='radio' && currentElement.checked )){
						this.formElements[currentElement.name] = {el:currentElement,val:currentElement.value};
					}
					if (currentElement.type=='radio' && !this.formElements[currentElement.name]){
						this.formElements[currentElement.name] = {el:currentElement,val:''};
					}
				}
			}
		}
	}

	this.validate = function() {
		if (this.config.callBeforeValidating){
			this.config.callBeforeValidating();
		}

		var valid=true;

		this.makeElementsArray();

		for (var n in this.formElements){
			var currentElement = this.formElements[n];

			if (this.rules[currentElement.el.name]) {
				var ruleName=currentElement.el.name;
				var notValid=false;

				ommitField:
				for (var currentRule in this.rules[ruleName]){
					var currentRuleParameter=this.rules[ruleName][currentRule];

					switch (currentRule){

						case 'minValue':
							if (currentElement.val<currentRuleParameter) var notValid=true;
							break;
						
						case 'maxValue':
							if (currentElement.val>currentRuleParameter) var notValid=true;
							break;

						case 'minLength':
							if (currentElement.val.length<currentRuleParameter) var notValid=true;
							break;

						case 'maxLength':
							if (currentElement.val.length>currentRuleParameter) var notValid=true;
							break;

						case 'regExp':
							if (!currentRuleParameter.test(currentElement.val)) var notValid=true;
							break;
						
						case 'checked':
							if (currentElement.el.checked!=currentRuleParameter) var notValid=true;
							break;

						case 'creditCard':
							var notValid=!this.isValidCreditCardNumber(currentElement.val);
							break;

						case 'PESEL':
							var notValid=!this.isValidCreditPESELNumber(currentElement.val);
							break;

						case 'func':
							var notValid=!currentRuleParameter( currentElement.val, currentElement );
							break;

						case 'nocheckif':
							if (currentRuleParameter()){
								var notValid=false;
								break ommitField;
						}
					}
				}

				if (notValid==true)	{
					valid=false;
					this.doReaction(currentElement.el,this.reactions[ruleName]);
					if (this.config.breakOnFirstError) return false;
				}
			}
		}
		if (valid && this.config.callOnSubmit) this.config.callOnSubmit();
		return valid;
	}

	this.doReaction = function ( element, reaction) {
		for (var n in reaction){
			switch (n){
				case 'alert' :	alert(reaction[n]);
								element.focus();
								break;
				case 'callparam'
							 :	if (this.config.callOnError) this.config.callOnError(element,reaction[n]);
								break;

				default	:		break;								
			}
		}
	}

	this.enableAutoValidating = function () {
		this.autoValidating=true;
		this.form.onsubmit= function() { return this.fv.validate();};
	}

	this.disableAutoValidating = function () {
		this.autoValidating=false;
		this.form.onsubmit= function() {return false;}
	}

	this.showError = function(txt){
		if (this.debug) alert('ERROR formValidator.js\n\n'+txt);
	}

	// walidacja numeru karty kredytowej
	//
	this.isValidCreditCardNumber = function( number ){
		var sum=0;
		for (var n=0; n<16 ;n++){
			var f= ((n%2==0)?2:1);
			var mult = number[n]*f;
			sum+= mult%10 + parseInt(mult/10); 
		}
		return (sum%10==0)?true:false;
	}

	// walidacja numeru PESEL
	//
	this.isValidCreditPESELNumber = function( pesel ){
		if(pesel.length!=11) return false;
		var wagi=new Array(1,3,7,9,1,3,7,9,1,3);
		var suma=0;
		for (var i=0; i<10;i ++) suma += parseInt(pesel.charAt(i)) * parseInt(wagi[i]);
		liczba = 10 - suma%10;
		if(liczba==10) liczba=0;
		return pesel.charAt(10)==liczba;
	}

    this.debug=debug;
	this.form=document.getElementById(formId);
	if (this.form==null) this.showError('brak formularza o id='+formId);
	
	this.rules={};
	this.reactions={};
	this.formElements={};
	this.config={	breakOnFirstError:true, 
					callBeforeValidating:null, 
					callOnValidatingError:null,
					autoValidating:true
				};

	if (this.form){
		this.form.fv=this;
		this.enableAutoValidating();
	}


}