简明现代魔法 -> JavaScript -> JavaScript验证用户输入

JavaScript验证用户输入

2010-06-29

在表单方面,验证用户输入是否合法是个重头戏:

	<body>
		<form action="" method="post">
			<fieldset class="login">
				<legend>Login Information</legend>
				<label for="username" class="hover">Username</label>
				<input type="text" id="username" class="required text"/><br/>
				
				<label for="password" class="hover">Password</label>
			    <input type="password" id="password" class="required text"/>
			</fieldset>
			<fieldset>
				<legend>Personal Information</legend>
				<label for="name">Name</label>
				<input type="text" id="name" class="required text"/><br/>
				
				<label for="email">Email</label>
				<input type="text" id="email" class="required email text"/><br/>
				
				<label for="date">Date</label>
				<input type="text" id="date" class="required date text"/><br/>
				
				<label for="url">Website</label>
				<input type="text" id="url" class="url text" value="http://"/><br/>
				
				<label for="phone">Phone</label>
				<input type="text" id="phone" class="phone text"/><br/>
				
				<label for="age">Over 13?</label>
				<input type="checkbox" id="age" name="age" value="yes"/><br/>
				
				<input type="submit" value="Submit Form" class="submit"/>
			</fieldset>
		</form>
	</body>

在表单内,所有<input>元素都精细地分好类(比如,type为text的元素其class也为text,必填项的class为required为js的运用做个钩子),并与正确的label一起被包含在合适的fieldset内。并配上css使得更美观一些:

<style type="text/css">
	form {
		font-family:Arial;
		font-size:14px;
		width:300px;
	}
	fieldset {
		border:1px solid #ccc;
		margin-bottom:10px;
	}
	fieldset.login input {
		width:125px;
	}
	legend {
		font-weight:bold;
		font-size:1.1em;
	}
	label {
		display:block;
		width:60px;
		text-align:right;
		float:left;
		padding-right:10px;
		margin:5px 0px;
	}
	input {
		margin:5px 0;
	}
	input.text {
		padding:0 0 0 3px;
		width:172px;
	}
	input.submit {
		margin:15px 0 0 70px;
	}
</style>

我们先来看js验证的规则集合,可以注意到所有测试都分别需要通用的名称和语义化的错误信息。下面给出本例中使用的验证规则集合:

var errMsg = {
	required:{
	    msg:'This field is required.',
	    test:function(obj) {
	                  return trim(obj.value).length > 0 || trim(obj.value) != obj.defaultValue;
	            }
	},
	email: {
	    msg:'Not a valid email address.',
	    test:function(obj) {
		return trim(obj.value).length <= 0 || /^[a-z0-9_+.-]+\@([a-z0-9-]+\.)+[a-z0-9]{2,4}$/i.test(obj.value);	
	    }
	},
	phone: {
	    msg:'Not a valid phone number.',
	    test:function(obj) {
	              var m = /(\d{3}).*(\d{3}).*(\d{4})/.exec( obj.value );
                              if(m) obj.value = "(" + m[1] + ") " + m[2] + "-" + m[3];
                              return trim(obj.value).length <= 0 || m;	
	    }	
	},	
	date: {
	    msg:'Not a valid date.',
	    test:function(obj) {
	              return trim(obj.value).length <= 0 || /^\d{2}\/\d{2}\/\d{2,4}$/.test(obj.value);
	    }
         },
	url: {
	    msg:'Not a valid URL.',
	    test:function(obj) {
                             return trim(obj.value).length <= 0 || obj.value == 'http://' || /^https?:\/\/([a-z0-9-]+\.)+[a-z0-9]{2,4}.*$/.test(obj.value);
	           }
	}
}

这里我已经对验证规则做了修改,原文中对于必填项(required)的验证:return obj.value.length > 0这个子条件有问题,如果只是输入了一连串空格而无实质性的内容,难道也让它验证通过吗?很明显不行,所以用trim函数来去掉空格在来判断才正确。

function trim(value) {
	return value.replace(/(^\s*)|(\s*$)/g,'');
}

这个函数用replace方法通过匹配正则表达式去掉字符串首尾空格,很常用。对于下面一些其他字段的判断如email,date等的判断也是这个问题,这里有个细节,像email这种需要特定格式验证的字段,得先看看用户输入了东西没,如果没有那也没必要判断,所以用trim(obj.value).length <= 0如果为true那么这个||运算就到此为止了,说明用户没输入什么东西,也就没必要判断格式了,反之如果为false,就说明有内容了,并且需要判断下。

规则给出来了,接着我们该用这些规则判断,然后给出必要的提示信息。先介绍个知识点:所有<form>元素(在DOM中)都有一个被称为elements的属性,这个属性是包含表单所有字段的数组,使用这个数组就可以轻松遍历所有可能的字段,并检查错误。在我debug的过程中,发现不光用户输入相关的<input>元素在elements中,两个<fieldset>元素也在其中...下面给出具体的验证相关的函数。

//验证表单所有字段的函数
//form是个表单元素的引用
function validateForm(form) {
       var valid = true;
       //遍历表单的所有字段元素
     //form.elements是表单所有字段的一个数组
       for(var i = 0; i < form.elements.length; i++) {
                   //先隐藏任何错误信息,以防不意的显示
                   hideErrors(from.elements[i]);
                   //检查字段是否包含正确的内容
             //注:原书中条件上加了个取反运算符'!',看了下面的validateField就知道这里有问题
                   if ( validateField(form.elements[i]) )
                              valid = false;
       }  
       return valid;   
}

//验证单个字段的内容
function validateField(elem) {
      var errors = [];
      //遍历所有可能的验证技术
    for(var name in errMsg ) {
            //查看字段是否有错误类型指定的class
            var re = new RegExp('(^|\\s)' + name + '(\\s|$)');
            //检查元素是否带有该class并把它传递给验证函数
        if( re.test(elem.className) && !errMsg[name].test(elem) )
                   //如果没有通过验证,把错误信息增加到列表中
             errors.push( errMsg[name].msg );
      }
      //如果存在错误信息,则显示出来
    if(errors.length)  showErrors( elem,  errors );
      return errors.length > 0; //>0说明有错误信息
} 

/*显示和隐藏相应字段的错误信息*/
//隐藏当前正显示的任何错位信息
function hideErrors(elem) {
     //获取当前字段的下一个元素
     var next = elem.nextSibling;
     //如果下一个元素是ul并有class为errors
     if(next && next.nodeName == 'UL' && next.className == 'errors')
              //删掉它(这是我们'隐藏'的含义)
              elem.parentNode.removeChild(next);
}

//显示表单内特定字段的错误信息
function showErrors(elem, errors) {
     //获取当前字段的下一个元素
     var next = elem.nextSibling;
     //如果该字段不是我们指定的包含错误的容器
   if( next && ( next.nodeName != 'UL' || next.className != 'errors' ) ) {
          //我们得生成一个
       next = document.createElement('ul');
           next.className = 'errors';
           //并在DOM中把它插入到恰当的地方
       //从HTML中看,这里的elem.nextSibling指向的是'<br/>',
          //而<ul>本身默认的display为block
       elem.parentNode.insertBefore( next, elem.nextSibling );
     }
     //现在有了一个包含错误的容器引用,我们可以遍历所有的错误信息了
   for(var i = 0; i < errors.length; i++) {
          var li = document.createElement('li');
          li.innerHTML = errors[i];
          //并插入到DOM中
          next.appendChild( li );
    }
}

在配上错误信息的css样式:

ul.errors {
      list-style:none;
      background:#ffcece;
      padding:3px;
      margin:3px 0 3px 70px;
      font-size:0.9em;
      width:165px;
}

查看示例

随机文章推荐
网站分类


注:如需转载本文,请注明出处(原文链接),谢谢。更多精彩内容,请进入简明现代魔法首页。

进入新博客
喜欢本文,就分享它吧
给我留言
您的名字:
您的邮件:
您的网站:


 

copyright © 2009 简明现代魔法    学习、分享、进步

power by Gonn 感谢所有关心和支持本站的朋友们