DHTML5(控件动态效果综合应用与表单校验)
----android培训 、java培训、期待与您交流!----
1.动态添加附件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>动态添加附件</title> <script type="text/javascript" src="JS/documentTools.js"></script> <style type="text/css"> table{ border:1px solid #00F; } table td{ border:1px solid #999; } </style> <script type="text/javascript"> function addAttachment(){ var count=0; var tableNode=byID("tableID"); var trNode=tableNode.insertRow(); trNode.id="tr_"+(++count);//为每个行对象绑定一个编号 trNode.insertCell().innerHTML="<input type='file'/>"; //trNode.insertCell().innerHTML //="<a href='javascript:void(0)'onclick='deleteAttachment("+count+")'>删除</a>"; trNode.insertCell().innerHTML ="<a href='javascript:void(0)'onclick='deleteAttachment_2()'>删除</a>"; } /* 删除可以有两种做法: 1.利用tableNode.deleteRow(index)/rows.remove(index) 2.利用tbodyNode.removeChild(rowObject) 三种删除动作会导致rows集合rowObject的index时刻该变 第一种需要根据index删除,操作起来相当麻烦 第二种获取删除行对象,那么可以为其手动指定一个编号便于获取. */ function deleteAttachment(count){ var trNode=byID("tr_"+count); trNode.parentNode.removeChild(trNode); }//简单做法,不为每行绑定一个id,利用事件源对象以及节点之间关系function deleteAttachment_2(){ var trNode=event.srcElement.parentNode.parentNode; trNode.parentNode.removeChild(trNode); } </script> </head> <body> <table id="tableID"> <tr> <td><a href="javascript:void(0)" onclick="addAttachment()">点击添加附件</a></td> </tr> </table> </body> </html>在这个例子中想到的一个问题:
JS单引号与双引号问题:
trNode.insertCell().innerHTML
="<a href='javascript:void(0)'onclick='deleteAttachment("+count+")'>删除</a>";
该如何书写传入字符串常量?
正确书写方式"<a href='javascript:void(0)'onclick='deleteAttachment(\"abc\")'>删除</a>";
var str="abc";
="<a href='javascript:void(0)'onclick='deleteAttachment("+str+")'>删除</a>";//失败
可以这样书写:
var str="\"abc\""//外层的""表示他是一个字符串,内层\" \"当它在" "内部时把abc当成字符串解析
//str="abc",这样书写会报:abc undefined 被当成未初始化的变量
"<a href='javascript:void(0)'onclick='deleteAttachment("+str+")'>删除</a>";由该篇博文得到的启发:http://cindysaj.iteye.com/blog/669797
2.邮件列表操作:(注意删除邮件)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>邮件列表综合功能</title> <script type="text/javascript" src="JS/documentTools.js"></script> <style type="text/css"> table{ border-collapse:collapse; width:500px; } table td{ border:1px solid #999; padding:10px; } table th{ border:1px solid #999; padding:10px; background-color:#099; } .evenLine{ background-color:#CCC; } .oddLine{ background-color:#999; } .highLight{ background-color:#FF9; } </style> <script type="text/javascript"> /*行颜色间隔显示,鼠标点击颜色变化,离开恢复原来颜色*/ window.onload=loadColor; function loadColor(){ var tableNode=byID("mailList"); for(var i=1;i<tableNode.rows.length-1;++i){ if(i%2==0) tableNode.rows[i].className="evenLine"; else tableNode.rows[i].className="oddLine"; var oldClass; tableNode.rows[i].onmouseover=function(){ oldClass=this.className; this.className="highLight"; } tableNode.rows[i].onmouseout=function(){ this.className=oldClass; } } } /*checkAll对应的事件处理方式*/ function checkAll(){ var checkboxNodes=byName("choose"); var checkAllNodes=byName("selectAll"); for(var index=0;index<checkboxNodes.length;++index) checkboxNodes[index].checked=event.srcElement.checked; event.srcElement==checkAllNodes[0]? checkAllNodes[1].checked=false:checkAllNodes[0].checked=false; //这里为了改变另一个已经被点击的全选的checked为false } /*反选,取消全选时置全选的checked为false*/ function cancelCheckAll(checkAllNodes){ for(var index=0;index<checkAllNodes.length;++index) checkAllNodes[index].checked=false; } /*将全选,反选,取消全选三个按钮用一个函数:*/ function choice(input){ var checkboxNodes=byName("choose"); var checkAllNodes=byName("selectAll"); for(var index=0;index<checkboxNodes.length;++index)//全选,取消全选,反选均需要获取与设置 //checkbox状态,都需要遍历 switch(input.value){ case "全选":checkboxNodes[index].checked=true;break; case "取消所选": checkboxNodes[index].checked=false; cancelCheckAll(checkAllNodes);break; case "反选":cancelCheckAll(checkAllNodes); checkboxNodes[index].checked=!checkboxNodes[index].checked//对当前状态取反 } } /*delSelected对应的事件处理方式*/ function delSelected(){ var flag=window.confirm("是否删除所选邮件?"); var checkboxNodes=byName("choose"); var deleteTrArr=new Array(),pointer=0;//为了便于操作把要删除的行先保留 if(flag){ for(var index=0;index<checkboxNodes.length;++index) if(checkboxNodes[index].checked){ deleteTrArr[pointer++]=checkboxNodes[index].parentNode.parentNode; } var tbodyNode=byTagName("tbody")[0]; for(var index=0;index<deleteTrArr.length;++index) tbodyNode.removeChild(deleteTrArr[index]); loadColor();//删除行会改变原有的行的奇偶排列要把行,需要颜色重新加载下 alert("删除成功!") } } </script> </head> <body> <table id="mailList"> <tr> <th><input type="checkbox" name="selectAll" onclick="checkAll()"/>全选</td> <th>发件人</td> <th>邮件内容</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三1</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose" /></td> <td>张三2</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三3</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三4</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三5</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三6</td> <td>新的邮件</td> </tr> <tr> <td><input type="checkbox" name="choose"/></td> <td>张三7</td> <td>新的邮件</td> </tr> <tr> <th><input type="checkbox" name="selectAll" onclick="checkAll()"/>全选</td> <th colspan="2"> <input type="button" value="全选" onclick="choice(this)"/> <input type="button" value="取消所选" onclick="choice(this)"/> <input type="button" value="反选" onclick="choice(this)"/> <input type="button" value="删除所选邮件" onclick="delSelected()"/> </th> </tr> </table> </body> </html>犯的错误:
tableNode.rows[i].onmouseover=function(){
oldClass=tableNode.rows[i].className
tableNode.rows[i].className="highLight";
}
//注意在页面加载时,JavaScript引擎先把循环执行完,为每一个行对象注册该事件
//那么i的值在不断自增,当页面加载完循环执行结束.
//当触发该事件时,i的值为9->tableNode.rows[i]为undefined
//我这里把事件的注册和事件的触发混淆,
//这里仅仅相当于一个赋值语句:
//tableNode.rows[i].onmouseover指向一个匿名函数对象当事件与函数同名:
window.onload=function(){
alert(3);
}
function onload(){
alert(10);
}
//IE10 下debug发现window.onload已经指向onload指向的函数对象
//但是并没有执行,最好不要同名.
3.表单验证1(主要熟悉JS中一些方法):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>表单验证1</title> <script type="text/javascript"> var submitFlag=false;//防止上来就点提交 function printText(spanNode,flag){ if(flag){ spanNode.innerHTML="<font color='green'>√</font>"; submitFlag=flag; } else{ spanNode.innerHTML="<font color='red'>×</font>"; submitFlag=flag; } } function checkUser(){ var userName=document.forms[0].user.value;//document.forms返回所有form对象集合 //id,tagname,name也可获取表单对象 var regex=new RegExp("^[a-zA-Z]{5}$")//JS中的正则和Java中的正则写法有略微区别 //[a-zA-Z]{5}该模式会匹配输入文本框中满足条件字符串的子串 //12abcde也将符合要求,它没有像Java中的正则限定位数为5位 //这时候必须加上^,$:分别匹配字符串的开始位置和结束位置 //在这里相当于拿整个字符串与模式匹配 var spanNode=document.getElementById("checkUser"); printText(spanNode,userName.match(regex)); } function checkPwd(){ var userPwd=document.forms[0].pwd.value; var spanNode=document.getElementById("checkPwd"); var regex=/^\d{6}$/; //JS正则特有写法,这里\d的\不需要转义,只有在字符串在需要 printText(spanNode,(regex.test(userPwd)));//test则依据是否有匹配返回true/false } function checkConfPwd(){ var userConfPwd=document.forms[0].confirmPwd.value; var userPwd=document.forms[0].pwd.value; var spanNode=document.getElementById("confirmPwd"); printText(spanNode,userConfPwd==userPwd); } function checkMail(){ var userMail=document.forms[0].mail.value; var regex=/^\w+@\w+(\.\w+)+$/; var spanNode=document.getElementById("mailInfo"); printText(spanNode,regex.test(userMail)); } function beforeSubmit(){ submitFlag?event.returnValue=true:event.returnValue=false; //以上有一步失败,将取消提交动作 //视频中提到,如果用户输入完所有项并且都符合要求,在submit前,又去修改了用户名//而输入光标未移动,又去点提交(注意:虽然你输入光标未移动,但是你去点击submit,userName会失去焦点再次触发onblur事件,那么就会在次校验) } </script> </head> <body> <form name="form" action="http://127.0.0.1" onsubmit="beforeSubmit()"><!--onsubmit在表单将要被提交时触发--> 用户名称:<input type="text" name="user" onblur="checkUser()"/> <span id="checkUser">用户名错误</span> <br/> <br/> 输入密码:<input type="text" name="pwd" onblur="checkPwd()"/> <span id="checkPwd"></span> <br/> <br/> 确认密码:<input type="text" name="confirmPwd" onblur="checkConfPwd()"/> <span id="confirmPwd"></span> <br/> <br/> 邮箱地址:<input type="text" name="mail" onblur="checkMail()"/> <span id="mailInfo"></span> <br/> <input type="submit" value="提交"/> </form> </body> </html>JS中String对象的match方法: (以下内容摘自W3CSchool)
match() 方法将检索字符串 stringObject,以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。1.如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配(搜寻符合模式的第一个子串,如果有定位符另考虑).如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式(正则表达式中的组)匹配的文本。
除了这些常规的数组元素之外,返回的数组还含有两个对象属性。index 属性声明的是匹配文本的起始字符在 stringObject 中的位置,input 属性声明的是对 stringObject 的引用。
例如:
var s = "The rainna in"
re=new RegExp("ai(nn)(a)+");
r = s.match(re);
alert(r+"..."+r.index+"..."+r.input)
/* ainna,nn,a...5...The rainna in */
2.如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到 stringObject 中的所有匹配子字符串。若没有找到任何匹配的子串,则返回 null。如果找到了一个或多个匹配子串,则返回一个数组。不过全局匹配返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。onsubmit="return beforeSubmit()" //beforeSubmit要有返回值
4.表单校验2:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>表单校验2</title> <style type="text/css"> table{ border-collapse:collapse; } table td,table th{ border:1px solid #00F; padding:10px; } table td{ background-color:#6C9; } table th{ background-color:#F90; } /*当文本框获取焦点的样式*/ .focus{ background-color:#9C0; } .original{ border:1px solid #CCC; background-color:#FFF; } .errorBorder{ border:2px solid red; } /*错误信息样式*/ .errorInfor{ color:#B50000; display:none; } </style> </head> <script type="text/javascript"> function changeTextBox(input){ input.className="original"; if(input.name=="userName")//页面打开,将焦点设置到userName文本框 input.focus(); input.onfocus=function(){ input.className="focus"; } } window.onload=function(){ var formNode=document.forms[0]; //为每个input控件注册focus事件和加载共同样式 changeTextBox(formNode.userName); changeTextBox(formNode.userPwd); changeTextBox(formNode.rePwd); changeTextBox(formNode.mail); } function check(inputNode,regex,divID){ var flag=false;//在最后提交时会用到 var divNode=document.getElementById(divID); if(regex.test(inputNode.value)){ inputNode.className="original"; divNode.style.display="none";//当用户输错,再次输入正确,隐藏错误信息 flag=true; } else{ inputNode.className="errorBorder"; divNode.style.display="block"; } return flag; } function checkUser(userNode){ return check(userNode,/^\w{3,5}$/,"userError"); } function checkPwd(pwdNode){ return check(pwdNode,/^\w{3,5}$/,"pwdError"); } function checkRePwd(rePwdNode){ var flag=false; var userPwdNode=document.getElementsByName("userPwd")[0]; var divNode=document.getElementById("pwdNotMatch"); if(rePwdNode.value==userPwdNode.value){ rePwdNode.className="orginal"; divNode.style.display="none"; flag=true; } else{ rePwdNode.className="errorBorder"; divNode.style.display="block"; } return flag; } function checkMail(mailNode){ return check(mailNode,/^\w+@\w+(\.\w+)+$/,"mailError"); } /*表单提交onsubmit事件对应处理方式*/ function submitForm(){ var formNode=event.srcElement; if(checkUser(formNode.userName)&&checkPwd(formNode.userPwd) &&checkRePwd(formNode.rePwd)&&checkMail(formNode.mail)) event.returnValue=true; else event.returnValue=true; } </script> <body> <form onsubmit="submitForm()"> <table> <tr> <th>注册表单</th> </tr> <tr> <td> <div>用户名</div> <input type="text" name="userName" onblur="checkUser(this)"/> <div class="errorInfor" id="userError">用户名错误,请按要求输入</div> <div>用户名必须是3-5位,由字母(a-z),数字(0-9),下划线(_)组成</div> </td> </tr> <tr> <td> <div>密码</div> <input type="password" name="userPwd"onblur="checkPwd(this)"/> <div class="errorInfor" id="pwdError">密码格式错误,请按规范输入</div> <div>密码必须是3-5位,由字母(a-z),数字(0-9),组成</div> </td> </tr> <tr> <td> <div>确认密码</div> <input type="password" name="rePwd" onblur="checkRePwd(this)"/> <div class="errorInfor" id="pwdNotMatch">两次密码输入不一致</div> </td> </tr> <tr> <td> <div>邮箱地址</div> <input type="text" name="mail" onblur="checkMail(this)"/> <div class="errorInfor" id="mailError">邮箱地址错误,请按要求填写</div> </td> </tr> <tr> <th> <input type="submit" value="提交" style="width:100px"/> </th> </tr> </table> </form> </body> </html>
5.关于测试以上表单校验发现的一个细节: (以下测试两种方法完成错误信息的隐藏与显示的测试)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Test</title> <style type="text/css"> .errorInfor{ color:#B50000; display:none; } </style> <script> function submitForm(formNode,index,checkUser){ var inputNode=document.forms[index].userName if(checkUser(inputNode)) event.returnValue=true; else event.returnValue=false; } function checkUser(inputNode){ var divNode=document.getElementById("divID"); if(inputNode.value=="abc"){ divNode.style.display="none"; return true; } else{ divNode.style.display="block"; return false; } } function checkUser_2(inputNode){ var divNode=document.getElementById("divUser"); if(inputNode.value=="efg"){ return true; } else{ divNode.innerHTML="用户名错误".fontcolor("red"); return false; } } </script> </head> <body> <form onsubmit="submitForm(this,0,checkUser)"> <input type="text" name="userName" onblur="checkUser(this)"/> <span class="errorInfor" id="divID">用户名错误</span><br/> <input type="submit" value="提交"/> </form> <br/> <form onsubmit="submitForm(this,1,checkUser_2)"> <input type="text" name="userName" onblur="checkUser_2(this)"/> <div id="divUser"></div> <input type="submit" value="提交"/> </form> </body> </html>1.采用页面写入错误信息,刚开始隐藏方式(display:none/block/inline)
有个细节:
当用户在点提交前,有错误的数据,再去修改正确后,此时输入光标仍然在文本框中,并且有错误提示.
此时点击submit
第一次点击:错误信息消除
第二次点击:提交.
2.而在JS中写入错误信息(innerHTML),则按上述情况只点击一次