zoukankan      html  css  js  c++  java
  • 为页面上某些文本框添加离开验证输入事件

    今天朋友问我一个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外还需要一个条件 理一理思路,要求应该是
      -> 文本框离开的时候应该判断一下,应该操作的文本框是哪一个
      -> 例如,开始点击第一个文本框时,应该操作的是第一个文本框
      -> 当点击第二个文本框时,判断一下,当前操作文本框是不是第一个文本框
      -> 显然是,因此弹出对话框"1请输入数据",然后第二个文本框获得焦点
      -> 第一个方法的this.focus()方法执行,第二个文本框失去焦点,第一个文本框获得焦点
      -> 此时离开第二个文本框的时候,判断当前文本框. 显然当前文本框是第一个,因此不用弹出对话框

    有了这个思路,就知道了,只要添加一个全局变量记录当前对花框即可
    但是什么时候为这个变量赋值呢?当然是第一次获得焦点的时候. 不过这是有点疑虑.
      -> 在第一个文本框选中的时候,点击第二个文本框时,不应该为这个变量赋值
      -> 但是一开始第一个文本框获得焦点时,需要为这个变量赋值
      -> 如果第一个文本框正常输入数据后,切刀第二个文本框,应该为这个变量赋值

    因此基本操作为

      -> 定义一个变量current,赋值为null
        -> 由于所有方法都需要判断,将变量定义成全局的

    1 var current = null;

      -> 当文本框获得焦点的时候,判断current是否为null,为空时为其赋值,否则不变

    if(!current) {
        current = this;
    }

      -> 那么这个变量可以记录第一次选中的文本框,在失去焦点的方法中,如果当前文本框与这个变量不匹配,就不弹出"请输入数据"的对话框

    1 if(this == current && this.value.length == 0) {        // 判断是否是当前文本框,以及是否有数据
    2     alert(this.title + "请输入数据");
    3     this.focus();
    4 }

      -> 然后在正确输入数据离开该文本框时,将current清空,赋值为null

    1 if(this == current && this.value.length == 0) {
    2     alert(this.title + "请输入数据");
    3     this.focus();
    4 }
    5 else {
    6     current = null;
    7 }

    那么js代码可以修改为

     1 <script type="text/javascript">
     2     var current = null;
     3     function initialize() {
     4         var text = document.getElementById("text").getElementsByTagName("input");
     5         for(var i = 0; i < text.length; i++) {
     6             text[i].onfocus = function() {
     7                 if(!current) {
     8                     current = this;
     9                 }
    10             }
    11             text[i].onblur = function() {
    12                 if(this == current && this.value.length == 0) {
    13                     alert(this.title + "请输入数据");
    14                     this.focus();
    15                 }
    16                 else {
    17                     current = null;
    18                 }
    19             }
    20         }
    21     }
    22     onload = function() {
    23         initialize();
    24     }
    25 </script>
  • 相关阅读:
    Create a toolwindow for the VBA editor with .NET(C#).
    批量采集世纪佳缘会员图片及winhttp异步采集效率
    写了一个Windows API Viewer,提供VBA语句的导出功能。提供两万多个API的MSDN链接内容的本地查询
    mysql主从复制
    windows实现MySQL主从复制
    理解“业务逻辑”的含义
    数据库主从复制与读写分离(了解)
    windows下npm安装vue
    phpstorm中配置真正的远程调试(xdebug)
    PHP常量详解:define和const的区别
  • 原文地址:https://www.cnblogs.com/jiangkun86/p/2723700.html
Copyright © 2011-2022 走看看