在聚焦输入时将点击事件添加到正文,然后在模糊时删除它

时间:2013-06-21 02:17:26

标签: javascript jquery

我想要一个文本输入,当它有焦点时,在body的任何地方注册一个点击事件。但是当焦点从中删除时,该点击事件将从body中删除。可悲的是,我似乎无法理解它。

$(document).ready(function () {

    $("html").on("focus", "#asdf", function () {
        $("body").on("click", "*:not(#asdf)", wasItClicked);
    });

    $("html").on("blur", "#asdf", function () {
        $("body").off("click", "*", wasItClicked);
    });

});

function wasItClicked() {
    alert("yeah");
}

BIN

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

当#asdf被聚焦,并且点击了一些其他元素时,事件将按照mousedown,blur,mouseup,click进行触发。因此,在点击火灾之前已经删除了处理程序。

mousedown事件在模糊之前触发。如果您对mousedown而不是单击没问题,可以使用:

$(document).ready(function () {

    $("#asdf").on("focus", function () {
        $("body").on("mousedown", wasItClicked);
    });

    $("#asdf").on("blur", function () {
        $("body").off("mousedown", wasItClicked);
    });

});

(bin)

编辑:

您可以使用mousedown事件来帮助确定您是否因为点击而失去焦点,并在失去焦点时删除点击处理程序中的处理程序。

$(document).ready(function () {
  $("#asdf").on("focus",function() {
    $("body").on("mousedown", setDown);
    $("body").on("click", wasItClicked);
   });
  $("#asdf").on("blur", function() {
    if ($(this).attr("mouse") != "down") {
     $("body").off("mousedown", setDown);
     $("body").off("click", wasItClicked);
    }
   });
});

function setDown() {
   $("#asdf").attr("mouse","down");
}

function wasItClicked() {
   if ($("#asdf") != $(document.activeElement)) {
     $("body").off("mousedown", setDown);
     $("body").off("click", wasItClicked);
   }
   $("#asdf").attr("mouse","up");
   alert("yeah");
}

new bin

答案 1 :(得分:0)

您可以使用setTimeout在添加和删除事件时删除单击并使用名称空间,因为您可能会意外删除另一个单击处理程序,但最简单的方法是删除处理程序中的单击事件:

  ...
  $("body").on("click.fromasf", "*:not(#asdf)", wasItClicked);
  ...
  function wasItClicked() {
      $("body").off("click.fromasf");
      console.log("yeah");
  }

以下是使用超时的示例:

<!DOCTYPE html>
<html>
 <head>
<script src="jquery-1.9.0.js"></script>
<style>
</style>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>Example</title>
</head>
 <body>
     <input type="text" id="asdf" />
     <input type="text" id="Text1" />
  <script>
      $(document).ready(function () {

          $("html").on("focus", "#asdf", function () {
              console.log("adding click handler");
              $("body").on("click.fromasf", "*:not(#asdf)", wasItClicked);
          });

          $("html").on("blur", "#asdf", function () {
              setTimeout(function () {
                  console.log("remove click");
                  $("body").off("click.fromasf");
              }, 500);
          });

      });

      function wasItClicked() {
          console.log("yeah");
      }
  </script>
 </body>
</html>

答案 2 :(得分:0)

好的,我看到了几个问题......

  1. 您将焦点事件委托给事件的HTML元素 单个元素...这有点矫枉过正,所以我会把 直接在focus
  2. 上发生blurinput个事件
  3. 当您致电off时,您需要在第二个参数
  4. 中传递完全相同的选择器
  5. 您的点击事件被委托给正文,并触发任何被点击并与选择器匹配的子元素 - 这不包括body本身...不确定您是否想要这样,但是我将其移至html元素,以包含body
  6. 一旦input失去焦点,该事件将被删除,因此点击不会注册(您可以使用超时作为答案中建议的@HMR)
  7. 我在仍然返回输入的html元素上的委托有一些问题(尽管有:not(#asdf)选择器)所以我只是将过滤器放入函数中。

    以下是修订后的代码(测试版):

    var click_selector = ":not(#asdf)";
    var click_target   = 'html';
    
    $(document).ready(function () {
    
        $("#asdf").on("focus", function () {
            $(click_target).on("click", click_selector,  wasItClicked);
        });
    
        $("#asdf").on("blur", function () {
            // Use timeout to be able to register the click before function is removed
            // NOTE that since 'click' fires when the mouse is released, if they
            //   hold the mouse down for a while, the event will be gone and won't
            //   register.  Maybe better to use 'mousedown' instead of 'click'
            //   in which case the timeout could probably be reduced to 10ms or something
    
            // Also, using timeouts creates the possibility of multiple click handlers
            // present at the same time (new one added before the previous is removed)
    
            setTimeout( function(){ 
                $(click_target).off("click", click_selector, wasItClicked);
            }, 100);
        });
    
    });
    
    function wasItClicked(e) {
      e.stopPropagation();
      e.preventDefault();
    
      if( e.target.id !== 'asdf' ){
        console.log('yeah', click_target, click_selector);
      }
    }