/* 通用表单验证方法 validform version 5.3.2 by sean during april 7, 2010 - march 26, 2013 for more information, please visit http://validform.rjboy.cn validform is available under the terms of the mit license. demo: $(".demoform").validform({//$(".demoform")指明是哪一表单需要验证,名称需加在form表单上; btnsubmit:"#btn_sub", //#btn_sub是该表单下要绑定点击提交表单事件的按钮;如果form内含有submit按钮该参数可省略; btnreset:".btn_reset",//可选项 .btn_reset是该表单下要绑定点击重置表单事件的按钮; tiptype:1, //可选项 1=>pop box,2=>side tip(parent.next.find; with default pop),3=>side tip(siblings; with default pop),4=>side tip(siblings; none pop),默认为1,也可以传入一个function函数,自定义提示信息的显示方式(可以实现你想要的任何效果,具体参见demo页); ignorehidden:false,//可选项 true | false 默认为false,当为true时对:hidden的表单元素将不做验证; dragonfly:false,//可选项 true | false 默认false,当为true时,值为空时不做验证; tipsweep:true,//可选项 true | false 默认为false,只在表单提交时触发检测,blur事件将不会触发检测(实时验证会在后台进行,不会显示检测结果); label:".label",//可选项 选择符,在没有绑定nullmsg时查找要显示的提示文字,默认查找".validform_label"下的文字; showallerror:false,//可选项 true | false,true:提交表单时所有错误提示信息都会显示,false:一碰到验证不通过的就停止检测后面的元素,只显示该元素的错误信息; postonce:true, //可选项 表单是否只能提交一次,true开启,不填则默认关闭; ajaxpost:true, //使用ajax方式提交表单数据,默认false,提交地址就是action指定地址; datatype:{//传入自定义datatype类型,可以是正则,也可以是函数(函数内会传入一个参数); "*6-20": /^[^\s]{6,20}$/, "z2-4" : /^[\u4e00-\u9fa5\uf900-\ufa2d]{2,4}$/, "username":function(gets,obj,curform,regxp){ //参数gets是获取到的表单元素值,obj为当前表单元素,curform为当前验证的表单,regxp为内置的一些正则表达式的引用; var reg1=/^[\w\.]{4,16}$/, reg2=/^[\u4e00-\u9fa5\uf900-\ufa2d]{2,8}$/; if(reg1.test(gets)){return true;} if(reg2.test(gets)){return true;} return false; //注意return可以返回true 或 false 或 字符串文字,true表示验证通过,返回字符串表示验证失败,字符串作为错误提示显示,返回false则用errmsg或默认的错误提示; }, "phone":function(){ // 5.0 版本之后,要实现二选一的验证效果,datatype 的名称 不 需要以 "option_" 开头; } }, useplugin:{ swfupload:{}, datepicker:{}, passwordstrength:{}, jqtransform:{ selector:"select,input" } }, beforecheck:function(curform){ //在表单提交执行验证之前执行的函数,curform参数是当前表单对象。 //这里明确return false的话将不会继续执行验证操作; }, beforesubmit:function(curform){ //在验证成功后,表单提交前执行的函数,curform参数是当前表单对象。 //这里明确return false的话表单将不会提交; }, callback:function(data){ //返回数据data是json格式,{"info":"demo info","status":"y"} //info: 输出提示信息; //status: 返回提交数据的状态,是否提交成功。如可以用"y"表示提交成功,"n"表示提交失败,在ajax_post.php文件返回数据里自定字符,主要用在callback函数里根据该值执行相应的回调操作; //你也可以在ajax_post.php文件返回更多信息在这里获取,进行相应操作; //ajax遇到服务端错误时也会执行回调,这时的data是{ status:**, statustext:**, readystate:**, responsetext:** }; //这里执行回调操作; //注意:如果不是ajax方式提交表单,传入callback,这时data参数是当前表单对象,回调函数会在表单验证全部通过后执行,然后判断是否提交表单,如果callback里明确return false,则表单不会提交,如果return true或没有return,则会提交表单。 } }); validform对象的方法和属性: tipmsg:自定义提示信息,通过修改validform对象的这个属性值来让同一个页面的不同表单使用不同的提示文字; datatype:获取内置的一些正则; eq(n):获取validform对象的第n个元素; ajaxpost(flag,sync,url):以ajax方式提交表单。flag为true时,跳过验证直接提交,sync为true时将以同步的方式进行ajax提交,传入了url地址时,表单会提交到这个地址; abort():终止ajax的提交; submitform(flag,url):以参数里设置的方式提交表单,flag为true时,跳过验证直接提交,传入了url地址时,表单会提交到这个地址; resetform():重置表单; resetstatus():重置表单的提交状态。传入了postonce参数的话,表单成功提交后状态会设置为"posted",重置提交状态可以让表单继续可以提交; getstatus():获取表单的提交状态,normal:未提交,posting:正在提交,posted:已成功提交过; setstatus(status):设置表单的提交状态,可以设置normal,posting,posted三种状态,不传参则设置状态为posting,这个状态表单可以验证,但不能提交; ignore(selector):忽略对所选择对象的验证; unignore(selector):将ignore方法所忽略验证的对象重新获取验证效果; addrule(rule):可以通过validform对象的这个方法来给表单元素绑定验证规则; check(bool,selector):对指定对象进行验证(默认验证当前整个表单),通过返回true,否则返回false(绑定实时验证的对象,格式符合要求时返回true,而不会等ajax的返回结果),bool为true时则只验证不显示提示信息; config(setup):可以通过这个方法来修改初始化参数,指定表单的提交地址,给表单ajax和实时验证的ajax里设置参数; */ (function ($, win, undef) { var errorobj = null, //指示当前验证失败的表单元素; msgobj = null, //pop box object msghidden = true; //msgbox hidden? var tipmsg = {//默认提示文字; tit: "提示信息", w: { "*": "不能为空!", "*6-16": "请填写6到16位任意字符!", "*18": "请填写18位身份证!", "n": "请填写数字!", "n6-16": "请填写6到16位数字!", "s": "不能输入特殊字符!", "s6-18": "请填写6到18位字符!", "ss6-18": "请填写6到18位字符不能输入中文!", "p": "请填写邮政编码!", "m": "请填写手机号码!", "e": "邮箱地址格式不对!", "url": "请填写网址!" }, def: "请填写正确信息!", undef: "datatype未定义!", reck: "两次输入的内容不一致!", r: "", //r: "通过信息验证!", c: "正在检测信息…", s: "请{填写|选择}{0|信息}!", v: "所填信息没有经过验证,请稍后…", p: "正在提交数据…" } $.tipmsg = tipmsg; var validform = function (forms, settings, inited) { var settings = $.extend({}, validform.defaults, settings); settings.datatype && $.extend(validform.util.datatype, settings.datatype); var brothers = this; brothers.tipmsg = { w: {} }; brothers.forms = forms; brothers.objects = []; //创建子对象时不再绑定事件; if (inited === true) { return false; } forms.each(function () { //已经绑定事件时跳过,避免事件重复绑定; if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; var curform = this; curform.settings = $.extend({}, settings); var $this = $(curform); //防止表单按钮双击提交两次; curform.validform_status = "normal"; //normal | posting | posted; //让每个validform对象都能自定义tipmsg; $this.data("tipmsg", brothers.tipmsg); //bind the blur event; $this.delegate("[datatype]", "blur", function () { //判断是否是在提交表单操作时触发的验证请求; var subpost = arguments[1]; validform.util.check.call(this, $this, subpost); }); $this.delegate(":text", "keypress", function (event) { if (event.keycode == 13 && $this.find(":submit").length == 0) { $this.submit(); } }); //点击表单元素,默认文字消失效果; //表单元素值比较时的信息提示增强; //radio、checkbox提示信息增强; //外调插件初始化; validform.util.enhance.call($this, curform.settings.tiptype, curform.settings.useplugin, curform.settings.tipsweep); curform.settings.btnsubmit && $this.find(curform.settings.btnsubmit).bind("click", function () { $this.trigger("submit"); return false; }); $this.submit(function () { var subflag = validform.util.submitform.call($this, curform.settings); subflag === undef && (subflag = true); if (subflag) { var button = $("#" + curform.id).find("input[type='submit']").last(); if (button.hasclass("posting") === true) { return false; } button.addclass("posting"); button.val("数据保存中..."); } return subflag; }); $this.find("[type='reset']").add($this.find(curform.settings.btnreset)).bind("click", function () { validform.util.resetform.call($this); }); }); //预创建pop box; if (settings.tiptype == 1 || (settings.tiptype == 2 || settings.tiptype == 3) && settings.ajaxpost) { creatmsgbox(); } } validform.defaults = { tiptype: 1, tipsweep: false, showallerror: false, postonce: false, ajaxpost: false } validform.util = { datatype: { "*": /[\w\w]+/, "*6-16": /^[\w\w]{6,16}$/, "n": /^\d+$/, "*18": /^(\d+){18}/, "n6-16": /^\d{6,16}$/, "s": /^[\u4e00-\u9fa5\uf900-\ufa2d\w\.\s]+$/, "s6-18": /^[\u4e00-\u9fa5\uf900-\ufa2d\w\.\s]{6,18}$/, "p": /^[0-9]{6}$/, "m": /^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|16[0-9]{9}$|17[0-9]{9}$|18[0-9]{9}$|19[0-9]{9}$/, "e": /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/, "url": /^(\w+:\/\/)?\w+(\.\w+)+.*$/, "ss6-18": /^[\a-za-z\d]{6,18}$/ }, tostring: object.prototype.tostring, isempty: function (val) { return val === "" || val === $.trim(this.attr("tip")); }, getvalue: function (obj) { var inputval, curform = this; if (obj.is(":radio")) { inputval = curform.find(":radio[name='" + obj.attr("name") + "']:checked").val(); inputval = inputval === undef ? "" : inputval; } else if (obj.is(":checkbox")) { inputval = ""; curform.find(":checkbox[name='" + obj.attr("name") + "']:checked").each(function () { inputval += $(this).val() + ','; }) inputval = inputval === undef ? "" : inputval; } else { inputval = obj.val(); } inputval = $.trim(inputval); return validform.util.isempty.call(obj, inputval) ? "" : inputval; }, enhance: function (tiptype, useplugin, tipsweep, addrule) { var curform = this; //页面上不存在提示信息的标签时,自动创建; curform.find("[datatype]").each(function () { if (tiptype == 2) { if ($(this).parent().next().find(".validform_checktip").length == 0) { $(this).parent().next().append(""); $(this).siblings(".validform_checktip").remove(); } } else if (tiptype == 3 || tiptype == 4) { if ($(this).siblings(".validform_checktip").length == 0) { $(this).parent().append(""); $(this).parent().next().find(".validform_checktip").remove(); } } }) //表单元素值比较时的信息提示增强; curform.find("input[recheck]").each(function () { //已经绑定事件时跳过; if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; var _this = $(this); var recheckinput = curform.find("input[name='" + $(this).attr("recheck") + "']"); recheckinput.bind("keyup", function () { if (recheckinput.val() == _this.val() && recheckinput.val() != "") { if (recheckinput.attr("tip")) { if (recheckinput.attr("tip") == recheckinput.val()) { return false; } } _this.trigger("blur"); } }).bind("blur", function () { if (recheckinput.val() != _this.val() && _this.val() != "") { if (_this.attr("tip")) { if (_this.attr("tip") == _this.val()) { return false; } } _this.trigger("blur"); } }); }); //hasdefaulttext; curform.find("[tip]").each(function () {//tip是表单元素的默认提示信息,这是点击清空效果; //已经绑定事件时跳过; if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; var defaultvalue = $(this).attr("tip"); var altercss = $(this).attr("altercss"); $(this).focus(function () { if ($(this).val() == defaultvalue) { $(this).val(''); if (altercss) { $(this).removeclass(altercss); } } }).blur(function () { if ($.trim($(this).val()) === '') { $(this).val(defaultvalue); if (altercss) { $(this).addclass(altercss); } } }); }); //enhance info feedback for checkbox & radio; curform.find(":checkbox[datatype],:radio[datatype]").each(function () { //已经绑定事件时跳过; if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; var _this = $(this); var name = _this.attr("name"); curform.find("[name='" + name + "']").filter(":checkbox,:radio").bind("click", function () { //避免多个事件绑定时的取值滞后问题; settimeout(function () { _this.trigger("blur"); }, 0); }); }); //select multiple; curform.find("select[datatype][multiple]").bind("click", function () { var _this = $(this); settimeout(function () { _this.trigger("blur"); }, 0); }); //plugins here to start; validform.util.useplugin.call(curform, useplugin, tiptype, tipsweep, addrule); }, useplugin: function (plugin, tiptype, tipsweep, addrule) { /* plugin:settings.useplugin; tiptype:settings.tiptype; tipsweep:settings.tipsweep; addrule:是否在addrule时触发; */ var curform = this, plugin = plugin || {}; //swfupload; if (curform.find("input[plugin='swfupload']").length && typeof (swfuploadhandler) != "undefined") { var custom = { custom_settings: { form: curform, showmsg: function (msg, type, obj) { validform.util.showmsg.call(curform, msg, tiptype, { obj: curform.find("input[plugin='swfupload']"), type: type, sweep: tipsweep }); } } }; custom = $.extend(true, {}, plugin.swfupload, custom); curform.find("input[plugin='swfupload']").each(function (n) { if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; $(this).val(""); swfuploadhandler.init(custom, n); }); } //datepicker; if (curform.find("input[plugin='datepicker']").length && $.fn.datepicker) { plugin.datepicker = plugin.datepicker || {}; if (plugin.datepicker.format) { date.format = plugin.datepicker.format; delete plugin.datepicker.format; } if (plugin.datepicker.firstdayofweek) { date.firstdayofweek = plugin.datepicker.firstdayofweek; delete plugin.datepicker.firstdayofweek; } curform.find("input[plugin='datepicker']").each(function (n) { if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; plugin.datepicker.callback && $(this).bind("dateselected", function () { var d = new date($.event._dpcache[this._dpid].getselected()[0]).asstring(date.format); plugin.datepicker.callback(d, this); }); $(this).datepicker(plugin.datepicker); }); } //passwordstrength; if (curform.find("input[plugin*='passwordstrength']").length && $.fn.passwordstrength) { plugin.passwordstrength = plugin.passwordstrength || {}; plugin.passwordstrength.showmsg = function (obj, msg, type) { validform.util.showmsg.call(curform, msg, tiptype, { obj: obj, type: type, sweep: tipsweep }); }; curform.find("input[plugin='passwordstrength']").each(function (n) { if (this.validform_inited == "inited") { return true; } this.validform_inited = "inited"; $(this).passwordstrength(plugin.passwordstrength); }); } //jqtransform; if (addrule != "addrule" && plugin.jqtransform && $.fn.jqtransselect) { if (curform[0].jqtransselected == "true") { return; }; curform[0].jqtransselected = "true"; var jqtransformhideselect = function (otarget) { var ulvisible = $('.jqtransformselectwrapper ul:visible'); ulvisible.each(function () { var oselect = $(this).parents(".jqtransformselectwrapper:first").find("select").get(0); //do not hide if click on the label object associated to the select if (!(otarget && oselect.olabel && oselect.olabel.get(0) == otarget.get(0))) { $(this).hide(); } }); }; /* check for an external click */ var jqtransformcheckexternalclick = function (event) { if ($(event.target).parents('.jqtransformselectwrapper').length === 0) { jqtransformhideselect($(event.target)); } }; var jqtransformadddocumentlistener = function () { $(document).mousedown(jqtransformcheckexternalclick); }; if (plugin.jqtransform.selector) { curform.find(plugin.jqtransform.selector).filter('input:submit, input:reset, input[type="button"]').jqtransinputbutton(); curform.find(plugin.jqtransform.selector).filter('input:text, input:password').jqtransinputtext(); curform.find(plugin.jqtransform.selector).filter('input:checkbox').jqtranscheckbox(); curform.find(plugin.jqtransform.selector).filter('input:radio').jqtransradio(); curform.find(plugin.jqtransform.selector).filter('textarea').jqtranstextarea(); if (curform.find(plugin.jqtransform.selector).filter("select").length > 0) { curform.find(plugin.jqtransform.selector).filter("select").jqtransselect(); jqtransformadddocumentlistener(); } } else { curform.jqtransform(); } curform.find(".jqtransformselectwrapper").find("li a").click(function () { $(this).parents(".jqtransformselectwrapper").find("select").trigger("blur"); }); } }, getnullmsg: function (curform) { var obj = this; var reg = /[\u4e00-\u9fa5\uf900-\ufa2da-za-z\s]+/g; var nullmsg; var label = curform[0].settings.label || ".validform_label"; label = obj.siblings(label).eq(0).text() || obj.siblings().find(label).eq(0).text() || obj.parent().siblings(label).eq(0).text() || obj.parent().siblings().find(label).eq(0).text(); label = label.replace(/\s(?![a-za-z])/g, "").match(reg); label = label ? label.join("") : [""]; reg = /\{(.+)\|(.+)\}/; nullmsg = curform.data("tipmsg").s || tipmsg.s; if (label != "") { nullmsg = nullmsg.replace(/\{0\|(.+)\}/, label); if (obj.attr("recheck")) { nullmsg = nullmsg.replace(/\{(.+)\}/, ""); obj.attr("nullmsg", nullmsg); return nullmsg; } } else { nullmsg = obj.is(":checkbox,:radio,select") ? nullmsg.replace(/\{0\|(.+)\}/, "") : nullmsg.replace(/\{0\|(.+)\}/, "$1"); } nullmsg = obj.is(":checkbox,:radio,select") ? nullmsg.replace(reg, "$2") : nullmsg.replace(reg, "$1"); obj.attr("nullmsg", nullmsg); return nullmsg; }, geterrormsg: function (curform, datatype, recheck) { var regxp = /^(.+?)((\d+)-(\d+))?$/, regxp2 = /^(.+?)(\d+)-(\d+)$/, regxp3 = /(.*?)\d+(.+?)\d+(.*)/, mac = datatype.match(regxp), temp, str; //如果是值不一样而报错; if (recheck == "recheck") { str = curform.data("tipmsg").reck || tipmsg.reck; return str; } var tipmsg_w_ex = $.extend({}, tipmsg.w, curform.data("tipmsg").w); //如果原来就有,直接显示该项的提示信息; if (mac[0] in tipmsg_w_ex) { return curform.data("tipmsg").w[mac[0]] || tipmsg.w[mac[0]]; } //没有的话在提示对象里查找相似; for (var name in tipmsg_w_ex) { if (name.indexof(mac[1]) != -1 && regxp2.test(name)) { str = (curform.data("tipmsg").w[name] || tipmsg.w[name]).replace(regxp3, "$1" + mac[3] + "$2" + mac[4] + "$3"); curform.data("tipmsg").w[mac[0]] = str; return str; } } return curform.data("tipmsg").def || tipmsg.def; }, _regcheck: function (datatype, gets, obj, curform) { var curform = curform, info = null, passed = false, reg = /\/.+\//g, regex = /^(.+?)(\d+)-(\d+)$/, type = 3; //default set to wrong type, 2,3,4; //datatype有三种情况:正则,函数和直接绑定的正则; //直接是正则; if (reg.test(datatype)) { var regstr = datatype.match(reg)[0].slice(1, -1); var param = datatype.replace(reg, ""); var rexp = regexp(regstr, param); passed = rexp.test(gets); //function; } else if (validform.util.tostring.call(validform.util.datatype[datatype]) == "[object function]") { passed = validform.util.datatype[datatype](gets, obj, curform, validform.util.datatype); if (passed === true || passed === undef) { passed = true; } else { info = passed; passed = false; } //自定义正则; } else { //自动扩展datatype; if (!(datatype in validform.util.datatype)) { var mac = datatype.match(regex), temp; if (!mac) { passed = false; info = curform.data("tipmsg").undef || tipmsg.undef; } else { for (var name in validform.util.datatype) { temp = name.match(regex); if (!temp) { continue; } if (mac[1] === temp[1]) { var str = validform.util.datatype[name].tostring(), param = str.match(/\/[mgi]*/g)[1].replace("\/", ""), regxp = new regexp("\\{" + temp[2] + "," + temp[3] + "\\}", "g"); str = str.replace(/\/[mgi]*/g, "\/").replace(regxp, "{" + mac[2] + "," + mac[3] + "}").replace(/^\//, "").replace(/\/$/, ""); validform.util.datatype[datatype] = new regexp(str, param); break; } } } } if (validform.util.tostring.call(validform.util.datatype[datatype]) == "[object regexp]") { passed = validform.util.datatype[datatype].test(gets); } } if (passed) { type = 2; info = obj.attr("sucmsg") || curform.data("tipmsg").r || tipmsg.r; //规则验证通过后,还需要对绑定recheck的对象进行值比较; if (obj.attr("recheck")) { var theother = curform.find("input[name='" + obj.attr("recheck") + "']:first"); if (gets != theother.val()) { passed = false; type = 3; info = obj.attr("errormsg") || validform.util.geterrormsg.call(obj, curform, datatype, "recheck"); } } } else { info = info || obj.attr("errormsg") || validform.util.geterrormsg.call(obj, curform, datatype); //验证不通过且为空时; if (validform.util.isempty.call(obj, gets)) { info = obj.attr("nullmsg") || validform.util.getnullmsg.call(obj, curform); } } return { passed: passed, type: type, info: info }; }, regcheck: function (datatype, gets, obj) { /* datatype:datatype; gets:inputvalue; obj:input object; */ var curform = this, info = null, passed = false, type = 3; //default set to wrong type, 2,3,4; //ignore; if (obj.attr("ignore") === "ignore" && validform.util.isempty.call(obj, gets)) { if (obj.data("cked")) { info = ""; } return { passed: true, type: 4, info: info }; } obj.data("cked", "cked"); //do nothing if is the first time validation triggered; var dtype = validform.util.parsedatatype(datatype); var res; for (var eithor = 0; eithor < dtype.length; eithor++) { for (var dtp = 0; dtp < dtype[eithor].length; dtp++) { res = validform.util._regcheck(dtype[eithor][dtp], gets, obj, curform); if (!res.passed) { break; } } if (res.passed) { break; } } return res; }, parsedatatype: function (datatype) { /* 字符串里面只能含有一个正则表达式; datatype名称必须是字母,数字、下划线或*号组成; datatype="/regexp/|phone|tel,s,e|f,e"; ==>[["/regexp/"],["phone"],["tel","s","e"],["f","e"]]; */ var reg = /\/.+?\/[mgi]*(?=(,|$|\||\s))|[\w\*-]+/g, dtype = datatype.match(reg), sepor = datatype.replace(reg, "").replace(/\s*/g, "").split(""), arr = [], m = 0; arr[0] = []; arr[0].push(dtype[0]); for (var n = 0; n < sepor.length; n++) { if (sepor[n] == "|") { m++; arr[m] = []; } arr[m].push(dtype[n + 1]); } return arr; }, showmsg: function (msg, type, o, triggered) { /* msg:提示文字; type:提示信息显示方式; o:{obj:当前对象, type:1=>正在检测 | 2=>通过, sweep:true | false}, triggered:在blur或提交表单触发的验证中,有些情况不需要显示提示文字,如自定义弹出提示框的显示方式,不需要每次blur时就马上弹出提示; tiptype:1\2\3时都有坑能会弹出自定义提示框 tiptype:1时在triggered bycheck时不弹框 tiptype:2\3时在ajax时弹框 tipsweep为true时在triggered bycheck时不触发showmsg,但ajax出错的情况下要提示 */ //如果msg为undefined,那么就没必要执行后面的操作,ignore有可能会出现这情况; if (msg == undef) { return; } //tipsweep为true,且当前不是处于错误状态时,blur事件不触发信息显示; if (triggered == "bycheck" && o.sweep && (o.obj && !o.obj.is(".validform_error") || typeof type == "function")) { return; } $.extend(o, { curform: this }); if (typeof type == "function") { type(msg, o, validform.util.cssctl); return; } if (type == 1 || triggered == "byajax" && type != 4) { msgobj.find(".validform_info").html(msg); } //tiptypt=1时,blur触发showmsg,验证是否通过都不弹框,提交表单触发的话,只要验证出错,就弹框; if (type == 1 && triggered != "bycheck" && o.type != 2 || triggered == "byajax" && type != 4) { msghidden = false; msgobj.find(".iframe").css("height", msgobj.outerheight()); msgobj.show(); setcenter(msgobj, 100); } if (type == 2 && o.obj) { o.obj.parent().next().find(".validform_checktip").html(msg); validform.util.cssctl(o.obj.parent().next().find(".validform_checktip"), o.type); } if ((type == 3 || type == 4) && o.obj) { o.obj.siblings(".validform_checktip").html(msg); validform.util.cssctl(o.obj.siblings(".validform_checktip"), o.type); } }, cssctl: function (obj, status) { switch (status) { case 1: obj.removeclass("validform_right validform_wrong").addclass("validform_checktip validform_loading"); //checking; break; case 2: obj.removeclass("validform_wrong validform_loading").addclass("validform_checktip validform_right"); //passed; break; case 4: obj.removeclass("validform_right validform_wrong validform_loading").addclass("validform_checktip"); //for ignore; break; default: obj.removeclass("validform_right validform_loading").addclass("validform_checktip validform_wrong"); //wrong; } }, check: function (curform, subpost, bool) { /* 检测单个表单元素; 验证通过返回true,否则返回false、实时验证返回值为ajax; bool,传入true则只检测不显示提示信息; */ var settings = curform[0].settings; var subpost = subpost || ""; var inputval = validform.util.getvalue.call(curform, $(this)); //隐藏或绑定dataignore的表单对象不做验证; if (settings.ignorehidden && $(this).is(":hidden") || $(this).data("dataignore") === "dataignore") { return true; } //dragonfly=true时,没有绑定ignore,值为空不做验证,但验证不通过; if (settings.dragonfly && !$(this).data("cked") && validform.util.isempty.call($(this), inputval) && $(this).attr("ignore") != "ignore") { return false; } var flag = validform.util.regcheck.call(curform, $(this).attr("datatype"), inputval, $(this)); //值没变化不做检测,这时要考虑recheck情况; //不是在提交表单时触发的ajax验证; //if (inputval == this.validform_lastval && !$(this).attr("recheck") && subpost == "") { // return flag.passed ? true : false; //} this.validform_lastval = inputval; //存储当前值; var _this; errorobj = _this = $(this); if (!flag.passed) { //取消正在进行的ajax验证; validform.util.abort.call(_this[0]); if (!bool) { //传入"bycheck",指示当前是check方法里调用的,当tiptype=1时,blur事件不让触发错误信息显示; validform.util.showmsg.call(curform, flag.info, settings.tiptype, { obj: $(this), type: flag.type, sweep: settings.tipsweep }, "bycheck"); !settings.tipsweep && _this.addclass("validform_error"); } return false; } //验证通过的话,如果绑定有ajaxurl,要执行ajax检测; //当ignore="ignore"时,为空值可以通过验证,这时不需要ajax检测; var ajaxurl = $(this).attr("ajaxurl"); //alert(ajaxurl); if (ajaxurl && !validform.util.isempty.call($(this), inputval) && !bool) { var inputobj = $(this); //当提交表单时,表单中的某项已经在执行ajax检测,这时需要让该项ajax结束后继续提交表单; //alert(subpost); if (subpost == "postform") { inputobj[0].validform_subpost = "postform"; } else { inputobj[0].validform_subpost = ""; } if (inputobj[0].validform_valid === "posting" && inputval == inputobj[0].validform_ckvalue) { return "ajax"; } inputobj[0].validform_valid = "posting"; inputobj[0].validform_ckvalue = inputval; validform.util.showmsg.call(curform, curform.data("tipmsg").c || tipmsg.c, settings.tiptype, { obj: inputobj, type: 1, sweep: settings.tipsweep }, "bycheck"); validform.util.abort.call(_this[0]); var ajaxsetup = $.extend(true, {}, settings.ajaxurl || {}); var localconfig = { type: "get", cache: false, url: ajaxurl, data: "param=" + encodeuricomponent(inputval) + "&name=" + encodeuricomponent($(this).attr("name")), success: function (data) { if ($.trim(data.status) === "y") { inputobj[0].validform_valid = "true"; data.info && inputobj.attr("sucmsg", data.info); validform.util.showmsg.call(curform, inputobj.attr("sucmsg") || curform.data("tipmsg").r || tipmsg.r, settings.tiptype, { obj: inputobj, type: 2, sweep: settings.tipsweep }, "bycheck"); _this.removeclass("validform_error"); errorobj = null; //前端 if (inputobj[0].validform_subpost == "postform") { curform.trigger("submit"); } } else { inputobj[0].validform_valid = data.info; validform.util.showmsg.call(curform, data.info, settings.tiptype, { obj: inputobj, type: 3, sweep: settings.tipsweep }); _this.addclass("validform_error"); } _this[0].validform_ajax = null; }, error: function (data) { if (data.status == "200") { if (data.responsetext == "y") { ajaxsetup.success({ "status": "y" }); } else { ajaxsetup.success({ "status": "n", "info": data.responsetext }); } return false; } //正在检测时,要检测的数据发生改变,这时要终止当前的ajax。不是这种情况引起的ajax错误,那么显示相关错误信息; if (data.statustext !== "abort") { var msg = "status: " + data.status + "; statustext: " + data.statustext; validform.util.showmsg.call(curform, msg, settings.tiptype, { obj: inputobj, type: 3, sweep: settings.tipsweep }); _this.addclass("validform_error"); } inputobj[0].validform_valid = data.statustext; _this[0].validform_ajax = null; //localconfig.error返回true表示还需要执行temp_err; return true; } } if (ajaxsetup.success) { var temp_suc = ajaxsetup.success; ajaxsetup.success = function (data) { localconfig.success(data); temp_suc(data, inputobj); } } if (ajaxsetup.error) { var temp_err = ajaxsetup.error; ajaxsetup.error = function (data) { //localconfig.error返回false表示不需要执行temp_err; localconfig.error(data) && temp_err(data, inputobj); } } ajaxsetup = $.extend({}, localconfig, ajaxsetup, { datatype: "json" }); _this[0].validform_ajax = $.ajax(ajaxsetup); return "ajax"; } else if (ajaxurl && validform.util.isempty.call($(this), inputval)) { validform.util.abort.call(_this[0]); _this[0].validform_valid = "true"; } if (!bool) { validform.util.showmsg.call(curform, flag.info, settings.tiptype, { obj: $(this), type: flag.type, sweep: settings.tipsweep }, "bycheck"); _this.removeclass("validform_error"); } errorobj = null; return true; }, submitform: function (settings, flg, url, ajaxpost, sync) { /* flg===true时跳过验证直接提交; ajaxpost==="ajaxpost"指示当前表单以ajax方式提交; */ var curform = this; //表单正在提交时点击提交按钮不做反应; if (curform[0].validform_status === "posting") { return false; } //要求只能提交一次时; if (settings.postonce && curform[0].validform_status === "posted") { return false; } var beforecheck = settings.beforecheck && settings.beforecheck(curform); if (beforecheck === false) { return false; } var flag = true, inflag; curform.find("[datatype]").each(function () { //跳过验证; if (flg) { return false; } //隐藏或绑定dataignore的表单对象不做验证; if (settings.ignorehidden && $(this).is(":hidden") || $(this).data("dataignore") === "dataignore") { return true; } var inputval = validform.util.getvalue.call(curform, $(this)), _this; errorobj = _this = $(this); inflag = validform.util.regcheck.call(curform, $(this).attr("datatype"), inputval, $(this)); if (!inflag.passed) { validform.util.showmsg.call(curform, inflag.info, settings.tiptype, { obj: $(this), type: inflag.type, sweep: settings.tipsweep }); _this.addclass("validform_error"); if (!settings.showallerror) { _this.focus(); flag = false; return false; } flag && (flag = false); return true; } //当ignore="ignore"时,为空值可以通过验证,这时不需要ajax检测; if ($(this).attr("ajaxurl") && !validform.util.isempty.call($(this), inputval)) { if (this.validform_valid !== "true") { var thisobj = $(this); validform.util.showmsg.call(curform, curform.data("tipmsg").v || tipmsg.v, settings.tiptype, { obj: thisobj, type: 3, sweep: settings.tipsweep }); _this.addclass("validform_error"); thisobj.trigger("blur", ["postform"]); //continue the form post; if (!settings.showallerror) { flag = false; return false; } flag && (flag = false); return true; } } else if ($(this).attr("ajaxurl") && validform.util.isempty.call($(this), inputval)) { validform.util.abort.call(this); this.validform_valid = "true"; } validform.util.showmsg.call(curform, inflag.info, settings.tiptype, { obj: $(this), type: inflag.type, sweep: settings.tipsweep }); _this.removeclass("validform_error"); errorobj = null; }); if (settings.showallerror) { curform.find(".validform_error:first").focus(); } if (flag) { var beforesubmit = settings.beforesubmit && settings.beforesubmit(curform); if (beforesubmit === false) { return false; } curform[0].validform_status = "posting"; if (settings.ajaxpost || ajaxpost === "ajaxpost") { //获取配置参数; var ajaxsetup = $.extend(true, {}, settings.ajaxpost || {}); //有可能需要动态的改变提交地址,所以把action所指定的url层级设为最低; ajaxsetup.url = url || ajaxsetup.url || settings.url || curform.attr("action"); //byajax:ajax时,tiptye为1、2或3需要弹出提示框; validform.util.showmsg.call(curform, curform.data("tipmsg").p || tipmsg.p, settings.tiptype, { obj: curform, type: 1, sweep: settings.tipsweep }, "byajax"); //方法里的优先级要高; //有undefined情况; if (sync) { ajaxsetup.async = false; } else if (sync === false) { ajaxsetup.async = true; } if (ajaxsetup.success) { var temp_suc = ajaxsetup.success; ajaxsetup.success = function (data) { settings.callback && settings.callback(data); curform[0].validform_ajax = null; if ($.trim(data.status) === "y") { curform[0].validform_status = "posted"; } else { curform[0].validform_status = "normal"; } temp_suc(data, curform); } } if (ajaxsetup.error) { var temp_err = ajaxsetup.error; ajaxsetup.error = function (data) { settings.callback && settings.callback(data); curform[0].validform_status = "normal"; curform[0].validform_ajax = null; temp_err(data, curform); } } var localconfig = { type: "get", async: true, data: curform.serializearray(), success: function (data) { if ($.trim(data.status) === "y") { //成功提交; curform[0].validform_status = "posted"; validform.util.showmsg.call(curform, data.info, settings.tiptype, { obj: curform, type: 2, sweep: settings.tipsweep }, "byajax"); } else { //提交出错; curform[0].validform_status = "normal"; validform.util.showmsg.call(curform, data.info, settings.tiptype, { obj: curform, type: 3, sweep: settings.tipsweep }, "byajax"); } settings.callback && settings.callback(data); curform[0].validform_ajax = null; }, error: function (data) { var msg = "status: " + data.status + "; statustext: " + data.statustext; validform.util.showmsg.call(curform, msg, settings.tiptype, { obj: curform, type: 3, sweep: settings.tipsweep }, "byajax"); settings.callback && settings.callback(data); curform[0].validform_status = "normal"; curform[0].validform_ajax = null; } } ajaxsetup = $.extend({}, localconfig, ajaxsetup, { datatype: "json" }); curform[0].validform_ajax = $.ajax(ajaxsetup); } else { if (!settings.postonce) { curform[0].validform_status = "normal"; } var url = url || settings.url; if (url) { curform.attr("action", url); } return settings.callback && settings.callback(curform); } } return false; }, resetform: function () { var brothers = this; brothers.each(function () { this.reset && this.reset(); this.validform_status = "normal"; }); brothers.find(".validform_right").text(""); brothers.find(".passwordstrength").children().removeclass("bgstrength"); brothers.find(".validform_checktip").removeclass("validform_wrong validform_right validform_loading"); brothers.find(".validform_error").removeclass("validform_error"); brothers.find("[datatype]").removedata("cked").removedata("dataignore").each(function () { this.validform_lastval = null; }); brothers.eq(0).find("input:first").focus(); }, abort: function () { if (this.validform_ajax) { this.validform_ajax.abort(); } } } $.datatype = validform.util.datatype; validform.prototype = { datatype: validform.util.datatype, eq: function (n) { var obj = this; if (n >= obj.forms.length) { return null; } if (!(n in obj.objects)) { obj.objects[n] = new validform($(obj.forms[n]).get(), {}, true); } return obj.objects[n]; }, resetstatus: function () { var obj = this; $(obj.forms).each(function () { this.validform_status = "normal"; }); return this; }, setstatus: function (status) { var obj = this; $(obj.forms).each(function () { this.validform_status = status || "posting"; }); return this; }, getstatus: function () { var obj = this; var status = $(obj.forms)[0].validform_status; return status; }, ignore: function (selector) { var obj = this; var selector = selector || "[datatype]" $(obj.forms).find(selector).each(function () { $(this).data("dataignore", "dataignore").removeclass("validform_error"); }); return this; }, unignore: function (selector) { var obj = this; var selector = selector || "[datatype]" $(obj.forms).find(selector).each(function () { $(this).removedata("dataignore"); }); return this; }, addrule: function (rule) { /* rule => [{ ele:"#id", datatype:"*", errormsg:"出错提示文字!", nullmsg:"为空时的提示文字!", tip:"默认显示的提示文字", altercss:"gray", ignore:"ignore", ajaxurl:"valid.php", recheck:"password", plugin:"passwordstrength" },{},{},...] */ var obj = this; var rule = rule || []; for (var index = 0; index < rule.length; index++) { var o = $(obj.forms).find(rule[index].ele); for (var attr in rule[index]) { attr !== "ele" && o.attr(attr, rule[index][attr]); } } $(obj.forms).each(function () { var $this = $(this); validform.util.enhance.call($this, this.settings.tiptype, this.settings.useplugin, this.settings.tipsweep, "addrule"); }); return this; }, ajaxpost: function (flag, sync, url) { var obj = this; $(obj.forms).each(function () { //创建pop box; if (this.settings.tiptype == 1 || this.settings.tiptype == 2 || this.settings.tiptype == 3) { creatmsgbox(); } validform.util.submitform.call($(obj.forms[0]), this.settings, flag, url, "ajaxpost", sync); }); return this; }, submitform: function (flag, url) { /*flag===true时不做验证直接提交*/ var obj = this; $(obj.forms).each(function () { var subflag = validform.util.submitform.call($(this), this.settings, flag, url); subflag === undef && (subflag = true); if (subflag === true) { this.submit(); } }); return this; }, resetform: function () { var obj = this; validform.util.resetform.call($(obj.forms)); return this; }, abort: function () { var obj = this; $(obj.forms).each(function () { validform.util.abort.call(this); }); return this; }, check: function (bool, selector) { /* bool:传入true,只检测不显示提示信息; */ var selector = selector || "[datatype]", obj = this, curform = $(obj.forms), flag = true; curform.find(selector).each(function () { validform.util.check.call(this, curform, "", bool) || (flag = false); }); return flag; }, config: function (setup) { /* config={ url:"ajaxpost.php",//指定了url后,数据会提交到这个地址; ajaxurl:{ timeout:1000, ... }, ajaxpost:{ timeout:1000, ... } } */ var obj = this; setup = setup || {}; $(obj.forms).each(function () { var $this = $(this); this.settings = $.extend(true, this.settings, setup); validform.util.enhance.call($this, this.settings.tiptype, this.settings.useplugin, this.settings.tipsweep); }); return this; } } $.fn.validform = function (settings) { return new validform(this, settings); }; function setcenter(obj, time) { var left = ($(window).width() - obj.outerwidth()) / 2, top = ($(window).height() - obj.outerheight()) / 2, top = (document.documentelement.scrolltop ? document.documentelement.scrolltop : document.body.scrolltop) + (top > 0 ? top : 0); obj.css({ left: left }).animate({ top: top }, { duration: time, queue: false }); } function creatmsgbox() { if ($("#validform_msg").length !== 0) { return false; } msgobj = $('