打印

表单验证Validator3.0测试

本主题由 蓝色 于 2008-9-25 03:51 分割
本帖进行了分割以前的回帖请看 1~100,101~200
本来想等3.0的文档写完再发布的,既然现在顶上来,就先作个3.0的链接吧.Validator 2.0是个失败的作品,所以一直是beta版.酝酿了十几个月,根据这一年以来对表单验证处理方面的经验,重新写了3.0.3.0目前仍然是测试中,不过这并不影响正常使用,实际上,我已经应用在好几个项目中了,只是觉得有些东西还应该做得更好,因此一直没有正式发布.现在公开,目的是希望大家在测试中能提出好的建议

3.0测试演示地址:
http://www.wfsr.net/validator/index.html

3.0的构架已经完全改变,可配置性更高,不过不兼容1.x和2.0,但是只需要作少量修改就可以安全升级至3.0.
1.属性名.
3.0的属性名除id及name外,首字母全部改用大写,比如dataType改为DataType,require改为Require.另外,msg改为Message.
2.Validator.Setup
需要手动调用该方法,告诉程序当前页需要应用Validator的表单及相关设置,具体可参见演示.

to be continued...

表单的验证一直是网页设计者头痛的问题,表单验证类 Validator就是为解决这个问题而写的,旨在使设计者从纷繁复杂的表单验证中解放出来,把精力集中于网页的设计和功能上的改进上。
Validator是基于JavaScript技术的伪静态类和对象的自定义属性,可以对网页中的表单项输入进行相应的验证,允许同一页面中同时验证多个表单,熟悉接口之后也可以对特定的表单项甚至仅仅是某个字符串进行验证。因为是伪静态类,所以在调用时不需要实例化,直接以"类名+.语法+属性或方法名"来调用。此外,Validator还提供3种不同的错误提示模式,以满足不同的需要。

[JavaScript] 版
Validator目前可实现的验证类型有:
1.是否为空;
2.中文字符;
3.双字节字符
4.英文;
5.数字;
6.整数;
7.实数;
8.Email地址;
9.使用HTTP协议的网址;
10.电话号码;
11.货币;
12.手机号码;
13.邮政编码;
14.身份证号码(1.05增强);
15.QQ号码;
16.日期;
17.符合安全规则的密码;
18.某项的重复值;
19.两数的关系比较;
20.判断输入值是否在(n, m)区间;
21.输入字符长度限制(可按字节比较);
22.对于具有相同名称的单选按钮的选中判断;
23.限制具有相同名称的多选按钮的选中数目;
24.自定义的正则表达式验证;
25.文件上传格式过滤(1.04)
运行环境(客户端):
在Windows Server 2003下用IE6.0+SP1和Mozilla Firefox 1.0测试通过;
在Lunix RedHat 9下的Netscape测试通过;


对于客户端的表单验证,这个基于JavaScript编写的Validator基本上都可以满足,具体可以下载CHM文件:

Validator.CHM下载

示例:

 提示:您可以先修改部分代码再运行
更新历史:

1.01
修正对12月份的日期验证(感谢flylg999)

1.03
修正Range验证类型时将数字当字符串比较的bug(感谢cncomxtlhnhbb)
修正日期验证(感谢Papsam)
增加Username验证类型
增加对Phone验证类型时支持分机号

1.04
增加文件格式的过滤,用于上传时限制上传的文件格式

1.05
增强对身份证号码的验证


[PHP]版
复制内容到剪贴板
代码:
  <title>表单验证类 Validator for PHP β</title>
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overfmin:auto;}
form{display:inline}
</style>
<table align="center">
<form action="Validator.php" method="post">
  <tr>
   <td>提示模式:</td><td>
   <select name="emode">
   <option value="1">警告提示框(客户端)</option>
   <option value="2">提示框加红色文字提示</option>
   <option value="3">附加红色提示</option>
   <option value="4">警告提示框(服务器端)</option>
   <option value="5">文字提示(服务器端)</option>
   </select></td>
  </tr>
  <tr>
   <td>真实姓名:</td><td><input name="Name"></td>
  </tr>
  <tr>
   <td>英文名:</td><td><input name="Nick"></td>
  </tr>
    <tr>
   <td>主页:</td><td><input name="Homepage"></td>
  </tr>
  <tr>
   <td>密码:</td><td><input name="Password"></td>
  </tr>
  <tr>
   <td>重复:</td><td><input name="Repeat"></td>
  </tr>
  <tr>
   <td>信箱:</td><td><input name="Email"></td>
  </tr>
    <tr>
   <td>信箱:</td><td><input name="Email1"></td>
  </tr>
  <tr>
   <td>QQ:</td><td><input name="QQ"></td>
  </tr>
    <tr>
   <td>身份证:</td><td><input name="Card"></td>
  </tr>
  <tr>
   <td>年龄:</td><td><input name="Year"></td>
  </tr>
   <tr>
   <td>年龄1:</td><td><input name="Year1"></td>
  </tr>
   <tr>
   <td>电话:</td><td><input name="Phone"></td>
  </tr>
   <tr>
   <td>手机:</td><td><input name="Mobile"></td>
  </tr>
     <tr>
   <td>生日:</td><td><input name="Birthday"></td>
  </tr>
   <tr>
   <td>邮政编码:</td><td><input name="Zip"></td>
  </tr>
  <tr>
   <td>邮政编码:</td><td><input name="Zip1"></td>
  </tr>
  <tr>
   <td>操作系统:</td><td><select name="OS"><option value="">选择您所用的操作系统</option><option value="Win98">Win98</option><option value="Win2k">Win2k</option><option value="WinXP">WinXP</option></select></td>
  </tr>
  <tr>
   <td>所在省份:</td><td>广东<input name="Province" value="1" type="radio">陕西<input name="Province" value="2" type="radio">浙江<input name="Province" value="3" type="radio">江西<input name="Province" value="4" type="radio"></td>
  </tr>
  <tr>
   <td>爱好:</td><td>运动<input name="Favorite" value="1" type="checkbox">上网<input name="Favorite" value="2" type="checkbox">听音乐<input name="Favorite" value="3" type="checkbox">看书<input name="Favorite" value="4" type="checkbox"></td>
  </tr>
   <td>自我介绍:</td><td><textarea name="Description">中文是一个字</textarea></td>
  </tr>
     <td>自传:</td><td><textarea name="History">中文是两个字节t</textarea></td>
  </tr>
  <tr>
   <td colspan="2"><input name="Submit" type="submit" value="确定提交"></td>
  </tr>
  </form>
</table>
<script defer>
/*************************************************
    Validator for PHP  β 客户端脚本
    code by 我佛山人
    wfsr@cunite.com
    http://www.cunite.com
*************************************************/
function dispError(items, messages, mode, separator){
    var iArray = items.split(separator);
    for(var i=iArray.length-1;i>=0;i--)
        iArray[i] = getObj(iArray[i]);
    messages = ("以下原因导致提交失败:\t\t\t\t" + separator + messages).split(separator);
    switch(mode){
        case 2 :
            for(i=iArray.length-1;i>=0;i--)
                iArray[i].style.color = "red";
        case 1 :
            alert(messages.join("\n"));
            iArray[0].focus();
            break;
        case 3 :
            for(i=iArray.length-1;i>=0;i--){
                try{
                    var span = document.createElement("SPAN");
                    span.id = "__ErrorMessagePanel";
                    span.style.color = "red";
                    iArray[i].parentNode.appendChild(span);
                    span.innerHTML = messages[i+1].replace(/\d+:/,"*");
                }
                catch(e){alert(e.description);}
            }
            iArray[0].focus();
            break;
    }
}
function getObj(name){
    var objs = document.getElementsByName(name);
    return objs[objs.length -1];
}
</script>
<?php
class Validator{
/*************************************************
    Validator for PHP  β 服务器端脚本
    code by 我佛山人
    wfsr@cunite.com
    http://www.cunite.com
*************************************************/
    var $submit;
    var $error_item, $error_message, $error_mode, $error_no;
    function Validator($submit_name = "Submit", $mode = 5){
        $this->submit = $submit_name;
        $this->error_mode = $mode;
        $this->error_no = 1;
    }
    function Validate($arr){
        if(! isset($_POST[$this->submit])) return false;
        $this->error_mode = $_POST["emode"];
        echo "<script defer>document.getElementsByName(\"emode\")[0].selectedIndex =" . ($this->error_mode - 1) . "</script>";
        if(is_array($arr)){
            $len = count($arr);
            for($i = 0; $i < $len; $i++){
                $this->is_valid($arr[$i]);
            }
        }
        if($this->error_no > 1)    
            $this->display_error();
    }
    function is_valid($str){
        $str = split(",", $str);
        if(count($str) < 3) return false;
        $name = trim($str[0]);
        $message = trim($str[1]);
        $data_type = trim($str[2]);
        $value = trim($_POST[$name]);
        switch($data_type){
            case "compare" :
                break;
            case "range" :
                break;
            case "repeat" :
                break;
            default :
                $method = "is_".$data_type;
                if(!$this->$method($value))
                    $this->add_error($name, $message);
                break;
        }
    }
    function add_error($name, $message){
        $this->error_item .= "," . $name;
        $this->error_message .= "," . $this->error_no . ":" . $message;
        $this->error_no ++;
    }
    function display_error(){
        $this->error_item = ereg_replace("^,+", "", $this->error_item);
        $this->error_message = ereg_replace("^,+", "", $this->error_message);
        switch($this->error_mode){
            case 4 :
                $info = "以下原因导致提交失败:\t\t\t\t,";
                echo "<script>alert(\"".join("\\n", split(",", $info . $this->error_message))."\")</script>";
                //print >>>end;
                break;
            case 5 :
                echo "输入有错误:<br /><ul><li>" . ereg_replace( "\b\d+:", "",join("</li><li>", split(",", $this->error_message))) . "</li></ul>";
                echo "<br /><a href='javascript:history.back()'>返回</a>";
                exit;
                break;
            default :
                echo "<script defer>dispError(\"" . $this->error_item . "\", \"" . $this->error_message . "\", " . $this->error_mode . ", \",\")</script>";
            break;
        }
    }
    function is_email($str){
        return preg_match("/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/", $str);
    }
    function is_url($str){
        return preg_match("/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/", $str);
    }
    function is_qq($str){
        return preg_match("/^[1-9]\d{4,8}$/", $str);
    }
    function is_zip($str){
        return preg_match("/^[1-9]\d{5}$/", $str);
    }
    function is_idcard($str){
        return preg_match("/^\d{15}(\d{2}[A-Za-z0-9])?$/", $str);
    }
    function is_chinese($str){
        return ereg("^[".chr(0xa1)."-".chr(0xff)."]+$",$str);
    }
    function is_english($str){
        return preg_match("/^[A-Za-z]+$/", $str);
    }
    function is_mobile($str){
        return preg_match("/^((\(\d{3}\))|(\d{3}\-))?13\d{9}$/", $str);
    }
    function is_phone($str){
        return preg_match("/^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/", $str);
    }
    function is_safe($str){
        return (preg_match("/^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/", $str) != 0);
    }
}
$v = new Validator();
$v->Validate(array("Name,名字只允许中文,chinese", "Nick, 只允许英文昵称, english", "Homepage, 主页Url格式不正确, url", "Password, 密码不符合安全规则, safe","Email,信箱格式错误,email", "QQ, QQ号码不存在, qq","Card, 身份证号码不正确, idcard","Phone, 电话号码不存在, phone","Mobile, 手机号码不存在, mobile","Zip, 邮政编码不存在, zip"));
?>
[ASP]版
复制内容到剪贴板
代码:
<%
Class Validator
'*************************************************
'    Validator for ASP beta 2 服务器端脚本
'    code by 我佛山人
'    wfsr@cunite.com
'    http://www.cunite.com
'*************************************************
    Private Re, Dic
    Private Separator
    Private ErrorItem, ErrorMessage, ErrorMode, ErrorNo
    Private FormName, FormIndex, FilePath, GetMethod
    Private Sub Class_Initialize()
        Set Re = New RegExp
        Re.IgnoreCase = True
        Re.Global = True
        Set Dic = CreateObject("Scripting.Dictionary")
        Separator = ","
        ErrorItem = ""
        ErrorMessage = ""
        ErrorMode = 5
        ErrorNo = 1
        FilePath = Server.MapPath(Request.ServerVariables("Script_Name"))
        GetMethod = "FSO"
    End Sub
    Private Sub Class_Terminate()
        Set Re = Nothing
        Dic.RemoveAll()
        Set Dic = Nothing
    End Sub
    Public Sub Validate()
        IF Request("Submit")="" Then    Exit Sub
        IF Not IsValidPost() Then    Exit Sub
        With Dic
            .Add "Compare", "Compare( PostValue, operator, toObj)"
            .Add "Custom", "Custom( PostValue,regexp )"
            .Add "Date", "IsDateFormat( PostValue,format )"
            .Add "Limit", "Limit( PostValue,min, max )"
            .Add "LimitB", "LimitB( PostValue,min, max )"
            .Add "Range", "Range( PostValue,min, max )"
            .Add "Repeat", "IsEqual( PostValue, Request(toObj) )"
            .Add "Group", "Group( PostValue,min, max )"
            .Add "NotEqual", "Op1 <> Op2"
            .Add "GreaterThan", "Op1 > Op2"
            .Add "GreaterThanEqual", "Op1 >= Op2"
            .Add "LessThan", "Op1 < Op2"
            .Add "LessThanEqual", "Op1 <= Op2"
            .Add "Equal", "Op1 = Op2"
        End With
        Call MatchCode()
        IF ErrorMessage <> "" Then DisplayError
    End Sub
    Private Sub MatchCode()
        Dim bI, bG, bM
        Dim Str
        Select Case GetMethod
            Case "FSO" :
                Dim FSO : Set FSO = Server.CreateObject("Scripting.FileSystemObject")
                Set TS = FSO.OpenTextFile(FilePath, 1, false)
                Str = TS.ReadAll()
                TS.Close
                Set TS = Nothing
                Set FSO = Nothing
            Case "XMLHTTP" :
                Dim XHttp : Set XHttp = Server.CreateObject("MSXML2.XMLHTTP")
                With XHttp
                    Call .Open("Get", "http://"&Request.ServerVariables("Server_Name")&Request.ServerVariables("Script_Name"), False)
                    Call .Send()
                    Str =B2S(.responseBody)
                End With
                Set XHttp = Nothing
        End Select
        Dim itemString
        With Re
            bI = .IgnoreCase
            bG = .Global
            bM = .MultiLine
            .IgnoreCase = True
            .Global = True
            .Pattern = "[\s\S]*<form [^>]+>([\s\S]+)<\/form>[\s\S]*"
            Str = .Replace(Str, "$1")
            .Global = True
            .MultiLine = True
            .Pattern = "<\/?(?!input|textarea|select)[^>]*>"
            Str = .Replace(Str, "")
            .Pattern = "^.*(<(?=input|textarea|select)[^>]*>).*$"
            Str = .Replace(Str, "$1")
            .Pattern = "([\r\n]+|^\s*)(?=<)"
            Str = .Replace(Str, "")
            While Test("dataType=([""\'])([^""\'>]+)\1", Str)
                .MultiLine = False
                .Pattern = "^([^\n]+)\n([\s\S]*)$"
                itemString = .Replace(Str, "$1")
                Str = .Replace(Str, "$2")
                .Pattern = "(name|dataType|to1|min|max|msg|require|regexp|format)=([""\'])([^""\'>]+)\2"
                Dim Matches : Set Matches = .Execute(itemString)
                Dim Match, RetStr : RetStr = ""
                   For Each Match in Matches
                      RetStr = RetStr & Match.Value & " : "
                   Next
                Call IsValid(Replace(Replace(Replace(RetStr, " : $", ""), "to=", "toObj="), """Require""", """NotEmpty"""))
            Wend
            .IgnoreCase = bI
            .Global = bG
            .MultiLine = bM
        End With
    End Sub
    Private Sub IsValid(ByVal Str)
        Dim name, msg, dataType, toObj, min, max, require, regexp, format
        min = 1 : max = 100 : require = "true" : format = "YMD"
        Execute Str
        Dim PostValue : PostValue = Request(name)
        Dim Fun
        
        IF require = "false" AND PostValue = "" Then Exit Sub
        IF Dic.Exists(dataType) Then    
            Fun = Dic.Item(dataType)
        Else Fun = "Is" & dataType &"( PostValue )"
        End IF
        IF Not Eval(Fun) Then Call AddError(name,msg)
    End Sub
    Private Sub DisplayError()
        ErrorItem = Replace(ErrorItem, "^(" & Separator & ")", "")
        ErrorMessage = Replace(ErrorMessage, "^(" & Separator & ")", "")
        Select Case ErrorMode
            Case 4
                ErrorMessage = Join(Split(ErrorMessage, Separator), "</li><li>")
                Response.Clear
                Response.Write "<div style=""padding-left:100px;font:bold 12px Tahoma"">输入有错误:<br><ul><li>" & Replace(ErrorMessage, "\b\d+:", "") & "</li></ul>"
                Response.Write "<br><a href='javascript:history.back()'>返回重填</a></div>"
                Response.End
            Case Else
                Response.Write("<script defer>dispError(""" & ErrorItem & """, """ & ErrorMessage & """, " & ErrorMode & ", """ & Separator & """)</script>")
        End Select
    End Sub
    Public Function IsEmail(ByVal Str)
        IsEmail = Test("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", Str)
    End Function
    Public Function IsUrl(ByVal Str)
        IsUrl = Test("^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>""])*$", Str)
    End Function
    Public Function IsNum(ByVal Str)
        IsNum= Test("^\d+$", Str)
    End Function
    Public Function IsQQ(ByVal Str)
        IsQQ = Test("^[1-9]\d{4,8}$", Str)
    End Function
    Public Function IsZip(ByVal Str)
        IsZip = Test("^[1-9]\d{5}$", Str)
    End Function
    Public Function IsIdCard(ByVal Str)
        IsIdCard = Test("^\d{15}(\d{2}[A-Za-z0-9])?$", Str)
    End Function
    Public Function IsChinese(ByVal Str)
        IsChinese = Test("^[\u0391-\uFFE5]+$", Str)
    End Function
    Public Function IsEnglish(ByVal Str)
        IsEnglish = Test("^[A-Za-z]+$", Str)
    End Function
    Public Function IsMobile(ByVal Str)
        IsMobile = Test("^((\(\d{3}\))|(\d{3}\-))?13\d{9}$", Str)
    End Function
    Public Function IsPhone(ByVal Str)
        IsPhone = Test("^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$", Str)
    End Function
    Public Function IsSafe(ByVal Str)
        IsSafe = (Test("^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\""]*)|.{0,5})$|\s", Str) = False)
    End Function
    Public Function IsNotEmpty(ByVal Str)
        IsNotEmpty = LenB(Str) > 0
    End Function
    Public Function IsDateFormat(ByVal Str, ByVal Format)
        IF Not IsDate(Str) Then
            IsDateFormat = False
            Exit Function
        End IF
        IF Format = "YMD" Then
            IsDateFormat = Test("^((\d{4})|(\d{2}))([-./])(\d{1,2})\4(\d{1,2})$", Str)
        Else
            IsDateFormat = Test("^(\d{1,2})([-./])(\d{1,2})\\2((\d{4})|(\d{2}))$", Str)
        End IF
    End Function
    Public Function IsEqual(ByVal Src, ByVal Tar)
        IsEqual = (Src = Tar)
    End Function
    Public Function Compare(ByVal Op1, ByVal Operator, ByVal Op2)
        Compare = False
        IF Dic.Exists(Operator) Then
            Compare = Eval(Dic.Item(Operator))
            Elseif IsNotEmpty(Op1) Then
                Compare = Eval(Op1 &  Operator & Op2 )
        End IF
    End Function
    Public Function Range(ByVal Src, ByVal Min, ByVal Max)
        Min = CInt(Min) : Max = CInt(Max)
        Range = (Min < Src And Src < Max)
    End Function
    Public Function Group(ByVal Src, ByVal Min, ByVal Max)
        Min = CInt(Min) : Max = CInt(Max)
        Dim Num : Num = UBound(Split(Src, ",")) + 1
        Group = Range(Num, Min - 1, Max + 1)
    End Function
    Public Function Custom(ByVal Str, ByVal Reg)
        Custom = Test(Reg, Str)
    End Function
    Public Function Limit(ByVal Str, ByVal Min, ByVal Max)
        Min = CInt(Min) : Max = CInt(Max)
        Dim L : L = Len(Str)
        Limit = (Min <= L And L <= Max)
    End Function
    Public Function LimitB(ByVal Str, ByVal Min, ByVal Max)
        Min = CInt(Min) : Max = CInt(Max)
        Dim L : L =bLen(Str)
        LimitB = (Min <= L And L <= Max)
    End Function
    Private Function Test(ByVal Pattern, ByVal Str)
        Re.Pattern = Pattern
        Test = Re.Test(Str)
    End Function
    Public Function bLen(ByVal Str)
        bLen = Len(Replace(Str, "[^\x00-\xFF]", ".."))
    End Function
    Private Function Replace(ByVal Str, ByVal Pattern, ByVal ReStr)
        Re.Pattern = Pattern
        Replace =     Re.Replace(Str, ReStr)
    End Function
    Private Function B2S(ByVal iStr)
        Dim reVal : reVal= ""
        Dim i, Code, nCode
        For i = 1 to LenB(iStr)
            Code = AscB(MidB(iStr, i, 1))
            IF Code < &h80 Then
                reVal = reVal & Chr(Code)
            Else
                nCode = AscB(MidB(iStr, i+1, 1))
                reVal = reVal & Chr(CLng(Code) * &h100 + CInt(nCode))
                i = i + 1
            End IF
        Next
        B2S = reVal
    End Function
    Private Sub AddError(ByVal Name, ByVal Message)
        ErrorItem = ErrorItem & Separator & Name
        ErrorMessage = ErrorMessage & Separator & ErrorNo & ":" & Message
        ErrorNo = ErrorNo + 1
    End Sub
    Public Function IsValidPost()
        Dim Url1 : Url1 = Cstr(Request.ServerVariables("HTTP_REFERER"))
        Dim Url2 : Url2 = Cstr(Request.ServerVariables("SERVER_NAME"))
        IsValidPost = (Mid(Url1, 8, Len(Url2)) = Url2)
    End Function
    Public Property Let Mode(ByVal Val)
        ErrorMode = CInt(Val)
    End Property
    Public Property Let Form(ByVal Val)
        IF IsNumeric(Val) Then
            FormIndex = Val
        Else
            FormName = Val
        End IF
    End Property
    Public Property Let Path(ByVal Val)
        IF Test("^[A-Za-z]:\\\w+$", Val) Then
            FilePath = Val
        Else
            FilePath = Server.MapPath(Val)
        End IF
    End Property
    Public Property Let Method(ByVal Val)
        GetMethod = Val
    End Property
End Class
%>
<title>表单验证类 Validator v1.0</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overfmin:auto;}
form{display:inline}
</style>
<script>
/*************************************************
    Validator for ASP beta 2 客户端脚本
    code by 我佛山人
    wfsr@cunite.com
    http://www.cunite.com
*************************************************/
function dispError(items, messages, mode, separator){
    var iArray = items.split(separator);
    for(var i=iArray.length-1;i>=0;i--)
        iArray[i] = getObj(iArray[i]);
    messages = ("以下原因导致提交失败:\t\t\t\t" + separator + messages).split(separator);
    switch(mode){
        case 2 :
            for(i=iArray.length-1;i>=0;i--)
                iArray[i].style.color = "red";
        case 1 :
            alert(messages.join("\n"));
            iArray[0].focus();
            break;
        case 3 :
            for(i=iArray.length-1;i>=0;i--){
                try{
                    var span = document.createElement("SPAN");
                    span.id = "__ErrorMessagePanel";
                    span.style.color = "red";
                    iArray[i].parentNode.appendChild(span);
                    span.innerHTML = messages[i+1].replace(/\d+:/,"*");
                }
                catch(e){alert(e.description);}
            }
            iArray[0].focus();
            break;
    }
}
function getObj(name){
    var objs = document.getElementsByName(name);
    return objs[objs.length -1];
}
</script>
<form name="theForm" id="demo" action="" method="post" onSubmit="return true">
<table align="center">
    <tr>
   <td>真实姓名:</td><td><input name="Name" dataType="Chinese" msg="真实姓名只允许中文"></td>
  </tr>
  <tr>
   <td>英文名:</td><td><input name="Nick" dataType="English" require="false" msg="英文名只允许英文字母"></td>
  </tr>
    <tr>
   <td>主页:</td><td><input name="Homepage" require="false" dataType="Url"   msg="非法的Url"></td>
  </tr>
  <tr>
   <td>密码:</td><td><input name="Password" dataType="Safe"   msg="密码不符合安全规则" type="password"></td>
  </tr>
  <tr>
   <td>重复:</td><td><input name="Repeat" dataType="Repeat" to="Password" msg="两次输入的密码不一致" type="password"></td>
  </tr>
  <tr>
   <td>信箱:</td><td><input name="Email" dataType="Email" msg="信箱格式不正确"></td>
  </tr>
    <tr>
   <td>信箱:</td><td><input name="Email1" dataType="Repeat" to="Email" msg="两次输入的信箱不一致"></td>
  </tr>
  <tr>
   <td>QQ:</td><td><input name="QQ" require="false" dataType="QQ" msg="QQ号码不存在"></td>
  </tr>
    <tr>
   <td>身份证:</td><td><input name="Card" dataType="IdCard" msg="身份证号码不正确"></td>
  </tr>
  <tr>
   <td>年龄:</td><td><input name="Year" dataType="Range" msg="年龄必须在18~28之间" min="18" max="28"></td>
  </tr>
   <tr>
   <td>年龄1:</td><td><input name="Year1" require="false" dataType="Compare" msg="年龄必须在18以上" to1="18" operator="GreaterThanEqual"></td>
  </tr>
   <tr>
   <td>电话:</td><td><input name="Phone" require="false" dataType="Phone" msg="电话号码不正确"></td>
  </tr>
   <tr>
   <td>手机:</td><td><input name="Mobile" require="false" dataType="Mobile" msg="手机号码不正确"></td>
  </tr>
     <tr>
   <td>生日:</td><td><input name="Birthday" dataType="Date" format="YMD" msg="生日日期不存在"></td>
  </tr>
   <tr>
   <td>邮政编码:</td><td><input name="Zip" dataType="Custom" regexp="^[1-9]\d{5}$" msg="邮政编码不存在"></td>
  </tr>
  <tr>
   <td>邮政编码:</td><td><input name="Zip1" dataType="Zip" msg="邮政编码不存在"></td>
  </tr>
  <tr>
   <td>操作系统:</td><td><select name="OS" dataType="Require"  msg="未选择所用操作系统" ><option value="">选择您所用的操作系统</option><option value="Win98">Win98</option><option value="Win2k">Win2k</option><option value="WinXP">WinXP</option></select></td>
  </tr>
  <tr>
   <td>所在省份:</td><td>广东<input name="Province" value="1" type="radio">陕西<input name="Province" value="2" type="radio">浙江<input name="Province" value="3" type="radio">江西<input name="Province" value="4" type="radio" dataType="Group"  msg="必须选定一个省份"></td>
  </tr>
  <tr>
   <td>爱好:</td><td>运动<input name="Favorite" value="1" type="checkbox">上网<input name="Favorite" value="2" type="checkbox">听音乐<input name="Favorite" value="3" type="checkbox">看书<input name="Favorite" value="4" type="checkbox" dataType="Group" min="2" max="3"  msg="必须选择2~3种爱好"></td>
  </tr>
  <tr>
   <td>自我介绍:</td><td><textarea name="Description" dataType="Limit" max="10"  msg="自我介绍内容必须在10个字之内">中文是一个字</textarea></td>
  </tr>
  <tr>
     <td>自传:</td><td><textarea name="History" dataType="LimitB" min="3" max="10"  msg="自传内容必须在[3~10]个字节之内">中文是两个字节t</textarea></td>
  </tr>
  <tr>
   <td colspan="2"><input name="Submit" type="submit" value="确定提交"></td>
  </tr>
</table>
</form>
<%
    Dim V : Set V = New Validator
    V.Mode = 3
    V.Method = "XMLHTTP"
    V.Validate()
    Set V = Nothing
%>
</body>
</html>
本帖最近评分记录

表单验证 Validator v2.0 beta

借个地方用用(by 我佛山人)
增加功能(在包含旧版功能基础上):
1. IP地址验证
2.多条件验证(还不够完善),只需要在validation.xml中多写一行<item name....>
3.通过 XHTML Strict验证
演示:
http://wishwing.net/Validator.htm

下载:
http://wishwing.net/Validator.rar
2.0 是基于XML的架构,项目的所有页面的表单验证信息都可以保存在Validation.xml文件里,格式:
复制内容到剪贴板
代码:
<?xml version="1.0" encoding="gb2312"?>
<formset>
    <form name="demo" path="/validator.htm">
        <item name="Card" dataType="IdCard" msg="身份证号错误" />
    </form>
</formset>
其中 form 的 name 值是站点根目录下 validator.htm 文件里 id 为 demo 的表单
item 的 name 同表单项的 name ,其它属性同旧版,不同之处是把原来写在表单项的自定义属性移到 XML 配置文件里

脚本部分代码:
复制内容到剪贴板
代码:
/*
Validator v2.0 beta
code by 我佛山人
*/
var XmlReader = function(){
    this.GetHttpRequest = function(){
        if (window.XMLHttpRequest)        // Gecko
            return new XMLHttpRequest();
        else if (window.ActiveXObject)    // IE
            return new ActiveXObject("MsXml2.XmlHttp") ;
    }
    this.LoadUrl = function(urlToCall, asyncFunctionPointer){
        var oXmlReader = this;
        var bAsync = (typeof(asyncFunctionPointer) == "function");
        var oXmlHttp = this.GetHttpRequest();    
        oXmlHttp.open("GET", urlToCall, bAsync);
        if (bAsync){    
            oXmlHttp.onreadystatechange = function()
            {
                if (oXmlHttp.readyState == 4){
                    oXmlReader.DOMDocument = oXmlHttp.responseXML;
                    if (oXmlHttp.status == 200)
                        asyncFunctionPointer( oXmlReader ) ;
                    else
                        alert("XML request error: " + oXmlHttp.statusText + " (" + oXmlHttp.status + ")" ) ;
                }
            }
        }
        
        oXmlHttp.send(null) ;
        
        if (!bAsync)
        {
            if (oXmlHttp.status == 200)
                this.DOMDocument = oXmlHttp.responseXML ;
            else
            {
                alert("XML request error: " + oXmlHttp.statusText + " (" + oXmlHttp.status + ")") ;
            }
        }
    }
    this.SelectNodes = function(xpath){
        if (document.all)        // IE
            return this.DOMDocument.selectNodes(xpath) ;
        else{                    // Gecko
            var aNodeArray = new Array();
            var xPathResult = this.DOMDocument.evaluate(xpath, this.DOMDocument, this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null) ;
            if (xPathResult){
                var oNode = xPathResult.iterateNext() ;
                while(oNode){
                    aNodeArray[aNodeArray.length] = oNode ;
                    oNode = xPathResult.iterateNext();
                }
            }
            return aNodeArray ;
        }
    }
    this.SelectSingleNode = function(xpath){
        if (document.all)        // IE
            return this.DOMDocument.selectSingleNode( xpath ) ;
        else{                    // Gecko
            var xPathResult = this.DOMDocument.evaluate( xpath, this.DOMDocument,
                    this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), 9, null);
            if (xPathResult && xPathResult.singleNodeValue)
                return xPathResult.singleNodeValue ;
            else    
                return null ;
        }
    }
}
Validator = {
    Require : /.+/,
    Email : /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
    Phone : /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/,
    Mobile : /^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$/,
    Url : /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/,
    IP : /^(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5])$/,
    IdCard : "Validator.IsIdCard(value)",
    Currency : /^\d+(\.\d+)?$/,
    Number : /^\d+$/,
    Zip : /^[1-9]\d{5}$/,
    QQ : /^[1-9]\d{4,8}$/,
    Integer : /^[-\+]?\d+$/,
    Double : /^[-\+]?\d+(\.\d+)?$/,
    English : /^[A-Za-z]+$/,
    Chinese :  /^[\u0391-\uFFE5]+$/,
    Username : /^[a-z]\w{3,}$/i,
    UnSafe : /^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/,
    IsSafe : function(str){return !this.UnSafe.test(str);},
    SafeString : "Validator.IsSafe(value)",
    Filter : "Validator.DoFilter(value, getAttribute('accept'))",
    Limit : "Validator.limit(value.length,getAttribute('min'),  getAttribute('max'))",
    LimitB : "Validator.limit(Validator.LenB(value), getAttribute('min'), getAttribute('max'))",
    Date : "Validator.IsDate(value, getAttribute('min'), getAttribute('format'))",
    Repeat : "value == document.getElementsByName(getAttribute('to'))[0].value",
    Range : "getAttribute('min') < (value|0) && (value|0) < getAttribute('max')",
    Compare : "Validator.compare(value,getAttribute('operator'),getAttribute('to'))",
    Custom : "Validator.Exec(value, getAttribute('regexp'))",
    Group : "Validator.MustChecked(getAttribute('name'), getAttribute('min'), getAttribute('max'))",
    ErrorItem : [document.forms[0]],
    ErrorMessage : ["以下原因导致提交失败:\t\t\t\t"],
    Validate : function(theForm, mode){
        this.obj = theForm || event.srcElement;
        this.ErrorMessage.length = 1;
        this.ErrorItem.length = 1;
        this.ErrorItem[0] = this.obj;
        Validator.Check = function (xml){
            var obj = Validator.obj;
            var items = xml.SelectNodes("//form[@path='" + location.pathname.toLowerCase() + "' and @name='" + obj.id + "']/item");
            var iLen = items.length;
            for(var i=0;i<iLen;i++){
                with(items[i]){
                    var _dataType = getAttribute("dataType");
                    var value = Validator.getValue(getAttribute("name"));
                    if(typeof(_dataType) == "object" || typeof(Validator[_dataType]) == "undefined")  continue;
                    Validator.ClearState(Validator.getObject(getAttribute("name")));
                    if(getAttribute("require") == "false" && value == "") continue;
                    switch(_dataType){
                        case "IdCard" :
                        case "Date" :
                        case "Repeat" :
                        case "Range" :
                        case "Compare" :
                        case "Custom" :
                        case "Group" :
                        case "Limit" :
                        case "LimitB" :
                        case "SafeString" :
                        case "Filter" :
                            if(!eval(Validator[_dataType]))    {
                                Validator.AddError(getAttribute("name"), getAttribute("msg"));
                            }
                            break;
                        default :
                            if(!Validator[_dataType].test(value)){
                                Validator.AddError(getAttribute("name"), getAttribute("msg"));
                            }
                            break;
                    }
                }
            }
        if(Validator.ErrorMessage.length > 1){
            mode = mode || 1;
            var errCount = Validator.ErrorItem.length;
            switch(mode){
            case 2 :
                for(var i=1;i<errCount;i++)
                    Validator.ErrorItem[i].style.color = "red";
            case 1 :
                alert(Validator.ErrorMessage.join("\n"));
                Validator.ErrorItem[1].focus();
                break;
            case 3 :
                for(var i=1;i<errCount;i++){
                try{
                    var span = document.createElement("SPAN");
                    span.id = "__ErrorMessagePanel";
                    span.style.color = "red";
                    Validator.ErrorItem[i].parentNode.appendChild(span);
                    span.innerHTML = Validator.ErrorMessage[i].replace(/\d+:/,"*");
                    }
                    catch(e){alert(e.description);}
                }
                Validator.ErrorItem[1].focus();
                break;
            default :
                alert(Validator.ErrorMessage.join("\n"));
                break;
            }
            return false;
        }
        return true;
        }
        new XmlReader().LoadUrl("/Validation.xml", Validator.Check);
    },
    getValue : function(fieldname){
        return this.getObject(fieldname).value;
    },
    getObject : function(fieldname){
        var tmpObj = this.obj[fieldname];
        if(typeof(tmpObj) == "undefined"){alert("不存在名称为" + fieldname + "的表单项");return false;}
        try{return (tmpObj.length && !tmpObj.tagName)?tmpObj[tmpObj.length-1] : tmpObj;}catch(ie){alert("不存在名称为" + fieldname + "的表单项\nerror:" + ie.description);}
    },
    limit : function(len,min, max){
        min = min || 0;
        max = max || Number.MAX_VALUE;
        return min <= len && len <= max;
    },
    LenB : function(str){
        return str.replace(/[^\x00-\xff]/g,"**").length;
    },
    ClearState : function(elem){
        with(elem){
            if(style.color == "red")
                style.color = "";
            var lastNode = parentNode.childNodes[parentNode.childNodes.length-1];
            if(lastNode.id == "__ErrorMessagePanel")
                parentNode.removeChild(lastNode);
        }
    },
    AddError : function(fieldname, str){
        Validator.ErrorItem[Validator.ErrorItem.length] = Validator.getObject(fieldname);
        Validator.ErrorMessage[Validator.ErrorMessage.length] = Validator.ErrorMessage.length + ":" + str;
    },
    Exec : function(op, reg){
        return new RegExp(reg,"g").test(op);
    },
    compare : function(op1,operator,op2){
        switch (operator) {
            case "NotEqual":
                return (op1 != op2);
            case "GreaterThan":
                return (op1 > op2);
            case "GreaterThanEqual":
                return (op1 >= op2);
            case "LessThan":
                return (op1 < op2);
            case "LessThanEqual":
                return (op1 <= op2);
            default:
                return (op1 == op2);            
        }
    },
    MustChecked : function(name, min, max){
        var groups = this.ErrorItem[0][name];
        var hasChecked = 0;
        min = min || 1;
        max = max || groups.length;
        for(var i=groups.length-1;i>=0;i-=1)
            if(groups[i].checked) hasChecked++;
        return min <= hasChecked && hasChecked <= max;
    },
    DoFilter : function(input, filter){
return new RegExp("^.+\.(?=EXT)(EXT)$".replace(/EXT/g, filter.split(/\s*,\s*/).join("|")), "gi").test(input);
    },
    IsIdCard : function(number){
        var date, Ai;
        var verify = "10x98765432";
        var Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        var area = ['','','','','','','','','','','','北京','天津','河北','山西','内蒙古','','','','','','辽宁','吉林','黑龙江','','','','','','','','上海','江苏','浙江','安微','福建','江西','山东','','','','河南','湖北','湖南','广东','广西','海南','','','','重庆','四川','贵州','云南','西藏','','','','','','','陕西','甘肃','青海','宁夏','新疆','','','','','','台湾','','','','','','','','','','香港','澳门','','','','','','','','','国外'];
        var re = number.match(/^(\d{2})\d{4}(((\d{2})(\d{2})(\d{2})(\d{3}))|((\d{4})(\d{2})(\d{2})(\d{3}[x\d])))$/i);
        if(re == null) return false;
        if(re[1] >= area.length || area[re[1]] == "") return false;
        if(re[2].length == 12){
            Ai = number.substr(0, 17);
            date = [re[9], re[10], re[11]].join("-");
        }
        else{
            Ai = number.substr(0, 6) + "19" + number.substr(6);
            date = ["19" + re[4], re[5], re[6]].join("-");
        }
        if(!this.IsDate(date, "ymd")) return false;
        var sum = 0;
        for(var i = 0;i<=16;i++){
            sum += Ai.charAt(i) * Wi[i];
        }
        Ai +=  verify.charAt(sum%11);
        return (number.length ==15 || number.length == 18 && number == Ai);
    },
    IsDate : function(op, formatString){
        formatString = formatString || "ymd";
        var m, year, month, day;
        switch(formatString){
            case "ymd" :
                m = op.match(new RegExp("^((\\d{4})|(\\d{2}))([-./])(\\d{1,2})\\4(\\d{1,2})$"));
                if(m == null ) return false;
                day = m[6];
                month = m[5]*1;
                year =  (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10));
                break;
            case "dmy" :
                m = op.match(new RegExp("^(\\d{1,2})([-./])(\\d{1,2})\\2((\\d{4})|(\\d{2}))$"));
                if(m == null ) return false;
                day = m[1];
                month = m[3]*1;
                year = (m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10));
                break;
            default :
                break;
        }
        if(!parseInt(month)) return false;
        month = month==0 ?12:month;
        var date = new Date(year, month-1, day);
        return (typeof(date) == "object" && year == date.getFullYear() && month == (date.getMonth()+1) && day == date.getDate());
        function GetFullYear(y){return ((y<30 ? "20" : "19") + y)|0;}
    }
}
这样的好东西怎么不置顶

btw: chm文档中属性regexp和format内容是一样的

表单验证Validator2.0 beta

不知道这样写对不对呀,我是新手呀。就这个也是写了大半天的,希望可以帮我看看,小弟感激不尽呀~~~~
一只小天鹅

表单验证Validator2.0 beta

你好,我做出来了,你还在吗?想请教一下关于javascript正则表达式是一下问题~~~
一只小天鹅

TOP

还在为头像烦恼?还在为不能关注好友动态烦忧?快来蓝色理想家园吧!