;(function(){

/** 验证框架 checkFun
* 使用方法:
* <input class="required" type="text" data-valid="isNonEmpty||isEmail" data-error="email不能为空||邮箱格式不正确" id="" />
* 1、需要验证的元素都加上【required】样式,当然这个required可以当参数传递,也可以自定义class类名
* 2、@data-valid 验证规则,验证多个规则中间用【||】隔开,更多验证规则,看rules和rule,后面遇到可继续增加
* 3、@data-error 规则对应的提示信息,一一对应
* 调用方式 checkFun({
formId:'verifyCheck', //<验证formId内class为required的元素
checkClass:'required', //<需要验证的DOM元素上默认class类名>
onBlur:function(el,state){console.log(state)}, //<被验证元素失去焦点的回调函数,回调函数中包括当前输入框失焦后是否通过验证的状态true表示通过,false表示未通过>
onFocus:null, //<被验证元素获得焦点的回调函数>
onChange: null, //<被验证元值改变的回调函数>
successTip: true, //<验证通过是否提示>
resultTips:null, //<显示提示的方法,参数obj[当前元素],isRight[是否正确提示],value[提示信息]>
clearTips:null //<清除提示的方法,参数obj[当前元素]>
}) 下面列举下实现的调用 //1.实现isNonEmpty,邮箱格式isEmail
<input class="required" type="text" data-valid="isNonEmpty||isEmail" data-error="email不能为空||邮箱格式不正确" id="" /> //2.验证最小长度minLength与最大长度maxLength
<input type="password" placeholder="密码" value="" class="required password" id="password" data-valid="isNonEmpty||minLength:3" data-error="密码不能为空||密码长度至少为3位"/> //3验证某个范围内between
<input type="password" placeholder="密码" value="" class="required password" id="password" data-valid="isNonEmpty||between:3-5" data-error="密码不能为空||密码长度在3-5位"/> //4.验证两次密码是否输入一致isRepeat
<div class="same">
<input type="password" placeholder="密码" value="" class="required password" id="password" data-valid="isNonEmpty||between:3-5" data-error="密码不能为空||密码长度在3-5位"/>
<label class="focus valid"></label>
</div>
<div class="same">
<input type="password" placeholder="重复密码" value="" class="required password2" id="password2" data-valid="isNonEmpty||isRepeat:password" data-error="密码不能为空||两次输入的密码不一致"/>
<label class="focus valid"></label>
</div> //5.验证密码强度level (使用方式跟minLength一样 level:3)
//6.验证是否为手机号码isPhone
//7.验证是否为纯中文isZh
//8.验证身份证号码isCard //下面的方式原生调用方式,当然可以使用jquery触发点击事件
document.getElementById('submitBtn').addEventListener('click',function(){ //点击提交按钮时验证
if(!checkFun.click()) return;
},false)
*/
/** 深度拷贝
* @param p 拷贝的对象
* @param c c默认传递的对象,也可以不传
* @result 返回拷贝后的对象
* */
var extendCopy = (function f(p,c){
var c = c || {};
for (var i in p) {
if(typeof p[i] === 'object'){
c[i] = (p[i] instanceof Array) ? [] : {};
f(p[i],c[i]);
}else{
  c[i] = p[i];
} 
}
return c;
}); var opts;
var checkFun = function(config){
opts = extendCopy(config || {},ValCheck.defaults);
return (new ValCheck())._init(opts);
} function ValCheck(){
//验证规则
var rule = {
phone:/^1\d{10}$/,
email:/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
card:/^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\d{4}(((((19|20)((\d{2}(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(\d{2}(0[13578]|1[02])31)|(\d{2}02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[48])0229)))|20000229)\d{3}(\d|X|x))|(((\d{2}(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(\d{2}(0[13578]|1[02])31)|(\d{2}02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[48])0229))\d{3}))$/, //身份证号
zh:/^[\u4e00-\u9fa5]+$///纯中文
}; this.rules = {
isNonEmpty: function(value, errorMsg) {//不能为空
errorMsg = errorMsg||" ";
if (!value.length) return errorMsg;
},
minLength: function(value, length, errorMsg) { //大于
errorMsg=errorMsg||" ";
if (value.length < length) return errorMsg;
},
maxLength: function(value, length, errorMsg) {//小于
errorMsg=errorMsg||" ";
if (value.length > length) return errorMsg;
},
between: function(value, range, errorMsg) {//大于小于
errorMsg=errorMsg||" ";
var min = parseInt(range.split('-')[0]);
var max = parseInt(range.split('-')[1]);
if (value.length < min || value.length > max) return errorMsg;
},
isRepeat:function(value, range, errorMsg){ //重复密码
errorMsg=errorMsg||" ";
var curPswDomVal = document.getElementById(range).value;
if(value!==curPswDomVal) return errorMsg;
},
isPhone: function(value, errorMsg) {
errorMsg=errorMsg||" ";
if (value!=null && value!='' && !rule.phone.test(value)) return errorMsg;
},
isEmail: function(value, errorMsg) {
errorMsg=errorMsg||" ";
if (value!=null && value!='' && !rule.email.test(value)) return errorMsg;
},
level:function(value,range,errorMsg){//密码复杂程度
errorMsg=errorMsg||" ";
var r=checkFun.pwdStrong(value);
if(range>4) range=3;
if(r<range) return errorMsg;
},
isZh: function(value, errorMsg) {
errorMsg=errorMsg||" ";
if (!rule.zh.test(value)) return errorMsg;
},
isCard: function(value, errorMsg) {
errorMsg=errorMsg||" ";
if (!rule.card.test(value)) return errorMsg;
}, };
} //默认配置
ValCheck.defaults = {
formId:'verifyCheck', //验证的ID
checkClass:'required', //需要验证的DOM元素上默认class类名
onBlur:null,//被验证元素失去焦点的回调函数
onFocus:null,//被验证元素获得焦点的回调函数
onChange: null,//被验证元素值改变的回调函数,回调参数为当前DOM元素
successTip: true,//验证通过是否有提示
resultTips:null,//验证提示的回调函数,传回参数obj[当前元素],isRight[验证是否通过],value[提示的值]
clearTips:null //清空提示的回调函数,传回参数obj[当前元素]
}; //验证初始化
ValCheck.prototype._init = function(config){
var self = this;
self.allinputs = document.getElementsByClassName(ValCheck.defaults.checkClass);
self.allinputs = Array.prototype.slice.call(self.allinputs,0);
for(var item =0, len = self.allinputs.length; item < len; item++){
(function(i){
self.allinputs[i].addEventListener('blur',function(e){
e.preventDefault();
var state = self.formValidator(self.allinputs[i]);
config.onBlur ? config.onBlur(self.allinputs[i],state) : '';
},false); self.allinputs[i].addEventListener('focus',function(e){
e.preventDefault();
if(config.onFocus){
config.onFocus(self.allinputs[i]);
}else{
var matched = []; //存放兄弟节点
var n = (self.allinputs[i].parentNode || {}).firstChild;
for(; n; n = n.nextSibling){
if(n.nodeType === 1 && n !== self.allinputs[i]){
n.innerHTML = '';
}
}
}
},false); self.allinputs[i].addEventListener('change',function(e){
e.preventDefault();
config.onChange ? config.onChange(self.allinputs[i]) : '';
},false);
})(item);
}
} /** 验证规则
* @param el 当前被验证的DOM元素
* */
ValCheck.prototype.formValidator = function(el){
var self = this;
var validataString = el.getAttribute('data-valid');
if(validataString === undefined){
return false;
}
var validArray = validataString.split('||'); var errorString = el.getAttribute('data-error');
if(errorString === undefined){
return false;
}
var errorArray = errorString.split('||');
var ruleArray = [];
for(var i =0, j = validArray.length; i < j; i++){
ruleArray.push({
funTitle:validArray[i],
errorMsg:errorArray[i]
});
}
return self.validataResult(el,ruleArray);
} /** 验证结果
* @param el 验证的DOM元素
* @param ruleArray 需要逐一验证的数组规则
* */
ValCheck.prototype.validataResult = function(el,ruleArray){
var self = this;
for(var i = 0, rule; rule = ruleArray[i++];){
var applyArgs = rule.funTitle.split(':');
var errorMsg = rule.errorMsg;
var ruleFun = applyArgs.shift();//得到匹配删除的函数名
applyArgs.unshift(el.value);// 数组第一位插入value值
applyArgs.push(errorMsg); //最后插入出错信息
applyArgs.push(el);
var result = self.rules[ruleFun].apply(el, applyArgs);
if(result){
opts.resultTips ? opts.resultTips(el, false, result) : self.resultTips(el, false, result);
return false;
} }
opts.successTip ? (
opts.resultTips ? opts.resultTips(el,true) : self.resultTips(el, true)
) : self.clearTip(el);
return true;
} /** 验证信息的显示
* @param el 当前被验证的DOM元素
* @param isRight 验证是否通过, false=未通过 true=验证通过
* @param value 提示信息
* */
ValCheck.prototype.resultTips = function(el, isRight, value){
var cls = 'el_error';
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)',"g");
value = value || '';
if(!isRight){
if(!el.className.match(reg)){
el.className += ' ' + cls;
}
}else{
if(el.className.match(reg)){
el.className = el.className.replace(reg,'');
}
}
var matched = []; //存放兄弟节点
var n = (el.parentNode || {}).firstChild;
for(; n; n = n.nextSibling){
if(n.nodeType === 1 && n !== el){
n.innerHTML = value; //赋值提示信息
}
}
}; /** 清空提示
* @param el 清空提示的DOM元素
*/
ValCheck.prototype.clearTip = function(el){
var cls = 'el_error';
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
el.className.replace(reg,'');
}; /****************对外开放方法******************/ /** 外部可调用click方法,比如点击事件时候调用checkFun.click(),验证成功返回true
* @param formId 验证DOM为formId区域下的表单
* @result {boolen} true or false
* */
checkFun.click = function(formId){
formId = formId || opts.formId;
var resultObj = []; //存放需要验证的DOM对象
var rangeobj = document.getElementById(formId);
if(rangeobj.getElementsByClassName){
rangeobj = [].slice.apply(rangeobj.getElementsByClassName(ValCheck.defaults.checkClass));
}else{
var tags = rangeobj.getElementsByTagName("*");
//遍历每个DOM元素
for(var i = 0, len = tags.length; i < len; i++){
// 获取到当前遍历元素所使用的所有类名
var classNames = tags[i].className.split(" ");
for(var j = 0, l=classNames.length; j < l; j++){
if(classNames[j] == ValCheck.defaults.checkClass){
rangeobj.push(tags[i]);
break;
}
}
}
}
var check = new ValCheck();
var checkResultNumber = 0; //检测结果,检查通过的数目
var resultState = true;
//开始验证所有DOM元素
for(var domNumber = 0, domlen = rangeobj.length; domNumber < domlen; domNumber++){
everyResultState = check.formValidator(rangeobj[domNumber]);
if(everyResultState){
checkResultNumber ++;
}
}
if(checkResultNumber !== domlen ){
resultState = false;
}
return resultState;
}; /** 判断密码强度
* @param val 当前DOM元素的value值
* @return {number} 返回数字等级
* */
checkFun.pwdStrong = function(val){
var lv=0;
if(val.match(/[a-z]/g)){lv++;}
if(val.match(/[A-Z]/g)){lv++;}
if(val.match(/[0-9]/g)){lv++;}
if(val.match(/(.[^a-z0-9A-Z])/g)){lv++;}
if(lv > 4){lv=4;}
if(lv===0) return false;
return lv;
} window.checkFun = checkFun;
})();

css代码:

.same{margin-bottom: 30px;position:relative;}
.same input{border:1px solid #ccc;width:200px;height:30px;line-height: 30px;padding-left:10px;}
.valid{color:red;position:absolute;}
.submitBtn{cursor: pointer;}

html代码:

<div id="verifyCheck">
<div class="same">
<input type="text" placeholder="邮箱" value="" class="required email" id="email" data-valid="isNonEmpty||isEmail" data-error="email不能为空||邮箱格式不正确"/>
<label class="focus valid"></label>
</div>
<div class="same">
<input type="password" placeholder="密码" value="" class="required password" id="password" data-valid="isNonEmpty||between:3-5" data-error="密码不能为空||密码长度在3-5位"/>
<label class="focus valid"></label>
</div>
<div class="same">
<input type="password" placeholder="重复密码" value="" class="required password2" id="password2" data-valid="isNonEmpty||isRepeat:password" data-error="密码不能为空||两次输入的密码不一致"/>
<label class="focus valid"></label>
</div>
<button class="submitBtn" id="submitBtn">提交</button>
</div>

JS调用:

checkFun({
onBlur:function(el,state){
console.log($(el));
}
}); document.getElementById('submitBtn').addEventListener('click',function(){
checkFun.click();
},false)

[待优化笔记]原生JS实现验证框架 checkFun的更多相关文章

  1. [笔记]原生JS实现的DOM操作笔记

    原生JS实现的DOM一系列操作参考: 原生JavaScript封装DOM库 siblings: 原生JS-查找相邻的元素-siblings方法的实现 addClass,removeClass,hasC ...

  2. ajax学习笔记(原生js的ajax)

    ajax是一个与服务器端语言无关的技术,可以使用在任何语言环境下的web项目(如JSP,PHP,ASP等). ajax优点: 1) 页面无刷新的动态数据交互 2) 局部刷新页面 3) 界面的美观 4) ...

  3. 原生JS 表单提交验证器

    转载:http://www.cnblogs.com/sicd/p/4613628.html 一.前言 最近在开发一个新项目,需要做登陆等一系列的表单提交页面.在经过“缜密”的讨论后,我们决定 不用外部 ...

  4. 框架操作DOM和原生js操作DOM比较

    问题引出 对于Angular和React操作DOM的速度,和原生js操作DOM的速度进行了一个比较: 一个同学做的demo 代码如下: <!DOCTYPE html> <html n ...

  5. 使用原生JS实现一个风箱式的demo,并封装了一个运动框架

    声明,该DEMO依托于某个培训机构中,非常感谢这个培训结构.话不多说,现在开始改demo的制作. 首先,在前端的学习过程中,轮播图是我们一定要学习的,所以为了更加高效的实现各种轮播图,封装了一个运动的 ...

  6. {{angular.js 使用技巧}} - 基于验证框架的扩展(w5cValidator)

    开场白: angular.js 是谷歌出的前端js MV*框架,我也是今年做 worktile 的时候才开始接触的,起初技术选型的时候还准备使用 backbone(毕竟很多大公司在使用他,而且也是比较 ...

  7. 表单验证--通过原生js模仿ajax的异步交互

    今天给大家带来个福利,我也是刚刚学习的很实用的一个东西,通过原生js模仿ajax的异步交互. 我的博客只是给那些新手看的大神勿喷,写的不好可留言,请指出. 因为当初自己学的时候一个问题不会找人问,知道 ...

  8. 页面性能优化-原生JS实现图片懒加载

    在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况.我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片.所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再 ...

  9. 原生js的开发笔记

    1.基本的dom操作 var a=document.getElementById('ma1').innerHTML;/获取html代码 alert(document.getElementById('m ...

随机推荐

  1. CI-CD平台搭建过程整理

    Coding ---> gitlab  --->jenkins ---> maven(nexus) ---> 编译构建成image ---> Harbor ---> ...

  2. Python的GUI编程(TK)

    TK在大多数 Unix平台.Windows平台和Macintosh系统都是预装好的,TKinter 模块是 Tk GUI 套件的标准Python接口.可实现Python的GUI编程. Tkinter模 ...

  3. Xamarin.Android 制作搜索框

    前段时间仿QQ做了一个搜索框样式,个人认为还不错,留在这里给大家做个参考,希望能帮助到有需要的人. 首先上截图(图1:项目中的样式,图2:demo样式): 不多说直接上代码: Main.axml &l ...

  4. SQL中EXPLAIN命令详解

    explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如: expla ...

  5. 解决添加codova plugin 编译出现问题:Execution failed for task ':processDebugManifest'.

    问题背景: ionic3项目上,添加cordova-plugin-cszbar,编译运行在android平台上 ,结果编译不成功.出现以下问题. Element uses-feature#androi ...

  6. Linux编程 11(shell全局环境变量与局变环境变量)

    一.概述 在linux中,很多程序和脚本都通过环境变量来获取系统信息,存储临时数据,配置信息.环境变量是指用来存储有关shell会话和工作环境信息,允许你在内存中存储数据,以便程序或shell中运行的 ...

  7. Java生成sitemap网站地图

    访问我的博客 sitemap 是什么?对应没有接触过网站 SEO 的同学可能不知道,这里引用一下百度站长的一段解释. Sitemap(即站点地图)就是您网站上各网页的列表.创建并提交Sitemap有助 ...

  8. python 时间模块time,datetime

    模块(module)是 Python 中非常重要的东西,你可以把它理解为 Python 的扩展工具.换言之,Python 默认情况下提供了一些可用的东西,但是这些默认情况下提供的还远远不能满足编程实践 ...

  9. 使用3D Slicer对图像进行配准

    在进行深度学习之前,我们需要图像进行一些预处理操作,其中配准是很重要的一环,以下将介绍使用软件3D Slicer来进行图像配准 3D Slicer是(1)一个软件平台,用以图像分析(包括配准和实时编辑 ...

  10. MySQL中间件之ProxySQL(5):线程、线程池、连接池

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.ProxySQL的线程 ProxySQL由多个模块组成,是一个多线 ...