捕获div焦点

时间:2014-06-15 18:30:56

标签: jquery html5 javascript-events focus

我有一个带有输入(子)的主div(父)和另外2个子div(可点击)。

我想捕获主要div的焦点输出事件 - 而不是在点击或聚焦输入或其他2个可点击的div时。我已经使用jQuery设置了一个事件处理程序来捕获所有元素上的focusin focusout事件。

当我点击输入

时,我看到的是什么
  1. 第一个输入是专注的
  2. 然后是主要的div。
  3. 如果我点击任何其他可点击的div

    1. 事件触发第一个焦点输入
    2. 然后主要div然后其他div获得焦点并且主要div获得焦点。
    3. 点击其他可点击的div时,我不希望主div失去焦点。

      我怎样才能实现这一目标?我想在松散焦点上验证输入,但是在点击其他div时不能验证

      到目前为止,这就是我所拥有的:Fiddle

      HTML:

      <div id="main">
          <input id="i" type="text" />
          <div id="Div2" class="icons" style="background-color:blue; right: 25px;" onclick="log('Clear Clicked');"></div>
          <div id="Div1" class="icons" style="background-color:red;" onclick="log('DD Clicked');"></div>
      </div>
      

      CSS:

      * {
          -webkit-box-sizing: border-box;
          /* Safari/Chrome, other WebKit */
          -moz-box-sizing: border-box;
          /* Firefox, other Gecko */
          box-sizing: border-box;
          /* Opera/IE 8+ */
      }
      #main {
          top: 50px;
          left: 200px;
          position: absolute;
          border: 1px solid #00bfff;
          width: 250px;
          height: 27px;
      }
      input {
          border: none;
          width: 248px;
          height: 25px;
          position: absolute;
          z-index: 200;
      }
      .icons {
          text-align:center;
          border:1px solid blue;
          height: 23px;
          width: 23px;
          position: absolute;
          top: 2px;
          right: 2px;
          z-index: 99999999999999999999999;
          background-position: center;
          background-repeat: no-repeat;
      }
      

      jQuery:

      $("#main").focusin(function () {
          log("Main div got focused");
      });
      
      $("#i").focusin(function () {
          log("input got focused");
      });
      
      $("#Div2").focusin(function () {
          log("dropdown div got focused");
      });
      
      $("#Div1").focusin(function () {
          log("clear div got focused");
      });
      
      $("#main").focusout(function () {
          log("Main div lost focused");
      });
      
      $("#i").focusout(function () {
          log("input lost focused");
      });
      
      $("#Div2").focusout(function () {
          log("dropdown div lost focused");
      });
      
      $("#Div1").focusout(function () {
          log("clear div lost focused");
      });
      
      function log(msg) {
          //window.console.log(msg);
          $("body").append("<p>" + msg + "</p>");
      }
      

      任何帮助或指导赞赏

5 个答案:

答案 0 :(得分:17)

这是一个最好的解决方法,因为我也有同样的问题^ _ ^

有一个事件的attr:“relatedTarget”

relatedTarget将提供此事件的下一个元素

因此,如果下一个元素不是你的盒子或盒子里的任何东西,那么就会引发焦点。

但是首先你必须让你的<div>元素可以集中,你必须像这样在div上添加tabindex =' - 1'

<div id="main" tabindex='-1'>

脚本很简短:

        $("#main, #main *").blur(function(e){
            if(!$(e.relatedTarget).is("#main, #main *")){
                //focus out.
            }
        });

焦点会丢失并进入#main,但是当你从#main区域丢失焦点时,你可以做任何事情。

这与您的要求略有不同,但我想这可能就是您想要的。 如果是这样,代码将非常干净。

答案 1 :(得分:1)

好的,所以看起来你正在构建某种输入小部件。我看到#main div是小部件的外部容器,输入用于输入文本,然后你有两个其他div作为按钮或其他东西。您希望在用户尝试退出窗口小部件时验证输入的值,并且您试图通过在focusout上侦听#main来捕获此事件。这不起作用,因为div不是可以获得焦点的元素。请参阅答案here了解更多信息。

我可以向你证明你的div不适合进行一些小实验:

如果您在e.stopPropagation()focusin听众中加入focusout作为输入,您会看到您的主要div实际上从未实际关注或未关注本身;它刚收到focusinfocusup事件,因为它们从您的输入中冒出DOM树。

所以,这意味着我们必须从另一个角度解决你的问题。

让我们用简短的用户故事描述你的小部件失去焦点意味着什么:

  1. 用户点击输入/ #main / #Div1 / #Div2 - 小部件获得焦点
  2. 用户点击输入(如果他/她尚未输入)并输入一些文字 - 小部件焦点不会丢失
  3. 用户点击#main上的某处 - 小部件焦点不会丢失
  4. 用户点击#Div1,然后#Div2 - 小工具焦点不会丢失
  5. 用户点击页面上的其他位置 - 窗口小部件焦点 丢失 - &gt;验证运行
  6. 我们现在确切知道哪些状态应该导致验证运行。

    首先,让我们用布尔变量跟踪小部件的“焦点”状态:

    var isFocused = false;

    小部件从未聚焦状态开始,当#main或其子级中的任何位置发生单击或者输入以某种方式聚焦时(可以通过选项卡进入)用键盘):

    $("#main").on('click',function(){
      isFocused = true;
    });
    $("#i").on('focus',function(){
      isFocused = true;
    });
    

    小部件变得不专心的唯一时间是a)它的焦点和b)用户点击页面上的其他位置:

    $(document).on('click',function(){
      if(isFocused){
        isFocused = false;
        //kick-off the validation check!
      }
    });
    

    但是,由于默认情况下所有事件都会冒出DOM树,#main内的多次点击会冒出document.body并触发验证检查。为防止这种情况发生,我们在stopPropagation的点击处理程序中点击事件调用#main

    $("#main").on('click',function(e){
      isFocused = true;
      e.stopPropagation();
    });
    

    就是这样!

    我希望我对你所追求的事情是正确的。

    这是一个带有上述代码的working fiddle

答案 2 :(得分:0)

这是一种简单的方法(据我所知)

$('#Div1').click(function(){
    log('Clear Clicked');
   //$('#main').focusin();
    $('#i').focus();
});
$('#Div2').click(function(){
   log('DD Clicked');
     //$('#main').focusin();
    $('#i').focus();
});

这里是fiddle

答案 3 :(得分:0)

基于此接受的答案Is there a way to use event.preventDefault with focusOut? If not, why?

$(document).on('mousedown', function (event) {
        target = event.target;
        main = document.getElementById("main");
        input = document.getElementById("i");

        if (target == input) return true;

        parent = event.target.parentNode;

        if (parent == main) {
            event.preventDefault();  //prevent default DOM action
            event.stopPropagation();   //stop bubbling
            return false;   // return
        }
});

答案 4 :(得分:0)

另一种解决方法是在运行focusout handler之前添加一个小的setTimeout。

您可以轻松地将要排除的元素列表列入白名单,并在获得焦点时将其与clearTimeout排除。