【问题标题】:jQuery handing both focus and click on an elementjQuery同时处理焦点和单击元素
【发布时间】:2011-02-03 17:18:28
【问题描述】:

我正在尝试确定工作流程以微调数据输入 Web 应用程序。在一个网页上绘制多个地址表单:

  1. Name___________
     Street_________
     Phone__________

  2. Name___________
     Street_________
     Phone__________

  [...many more...]

现在我想知道用户是否使用 Tab 键进入第二个“名称”字段(或该记录中的任何位置),或者他们是否使用鼠标单击它。 (或 shift-tab 反向移动。)

我在焦点和点击输入字段上都设置了一个处理程序:

$('input').click(function() { TabulateClick(this) });
$('input').focus(function() { TabulateFocus(this) });

在处理程序中,我确定用户正在处理哪个地址以及我们是否“切换”了地址记录。 (如果焦点在第一个地址的“电话”中,并且您单击相同地址中的“姓名”字段,那实际上并没有切换记录,所以我不将其制成表格。)

    function TabulateClick(field)
    {
         var currentAddressRecord = FindAddress(field);
         if ( lastAddressRecord != currentAddressRecord )
             switchedAddressesWithClick++;
         lastAddressRecord = currentAddress;
    }
    function TabulateFocus(field)
    {
         var currentAddress = FindAddress(field);
         if ( lastAddressRecord != currentAddressRecord )
             switchedAddressesWithTab++;
         lastAddressRecord = currentAddress;
    }

我的问题是,当我在字段中单击鼠标时,focus 事件首先会触发一个错误的switchedAddressesWithTab 并更改 currentAddress(这是)。当click 处理程序运行时,lastAddressRecord 被破坏了。

focus 处理程序内部是否有办法知道同一对象上存在待处理的click 事件?或者在click 处理程序中知道它以前只是由focus 处理的?

【问题讨论】:

    标签: javascript jquery events focus mouse


    【解决方案1】:

    我认为这是基于鼠标按下发生在焦点之前的事实。见demo

    var lastClick = null;
    $('input').mousedown(function(e) {
      lastClick = e.target;
    }).focus(function(e){
        if (e.target == lastClick) {
          console.log('click');
        } else {
          console.log('tab');    
        }
        lastClick = null;
    
    });
    

    为了修复 Josiah 发现的错误,我将代码更改为以下内容。见demo

    var lastFocusedElement = null;
    var isClick = false;
    $('input').mousedown(function(e) {     
         isClick= true;
    }).focus(function(e){
    
        // To prevent focus firing when element already had focus
        if (lastFocusedElement != e.target) {
            if (isClick) {
              console.log('click ----');
            } else {
              console.log('tab -----');    
            }
            lastFocusedElement = e.target;
            isClick = false;
        }
    });
    
    $(document.body).focus(function(){
      lastFocusedElement = document.body;
    });
    

    一个问题是,当您离开窗口并切换回来时,您没有得到“点击”或标签。您会在具有焦点的输入上获得焦点事件,但您无法确定它是选项卡还是单击,因为两者都不是。

    我认为这是最接近你的,我会在你的页面上试试这个,看看行为是否足够好。

    【讨论】:

    • @Juan - 因为我们今天进入 QA,当您通过标签浏览所有字段到正文时,然后单击控制台日志中的一个 click,tab
    • @Josiah:很好,但我不明白为什么会这样......我想我们为 OP 提供了两种大部分时间都有效的方法,但仍然在这方面再投入 2 分钟
    • @Juan - 是的,感谢您说服我在这个问题上花费比我预期的更多的时间;)我们能做什么,该死的开发人员。
    • @Josiah, @Juan -- 别难过,我花了一上午的时间。 :)
    • 不确定为什么“焦点”在跳出最后一个字段(进入位置栏)然后再次单击它后会触发两次,这就是导致我的解决方案失败的原因
    【解决方案2】:

    您可以在 jQuery 中使用 .on() 方法。这是在同一个元素上绑定两个事件的另一种方法。

    var hasClicked = false;
    $('.myinputfield').on('mousedown : click',function(e){
         if (e.type == 'mousedown') {
            // execute code
            hasClicked = true;
         }
         if(e.type == 'focus' && !hasClicked) {
            //execute code
            console.log(e.type)
         }
         hasClicked = false;
    });
    

    【讨论】:

      【解决方案3】:

      只需绑定焦点,然后检查事件是否e.which == 9 // tab

      我最初的想法没有奏效(感谢@Juan)。使用事件的组合应该让你到达你想去的地方。 如果用户单击文本框,则最后一次按键将不是选项卡。所有输入都在监视和存储最后一个键代码以传递给焦点事件。 here is the fiddle

      var lastKeyCode = 0;
      $('input').focus(function(e) {
          if(lastKeyCode == 9)
               // tabbed into field
          else
               // clicked into field
      }).keydown(function(e){
          if(e.which == 9) // added timeout to clear lastkeypress
              setTimeout(function(){lastKeyPress = 0}, 50);
          lastKeyPress = e.which; // store last key code
      });
      

      【讨论】:

      • 嗯,很有意思,这个测试了吗?
      • @Josiah:我认为这行不通——在 FF 中,即使我进入该字段,我也无法定义。
      • 不起作用:jsfiddle.net/3py9V。如果您提出未经测试的建议,您应该提及您的回答是未经测试的建议
      • @Juan 和@Andrew - 感谢您指出这一点。我更新了帖子。
      • 您最好保留以前的答案并添加更新,否则 cmets 没有意义。但这仍然不起作用......如果您单击第二个输入,然后单击选项卡,然后单击返回任一输入,它会认为它是一个选项卡。虽然大部分时间都有效
      猜你喜欢
      • 2019-11-20
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多