区分键盘/鼠标触发的焦点事件

问题描述 投票:0回答:6

我正在使用 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');
    }
});

谢谢

javascript jquery jquery-ui jquery-ui-autocomplete
6个回答
13
投票

我能想到的唯一方法是让处理程序监听

keypress
click
事件,并打开/关闭布尔标志。然后在输入的
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 上制作了一个小型工作原型(你不喜欢这个网站吗?)。 想要的话就来看看吧。

当然,这都是通过

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

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


8
投票

我发现实现这一目标的最简单、最优雅的方法是使用“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
}

我特别喜欢这样一个事实,即如果您只想为鼠标/键盘提供不同的视觉行为,则可以在样式表(它真正所属的位置)中实现这一点,而不是通过一些黑客事件检查Javascript(当然,如果您确实需要做一些不仅仅是纯粹视觉的事情,前一种方法可以让您用 Javascript 来处理它)。


7
投票

您实际上应该能够从传递到焦点事件的事件对象中确定这一点。根据您的代码结构,这可能会有所不同,但其中通常有一个名为

originalEvent
的属性,它可能嵌套到一定深度。更仔细地检查
event
对象以确定正确的语法。然后通过正则表达式测试
mousenter
keydown
。像这样的东西:

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

1
投票

这可以使用

mousedown
事件来处理,请参阅下面的示例。

this.focusFrom = 'keyboard' => 

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

handleMouseDown = () => {
    this.focusFrom = 'mouse';
}

handleOnClick = () => {
    this.focusFrom = 'keyboard';
}

0
投票

首先想到的是找到鼠标的位置,检查是否在元素的位置内

用它来存储元素的位置:

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!
   }
}

0
投票

我知道这个问题很久以前就有人问过。但如果有人想要解决方案,这里有一个带有文本输入的纯 JS 示例代码。

控制台还会告诉您事件发生的顺序。

const testInput = document.getElementById('testInput');
let click = false;

testInput.addEventListener('mousedown', (event) => {
  console.log('mousedown --->');
  click = true;
});


testInput.addEventListener('keydown', (event) => {
  console.log('keydown --->');
  click = false;
});


testInput.addEventListener('focus', (event) => {
  console.log('focus --->');
  if (click) {
    testInput.placeholder = "Through Mouseclick";
    testInput.classList.remove('key');
    testInput.classList.add('expand');
  } else {
    testInput.placeholder = "Through keyboard";
    testInput.classList.remove('expand');
    testInput.classList.add('key');
  }
});

testInput.addEventListener('blur', (event) => {
   // Reset flags and remove classes
   testInput.placeholder = "Enter your text   ";
   testInput.classList.remove('key');
   testInput.classList.remove('expand');
   click = false;
});
input[type='text'] {
  transition: width 200ms;
  width: 150px;
  padding: 10px;
  border-radius: 5px;
}

input[type='text'].key {
  outline: 1px solid blue;
}

input[type='text'].expand {
  outline: 2px solid green;
  width: 250px;
}
<a href="#dummy-link"> Dummy Link </a>
<br/>
<input type="text" id="testInput" placeholder="Enter your text "/>

© www.soinside.com 2019 - 2024. All rights reserved.