diff --git a/README.md b/README.md index f12f6e8..d11d5be 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # jQuery Validator -当前版本: **1.3.9** +当前版本: **1.4.0** jQuery Validator 是一个简单易用、功能强大的基于jQuery的表单验证框架。其设计目标如下: * 【简单易用,轻松上手】:一般情况下,无需进行任何配置,内置的校验器和校验规则即可满足绝大多数中文环境下的常规表单验证需求,开箱即可使用! diff --git a/jquery-validator.js b/jquery-validator.js index a725561..660c151 100644 --- a/jquery-validator.js +++ b/jquery-validator.js @@ -1,6 +1,6 @@ /************************************** @Name: jQuery-Validator 基于jQuery的前端验证框架 - @Version: 1.3.9 + @Version: 1.4.0 @Author: Ready @Date: 2022-01-12 @Documentation: https://codeplayer.vip/p/j7sud @@ -10,7 +10,7 @@ !function ($, global) { var console = global && global.console; if(typeof jQuery === "undefined" || $ !== jQuery){ - console && console.log("jQuery must be initialized before loading the Validator."); + console && console.warn("jQuery must be initialized before loading the Validator."); return; } var V = function(method){ @@ -36,7 +36,7 @@ }, fn = V.fn = V.prototype = { // 版本号 - version: "1.3.9", + version: "1.4.0", constructor: V, @@ -45,8 +45,19 @@ return $dom.val(); }, - // 严格模式:如果为false,则指定选择器没有对应元素时,直接忽略该元素的校验 - strict: true, + // 校验跳过模式(支持位运算或运算):0=不忽略任何元素;1=仅忽略不存在的元素;2=仅忽略不可见的元素;4=仅忽略只读的元素 + skip: 0, + + filter: function($dom, context){ + var s = this.skip; + if ( f > 0 && ( + (s & 1) === 1 && !$dom.length + || (s & 2) === 2 && !$dom.is(':visible') + || (s & 4) === 4 && $dom.is('[readonly]')) + ){ + return false; + } + }, // 用于选取label的attribute labelAttr: "label", @@ -163,26 +174,28 @@ expr = sign + expr; } // 位数表达式 - var subExpr = expr.substr(1); + var subExpr = expr.substr(1), digits = "+", fraction = ""; switch(subExpr){ case "int": case "integer": - regex = new RegExp("^" + signExpr + "\\d+$"); break; case "money": - regex = new RegExp("^" + signExpr + "\\d+(\\.\\d{1,2})?$"); + fraction = "(\\.\\d{1,2})?"; break; case "float": case "double": - regex = new RegExp("^" + signExpr + "\\d+(\\.\\d+)?$"); + fraction = "(\\.\\d+)?"; break; default: var subArray = subExpr.split(".", 2); - regex = "^" + signExpr + "\\d" + subArray[0]; - if(subArray[1]) regex += "\\.\\d" + subArray[1]; - regex = new RegExp(regex + "$"); + digits = subArray[0]; + if( subArray[1] ){ + fraction = subArray[1].startsWith("{0,") + ? "(\\.\\d" + subArray[1].replace(/^\{0,/, "{1,") + ")?" + : "\\.\\d" + subArray[1]; + } } - cache[context.rule.format] = regex; + cache[context.rule.format] = regex = new RegExp("^" + signExpr + "\\d" + digits + fraction + "$"); } V.debug && log( "number formatter [" + expr + "] regexp:", regex ); if(regex.test(value)){ @@ -533,7 +546,7 @@ context = V.context = { ruleName: ruleName, origin: rule, $dom: $dom, rule: rule }; V.debug && log( "current validate context [" + (is$ ? $dom.selector : value) + "]:" , context ); if( is$ ){ - if(!$dom.length && !me.strict) return me.afterHandler(true, context); // 非严格模式,直接跳过校验 + if( me.filter($dom, context) === false ) return me.afterHandler(true, context); // 非严格模式,直接跳过校验 value = me.getValue($dom, context); if( required == null ){ var r = me.isRequired(value, context); diff --git a/jquery-validator.min.js b/jquery-validator.min.js index d71674f..9aedc56 100644 --- a/jquery-validator.min.js +++ b/jquery-validator.min.js @@ -1,10 +1,10 @@ /************************************** @Name: jQuery-Validator 基于jQuery的前端验证框架 - @Version: 1.3.9 + @Version: 1.4.0 @Author: Ready @Date: 2022-01-12 @Documentation: https://codeplayer.vip/p/j7sud @Email: CodePlayer360@gmail.com @Licence: https://www.apache.org/licenses/LICENSE-2.0.html */ -!function(a,b){var d,e,f,g,c=b&&b.console;return"undefined"==typeof jQuery||a!==jQuery?(c&&c.log("jQuery must be initialized before loading the Validator."),void 0):(d=function(b){if(!(this instanceof d))return new d(b);if(b||(b="v"),!a.fn[b]){var c=this;a.fn[b]=function(a,b){return c.execute(this,a,b)}}},e=d.cache={},f=d.log=function(){if(c){for(var a=0;a2&&(g=["?",g[0]])):g=["?",null],e[c.rule.format]=g),d.debug&&f("idcard pattern:",g),!a||"?"==g[0]&&15!=a.length&&18!=a.length||a.length!=g[0])return!1;if(h=18==a.length){for(i=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2],j=0,k=0;kq.getTime())return!1;if(r=q.getFullYear()-p.getFullYear(),q.setFullYear(q.getFullYear()-r),p.getTime()>q.getTime()&&r--,s=c.label,c.age=r,c.label="身份证年龄",this.validator.range.call(this,r,g[1],c)===!1)return!1;c.label=s}return p}},validator:{required:function(b,c,d){var f,g,e=d.$dom;if(e&&e.length&&(g=e[0],g.nodeName,null==g.checked||"checkbox"!=g.type&&"radio"!=g.type||(f=!0,d.actual=b=e.filter(":checked").length)),!b){if(c&&(!a.isFunction(c)||(c=c.call(this,b,d))))return this.sendError(f?"checked":"",b,"required",d),!1;d._stop=!0}},format:function(a,b,c){var e=d.util.parseFormat(b),f=this.formatter[c.child=e[0]];if(f)return a=c.formatResult=f.call(this,a,e[1],c),a===!1&&this.sendError(b,a,e[1],c),a;throw"Unsupported format validator:"+e[0]},text:function(b,c,d){var e=a.type(c);switch(e){case"string":if(c!=b)return this.sendError("==",b,c,d),!1;break;case"regexp":if(!c.test(b))return this.sendError("regexp",b,c,d),!1;break;case"function":if(c.call(this,b,d)===!1)return this.sendError("function",b,c,d),!1;break;default:throw"Unexpected text validator:"+c}},length:function(a,b,c){return this.validator.range.call(this,c.value.length,b,c)},range:function(a,b,c){var f,g,e=d.util.parseIntervalPattern(b);if(e.equals){if(a!=e.min)return this.sendError("==",a,e.min,c),!1}else{if(e.min&&(f=a>e.min||">="==e.left&&e.min==a,!f))return this.sendError(e.left,a,e.min,c),f;if(e.max&&(g=a=":"{label}必须大于或等于{expected}!",">":"{label}必须大于{expected}!","<=":"{label}必须小于或等于{expected}!","<":"{label}必须小于{expected}!","length.==":"{label}的长度必须等于{expected}!","length.>=":"{label}的长度必须大于或等于{expected}!","length.>":"{label}的长度必须大于{expected}!","length.<=":"{label}的长度必须小于或等于{expected}!","length.<":"{label}的长度必须小于{expected}!","format.number":"{label}必须是有效的整数!","format.number/money":"{label}必须是整数或最多保留两位的小数!","format.number/double":"{label}必须是有效的整数或小数!","format.date":'{label}必须为"{dateFormat}"格式的有效时间!',file:"{label}的格式不正确,必须为{expected}等格式!","default":"{label}的格式不正确!"},setMessage:function(a,b,c){c||(c=!(this instanceof d));var e=c?g.messages:this.messages;if(c||e!=g.messages||(this.messages=e={}),"object"==typeof a)for(i in a)e[i]=a[i];else e[a]=b},getMessage:function(b){var e,f,h,c=[b.message,b.rule.message,this.messages,g.messages];for(h in c){if(f=e=c[h],e===!1)return f;if(null!=e){if("object"==typeof e&&(f=e[b.validator+"."+b.trigger],null==f&&(!b.child||null==(f=e[b.validator+"."+b.child]))&&null==(f=e[b.validator])&&(f=e[b.trigger])),f===!1)return f;if(null!=f)break}}return f&&a.isFunction(f)&&(f=f.call(null,b)),f!==!1&&(f||(f=this.messages["default"]||g.messages["default"]),f&&(f=d.util.parseMessage(f,b,this))),f},labels:{},setLabel:function(a,b,c){c||(c=!(this instanceof d));var e=c?g.labels:this.labels;if(c||e!=g.labels||(this.labels=e={}),"object"==typeof a)for(i in a)e[i]=a[i];else e[a]=b},getLabel:function(a,b,c){if(!a&&b&&(a=b.prop("name")),null!=a){var d=c.label||this.labels[a]||g.labels[a];if(null==d&&b&&b.length&&(d=b.attr(this.labelAttr||"label")||this.findLabel&&this.findLabel(a,b,c)||b.first().prev("label").text()),d)return d}return""}},d.util={parseFormat:function(a){var b=a.indexOf("/"),c=[a,""];return b>0&&(c[0]=a.substring(0,b),c[1]=a.substr(b+1)),c},parseIntervalPattern:function(a){if(!e[a]){if(e.__interval||(e.__interval=/^([\[\(])(-?\d+(\.\d+)?)?(,)?(-?\d+(\.\d+)?)?([\]\)])$/),!e.__interval.test(a)||!RegExp.$2&&!RegExp.$4)throw"Unexpected interval pattern:"+a;var b={min:RegExp.$2,max:RegExp.$5};RegExp.$4==RegExp.$5?b.equals=!0:(b.left="["==RegExp.$1?">=":">",b.right="]"==RegExp.$7?"<=":"<"),e[a]=b}return e[a]},parseMessage:function(b,c,d){var f=c.$relatedDoms;return b.replace(e.__message||(e.__message=/\{([^}]+)\}/g),function(b,e){var h,i,g=e.charAt(0);return"#"==g||"$"==g?(i=e.substr(1),h=f&&f[i]?d.getLabel(null,f[i],c):d.getLabel(null,a("#"==g?"#"+i:"[name='"+i+"']"),c)):h=c[e],h||(h=""),h})},pushDomContext:function(a,b,c){var d=c.$relatedDoms||(c.$relatedDoms=[]);a||(a=b.prop("name")),d.push(b),a&&(d[a]=b)}},g.define({username:{pre:"trimAll,lower,flush",text:/^[a-z][a-z0-9_]{5,15}$/i,message:"{label}必须是英文字母、数字和下划线组成的6~16位字符,并且必须以字母开头!"},password:{length:"[6,16]"},age:{format:"number",range:"[18,100]"},"int":{format:"number"},"int+":{format:"number",range:"(0,)"},money:{format:"number/money"},"money+":{format:"number/money",range:"(0,)"},date:{format:"date"},datetime:{format:"date/datetime"},phoneCode:{format:"number",length:"[6]"},imageCode:{length:"[4]"},required:{},cellphone:!0,email:!0,idcard:{pre:"upper,flush",format:"idcard/18:[18,]"},image:"jpg|jpeg|gif|png|bmp"}),(b||(b="undefined"!=typeof window?window:this))&&(b.V=d),void 0)}(jQuery,window); \ No newline at end of file +!function(a,b){var d,e,g,h,c=b&&b.console;return"undefined"==typeof jQuery||a!==jQuery?(c&&c.warn("jQuery must be initialized before loading the Validator."),void 0):(d=function(b){if(!(this instanceof d))return new d(b);if(b||(b="v"),!a.fn[b]){var c=this;a.fn[b]=function(a,b){return c.execute(this,a,b)}}},e=d.cache={},g=d.log=function(){if(c){for(var a=0;a0&&(1===(1&c)&&!a.length||2===(2&c)&&!a.is(":visible")||4===(4&c)&&a.is("[readonly]"))?!1:void 0},labelAttr:"label",$:function(b,c){if(!b)return null;if(b instanceof a)return b;if("string"===a.type(b)){var d=b.charAt(0);"#"!=d&&("$"==d&&(b=b.substr(1)),b="[name='"+b+"']")}return a(b,c)},defaultRules:{required:!0},extendRule:function(b,c,d){for(var g,e=b?a.extend({},c):c,f=c.extend;f;){if(g=this.getRule(f),!g)throw"extended rule not found:"+f;for(i in g)i in e||(e[i]=g[i]);f=g.extend}if(d)for(i in d)i in e||(e[i]=d[i]);return e.extend&&delete e.extend,e},clipRule:function(a){return this.extendRule(!0,a,this.defaultRules)},afterHandler:function(b,c){var d=c.rule&&c.rule.after;return d&&a.isFunction(d)&&d.call(this,b,c),b},isRequired:function(a,b){var c=b.$dom.attr("optional");return"true"==c||"false"==c?"true"==c:void 0},pre:{trim:function(b){return a.trim(b)},trimAll:function(a){return e.__whiteSpace||(e.__whiteSpace=/\s/g),a?a.replace(e.__whiteSpace,""):a},lower:function(a){return a?a.toLowerCase():a},upper:function(a){return a?a.toUpperCase():a},flush:function(a,b){var c=b.$dom;return c&&1==c.length&&c.val(a),a}},formatter:{number:function(a,b,c){var h,i,j,k,l,m,f=e[c.rule.format];if(!f){switch(b||(b="+int"),h=b.charAt(0),i="",h){case"+":break;case"-":i="-";break;case"?":i="-?";break;default:h="+",b=h+b}switch(j=b.substr(1),k="+",l="",j){case"int":case"integer":break;case"money":l="(\\.\\d{1,2})?";break;case"float":case"double":l="(\\.\\d+)?";break;default:m=j.split(".",2),k=m[0],m[1]&&(l=m[1].startsWith("{0,")?"(\\.\\d"+m[1].replace(/^\{0,/,"{1,")+")?":"\\.\\d"+m[1])}e[c.rule.format]=f=new RegExp("^"+i+"\\d"+k+l+"$")}return d.debug&&g("number formatter ["+b+"] regexp:",f),f.test(a)?parseFloat(a):!1},date:function(a,b,c){var h,f,i,j,k,l,m;if(b?"datetime"==b?b="yyyy-MM-dd HH:mm:ss":"time"==b&&(b="HH:mm:ss"):b="yyyy-MM-dd",c.dateFormat=b,!a||a.length!=b.length)return!1;if(f=e[c.rule.format],!f){for(i=e.__date||(e.__date=new RegExp("yyyy|MM|dd|HH|mm|ss","g")),f={},i.lastIndex=0;h=i.exec(b);)f[h[0]]=[h.index,h.index+h[0].length];e[c.rule.format]=f}d.debug&&g("date pattern:",f),j={},k=a.split("");for(l in f){for(h=f[l],m=h[0];m2&&(f=["?",f[0]])):f=["?",null],e[c.rule.format]=f),d.debug&&g("idcard pattern:",f),!a||"?"==f[0]&&15!=a.length&&18!=a.length||a.length!=f[0])return!1;if(h=18==a.length){for(i=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2],j=0,k=0;kq.getTime())return!1;if(r=q.getFullYear()-p.getFullYear(),q.setFullYear(q.getFullYear()-r),p.getTime()>q.getTime()&&r--,s=c.label,c.age=r,c.label="身份证年龄",this.validator.range.call(this,r,f[1],c)===!1)return!1;c.label=s}return p}},validator:{required:function(b,c,d){var f,g,e=d.$dom;if(e&&e.length&&(g=e[0],g.nodeName,null==g.checked||"checkbox"!=g.type&&"radio"!=g.type||(f=!0,d.actual=b=e.filter(":checked").length)),!b){if(c&&(!a.isFunction(c)||(c=c.call(this,b,d))))return this.sendError(f?"checked":"",b,"required",d),!1;d._stop=!0}},format:function(a,b,c){var e=d.util.parseFormat(b),f=this.formatter[c.child=e[0]];if(f)return a=c.formatResult=f.call(this,a,e[1],c),a===!1&&this.sendError(b,a,e[1],c),a;throw"Unsupported format validator:"+e[0]},text:function(b,c,d){var e=a.type(c);switch(e){case"string":if(c!=b)return this.sendError("==",b,c,d),!1;break;case"regexp":if(!c.test(b))return this.sendError("regexp",b,c,d),!1;break;case"function":if(c.call(this,b,d)===!1)return this.sendError("function",b,c,d),!1;break;default:throw"Unexpected text validator:"+c}},length:function(a,b,c){return this.validator.range.call(this,c.value.length,b,c)},range:function(a,b,c){var f,g,e=d.util.parseIntervalPattern(b);if(e.equals){if(a!=e.min)return this.sendError("==",a,e.min,c),!1}else{if(e.min&&(f=a>e.min||">="==e.left&&e.min==a,!f))return this.sendError(e.left,a,e.min,c),f;if(e.max&&(g=a=":"{label}必须大于或等于{expected}!",">":"{label}必须大于{expected}!","<=":"{label}必须小于或等于{expected}!","<":"{label}必须小于{expected}!","length.==":"{label}的长度必须等于{expected}!","length.>=":"{label}的长度必须大于或等于{expected}!","length.>":"{label}的长度必须大于{expected}!","length.<=":"{label}的长度必须小于或等于{expected}!","length.<":"{label}的长度必须小于{expected}!","format.number":"{label}必须是有效的整数!","format.number/money":"{label}必须是整数或最多保留两位的小数!","format.number/double":"{label}必须是有效的整数或小数!","format.date":'{label}必须为"{dateFormat}"格式的有效时间!',file:"{label}的格式不正确,必须为{expected}等格式!","default":"{label}的格式不正确!"},setMessage:function(a,b,c){c||(c=!(this instanceof d));var e=c?h.messages:this.messages;if(c||e!=h.messages||(this.messages=e={}),"object"==typeof a)for(i in a)e[i]=a[i];else e[a]=b},getMessage:function(b){var e,f,g,c=[b.message,b.rule.message,this.messages,h.messages];for(g in c){if(f=e=c[g],e===!1)return f;if(null!=e){if("object"==typeof e&&(f=e[b.validator+"."+b.trigger],null==f&&(!b.child||null==(f=e[b.validator+"."+b.child]))&&null==(f=e[b.validator])&&(f=e[b.trigger])),f===!1)return f;if(null!=f)break}}return f&&a.isFunction(f)&&(f=f.call(null,b)),f!==!1&&(f||(f=this.messages["default"]||h.messages["default"]),f&&(f=d.util.parseMessage(f,b,this))),f},labels:{},setLabel:function(a,b,c){c||(c=!(this instanceof d));var e=c?h.labels:this.labels;if(c||e!=h.labels||(this.labels=e={}),"object"==typeof a)for(i in a)e[i]=a[i];else e[a]=b},getLabel:function(a,b,c){if(!a&&b&&(a=b.prop("name")),null!=a){var d=c.label||this.labels[a]||h.labels[a];if(null==d&&b&&b.length&&(d=b.attr(this.labelAttr||"label")||this.findLabel&&this.findLabel(a,b,c)||b.first().prev("label").text()),d)return d}return""}},d.util={parseFormat:function(a){var b=a.indexOf("/"),c=[a,""];return b>0&&(c[0]=a.substring(0,b),c[1]=a.substr(b+1)),c},parseIntervalPattern:function(a){if(!e[a]){if(e.__interval||(e.__interval=/^([\[\(])(-?\d+(\.\d+)?)?(,)?(-?\d+(\.\d+)?)?([\]\)])$/),!e.__interval.test(a)||!RegExp.$2&&!RegExp.$4)throw"Unexpected interval pattern:"+a;var b={min:RegExp.$2,max:RegExp.$5};RegExp.$4==RegExp.$5?b.equals=!0:(b.left="["==RegExp.$1?">=":">",b.right="]"==RegExp.$7?"<=":"<"),e[a]=b}return e[a]},parseMessage:function(b,c,d){var f=c.$relatedDoms;return b.replace(e.__message||(e.__message=/\{([^}]+)\}/g),function(b,e){var h,i,g=e.charAt(0);return"#"==g||"$"==g?(i=e.substr(1),h=f&&f[i]?d.getLabel(null,f[i],c):d.getLabel(null,a("#"==g?"#"+i:"[name='"+i+"']"),c)):h=c[e],h||(h=""),h})},pushDomContext:function(a,b,c){var d=c.$relatedDoms||(c.$relatedDoms=[]);a||(a=b.prop("name")),d.push(b),a&&(d[a]=b)}},h.define({username:{pre:"trimAll,lower,flush",text:/^[a-z][a-z0-9_]{5,15}$/i,message:"{label}必须是英文字母、数字和下划线组成的6~16位字符,并且必须以字母开头!"},password:{length:"[6,16]"},age:{format:"number",range:"[18,100]"},"int":{format:"number"},"int+":{format:"number",range:"(0,)"},money:{format:"number/money"},"money+":{format:"number/money",range:"(0,)"},date:{format:"date"},datetime:{format:"date/datetime"},phoneCode:{format:"number",length:"[6]"},imageCode:{length:"[4]"},required:{},cellphone:!0,email:!0,idcard:{pre:"upper,flush",format:"idcard/18:[18,]"},image:"jpg|jpeg|gif|png|bmp"}),(b||(b="undefined"!=typeof window?window:this))&&(b.V=d),void 0)}(jQuery,window); \ No newline at end of file