
(function($) {

	$.validate = function(options)
	{
		// Set up some options
		options = options || {};
		options.fieldset = options.fieldset || "";
		options.messagecontainer = options.messagecontainer || ".validationmsg";
		options.errormsg = options.errormsg || ".errmsg";
		options.notvalidclass = options.notvalidclass || "redbrdr";
		options.messageheader = options.messageheader || "Validation errors were found with:";
		options.onerror = options.onerror || "";
		options.erroridprefix = options.erroridprefix || "validationerror_";
		options.selectboxdefault = options.selectboxdefault || [""];
		options.selectboxdefaultclass = options.selectboxdefaultclass || "defaultval";
		options.usedefault = options.usedefault || false;

	    var errors = new Array();

		$("." + options.notvalidclass).each(function(i, item) {
			$(item).removeClass(options.notvalidclass);
		});

		function isEmail(str){
		    var regex = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/;
		    return regex.test(str);
	    }

	    function isUrl(str) {
		    var regex = /^((http|ftp|https):\/\/w{3}[\d]*.|(http|ftp|https):\/\/|w{3}[\d]*.)([\w\d\._\-#\(\)\[\]\\,;:]+@[\w\d\._\-#\(\)\[\]\\,;:])?([a-z0-9]+.)*[a-z\-0-9]+.([a-z]{2,3})?[a-z]{2,6}(:[0-9]+)?(\/[\/a-z0-9\._\-,]+)*[a-z0-9\-_\.\s\%]+(\?[a-z0-9=%&amp;\.\-,#]+)?$/;
		    return regex.test(str);
	    }

        function isDate(str) {
		    var regex = /^((0?[13578]|10|12)(-|\/)((0[0-9])|([12])([0-9]?)|(3[01]?))(-|\/)((\d{4})|(\d{2}))|(0?[2469]|11)(-|\/)((0[0-9])|([12])([0-9]?)|(3[0]?))(-|\/)((\d{4}|\d{2})))$/;
		    return regex.test(str);
	    }
	    
	    function isSixDigitYear(str){
			var regex = /^((0[1-9])|(1[0-2]))\/(\d{4})$/;
			return regex.test(str);
	    }

        function isTime(str) {
		    var regex = /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$/;
		    return regex.test(str);
	    }

	    function isNumber(str) {
		    var regex = /^[0-9-]*$/;
		    return regex.test(str);
	    }

	    function isDollar(str){
			var regex = /^\-?\$?(((\d{1,3},)+\d{3})|\d+)(\.\d{1,2})?$/;
		    return regex.test(str);
	    }

	    function isQuarter(str) {
		    var regex = /^[1-4]{1}$/;
		    return regex.test(str);
	    }

	    function isYear(str) {
		    var regex = /^[0-9]{4}$/;
		    return regex.test(str);
	    }
	    
	    function isSSN(str){
			var regex = /^\d{3}-\d{2}-\d{4}$/;
			return regex.test(str);
	    }
	    
	    function isCloseYear(item){
			var diff;
			var rt;
			var msg;
			var val;
			var dt = new Date().getYear();

			if (item.value.length == 7 && isSixDigitYear(item.value)){
				val = item.value.substr(3,4);
			} else if (isDate(item.value)){
				val = Date.parse(item.value, 'MM/dd/yyyy').getFullYear();
			}
			if (val != ""){
				diff = Math.abs(parseInt(dt) - parseInt(val));
				if (diff > 1){
					msg = getMsg(item);
					msg = msg.replace(".", "");
					if (confirm(msg + " is " + diff + " years from now.\nIs this correct?")){
						rt = true;
					} else {
						rt = false;
					}
				}
		    } else {
				rt = true;
		    }
		    return rt;
	    }

	    function isZip(str) {
			var rt;
		    var regex = /^[0-9-]{5}$/;
		    rt = regex.test(str);
		    return rt;
	    }

	    function isZipExt(str) {
			var rt = false;
		    var regex = /^[0-9-]{4}$/;
		    if (str != ""){
				rt = regex.test(str);
		    }else{
				rt = true;
			}
			return rt;
	    }

	    function isEmpty(item) {
		    if (item.value == "")
		        return true;
            if (options.usedefault && item.value == $(item).attr("title"))
                return true;

            return false;
	    }

		function getMsg(item){
			return $(item.parentNode).find(options.errormsg).html();
		}

		function validateTextBox(item){
			if ($(item).hasClass("email") && isEmail(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

            if ($(item).hasClass("url") && isUrl(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

            if ($(item).hasClass("date") && isDate(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

            if ($(item).hasClass("time") && isTime(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

			if ($(item).hasClass("number") && isNumber(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "number"});
			}

			if ($(item).hasClass("zip") && isZip(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

			if ($(item).hasClass("zipext") && isZipExt(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
			
			if ($(item).hasClass("quarter") && isQuarter(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}

			if ($(item).hasClass("year") && isYear(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
			
			if ($(item).hasClass("datesix") && isSixDigitYear(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
			
			if ($(item).hasClass("closeyear") && isCloseYear(item) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
			
			if ($(item).hasClass("dollar") && isDollar(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
			
			if ($(item).hasClass("ssn") && isSSN(item.value) == false){
				errors.push({id: item.id, msg: getMsg(item), type: "text"});
			}
		}

		function validateCheckbox(item){
			if(item.checked != true)
				errors.push({id: item.id, msg: getMsg(item), type: "checkbox"});
		}

		function validateSelect(item){	
			if ($.inArray(item.value, options.selectboxdefault) > -1 || item[item.selectedIndex].className == options.selectboxdefaultclass)
				errors.push({id: item.id, msg: getMsg(item), type: "select-one"});
		}

		function validatePassword(){
			if ($(".pwmatch").length == 2){ 
				if ($(".pwmatch").get(0).value + $(".pwmatch").get(1).value != ""){
					if ($(".pwmatch").get(0).value != $(".pwmatch").get(1).value){
						errors.push({id: $(".pwmatch").get(0).id, msg: "Passwords do not match.", type: "password"});
						errors.push({id: $(".pwmatch").get(1).id, msg: "", type: "password"});
					}
				}else{
					errors.push({id: $(".pwmatch").get(0).id, msg: "Passwords can not be empty.", type: "password"});
					errors.push({id: $(".pwmatch").get(1).id, msg: "", type: "password"});
				}
			}
		}
				
		// Loop required
		$(options.fieldset + " .required").each(function(i, item) {
			if (isEmpty(item) == true){
				errors.push({id: item.id, msg: getMsg(item), type: item.type});
			}else{
				switch (item.type){
					case "checkbox":
						validateCheckbox(item);
						break;					
					case "text":
					case "file":
					case "hidden":
					case "textarea":
						validateTextBox(item);
						break;				
					case "select-one":
						validateSelect(item);
						break;
					case "password":
						validatePassword();
						break;
				}
			}
		});

		// Loop
		$(options.fieldset + " .notrequired").each(function(i, item) {
			if (isEmpty(item) == false){
			switch (item.type){
					case "checkbox":
						validateCheckbox(item);
						break;					
					case "text":
					case "file":
					case "hidden":
					case "textarea":
						validateTextBox(item);
						break;				
					case "select-one":
						validateSelect(item);
						break;
					case "password":
						validatePassword();
						break;
				}
			}
		});

		$(options.fieldset + " .checkboxgroup," + options.fieldset + " .radiogroup").each(function(i, item) {
			var checked = 0;
			var msg = $(item).find(options.errormsg).text();

			$(item).find("input[type=checkbox], input[type=radio]").each(function(i, item) {
				if (item.checked)
					checked++;
			});

			if(checked == 0)
				errors.push({id: item.id, msg: msg, type: "group"});
		});

		if (errors.length > 0){
			if (typeof(options.onerror) == "function"){
				options.onerror(errors);
				return false;
			}
			var msg = options.messageheader + '\n';

			$(errors).each(function(i, item) {
				$("#" + item.id).addClass(options.notvalidclass);
				if (item.msg != ""){
					msg = msg + item.msg + '\n';				
				}
			});

			alert("Errors were found with the highlighted items.");
			return false;
		}
		
		return true;
	}
})(jQuery);