diff --git a/dist/validatr.js b/dist/validatr.js
index 4be8dd0..7910dc4 100644
--- a/dist/validatr.js
+++ b/dist/validatr.js
@@ -1,4 +1,4 @@
-/*! Validatr - v0.5.1 - 2013-03-12
+/*! Validatr - v0.5.1 - 2013-05-17
* http://jaymorrow.github.com/validatr/
* Copyright (c) 2013 Jay Morrow; Licensed MIT */
(function(window, document, $, undefined) {
@@ -11,23 +11,23 @@
var Support = {},
- docElement = document.documentElement,
+ docElement = document.documentElement,
- inputElem = document.createElement('input'),
+ inputElem = document.createElement('input'),
- selectElem = document.createElement('select'),
+ selectElem = document.createElement('select'),
- textareaElem = document.createElement('textarea'),
+ textareaElem = document.createElement('textarea'),
- smile = ':)',
+ smile = ':)',
- tests = {},
+ tests = {},
- inputs = {},
+ inputs = {},
- attrs = {},
+ attrs = {},
- testElem;
+ testElem;
Support.attributes = (function( props ) {
for ( var i = 0, len = props.length; i < len; i++ ) {
@@ -38,7 +38,7 @@
Support.inputtypes = (function(props) {
-
+
for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
inputElem.setAttribute('type', inputElemType = props[i]);
bool = inputElem.type !== 'text';
@@ -73,10 +73,10 @@
return inputs;
})('search tel url email datetime date month week time datetime-local number range color'.split(' '));
- (function(props) {
+ (function(props) {
for ( var i = 0, len = props.length; i < len; i++ ) {
testElem = inputElem;
-
+
try {
testElem.setAttribute('type', props[i]);
} catch (e) {
@@ -99,26 +99,74 @@
return Support;
}()),
+ /*
+ * Really simple date/time logic
+ * Mostly taken from moment.js version : 2.0.0
+ * author : Tim Wood
+ * license : MIT
+ * momentjs.com
+ */
Format = (function () {
- var rules = {
- isoDate: /^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/
- },
+ var tokens = /(d?d|w?w|m?m|(?:yy)?yy|M?M)/g,
- utils = {
- separators: /(\/|\-|\.)/g,
- separatorsNoGroup: /\/|\-|\./g,
- dateParts: {
- dd: '(0[1-9]|[12][0-9]|3[01])',
- mm: '(0[1-9]|1[012])',
- yyyy: '(\\d{4})'
+ tokenOneTwo = /\d{1,2}/,
+ tokenTwo = /\d{2}/,
+ tokenFour = /\d{4}/,
+
+ _monthFullNames = 'January|February|March|April|May|June|July|August|September|October|November|December',
+ _monthShortNames = 'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec',
+
+ monthFullNames = new RegExp(_monthFullNames, 'i'),
+ monthShortNames = new RegExp(_monthShortNames, 'i'),
+
+ fullMonths = _monthFullNames.toLowerCase().split('|'),
+ shortMonths = _monthShortNames.toLowerCase().split('|'),
+
+ formatParts = {
+ d: function () {
+ return this.getDate();
+ },
+ dd: function () {
+ return pad(this.getDate());
+ },
+ w: function () {
+ return getWeek(this);
+ },
+ ww: function () {
+ return pad(getWeek(this));
+ },
+ m: function () {
+ return this.getMonth() + 1;
+ },
+ mm: function () {
+ return pad(this.getMonth() + 1);
+ },
+ yy: function () {
+ return this.getFullYear().toString().substr(2);
+ },
+ yyyy: function () {
+ return this.getFullYear();
+ },
+ M: function () {
+ return proper(shortMonths[this.getMonth()]);
+ },
+ MM: function () {
+ return proper(fullMonths[this.getMonth()]);
}
};
+ function proper(m) {
+ return m.substr(0,1).toUpperCase() + m.substr(1);
+ }
+
+ function pad(n) {
+ return n < 10 ? '0' + n : n;
+ }
+
function indexOf(array, value) {
var index = -1,
length = array ? array.length : 0;
-
while (++index < length) {
if (array[index] === value) {
return index;
@@ -128,58 +176,163 @@
return -1;
}
+ function getParts(token) {
+ switch(token) {
+ case 'd' :
+ case 'w' :
+ case 'm' :
+ return tokenOneTwo;
+ case 'dd':
+ case 'ww':
+ case 'mm':
+ case 'yy':
+ return tokenTwo;
+ case 'M':
+ return monthShortNames;
+ case 'MM':
+ return monthFullNames;
+ case 'yyyy':
+ return tokenFour;
+ }
+ }
+
+ function createDateArray(token, input, dateArray) {
+ if (input === undefined) {
+ return;
+ }
- function parseDate(element) {
- var format = element.getAttribute('data-format') || $.fn.validatr.defaultOptions.dateFormat,
- split = format.split(utils.separatorsNoGroup),
- dateSplit = element.value.split(utils.separatorsNoGroup),
- isoSplit = 'yyyy-mm-dd'.split('-'),
- rule = format.replace(utils.separators, '\\$1')
- .replace('yyyy', utils.dateParts.yyyy)
- .replace('mm', utils.dateParts.mm)
- .replace('dd', utils.dateParts.dd),
- index = -1,
- length = isoSplit.length,
- iso = [];
-
- rule = new RegExp(rule);
- if (!rule.test(element.value)) {
- return false;
+ switch(token) {
+ case 'd' :
+ case 'dd':
+ dateArray[2] = ~~input;
+ break;
+ case 'w' :
+ case 'ww':
+ dateArray[3] = ~~input;
+ break;
+ case 'm' :
+ case 'mm':
+ dateArray[1] = ~~input - 1;
+ break;
+ case 'M':
+ dateArray[1] = indexOf(shortMonths, input.toLowerCase());
+ break;
+ case 'MM':
+ dateArray[1] = indexOf(fullMonths, input.toLowerCase());
+ break;
+ case 'yy' :
+ dateArray[0] = ~~('20' + input);
+ break;
+ case 'yyyy':
+ dateArray[0] = ~~input;
+ break;
}
+ }
- while (++index < length) {
- iso[index] = dateSplit[ indexOf(split, isoSplit[index]) ];
+ function getWeek(date) {
+ var first = new Date(date.getFullYear(), 0, 1, 0, 0, 0);
+
+ return Math.ceil((((date - first) / 86400000) + first.getDay() + 1) / 7);
+ }
+
+ function createDateFromWeek(dateArray) {
+ var date = dayOfWeek(dateArray[0]),
+ weekTime = 1000 * 60 * 60 * 24 * 7 * (dateArray[3] - 1),
+ targetTime = date.getTime() + weekTime - (86400000 * (date.getDay() - $.fn.validatr.defaultOptions.weekStart)),
+ result = new Date(targetTime);
+ result.setHours(0);
+
+ return result;
+ }
+
+ function dayOfWeek(year) {
+ var date = new Date(year, 0, 1, 0, 0, 0),
+ day = ($.fn.validatr.defaultOptions.yearStart - date.getDay()) + date.getDate();
+
+ date.setDate(day);
+ return date;
+ }
+
+ function createDate(dateArray) {
+ var i = 0,
+ date = [],
+ isNum = false;
+
+ for (i; i < 7; i += 1) {
+ isNum = typeof dateArray[i] === 'number';
+
+ if (!isNum && i < 2) {
+ return false;
+ }
+
+ date[i] = !isNum ? (i === 2 ? 1 : 0) : dateArray[i];
}
-
- return parseISODate(iso.join('-'));
+
+ return new Date(date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
}
- function parseISODate(dateString) {
- if (!rules.isoDate.test(dateString)) {
- return false;
+ function parseDate(string, format) {
+ var parts = format.match(tokens) || [],
+ dateArray = [],
+ length = parts.length,
+ i = 0,
+ input;
+
+ if (!length) {
+ throw new Error('Ivalid date format.');
+ }
+ for (i; i < length; i += 1) {
+ input = (getParts(parts[i]).exec(string) || [])[0];
+
+ if (!input) {
+ continue;
+ }
+
+ string = string.slice(string.indexOf(input) + input.length);
+ createDateArray(parts[i], input, dateArray);
}
- var date = rules.isoDate.exec(dateString);
- return new Date(parseInt(date[1], 10), parseInt(date[2], 10) - 1, parseInt(date[3], 10));
+ if (/w?w/.test(format)) {
+ return createDateFromWeek(dateArray);
+ }
+
+ if (dateArray.length && dateArray.length === length) {
+ return createDate(dateArray);
+ }
}
- function formatISODate(dateObj, element) {
- function pad(n) {
- return n < 10 ? '0' + n : n;
+ function formatDate(dateObj, format) {
+ if (dateObj === false) {
+ return false;
}
- var date = pad(dateObj.getDate()),
- month = pad(dateObj.getMonth() + 1),
- year = dateObj.getFullYear(),
- dateString = (element.getAttribute('data-format') || $.fn.validatr.defaultOptions.dateFormat).replace('mm', month).replace('yyyy', year).replace('dd', date);
+ if (format === undefined) {
+ format = 'yyyy-mm-dd';
+ }
+
+ var parts = format.match(tokens) || [],
+ length = parts.length,
+ i = 0;
- return dateString;
+ if (!length) {
+ throw new Error('Ivalid date format.');
+ }
+
+ for (i; i < length; i += 1) {
+ if ( formatParts[ parts[i] ]) {
+ format = format.replace(parts[i], formatParts[ parts[i] ].call(dateObj));
+ }
+ }
+
+ return format;
}
return {
- formatISODate: formatISODate,
- parseDate: parseDate,
- parseISODate: parseISODate
+ date: parseDate,
+ isoDate: function (string) {
+ return parseDate(string, 'yyyy-mm-dd');
+ },
+ toString: formatDate
};
}()),
@@ -187,9 +340,7 @@
var rules = {
color: /^#[0-9A-F]{6}$/i,
email: /^[a-zA-Z0-9.!#$%&’*+\/=?\^_`{|}~\-]+@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$/,
- isoDate: /^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/,
number: /^-?\d*\.?\d*$/,
- time: /^([01][0-9]|2[0-3])(:([0-5][0-9])){2}$/,
url: /^\s*https?:\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?\s*$/
},
@@ -198,16 +349,9 @@
spaces: /,\s*/
},
- minMax = function (value, min, max, step, type) {
+ minMax = function (value, min, max, step) {
var result = true,
- msg = $.validatr.messages.range.base,
- minString = min,
- maxString = max;
-
- if (type === 'date') {
- minString = min && Format.formatISODate(min, this);
- maxString = max && Format.formatISODate(max, this);
- }
+ msg = $.validatr.messages.range.base;
if (value !== false) {
if (step !== false) {
@@ -225,14 +369,33 @@
} else if (max !== false) {
result = value <= max;
msg = $.validatr.messages.range.underflow;
- }
+ }
}
}
return {
valid: value !== false && result,
- message: msg.replace('{{type}}', type).replace('{{min}}', minString).replace('{{max}}', maxString)
- };
+ message: msg
+ };
+ },
+
+ getFormat = function (element, type) {
+ type += 'Format';
+ return element.getAttribute('data-format') || ( $.data(element.form, 'validatr').options[type] || $.fn.validatr.defaultOptions[type] );
+ },
+
+ formatMessage = function (message, type, min, max) {
+ message = message.replace('{{type}}', type);
+
+ if (min) {
+ message = message.replace('{{min}}', min);
+ }
+
+ if (max) {
+ message = message.replace('{{max}}', max);
+ }
+
+ return message;
};
return {
@@ -252,12 +415,17 @@
date: function (element) {
var $element = $(element),
- value = Support.inputtypes.date ? Format.parseISODate(element.value) : Format.parseDate(element),
- min = $element.attr('min') ? Format.parseISODate($element.attr('min')) : false,
- max = $element.attr('max') ? Format.parseISODate($element.attr('max')) : false,
- step = false;
-
- return minMax.call(element, value, min, max, step, 'date');
+ format = getFormat(element, 'date'),
+ value = Format.date(element.value, format) || false,
+ min = $element.attr('min') ? Format.isoDate($element.attr('min')) : false,
+ max = $element.attr('max') ? Format.isoDate($element.attr('max')) : false,
+ step = false,
+ result = minMax(value, min, max, step);
+
+ if (!result.valid) {
+ result.message = formatMessage(result.message, 'date', Format.toString(min, format), Format.toString(max, format));
+ }
+ return result;
},
email: function (element) {
@@ -285,18 +453,39 @@
};
},
+ month: function (element) {
+ var $element = $(element),
+ format = getFormat(element, 'month'),
+ value = Format.date(element.value, format) || false,
+ min = $element.attr('min') ? Format.isoDate($element.attr('min') + '01') : false,
+ max = $element.attr('max') ? Format.isoDate($element.attr('max') + '01') : false,
+ step = false,
+ result = minMax(value, min, max, step);
+
+ if (!result.valid) {
+ result.message = formatMessage(result.message, 'month', Format.toString(min, format), Format.toString(max, format));
+ }
+ return result;
+ },
+
number: function (element) {
var value = element.value.replace(',', ''),
num = rules.number.test(value) ? parseFloat(value) : false,
min = rules.number.test( element.getAttribute('min') ) ? parseFloat( element.getAttribute('min') ) : false,
max = rules.number.test( element.getAttribute('max') ) ? parseFloat( element.getAttribute('max') ) : false,
- step = rules.number.test( element.getAttribute('step') ) ? parseFloat( element.getAttribute('step') ) : element.getAttribute('step') === 'any' ? 'any' : false;
-
+ step = rules.number.test( element.getAttribute('step') ) ? parseFloat( element.getAttribute('step') ) : element.getAttribute('step') === 'any' ? 'any' : false,
+ result;
+
if (step === false || step <= 0) {
step = 1;
}
- return minMax.call(element, value, min, max, step, 'number');
+ result = minMax(value, min, max, step, 'number');
+
+ if (!result.valid) {
+ result.message = formatMessage(result.message, 'number', min, max);
+ }
+ return result;
},
pattern: function (element) {
@@ -308,7 +497,7 @@
radio: function (element) {
return {
- valid: $(document.getElementsByName(element.name)).is(':checked'),
+ valid: $(element).closest('form').find('[name=' + element.name + ']' ).is(':checked'),
message: $.validatr.messages.radio
};
},
@@ -328,13 +517,6 @@
};
},
- time: function (element) {
- return {
- valid: rules.time.test(element.value),
- message: $.validatr.messages.time
- };
- },
-
url: function (element) {
return {
valid: rules.url.test(element.value),
@@ -504,7 +686,7 @@
this.template = (function (options) {
var template = $(options.template).addClass('validatr-message');
-
+
if (options.theme.length) {
template.addClass(theme[options.theme] || options.theme);
} else {
@@ -540,7 +722,7 @@
this.formElements.on({
'focus.validatrelement': bindEvents,
- 'blur.validatrelement': unbindEvents
+ 'blur.validatrelement': unbindEvents
});
$('input[type=radio], input[type=checkbox]').on('click.validatrelement', function (e) {
@@ -561,19 +743,19 @@
if (target.nodeName.toLowerCase() === 'select') {
$target.on('change.validatrinput', function () {
setTimeout(function () {
- validateElement(target);
+ validateElement(target);
}, 1);
});
}
$target.on({
'blur.validatrinput': function () {
- validateElement(target);
+ validateElement(target);
},
'keyup.validatrinput': function (event) {
- if (target.value.length && $.inArray(keyCodes, event.keyCode) === -1) {
+ if (target.value.length && $.inArray(event.keyCode, keyCodes) === -1) {
validateElement(target);
- }
+ }
}
});
}
@@ -584,7 +766,9 @@
function validateElement(element) {
if (element.type === 'radio') {
- var radio = $(document.getElementsByName(element.name)).filter('[required]');
+ // use form context in case of extra form(s) with input that has
+ // same name on the page.
+ var radio = $(element).closest('form').find('[name=' + element.name + ']' ).filter('[required]');
if (radio.length) {
element = radio[0];
}
@@ -604,7 +788,7 @@
} else {
if (required) {
check = Tests.required(element);
- }
+ }
if (check.valid && element.value.length && !filters.boxes.test(type)) {
if (element.pattern) {
@@ -631,16 +815,16 @@
if (check.valid) {
$element.trigger('valid');
return true;
- }
-
+ }
+
$.data(element, 'validationMessage', check.message);
$element.trigger('invalid');
-
+
return false;
}
function validateForm (elements) {
- var valid = true;
+ var valid = true;
elements.each(function (i, element) {
if (!validateElement(element)) {
@@ -729,7 +913,7 @@
if (location === 'bottom') {
error.offset({top: offset.top + error.outerHeight()});
- }
+ }
} else if (filters.leftright.test(location)) {
error.offset({top: (offset.top + $target.outerHeight() / 2) - (error.outerHeight() / 2)});
@@ -739,13 +923,13 @@
if (location === 'right') {
error.offset({left: offset.left + $target.outerWidth() + 2});
- }
- }
+ }
+ }
}
/*! Inspired by jQuery UI - v1.9.2 - 2012-12-04
* http://jqueryui.com
- * Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT
+ * Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT
*/
$.fn.validatr = function(options) {
var isMethod = typeof options === 'string',
@@ -756,7 +940,7 @@
if (isMethod) {
this.each(function() {
var methodValue;
-
+
instance = $.data(this, 'validatr');
if (!instance) {
throw new Error("cannot call methods on validatr prior to initialization; attempted to call method '" + options + "'" );
@@ -787,17 +971,21 @@
};
$.fn.validatr.defaultOptions = {
- dateFormat: 'yyyy-mm-dd',
+ dateFormat: 'yyyy-mm-d',
location: 'right',
+ monthFormat: 'yyyy-mm',
position: position,
showall: false,
template: '
{{message}}
',
theme: '',
- valid: $.noop
+ valid: $.noop,
+ weekFormat: 'yyyy-Www',
+ weekStart: 0,
+ yearStart: 6
};
$.validatr = new Validatr();
-
+
$.validatr.messages = {
checkbox: 'Please check this box if you want to proceed.',
color: 'Please enter a color in the format #xxxxxx',
@@ -809,7 +997,7 @@
radio: 'Please select one of these options.',
range: {
base: 'Please enter a {{type}}',
- overflow: 'Please enter a {{type}} greater than or equal to {{min}}.',
+ overflow: 'Please enter a {{type}} greater than or equal to {{min}}.',
overUnder: 'Please enter a {{type}} greater than or equal to {{min}} and less than or equal to {{max}}.',
invalid: 'Invalid {{type}}',
underflow: 'Please enter a {{type}} less than or equal to {{max}}.'
@@ -819,10 +1007,10 @@
time: 'Please enter a time in the format hh:mm:ss',
url: 'Please enter a url.'
};
-
+
$.validatr.debug = function () {
/*global QUnit */
-
+
if (!QUnit) {
throw new Error('QUnit is required for debugging');
}
@@ -837,5 +1025,4 @@
$.expr[':'].validatr = function(elem) {
return !!$.data(elem, 'validatr');
};
-
}(this, this.document, jQuery));
diff --git a/dist/validatr.min.js b/dist/validatr.min.js
index c58837c..a13a3c7 100644
--- a/dist/validatr.min.js
+++ b/dist/validatr.min.js
@@ -1,4 +1,4 @@
-/*! Validatr - v0.5.1 - 2013-03-12
+/*! Validatr - v0.5.1 - 2013-05-17
* http://jaymorrow.github.com/validatr/
* Copyright (c) 2013 Jay Morrow; Licensed MIT */
-(function(t,e,a,r){"use strict";function i(t,e){if(this.el=t,this.$el=a(t),!this.$el.length||!this.$el.is("form"))throw Error("validatr needs a form to work.");this.isSubmit=!1,this.firstError=!1,this.options=a.extend({},a.fn.validatr.defaultOptions,e),this.template=function(t){var e=a(t.template).addClass("validatr-message");return t.theme.length?e.addClass(w[t.theme]||t.theme):e.css(k),e[0].outerHTML}(this.options),this.option=function(t,e){return arguments.length?e===r?this.options[t]===r?null:this.options[t]:(this.options[t]=e,r):a.extend({},this.options)},this.formElements=this.getElements(this.el).on("valid.validatr",a.proxy(f,this)).on("invalid.validatr",a.proxy(c,this)),this.el.noValidate=!0,this.$el.on("submit.validatr",a.proxy(m,this)),this.$el.on("reset.validatr",a.proxy(p,this))}function s(){this.formElements.on({"focus.validatrelement":o,"blur.validatrelement":l}),a("input[type=radio], input[type=checkbox]").on("click.validatrelement",function(t){u(t.target)})}function n(){this.formElements.off(".validatrelement")}function o(t){var e=t.target,r=a(e);"select"===e.nodeName.toLowerCase()&&r.on("change.validatrinput",function(){setTimeout(function(){u(e)},1)}),r.on({"blur.validatrinput":function(){u(e)},"keyup.validatrinput":function(t){e.value.length&&-1===a.inArray(E,t.keyCode)&&u(e)}})}function l(t){a(t.target).off(".validatrinput")}function u(t){if("radio"===t.type){var r=a(e.getElementsByName(t.name)).filter("[required]");r.length&&(t=r[0])}var i=a(t),s=x.notInput.test(t.nodeName)?t.nodeName.toLowerCase():t.getAttribute("type"),n=v.attributes.required?t.required:a(t).is("[required]"),o={valid:!0,message:""};if(v.inputtypes[s]?(o.valid=t.validity.valid,o.message=t.validationMessage):(n&&(o=y.required(t)),o.valid&&t.value.length&&!x.boxes.test(s)&&(t.pattern&&(s="pattern"),y[s]&&(o=y[s](t)))),o.valid)for(var l in b)if(b.hasOwnProperty(l)&&i.is("[data-"+l+"]")&&(o=b[l](t),!o.valid))break;return o.valid?(i.trigger("valid"),!0):(a.data(t,"validationMessage",o.message),i.trigger("invalid"),!1)}function d(t){var e=!0;return t.each(function(t,a){u(a)||(e=!1)}),e}function m(){this.isSubmit=!0,p.call(this);var t=d(this.formElements);return t?this.options.valid.call(this.el,this.el):(s.call(this),this.isSubmit=!1,t)}function p(){n.call(this),this.firstError=!1,this.formElements.next(".validatr-message").remove()}function c(t){if(!A){t.preventDefault();var e=t.target,i=a(e),s=this.options,n=e.getAttribute("data-message")||a.data(e,"validationMessage"),o=a(this.template.replace("{{message}}",n));return this.isSubmit&&!this.firstError?(this.firstError=i.after(o),s.position.call(this,o,i),r):((!this.isSubmit||s.showall)&&(f(t),i.after(o),s.position.call(this,o,i)),r)}}function f(t){A||a(t.target).next(".validatr-message").remove()}function h(t,e){t.css("position","absolute");var a=e.offset(),r=e[0].getAttribute("data-location")||this.options.location;x.topbottom.test(r)?(t.offset({left:a.left}),"top"===r&&t.offset({top:a.top-t.outerHeight()-2}),"bottom"===r&&t.offset({top:a.top+t.outerHeight()})):x.leftright.test(r)&&(t.offset({top:a.top+e.outerHeight()/2-t.outerHeight()/2}),"left"===r&&t.offset({left:a.left-t.outerWidth()-2}),"right"===r&&t.offset({left:a.left+e.outerWidth()+2}))}var v=function(){var t,a={},i=e.documentElement,s=e.createElement("input"),n=e.createElement("select"),o=e.createElement("textarea"),l=":)",u={},d={};return a.attributes=function(t){for(var e=0,a=t.length;a>e;e++)d[t[e]]=!!(t[e]in s);return d}("max min multiple pattern required step".split(" ")),a.inputtypes=function(t){for(var a,n,o,d=0,m=t.length;m>d;d++)s.setAttribute("type",n=t[d]),a="text"!==s.type,a&&(s.value=l,s.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(n)&&s.style.WebkitAppearance!==r?(i.appendChild(s),o=e.defaultView,a=o.getComputedStyle&&"textfield"!==o.getComputedStyle(s,null).WebkitAppearance&&0!==s.offsetHeight,i.removeChild(s)):/^(search|tel)$/.test(n)||(a=/^(url|email)$/.test(n)?s.checkValidity&&s.checkValidity()===!1:s.value!==l)),u[t[d]]=!!a;return u}("search tel url email datetime date month week time datetime-local number range color".split(" ")),function(r){for(var i=0,n=r.length;n>i;i++){t=s;try{t.setAttribute("type",r[i])}catch(o){t=e.createElement('')}t.style.cssText="position:absolute;visibility:hidden;",a.inputtypes[r[i]]=!!t.checkValidity}}("text password radio checkbox".split(" ")),a.inputtypes.select=!!n.checkValidity,a.inputtypes.textarea=!!o.checkValidity,s=null,t=null,n=null,o=null,a}(),g=function(){function t(t,e){for(var a=-1,r=t?t.length:0;r>++a;)if(t[a]===e)return a;return-1}function e(e){var i=e.getAttribute("data-format")||a.fn.validatr.defaultOptions.dateFormat,s=i.split(n.separatorsNoGroup),o=e.value.split(n.separatorsNoGroup),l="yyyy-mm-dd".split("-"),u=i.replace(n.separators,"\\$1").replace("yyyy",n.dateParts.yyyy).replace("mm",n.dateParts.mm).replace("dd",n.dateParts.dd),d=-1,m=l.length,p=[];if(u=RegExp(u),!u.test(e.value))return!1;for(;m>++d;)p[d]=o[t(s,l[d])];return r(p.join("-"))}function r(t){if(!s.isoDate.test(t))return!1;var e=s.isoDate.exec(t);return new Date(parseInt(e[1],10),parseInt(e[2],10)-1,parseInt(e[3],10))}function i(t,e){function r(t){return 10>t?"0"+t:t}var i=r(t.getDate()),s=r(t.getMonth()+1),n=t.getFullYear(),o=(e.getAttribute("data-format")||a.fn.validatr.defaultOptions.dateFormat).replace("mm",s).replace("yyyy",n).replace("dd",i);return o}var s={isoDate:/^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/},n={separators:/(\/|\-|\.)/g,separatorsNoGroup:/\/|\-|\./g,dateParts:{dd:"(0[1-9]|[12][0-9]|3[01])",mm:"(0[1-9]|1[012])",yyyy:"(\\d{4})"}};return{formatISODate:i,parseDate:e,parseISODate:r}}(),y=function(){var t={color:/^#[0-9A-F]{6}$/i,email:/^[a-zA-Z0-9.!#$%&’*+\/=?\^_`{|}~\-]+@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$/,isoDate:/^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/,number:/^-?\d*\.?\d*$/,time:/^([01][0-9]|2[0-3])(:([0-5][0-9])){2}$/,url:/^\s*https?:\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?\s*$/},i={boxes:/checkbox|radio/i,spaces:/,\s*/},s=function(t,e,r,i,s){var n=!0,o=a.validatr.messages.range.base,l=e,u=r;return"date"===s&&(l=e&&g.formatISODate(e,this),u=r&&g.formatISODate(r,this)),t!==!1&&(i!==!1&&(n="any"===i?!0:0===(t-e)%i,o=a.validatr.messages.range.invalid),n&&(e!==!1&&r!==!1?(n=t>=e&&r>=t,o=a.validatr.messages.range.overUnder):e!==!1?(n=t>=e,o=a.validatr.messages.range.overflow):r!==!1&&(n=r>=t,o=a.validatr.messages.range.underflow))),{valid:t!==!1&&n,message:o.replace("{{type}}",s).replace("{{min}}",l).replace("{{max}}",u)}};return{checkbox:function(t){return{valid:t.checked,message:a.validatr.messages.checkbox}},color:function(e){return{valid:t.color.test(e.value),message:a.validatr.messages.color}},date:function(t){var e=a(t),r=v.inputtypes.date?g.parseISODate(t.value):g.parseDate(t),i=e.attr("min")?g.parseISODate(e.attr("min")):!1,n=e.attr("max")?g.parseISODate(e.attr("max")):!1,o=!1;return s.call(t,r,i,n,o,"date")},email:function(e){var s=!0,n=a.validatr.messages.email.single,o=v.attributes.multiple?e.multiple:a(e).is("[multiple]");if(o){var l=e.value.split(i.spaces);a.each(l,function(e,i){return t.email.test(i)?r:(s=!1,n=a.validatr.messages.email.multiple,r)})}else s=t.email.test(e.value);return{valid:s,message:n}},number:function(e){var a=e.value.replace(",",""),r=(t.number.test(a)?parseFloat(a):!1,t.number.test(e.getAttribute("min"))?parseFloat(e.getAttribute("min")):!1),i=t.number.test(e.getAttribute("max"))?parseFloat(e.getAttribute("max")):!1,n=t.number.test(e.getAttribute("step"))?parseFloat(e.getAttribute("step")):"any"===e.getAttribute("step")?"any":!1;return(n===!1||0>=n)&&(n=1),s.call(e,a,r,i,n,"number")},pattern:function(t){return{valid:RegExp(t.getAttribute("pattern")).test(t.value),message:a.validatr.messages.pattern}},radio:function(t){return{valid:a(e.getElementsByName(t.name)).is(":checked"),message:a.validatr.messages.radio}},range:function(t){return this.number(t)},required:function(t){return i.boxes.test(t.type)?this[t.type](t):{valid:!!t.value.length,message:"select"===t.nodeName.toLowerCase()?a.validatr.messages.select:a.validatr.messages.required}},time:function(e){return{valid:t.time.test(e.value),message:a.validatr.messages.time}},url:function(e){return{valid:t.url.test(e.value),message:a.validatr.messages.url}}}}(),b=function(){function t(t){if("text"!==t.type)throw Error("element must have a type of text");var e=t.getAttribute("data-as");return y[e]?y[e](t):r}function i(t){var r=t.getAttribute("data-match"),i=e.getElementById(r)||e.getElementsByName(r)[0];return i?(a(i).off("valid.validatrinput").on("valid.validatrinput",function(){t.value===i.value&&u(t)}),{valid:t.value===i.value,message:"'"+t.name+"' does not equal '"+i.name+"'"}):{valid:!1,message:"'"+r+"' can not be found"}}return{as:t,match:i}}(),x={boxes:/checkbox|radio/i,leftright:/left|right/i,notInput:/select|textarea/i,topbottom:/top|bottom/i},E=[16,17,18,19,20,33,34,35,36,37,39],w={bootstrap:"alert alert-error",jqueryui:"ui-state-error ui-corner-all"},k={color:"#f0444d",backgroundColor:"#ffcbcb",border:"1px solid #e4a6af",padding:"2px 6px",borderRadius:"2px"},A=!1,q=function(){};q.prototype={addTest:function(t){var e="string"!=typeof t,r=Array.prototype.slice.call(arguments,1)[0];if(e)a.extend(b,t);else{if(!r)throw Error("You must include a callback function");b[t]=r}},getElements:function(t){if(this.formElements)return this.formElements;var e=a(t).map(function(){return a.makeArray(this.elements)}).not("fieldset, button, input[type=submit], input[type=button], input[type=reset]");return t.id&&(e=e.add(a('[form="'+t.id+'"]'))),e},validateElement:function(t){if(!t)throw Error("method requires an element");A=!0;var e=u(t[0]||t);return A=!1,e},validateForm:function(t){var e,a=this.el||(t instanceof jQuery?t[0]:t);if("form"!==a.nodeName.toLowerCase())throw Error("you must pass a form to this method");return A=!0,e=d(this.formElements||this.getElements(a)),A=!1,e}},a.fn.validatr=function(t){var e,s="string"==typeof t,n=Array.prototype.slice.call(arguments,1),o=this;if(s)this.each(function(){var i;if(e=a.data(this,"validatr"),!e)throw Error("cannot call methods on validatr prior to initialization; attempted to call method '"+t+"'");if(!a.isFunction(e[t]))throw Error("no such method '"+t+"' for validatr instance");return i=e[t].apply(e,n),i!==e&&i!==r?(o=i&&i.jquery?o.pushStack(i.get()):i,!1):r});else{var l;this.each(function(){e=a.data(this,"validatr"),e||(l=new q,i.call(l,this,t||{}),a.data(this,"validatr",l))})}return o},a.fn.validatr.defaultOptions={dateFormat:"yyyy-mm-dd",location:"right",position:h,showall:!1,template:"
{{message}}
",theme:"",valid:a.noop},a.validatr=new q,a.validatr.messages={checkbox:"Please check this box if you want to proceed.",color:"Please enter a color in the format #xxxxxx",email:{single:"Please enter an email address.",multiple:"Please enter a comma separated list of email addresses."},pattern:"Please match the requested format.",radio:"Please select one of these options.",range:{base:"Please enter a {{type}}",overflow:"Please enter a {{type}} greater than or equal to {{min}}.",overUnder:"Please enter a {{type}} greater than or equal to {{min}} and less than or equal to {{max}}.",invalid:"Invalid {{type}}",underflow:"Please enter a {{type}} less than or equal to {{max}}."},required:"Please fill out this field.",select:"Please select an item in the list.",time:"Please enter a time in the format hh:mm:ss",url:"Please enter a url."},a.validatr.debug=function(){if(!QUnit)throw Error("QUnit is required for debugging");this.Support=v,this.Tests=y,this.CustomTests=b,this.Format=g},a.expr[":"].validatr=function(t){return!!a.data(t,"validatr")}})(this,this.document,jQuery);
\ No newline at end of file
+(function(t,e,a,r){"use strict";function i(t,e){if(this.el=t,this.$el=a(t),!this.$el.length||!this.$el.is("form"))throw Error("validatr needs a form to work.");this.isSubmit=!1,this.firstError=!1,this.options=a.extend({},a.fn.validatr.defaultOptions,e),this.template=function(t){var e=a(t.template).addClass("validatr-message");return t.theme.length?e.addClass(k[t.theme]||t.theme):e.css(E),e[0].outerHTML}(this.options),this.option=function(t,e){return arguments.length?e===r?this.options[t]===r?null:this.options[t]:(this.options[t]=e,r):a.extend({},this.options)},this.formElements=this.getElements(this.el).on("valid.validatr",a.proxy(h,this)).on("invalid.validatr",a.proxy(f,this)),this.el.noValidate=!0,this.$el.on("submit.validatr",a.proxy(m,this)),this.$el.on("reset.validatr",a.proxy(c,this))}function n(){this.formElements.on({"focus.validatrelement":o,"blur.validatrelement":l}),a("input[type=radio], input[type=checkbox]").on("click.validatrelement",function(t){u(t.target)})}function s(){this.formElements.off(".validatrelement")}function o(t){var e=t.target,r=a(e);"select"===e.nodeName.toLowerCase()&&r.on("change.validatrinput",function(){setTimeout(function(){u(e)},1)}),r.on({"blur.validatrinput":function(){u(e)},"keyup.validatrinput":function(t){e.value.length&&-1===a.inArray(t.keyCode,x)&&u(e)}})}function l(t){a(t.target).off(".validatrinput")}function u(t){if("radio"===t.type){var e=a(t).closest("form").find("[name="+t.name+"]").filter("[required]");e.length&&(t=e[0])}var r=a(t),i=w.notInput.test(t.nodeName)?t.nodeName.toLowerCase():t.getAttribute("type"),n=v.attributes.required?t.required:a(t).is("[required]"),s={valid:!0,message:""};if(v.inputtypes[i]?(s.valid=t.validity.valid,s.message=t.validationMessage):(n&&(s=y.required(t)),s.valid&&t.value.length&&!w.boxes.test(i)&&(t.pattern&&(i="pattern"),y[i]&&(s=y[i](t)))),s.valid)for(var o in b)if(b.hasOwnProperty(o)&&r.is("[data-"+o+"]")&&(s=b[o](t),!s.valid))break;return s.valid?(r.trigger("valid"),!0):(a.data(t,"validationMessage",s.message),r.trigger("invalid"),!1)}function d(t){var e=!0;return t.each(function(t,a){u(a)||(e=!1)}),e}function m(){this.isSubmit=!0,c.call(this);var t=d(this.formElements);return t?this.options.valid.call(this.el,this.el):(n.call(this),this.isSubmit=!1,t)}function c(){s.call(this),this.firstError=!1,this.formElements.next(".validatr-message").remove()}function f(t){if(!A){t.preventDefault();var e=t.target,i=a(e),n=this.options,s=e.getAttribute("data-message")||a.data(e,"validationMessage"),o=a(this.template.replace("{{message}}",s));return this.isSubmit&&!this.firstError?(this.firstError=i.after(o),n.position.call(this,o,i),r):((!this.isSubmit||n.showall)&&(h(t),i.after(o),n.position.call(this,o,i)),r)}}function h(t){A||a(t.target).next(".validatr-message").remove()}function p(t,e){t.css("position","absolute");var a=e.offset(),r=e[0].getAttribute("data-location")||this.options.location;w.topbottom.test(r)?(t.offset({left:a.left}),"top"===r&&t.offset({top:a.top-t.outerHeight()-2}),"bottom"===r&&t.offset({top:a.top+t.outerHeight()})):w.leftright.test(r)&&(t.offset({top:a.top+e.outerHeight()/2-t.outerHeight()/2}),"left"===r&&t.offset({left:a.left-t.outerWidth()-2}),"right"===r&&t.offset({left:a.left+e.outerWidth()+2}))}var v=function(){var t,a={},i=e.documentElement,n=e.createElement("input"),s=e.createElement("select"),o=e.createElement("textarea"),l=":)",u={},d={};return a.attributes=function(t){for(var e=0,a=t.length;a>e;e++)d[t[e]]=!!(t[e]in n);return d}("max min multiple pattern required step".split(" ")),a.inputtypes=function(t){for(var a,s,o,d=0,m=t.length;m>d;d++)n.setAttribute("type",s=t[d]),a="text"!==n.type,a&&(n.value=l,n.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(s)&&n.style.WebkitAppearance!==r?(i.appendChild(n),o=e.defaultView,a=o.getComputedStyle&&"textfield"!==o.getComputedStyle(n,null).WebkitAppearance&&0!==n.offsetHeight,i.removeChild(n)):/^(search|tel)$/.test(s)||(a=/^(url|email)$/.test(s)?n.checkValidity&&n.checkValidity()===!1:n.value!==l)),u[t[d]]=!!a;return u}("search tel url email datetime date month week time datetime-local number range color".split(" ")),function(r){for(var i=0,s=r.length;s>i;i++){t=n;try{t.setAttribute("type",r[i])}catch(o){t=e.createElement('')}t.style.cssText="position:absolute;visibility:hidden;",a.inputtypes[r[i]]=!!t.checkValidity}}("text password radio checkbox".split(" ")),a.inputtypes.select=!!s.checkValidity,a.inputtypes.textarea=!!o.checkValidity,n=null,t=null,s=null,o=null,a}(),g=function(){function t(t){return t.substr(0,1).toUpperCase()+t.substr(1)}function e(t){return 10>t?"0"+t:t}function i(t,e){for(var a=-1,r=t?t.length:0;r>++a;)if(t[a]===e)return a;return-1}function n(t){switch(t){case"d":case"w":case"m":return h;case"dd":case"ww":case"mm":case"yy":return p;case"M":return w;case"MM":return b;case"yyyy":return v}}function s(t,e,a){if(e!==r)switch(t){case"d":case"dd":a[2]=~~e;break;case"w":case"ww":a[3]=~~e;break;case"m":case"mm":a[1]=~~e-1;break;case"M":a[1]=i(k,e.toLowerCase());break;case"MM":a[1]=i(x,e.toLowerCase());break;case"yy":a[0]=~~("20"+e);break;case"yyyy":a[0]=~~e}}function o(t){var e=new Date(t.getFullYear(),0,1,0,0,0);return Math.ceil(((t-e)/864e5+e.getDay()+1)/7)}function l(t){var e=u(t[0]),r=6048e5*(t[3]-1),i=e.getTime()+r-864e5*(e.getDay()-a.fn.validatr.defaultOptions.weekStart),n=new Date(i);return n.setHours(0),n}function u(t){var e=new Date(t,0,1,0,0,0),r=a.fn.validatr.defaultOptions.yearStart-e.getDay()+e.getDate();return e.setDate(r),e}function d(t){var e=0,a=[],r=!1;for(e;7>e;e+=1){if(r="number"==typeof t[e],!r&&2>e)return!1;a[e]=r?t[e]:2===e?1:0}return new Date(a[0],a[1],a[2],a[3],a[4],a[5],a[6])}function m(t,e){var a,i=e.match(f)||[],o=[],u=i.length,m=0;if(!u)throw Error("Ivalid date format.");for(m;u>m;m+=1)a=(n(i[m]).exec(t)||[])[0],a&&(t=t.slice(t.indexOf(a)+a.length),s(i[m],a,o));return/w?w/.test(e)?l(o):o.length&&o.length===u?d(o):r}function c(t,e){if(t===!1)return!1;e===r&&(e="yyyy-mm-dd");var a=e.match(f)||[],i=a.length,n=0;if(!i)throw Error("Ivalid date format.");for(n;i>n;n+=1)E[a[n]]&&(e=e.replace(a[n],E[a[n]].call(t)));return e}var f=/(d?d|w?w|m?m|(?:yy)?yy|M?M)/g,h=/\d{1,2}/,p=/\d{2}/,v=/\d{4}/,g="January|February|March|April|May|June|July|August|September|October|November|December",y="Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",b=RegExp(g,"i"),w=RegExp(y,"i"),x=g.toLowerCase().split("|"),k=y.toLowerCase().split("|"),E={d:function(){return this.getDate()},dd:function(){return e(this.getDate())},w:function(){return o(this)},ww:function(){return e(o(this))},m:function(){return this.getMonth()+1},mm:function(){return e(this.getMonth()+1)},yy:function(){return(""+this.getFullYear()).substr(2)},yyyy:function(){return this.getFullYear()},M:function(){return t(k[this.getMonth()])},MM:function(){return t(x[this.getMonth()])}};return{date:m,isoDate:function(t){return m(t,"yyyy-mm-dd")},toString:c}}(),y=function(){var t={color:/^#[0-9A-F]{6}$/i,email:/^[a-zA-Z0-9.!#$%&’*+\/=?\^_`{|}~\-]+@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$/,number:/^-?\d*\.?\d*$/,url:/^\s*https?:\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?\s*$/},e={boxes:/checkbox|radio/i,spaces:/,\s*/},i=function(t,e,r,i){var n=!0,s=a.validatr.messages.range.base;return t!==!1&&(i!==!1&&(n="any"===i?!0:0===(t-e)%i,s=a.validatr.messages.range.invalid),n&&(e!==!1&&r!==!1?(n=t>=e&&r>=t,s=a.validatr.messages.range.overUnder):e!==!1?(n=t>=e,s=a.validatr.messages.range.overflow):r!==!1&&(n=r>=t,s=a.validatr.messages.range.underflow))),{valid:t!==!1&&n,message:s}},n=function(t,e){return e+="Format",t.getAttribute("data-format")||a.data(t.form,"validatr").options[e]||a.fn.validatr.defaultOptions[e]},s=function(t,e,a,r){return t=t.replace("{{type}}",e),a&&(t=t.replace("{{min}}",a)),r&&(t=t.replace("{{max}}",r)),t};return{checkbox:function(t){return{valid:t.checked,message:a.validatr.messages.checkbox}},color:function(e){return{valid:t.color.test(e.value),message:a.validatr.messages.color}},date:function(t){var e=a(t),r=n(t,"date"),o=g.date(t.value,r)||!1,l=e.attr("min")?g.isoDate(e.attr("min")):!1,u=e.attr("max")?g.isoDate(e.attr("max")):!1,d=!1,m=i(o,l,u,d);return m.valid||(m.message=s(m.message,"date",g.toString(l,r),g.toString(u,r))),m},email:function(i){var n=!0,s=a.validatr.messages.email.single,o=v.attributes.multiple?i.multiple:a(i).is("[multiple]");if(o){var l=i.value.split(e.spaces);a.each(l,function(e,i){return t.email.test(i)?r:(n=!1,s=a.validatr.messages.email.multiple,r)})}else n=t.email.test(i.value);return{valid:n,message:s}},month:function(t){var e=a(t),r=n(t,"month"),o=g.date(t.value,r)||!1,l=e.attr("min")?g.isoDate(e.attr("min")+"01"):!1,u=e.attr("max")?g.isoDate(e.attr("max")+"01"):!1,d=!1,m=i(o,l,u,d);return m.valid||(m.message=s(m.message,"month",g.toString(l,r),g.toString(u,r))),m},number:function(e){var a,r=e.value.replace(",",""),n=(t.number.test(r)?parseFloat(r):!1,t.number.test(e.getAttribute("min"))?parseFloat(e.getAttribute("min")):!1),o=t.number.test(e.getAttribute("max"))?parseFloat(e.getAttribute("max")):!1,l=t.number.test(e.getAttribute("step"))?parseFloat(e.getAttribute("step")):"any"===e.getAttribute("step")?"any":!1;return(l===!1||0>=l)&&(l=1),a=i(r,n,o,l,"number"),a.valid||(a.message=s(a.message,"number",n,o)),a},pattern:function(t){return{valid:RegExp(t.getAttribute("pattern")).test(t.value),message:a.validatr.messages.pattern}},radio:function(t){return{valid:a(t).closest("form").find("[name="+t.name+"]").is(":checked"),message:a.validatr.messages.radio}},range:function(t){return this.number(t)},required:function(t){return e.boxes.test(t.type)?this[t.type](t):{valid:!!t.value.length,message:"select"===t.nodeName.toLowerCase()?a.validatr.messages.select:a.validatr.messages.required}},url:function(e){return{valid:t.url.test(e.value),message:a.validatr.messages.url}}}}(),b=function(){function t(t){if("text"!==t.type)throw Error("element must have a type of text");var e=t.getAttribute("data-as");return y[e]?y[e](t):r}function i(t){var r=t.getAttribute("data-match"),i=e.getElementById(r)||e.getElementsByName(r)[0];return i?(a(i).off("valid.validatrinput").on("valid.validatrinput",function(){t.value===i.value&&u(t)}),{valid:t.value===i.value,message:"'"+t.name+"' does not equal '"+i.name+"'"}):{valid:!1,message:"'"+r+"' can not be found"}}return{as:t,match:i}}(),w={boxes:/checkbox|radio/i,leftright:/left|right/i,notInput:/select|textarea/i,topbottom:/top|bottom/i},x=[16,17,18,19,20,33,34,35,36,37,39],k={bootstrap:"alert alert-error",jqueryui:"ui-state-error ui-corner-all"},E={color:"#f0444d",backgroundColor:"#ffcbcb",border:"1px solid #e4a6af",padding:"2px 6px",borderRadius:"2px"},A=!1,M=function(){};M.prototype={addTest:function(t){var e="string"!=typeof t,r=Array.prototype.slice.call(arguments,1)[0];if(e)a.extend(b,t);else{if(!r)throw Error("You must include a callback function");b[t]=r}},getElements:function(t){if(this.formElements)return this.formElements;var e=a(t).map(function(){return a.makeArray(this.elements)}).not("fieldset, button, input[type=submit], input[type=button], input[type=reset]");return t.id&&(e=e.add(a('[form="'+t.id+'"]'))),e},validateElement:function(t){if(!t)throw Error("method requires an element");A=!0;var e=u(t[0]||t);return A=!1,e},validateForm:function(t){var e,a=this.el||(t instanceof jQuery?t[0]:t);if("form"!==a.nodeName.toLowerCase())throw Error("you must pass a form to this method");return A=!0,e=d(this.formElements||this.getElements(a)),A=!1,e}},a.fn.validatr=function(t){var e,n="string"==typeof t,s=Array.prototype.slice.call(arguments,1),o=this;if(n)this.each(function(){var i;if(e=a.data(this,"validatr"),!e)throw Error("cannot call methods on validatr prior to initialization; attempted to call method '"+t+"'");if(!a.isFunction(e[t]))throw Error("no such method '"+t+"' for validatr instance");return i=e[t].apply(e,s),i!==e&&i!==r?(o=i&&i.jquery?o.pushStack(i.get()):i,!1):r});else{var l;this.each(function(){e=a.data(this,"validatr"),e||(l=new M,i.call(l,this,t||{}),a.data(this,"validatr",l))})}return o},a.fn.validatr.defaultOptions={dateFormat:"yyyy-mm-d",location:"right",monthFormat:"yyyy-mm",position:p,showall:!1,template:"
{{message}}
",theme:"",valid:a.noop,weekFormat:"yyyy-Www",weekStart:0,yearStart:6},a.validatr=new M,a.validatr.messages={checkbox:"Please check this box if you want to proceed.",color:"Please enter a color in the format #xxxxxx",email:{single:"Please enter an email address.",multiple:"Please enter a comma separated list of email addresses."},pattern:"Please match the requested format.",radio:"Please select one of these options.",range:{base:"Please enter a {{type}}",overflow:"Please enter a {{type}} greater than or equal to {{min}}.",overUnder:"Please enter a {{type}} greater than or equal to {{min}} and less than or equal to {{max}}.",invalid:"Invalid {{type}}",underflow:"Please enter a {{type}} less than or equal to {{max}}."},required:"Please fill out this field.",select:"Please select an item in the list.",time:"Please enter a time in the format hh:mm:ss",url:"Please enter a url."},a.validatr.debug=function(){if(!QUnit)throw Error("QUnit is required for debugging");this.Support=v,this.Tests=y,this.CustomTests=b,this.Format=g},a.expr[":"].validatr=function(t){return!!a.data(t,"validatr")}})(this,this.document,jQuery);
\ No newline at end of file
diff --git a/src/js/validatr.js b/src/js/validatr.js
index 805355f..e071277 100644
--- a/src/js/validatr.js
+++ b/src/js/validatr.js
@@ -502,7 +502,9 @@
radio: function (element) {
return {
- valid: $(document.getElementsByName(element.name)).is(':checked'),
+ // use form context in case of extra form(s) with input that has
+ // same name on the page.
+ valid: $(element).closest('form').find('[name=' + element.name + ']' ).is(':checked'),
message: $.validatr.messages.radio
};
},
@@ -771,7 +773,9 @@
function validateElement(element) {
if (element.type === 'radio') {
- var radio = $(document.getElementsByName(element.name)).filter('[required]');
+ // use form context in case of extra form(s) with input that has
+ // same name on the page.
+ var radio = $(element).closest('form').find('[name=' + element.name + ']' ).filter('[required]');
if (radio.length) {
element = radio[0];
}