今天朋友问我一个js的问题,他是这么描述的:
页面上有些许文本框,但是要求获得焦点后就必须为其输入数据. 如果光标离开,
验证是否已经填入数据,如果没有填入数据就弹出提示对话框. 结束对话框后,
要求该文本框获得焦点,可以继续输入.
起初我没有在意,但是看了他的要求,我觉得应该很简单吧!后来看了看,似乎并不容易.
问题出现在怎么添加事件执行代码. 先贴一段代码,
为id为text的div标签下的所有文本框添加失去焦点的事件
1 <html> 2 <head> 3 <title></title> 4 <script type="text/javascript"> 5 function initialize() { 6 var text = document.getElementById("text").getElementsByTagName("input"); 7 for(var i = 0; i < text.length; i++) { 8 text[i].onblur = function() { 9 // 失去焦点的事件 10 } 11 } 12 } 13 14 onload = function() { 15 initialize(); 16 } 17 </script> 18 </head> 19 <body> 20 <div id="text"> 21 <input type="text" /><br /> 22 <input type="text" /><br /> 23 <input type="text" /><br /> 24 <input type="text" /><br /> 25 </div> 26 </body> 27 </html>
关于这个题目的问题就在于如何使文本框获得焦点.
要求失去焦点的时候检查是否有数据,没有数据弹出对话框,并要求当前文本框获得焦点
简单的想法就是
1 text[i].onblur = function() { 2 // 长度为零表示没有数据 3 if(this.value.length == 0) { 4 alert("请输入数据"); // 弹出对话框 5 this.focus(); // 获得焦点 6 } 7 }
感觉没什么问题,但是一到浏览器中执行就悲剧了.
因为会死在一个窗体事件的调用上. 怎么回事儿呢?
原来第一个文本框获得焦点的时候,如果没有输入数据,直接跳到第二个文本框
(或者是点击页面的其他地方,也或者让光标离开浏览器),都会触发离开的事件
1、如果是点击文本框,将鼠标离开文本框点击,也不点击其他文本框
-> 离开时首先判断文本框中是否有数据,即value.length == 0
-> 如果没有数据,则弹出对话框"请输入数据",同时文本框失去焦点
-> 待用户点击确认后,该文本框获得焦点
这样没有什么问题,但是如果点击的是下一个文本框就不一样了
2、点击第一个文本框,然后点击另一个文本框(悲剧了)
-> 第一个文本框失去焦点,第二个文本框得到焦点就触发了事件
-> 添加代码,得到焦点的代码,看看当第二个文本框获得焦点时事件的触发顺序
-> 先为每个文本框添加一个title属性,并一次赋值: 1,2,3,4
1 <div id="text"> 2 <input type="text" title="1" /><br /> 3 <input type="text" title="2" /><br /> 4 <input type="text" title="3" /><br /> 5 <input type="text" title="4" /><br /> 6 </div>
-> 再添加js代码
function initialize() { var text = document.getElementById("text").getElementsByTagName("input"); for(var i = 0; i < text.length; i++) { text[i].onfocus = function() { alert(this.title + "获得焦点"); } text[i].onblur = function() { alert(this.title + "请输入数据"); this.focus(); } } }
-> 使用IE8浏览器测试,鼠标离开首先弹出对话框"1请输入数据"
-> 随后是"2获得焦点", "2请输入数据", "1获得焦点", "1请输入数据", "2获得焦点", "2请输入数据", ...如此反复
-> 分析一下执行过程
-> 鼠标点击第二个文本框,触发失去焦点方法,弹出对话框"1请输入数据"
-> 点击弹出对话框确定按钮后,浏览器激活,第二个文本框获得焦点,触发方法,显示"2获得焦点",但是第一步中方法this.focus()没有执行
-> 结束这个弹出对话框,this.focus()方法被执行,由于this指第一个文本框,因此第一个文本框获得焦点
-> 焦点离开第二个文本框,触发离开的事件,显示"2请输入数据"
-> 结束后第一个文本框获得焦点,显示"1获得焦点",但是刚刚离开第二个方法的this.focus()方法没有执行
-> 因此结束弹出对话框后,执行this.focus()方法,第二个文本框获得焦点,继续离开第一个对话框,触发事件
-> 可以了解到,这里就进入了死循环,不断在两个文本框中跳来跳去
要解决这个问题,基本上就是在离开的时候获得焦点的情况
-> 期望的执行,应该是:第一个文本框获得焦点,点击第二个文本框,由于第一个文本框中没有数据,弹出对话框
-> 对话框结束,第二个文本框获得焦点,执行第一个对话框中的this.focus()方法,此时跳回第一个文本框
-> 关键点来了,在这里从第二个文本框中失去焦点,第一个文本框获得焦点时,不应该触发离开第二个文本框的事件
由于文本框添加方法是一起添加的,因此这里需要考虑,应该离开文本框时不是总是弹出对话框,也就是说,除了value.length == 0外还需要一个条件 理一理思路,要求应该是
-> 文本框离开的时候应该判断一下,应该操作的文本框是哪一个
-> 例如,开始点击第一个文本框时,应该操作的是第一个文本框
-> 当点击第二个文本框时,判断一下,当前操作文本框是不是第一个文本框