Skip to content

Instantly share code, notes, and snippets.

@douglasback
Created October 2, 2012 14:45
Show Gist options
  • Save douglasback/3819713 to your computer and use it in GitHub Desktop.
Save douglasback/3819713 to your computer and use it in GitHub Desktop.
jQ Tools Validator 1.2.7
/**
* @license
* jQuery Tools Validator @VERSION - HTML5 is here. Now use it.
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/form/validator/
*
* Since: Mar 2010
* Date: @DATE
*/
/*jslint evil: true */
(function($) {
$.tools = $.tools || {version: '@VERSION'};
// globals
var typeRe = /\[type=([a-z]+)\]/,
numRe = /^-?[0-9]*(\.[0-9]+)?$/,
dateInput = $.tools.dateinput,
// http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/
emailRe = /^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
urlRe = /^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,
v;
v = $.tools.validator = {
conf: {
grouped: false, // show all error messages at once inside the container
effect: 'default', // show/hide effect for error message. only 'default' is built-in
errorClass: 'invalid', // input field class name in case of validation error
// when to check for validity?
inputEvent: null, // change, blur, keyup, null
errorInputEvent: 'keyup', // change, blur, keyup, null
formEvent: 'submit', // submit, null
lang: 'en', // default language for error messages
message: '<div/>',
messageAttr: 'data-message', // name of the attribute for overridden error message
messageClass: 'error', // error message element's class name
offset: [0, 0],
position: 'center right',
singleError: false, // validate all inputs at once
speed: 'normal' // message's fade-in speed
},
/* The Error Messages */
messages: {
"*": { en: "Please correct this value" }
},
localize: function(lang, messages) {
$.each(messages, function(key, msg) {
v.messages[key] = v.messages[key] || {};
v.messages[key][lang] = msg;
});
},
localizeFn: function(key, messages) {
v.messages[key] = v.messages[key] || {};
$.extend(v.messages[key], messages);
},
/**
* Adds a new validator
*/
fn: function(matcher, msg, fn) {
// no message supplied
if ($.isFunction(msg)) {
fn = msg;
// message(s) on second argument
} else {
if (typeof msg == 'string') { msg = {en: msg}; }
this.messages[matcher.key || matcher] = msg;
}
// check for "[type=xxx]" (not supported by jQuery)
var test = typeRe.exec(matcher);
if (test) { matcher = isType(test[1]); }
// add validator to the arsenal
fns.push([matcher, fn]);
},
/* Add new show/hide effect */
addEffect: function(name, showFn, closeFn) {
effects[name] = [showFn, closeFn];
}
};
/* calculate error message position relative to the input */
function getPosition(trigger, el, conf) {
// Get the first element in the selector set
el = $(el).first() || el;
// get origin top/left position
var top = trigger.offset().top,
left = trigger.offset().left,
pos = conf.position.split(/,?\s+/),
y = pos[0],
x = pos[1];
top -= el.outerHeight() - conf.offset[0];
left += trigger.outerWidth() + conf.offset[1];
// iPad position fix
if (/iPad/i.test(navigator.userAgent)) {
top -= $(window).scrollTop();
}
// adjust Y
var height = el.outerHeight() + trigger.outerHeight();
if (y == 'center') { top += height / 2; }
if (y == 'bottom') { top += height; }
// adjust X
var width = trigger.outerWidth();
if (x == 'center') { left -= (width + el.outerWidth()) / 2; }
if (x == 'left') { left -= width; }
return {top: top, left: left};
}
// $.is("[type=xxx]") or $.filter("[type=xxx]") not working in jQuery 1.3.2 or 1.4.2
function isType(type) {
function fn() {
return this.getAttribute("type") == type;
}
fn.key = "[type=\"" + type + "\"]";
return fn;
}
var fns = [], effects = {
'default' : [
// show errors function
function(errs) {
var conf = this.getConf();
// loop errors
$.each(errs, function(i, err) {
// add error class
var input = err.input;
input.addClass(conf.errorClass);
// get handle to the error container
var msg = input.data("msg.el");
// create it if not present
if (!msg) {
msg = $(conf.message).addClass(conf.messageClass).appendTo(document.body);
input.data("msg.el", msg);
}
// clear the container
msg.css({visibility: 'hidden'}).find("p").remove();
// populate messages
$.each(err.messages, function(i, m) {
$("<p/>").html(m).appendTo(msg);
});
// make sure the width is not full body width so it can be positioned correctly
if (msg.outerWidth() == msg.parent().width()) {
msg.add(msg.find("p")).css({display: 'inline'});
}
// insert into correct position (relative to the field)
var pos = getPosition(input, msg, conf);
msg.css({ visibility: 'visible', position: 'absolute', top: pos.top, left: pos.left })
.fadeIn(conf.speed);
});
// hide errors function
}, function(inputs) {
var conf = this.getConf();
inputs.removeClass(conf.errorClass).each(function() {
var msg = $(this).data("msg.el");
if (msg) { msg.css({visibility: 'hidden'}); }
});
}
]
};
/* sperial selectors */
$.each("email,url,number".split(","), function(i, key) {
$.expr[':'][key] = function(el) {
return el.getAttribute("type") === key;
};
});
/*
oninvalid() jQuery plugin.
Usage: $("input:eq(2)").oninvalid(function() { ... });
*/
$.fn.oninvalid = function( fn ){
return this[fn ? "on" : "trigger"]("OI", fn);
};
/******* built-in HTML5 standard validators *********/
v.fn(":email", "Please enter a valid email address", function(el, v) {
return !v || emailRe.test(v);
});
v.fn(":url", "Please enter a valid URL", function(el, v) {
return !v || urlRe.test(v);
});
v.fn(":number", "Please enter a numeric value.", function(el, v) {
return numRe.test(v);
});
v.fn("[max]", "Please enter a value no larger than $1", function(el, v) {
// skip empty values and dateinputs
if (v === '' || dateInput && el.is(":date")) { return true; }
var max = el.attr("max");
return parseFloat(v) <= parseFloat(max) ? true : [max];
});
v.fn("[min]", "Please enter a value of at least $1", function(el, v) {
// skip empty values and dateinputs
if (v === '' || dateInput && el.is(":date")) { return true; }
var min = el.attr("min");
return parseFloat(v) >= parseFloat(min) ? true : [min];
});
v.fn("[required]", "Please complete this mandatory field.", function(el, v) {
if (el.is(":checkbox")) { return el.is(":checked"); }
return !!v;
});
v.fn("[pattern]", function(el, v) {
return v === '' || new RegExp("^" + el.attr("pattern") + "$").test(v);
});
v.fn(":radio", "Please select an option.", function(el) {
var checked = false;
var els = $("[name='" + el.attr("name") + "']").each(function(i, el) {
if ($(el).is(":checked")) {
checked = true;
}
});
return (checked) ? true : false;
});
function Validator(inputs, form, conf) {
// private variables
var self = this,
fire = form.add(self);
// make sure there are input fields available
inputs = inputs.not(":button, :image, :reset, :submit");
// Prevent default Firefox validation
form.attr("novalidate", "novalidate");
// utility function
function pushMessage(to, matcher, returnValue) {
// only one message allowed
if (!conf.grouped && to.length) { return; }
// the error message
var msg;
// substitutions are returned
if (returnValue === false || $.isArray(returnValue)) {
msg = v.messages[matcher.key || matcher] || v.messages["*"];
msg = msg[conf.lang] || v.messages["*"].en;
// substitution
var matches = msg.match(/\$\d/g);
if (matches && $.isArray(returnValue)) {
$.each(matches, function(i) {
msg = msg.replace(this, returnValue[i]);
});
}
// error message is returned directly
} else {
msg = returnValue[conf.lang] || returnValue;
}
to.push(msg);
}
// API methods
$.extend(self, {
getConf: function() {
return conf;
},
getForm: function() {
return form;
},
getInputs: function() {
return inputs;
},
reflow: function() {
inputs.each(function() {
var input = $(this),
msg = input.data("msg.el");
if (msg) {
var pos = getPosition(input, msg, conf);
msg.css({ top: pos.top, left: pos.left });
}
});
return self;
},
/* @param e - for internal use only */
invalidate: function(errs, e) {
// errors are given manually: { fieldName1: 'message1', fieldName2: 'message2' }
if (!e) {
var errors = [];
$.each(errs, function(key, val) {
var input = inputs.filter("[name='" + key + "']");
if (input.length) {
// trigger HTML5 ininvalid event
input.trigger("OI", [val]);
errors.push({ input: input, messages: [val]});
}
});
errs = errors;
e = $.Event();
}
// onFail callback
e.type = "onFail";
fire.trigger(e, [errs]);
// call the effect
if (!e.isDefaultPrevented()) {
effects[conf.effect][0].call(self, errs, e);
}
return self;
},
reset: function(els) {
els = els || inputs;
els.removeClass(conf.errorClass).each(function() {
var msg = $(this).data("msg.el");
if (msg) {
msg.remove();
$(this).data("msg.el", null);
}
}).off(conf.errorInputEvent + '.v' || '');
return self;
},
destroy: function() {
form.off(conf.formEvent + ".V reset.V");
inputs.off(conf.inputEvent + ".V change.V");
return self.reset();
},
//{{{ checkValidity() - flesh and bone of this tool
/* @returns boolean */
checkValidity: function(els, e) {
els = els || inputs;
els = els.not(":disabled");
// filter duplicate elements by name
var names = {};
els = els.filter(function(){
var name = $(this).attr("name");
if (!names[name]) {
names[name] = true;
return $(this);
}
});
if (!els.length) { return true; }
e = e || $.Event();
// onBeforeValidate
e.type = "onBeforeValidate";
fire.trigger(e, [els]);
if (e.isDefaultPrevented()) { return e.result; }
// container for errors
var errs = [];
// loop trough the inputs
els.each(function() {
// field and it's error message container
var msgs = [],
el = $(this).data("messages", msgs),
event = dateInput && el.is(":date") ? "onHide.v" : conf.errorInputEvent + ".v";
// cleanup previous validation event
el.off(event);
// loop all validator functions
$.each(fns, function() {
var fn = this, match = fn[0];
// match found
if (el.filter(match).length) {
// execute a validator function
var returnValue = fn[1].call(self, el, el.val());
// validation failed. multiple substitutions can be returned with an array
if (returnValue !== true) {
// onBeforeFail
e.type = "onBeforeFail";
fire.trigger(e, [el, match]);
if (e.isDefaultPrevented()) { return false; }
// overridden custom message
var msg = el.attr(conf.messageAttr);
if (msg) {
msgs = [msg];
return false;
} else {
pushMessage(msgs, match, returnValue);
}
}
}
});
if (msgs.length) {
errs.push({input: el, messages: msgs});
// trigger HTML5 ininvalid event
el.trigger("OI", [msgs]);
// begin validating upon error event type (such as keyup)
if (conf.errorInputEvent) {
el.on(event, function(e) {
self.checkValidity(el, e);
});
}
}
if (conf.singleError && errs.length) { return false; }
});
// validation done. now check that we have a proper effect at hand
var eff = effects[conf.effect];
if (!eff) { throw "Validator: cannot find effect \"" + conf.effect + "\""; }
// errors found
if (errs.length) {
self.invalidate(errs, e);
return false;
// no errors
} else {
// call the effect
eff[1].call(self, els, e);
// onSuccess callback
e.type = "onSuccess";
fire.trigger(e, [els]);
els.off(conf.errorInputEvent + ".v");
}
return true;
}
//}}}
});
// callbacks
$.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","), function(i, name) {
// configuration
if ($.isFunction(conf[name])) {
$(self).on(name, conf[name]);
}
// API methods
self[name] = function(fn) {
if (fn) { $(self).on(name, fn); }
return self;
};
});
// form validation
if (conf.formEvent) {
form.on(conf.formEvent + ".V", function(e) {
if (!self.checkValidity(null, e)) {
return e.preventDefault();
}
// Reset event type and target
e.target = form;
e.type = conf.formEvent;
});
}
// form reset
form.on("reset.V", function() {
self.reset();
});
// disable browser's default validation mechanism
if (inputs[0] && inputs[0].validity) {
inputs.each(function() {
this.oninvalid = function() {
return false;
};
});
}
// Web Forms 2.0 compatibility
if (form[0]) {
form[0].checkValidity = self.checkValidity;
}
// input validation
if (conf.inputEvent) {
inputs.on(conf.inputEvent + ".V", function(e) {
self.checkValidity($(this), e);
});
}
// checkboxes and selects are checked separately
inputs.filter(":checkbox, select").filter("[required]").on("change.V", function(e) {
var el = $(this);
if (this.checked || (el.is("select") && $(this).val())) {
effects[conf.effect][1].call(self, el, e);
}
});
// get radio groups by name
inputs.filter(":radio[required]").on("change.V", function(e) {
var els = $("[name='" + $(e.srcElement).attr("name") + "']");
if ((els != null) && (els.length != 0)) {
self.checkValidity(els, e);
}
});
// reposition tooltips when window is resized
$(window).resize(function() {
self.reflow();
});
}
// jQuery plugin initialization
$.fn.validator = function(conf) {
var instance = this.data("validator");
// destroy existing instance
if (instance) {
instance.destroy();
this.removeData("validator");
}
// configuration
conf = $.extend(true, {}, v.conf, conf);
// selector is a form
if (this.is("form")) {
return this.each(function() {
var form = $(this);
instance = new Validator(form.find(":input"), form, conf);
form.data("validator", instance);
});
} else {
instance = new Validator(this, this.eq(0).closest("form"), conf);
return this.data("validator", instance);
}
};
})(jQuery);
/*
jQuery Tools Validator @VERSION - HTML5 is here. Now use it.
NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
http://flowplayer.org/tools/form/validator/
Since: Mar 2010
Date: @DATE
*/
(function(d){function j(b,a,c){var a=d(a).first()||a,e=b.offset().top,i=b.offset().left,f=c.position.split(/,?\s+/),h=f[0],f=f[1],e=e-(a.outerHeight()-c.offset[0]),i=i+(b.outerWidth()+c.offset[1]);/iPad/i.test(navigator.userAgent)&&(e-=d(window).scrollTop());c=a.outerHeight()+b.outerHeight();"center"==h&&(e+=c/2);"bottom"==h&&(e+=c);b=b.outerWidth();"center"==f&&(i-=(b+a.outerWidth())/2);"left"==f&&(i-=b);return{top:e,left:i}}function q(b,a,c){var e=this,i=a.add(e),b=b.not(":button, :image, :reset, :submit");
a.attr("novalidate","novalidate");d.extend(e,{getConf:function(){return c},getForm:function(){return a},getInputs:function(){return b},reflow:function(){b.each(function(){var a=d(this),b=a.data("msg.el");b&&(a=j(a,b,c),b.css({top:a.top,left:a.left}))});return e},invalidate:function(a,h){if(!h){var g=[];d.each(a,function(a,c){var f=b.filter("[name='"+a+"']");f.length&&(f.trigger("OI",[c]),g.push({input:f,messages:[c]}))});a=g;h=d.Event()}h.type="onFail";i.trigger(h,[a]);h.isDefaultPrevented()||n[c.effect][0].call(e,
a,h);return e},reset:function(a){a=a||b;a.removeClass(c.errorClass).each(function(){var a=d(this).data("msg.el");a&&(a.remove(),d(this).data("msg.el",null))}).off(c.errorInputEvent+".v"||"");return e},destroy:function(){a.off(c.formEvent+".V reset.V");b.off(c.inputEvent+".V change.V");return e.reset()},checkValidity:function(a,h){var a=a||b,a=a.not(":disabled"),k={},a=a.filter(function(){var a=d(this).attr("name");if(!k[a])return k[a]=!0,d(this)});if(!a.length)return!0;h=h||d.Event();h.type="onBeforeValidate";
i.trigger(h,[a]);if(h.isDefaultPrevented())return h.result;var m=[];a.each(function(){var a=[],b=d(this).data("messages",a),f=p&&b.is(":date")?"onHide.v":c.errorInputEvent+".v";b.off(f);d.each(r,function(){var f=this[0];if(b.filter(f).length){var k=this[1].call(e,b,b.val());if(!0!==k){h.type="onBeforeFail";i.trigger(h,[b,f]);if(h.isDefaultPrevented())return!1;var j=b.attr(c.messageAttr);if(j)return a=[j],!1;j=a;if(c.grouped||!j.length){var l;!1===k||d.isArray(k)?(l=g.messages[f.key||f]||g.messages["*"],
l=l[c.lang]||g.messages["*"].en,(f=l.match(/\$\d/g))&&d.isArray(k)&&d.each(f,function(a){l=l.replace(this,k[a])})):l=k[c.lang]||k;j.push(l)}}}});if(a.length&&(m.push({input:b,messages:a}),b.trigger("OI",[a]),c.errorInputEvent))b.on(f,function(a){e.checkValidity(b,a)});if(c.singleError&&m.length)return!1});var j=n[c.effect];if(!j)throw'Validator: cannot find effect "'+c.effect+'"';if(m.length)return e.invalidate(m,h),!1;j[1].call(e,a,h);h.type="onSuccess";i.trigger(h,[a]);a.off(c.errorInputEvent+".v");
return!0}});d.each(["onBeforeValidate","onBeforeFail","onFail","onSuccess"],function(a,b){if(d.isFunction(c[b]))d(e).on(b,c[b]);e[b]=function(a){if(a)d(e).on(b,a);return e}});if(c.formEvent)a.on(c.formEvent+".V",function(b){if(!e.checkValidity(null,b))return b.preventDefault();b.target=a;b.type=c.formEvent});a.on("reset.V",function(){e.reset()});b[0]&&b[0].validity&&b.each(function(){this.oninvalid=function(){return!1}});a[0]&&(a[0].checkValidity=e.checkValidity);if(c.inputEvent)b.on(c.inputEvent+
".V",function(a){e.checkValidity(d(this),a)});b.filter(":checkbox, select").filter("[required]").on("change.V",function(a){var b=d(this);(this.checked||b.is("select")&&d(this).val())&&n[c.effect][1].call(e,b,a)});b.filter(":radio[required]").on("change.V",function(a){var b=d("[name='"+d(a.srcElement).attr("name")+"']");null!=b&&0!=b.length&&e.checkValidity(b,a)});d(window).resize(function(){e.reflow()})}d.tools=d.tools||{version:"@VERSION"};var s=/\[type=([a-z]+)\]/,t=/^-?[0-9]*(\.[0-9]+)?$/,p=d.tools.dateinput,
u=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,v=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,g;g=d.tools.validator={conf:{grouped:!1,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:!1,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(b,a){d.each(a,function(a,d){g.messages[a]=
g.messages[a]||{};g.messages[a][b]=d})},localizeFn:function(b,a){g.messages[b]=g.messages[b]||{};d.extend(g.messages[b],a)},fn:function(b,a,c){d.isFunction(a)?c=a:("string"==typeof a&&(a={en:a}),this.messages[b.key||b]=a);if(a=s.exec(b)){var e=a[1],b=function(){return this.getAttribute("type")==e};b.key='[type="'+e+'"]'}r.push([b,c])},addEffect:function(b,a,c){n[b]=[a,c]}};var r=[],n={"default":[function(b){var a=this.getConf();d.each(b,function(b,e){var g=e.input;g.addClass(a.errorClass);var f=g.data("msg.el");
f||(f=d(a.message).addClass(a.messageClass).appendTo(document.body),g.data("msg.el",f));f.css({visibility:"hidden"}).find("p").remove();d.each(e.messages,function(a,b){d("<p/>").html(b).appendTo(f)});f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});g=j(g,f,a);f.css({visibility:"visible",position:"absolute",top:g.top,left:g.left}).fadeIn(a.speed)})},function(b){var a=this.getConf();b.removeClass(a.errorClass).each(function(){var a=d(this).data("msg.el");a&&a.css({visibility:"hidden"})})}]};
d.each(["email","url","number"],function(b,a){d.expr[":"][a]=function(b){return b.getAttribute("type")===a}});d.fn.oninvalid=function(b){return this[b?"on":"trigger"]("OI",b)};g.fn(":email","Please enter a valid email address",function(b,a){return!a||u.test(a)});g.fn(":url","Please enter a valid URL",function(b,a){return!a||v.test(a)});g.fn(":number","Please enter a numeric value.",function(b,a){return t.test(a)});g.fn("[max]","Please enter a value no larger than $1",function(b,a){if(""===a||p&&b.is(":date"))return!0;
var c=b.attr("max");return parseFloat(a)<=parseFloat(c)?!0:[c]});g.fn("[min]","Please enter a value of at least $1",function(b,a){if(""===a||p&&b.is(":date"))return!0;var c=b.attr("min");return parseFloat(a)>=parseFloat(c)?!0:[c]});g.fn("[required]","Please complete this mandatory field.",function(b,a){return b.is(":checkbox")?b.is(":checked"):!!a});g.fn("[pattern]",function(b,a){return""===a||RegExp("^"+b.attr("pattern")+"$").test(a)});g.fn(":radio","Please select an option.",function(b){var a=!1;
d("[name='"+b.attr("name")+"']").each(function(b,e){d(e).is(":checked")&&(a=!0)});return a?!0:!1});d.fn.validator=function(b){var a=this.data("validator");a&&(a.destroy(),this.removeData("validator"));b=d.extend(!0,{},g.conf,b);if(this.is("form"))return this.each(function(){var c=d(this);a=new q(c.find(":input"),c,b);c.data("validator",a)});a=new q(this,this.eq(0).closest("form"),b);return this.data("validator",a)}})(jQuery);
/*!
* jQuery Tools v1.2.7 - The missing UI library for the Web
*
* validator/validator.js
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/
*
*/
(function(a){a.tools=a.tools||{version:"v1.2.7"};var b=/\[type=([a-z]+)\]/,c=/^-?[0-9]*(\.[0-9]+)?$/,d=a.tools.dateinput,e=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,f=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,g;g=a.tools.validator={conf:{grouped:!1,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:!1,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(b,c){a.each(c,function(a,c){g.messages[a]=g.messages[a]||{},g.messages[a][b]=c})},localizeFn:function(b,c){g.messages[b]=g.messages[b]||{},a.extend(g.messages[b],c)},fn:function(c,d,e){a.isFunction(d)?e=d:(typeof d=="string"&&(d={en:d}),this.messages[c.key||c]=d);var f=b.exec(c);f&&(c=i(f[1])),j.push([c,e])},addEffect:function(a,b,c){k[a]=[b,c]}};function h(b,c,d){c=a(c).first()||c;var e=b.offset().top,f=b.offset().left,g=d.position.split(/,?\s+/),h=g[0],i=g[1];e-=c.outerHeight()-d.offset[0],f+=b.outerWidth()+d.offset[1],/iPad/i.test(navigator.userAgent)&&(e-=a(window).scrollTop());var j=c.outerHeight()+b.outerHeight();h=="center"&&(e+=j/2),h=="bottom"&&(e+=j);var k=b.outerWidth();i=="center"&&(f-=(k+c.outerWidth())/2),i=="left"&&(f-=k);return{top:e,left:f}}function i(a){function b(){return this.getAttribute("type")==a}b.key="[type=\""+a+"\"]";return b}var j=[],k={"default":[function(b){var c=this.getConf();a.each(b,function(b,d){var e=d.input;e.addClass(c.errorClass);var f=e.data("msg.el");f||(f=a(c.message).addClass(c.messageClass).appendTo(document.body),e.data("msg.el",f)),f.css({visibility:"hidden"}).find("p").remove(),a.each(d.messages,function(b,c){a("<p/>").html(c).appendTo(f)}),f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});var g=h(e,f,c);f.css({visibility:"visible",position:"absolute",top:g.top,left:g.left}).fadeIn(c.speed)})},function(b){var c=this.getConf();b.removeClass(c.errorClass).each(function(){var b=a(this).data("msg.el");b&&b.css({visibility:"hidden"})})}]};a.each("email,url,number".split(","),function(b,c){a.expr[":"][c]=function(a){return a.getAttribute("type")===c}}),a.fn.oninvalid=function(a){return this[a?"on":"trigger"]("OI",a)},g.fn(":email","Please enter a valid email address",function(a,b){return!b||e.test(b)}),g.fn(":url","Please enter a valid URL",function(a,b){return!b||f.test(b)}),g.fn(":number","Please enter a numeric value.",function(a,b){return c.test(b)}),g.fn("[max]","Please enter a value no larger than $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("max");return parseFloat(b)<=parseFloat(c)?!0:[c]}),g.fn("[min]","Please enter a value of at least $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("min");return parseFloat(b)>=parseFloat(c)?!0:[c]}),g.fn("[required]","Please complete this mandatory field.",function(a,b){if(a.is(":checkbox"))return a.is(":checked");return b}),g.fn("[pattern]",function(a,b){return b===""||(new RegExp("^"+a.attr("pattern")+"$")).test(b)}),g.fn(":radio","Please select an option.",function(b){var c=!1,d=a("[name='"+b.attr("name")+"']").each(function(b,d){a(d).is(":checked")&&(c=!0)});return c?!0:!1});function l(b,c,e){var f=this,i=c.add(f);b=b.not(":button, :image, :reset, :submit"),c.attr("novalidate","novalidate");function l(b,c,d){if(e.grouped||!b.length){var f;if(d===!1||a.isArray(d)){f=g.messages[c.key||c]||g.messages["*"],f=f[e.lang]||g.messages["*"].en;var h=f.match(/\$\d/g);h&&a.isArray(d)&&a.each(h,function(a){f=f.replace(this,d[a])})}else f=d[e.lang]||d;b.push(f)}}a.extend(f,{getConf:function(){return e},getForm:function(){return c},getInputs:function(){return b},reflow:function(){b.each(function(){var b=a(this),c=b.data("msg.el");if(c){var d=h(b,c,e);c.css({top:d.top,left:d.left})}});return f},invalidate:function(c,d){if(!d){var g=[];a.each(c,function(a,c){var d=b.filter("[name='"+a+"']");d.length&&(d.trigger("OI",[c]),g.push({input:d,messages:[c]}))}),c=g,d=a.Event()}d.type="onFail",i.trigger(d,[c]),d.isDefaultPrevented()||k[e.effect][0].call(f,c,d);return f},reset:function(c){c=c||b,c.removeClass(e.errorClass).each(function(){var b=a(this).data("msg.el");b&&(b.remove(),a(this).data("msg.el",null))}).off(e.errorInputEvent+".v");return f},destroy:function(){c.off(e.formEvent+".V reset.V"),b.off(e.inputEvent+".V change.V");return f.reset()},checkValidity:function(c,g){c=c||b,c=c.not(":disabled");var h={};c=c.filter(function(){var b=a(this).attr("name");if(!h[b]){h[b]=!0;return a(this)}});if(!c.length)return!0;g=g||a.Event(),g.type="onBeforeValidate",i.trigger(g,[c]);if(g.isDefaultPrevented())return g.result;var m=[];c.each(function(){var b=[],c=a(this).data("messages",b),h=d&&c.is(":date")?"onHide.v":e.errorInputEvent+".v";c.off(h),a.each(j,function(){var a=this,d=a[0];if(c.filter(d).length){var h=a[1].call(f,c,c.val());if(h!==!0){g.type="onBeforeFail",i.trigger(g,[c,d]);if(g.isDefaultPrevented())return!1;var j=c.attr(e.messageAttr);if(j){b=[j];return!1}l(b,d,h)}}}),b.length&&(m.push({input:c,messages:b}),c.trigger("OI",[b]),e.errorInputEvent&&c.on(h,function(a){f.checkValidity(c,a)}));if(e.singleError&&m.length)return!1});var n=k[e.effect];if(!n)throw"Validator: cannot find effect \""+e.effect+"\"";if(m.length){f.invalidate(m,g);return!1}n[1].call(f,c,g),g.type="onSuccess",i.trigger(g,[c]),c.off(e.errorInputEvent+".v");return!0}}),a.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(b,c){a.isFunction(e[c])&&a(f).on(c,e[c]),f[c]=function(b){b&&a(f).on(c,b);return f}}),e.formEvent&&c.on(e.formEvent+".V",function(a){if(!f.checkValidity(null,a))return a.preventDefault();a.target=c,a.type=e.formEvent}),c.on("reset.V",function(){f.reset()}),b[0]&&b[0].validity&&b.each(function(){this.oninvalid=function(){return!1}}),c[0]&&(c[0].checkValidity=f.checkValidity),e.inputEvent&&b.on(e.inputEvent+".V",function(b){f.checkValidity(a(this),b)}),b.filter(":checkbox, select").filter("[required]").on("change.V",function(b){var c=a(this);(this.checked||c.is("select")&&a(this).val())&&k[e.effect][1].call(f,c,b)}),b.filter(":radio[required]").on("change.V",function(b){var c=a("[name='"+a(b.srcElement).attr("name")+"']");c!=null&&c.length!=0&&f.checkValidity(c,b)}),a(window).resize(function(){f.reflow()})}a.fn.validator=function(b){var c=this.data("validator");c&&(c.destroy(),this.removeData("validator")),b=a.extend(!0,{},g.conf,b);if(this.is("form"))return this.each(function(){var d=a(this);c=new l(d.find(":input"),d,b),d.data("validator",c)});c=new l(this,this.eq(0).closest("form"),b);return this.data("validator",c)}})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment