支持异步验证、动态添加验证、动态移除验证、自定义验证规则或者规则是一个函数、依赖验证(依赖于另一个项是否已经验证成功)、重复项验证如密码、自定义验证成功或失败回调(可用于自定义验证样式)、添加html属性形式配置验证参数或直接js传入参数的方式、
/**
* 内联配置式
* data-pattern 验证规则 可以是预定义的正则、正则字面量 与js配置式相比是不能指定验证函数
* eg: *{6-12}、\d+.\d+、*{6}|\d+.\d+
* data-ajaxcheck 异步验证url
* data-ajaxtype 验证的请求类型 默认post
* data-attach 属于配合异步验证使用 异步验证时有可能需要传递附加参数,name值以英文逗号分割
* eg: mobile,sex
* data-depend 依赖于其他项是否验证正确,当所依赖项验证全部通过时才会验证此项
* eg: mobile,sex
* data-recheck 重复验证,值为被对比项的name值
* eg: password
* data-empty 当值为空时的提示内容
* eg: 手机号不能为空
* data-error 当值格式错误时的提示内容
* eg: 手机号格式不正确
* ignore 有值验证、无值不验证
*
* js配置式 配置的验证字段必须在表单中存在初始化时才会生效验证规则
* pattern 需要验证的项 以需验证项的name为键名,值可以是是预定义的正则、正则字面量或一个验证函数,否则被转换成字符串并测试是否全等
* eg: {
* mobile: "*{6-12}"、/\d+.\d+/、"*{6}|\d+.\d+"、验证函数
* }
* ajaxcheck 异步验证 需要对象值 覆盖内联式
* eg: 以验证项name值为键名,键值可以是函数或对象
* 当为函数时,用于配合该验证项验证,所需其他参数从内联属性获取,作为异步验证接口的回调处理函数,返回true值表验证通过
* 当为对象时,用于配置异步验证
* mobile: {
* url: '/check',
* attach: ['mobile','sex'], // 或者直接字符串"mobile,sex"
* detect: 回调验证函数 如验证成功返回ture,
* ajaxtype: 验证的请求类型 默认post
* }
* depend 依赖于其他项是否验证正确 覆盖内联式
* recheck 异步验证 值为被对比项的name值 覆盖内联式
* eg: password
* ignore 有值验证、无值不验证 值为一个忽略项name值的数组
* eg: ['mobile','sex']
* rules 自定义验证规则 以规则名为键名,值可以是预定义的正则、字面量或一个验证函数,与HTML元素data-pattern属性值应用于键名相同的规则
* eg: "*{6-12}"、/\d+.\d+/、"*{6}|\d+.\d+"、验证函数 字面量值只要包含预定义正则时,值必须是一个字符串
*
*
* 其他可配置参数
* checkBefore // 每个需验证元素验证前的执行的函数
* checkAfter // 每个需验证元素验证后的执行的函数 参数中包含改元素的验证结果
* submitBtn // 值为选择器字符串 指定表单提交按钮
*
* ******错误成功提示相关*********
* showAllError // 是否显示所有错误提示(默认是),设为false时提交表单时碰到检测失败的元素就会停止检测后面的元素
* errorTip // 自定义错误提示处理函数,第二个参数是错误的字段,可能没有不传(因为存在非指定字段错误的类型),所以这里一定要判断一下元素是否存在
* successTip // 自定义成功提示处理函数
* showSuccessTip // 是否显示成功提示(默认否)
* label // 当未设置错误/为空情况的错误提示时 会查找label指定的选择器内容并跟相关文案拼接起来组成提示内容
*
* *****提交相关*******
* submitBefore // 提交前的函数,返回false可阻止继续提交
* ajaxPost // 是否是异步提交表单(默认是)
* callback // 异步提交后的回调函数 参数中包含请求的结果
* postOnce // 是否只能提交一次(默认否) 当设为true时 必须在callback中返回true值表示提交成功
* sendingTip // 异步提交时的 是否将提交按钮内容显示为提示文字 默认显示
* sendingText // 提交中提示文字 默认 请稍候...
*
* **********实例方法调用***************
* **********除了获取状态的方法isIgnore、getStatus,其他方法都返回实例**********
* // 实例挂载在form表单上 eg: $(".sub_form").data("validator").isIgnore('mobile')
* addIgnore // 添加无值忽略验证项
* removeIgnore // 删除无值忽略验证项
* addItem // 添加验证项 会覆盖之前的同类型验证配置(包括内联式和js配置式,如异步验证、重复验证等)
* removeItem // 删除验证项
* triggerCheck // 手动触发一个项的验证 第一个参数要验证的项,第二个参数传递false可指定不显示错误提示
* isIgnore // 获取状态 判断是否为无值忽略验证项
* getStatus // 获取状态 获取表单或元素的验证状态 参数为元素的name值或HTML元素(表单元素或控件元素) 返回验证状态,不在验证范围的都直接返回true
*
* // 当表单异步提交时 可在callback中调用 一般用于提交表单后后端返回了非字段错误
* // 所有表单字段验证的错误提示都统一显示在一处 此时就非常合适在callback中调用这个统一显示错误提示的方法
* // 参数1是错误信息,参数2错误元素name值(非字段错误并且所有错误提示都是显示在一处时不用关心哪个字段错误了时,可不传)
* errorTip
* successTip // 表单字段验证成功
*/
;
(function ($) {
$.fn.validator = function (ops) {
var form = this;
var ori_patterns = {
'*': /^.+$/,
'n': /^\d+$/,
'zh': /^[\u4e00-\u9fa5]$/,
'email': /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
'url': /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i,
m: /^(1[3|4|5|6|7|8|9]\d{9}|[569]{1}\d{3}[-]?\d{4})$/, // 国内&香港手机,
pwd: /^(?![^a-zA-Z]+$)(?!\D+$).{6,20}$/, // 强密码
user: /[\w\u4E00-\u9FA5\uF900-\uFA2D]{3,15}/, // 用户名
}
var def = {
ignore: [],
rules: {},
ajaxcheck: {}, // 覆盖内联式
recheck: {}, // 覆盖内联式
depend: {}, // 覆盖内联式
pattern: {}, // 合并内联式
checkBefore: {}, // 每个需验证元素验证前的执行的函数
checkAfter: {}, // 每个需验证元素验证后的执行的函数
showSuccessTip: false, // 是否显示成功提示
showAllError: true, // 是否显示所有错误提示,设为false提交表单时碰到检测失败的元素就会停止检测后面的元素
submitBefore: $.noop, // 提交前的函数,返回false可阻止继续提交
ajaxPost: true, // 是否是异步提交
callback: $.noop, // 异步提交后的回调函数 参数中包含请求的结果
postOnce: false, // 是否只能提交一次
label: '',
submitBtn: '', // 指定提交按钮 必需选择器字符串,否则会查找表单下的:submit类型按钮
sendingTip: true,
sendingText: '请稍候...', // 提交中按钮上的提示文字
}
var conf = $.extend(true, {}, def, ops || {});
function Valid(cur_form, conf) {
var that = this;
that.conf = $.extend(true, {}, conf);
that.$form = $(cur_form);
that._init();
that._checkEvent();
that._submit();
setTimeout(function () {
// 直接触发一次 可能会存在默认就可以成为已验证状态的项
for (var k in that.checkItem) {
that.triggerCheck(k, false);
}
})
}
Valid.prototype = {
constructor: Valid,
_init: function () {
var that = this;
var $form = that.$form;
var conf = that.conf;
// 验证项
that.checkItem = {};
// 依赖项
that.dependItem = {};
// 被依赖项
that.beDependItem = {};
// 是否正在异步提交表单的标记
that._posting = false;
if (conf.submitBtn) {
that.$submit = that.$form.find(conf.submitBtn);
}
if (!that.$submit) {
that.$submit = that.$form.find(':submit');
}
that._btnOldText = that.$submit.html();
// 编程配置式异步验证项
for (var k in conf.ajaxcheck) {
if (typeof conf.ajaxcheck != 'function' && conf.ajaxcheck[k].url) {
$form.find('[name="' + k + '"]').attr('data-ajaxcheck', conf.ajaxcheck[k].url +
"");
}
}
// 编程配置式自定义重复验证项
for (var k in conf.recheck) {
that.addRecheck(k, conf.recheck[k]);
}
// // 编程配置式自定义依赖项
for (var k in conf.depend) {
that.addDepend(k, conf.depend[k]);
}
// 编程配置式自定义有值才验证项
for (var i = 0; conf.ignore[i]; i++) {
that.addIgnore(conf.ignore[i]);
}
// 编程配置式异步验证
for (var k in conf.ajaxcheck) {
that.addAjaxCheck(k, conf.ajaxcheck[k]);
}
// 编程配置式自定义验证项
for (var k in conf.pattern) {
that.addPattern(k, conf.pattern[k]);
}
// debugger
$form.find('[data-recheck],[data-ajaxcheck],[data-pattern],[data-depend],[ignore]')
.each(function () {
that.checkItem[this.name] = false;
});
},
_checkEvent: function () {
var that = this;
var $form = that.$form;
var conf = that.conf;
var showErrorTip = true;
$form.on('change.validator', function (e, params) {
// 指定验证不显示错误提示
showErrorTip = params === undefined || (params && params.hideErrorTip !==
false);
// debugger
// console.log(e)
if (!e.isTrigger || (params && 'hideErrorTip' in params && showErrorTip)) {
that._showAllErrorFlag = false;
}
var ele = e.srcElement || e.target;
var $ele = $(ele);
var name = ele.name;
// debugger
if (name in that.checkItem) {
that.checkItem[name] = false;
if (name in conf.checkBefore) {
if (conf.checkBefore[name].call(that, $ele, $form) === false) {
return true;
}
}
var ori_val = _getVal(ele);
var check_val = ori_val;
if ($.isArray(check_val)) {
check_val = check_val.join();
}
// 有值才验证项
if ($ele.is('[ignore]') && !check_val) {
return;
}
var depend_check = true;
// 存在需验证的依赖项
if (that.dependItem[name]) {
for (var k in that.dependItem[name]) {
if (!(depend_check = that.getStatus(k))) {
break;
}
}
}
if (!depend_check) {
return;
}
var have_conf_pattern = conf.pattern && conf.pattern[name];
var have_conf_ajaxcheck = (conf.ajaxcheck && conf.ajaxcheck[name]) || {};
var attrs_conf = {
recheck: conf.recheck[name] || $ele.attr('data-recheck'),
ajaxcheck: have_conf_ajaxcheck.url || $ele.attr(
'data-ajaxcheck'),
attach: have_conf_ajaxcheck.attach || $ele.attr('data-attach'),
ajaxtype: have_conf_ajaxcheck.ajaxtype || $ele.attr(
'data-ajaxtype') || 'post',
"empty": $ele.attr('data-empty') || (have_conf_pattern &&
have_conf_pattern['empty'] ? have_conf_pattern['empty'] :
''),
"error": $ele.attr('data-error') || (have_conf_pattern &&
have_conf_pattern['error'] ? have_conf_pattern['error'] :
''),
pattern: $ele.attr('data-pattern'),
conf_pattern: conf.pattern[name],
};
var check_sort = ['recheck', 'pattern', 'conf_pattern'];
var check_sort_res = true;
var check_sort_i = 0;
var check_sort_curr = check_sort[check_sort_i];
if (check_val) {
while (check_sort_curr = check_sort[check_sort_i]) {
if (attrs_conf[check_sort_curr]) {
if (check_sort_curr === 'recheck') {
var chk_ele = $form.find('[name="' + attrs_conf.recheck +
'"]')[0];
if (check_val !== _getVal(chk_ele)) {
_errorTip(attrs_conf["error"] || "两次输入不一致", name);
check_sort_res = false;
break;
}
} else {
var get_pattern = attrs_conf[check_sort_curr];
// if (check_sort_curr === 'conf_pattern' && 'detect' in get_pattern) {
// // js配置式,并且存在验证器键值时,需要获取定义的验证器
// get_pattern = get_pattern.detect;
// }
get_pattern = that._getPatt(get_pattern);
if (typeof get_pattern === 'function') {
var get_pattern_fn_back = get_pattern.call(that,
check_val, ori_patterns, $ele, $form);
if (get_pattern_fn_back !== true) {
_errorTip(typeof get_pattern_fn_back ===
'string' ? get_pattern_fn_back :
_getErrorText(ele, attrs_conf["error"]),
name);
check_sort_res = false;
break;
}
} else {
if (!get_pattern.test(check_val)) {
_errorTip(_getErrorText(ele, attrs_conf["error"]),
name);
check_sort_res = false;
break;
}
}
}
}
check_sort_i++;
}
} else {
_errorTip(attrs_conf["empty"] || _getEmptyText(ele, _getLabelText(
$ele)) || $ele.attr('placeholder'), name);
check_sort_res = false;
}
if (check_sort_res) {
if (attrs_conf.ajaxcheck) {
var $post_ele = $(ele);
if (attrs_conf.attach) {
$post_ele = $post_ele.add($(attrs_conf.attach.toString().replace(
/^,/g, '').replace(/,$/g, '').replace(
/([^,]+)/g, '[name="$1"]'), $form))
}
$.ajax({
type: attrs_conf.ajaxtype,
url: attrs_conf.ajaxcheck,
dataType: 'json',
data: $post_ele.serialize(),
success: function (m, status, xhr) {
var conf_ajaxcheck;
if (conf.ajaxcheck && (conf_ajaxcheck =
conf.ajaxcheck[name])) {
// 自定义回调处理
var check_res;
if (typeof conf_ajaxcheck ===
'function') {
// 只是指定一个异步验证的回调函数
check_res = conf_ajaxcheck.call(
that, m, _e, ele, $form,
xhr);
} else if (typeof conf_ajaxcheck.detect ===
'function') {
// js配置式定义异步验证的回调函数
check_res = conf_ajaxcheck.detect.call(
that, m, _e, ele, $form,
xhr);
} else {
new Error(name + '异步验证配置异常');
}
if (check_res === true) {
that.successTip($ele, $form);
if (e.isTrigger) {
that.$submit.trigger(
'click.validator');
}
} else {
that.checkItem[name] = false;
// 如果自定义验证函数当字段验证失败时没调用时程序自己调用一次
if (_e.called !== true) {
_e(typeof check_res ===
"string" ? check_res :
'', attrs_conf["error"]
);
}
}
} else if (typeof m === 'object') {
// 默认回调处理 接口必须是配合返回
if (m.status == 0) {
_errorTip(_getErrorText(ele,
attrs_conf["error"]),
name);
} else if (m.status) {
that.successTip($ele, $form);
if (e.isTrigger) {
that.$submit.trigger(
'click.validator');
}
}
}
function _e(err) {
if (!_e.called) {
_errorTip(err, name);
_e.called = true;
}
}
},
error: function () {
_errorTip("网络错误,稍后重试", name);
}
})
} else {
that.successTip($ele, $form);
}
}
}
});
function _errorTip() {
if (showErrorTip) {
that.errorTip.apply(that, arguments);
}
}
function _getVal(ele) {
// var tagName = ele.tagName.toLowerCase();
var type = ele.type;
var name = ele.name;
var $ele = $('[name="' + name + '"]', $form);
var val;
if (type === 'radio') {
val = $('[name="' + name + '"]:checked', $form).val();
} else if (type === 'checkbox') {
$('[name="' + name + '"]:checked', $form).each(function () {
if (!$.isArray(val)) {
val = [];
}
val.push(this.value);
});
} else {
val = $ele.val();
}
// if ($.isArray(val)) {
// val = val.join();
// }
return val;
}
function _getErrorText(ele, err) {
var label_text = _getLabelText($(ele));
return err || (label_text || $(ele).attr('placeholder')) + '格式不正确';
}
function _getEmptyText(ele, label) {
if (label) {
var tagName = ele.tagName.toLowerCase();
var type = ele.type;
var name = ele.name;
var $ele = $('[name="' + name + '"]', $form);
var text = "";
if (tagName === 'input') {
if (~$.inArray(['radio', 'checkbox'])) {
text = "请选择";
} else {
text = "请输入";
}
} else if (tagName === 'textarea') {
text = "请输入";
} else if (tagName === 'select') {
text = "请选择";
}
return text + label;
} else {
return "";
}
}
function _getLabelText($ele) {
var label = conf.label;
if (label) {
while ($ele[0] !== $form[0]) {
var $coll = $ele.siblings(label);
if ($coll.length) {
if ($coll.length === 1) {
return $coll.text().replace(/[\*::]/g, '');
} else {
new Error('指定label时,所有label之间不能是兄弟节点关系')
}
} else {
$ele = $coll.parent();
}
}
}
return "";
}
},
_submit: function () {
var that = this;
var $form = that.$form;
var $submit = that.$submit;
var conf = that.conf;
$submit.on('click.validator', function (e) {
if (that._getFormStatus()) {
if (conf.submitBefore.call(that, $form) === false) {
return;
}
// 提交
if (conf.ajaxPost) {
e.preventDefault();
if (
(conf.postOnce && that.postOnced) ||
that._posting
) {
return;
}
that.$submit.attr('disabled', true);
if (conf.sendingTip) {
that.$submit.html(conf.sendingText);
}
that._posting = true;
$.ajax({
url: $form.attr('action'),
type: $form.attr('method') || 'get',
data: $form.serialize(),
dataType: 'json',
success: function () {
var _c = conf.callback.apply(that, arguments);
that.postOnced = _c !== false;
// 回调返回false说明没有表单提交失败 需要重置按钮
if (_c === false) {
that.$submit.removeAttr('disabled').html(
that._btnOldText);
}
},
error: function () {
that.errorTip('网络错误,稍后重试');
that.$submit.removeAttr('disabled').html(that._btnOldText);
},
complete: function () {
that._posting = false;
that._showAllErrorFlag = false;
}
});
} else {
that.$submit.attr('disabled', true);
if (conf.sendingTip) {
that.$submit.html(conf.sendingText);
}
}
} else {
// 当提交表单时设置不一次性显示所有错误时程序逻辑中需要用到的标记 当次提交表单是否已显示过一次错误提示
that._showAllErrorFlag = false;
e.preventDefault();
for (var k in that.checkItem) {
if (!that.checkItem[k]) {
that.triggerCheck(k);
}
}
return false;
}
});
},
_getFormStatus: function () {
var items = this.checkItem;
for (var k in items) {
if (!items[k]) {
return false;
}
}
return true;
},
_getPatt: function (patt) {
if (patt.constructor === Object) {
patt = patt.pattern || "";
}
// 编程配置式自定义的是正则函数或字面量
if (typeof patt === 'function' || patt instanceof RegExp) {
return patt;
}
patt = patt + '';
// 完全匹配自定义
if (patt in this.conf.rules) {
return this.conf.rules[patt];
}
patt = patt.replace(/^[,|]/, '').replace(/[,|]$/, '');
// 完全匹配预置定义
if (patt in ori_patterns) {
return ori_patterns[patt];
}
var patt_arr, ori_match;
// 如果是正则不能使用规则累计或多选一
if (~patt.search(/^\/.+\/$/)) {
patt_arr = [patt.slice(1, patt.length - 1)];
} else {
var patt_split = patt.split(/[,|]/);
patt_arr = [];
for (var i = 0; patt_split[i]; i++) {
ori_match = patt_split[i].match(/^(\*|n|zh)(?:(\d+)?(?:-(\d+))?)$/);
if (ori_match) {
ori_match = ori_patterns[ori_match[1]].toString().replace('$', '{' +
ori_match[2] + (ori_match[3] ? ',' + ori_match[3] : '') + '}$');
ori_match = ori_match.replace('+{', '{');
patt_arr.push(ori_match.slice(1, ori_match.length - 1));
} else {
if (patt_split[i] in ori_patterns) {
patt_arr.push(ori_patterns[patt_split[i]]);
} else if (patt_split[i] in this.conf.rules) {
patt_arr.push(this.conf.rules[patt_split[i]])
} else {
patt_arr.push(patt_split[i]);
}
}
}
}
// debugger
if (patt_arr.length === 1) {
return new RegExp(patt_arr[0]);
} else {
// 规则累计或多选一
// “|”为或者、“,”为并且 如*6,email|url
return function (val, pattern, $ele, $form) {
var mark = patt.match(/[,|]/);
var test = [];
for (var i = 0; patt_arr[i]; i++) {
if (typeof patt_arr[i] === 'function' ? patt_arr[i].apply(this,
arguments) : new RegExp(patt_arr[i]).test(val)) {
// test[i] = true;
if (mark[i] === undefined) {
// 已经是最后一个验证
return true;
} else if (mark[i] === ',') {
continue;
} else {
return true;
}
} else {
if (mark[i] === undefined) {
// 已经是最后一个验证
return false;
} else if (mark[i] === '|') {
continue;
} else {
return false;
}
}
}
return true;
}
}
},
_checkAfter: function (status, $ele, $form) {
var after = this.conf.checkAfter;
var name = $ele.attr("name");
if (name in after) {
after[name].apply(this, arguments);
}
},
_getEle: function (name) {
return $("[name='" + name + "']", this.$form);
},
_setCheckItem: function (name, status) {
if (this._getEle(name).length) {
this.checkItem[name] = status;
}
},
triggerCheck: function (name, hideErrorTip) {
this._getEle(name).trigger('change.validator', {
hideErrorTip: hideErrorTip
});
return this;
},
addRecheck: function (name, recheck) {
this._getEle(name).attr('data-recheck', recheck);
return this;
},
addDepend: function (name, depend) {
depend = depend.split(',');
var $ele = this._getEle(name);
var attr = $ele.attr('data-depend').split(',');
var all_depend = depend.concat(attr);
attr = [];
for (var i = 0; all_depend[i]; i++) {
attr.push(all_depend[i]);
}
$ele.attr('data-depend', all_depend + '');
// 依赖和被依赖标记
var _dependItem = this.dependItem[name] || {};
var temp;
for (var i = 0; temp = depend[i]; i++) {
// 标记依赖项
_dependItem[temp] = '';
// 标记被依赖项
var _beDependItem = this.beDependItem[temp] || {};
_beDependItem[name] = '';
this.beDependItem[temp] = _beDependItem;
}
this.dependItem[name] = _dependItem;
return this;
},
addAjaxCheck: function (name, ajaxcheck) {
var $ele = this._getEle(name);
if (ajaxcheck.url) {
$ele.attr('data-ajaxcheck', ajaxcheck.url);
}
if (ajaxcheck.attach) {
$ele.attr('data-attach', ajaxcheck.attach);
}
if (ajaxcheck.ajaxtype) {
$ele.attr('data-ajaxtype', ajaxcheck.ajaxtype);
}
if (ajaxcheck.detect) {
this.conf.ajaxcheck[name] = ajaxcheck.detect;
}
return this;
},
addPattern: function (name, pattern) {
if (typeof pattern === 'function') {
this.conf.pattern[name] = pattern;
} else {
this._getEle(name).attr('data-pattern', pattern);
}
return this;
},
addIgnore: function (name) {
this._getEle(name).attr('ignore', 'ignore');
return this;
},
removeRecheck: function (name) {
this._getEle(name).removeAttr('data-recheck');
return this;
},
removeDepend: function (name, depend) {
var $ele = this._getEle(name);
var attr = $ele.attr('data-depend') || '';
if (attr && depend) {
$attr = attr.replace(new(depend, 'g'), '');
}
// 不传depend或depend为空就是移除所有依赖
if (depend) {
depend = depend.split(',');
} else {
depend = attr.split(',');
}
var _dependItem = this.dependItem[name] || {};
var temp;
for (var i = 0; temp = depend[i]; i++) {
// 移除标记依赖项
if (temp in _dependItem) {
delete _dependItem[temp];
}
// 移除被依赖项标记
var _beDependItem = this.beDependItem[temp] || {};
if (name in _beDependItem) {
delete _beDependItem[name];
}
this.beDependItem[temp] = _beDependItem;
}
this.dependItem[name] = _dependItem;
return this;
},
removeAjaxCheck: function (name) {
var $ele = this._getEle(name);
$ele
.removeAttr('data-ajaxcheck')
.removeAttr('data-attach');
if (this.conf.ajaxcheck[name] && 'detect' in this.conf.ajaxcheck[name]) {
delete this.conf.ajaxcheck[name].detect;
}
return this;
},
removePattern: function (name) {
this._getEle(name).removeAttr('data-pattern');
if (typeof this.conf.pattern[name]) {
delete this.conf.pattern[name];
}
return this;
},
removeIgnore: function (name) {
this._getEle(name).removeAttr('ignore');
return this;
},
addItem: function (name, pattern, nowTrigger) {
if (name && pattern) {
var $ele = this._getEle(name);
if ($ele.length) {
// 设置配置式能进入验证环节
this.checkItem[name] = false;
switch (pattern.constructor) {
case RegExp:
case String:
case Function:
this.addPattern(name, pattern);
break;
case Object:
if ('recheck' in pattern) {
this.addRecheck(name, pattern.recheck);
}
if ('depend' in pattern) {
this.addDepend(name, pattern.depend);
}
if ('ajaxcheck' in pattern) {
this.addAjaxCheck(name, pattern.ajaxcheck);
}
if ('ignore' in pattern && pattern.ignore === name) {
this.addIgnore(name);
}
if ('pattern' in pattern) {
this.addPattern(name, pattern.pattern);
}
for (var k in pattern) {
if (~$.inArray(k, ['empty', 'error'])) {
$ele.attr('data-' + k, pattern[k]);
}
}
}
// 触发一次验证
if (nowTrigger) {
$ele.triggerHandler('change');
}
}
}
return this;
},
removeItem: function (name) {
var that = this;
if (name) {
that.removeRecheck(name);
that.removeDepend(name);
that.removeAjaxCheck(name);
that.removePattern(name);
that.removeIgnore(name);
that._setCheckItem(name, false);
if (name in that.checkItem) {
delete that.checkItem[name];
}
}
return that;
},
isIgnore: function (name) {
return !!(this._getEle(name).is('[ignore]') || ~$.inArray(this.conf.ignore, name));
},
/**
* 获取表单或元素的验证状态
* @param {[string|htmlElment]} name [元素的name值或表单元素或控件元素]
* @return {[boolean]} [验证状态,不在验证范围的都直接返回true]
*/
getStatus: function (name) {
if (typeof name === 'string') {
return name in this.checkItem ? !!this.checkItem[name] : true;
} else {
if (typeof name === 'object') {
// 获取表单验证状态
if (name.tagName === 'form') {
return this._getFormStatus();
} else {
// 表单元素
return name.name in this.checkItem ? !!this.checkItem[name.name] : true;
}
}
}
return true;
},
errorTip: function (msg, name) {
var that = this;
var conf = that.conf;
var $ele = that._getEle(name);
if (!$ele.length) {
$ele = name;
}
if (name && $ele.length) {
if (!conf.showAllError && that._showAllErrorFlag) {
return that;
}
if (!~$.inArray($ele.attr('type'), ['radio', 'checkbox'])) {
$ele.addClass('validator-error')
.removeClass('validator-success');
}
that._showAllErrorFlag = true;
// 依赖于此元素状态的项要设为false
if (name in that.beDependItem) {
for (var k in that.beDependItem[name]) {
that._setCheckItem(k, false);
}
}
that.checkItem[$ele.attr('name')] = false;
that._checkAfter(false, $ele, that.$form);
}
// 无法获取错误信息时
if (!msg && name) {
msg = '字段' + name + '验证错误';
}
// 当表单异步提交callback调用中如果结果出现错误时可能需要直接调用错误提示方法
if (typeof conf.errorTip === 'function') {
conf.errorTip.apply(that, [msg, $ele, that.$form]);
} else {
console.log('默认失败提示:' + msg)
}
return that;
},
successTip: function ($ele, $form) {
var conf = this.conf;
if (!~$.inArray($ele.attr('type'), ['radio', 'checkbox'])) {
$ele.removeClass('validator-error')
.addClass('validator-success');
}
if (conf.showSuccessTip) {
if (typeof conf.successTip === 'function') {
conf.successTip.apply(this, arguments);
} else {
console.log('默认成功提示:验证成功')
}
}
this.checkItem[$ele.attr('name')] = true;
this._checkAfter(true, $ele, $form);
return this;
}
}
form.each(function () {
this.validator = new Valid(this, conf);
// form表单上挂载实例
$(this).data('validator', this.validator);
});
return form;
}
}(jQuery));