HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>表单验证</title>
<link rel="stylesheet" href="css/lesson12.css">
<script src="javascript/lesson12.js"></script>
</head>
<body>
<form action="#">
<p> <label for="userName">用户名:<input type="text" id="userName" class="btx"></label>
<p> <label for="pw1">密码:<input type="password" id="pw1" class="btx" ></label>
<p> <label for="pw2">重复密码:<input type="password" id="pw2" class="btx"></label>
<p> <input type="submit" value="提交"> <input type="reset" value="重置">
</form>
</body>
</html>
CSS
@charset "UTF-8";
.btx{
color:#000;
background-color:#fff ;
}
.btxtx{
color:#000;
background-color:#ff8000;
}
JS
/**
*
*/
window.onload = init ;
function init()
{
for(var i = 0 ; i < document.forms.length ; i ++)
{
document.forms[i].onsubmit = submitEvet ;
}
}
function submitEvet()
{
//var tagArr = document.getElementsByTagName("*");
//通过标签的类名获得具有同类名的标签节点集合。注意Elements多一个s
var tagArr = document.getElementsByClassName("btx");
var v_length = tagArr.length ; //获得数组长度
//for(var i= 0 ; i < v_length ; i++) //如果这样写,最后会产生数组越界错误,导致页面重载
for(var i= 0 ; i < tagArr.length ; i++)
{
//检查input标签中是否有输入值
if(tagArr[i].value=="")
{
//当修改数组元素中的属性后,原数组长度就会-1 ,被修改属性的元素会被踢出数组
tagArr[i].className = "btxtx" ;
}
}
return false ;
}
当页面第一次加载,而不输入任何项目,直接点击提交,理想中的样子
而实际上是这个样子
用chrome调试工具单步跟踪,循环第一次处理之前,数组元素个数为3
在第一次修改元素类名之后,数组元素减少一个,但是存储数组长度的变量 v_length 却没有变 ,数组实际长度为2
当数组长度发生变化后,数组下标与元素的对应关系也在发生变化 在第一次处理之前 tagArr[1] = pw1 , 在第一次处理之后
tagArr[1] = pw2 ,所以当 i = 1 时 ,处理的元素就是pw2 ,跳过了 pw1 所以页面中才会出现一个样式未被改变的输入框
第二次处理之后,数组中就只剩下被跳过处理的pw1 ,所以 如果在for循环中使用存储数组长度的变量 v_length 作为条件控制,
这个时候,就会发生数组越界错误,2<3 条件成立 , 但tagArr[2] 是不存在的,if 语句就会出错,页面会重载
然后在网上查了一下,并没有发现有人提起过这个事,以为JS在数组处理方面本来就是这个样子,当数组元素中属性发生变化后
元素会被踢出数组,于是做了一个验证,同样是对象类型数组,比如下面这个测试:
结果并没有想象中的数组元素减少的现象。其实在做这个测试的过程中还发现一个有趣的现象,在第一次处理之后,如果用log方法打印数组,会发现打印出的数组元素中的属性已经全部都被修改了,但是单独打印出的数组元素,属性又是正常的。
然后修改原有JS的写法,利用标签ID来达到想要的效果
CSS
@charset "UTF-8";
body{
color:#000 ;
background-color:#fff ;
text-align:center;
margin:auto;
}
#btxtx,#userName,#pw1,#pw2{
background-color:#fff;
}
#userName_wt,#pw1_wt,#pw2_wt{
background-color:#ff8000;
}
JS
window.onload = init;
var IdArr = new Array(); //声明数组,用于存储表单原有样式信息
function init()
{
for(var i = 0 ; i<document.forms.length ; i ++ )
{
document.forms[i].onsubmit = submitEvet ;
}
}
function submitEvet()
{
//var TagArr = document.getElementsByTagName("*");
var TagArr = document.getElementsByTagName("INPUT");
for (var i = 0; i < TagArr.length; i++)
{
if(!IdArr[i]) //如果数组元素为空,即没有存储任何内容
{
IdArr[i]=TagArr[i].id ; //保存原有样式 因为ID对应CSS样式表
}
var TagStr = TagArr[i].nodeName ; //获得标签名称,返回值是大写字母且没有尖括号
var TagObj = TagArr[i] ; //获得标签对象
//检查当前标签名和标签值,以及是否已经对ID进行过修改,如果不判断ID是否以及被修改过,而只判断名称和值,则在第二次提交时,没填写值
//的input标签的ID将会累加“_wt” 导致样式失效。
if(TagStr=="INPUT" && TagObj.value=="" && TagArr[i].id.indexOf("_wt") == -1)
{
TagObj.id=TagArr[i].id+"_wt"; //修改元素标签id 通过css改变其外观样式
}
else if(TagStr=="INPUT" && TagObj.value!="" && TagArr[i].id.indexOf("_wt") > -1)
{
TagObj.id=IdArr[i]; //样式还原
}
if(TagStr=="LABEL")
{
// alert(TagObj.innerHTML); //获取指定标签中间的内容。
// alert(TagObj.outerHTML); //获取指定标签包含标签自身的内容。
}
}
/********************最后检查是否还有未填项************************* */
var num = 0 ;
for(j=0; j<TagArr.length; j++)
{
if(TagArr[j].id.indexOf("_wt")>-1)
{
num=num+1 ;
TagArr[j].focus(); //输入框获得焦点
TagArr[j].select(); //输入框被选中
//一旦发现必填项未输入内容,则跳出循环,否则输入框的焦点会出现在最后一个未输入内容的输入框中,而不是第一个
break ;
}
}
if(num==0)
{
alert("提交成功");
return true ;
}
else
{
alert("有必填项未填写,请填写完整");
return false;
}
}
在利用ID这种写法时,最开始,对未输入项的标签直接修改其ID 但是这个ID值 是一个特定的字符串,比如CSS中"btxtx"。然后
CSS文件中也没有这么多的样式,只有一个ID为 #btxtx 的样式 。 运行效果是一样。 后来才反应过来,这样的做法,是违背了标
签ID 在文档中唯一性这一说法,但是浏览器也没有报错,并且运行效果也达到预期。
为了维护ID唯一性这一说法,才改用ID名称追尾这种,同时CSS文档中也就加入了很多ID的样式。