Skip to content

Instantly share code, notes, and snippets.

@thegrubbsian
Created December 14, 2010 04:40
Show Gist options
  • Save thegrubbsian/740006 to your computer and use it in GitHub Desktop.
Save thegrubbsian/740006 to your computer and use it in GitHub Desktop.
A very simple validation plugin for jQuery in just over 100 lines.
(function(jQuery) {
jQuery.fn.validator = function(options) {
var isEmpty = function(obj) { return obj == null || obj.length == 0; };
var opts = jQuery.extend(true, { // Allows for overriding any messages or validator functions
wrapperClass: "invalid", messageClass: "message", useMessages: true,
onValidation: null, onValidationFailed: null, // Callbacks which recieve an object containing the element and state { el: el, state: state }
validateOn: "blur", // The jQuery events that cause validation to occur
defaultMessages: {
"required": "Required",
"min": "Value is not long enough.",
"max": "Value is too long.",
"accepted": "Must be checked.",
"number": "Must be a number.",
"date": "Must be a valid date.",
"email": "Must be an email address.",
"url": "Must be a URL.",
"regex": "Invalid"
},
validatorFunctions: { // Return true if the value passes validation
"required": function(el, value) { return ! isEmpty(value); },
"min": function(el, value, args) { return isEmpty(value) || value.length >= args.length; },
"max": function(el, value, args) { return isEmpty(value) || value.length <= args.length; },
"accepted": function(el, value) { return el.is(":checked"); },
"number": function(el, value) { return isEmpty(value) || (!isNaN(value) && !/^\s+$/.test(value)); },
"alpha": function(el, value) { return isEmpty(value) || /^[a-zA-Z]+$/.test(value); },
"date": function(el, value) { return isEmpty(value) || !isNaN(new Date(value)); },
"email": function(el, value) { return isEmpty(value) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(value); },
"url": function(el, value) { return isEmpty(value) || /(((ht|f)tp(s?):\/\/)|(www\.[^ \[\]\(\)\n\r\t]+)|(([012]?[0-9]{1,2}\.){3}[012]?[0-9]{1,2})\/)([^ \[\]\(\),;&quot;'&lt;&gt;\n\r\t]+)([^\. \[\]\(\),;&quot;'&lt;&gt;\n\r\t])|(([012]?[0-9]{1,2}\.){3}[012]?[0-9]{1,2})/.test(value); },
"regex": function(el, value, args) { return isEmpty(value) || args.expression.test(value); }
}
}, options);
this.live(opts.validateOn, function() {
var el = jQuery(this), validators = {};
var validationString = expandValidatorString(el.data("validator") || "");
try { validators = eval("({" + validationString + "})"); } catch (e) { } // Keeps invalid validation methods from raising errors
var state = validate(el, validators, el.val());
render(el, state);
notify(el, state);
});
var expandValidatorString = function(str) {
for (method in opts.validatorFunctions) {
var containsExp = new RegExp(method);
var testExp = new RegExp(method + "\\b(:|\\s:)");
if (containsExp.test(str) && !testExp.test(str)) {
str = str.replace(containsExp, method + ":{}");
}
}
return str;
};
var validate = function(el, validators, value) {
var state = { isValid: true, errors: [] };
for (method in opts.validatorFunctions) {
if (!validators[method]) { continue; }
var errOpts = validators[method];
if (opts.validatorFunctions[method](el, value, errOpts)) { continue; }
state.isValid = false;
state.errors.push({
method: method,
message: errOpts.message ? errOpts.message: opts.defaultMessages[method],
title: errOpts.title ? errOpts.title: opts.defaultMessages[method]
});
}
el.data("validation-state", state); // Adds the current validation state to the DOM element
return state;
};
var render = function(el, state) {
if (el.parent().is("." + opts.wrapperClass)) {
jQuery("span." + opts.messageClass, el.parent()).remove();
el.unwrap();
}
if (!state.isValid) {
el.wrap(jQuery("<div class='" + opts.wrapperClass + "'></div>"));
var message = jQuery("<span class='" + opts.messageClass + "'></span>");
var text = "", title = "";
for (var i = 0; i < state.errors.length; i++) {
if (state.errors[i].message && opts.useMessages) {
text = text + state.errors[i].message;
}
title = title + state.errors[i].title;
}
message.text(text);
el.parent().append(message).attr("title", title);
}
};
var notify = function(el, state) {
var container = el.closest("form"); // Validation events will be triggered on the nearest form or body if no form is present
if (container.length == 0) { container = jQuery("body"); }
container.trigger("validation", [{ el: el, state: state }]);
if (opts.onValidation) { opts.onValidation(el, state); }
if (state.isValid) { return; }
container.trigger("validationFailed", [{ el: el, state: state }]);
if (opts.onValidationFailed) { opts.onValidationFailed(el, state); }
};
};
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<title>Usage Example for jQuery.validator</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="jquery.validator.js"></script>
<script type="text/javascript">
$(function() {
$(":input").validator();
$("#form1").bind("validation", function(e, validation) {
alert("The field is: " + (validation.state.isValid ? "valid." : "invalid."));
});
$("#form2").bind("validationFailed", function(e, validation) {
alert("Validation has failed :(");
});
});
</script>
<style type="text/css">
/* Styles used by validator (can be modified via options) */
div.invalid input[type='text'],
div.invalid input[type='password'],
div.invalid select {
border: 1px solid red;
}
div.invalid span.message {
color: red;
font-weight: bold;
}
/* Demo styles */
div.field input { border: 1px solid #999; padding: 3px 5px; }
div.field { margin-bottom: 20px; }
div.field label { display: block; }
</style>
</head>
<body>
<div class="field">
<label>Required</label>
<input type="text" name="field1" data-validator="required:{message:'!!!'}" value="Remove me" />
</div>
<div class="field">
<label>Number</label>
<input type="text" name="field2" data-validator="number:{message:'***'}" />
</div>
<div class="field">
<label>Required, Number</label>
<input type="text" name="field3" data-validator="required,number:{message:'Needs a number!'}" value="12345" />
</div>
<div class="field">
<label>URL</label>
<input type="text" name="field4" data-validator="url" value="http://www.google.com" />
</div>
<div class="field">
<label>Email</label>
<input type="text" name="field5" data-validator="email" value="jim.bob@hillbilly.net" />
</div>
<div class="field">
<label>Min Length (3)</label>
<input type="text" name="field6" data-validator="min:{length:3}" value="abcd" />
</div>
<div class="field">
<label>Max Length (5)</label>
<input type="text" name="field7" data-validator="max:{length:5}" value="abcd" />
</div>
<div class="field">
<label>Empty Validator Attribute</label>
<input type="text" name="field8" data-validator="" value="I'm empty" />
</div>
<div class="field">
<label>Invalid Validator Attribute</label>
<input type="text" name="field9" data-validator="invalidmethod" value="My method doesn't exist" />
</div>
<form id="form1">
<div class="field">
<label>Will Alert On Validation</label>
<input type="text" name="field10" data-validator="required" value="I'm required" />
</div>
</form>
<form id="form2">
<div class="field">
<label>Will Alert On Validation Failed</label>
<input type="text" name="field11" data-validator="required" value="I'm required" />
</div>
</form>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment