[待优化笔记]原生JS实现验证框架 checkFun
;(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的更多相关文章
- [笔记]原生JS实现的DOM操作笔记
原生JS实现的DOM一系列操作参考: 原生JavaScript封装DOM库 siblings: 原生JS-查找相邻的元素-siblings方法的实现 addClass,removeClass,hasC ...
- ajax学习笔记(原生js的ajax)
ajax是一个与服务器端语言无关的技术,可以使用在任何语言环境下的web项目(如JSP,PHP,ASP等). ajax优点: 1) 页面无刷新的动态数据交互 2) 局部刷新页面 3) 界面的美观 4) ...
- 原生JS 表单提交验证器
转载:http://www.cnblogs.com/sicd/p/4613628.html 一.前言 最近在开发一个新项目,需要做登陆等一系列的表单提交页面.在经过“缜密”的讨论后,我们决定 不用外部 ...
- 框架操作DOM和原生js操作DOM比较
问题引出 对于Angular和React操作DOM的速度,和原生js操作DOM的速度进行了一个比较: 一个同学做的demo 代码如下: <!DOCTYPE html> <html n ...
- 使用原生JS实现一个风箱式的demo,并封装了一个运动框架
声明,该DEMO依托于某个培训机构中,非常感谢这个培训结构.话不多说,现在开始改demo的制作. 首先,在前端的学习过程中,轮播图是我们一定要学习的,所以为了更加高效的实现各种轮播图,封装了一个运动的 ...
- {{angular.js 使用技巧}} - 基于验证框架的扩展(w5cValidator)
开场白: angular.js 是谷歌出的前端js MV*框架,我也是今年做 worktile 的时候才开始接触的,起初技术选型的时候还准备使用 backbone(毕竟很多大公司在使用他,而且也是比较 ...
- 表单验证--通过原生js模仿ajax的异步交互
今天给大家带来个福利,我也是刚刚学习的很实用的一个东西,通过原生js模仿ajax的异步交互. 我的博客只是给那些新手看的大神勿喷,写的不好可留言,请指出. 因为当初自己学的时候一个问题不会找人问,知道 ...
- 页面性能优化-原生JS实现图片懒加载
在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况.我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片.所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再 ...
- 原生js的开发笔记
1.基本的dom操作 var a=document.getElementById('ma1').innerHTML;/获取html代码 alert(document.getElementById('m ...
随机推荐
- Java核心技术卷一基础知识-第11章-异常、断言、日志和调试-读书笔记
第11章 异常.断言.日志和调试 本章内容: * 处理错误 * 捕获异常 * 使用异常机制的技巧 * 使用断言 * 日志 * 调试技巧 * GUI程序排错技巧 * 使用调试器 11.1 处理错误 如果 ...
- 吴恩达机器学习笔记38-决策下一步做什么(Deciding What to Do Next Revisited)
我们已经讨论了模型选择问题,偏差和方差的问题.那么这些诊断法则怎样帮助我们判断,哪些方法可能有助于改进学习算法的效果,而哪些可能是徒劳的呢? 让我们再次回到最开始的例子,在那里寻找答案,这就是我们之前 ...
- SpringCache实战遇坑
1. SpringCache实战遇坑 1.1. pom 主要是以下两个 <dependency> <groupId>org.springframework.boot</g ...
- 使用PageHepler分页
首先需要引入依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>p ...
- 【mysql】模糊查询的使用
1.like/not like 关键字的模糊查询(SQL模式) 基础模板: SELECT * FROM test WHERE name LIKE '%你好_' :匹配 ...
- [原创]K8Cscan插件之Cisco思科设备扫描(IP、设备型号、主机名、Boot、硬件版本)
[原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...
- (转)python异步编程--回调模型(selectors模块)
原文:https://www.cnblogs.com/zzzlw/p/9384308.html#top 目录 0. 参考地址 1. 前言 2. 核心类 3. SelectSelector核心函数代码分 ...
- 【WebAPI No.1】创建简单的 .NETCore WebApi
介绍: 官方定义如下,强调两个关键点,即可以对接各种客户端(浏览器,移动设备),构建http服务的框架.Web API最重要的是可以构建面向各种客户端的服务. core的WebAPI与ASP.NET ...
- redis 系列4 数据结构之链表
一. 概述 链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可能通过增删节点来灵活地调整链表的长度.作为一种数据结构,在C语言中并没有内置的这种数据结构.所以Redis构建了自己的链表实现 ...
- 项目ITP(五) spring4.0 整合 Quartz 实现任务调度
前言 系列文章:[传送门] 项目需求: 二维码推送到一体机上,给学生签到扫描用.然后需要的是 上课前20分钟 ,幸好在帮带我的学长做 p2p 的时候,接触过.自然 quartz 是首选.所以我就配置了 ...