前言
网上有好多form表单校验插件,包括jquery的表单检验插件,这些中好多插件功能很齐全强大,提示方式很酷,很美观好看。本想拿来用,但是发现几个问题:
1、使用不方便。校验规则繁多,调用校验函数难记忆。
2、提示方式固定。一般插件给出固定的几种提示方式,但是实际中,不同系统都有自己的页面风格样式,有自己的提示方式,插件自带的一般用不上。
因此,我最终没有采用这些插件,以免用后出现难以修改或实现的情况。
如果一种校验插件能避免以上两个问题最好了,方便使用,提示方式自定义 ,所以自己做了一个简单的校验器,希望能慢慢完善。
正文
先来一个DEMO
1、html:
<ul id="form"> <li> <span class="name-col">姓名:</span> <span class="value-col"> <input type="text" name="username" minLength="5" maxLength="20" required afterFunc="showTip"></input> </span> </li> <li> <span class="name-col">年龄:</span> <span class="value-col"> <input type="text" vtype="number" min="18" max="40" step="1" name="age" onEvent="keyup" beforeFunc="modify" afterFunc="showTip"></input> </span> </li> <li> <span class="name-col">电话:</span> <span class="value-col"> <input type="text" name="phone" pattern="^(0[0-9]{2,3}-)?[2-9][0-9]{6,7}(-[0-9]{1,4})?$" afterFunc="showTip"></input> </span> </li> <li> <span class="name-col">性别:</span> <span class="value-col"> <input type="radio" name="sex" checked />男 <input type="radio" name="sex" />女 </span> </li> <li> <span class="name-col">爱好:</span> <span class="value-col"> <input type="checkbox" name="love" value="1" />爬山 <input type="checkbox" name="love" value="2" />游泳 <input type="checkbox" name="love" value="3" />音乐 <input type="checkbox" name="love" value="4" />读书 </span> </li> <li> <span class="name-col">自我描述:</span> <span class="value-col"> <textarea name="description" minLength="10" maxLength="20" afterFunc="showTip"></textarea> </span> </li> <li> <button onclick="validate()" >validate</button> <button onclick="disabd()">disabled</button> </li> </ul>
2、js调用方法:
$(function(){ $("#form").validateInit(); }); var modify = function(source){ source.val(source.val().replace(/[^0-9]+/g,'')); }; var validate = function(){ var res = $("#form").validate(); alert(res.valid); }; var showTip = function(e){ var res = e.getVresult(); if(res && res.valid == false){ e.next().remove(); e.after('<span>'+res.errorType+'</span>'); }else{ e.next().remove(); } }; var disabd = function(){ $("#form").disableValidate(); }
说明:
1、 校验规则添加到表单元素的属性上,属性使用类似html5的表单校验。
<input type="text" name="username" minLength="5" maxLength="20" required afterFunc="showTip"></input>
<input type="text" vtype="number" min="18" max="40" step="1" name="age" onEvent="keyup" beforeFunc="modify" afterFunc="showTip"></input>
以上input的例子:vtype="number"说明为number类型,min=18,max=40,step=1,这些规则可代码就可以知道是什么意思。
2、js校验调用:
页面初始化时:$("#form").validateInit();
校验时调用:$("#form").validate();
这里$("#form")可以是单个表单元素(input)可以是容器(form)。
使用很简单方便吧。
具体说明:
1、表单元素上的校验属性:
pattern:自定义正则表达式,这个很好用,以至于不想写下面的vtype其他种类了。
vtype:校验类型 有number,email,tel。还有待添加。
min: vtype为number时的最小值
max:vtype为number时的最大值
step: vtype为number时,增加步长。
minLength:字符串最小长度
maxLength:字符串最大长度
required: 必填项
beforeFunc:校验前调用函数,传递参数为对象本身。
afterFunc:校验完成后调用函数,传递参数为对象本身。
onEvent: 将校验函数绑定到的事件。
2、插件方法:
validateInit 校验初始化--该方法会根据表单元素的属性,进行相应的校验函数绑定到blur事件上,
disableValidate 禁用校验--去掉校验事件,去掉校验结果
validate 校验--立即校验,结果保存saveVresult(),可以用getVresult().valid查看是否通过校验。
isFormElement 是否为表单元素--
vattr 校验属性的获取和设置
getVresult 获取校验结果
saveVresult 保存校验结果
这七个方法都在表单元素上。如$('div[name='form']').validate()则是校验div里面的所有表单元素。$('input[name='username']')则校验本身。
校验器代码:
/** * form 表单校验器 * 使用规则仿照html5表单验证情况。 * @author jokinliu@163.com * @date 2014-08-05 * @version V2.0 */ (function($){ /** * 表单校验添加jquery插件方法,方法简介如下: * 1、validateInit 校验初始化 * 2、disableValidate 禁用校验 * 3、validate 校验 * 4、isFormElement 是否为表单元素 * 5、vattr 校验属性的获取和设置 * 6、getVresult 获取校验结果 * 7、saveVresult 保存校验结果 */ $.fn.extend({ /********************************************************************************* * 初始化校验 绑定校验事件 * validityObj: 校验选项,可选,如果设置了该选项,往后的校验就以该选项的值为主 * validityObj = { * vtype: 校验类型 * pattern: 校验正则表达式 * max: vtype为number是的最大值 * min: vtype为number是的最小值 * maxLength:非number是字符串的最大长度 * minLength:非number是字符串的最小长度 * step:vtype为number是的step * onEvent: * beforeFunc: func1, //校验前的执行方法,该方法接受对象本身参数$(this)。 * afterFunc: func2, //校验后的执行方法,该方法接受对象本身参数$(this)。 * } *********************************************************************************/ validateInit: function(validityObj){ if($(this).isFormElement()){ $(this).data('vresult',''); event.onEvent($(this), validityObj); } else{ $(this).find(constants.formElements.join(',')).each(function(){ $(this).data('vresult',''); event.onEvent($(this), validityObj); }); } }, /****************************************** * disabled校验功能 * 取消本对象上的校验相关 * 1、取消绑定校验事件。 * 2、取消校验结果,设置不可用标识$(this).data('vresult','disabled'); ******************************************/ disableValidate: function(){ if($(this).isFormElement()){ event.offEvent($(this)); $(this).data('vresult','disabled'); } else{ $(this).find(constants.formElements.join(',')).each(function(){ event.offEvent($(this)); $(this).data('vresult','disabled'); }); } return $(this); }, /********************************************************************************* * 校验方法,开始校验 * validityObj: 校验选项,可选,如果设置了该选项,往后的校验就以该选项的值为主 * validityObj = { * vtype: 校验类型 * pattern: 校验正则表达式 * max: vtype为number是的最大值 * min: vtype为number是的最小值 * maxLength:非number是字符串的最大长度 * minLength:非number是字符串的最小长度 * step:vtype为number是的step * onEvent: * beforeFunc: func1, //校验前的执行方法,该方法接受对象本身参数$(this)。 * afterFunc: func2, //校验后的执行方法,该方法接受对象本身参数$(this)。 * } *********************************************************************************/ validate: function(validityObj){ if($(this).isFormElement()){ if(validityObj){ for(var attr in validityObj){ validityObj[attr] && source.vattr(attr, validityObj[attr]); } } return event.validate('', $(this)); } else{ var result = true; $(this).find(constants.formElements.join(',')).each(function(){ var res = event.validate('', $(this)); if(res && res.valid == false) result = false; }); return {valid:result}; } }, /********************************************* * 是否为表单元素 * 判断当前对象的tagName是否为INPUT,TEXTEREA等。 *********************************************/ isFormElement: function(){ var tag = $(this)[0].tagName; for(var i=0; i<constants.formElements.length; i++){ if(tag == constants.formElements[i]){ return true; } } return false; }, /******************************************************************** * 校验属性的获取和设置 * 将属性取出放置到data('validator')中 *******************************************************************/ vattr: function(attr, val){ !$(this).data('validator') && $(this).data('validator',{}); var data = $(this).data('validator'); if(val && (val+'').trim() != ''){ data[attr] = val; return $(this); } if(!data[attr]){ var attrVal = $(this).attr(attr); if(attrVal && attrVal.trim() != ''){ if(attr == 'beforeFunc' || attr == 'afterFunc'){ data[attr] = eval("("+attrVal.trim()+")"); }else{ data[attr] = attrVal.trim(); } } } return data[attr]; }, /***************************************************************** * 获取校验结果,从data('vresult')中 * 校验完成时,结果存储在当前对象的 $(this).data('vresult')中; * 结果对象为htmL5校验结果对象,并添加几个其他 * result = { * badInput: false, * customError: false, * errorType: "typeMismatch", //错误类型,记录值为true的属性到这里。 * patternMismatch: false, * rangeOverflow: false, * rangeUnderflow: false, * stepMismatch: false, * tooLong: false, * typeMismatch: true, * valid: false, * valueMissing: false * } *****************************************************************/ getVresult: function(){ return $(this).data('vresult'); }, /***************************************************************** * 保存校验结果,到data('vresult')中 * 校验完成时,结果存储在当前对象的 $(this).data('vresult')中; * 结果对象为htmL5校验结果对象,并添加几个其他 * result = { * badInput: false, * customError: false, * errorType: "typeMismatch", //错误类型,记录值为true的属性到这里。 * patternMismatch: false, * rangeOverflow: false, * rangeUnderflow: false, * stepMismatch: false, * tooLong: false, * typeMismatch: true, * valid: false, * valueMissing: false * } *****************************************************************/ saveVresult: function(result){ var result = $.extend({},$(this)[0].validity, result); for(var attr in result){ if(attr != "valid" && result[attr] == true){ result.valid = false; result.errorType = attr; break; } } $(this).data('vresult', result); return $(this); } }); /****************************************** * jquery对象方法调用的事件函数 * 主要函数有: * 1、validate 校验 * 2、onEvent 添加事件 * 3、offEvent 取消事件 **************************************/ var event = { validate: function(event, source){ source = !source ? event.data.source : source; if(source.data('vresult')=='disabled') return; //disabed used .disabedvalidate() //do beforeFunc source.vattr('beforeFunc') instanceof Function && source.vattr('beforeFunc')(source); //do validate source.saveVresult(validator.validate(source)); //do afterFunc source.vattr('afterFunc') instanceof Function && source.vattr('afterFunc')(source); return source.getVresult(); }, onEvent: function(source, validityObj){ if(validityObj){ for(var attr in validityObj) validityObj[attr] && source.vattr(attr, validityObj[attr]); } source.vattr('onEvent') && source.on(source.vattr('onEvent'), {source:source}, this.validate); source.on('blur', {source:source}, this.validate); }, offEvent: function(source){ source.off(event, this.validate); source.off('blur', this.validate); } }; //常量 var constants = { formElements: ['INPUT','TEXTAREA'] }; var validator = { empty: function(value){ return !value || value.trim() == ''; }, number: function(value){ if(this.empty(value)) return true; return /^-?[1-9]d*(.d+)?$/.test(value); }, min: function(value, min){ if(this.empty(value)) return true; return value*1>=min; }, max: function(value, max){ if(this.empty(value)) return true; return value*1<=max; }, step: function(value, step, min){ if(this.empty(value)) return true; min = this.number(min)?min*1:0; return (value*1-min)/step*1%1===0; }, tel: function(value){ if(this.empty(value)) return true; var reg = /^(0[0-9]{2,3}-)?[2-9][0-9]{6,7}(-[0-9]{1,4})?$/; return reg.test(value.trim()); }, mobile: function(value){ if(this.empty(value)) return true; var reg = /^1[3-8]d{9}$/; return reg.test(value.trim()); }, email: function(value){ if(this.empty(value)) return true; var reg = /^.{2,}@.{2,}$/; return reg.test(value.trim()); }, pattern: function(value, regExp){ if(this.empty(value)) return true; return RegExp(regExp).test(value); }, validate: function(source){ if(!source.vattr('vtype') && !source.vattr('pattern') && !source.vattr('minLength') && !source.vattr('maxLength')) return; var vtype = source.vattr('vtype')?source.vattr('vtype'):source.vattr('type'); var val = source.val().trim(); source.val(val); //required validate if(source.vattr("required") == 'required' && validator.empty(val)){ return {valueMissing:true}; } //vtype validate if(vtype == 'number'){ if(!validator.number(val)) return {typeMismatch:true}; if(source.vattr('min') && !isNaN(source.vattr('min')*1)){ if(!validator.min(val, source.vattr('min')*1)) return {rangeUnderflow:true}; } if(source.vattr('max') && !isNaN(source.vattr('max')*1)){ if(!validator.max(val, source.vattr('max')*1)) return {rangeOverflow:true}; } if(source.vattr('step') && !isNaN(source.vattr('step')*1)){ if(!validator.step(val,source.vattr('step'),source.vattr('min'))) return {stepMismatch:true}; } }else{ if(vtype == 'email'){ if(!validator.email(val)) return {typeMismatch:true}; }else if(vtype == 'tel'){ if(!validator.tel(val)) return {typeMismatch:true}; }else if(vtype == 'url'){ if(!validator.url(val)) return {typeMismatch:true}; } if(!validator.empty(val)){ if(source.vattr('minLength') && !isNaN(source.vattr('minLength')*1)){ if(val.length < source.vattr('minLength')*1) return {tooShort:true}; } if(source.vattr('maxLength') && !isNaN(source.vattr('maxLength')*1)){ if(val.length > source.vattr('maxLength')*1) return {tooLong:true}; } } } //pattern validate if(source.vattr('pattern') && source.vattr('pattern').trim() != ''){ if(!validator.pattern(val, source.vattr('pattern'))) return {patternMismatch:true}; } } }; /** * String trim */ String.prototype.trim = function(){ return this.replace(/(^s*)|(s*$)/g, ''); }; String.prototype.leftTrim = function(){ return this.replace(/^s*/g, ''); }; String.prototype.rightTrim = function(){ return this.replace(/s*$/g, ''); }; })(jQuery);