function Validator(frmname)
{
	var validate = Array(); //array of fields to validate
	
	this.formobj=document.forms[frmname];
	if(!this.formobj) {
		alert("ERROR: could not get Form object " + frmname);
		return;
	}
	//clear submit actions
	if(this.formobj.onsubmit) {
		this.formobj.old_onsubmit = this.formobj.onsubmit;
		this.formobj.onsubmit=null;
	} else {
		this.formobj.old_onsubmit = null;
	}
	
	//field to validate, errorstr of field for error string, type of validation
	this.add = function(field,validation) { 
		var fieldobj = this.formobj[field];
		if(!fieldobj) {
			alert("ERROR: Did not find the field: " + field);
			return;
		}
		for(var i=0;i<validation.length;i++) {
			if(validation[i].type == 'live') {
				//alert(frmname+"_validator.validate('"+field+"')");
				$(field).onkeyup=function(){eval(frmname+"_validator.validate('"+field+"')");};
				$(field).onfocus=function(){eval(frmname+"_validator.validate('"+field+"')");};
			}
			if(validation[i].type == 'restrict') {

				var val = validation[i].value;
				$(field).onkeypress=function(e){return eval("restrict(e,'"+val+"')")};
			}
		}
		validate.push(Array(field,validation));
	}
	
	this.doValidation = function () {		
		var isValid = true;
		//loop through fields to validate
		for(var i=0; i < validate.length && isValid == true; i++) {
			//loop through field validation
			for(var j=0; j < validate[i][1].length; j++) {
				errorstr = '';
				if((errorstr = check($(validate[i][0]),validate[i][1][j].type,validate[i][1][j].value)) !=  true) {
					isValid = false;
					$(validate[i][0]).focus();
					if(validate[i][1][j].position != null) { 
						showNotice("error",errorstr,$(validate[i][1][j].position));
					} else {
						showNotice("error",errorstr,$(validate[i][0]));
					}
					
					break;
				}
			}
		}
		
		return isValid;
	}
	
	this.formobj.onsubmit = this.doValidation;
	
	this.validate = function (field) {
		var isValid = true;
		
		for(var i=0; i < validate.length && isValid == true; i++) {
			if(field == validate[i][0]){
				
				//loop through field validation
				for(var j=0; j < validate[i][1].length; j++) {
					errorstr = '';
					if((errorstr = check($(validate[i][0]),validate[i][1][j].type,validate[i][1][j].value)) !=  true) {
						isValid = false;
						$(validate[i][0]).focus();
						if(validate[i][1][j].position != null) {
							showNotice("warning",errorstr,$(validate[i][1][j].position));
						} else {
							showNotice("warning",errorstr,$(validate[i][0]));
						}
						break;
					}
					
				}				
				break;
			}
		}
		if(isValid) {
			hideNotice();
		}		
		return isValid;
	}
}
function validateEmail(email) {
    if(email.length <= 0) {
	  return false;
	}
    var splitted = email.match("^(.+)@(.+)$");
    if(splitted == null) return false;
    if(splitted[1] != null ) {
		var regexp_user=/^\"?[\w-_\.]*\"?$/;
		if(splitted[1].match(regexp_user) == null) return false;
    }
    if(splitted[2] != null) {
		var regexp_domain=/^[\w-\.]*\.[A-Za-z]{2,4}$/;
		if(splitted[2].match(regexp_domain) == null) {
			var regexp_ip =/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/;
			if(splitted[2].match(regexp_ip) == null) return false;
		}
		return true;
    }
	return false;
}

function check(fieldobj, type, value) {
	//var epos = type.search("="); 
    //var  command  = ""; 
    //var  cmdvalue = ""; 
	//if(epos >= 0) { 
		//command  = type.substring(0,epos); 
		//cmdvalue = type.substr(epos+1); 
	//} else { 
		//command = type; 
	//} 
	
	switch(type) { 
		case "required": 
		case "req":
			if(fieldobj.value.length == 0) { 
				return "This is a required field.";
			}
		break;             
		case "maxlength": 
		case "maxlen":
			if(fieldobj.value.length >  parseInt(value)) { 
				return false; 
			}
		break;
        case "minlength": 
        case "minlen": 
			if(fieldobj.value.length > 0 && fieldobj.value.length <  parseInt(value)) { 
				return value+" characters are required.";                 
			}
		break; 
        case "alnum": 
        case "alphanumeric"://contains alphabetic or numeric values
			var charpos = fieldobj.value.search("[^A-Za-z0-9]");
			if(charpos == null) { 
				alert(charpos)
				return false; 
			} 
		break;
		case "reqalphanumeric"://requires alphabetic and numeric values
			var charpos = fieldobj.value.search("[^A-Za-z]");
			if(charpos == -1) { 
				return false; 
			} 
			var charpos = fieldobj.value.search("[^0-9]");
			if(charpos == -1) { 
				return false; 
			} 
		break;
        case "num": 
        case "numeric":  
			var charpos = fieldobj.value.search("[^0-9]"); 
			if(fieldobj.value.length > 0 &&  charpos >= 0) { 
				return "Please enter a numeric value."; 
			}
		break;               
        case "alphabetic": 
        case "alpha": 
			var charpos = fieldobj.value.search("[^A-Za-z]"); 
			if(fieldobj.value.length > 0 &&  charpos >= 0) { 
				return false; 
			} 
		break;
		case "alnumhyphen":
			var charpos = fieldobj.value.search("[^A-Za-z0-9\-_]"); 
			if(fieldobj.value.length > 0 &&  charpos >= 0) { 
				return false; 
			}			
			break;
        case "email": 
			if(fieldobj.value.length > 0 && !validateEmail(fieldobj.value)) { 
				return "Please enter a valid email address."; 
			}
		break; 
        case "email_confirm": 
			if(fieldobj.value != $('email').value) {
				return false; 
			}
		break;  
        case "lt": 
        case "lessthan": 
			if(isNaN(fieldobj.value)) { 
				return false; 
			}
			if(fieldobj.value >=  parseInt(cmdvalue)) { 
				return false;                 
			}             
		break; 
        case "gt": 
        case "greaterthan": 
			if(isNaN(fieldobj.value)) { 
				return false; 
			}
			if(fieldobj.value <=  parseInt(cmdvalue)) { 
				return false;                 
			}            
		break; 
        case "regexp": 
		 	if(fieldobj.value.length > 0) {
	            if(!fieldobj.value.match(cmdvalue)) { 
	              return false;                   
	            }
			}
		break; 
    } 
	return true;
}
function selectDay(field_id) {
	var year = $(field_id+"_year").value;
	var month = $(field_id+"_month").value;
	var dayObj = $(field_id+"_day");
	if(year != "" && month != "") {
		//dayObj.style.display = "block";
		var currentSel = dayObj.value;
		var dim = days_in_month(year, month-1);
		dayObj.options.length = 0; //clear
		for(var i=1;i<=dim; i++) {
			dayObj.options[i] = new Option(i,i);
		}
		if(currentSel > dayObj.length) {
			dayObj.selectedIndex = dayObj.length-1;
		} else {
			dayObj.selectedIndex = currentSel;
		}
	
	} else {
		//dayObj.style.display = "none";
	}
	updateDate(field_id);
}
function updateDate(field_id) {
	var year = $(field_id+"_year").value;
	var month = $(field_id+"_month").value;
	var day = $(field_id+"_day").value;
	$(field_id).value= year + "-" + month + "-" + day;
}
function days_in_month (year, month) {
     return 32 - new Date(year, month, 32).getDate();
}
function phoneKeyDown(e, id, num) {
	current = $(id+"_"+num);
	next = $(id+"_"+(num+1));
	previous = $(id+"_"+(num-1));
	
	var KeyID = (window.event) ? event.keyCode : e.keyCode;

	if(getCaretPos(current).end == 0 && (num-1) >= 0) {
		if(KeyID == 37 || KeyID == 8){//leftkey, backspace
			setCaretPosition(previous,previous.value.length);
		}
	}
}

function phoneKeyUp(e, id, num) {
	current = $(id+"_"+num);
	next = $(id+"_"+(num+1));
	previous = $(id+"_"+(num-1));
	
	var KeyID = (window.event) ? event.keyCode : e.keyCode;

	if(current.value.length >= current.size && getCaretPos(current).end == current.size) {
		if((num+1) < 3 && KeyID != 9 & KeyID != 16) {//not tab key or shift key
			setCaretPosition(next,0);
		}
	} 
	$(id).value = $(id+"_0").value+$(id+"_1").value+$(id+"_2").value;
	
	var size = $(id+"_0").size+$(id+"_1").size+$(id+"_2").size;
	if($(id).value.length !=  size && $(id).value.length > 0) {
		showNotice("warning",size + " characters are required.",$(id+"_2"));
	} else {
		hideNotice();
	}
}

function isNumberKey(evt) {
	var KeyID = (window.event) ? event.keyCode : evt.keyCode;
	if(KeyID != 9 && KeyID != 37) {//not tab or left key
		var charCode = (evt.which) ? evt.which : event.keyCode;
		if (charCode > 31 && (charCode < 48 || charCode > 57))
			return false;
	
		return true;
	}
}

function restrict(e, value) {
	var KeyID = (window.event) ? event.keyCode : e.keyCode;
	if(KeyID != 9 && KeyID != 37 && KeyID != 8 && KeyID != 39 && KeyID != 13) {//not tab or left key or backspace or right or enter
		if (!e) var e = window.event;
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		var character = String.fromCharCode(code);
		var charpos = character.search(value);
		if(charpos == -1) { 
			return false; 
		}
	}
	return true;
}



function getCaretPos(input) {
	var result = { start: 0, end: 0 };
	if (input.setSelectionRange) {
		result.start = input.selectionStart;
		result.end = input.selectionEnd;
	} else if (document.selection && document.selection.createRange) {
		var range = document.selection.createRange();
		var r2 = range.duplicate();
		result.start = 0 - r2.moveStart('character', -100000);
		result.end = result.start + range.text.length;
	}
	return result;
}
function setCaretPosition(field, pos) {
	if(field.setSelectionRange) {
		
		field.setSelectionRange(pos,pos);
		field.focus();
	} else if (field.createTextRange) {
		var range = field.createTextRange();
		range.collapse(true);
		range.moveEnd('character', pos);
		range.moveStart('character', pos);
		range.select();
	}
}


function $(field) {
	return document.getElementById(field);
}

function findPosX(obj) {
	var curleft = 0;
	if(obj.offsetParent) {
		while(1) {
			curleft += obj.offsetLeft;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	} else if(obj.x) {
		curleft += obj.x;
	}
	return curleft;
}

function findPosY(obj) {
	var curtop = 0;
	if(obj.offsetParent) {
		while(1) {
			curtop += obj.offsetTop;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		} 
	} else if(obj.y) {
		curtop += obj.y;
	}
	return curtop;
}

function showNotice(type, message, obj) {
	
	$("notice").className = type;
	$("notice").style.display = "block";
	$("notice_message").innerHTML = message;
	positionNotice(obj);
	window.onresize = function() {
		positionNotice(obj);
	}
}

function hideNotice() {
	$("notice").style.display = "none";
	window.onresize = null;
}

function positionNotice(obj) {
	$("notice").style.left = (findPosX(obj)+obj.offsetWidth)+"px";
	$("notice").style.top = (findPosY(obj)-(obj.offsetHeight/2))+"px";
}
