// bok allows for whitespace and must be the first element
function stringTrim(){return this.replace(/\s+$|^\s+/g,'');}
function stringLTrim(){return this.replace(/^\s+/,'');}
function stringRTrim(){return this.replace(/\s+$/,'');}
function stringLTrimZeros(){return this.replace(/^0+/,'');}
String.prototype.Trim=stringTrim;String.prototype.RTrim=stringRTrim;String.prototype.LTrim=stringLTrim;String.prototype.LTrimZeros=stringLTrimZeros;
function Validator(f){this.enabled=true;this.f=f;}
Validator.prototype.fail = function(){alert('Error de validación');return false;}
Validator.prototype.error=function(elem){
	cn=elem.className;
	message = elem[msg] ? elem[msg] : elem.getAttribute(msg);
	if (typeof message == 'undefined' || message == null || message == ''){message = 'Error en los datos';}
	if (cn != ''){elem.className = cn + ' errHilite';}else{elem.className = 'errHilite';}
	alert(message);try{elem.focus();}catch(e){};return false;
}
Validator.prototype.getType=function(el){
	elemtype = el.nodeName.toLowerCase();
	if (elemtype = 'input')	elemtype = el.type;
	return elemtype;
}
Validator.prototype.validate=function(){
	attr='alt';msg='emsg';errorclass='errHilite';sbutton=null;
	if (this.f==null) return this.fail;
	num=0;
	while (elem = this.f.elements[num++]){elem.className = elem.className.replace(errorclass,'');}
	num=0;
	while (elem = this.f.elements[num++]){
		elemtype = this.getType(elem);
		if (elemtype == 'fieldset') continue;
		if (elemtype == 'submit') sbutton = elem;
		patterns = elem[attr] ? elem[attr] : elem.getAttribute(attr);
		if (typeof patterns == 'undefined' || patterns == null || patterns == '') continue;
		patterns = patterns.split('|');
		for(j=0;j<patterns.length;j++){
			params=patterns[j];
			params=params.split(':');
			proot = params[0];
if (proot == 'bok'){
	// value may be white space
	re=/^[ \f\n\r\t\v]*$/;
	if (re.test(elem.value)) break;

}else if (proot == 'blank'){
	// value may not be white space
	if (elemtype!='text' && elemtype!='password' && elemtype!='textarea' && elemtype!='file') return this.fail();
	re=/^[ \f\n\r\t\v]*$/;
	if (re.test(elem.value)) return this.error(elem);

}else if (proot == 'length'){
	// value length must be in a range length:min:max
	if (elemtype!='text' && elemtype!='password' && elemtype!='textarea') return this.fail();
	if (params.length < 2) return this.fail();
	re=/^\d+$/;
	if (!re.test(params[1])) return this.fail();
	amin=parseInt(params[1]);
	if (params.length > 2 && !re.test(params[2])) return this.fail();
	amax=parseInt(params[2]);
	if (params.length > 2 && amin > amax) return this.fail();
	if (elem.value.length < amin) return this.error(elem);
	if (params.length > 2 && elem.value.length > amax) return this.error(elem);

}else if (proot == 'alnum'){
	// value must be alphanumeric, trimmed, may not be blank
	if (elemtype!='text' && elemtype!='password' && elemtype!='textarea') return this.fail();
	elem.value=elem.value.Trim();
	re=/^[A-Za-z0-9]+$/;
	if (!re.test(elem.value)) return this.error(elem);

}else if (proot == 'email'){
	// must be valid email, trimmed, may not be blank
	if (elemtype!='text' && elemtype!='password') return this.fail();
	elem.value=elem.value.Trim();
	re=/^[A-Za-z0-9_\.\-]+@[A-Za-z0-9_\.\-]+\.[a-z]{2,7}$/;
	if (!re.test(elem.value)) return this.error(elem);

}else if (proot == 'date'){
	// must be valid date, trimmed, may not be blank, format = dia-mes-año
	if (elemtype!='text' && elemtype!='password') return this.fail();
	elem.value=elem.value.Trim();
	re=/^([0-9]{1,2})[\.\-\/]([0-9]{1,2})[\.\-\/]([0-9]{4})$/;
	if (!re.test(elem.value)) return this.error(elem);
	day=RegExp.$1;month=RegExp.$2;year=RegExp.$3;
	day=parseInt(day.LTrimZeros());month=parseInt(month.LTrimZeros());year=parseInt(year.LTrimZeros());
	if(day < 1 || day > 31 || month < 1 || month > 12 || year == 0){
		return this.error(elem);
	}

}else if (proot == 'url'){
	// must be valid url, trimmed, may not be blank
	if (elemtype!='text') return this.fail();
	elem.value=elem.value.Trim();
	
	alphanum='[a-zA-Z0-9]';
	escaped='(%[0-9a-fA-F]{2})';
	unreserved='[a-zA-Z0-9_.!~*\'()-]';
	reserved='[;/?:@&=+$,]';
	schema='((https://)|(http://))?';
	domain='([a-zA-Z0-9\-]+\\.)+[a-z]{2,6}';
	ip='([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})';
	port='(:[0-9]+)?';
	path='(/(('+unreserved+'|'+escaped+'|'+'[:@+$,]'+')+/?)*)?';
	querystring='(\\?('+reserved+'|'+unreserved+'|'+escaped+')*)?';
	fragment='(#('+reserved+'|'+unreserved+'|'+escaped+')*)?';
	regexp='^'+schema+domain+port+path+querystring+fragment+'$';
	re=new RegExp(regexp);
	if(!re.test(elem.value)) return this.error(elem);
	if(elem.value.substr(0,7)!='http://' && elem.value.substr(0,8)!='https://') 
		elem.value='http://'+elem.value;

}else if (proot=='number' || proot=='float'){
	// value must be in a range (number:min:max) both optional, trimmed, may not be blank
	if (elemtype!='text' && elemtype!='password' && elemtype!='select-one') return this.fail();
	if(proot=='number')re=/^[0-9]+$/;else re=/^[0-9]+(,|\.)?[0-9]*$/;
	if (params.length > 1 && !re.test(params[1])) return this.fail();
	amin=parseFloat(params[1]);
	if (params.length > 2 && !re.test(params[2])) return this.fail();
	amax=parseFloat(params[2]);
	if (params.length > 2 && amin > amax) return this.fail();
	elem.value=elem.value.Trim();
	if (!re.test(elem.value)) return this.error(elem);
	avalue = parseFloat(elem.value);
	if (avalue < amin) return this.error(elem);
	if (params.length > 2 && avalue > amax) return this.error(elem);
	
}else if (proot == 'select'){
	// value must be greater than 0, used in dropdown lists
	if (elemtype!='select-one') return this.fail();
	avalue = parseInt(elem.value);
	if (avalue <= 0) return this.error(elem);
	
}else if (proot == 'equalto'){
	// value must coincide with another control's
	if (elemtype!='text' && elemtype!='password' && elemtype!='textarea' && elemtype!='select-one') return this.fail();
	if (params.length < 2) return this.fail();
	if (typeof this.f.elements[params[1]] == 'undefined') return this.fail();
	if (this.f.elements[params[1]].value != elem.value) return this.error(elem);

}else if (proot == 'atleast'){
	// at least one of several controls must be nonblank, must be set on a hidden field
	if (elemtype!='hidden') return this.fail();
	if (params.length < 2) return this.fail();
	found=false;
	re=/^[ \f\n\r\t\v]*$/;
	for(i=1;i<params.length;i++){
		if(typeof this.f.elements[params[i]] == 'undefined') return this.fail();
		etype=this.getType(this.f.elements[params[i]]);
		if(etype=='text' && !re.test(this.f.elements[params[i]].value)) found=true;
	}
	if(!found) return this.error(elem);

}else if (proot == 'file'){
	// file extension must be of a list of types, trimmed, may not be blank
	if (params.length < 2 || elemtype!='file') return this.fail('file');				
	elem.value=elem.value.Trim();
	extfound=false;
	if (elem.value==''){
		return this.error(elem);
	}else for(k=1;k<params.length;k++){
		re = new RegExp('.*\.'+params[k]+'$','i');
		if (re.test(elem.value)){
			extfound=true;
			break;
		}
	}
	if(!extfound) return this.error(elem);

}else if (proot == 'radio'){
	// one radio must be checked, it is enough with one validator
	if (elemtype!='radio') return this.fail();
	if (elem==this.f.elements[elem.name] && !elem.checked){
		return this.error(elem);
	}else{
		checkedfound=false;
		elems = this.f.elements[elem.name];
		for (i=0;i<elems.length;i++) if(elems.item(i).checked){
			checkedfound=true;
			break;
		}
		if(!checkedfound) return this.error(elem);
	}

}else if (proot == 'checked'){
	// a checkboc must be checked
	if (elemtype!='checkbox') return this.fail();
	if (!elem.checked){
		return this.error(elem);
	}
}else{return this.fail();}
		}
	}
	if (sbutton != null) sbutton.disabled = true;
	return true;
}
function validateForm(f){var v=new Validator(f);return !v.enabled || v.validate();}

