【问题标题】:Differentiate between focus event triggered by keyboard/mouse区分键盘/鼠标触发的焦点事件
【发布时间】:2011-04-13 17:44:27
【问题描述】:

我正在使用 jquery ui 自动完成功能,并希望在键盘交互和鼠标交互触发的焦点事件之间破译。我该怎么办?

$('input').autocomplete({
    source: function(request, response) {
        ...
    },
    focus: function(event, ui) {
        // If focus triggered by keyboard interaction
            alert('do something');
        // If focus event triggered by mouse interaction
            alert('do something else');
    }
});

谢谢

【问题讨论】:

  • 嗯,我知道用鼠标聚焦的唯一方法是click 事件,但是如何识别键盘焦点 - 好问题。我假设检查按下了什么键(仅 TAB?)是正确的想法,但我不太确定。也许检查click 是否在focus() 上被解雇?不知道该怎么做,但也许这会帮助那些想尝试一下的人。
  • 我试图分离的两件事实际上是使用箭头键向下/向上移动自动完成列表,并用鼠标悬停在自动完成列表项上。 UI 自动完成通过选择项目并关闭自动完成来处理鼠标点击 - 分别采用选择参数。

标签: javascript jquery jquery-ui jquery-ui-autocomplete


【解决方案1】:

我能想到的唯一方法是让处理程序监听keypressclick 事件,并打开/关闭布尔标志。然后在您输入的 focus 处理程序上,您可以检查您的标志的值是什么,然后从那里开始。

大概是这样的

var isClick;
$(document).bind('click', function() { isClick = true; })
           .bind('keypress', function() { isClick = false; })
           ;

var focusHandler = function () {
    if (isClick) {
        // clicky!
    } else {
        // tabby!
    }
}

$('input').focus(function() {
    // we set a small timeout to let the click / keypress event to trigger
    // and update our boolean
    setTimeout(focusHandler,100);
});

在 jsFiddle 上制作了一个小型工作原型(您不只是喜欢这个网站吗?)。 Check it out if you want.

当然,这都是在 <input> 上运行 focus 事件,但自动完成上的 focus 处理程序以相同的方式工作。

setTimeout 会引入一点延迟,但在 100 毫秒时,它可能可以忽略不计,这取决于您的需要。

【讨论】:

  • 也是一个好主意 - 但我实际上不是在寻找点击,而是在寻找悬停:)
  • 在这种情况下,将click 处理程序切换为hover(或者更好,我认为是mousein)处理程序应该不会太难。让我看看我能不能在一段时间内掀起一些东西。 :D
  • 焦点处理程序的setTimeout。好主意。
  • 我认为keydown事件更可靠
  • @emfi 是的,keydown 还检测 tab、alt、ctrl 等
【解决方案2】:

我发现实现这一目标的最简单、最优雅的方法是使用“What Input?”库。它很小(约 2K 缩小),让您可以在脚本中访问事件类型:

if (whatInput.ask() === 'mouse') {
  // do something
}

...以及(通过添加到文档body 的单个数据属性)样式:

[data-whatinput="mouse"] :focus,
[data-whatinput="touch"] :focus {
  // focus styles for mouse and touch only
}

我特别喜欢这样一个事实,即您只希望鼠标/键盘具有不同的视觉行为,它可以在样式表(它真正属于的地方)中做到这一点,而不是通过一些 hacky 的事件检查 Javascript(尽管当然,如果你确实需要做一些不仅仅是纯粹视觉的事情,前一种方法可以让你用 Javascript 来处理它。

【讨论】:

    【解决方案3】:

    您实际上应该能够从传递给焦点事件的事件对象中确定这一点。根据您的代码结构,这可能会有所不同,但其中通常有一个名为 originalEvent 的属性,它可能嵌套到一定深度。更仔细地检查event-object 以确定正确的语法。然后通过正则表达式测试mousenterkeydown。像这样的:

    focus: function(event, ui){
      if(/^key/.test(event.originalEvent.originalEvent.type)){
        //code for keydown
      }else{
        //code for mouseenter and any other event
      }
    }
    

    【讨论】:

    • event.originalEvent.originalEvent.type 在 Chrome v34 中给我Cannot read property 'type' of undefined
    • 问题是originalEvent 没有跨浏览器AFAIK规范化
    • 是的,这将是一个完美的解决方案,但它似乎只在 Firefox 中受支持:developer.mozilla.org/en-US/docs/Web/API/Event/…,他们不鼓励在生产中使用它。为尝试 +1。
    • 截至 2020 年 11 月,这种方法似乎可以在 Chrome、Firefox、Safari 和 Edge 上完美运行。即使 Firefox 文档说不支持,它也受支持。
    【解决方案4】:

    首先想到的是,你可以找到鼠标的位置并检查它是否在元素的位置内

    使用它来存储元素的位置:

    var input = $('#your_autocompleted_element_id'),
        offset = input.offset(),
        input_x = offset.top,
        input_y = offset.left,
        input_w = input.outerWidth(),
        input_h = input.outerHeight();
    

    然后用它来查找鼠标在窗口内的绝对位置:

    var cur_mx, cur_my;
    $(document).mousemove(function(e){
       cur_mx = e.pageX;
       cur_my = e.pageY;
    });
    

    然后在您的自动完成设置中:

    focus: function(event, ui) {
       // mouse is doing the focus when...
       // mouse x is greater than input x and less than input x + input width
       // and y is greater than input y and less than input y + input height
       if (cur_mx >= input_x && cur_mx <= input_x + input_w && cur_my >= input_y && cur_my <= input_y + input_h) {
          // do your silly mouse focus witchcraft here
       } else {
          // keyboard time!
       }
    }
    

    【讨论】:

    • ... 但是,在 Tab 键按下期间,鼠标光标总是有可能落在刚刚聚焦的元素上。 :p
    • 是的,这是个好主意。但正如 RIchard 指出的那样,如果鼠标碰巧位于自动完成区域上方,它将无法工作。为努力 +1!
    【解决方案5】:

    这可以使用mousedown 事件来处理,请参阅下面的示例。

    this.focusFrom = 'keyboard' => 
    
    onFocus = () => {
        if (this.focusFrom === 'keyboard') {
            // do something when focus from keyboard
        }
    }
    
    handleMouseDown = () => {
        this.focusFrom = 'mouse';
    }
    
    handleOnClick = () => {
        this.focusFrom = 'keyboard';
    }
    

    【讨论】:

    • @Tyler2P 你是什么意思?看起来像 ES6
    猜你喜欢
    • 2011-11-19
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 2011-03-06
    相关资源
    最近更新 更多