位置:海鸟网 > IT > JavaScript >

简洁实用的表单验证程序

看了山人表单验证,又看了其他一些验证程序和相关的一些参考资料,写出了一个比较简洁的js表单验证程序。

功能简述:

验证:

http地址 
时间日期 
e-mail 
数字 
字符长度检查 
一项输入与另一项输入比较(例如:密码的确认输入) 
大小比较(只能有一个比较符号)
特点

扩展容易,可以方便的添加自己需要的验证方式 
兼容性好(ie5,6 firefox,oprea) 
可用性好,没有使用alert()来弹出提示
编写思路:

整个程序的结构及较简单,为了能够验证一些常用的格式,先对js的内置对象进行了扩展。比如:

String.prototype.isUrl = function(){
       var url = /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/;
       var tmpStr = this;
       return url.test(tmpStr);
}



这个用来验证http地址。

然后写了一个对象叫做vform 包含了主要的功能,vform初始化的时候,会检查添加好的验证规则,并将要验证的表单控件对象扩展,添加validate() 和 validlength()两个函数,并且添加onblur事件来进行验证。
出错提示采用的建立div对象的方法,出错就显示,正确就隐藏。所以还需要给div定义一个样式。
使用前需要指定表单的id 注意是id不是name 要不然会出错,而规则添加的时候要指定的是表单控件的name属性不是id

验证规则参数:

obj — 表单控件name 

minLength — 填写的字符串最小长度0意味着可以不填 而1意味着是必添

dataType — 验证格式有

e-mail 
url 
date 
number 
any 
还有两种动态的格式用\开头, \表单控件的name 表示必须与之的值一样; 
\>数字 表示大于数字,类推;但是没有\>=这样的
maxLength — 最大长度。

与其他程序不一样的是:我对http地址与日期格式地址的处理不同,填入的地址没有我会添加上后验证,这样比较人性化,符合可用性的要求。日期的处理也是一样,先尽可能的对填写的数字进行格式转化,然后再验证。格式采用了yyyy-mm-dd的格式。

原始位置:,原始文件应用一个日历输入控件在此省略……

完整的代码如下:
[html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<html xmlns="">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>vForm表单验证程序</title>
<style type="text/css">
<!--
div.info {
 width: 170px;
 overflow:visible;
 height:auto;
 font-size: small;
 position: absolute;
 background-color: #FFffdd;
 border: 1px solid #000;
 filter:progid:DXImageTransform.Microsoft.Shadow(color=#111111,direction=135,strength=3);
 top: 375px;
 padding: 5px;
 left: 671px;
}
div.info_title

.err{
 padding: 5px;
 height: 50px;
 width: 24em;
 position: absolute;
 background-color: #FFFFCC;
 left: 196px;
 top: 114px;
 font-size: small;
 opacity:0.5;
 border: 1px double #333333;
 filter: Shadow(Color=#000000, Direction=135);
 filter:progid:DXImageTransform.Microsoft.Shadow(color=#111111,direction=135,strength=5);

}
#form1 .text_input {
 border-top: 1px solid #333333;
 border-right: 1px solid #999999;
 border-bottom: 1px solid #ddd;
 border-left: 1px solid #000000;
}
.info_title {
 color: #FF0000;
 background: #ACB9D1;
}
#form1 {
 position: static;
 left: 581px;
 top: 463px;
 border: 1px solid #3300FF;
 padding: 5px;
 ;
}
#imok {
 display: block;
 position: absolute;
 height:315px;
 overflow:scroll;
 left: 100px;
 top: 100px;
 width: 306px;
}
.title h1 {
 background: #33CCFF;
 border-bottom: medium solid #3366FF;
}
.title p {
 font-size: medium;
 text-indent: 2em;
}
body {
 font-family: Verdana, Arial, Helvetica, sans-serif;
 font-size: medium;
}

code {
 font: 12px/18px "lucida Grande", verdana, lucida, Arial, helvetica, "宋体", sans-serif;
 border:1px solid #0099cc;
 padding:5px;
 margin: 5px;
 width: 80%;
 color: #000;
 background-color: #ddedfb;
 display: block;
}

-->
</style>
<script language="JavaScript" type="text/javascript">
//程序基本思路:通过扩展对象来实现,将String扩展 将默认的表单元素扩展 定义两个自定义对象。
//String.isEmail
//String.isUrl
//表单元素.required
//表单元素.isvalid
//表单元素.validate
//

//字符串验证扩展
//├电子邮件验证
String.prototype.isEmail = function(){
 var tmpStr = this;
 var email = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
 return email.test(tmpStr)
}
//├http地址验证
String.prototype.isUrl = function(){
 var url = /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/;
 var tmpStr = this;
 return url.test(tmpStr);
}
//├日期验证(第一部分)
String.prototype.isDateTime = function(){
 if(Date.parse(this)||Date.parseDate(this))
 {
  return true;
 }
 else
 {
  return false;
 }
}
String.prototype.isInteger = function()
{
 var _i = /^[-\+]?\d+$/;
 var _s = this; 
 return _i.test(_s);
}
Date.prototype.toIsoDate = function()
{
 var _d = this;
 var _s;
 _Y =_d.getFullYear();
 _M = _d.getMonth() + 1;
 _D = _d.getDate();
 _H = _d.getHours();
 _I = _d.getMinutes();
 _S = _d.getSeconds();
 with(_d)
 {
  _s = [getMonth() + 1,getDate(),getHours(),getMinutes(),getSeconds()];
 }
 for(var i = 0; i < _s.length; i++)
 {
  if (_s[i].toString().length == 1)_s[i]= '0'+_s[i];
 }
  return (_Y + '-'+_s[0]+'-'+_s[1]+' '+_s[2]+':'+_s[3]+':'+_s[4])
}
//├日期验证(第二部分)
Date.parseDate = function(str, fmt) {
 fmt = fmt||"%Y-%m-%d %H:%M";
 var today = new Date();
 var y = 0;
 var m = -1;
 var d = 0;
 var a = str.split(/\W+/);
 var b = fmt.match(/%./g);
 var i = 0, j = 0;
 var hr = 0;
 var min = 0;
 for (i = 0; i < a.length; ++i) {
  if (!a[i])
   continue;
  switch (b[i]) {
      case "%d":
      case "%e":
   d = parseInt(a[i], 10);
   break;

      case "%m":
   m = parseInt(a[i], 10) - 1;
   break;

      case "%Y":
      case "%y":
   y = parseInt(a[i], 10);
   (y < 100) && (y += (y > 29) ? 1900 : 2000);
   break;

      case "%b":
      case "%B":
   for (j = 0; j < 12; ++j) {
    if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
   }
   break;

      case "%H":
      case "%I":
      case "%k":
      case "%l":
   hr = parseInt(a[i], 10);
   break;

      case "%P":
      case "%p":
   if (/pm/i.test(a[i]) && hr < 12)
    hr += 12;
   else if (/am/i.test(a[i]) && hr >= 12)
    hr -= 12;
   break;

      case "%M":
   min = parseInt(a[i], 10);
   break;
  }
 }
 if (isNaN(y)) y = today.getFullYear();
 if (isNaN(m)) m = today.getMonth();
 if (isNaN(d)) d = today.getDate();
 if (isNaN(hr)) hr = today.getHours();
 if (isNaN(min)) min = today.getMinutes();
 if (y != 0 && m != -1 && d != 0)
  return new Date(y, m, d, hr, min, 0);
 y = 0; m = -1; d = 0;
 for (i = 0; i < a.length; ++i) {
  if (a[i].search(/[a-zA-Z]+/) != -1) {
   var t = -1;
   for (j = 0; j < 12; ++j) {
    if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
   }
   if (t != -1) {
    if (m != -1) {
     d = m+1;
    }
    m = t;
   }
  } else if (parseInt(a[i], 10) <= 12 && m == -1) {
   m = a[i]-1;
  } else if (parseInt(a[i], 10) > 31 && y == 0) {
   y = parseInt(a[i], 10);
   (y < 100) && (y += (y > 29) ? 1900 : 2000);
  } else if (d == 0) {
   d = a[i];
  }
 }
 if (y == 0)
  y = today.getFullYear();
 if (m != -1 && d != 0)
  return new Date(y, m, d, hr, min, 0);
 return today;
};
//扩展完成

//对象定义

var vform = new Object;
//获取弹出提示的显示位置
vform.getAbsolutePos = function(el) {
 var _p = { x: 0, y: 0 };
  do{
    _p.x += (el.offsetLeft - el.scrollLeft);
    _p.y += (el.offsetTop - el.scrollTop); 
  }
   while(el=el.offsetParent)
     return _p;
      };
vform.toString = function()
{
 return("vForm表单验证程序\n版本:1.0beta\n作者:雷晓宝\n时间:2006-07-31\n网址:\n许可:LGPL");
}
vform.rules = new Array;
vform.rules.add = function(obj,minLength,dataType,errmsg,maxLength,rule,patams)
{
    var curlen = this.length;
        this[curlen] = [obj,minLength,dataType,errmsg,maxLength,rule,patams];
        //this[curlen] = [ 0 ,    1    ,    2   ,   3  ,   4  ,  5 ,   6  ];

    return this.length;
}
vform.init= function()
{
 if(document.getElementById(this.form_id))
 {
  //获取表单
  var o = document.getElementById(this.form_id);
  //遍历规则
  for(var i = 0 ;i< this.rules.length;i++)
  {
   _r = this.rules[i]
   //如果存在元素,则添加验证程序
   if(_o = o.elements[_r[0]])
   {
    //判断是是否必填,是否有最小长度
    if(_r[1] > 0 )
    {
     _o.required = true;//必填的含义和最小长度为1是一样的
     _o.minLength = parseInt(_r[1]);
    }
    else
    {
     _o.required = false;
     _o.minLength = 0;
    }
    //判断是否有最大长度;
    if(_r[4])
    {
     _o.maxLength = parseInt(_r[4]);
    }
    //添加长度验证函数
    _o.validLength = function ()
    {
     var b =true;
     if(this.minLength)
     {
      b = (this.minLength <= this.value.length);
     }
     if(this.type == 'textarea' && this.maxLength )
     {
      b = b && (this.maxLength >= this.value.length );
     }
     return (b);
    }
    //添加验证,进行格式验证
    switch(_r[2])
    {
     case 'e-mail':
      _o.validate = function()
      {
       this.isvalid = this.validLength() && this.value.isEmail();
       return (this.isvalid);
      };
      break;
     case 'url':
      _o.validate = function()
      {
       if (this.value.substring(0,7) != '')this.value = '' +this.value;
       this.isvalid = this.validLength() && this.value.isUrl();
       return (this.isvalid);
      }
      break;
     case 'date':
      _o.validate = function()
      {
       var _d = Date.parse(this.value)||Date.parseDate(this.value);
       this.value =  _d.toIsoDate();
       
       this.isvalid = this.validLength() && this.value.isDateTime();
       return (this.isvalid);
       a=a>b?1:1;
      }
      break;
     case 'number':
      _o.validate = function()
      {
       this.isvalid = this.validLength() && this.value.isInteger();
       return (this.isvalid);

      }
      break;
     case 'any':
      _o.validate = function()
      {
       this.isvalid = this.validLength();
       return  this.isvalid
      }
      break;
     default :
      var regexp = /^\\\w+$/;
      if ( regexp.test(_r[2]))//表示必须和同表单下的某个字段的值一样。用于重复输入的验证
      {
       _el = _r[2].substring(1);
       if (o.elements[_el]){
        _o.equal = _el;
        _o.validate = function()
        {
         if(_o = this.form.elements[this.equal])
         {
          if ( (_o.value == this.value) && this.validLength())
          {
           return true;
          }else {
          return false;
          }
         }else{
          alert('setup error');
         }
        
        }
       }else
       {
        alert(_el + 'is not a valid form element');
        _o.validate = function(){return true;}
       }
      }
      var regexp1 = /^\\(==|!=|>=|<=|>|<)/;
      if ( regexp1.test(_r[2]) )
      {
       _s0 = _r[2];
       _s1 = RegExp.$1;
       _s2 = _s0.replace(regexp1,'');
       _operator = _s1.substring(0);//比较操作符
       var regexp2 = /^\w+$/;
       if (regexp2.test(_s2))//是一个标志符,整数 或者变量
       {
        _o.operation = _operator+_s2;
        _o.validate = function()
        {
         _b = true;
         if (this.value.length !=0)
         {
          _b = eval(this.value+this.operation+';');
         }         
         _b = _b && this.validLength();
         return _b;
        }
       }
      };
      break;
      
    }
    //添加验证提示(div标签)并初始化
    var _p = vform.getAbsolutePos(_o);
    _o.tip = new tip(_r[3],vform.err_class,_p.x+_o.offsetWidth+3,_p.y);

    _o.tip.init();
    //失去焦点时,开始验证
    _o.onblur =function(e)
    {
     if(this.minLength || this.value.length >0) 
     { 
      if( this.validate() )
      {
       this.tip.hide();
      }else
      {
       this.tip.show();//显示错误信息
       //this.focus(); 添加这句在ie里会导致死循环 :(
       return false;
      }
     }
    }
   }
  }
 //焦点验证可能会失败,所以最后需要表单提交前的验证作为最后的补充。
  document.getElementById(this.form_id).onsubmit = function()
  {
   var valid = true;
   for(i=0;i<this.elements.length;i++)
   {
    _o = this.elements[i];
    if(_o.minLength && !_o.isvalid)
    {
     _o.tip.show();
     valid = false;
    }
   }
   return valid;
  }
 }
}
//弹出提示定义
function tip(text,className,x,y)
{
 var o = document.createElement("div");
 o.style.display = "none";
 o.innerHTML = text;
 //var t = document.createTextNode(text);
 document.body.appendChild(o);
 //o.appendChild(t);
 
 this.init = function(dis)
 {
  o.className = "info";
  o.style.left = x+"px";
  o.style.top = y+"px";
  o.style.zindex = 100;
  if(dis)
  {
   o.style.display = "";
  }
  else
  {
   o.style.display = "none";
  }
 }
 this.show = function()
 {
  o.style.display = "";
 }
 this.hide = function()
 {
  o.style.display = "none";
 }
}


function start()
{
  vform.form_id = 'form1';//必须是表单的id
  vform.err_class = 'info';//出错提示的样式
 //验证规则,逐条填写
vform.rules.add('frm_name',1,'e-mail','请您按照 user@domain.com 的格式输入电子邮件地址。<br /><span style="color:#f00">必填项目</span>');
  vform.rules.add('myweb',1,'url','请您按照  的格式输入您的网址。<br /><span style="color:#f00">必填项目</span>');
  vform.rules.add('dateinput',0,'date','请按2000-03-05 的格式输入日期。<br /><span style="color:#f00">必填项目</span>');
  vform.rules.add('qq',0,'number','这必须是一个整数');
  vform.rules.add('least10',10,'any','您必须至少填写10个<br /><span style="color:#f00">必填项目</span>');
  vform.rules.add('ok100',1,'any','这里被限制为100个字符<br /><span style="color:#f00">必填项目</span>',100);
  vform.rules.add('r_pass0',5,'any','密码最短5位最长20位<br /><span style="color:#f00">必填项目</span>',20);
  vform.rules.add('r_pass1',5,"\\r_pass0",'确认密码错误<br /><span style="color:#f00">必填项目</span>',20);
  vform.rules.add('frm_sel',1,"\\>2",'必须大于2000<br /><span style="color:#f00">必填项目</span>');
  vform.init();
 
}

</script>
</head>
<body onload="start()">

<form id="form1" name="form1" method="get" action="">
 <label for="frm_name">e-mail:
 <input name="frm_name" type="text" class="text_input" id="frm_name" title="输入一个电子邮箱地址"/>
 </label>
 *
 <p>
  <label for="r_pass0">输入密码:
  <input name="r_pass0" type="text" class="text_input" id="r_pass0" title="输入您希望的密码 " />
  </label>
 *</p>
 <p>
  <label for="r_pass1">密码确认:
  <input name="r_pass1" type="text" class="text_input" id="r_pass1" title="将密码确认一次" />
  </label>
 *</p>
 <p>
  <label for="frm_sel">选择:
  <select name="frm_sel" id="frm_sel" title="请选择一个答案">
   <option value="0">请选择一个答案</option>
   <option value="1" selected="selected">1000</option>
   <option value="2">2000</option>
   <option value="3">3000</option>
   <option value="4">4000</option>
   <option value="5">5000</option>
   <option value="6">6000</option>
  </select>
</label>
 *</p>
 <p>
  <label for="input3">输入网址:
  <input name="myweb" type="text" class="text_input" id="input3" title="输入一个网址" onmousemove="" value="" maxlength="100"/>
  </label>
 *</p>
 <p>
  <label for="dateinput">输入日期
  <input name="dateinput" type="text" class="text_input" title="输入一个日期" id="dateinput"/>
</label>
 *</p>
 <p>
  <label for="mub">输入数字
  <input name="qq" type="text" class="text_input" title="填写数字" id="mub"/>
  </label>
 </p>
 <p>
  <label for="len">输入任意但长度限制为10个
  <input name="least10" type="text" class="text_input" maxlength="88" id="len"/>
  *
  </label>
 </p>
 <p>
  <label for="text">只能输入100个
  <textarea name="ok100" cols="40" rows="5" id="text" title="详细内容"></textarea>
  *
  </label>
 </p>
 <p>
  <input type="submit" name="Submit" value="提交" />
  <button onclick="alert(vform)" >关于验证程序</button>
 </p>
</form>
<!--具体的日期设置,必须放在body的结束标签前面-->
<script type="text/javascript">
  vform .init();
    Calendar.setup({
   inputField     :    "dateinput",   // 把这个改成你需要的 id
   ifFormat       :    "%Y-%m-%d %H:%M", // format of the input field
   showsTime      :    true,
   //button     :    "dateinput_btn", 
   timeFormat     :    "24"
   });
 </script>
<!--END具体的日期设置,必须放在body的结束标签前面-->
<div class="title">
 <h1>vForm1.0beta</h1>
 <ul>
  <li>作者:雷晓宝</li>
  <li>时间:2006-08-08</li>
  <li>网址:</li>
  <li>e-mail:lxbzmy@163.com</li>
  <li>许可:LGPL</li>
 </ul>
 <h2>功能简述:</h2>
 <ol>
   <li>
     <h3>验证:</h3>
     <ul>
       <li>http地址。</li>
          <li>时间日期</li>
       <li>e-mail</li>
       <li>数字</li>
       <li>字符长度检查</li>
       <li>一项输入与另一项输入比较(例如:密码的确认输入)</li>
       <li>大小比较(只能有一个比较符号)</li>
        </ul>
   </li>
      <li>
        <h3>特点</h3>
        <ul>
          <li>扩展容易,可以方便的添加自己需要的验证方式</li>
          <li>兼容性好(ie5,6 firefox,oprea)。</li>
        <li>可用性好,没有使用alert()来弹出提示;</li>
        </ul>
      </li>
  </ol>
 <p> </p>
 <h2>使用方法</h2>
 <p>使用时,需要定义一个出错提示框的样式,本例的样式为:<code>div.info {
 width: 170px;<br />
    overflow:visible;<br />
    height:auto;<br />
    font-size: small;<br />
    position: absolute;<br />
    background-color: #FFffdd;<br />
    border: 1px solid #000;<br />
    filter:progid:DXImageTransform.Microsoft.Shadow(color=#111111,direction=135,strength=3);<br />
    padding: 5px;<br />
    }</code></p>
 <p>然后在网页<head>部分中添加<code><script type="text/javascript" src="calendar/calendar.js"></script></code><br />
   然后可以写一个函数设置表单名称,验证规则,<code>function start()<br />
   { 
   <br />
   vFormvform.form_id = 'form1';<br />
  vform.err_class = 'info';<br />
  // (obj,required(true/false),dataType,errmsg,minlen,maxlen,rule,patams)<br />
  //验证规则,逐条填写<br />
  vform.rules.add('frm_name',1,'e-mail','请您按照 user@domain.com 的格式输入电子邮件地址。<br /><span style="color:#f00">必填项目</span>');<br />
  vform.rules.add('myweb',1,'url','请您按照  的格式输入您的网址。<br /><span style="color:#f00">必填项目</span>');<br />
  vform.rules.add('dateinput',0,'date','请按2000-03-05 的格式输入日期。<br /><span style="color:#f00">必填项目</span>');<br />
  vform.rules.add('qq',0,'number','这必须是一个整数');<br />
  vform.rules.add('least10',10,'any','您必须至少填写10个<br /><span style="color:#f00">必填项目</span>');<br />
  vform.rules.add('ok100',1,'any','这里被限制为100个字符<br /><span style="color:#f00">必填项目</span>',100);<br />
   vform.init();<br />
   }</code>最后为body添加onload事件。
   <code><body onload="start();"></code></p>
 <p> </p>
</div>
</body>
</html>[/code]