« Back to Index

Basic Form Validator

View original Gist on GitHub

form-validator.md

require.config({ 
	catchError: {
		define: true
	}
});

require(["../ErrorHandler/errors"], function (handler) {
	require.onError = handler;
});

require(["validate"], function (validate) {
	validate(document.forms["formname"]);
});

define(function(){
	
	function validate (form) {
		var errors = [],
			form = form,
			fields = form.elements,
			formats = {
				number: function (field) {
					if (/^\D+/.test(field.value) || !field.value.length) {
						errors.push(field);
					}
				},
				date: function (field) {
					/*
						The regex allows the following formats:
							00/00/0000
							00/00/00
							0/0/00
					 */
					if (!/^\d{1,2}\/\d{1,2}\/\d{2,4}$/.test(field.value) || !field.value.length) {
    				    errors.push(field);
					}
				},
				email: function (field) {
					if (field.value.indexOf("@") === -1 || !field.value.length) {
						errors.push(field);
					}
				},
				mobile: function (field) {
					/*
						The regex allows the following formats:
							+44 07000000000
							07000000000
							+4407000000000
						
						So there is an optional +000 country code at the start (wrapped in a non-capturing group)
						We then allow for an optional space after the optional country code
						Finally we allow for 11 digits (no spaces)
					 */
					if (!/^(?:\+\d{1,3})?\s?\d{11}$/.test(field.value) || !field.value.length) {
						errors.push(field);
					}
				},
				password: function (field) {
					/*
						The regex makes sure there is at least 8 alpha-numerical characters
						And that at least one of those values is a number
						And that at least one of those values is a text character
						We use a positive lookahead (which checks to see if a sub pattern matches a specific position)
						The lookahead checks for any character (zero or more times) is followed by a digit (e.g. making sure there is at least one digit)
						The lookahead then checks for any character (zero or more times) is followed by a text character (e.g. making sure there is at least one text character)
						Finally after the two lookaheads we have the standard regex which makes sure there is at least 8 alpha-numerical characters
					 */
					if (!/^(?=.*\d)(?=.*[a-z])\w{8,}/i.test(field.value)) {
						errors.push(field);
					}
				},
				income: function (field) { 
					if (!/^[\d,.]+/.test(field.value) || !field.value.length) {
						errors.push(field);
					}
				},
				accountnumber: function (field) {
					if (!/^\d{8}$/.test(field.value)) {
						errors.push(field);
					}
				},
				cardnumber: function (field) {
					/*
						The following regex was actually borrowed from The Regular Expression Cookbook (co-written by the regex legend @stevenlevithan)
					 */
					if (!/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/g.test(field.value)) {
						errors.push(field);
					}
				},
				shortdate: function (field) {
					/*
						The regex allows the following formats:
							00/0000
							0/0000
							00/00
							0/00
					 */
					if (!/^\d{1,2}\/\d{2,4}$/.test(field.value) || !field.value.length) {
    				    errors.push(field);
					}
				},
			};
		
		form.onsubmit = function(){
			var len = fields.length,
				field,
				classname,
				i;
			
			errors = [];
			
			while(len--) {
				field = fields[len];
				classname = field.className;
				i = classname.indexOf("mandatory");
				
				if (i >= 0) {
					// For the validation script to work we need to ensure a specific format is used in the HTML.
					// The main principle is to make sure the last class on an input is either 'mandatory' or 'mandatory-xxxx' 
					// e.g. 'mandatory-number', 'mandatory-dob', 'mandatory-email', 'mandatory-mobile', 'mandatory-password'
					
					if (classname.split("mandatory-")[1]) {
						// If there is a second item then we know there is a specific type to validate against
						formats[classname.split("mandatory-")[1]](field);
					} else {
						// Otherwise we validate by standard method
						// e.g. if the length is zero (meaning the field is empty) then zero will coerce to false
						// 		so we return the opposite of that using the ! operator (so the first part of the following condition is met)
						// 		and if the length is greater than zero then the regex checks to see if the content isn't just empty spaces
						if (/^\s+$/.test(field.value) || !field.value.length) {
							errors.push(field);
						}
					}
				}
			}
			
			// Make sure there are no errors stored
			// If errors.length is zero then that means there are no errors
			// Zero will coerce to false and so we return the opposite of false using the ! operator
			if (!errors.length) {
				return true;
			} 
			
			// We return false to prevent the form from submitting
			// And we display the errors we found
			else {				
				console.log(errors); // TODO: actually display the errors appropriately!
				return false;
			}
		}
	}
	
	return validate;
	
});