/*
cosValidate jQuery plugin v1.41
Written by: J. Williams, City of Spokane

Changelog:
v1.43 Further fixes to .trim() for all versions of Internet Explorer
v1.42 Adjusted zip code error message
v1.41 Fixed support for jQuery.trim() in Internet Explorer
v1.4: Added support for 'required' on radioboxes
v1.3: Added 'ordered' class for an order-specific error message
v1.2: Added support for 'required' on checkboxes
v1.1: Added support for multiple forms on a single page
v1.0: First full release

Looks through a form for elements with class names and validates them accordingly. Requires form elements have 'name' attribute. Elements which fail validation are given the class 'bad', which can be styled to suit, and a message in a <span class='bad'> is appended following the element.

Validation classes for form elements are:
    required: Only elements with this class attribute will be checked
	alpha: Alphabetic  (A-Z, a-z) characters only
	alphaSpaces: Alphabetic characters and spaces
	alphaNumeric: Alphabetic and numeric (0-9) characters
	alphaNumericSpaces: Alphabetic and numeric characters and spaces
	noAlpha: All characters except alphabetic
	noNumbers: All characters except numeric
	number: Must be a number, whole or decimal
	integer: Must be a whole number
	decimal: Must be a decimal number
	numberNonNegative: Must be zero or a positive number
	numberPositive: Must be a positive number
	date: Must be a date. Accepts formats: mm/dd/yyyy, mm/dd/yy, mm-dd-yyyy, mm-dd-yy
	email: Must be an email address
	ssn: Must be a US Social Security number XXX-XX-XXXX
	zip: Must be a US Zip code, +4 optional
	usPhone: A US phone number, with area code
    usPhoneNoArea: A US phone number, without area code
	hexColor: A hexidecimal color code, optional # prefix
	ordered: Must be a value of 'true' to not trigger error 'These must be in the correct order'

EXAMPLE:
	JavaScript:
	$('form#formName').cosValidate();
	
	HTML:
	<form id="formName">
		<input type="text" name="firstName" class="required alphaSpaces" />
		<input type="submit" name="sendForm" />
	</form>
*/
var regularExpressions = {
	alpha: function() { return new RegExp('^[a-zA-Z]+$'); },
	alphaSpaces: function() { return new RegExp('^[a-zA-Z ]+$'); },
	alphaNumeric: function() { return new RegExp('^[a-zA-Z0-9]+$'); },
	alphaNumericSpaces: function() { return new RegExp('^[a-zA-Z0-9 ]+$'); },
	noAlpha: function() { return new RegExp('^[^a-zA-Z]$'); },
	noNumbers: function() { return new RegExp('^[^0-9]$'); },
	number: function() { return new RegExp('^[\\d\\.]+$'); },
	integer: function() { return new RegExp('^\\d+$'); },
	decimal: function() { return new RegExp('^\\d*\\.\\d+$'); },
	numberNonNegative: function() { return new RegExp('^[\\d\\.]+$'); },
	numberPositive: function() { return new RegExp('^[1-9][\\d\\.]*$'); },
	date: function() { return new RegExp('^((0?[1-9])|(1[0-2]))[/-]((0?[1-9])|([1-2][0-9])|(3[0-1]))[/-]([1-2][0-9])?[0-9]{2}$'); },
	email: function() { return new RegExp('^([a-zA-Z0-9_\\-\\.])+@(([0-2]?[0-5]?[0-5]\\.[0-2]?[0-5]?[0-5]\\.[0-2]?[0-5]?[0-5]\\.[0-2]?[0-5]?[0-5])|((([a-zA-Z0-9\\-])+\\.)+([a-zA-Z\\-])+))$'); },
	ssn: function() { return new RegExp('^[0-9]{3}-[0-9]{2}-[0-9]{4}$'); },
	zip: function() { return new RegExp('^[0-9]{5}(-[0-9]{4})?$'); },
	usPhone: function() { return new RegExp('^([0-9]{3}(-| |\\.)?[0-9]{7})|([0-9]{3}(-| |\\.)[0-9]{3}(-| |\\.)[0-9]{4})|(\\([0-9]{3}\\) ?[0-9]{3}(-| |\\.)?[0-9]{4})$'); },
    usPhoneNoArea: function() { return new RegExp('^[0-9]{3}(-| |\\.)?[0-9]{4}$'); },
	hexColor: function() { return new RegExp('^(#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?)$'); }
};
(function($) {
	$.fn.cosValidate = function()	{
		var $formElements, $form;
	    var validForm = true;
	    
	    return this.each(function()	{
	        $form = $(this);
	        $formElements = $form.find('input, select, textarea');
	        $formElements.each(function() {
	            if ($(this).next('label').attr('for') == $(this).attr('id'))
	            {
	                $(this).next('label').after('<span class="' + $(this).attr('id') + ' feedback"></span>\n');
	            }
	            else
	            {
	                $(this).after('<span class="' + $(this).attr('id') + ' feedback"></span>\n');
	            }
	        });
	        $form.find('input, textarea').bind('keyup click change', function() { validate(); });
	        $form.find('select').bind('change', function() { validate(); });
	        validate();
        });
        function invalidElem($el, reason) {
		    $el.addClass('bad');
		    $form.find("span." + $el.attr('id')).addClass('bad');
		    $form.find("span." + $el.attr('id')).text(' '+reason+' ');
		    validForm = false;
	    }
	    function validElem($el) {
		    $el.removeClass('bad');
		    $form.find("span." + $el.attr('id')).remove('bad');
		    $form.find("span." + $el.attr('id')).text('');
	    }
	    function validate()	{
		    if (!$formElements)	{
			    $formElements = $form.find('input, select, textarea');
		    }
		    validForm = true;
		    $formElements.each(function() {
			    if ($(this).is('.required') && $.trim($(this).val()) === '') {
				    invalidElem($(this), 'This field is required'); }
				else if ($(this).is('.required') && $(this).attr('type') == 'checkbox' && $(this).is(':not(:checked)')) {
				    invalidElem($(this), 'This box must be checked'); }
			    else if ($(this).is('.required') && $(this).attr('type') == 'radio' && $(this).is(':not(:checked)')) {
				    invalidElem($(this), 'This option must be selected'); }
			    else if ($(this).is('.ordered') && $(this).val() != 'true') {
			        invalidElem($(this), 'These must be in the correct order'); }
			    else if ($(this).is('.alpha') && !regularExpressions.alpha().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be letters only'); }
			    else if ($(this).is('.alphaSpaces') && !regularExpressions.alphaSpaces().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be letters and spaces only'); }
			    else if ($(this).is('.alphaNumeric') && !regularExpressions.alphaNumeric().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be letters and numbers'); }
			    else if ($(this).is('.alphaNumericSpaces') && !regularExpressions.alphaNumericSpaces().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be letters, numbers and spaces'); }
			    else if ($(this).is('.number') && !regularExpressions.number().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a number'); }
			    else if ($(this).is('.integer') && !regularExpressions.integer().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a whole number'); }
			    else if ($(this).is('.decimal') && !regularExpressions.decimal().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a decimal number'); }
			    else if ($(this).is('.numberNonNegative') && !regularExpressions.numberNonNegative().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a non-negative number'); }
			    else if ($(this).is('.numberOneOrMore') && !regularExpressions.numberPositive().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a positive number'); }
			    else if ($(this).is('.date') && !regularExpressions.date().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a date'); }
			    else if ($(this).is('.hexColor') && !regularExpressions.hexColor().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a hexadecimal color'); }
			    else if ($(this).is('.email') && !regularExpressions.email().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a valid email address'); }
			    else if ($(this).is('.ssn') && !regularExpressions.ssn().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a valid Social Security Number: 123-45-6789'); }
			    else if ($(this).is('.zip') && !regularExpressions.zip().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a valid USPS Zip Code'); }
			    else if ($(this).is('.usPhone') && !regularExpressions.usPhone().test($.trim($(this).val()))) {
				    invalidElem($(this), 'This field must be a valid US Phone Number with area code'); }
			    else {
				    validElem($(this));	}
		    });
		    if(!validForm) {
			    $form.find('input[type=submit]').attr('disabled', 'disabled');
			    $form.find("span." + $form.find('input[type="submit"]').attr('id')).addClass('bad');
			    $form.find("span." + $form.find('input[type="submit"]').attr('id')).text(' Please fix the highlighted errors before sending. ');
		    }
		    else {
			    $form.find('input[type=submit]').removeAttr('disabled');
			    $form.find("span." + $form.find('input[type="submit"]').attr('id')).remove('bad');
			    $form.find("span." + $form.find('input[type="submit"]').attr('id')).text('');
		    }
	    };
	};
})(jQuery);
