function Validator(frmname)
{
	var validation = Array(); //array of fields to validate
	var isValid = true;
	
	if((this.formobj = $("form[@name="+frmname+"]")).size() <= 0) {
		alert("ERROR: could not get form object: " + frmname);
		return;
	}
	
	
	this.setup = function() {
		
		for(var i=0; i<arguments.length; i++) {
			var fieldobj = $("#"+arguments[i].id);
			fieldobj.num = i;
			if(fieldobj.size() <= 0) {
				alert("ERROR: Did not find: " + arguments[i].id);
				return;
			}
			for (var name in arguments[i]) {
				if(name == 'live' && arguments[i][name] == true) {
					fieldobj.bind("keypress",{num:i,validator:this}, function(e) {e.data.validator.validate("warning",e.data.num);}  );
					fieldobj.bind("focus",{num:i,validator:this}, function(e) {if (e.data.validator.isValid == true) {
						e.data.validator.validate("warning", e.data.num);
					}}  );
				}
			}
			if(val = arguments[i]['restrict']) {
				fieldobj.bind("input blur change keyup keydown",{val:val,num:i,validator:this},function(e){

                    var value = $("#"+e.data.validator.validation[e.data.num].id).val();
                    var len = value.length;
					if (len > 0) {
						var newstring = '';
						for (var j = 0; j < len; j++) {
							var char = value.substr(j, 1);
							if (char.search(e.data.val) != -1) {
								newstring += char;
							}
							else 
								if (e.data.val.search(/ /) == -1 && e.data.val.search(/_/) != -1 && char == " ") {
									newstring += "_";
								}
						}
						$("#" + e.data.validator.validation[e.data.num].id).val(newstring);
						
					}
					if(e.type == "keydown") {
						
						var KeyID = (window.event) ? event.keyCode : e.keyCode;
						
						if(KeyID >= 65 && KeyID <= 90 || KeyID >= 48 && KeyID <= 57) {
							
							if (!e) var e = window.event;
							if (e.keyCode) code = e.keyCode;
							else if (e.which) code = e.which;
							var character = String.fromCharCode(code);
							if(e.shiftKey == false) {
								character = character.toLowerCase();
							}
							var charpos = character.search(e.data.val);
							if(charpos == -1) { 
								return false; 
							}
						}
						return true;
						
					}
                });
			}
		}
		this.validation = arguments;
	}
	
	this.validate = function (level) {
		this.isValid = true;
		if(arguments.length>1 && !isNaN(arguments[1])) {//specify a field to validate
			
			for (var name in this.validation[arguments[1]]) {
				errorstr = '';
				value = this.validation[arguments[1]][name];
				obj = $("#"+this.validation[arguments[1]].id);
				
				if(this.validation[arguments[1]].required==true && name != "id" && (errorstr = check(obj , name , value)) !=  true || obj.val() != "" && name != "id" && (errorstr = check(obj , name , value)) !=  true) {
					this.isValid = false;
					break;
				}
			}
		} else { //validate all fields
			for(var i=0; i < this.validation.length && this.isValid == true; i++) {
				for (var name in this.validation[i]) {
					errorstr = '';
					value = this.validation[i][name];
					obj = $("#"+this.validation[i].id);
					
					if(this.validation[i].required==true && name != "id" && (errorstr = check(obj , name , value)) !=  true || obj.val() != "" && name != "id" && (errorstr = check(obj , name , value)) !=  true) {
						this.isValid = false;
						if(this.validation[i]['showError'] != undefined) {
							obj = $("#"+this.validation[i]['showError']);
						}
						break;
					}
				}
				
			}
		}
		
		if(this.isValid) {
			hideNotice();
		} else {
			if(level == "error") {
				obj.focus();
			}
			showNotice(level,errorstr,obj);
		}
		return this.isValid;
	}

	//this.formobj.bind("submit", function(){ return eval(frmname+"_validator.validate('error')"); } );
	this.formobj.bind("submit",{validator:this}, function(e) {return e.data.validator.validate("error");}  );

}

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 fieldvalue = (fieldobj.attr("value")==undefined?"":fieldobj.attr("value"));
	switch(type) { 
		case "required": 
		case "req":
			if(fieldvalue.length == 0) { 
				return "This is a required field";
			}
		break;             
		case "maxlength": 
		case "maxlen":
			if(fieldvalue.length >  parseInt(value)) { 
				return "Too many characters entered. Please enter "+value+"."; 
			}
		break;
        case "minlength": 
        case "minlen": 
			if(fieldvalue.length > 0 && fieldvalue.length <  parseInt(value)) { 
				return value+" characters are required.";                 
			}
		break; 
        case "alnum": 
        case "alphanumeric"://contains alphabetic or numeric values
			var charpos = fieldvalue.search("[^A-Za-z0-9]");
			if(charpos == null) { 
				alert(charpos)
				return false; 
			} 
		break;
		case "reqalphanumeric"://requires alphabetic and numeric values
			var charpos = fieldvalue.search("[^A-Za-z]");
			if(charpos == -1) { 
				return false; 
			} 
			var charpos = fieldvalue.search("[^0-9]");
			if(charpos == -1) { 
				return false; 
			} 
		break;
        case "num": 
        case "numeric":  
			var charpos = fieldvalue.search("[^0-9]"); 
			if(fieldvalue.length > 0 &&  charpos >= 0) { 
				return "Please enter a numeric value."; 
			}
		break;               
        case "alphabetic": 
        case "alpha": 
			var charpos = fieldvalue.search("[^A-Za-z]"); 
			if(fieldvalue.length > 0 &&  charpos >= 0) { 
				return false; 
			} 
		break;
		case "alnumhyphen":
			var charpos = fieldvalue.search("[^A-Za-z0-9\-_]"); 
			if(fieldvalue.length > 0 &&  charpos >= 0) { 
				return false; 
			}			
			break;
        case "email": 
			if(fieldvalue.length > 0 && !validateEmail(fieldvalue)) { 
				return "Please enter a valid email address."; 
			}
		break; 
        case "email_confirm": 
			if(fieldvalue != $('email').value) {
				return false; 
			}
		break;  
        case "lt": 
        case "lessthan": 
			if(isNaN(fieldvalue)) { 
				return false; 
			}
			if(fieldvalue >=  parseInt(cmdvalue)) { 
				return false;                 
			}             
		break; 
        case "gt": 
        case "greaterthan": 
			if(isNaN(fieldvalue)) { 
				return false; 
			}
			if(fieldvalue <=  parseInt(cmdvalue)) { 
				return false;                 
			}            
		break; 
        case "regexp": 
		 	if(fieldvalue.length > 0) {
	            if(!fieldvalue.match(cmdvalue)) { 
	              return false;                   
	            }
			}
		break; 
    } 
	return true;
}
function selectDay(field_id) {
	var year = $('#'+field_id+'_year').val();
	var month = $('#'+field_id+'_month').val();
	var dayObj = $('#'+field_id+'_day');
	if(year != "" && month != "") {
		var currentSel = dayObj[0].selectedIndex;
		var dim = days_in_month(year, month-1);

		html = '<option></option>';
		for(var i=1;i<=dim; i++) {
			html += '<option>'+i+'</option>';
		}
		dayObj.html(html);
		if(currentSel > dim) {
			dayObj[0].selectedIndex = dim;
		} else {
			dayObj[0].selectedIndex = currentSel;
		}
	}
	updateDate(field_id);
}
function updateDate(field_id) {
	var year = $('#'+field_id+'_year').val();
	var month = $('#'+field_id+'_month').val();
	var day = $('#'+field_id+'_day').val();
	dateString = '';
	if(year != '') {
		dateString += year + '-'; 
	} else {
		dateString += '0000-';
	}
	if(month != '') {
		dateString += month + '-';
	} else {
		dateString += '00-';
	}
	if(day != '') {
		dateString += day;
	} else {
		dateString += '00';
	}
	$('#'+field_id).attr('value',dateString);
}
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[0]).end == 0 && (num-1) >= 0) {
		if(KeyID == 37 || KeyID == 8){//leftkey, backspace
			setCaretPosition(previous[0],previous.attr('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.val().length >= current.attr('size') && getCaretPos(current[0]).end == current.attr('size')) {
		if((num+1) < 3 && KeyID != 9 & KeyID != 16) {//not tab key or shift key
			setCaretPosition(next[0],0);
		}
	} 
	$('#'+id).attr('value', $('#'+id+'_0').val()+$('#'+id+'_1').val()+$('#'+id+'_2').val());
	
	var size = Number($('#'+id+'_0').attr('size'))+Number($('#'+id+'_1').attr('size'))+Number($('#'+id+'_2').attr('size'));
	if($('#'+id).val().length !=  size && $('#'+id).val.length > 0) {
		showNotice("warning",size + " characters are required.",$('#'+id+'_2'));
	} else {
		hideNotice();
	}
}

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 showNotice(type, message, obj) {	
	$("#notice").show();
	$("#notice").attr("className",type);
	positionNotice(obj);
	$(window).bind("resize",function(){
		positionNotice(obj);
	});
	$("#notice table tr td.c").html(message);
}

function hideNotice() {
	$("#notice").hide();
	$(window).unbind("resize");
}

function positionNotice(obj) {
	var offset = obj.offset();
	$('#notice').css('left', ((offset.left+obj.outerWidth())-5)+'px');
	$('#notice').css('top', offset.top+'px');
}

function countryChange(countryObj, stateObj) {
	var country = $('#'+countryObj+'_country');
	value = country.val().split(':');
	
	if(stateObj != null) {
		var stateSelect = $('#'+stateObj+'_stateSelect');
		var stateText = $('#'+stateObj);
	}
	
	if(value.length == 1) {
		if(stateObj != null) {
			//show textfield
			stateSelect.hide();
			stateText.show();
		}
		$('#'+countryObj).val(value);
	} else {
		$('#'+countryObj).val(value[0]);
		
		if(stateObj != null) {
			//show select
			stateSelect.show();
			stateText.hide();
			
			states = value[1].split(",");	
			html = '<option></option>';
			for(i=0;i<states.length;i++) {
				html += '<option value="'+states[i]+'">'+states[i]+'</option>';
			}
			stateSelect.html(html);
			stateSelect.val('option:first').attr('selected', 'selected');
		}
	}
}

function stateUpdate(obj) {
	$('#'+obj).val($('#'+obj+'_stateSelect').val());
}

/* Preload Images */
var preloaded = new Array();
function preload_images() {
	for (var i = 0; i < arguments.length; i++){
		preloaded[i] = document.createElement('img');
		preloaded[i].setAttribute('src',arguments[i]);
	};
};


//preload validation images
preload_images(
	"/puppy/images/validation/error.png",
	"/puppy/images/validation/warning.png"
);
