You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Dormitory_Management_System/src/main/webapp/js/validate.js

232 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 立即执行函数,用于创建一个局部作用域,避免全局变量污染,在这个函数内部定义了一个基础的类继承机制以及一些与表单验证相关的功能代码。
(function () {
/**
* 所有类的基类,提供继承机制
* 这里通过一些巧妙的代码逻辑实现了一个简单的类继承模式,允许创建类并能方便地继承其他类的属性和方法,同时处理了在子类中调用父类同名方法的情况(通过 _super 机制)。
*/
// 用于检测当前JavaScript环境是否支持在函数内部通过名字访问函数自身的代码用于判断是否是严格模式等情况根据检测结果确定后续用于检测函数中是否包含 _super 关键字的正则表达式。
var initializing = false, fnTest = /xyz/.test(function () { xyz; })? /\b_super\b/ : /.*/;
// 创建一个名为 Class 的全局函数在严格模式下这里的this指向全局对象非严格模式下指向调用者的上下文对象一般在浏览器环境下是 window 对象),这个函数后续作为创建类的构造函数,初始时它只是一个空函数,后续会通过扩展功能来完善类的创建逻辑。
this.Class = function () { };
// 为 Class 函数添加一个 extend 方法用于实现类的继承功能通过传入一个包含属性和方法的对象prop来定义子类要扩展或重写的内容。
Class.extend = function (prop) {
// 获取当前类(调用 extend 方法的类)的原型对象,也就是父类的原型,后续用于在子类中访问父类的方法等操作,实现继承关系中的方法复用和重写逻辑。
var _super = this.prototype;
// 设置 initializing 为 true表示正在初始化一个新的类在继承过程中创建子类的原型对象阶段用于后续在构造函数中判断是否是初始化阶段避免一些不必要的操作比如重复调用初始化方法等
initializing = true;
// 通过使用 new 操作符调用当前类this 指向调用 extend 的类,也就是父类)的构造函数来创建一个新的对象,这个对象将作为子类的原型对象,它会继承父类原型上的属性和方法。
var prototype = new this();
// 完成子类原型对象的创建后,将 initializing 重新设置为 false表示初始化阶段结束。
initializing = false;
// 遍历传入的属性对象prop中的每个属性一般是方法或新定义的属性进行相应的处理判断是普通属性赋值还是函数属性的特殊处理涉及到父类同名函数的调用情况
for (var name in prop) {
// 判断当前属性prop[name]是否是函数类型并且父类原型上是否存在同名的函数属性_super[name]),同时还要检测该函数的代码中是否包含 _super 关键字(通过 fnTest 正则表达式判断),如果满足这些条件,则进行特殊的函数包装处理,用于实现子类中调用父类同名函数的功能。
prototype[name] = typeof prop[name] == "function"
&& typeof _super[name] == "function" && fnTest.test(prop[name])?
// 如果满足上述条件,返回一个新的函数,这个函数内部实现了先临时保存当前对象的 _super 属性(可能是之前保存的父类同名函数引用),然后将 _super 属性指向父类的同名函数,接着调用传入的函数(也就是子类重写的函数),在调用完成后恢复 _super 属性的原始值,最后返回函数执行的结果,这样就巧妙地实现了在子类函数中通过 this._super 调用父类同名函数的功能。
(function (name, fn) {
return function () {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) : prop[name];
}
// 创建一个新的函数(作为子类的构造函数),在这个构造函数中,如果当前不是处于初始化阶段(即不是在创建子类原型对象过程中),并且子类定义了 init 方法(一般用于初始化操作),则调用子类的 init 方法,并传入相应的参数,实现子类实例化时的初始化逻辑。
function Class() {
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// 将前面创建并处理好的原型对象prototype赋值给新创建的子类构造函数Class的原型属性这样通过这个构造函数创建的实例就能继承原型对象上的属性和方法了。
Class.prototype = prototype;
// 修复子类构造函数的 constructor 属性,将其指向正确的子类构造函数本身,确保在使用 instanceof 等操作时能正确识别对象的构造函数类型。
Class.prototype.constructor = Class;
// 将 extend 方法也添加到子类的构造函数上,使得子类也能继续通过调用 extend 方法来实现进一步的继承,形成继承链,这里通过 arguments.callee 引用当前的 extend 函数本身来实现这个功能不过在严格模式下arguments.callee 是不允许使用的,代码可能需要调整)。
Class.extend = arguments.callee;
// 返回创建好的子类构造函数,外部可以通过调用这个构造函数来创建子类的实例对象,完成类的继承和实例化操作。
return Class;
};
})();
// 使用前面定义的 Class 类及继承机制创建一个名为 validate 的类,它继承自 Class主要用于实现表单验证相关的功能比如验证表单字段是否符合特定的规则、显示错误提示等。
var validate = Class
.extend({
// 默认配置对象包含了验证相关的各种默认设置如验证规则rules、提交表单时执行的函数submitFun、用于显示错误信息的HTML标签模板errorLabel以及出现错误时执行的函数errorFun等属性。
defaultCfg: {
rules: {},
submitFun: function () { },
errorLabel: '<label style="color:red"></label>',
errorFun: function () { }
},
// 初始化方法,在创建 validate 类的实例时会被调用(如果不是处于类继承的初始化阶段,也就是 new 操作实例化时会执行),用于初始化验证相关的配置信息以及绑定一些事件处理等操作。
init: function (cfg) {
// 使用 jQuery 的 extend 方法将传入的配置对象cfg与默认配置对象defaultCfg进行合并得到最终的配置对象并赋值给 this.cfg这样既可以使用默认配置又能通过传入的参数覆盖部分默认配置。
this.cfg = $.extend({}, this.defaultCfg, cfg);
// 初始化一个标志变量flag为0用于记录表单验证过程中是否出现错误等情况后续根据这个标志来决定是否执行提交表单等操作。
this.flag = 0;
// 调用 toAction 方法并传入当前实例对象this开始进行表单验证相关的操作比如遍历验证规则并对相应的表单字段进行验证。
this.toAction(this);
// 如果验证过程中没有出现错误flag 仍然为0则解除表单字段的 keyup 事件绑定可能是之前绑定的用于实时验证的事件这里在全部验证通过后解除避免重复验证等不必要的操作然后执行提交表单的函数submitFun提交表单数据等操作具体由这个函数的实现决定
if (this.flag == 0) {
for (var i in this.cfg.rules) {
$("#" + i).unbind("keyup");
}
this.cfg.submitFun();
}
},
// 用于执行表单验证的主要方法接收一个表示当前验证实例的对象that在这个方法内部会遍历配置的验证规则并针对每个规则调用 toVal 方法对相应的表单字段进行验证操作。
toAction: function (that) {
for (var i in that.cfg.rules) {
this.toVal("#" + i, that.cfg.rules[i]);
}
},
// 具体验证单个表单字段的方法接收一个表单字段的选择器ele一般是类似 "#inputId" 的形式表示通过ID选择元素以及对应的验证规则常量constant用于确定使用哪种验证规则来验证该字段根据验证结果调用相应的方法来显示或移除错误提示信息。
toVal: function (ele, constant) {
// 调用 validateConstant 对象中对应的验证规则函数(通过 constant 作为键来查找),传入表单字段的值(通过 jQuery 获取元素的值)进行验证,如果验证通过(返回 true则调用 toRemoveError 方法移除该字段的错误提示信息,否则调用 toShowError 方法显示相应的错误提示信息(传入错误提示消息,通过 errorMsg 对象根据验证规则常量获取)。
validateConstant[constant].test($(ele).val())?
this.toRemoveError(ele) : this.toShowError(ele, errorMsg[constant]);
},
// 用于移除表单字段错误提示信息的方法接收一个表单字段的选择器ele首先获取当前验证实例对象通过 this 赋值给 that 变量),然后判断该字段所在的表单组元素(通过 closest 方法查找父级的.form-group 元素)是否有 "not-allow" 属性,如果有则表示之前添加过错误提示等限制属性,现在需要移除这些属性,恢复表单字段和表单组的原始样式(通过 removeAttr 方法移除相关样式属性),同时移除该字段后面的错误提示标签(通过 next 方法找到并 remove 方法移除),最后重新绑定 keyup 事件,当用户再次输入内容时重新进行验证(调用 toVal 方法)。
toRemoveError: function (ele) {
var that = this;
if ($(ele).closest(".form-group").attr("not-allow")) {
$(ele).removeAttr("style").closest(".form-group").removeAttr("style")
.removeAttr("not-allow");
$(ele).next().remove();
$(ele).keyup(function () {
ele = ele.replace("#", "");
that.toVal("#" + ele, that.cfg.rules[ele]);
});
}
},
// 用于显示表单字段错误提示信息的方法接收一个表单字段的选择器ele以及对应的错误提示消息message首先根据配置的错误标签模板cfg.errorLabel创建一个包含错误消息的 <label> 标签元素(通过 jQuery 的 text 方法设置文本内容),然后判断该字段所在的表单组元素是否已经有 "not-allow" 属性(如果没有则表示之前没有添加过错误提示,需要添加),如果没有则将错误提示标签添加到表单字段后面(通过 after 方法),同时设置表单字段和表单组的样式为红色边框、红色文字等错误提示样式(通过 css 方法设置样式属性,并通过 attr 方法添加 "not-allow" 属性表示已经添加了错误提示),最后重新绑定 keyup 事件当用户再次输入内容时重新进行验证并且每次显示错误提示时会将标志变量flag加1表示出现了错误情况后续可以根据这个标志来判断是否能提交表单等操作。
toShowError: function (ele, message) {
var error = $(this.cfg.errorLabel).text(message);
if (!$(ele).closest(".form-group").attr("not-allow")) {
$(ele).after(error);
$(ele).css("border", "1px solid red").closest(".form-group")
.css("color", "red").attr("not-allow", "true");
$(ele).keyup(function () {
ele = ele.replace("#", "");
that.toVal("#" + ele, that.cfg.rules[ele]);
});
}
this.flag++;
var that = this;
}
})
// 定义一个名为 validateConstant 的对象,用于存储各种表单字段验证的正则表达式或验证函数,通过不同的键(验证规则常量,如 "notEmpty"、"password" 等)来对应不同的验证逻辑,用于验证表单输入是否符合相应的格式要求。
var validateConstant = {
"notEmpty": /^.+$/,// 合法字符,该正则表达式表示只要输入有内容(至少包含一个字符)就算符合要求,用于验证字段不能为空。
"password": /^[0-9A-Za-z]{1,18}$/,// 密码验证密码格式要求由数字、大小写字母组成长度在1到18位之间。
"rightfulString": /^[A-Za-z0-9_-]+$/,// 合法字符,验证输入是否是由大小写字母、数字、下划线和短横线组成的合法字符串。
"number": /^\d+$/,// 数字,验证输入是否只包含数字。
"endlish": /^[A-Za-z]+$/,// 纯英文,验证输入是否只包含英文字母。
"numberEnglish": /^[A-Za-z0-9]+$/,// 英文和数字,验证输入是否只包含英文字母和数字。
"float": /^[+]?\d+(\.\d+)?$/,// 浮点型,验证输入是否是合法的浮点数格式,可以包含正负号、整数部分和可选的小数部分。
"money": /(^[1-9]\d{0,9}(\.\d{1,2})?$)/,
"chinese": "/^[\u4e00-\u9fa5]+$/",// 纯中文验证输入是否只包含中文字符通过Unicode编码范围来判断不过这里的正则表达式写法有点问题外面的双引号应该去掉正确的是 /^[\u4e00-\u9fa5]+$/.
"mobile": /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(14[0-9]{1}))+\d{8})$/,// 手机号,验证输入是否是符合常见手机号码格式的字符串。
"tel": /^(\d{3,4}-?)?\d{7,9}$/g,// 电话,验证输入是否是符合常见电话号码格式(可以包含区号,用 - 连接,也可以没有区号)的字符串,注意这里的 /g 表示全局匹配标志,在验证时会匹配所有符合的内容(不过在这个场景下一般只验证一个电话号码,是否需要全局匹配可根据实际情况调整)。
"qq": /^[1-9]\d{4,12}$/,// qq验证输入是否是符合QQ号码格式数字开头长度在5到13位之间的数字字符串。
"zipCode": /^[0-9]{6}$/,// 邮政编码验证输入是否是6位数字的邮政编码格式。
"email": /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,// 邮箱,验证输入是否是符合常见邮箱格式(包含用户名、@符号、域名等部分,这里只是简单的格式验证,不是非常严格)的字符串。
"positive": /^[1-9][0-9]+$/,//大于0的数字验证输入是否是大于0的整数数字开头且不是0后面可以跟其他数字
"checkIdCard": function (idcard) {// 校验身份证定义一个函数用于验证身份证号码的合法性根据身份证号码的位数15位或18位以及对应的出生日期、地区编码、校验位等规则来进行详细的验证返回 true 表示验证通过false 表示验证不通过。
var area = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西",
37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃",
63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" }
var idcard, Y, JYM;
var S, M;
var idcard_array = new Array();
idcard_array = idcard.split("");
//地区检验,通过截取身份证号码的前两位,在 area 对象中查找对应的地区名称,如果查找不到则表示地区编码不合法,返回 false。
if (area[parseInt(idcard.substr(0, 2))] == null) {
return false;
}
//身份号码位数及格式检验根据身份证号码的长度15位或18位分别进行不同的格式和合法性验证主要涉及出生日期的合法性检查以及18位身份证的校验位计算等操作。
switch (idcard.length) {case 15:
if ( (parseInt(idcard.substr(6,2))+1900) % 4 == 0 || ((parseInt(idcard.substr(6,2))+1900) % 100 == 0 && (parseInt(idcard.substr(6,2))+1900) % 4 == 0 )){
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;
//测试出生日期的合法性
} else {
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/;
//测试出生日期的合法性
}
if(ereg.test(idcard)){
return true;
}else{
return false;
}
break;
case 18:
//18位身份号码检测
//出生日期的合法性检查
//闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
//平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if ( parseInt(idcard.substr(6,4)) % 4 == 0 || (parseInt(idcard.substr(6,4)) % 100 == 0 && parseInt(idcard.substr(6,4))%4 == 0 )){
ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/;
//闰年出生日期的合法性正则表达式
} else {
ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/;
//平年出生日期的合法性正则表达式
}
if(ereg.test(idcard)){//测试出生日期的合法性
//计算校验位
S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7 + (parseInt(idcard_array[1]) + parseInt(idcard_array[11])) * 9
+ (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10 + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5
+ (parseInt(idcard_array[4]) + parseInt(idcard_array[14])) * 8 + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4
+ (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2 + parseInt(idcard_array[7]) * 1 + parseInt(idcard_array[8]) * 6
+ parseInt(idcard_array[9]) * 3 ;
Y = S % 11;
M = "F";
JYM = "10X98765432";
M = JYM.substr(Y,1);//判断校验位
if(M == idcard_array[17].toUpperCase()) {
return true; //检测ID的校验位
}else{
return false;
}
}else{
return false;
}
break;
default:
return false;
break;
}
}
}
var errorMsg = {
"notEmpty" : "不能为空",
"password" : "请输入正确的密码",
"rightfulString" : "请输入合法字符",// 合法字符
"number" : "只能输入数字",// 数字
"endlish" : "只能输入英文",// 纯英文
"numberEnglish" : "只能输入英文或数字",// 英文和数字
"float" : "只能输入小数",// 浮点型
"money" : "请输入合法价格",
"chinese" : "只能输入汉字",// 纯中文
"mobile" : "请输入正确的手机号",// 手机号
"tel" : "请输入正确的电话号码",// 电话
"qq" : "请输入正确的QQ号",// qq
"zipCode" : "请输入正确的QQ号",
"email" : "请输入正确的邮箱",// 邮箱
"positive":"请输入大于0的数字",//大于0的数字
"checkIdCard" : "请输入正确的身份证号"// 校验身份证
}