Crazy Form validation with jQuery

by Faisal Khan Janjua

HTML

<p>All fields are required except month</p>
<form action="#" method="post" class="validateForm">
<input name="fullname" minlength="3" maxlength="50" data-required="true" data-validate="alphabetsOnly" placeholder="First Name" />
<textarea name="address" maxlength="300" data-required="true" data-validate="commentsOnly" placeholder="Address (Street name and Unit #)"></textarea>
<input type="number" name="cardMonth" min="6" max="12" data-required="false" data-validate="numbersOnly" placeholder="Month" />
<select name="country" placeholder="Country" data-required="true">
  <option value="">--Select Country--</option>
  <option value="PK">Pakistan</option>
  <option value="KSA">Saudi Arabia</option>
</select>

<div class="formErrors">Please fill the correct information in above fields</div>

<button type="submit">Send</button>
</form>

<!-- 
==========INSTRUCTIONS==========
  1. Class "validateForm" on form tag is important if you want to validate whole form on submit before submitting.
  2. Every required field must include data attribute like data-required="true"
  3. Every field can be validated in several types and must have attribute like data-validate="numbersOnly" having one of the following values:
    a. numbersOnly
    b. alphabetsOnly
    c. alphanumeric
    d. commentsOnly
    e. validateEmail
  4. Attribute 'max' and 'maxlength' will be handled with js if used for number or string field respectively.
  5. Attribute 'min' and 'minlength' will throw error with Js.
  6. You need to copy error related CSS for hiding and showing error messages.
  7. Disabled fields will not validated by default
-->

CSS

input, textarea, select {
  width: 80%;
  border: 1px solid #999;
}
button {
  width: 200px;
}
span.error, div.error, p.error {
    color: red;
    display: block;
    font-size: 13px;
    margin-bottom: 10px;
}
input.error, textarea.error, select.error {
  border-color: red;
}
.formErrors {
	display: none;
  margin-top: 20px;
}
.formErrors.error {
  display: block;
}

JavaScript

/************** Validations Start **************/
$(document).on('keypress', '[data-validate="numbersOnly"]', function (e) {
	if(e.key=='e'||e.key=='E'||e.key=='+'||e.key=='-'){ return false; }
	if(!$(this).hasClass('allowDecimals')){ if(e.key=='.'){ return false; } }
}); // fix characters on input[type="number"] field

$(document).on('input paste mouseenter blur change', '[data-required], [data-validate]', function (e) {
	crazyFormValidator($(this), e);
});

/* Form Validation Start */
$(document).on('submit', '.validateForm', function (e) {
	e.preventDefault();
	var validForm = true, errorCount = 0;
	$(this).find('[name]').each(function (){
		var response = crazyFormValidator($(this));
		if(response == false) { errorCount++; }
	});
	if(errorCount>0) { validForm = false; }
	if(validForm) { $('.formErrors').removeClass('error'); }
	else{ $('.formErrors').addClass('error'); }
	if(validForm){console.log('Submitting form...');}
	return validForm;
});
/* Form Validation End */
function crazyFormValidator(field, e){
	if(e){
		var tag = field.prop("tagName");
		if(e.type != 'mouseenter' && field.attr('data-required') == 'true' && field.val().trim() == '') {
			field.addClass('error');
			if(field.next('span.error').length < 1){
				field.after('<span class="error">' + field.attr('placeholder') + ' is required.</span>');
			}
		}
		if(e.type != 'mouseenter' && field.attr('data-required') == 'true' && field.val()) {
			field.removeClass('error').next('span.error').remove();
			$('.formErrors').removeClass('error');
		}
		if((e.type=='input'||e.type=='mouseenter'||e.type=='paste') && (tag == 'INPUT'||tag == 'TEXTAREA')){
			var maxVal = parseInt(field.attr('max'));
			if(maxVal){ if(parseInt(field.val()) >= maxVal) { field.val(maxVal); } }
			var maxLn = parseInt(field.attr('maxlength'));
			if(maxLn) { if(field.val().length >= maxLn) { field.val(field.val().substring(0, maxLn)); } }
		}
		if(field.attr('data-validate')){
			var incRx = '';
			if(e.type == 'mouseenter' ||...