Mootools之FormCheck的扩展
本文章对mootools formcheck插件进行改进,//注意,这里不对FormChekc源码做详细分析,仅仅简单介绍下怎么扩展的,且后面会付上扩展后的js文件和使用手册。
Mootools FormCheck 下载地址:http://mootools.floor.ch/en/download/
去年进公司的时候接触到了一种新的JS前端框架技术Mootools,它的语法与JQuery比较相似,个人觉得它与JQuery最大的区别在于Mootools提供面向对象的编程方式。作为应用系统基本上大部分页面都有表单,而对表单的较验则是用的FormCheck插件,我在用FormCheck插件的时候发现以下不爽的问题:
1、验证表达式的配置太难看了。validate['required'] 我觉得里面这个单引号多余.
2、在有的情况下想自定义一个Function来处理数据的验证,这个FormCheck冒似没有提供。因为FormCheck是使用正则表达式来验证的数据的,它无非就是调用正则的test方法来验证,也许你会想到用下面这种方式来变通:
//...省略了其它配置 regexp:{ customValidate:{ test:function(v){ //do something... return true/false; } } } //...省略了其它配置 //这样配置验证表达式:class="validate['customValidate']"
这样做确实可以,我一开始就是这样做的,但是后来发现有些需求需要根据输入的值做一些更人性化的提示,完蛋了,它彻底的不支持,没办法只好看源代码改咯....
第一步:去掉那讨厌的单引号。
找到register : function(el, position)方法//这个方法是给当前的输入框注册验证器的
在这个方法的下面添加如下方法代码:
/** * 从这类字符串( "required",c{validatePassword} )中分割出表达式列表 * @param exps * @param splitChar * @returns {Array} * @private */ _getExpressions:function(exps,splitChar){ splitChar=splitChar||','; var expressions=new Array(),sb=new Array(),methodCount=0,blockCount=0,arrayCount=0,c; for(var i=0;i<exps.length;i++){ c=exps.charAt(i); if(c=='('){ methodCount++; }else if(c==')'){ methodCount--; }else if(c=='{'){ blockCount++; }else if(c=='}'){ blockCount--; }else if(c=='['){ arrayCount++; }else if(c==']'){ arrayCount--; }else if(c==splitChar&&methodCount==0&&blockCount==0&&arrayCount==0){ expressions.push(sb.join('')); sb.splice(0,sb.length); continue; } sb.push(c); } if(sb.length!=0){ expressions.push(sb.join('')); } return expressions; },
然后修改register : function(el, position)方法内的代码如下:
register : function(el, position) { el.validation = []; el.getProperty("class").split(' ').each(function(classX) { if (classX.match(/^validate(\[.+\])$/)) { var valid = true; /******************* Modify BEGIN*************************/ //注掉下面这行代码 //var validators = eval(classX.match(/^validate(\[.+\])$/)[1]);//正是因为这句话导致validate中的表达式一定得用引号括住 var validators=[]; var vStr = classX.match(/^validate\[(.+)\]$/)[1]; this._getExpressions(vStr).each(function(item){ if(item.charAt(0)=="'" || item.charAt(0)=='"'){//忽略引号 做兼容 validators.push(item.substring(1,item.length-1)); }else{ validators.push(item); } }); delete vStr; /*******************Modify END*************************/ //...这里省略了其余的代码
第二步:增加自定义验证方式
在类的options下面加入如下属性
customValidation:{ _compare:function(v1,v2,exp){ if(v1&&v1!=''&&v2&&v2!=''){ var numRgx=/^\d+$/; if(numRgx.test(v1)&&numRgx.test(v2)){ if(eval([v1,exp,v2].join('')))return true; }else{ if(eval(["'",v1,"'",exp,"'",v2,"'"].join('')))return true; } return false; } return true; }, gt:{ msg:"当前值必需大于 \"%{minValue}\".", fn:function(v,minValue,el){ if(!this.options.customValidation._compare(v,minValue,">=")){ return {minValue:minValue}; } return true; } }, ge:{ msg:"当前值必需大于等于 \"%{minValue}\".", fn:function(v,minValue,el){ if(!this.options.customValidation._compare(v,minValue,">=")){ return {minValue:minValue}; } return true; } }, eq:{ msg:"当前值必需是 \"%{value}\".", fn:function(v,newValue,el){ if(!this.options.customValidation._compare(v,newValue,"==")){ return {value:newValue}; } return true; } }, nq:{ msg:"当前值不能等于 \"%{value}\".", fn:function(v,value,el){ if(!this.options.customValidation._compare(v,value,"!=")){ return {value:value}; } return true; } }, lt:{ msg:"当前值必需小于 \"%{value}\".", fn:function(v,newValue,el){ if(!this.options.customValidation._compare(v,newValue,"<")){ return {value:newValue}; } return true; } }, le:{ msg:"当前值必需小于等于 \"%{value}\".", fn:function(v,newValue,el){ if(!this.options.customValidation._compare(v,newValue,"<=")){ return {value:newValue}; } return true; } }, range:{ msg:"当前值需在\"%{begin}\"至\"%{end}\"之间.", fn:function(v,begin,end){ if(v!=''){ if(v>=begin&&v<=end){ return true; }else{ return {begin:begin,end:end}; } } return true; } }, fileSuffix:{ msg:"文件类型必需是 %{suffixes} 文件.", fn:function(v,suffix){ suffix=$splat(suffix); var suf=v.lastIndexOf('.'); if(suf!=-1){ suf=v.substr(suf+1).toLowerCase(); if(suffix.some(function(sf){ return suf==sf.toLowerCase(); })){ return true; } } return {suffixes:suffix.join("、")}; } } }
找到validate : function(el)方法//此方法在el需要被验证的时候触发
在此validate 方法下面加入以下方法:
/** * 这个Function负责执行验证函数里面的参数 */ _EXPRESSION_EXECUTE_FN:new Function("return eval(arguments[0])"), /** * 从表达式中获取结果 * @param exp * @param scope * @returns {*} * @private */ _getResultByExp:function(exp,scope){ return this._EXPRESSION_EXECUTE_FN.call(scope||window,exp); },
找到validate方法下的el.validation.each(function(rule) {代码段
在第一个else的最后面加入如下代码:
/************************** Modify Begin ****************************/ var customExpRegx=/^c{(.+)}/i; var cExp=rule.match(customExpRegx),me=this; if(cExp){ var exp=cExp[1]; var exps=me._getExpressions(exp); exps.each(function(e){ var v,vh,vr,args=[el.get('value')]; if(e.indexOf('(')!=-1){//处理传参的情况 exr=e.match(/^(\S+?)\((.+)\)/); v=exr[1]; me._getExpressions(exr[2]).each(function(arg){ args.push( me._getResultByExp(arg,el) ); },me); }else{ v=e; } args.push(el); vh=me.options.customValidation[v];//从配置中取得验证器方法 if(vh){ if($type(vh)=='function'){ vr=vh.apply(me,args); }else{ vr=vh.fn.apply(me,args); } if(vr===true){ el.isOk=el.isOk&&true; }else{ el.isOk=false; if($type(vr)=='object'){//处理提示消息绑定值的情况 el.errors.push(vh.msg.replace(/\%{(\w+)}/g,function(){ var vm=vr[arguments[1]]; if($type(vm)=='array'){ return vm.join(','); }else{ return vm; } })); }else if($type(vr)=='string'){//返回字符串直接将其作为提示信息 el.errors.push(vr); }else{ el.errors.push(vh.msg||'当前值不合法'); } } } },this); } /************************** Modify End ****************************/
完事...
示例:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>test</title> <script type="text/javascript" src="mootools-1.2.5-core-yc.js"></script> <script type="text/javascript" src="mootools-1.2.5.1-more.js"></script> <link media="screen" rel="stylesheet" href="theme/blue/formcheck.css" type="text/css"> <script type="text/javascript" src="lang/en.js"></script> <script type="text/javascript" src="formcheck.js"></script> <script type="text/javascript"> window.addEvent("domready",function(){ new FormCheck('form', { submitReload:1, display : { showErrors:1, indicateErrors : 1, fadeDuration : 1000 }, customValidation:{ validatePassword:function(v){ if(v==null||v=='')return true; if(v.length<6){ return "密码长度要大于6位哦,亲"; } var pl=0; if(/\d/.test(v)){ pl++; } if(/[a-zA-Z]/.test(v)){ pl++; } if(/[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/.test(v)){ pl++; } if(pl<=1){ return "密码再设复杂点吧,亲"; } return true; } } }); }); </script> </head> <body> <div style="position: absolute; left:30%;top:30%"> <form id="form" action="http://www.baidu.com" method="POST"> <lable> email:<input type="text" name="email" class="validate[required,email]"/></br> password:<input type="text" class='validate["required",c{validatePassword}]' name="password" id="password" /><br/> confirmation:<input type="text" class="validate[c{eq($('password').get('value'))}]" name="confirm" /> <br/> <input type="submit" value="submit"/> </lable> </form> </div> </body> </html>
效果如下:
详细的使用示例请参看rar附件中的使用文档....
将FormCheck1.6.rar中的formcheck.js替换原来1.6版本下的forcheck.js(不用担心,完全兼容原来的)