我正在使用 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');
}
});
谢谢
我能想到的唯一方法是让处理程序监听
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 毫秒时,根据您的需要,它可能可以忽略不计。
我发现实现这一目标的最简单、最优雅的方法是使用“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 来处理它)。
您实际上应该能够从传递到焦点事件的事件对象中确定这一点。根据您的代码结构,这可能会有所不同,但其中通常有一个名为
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
}
}
这可以使用
mousedown
事件来处理,请参阅下面的示例。
this.focusFrom = 'keyboard' =>
onFocus = () => {
if (this.focusFrom === 'keyboard') {
// do something when focus from keyboard
}
}
handleMouseDown = () => {
this.focusFrom = 'mouse';
}
handleOnClick = () => {
this.focusFrom = 'keyboard';
}
首先想到的是找到鼠标的位置,检查是否在元素的位置内
用它来存储元素的位置:
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!
}
}
我知道这个问题很久以前就有人问过。但如果有人想要解决方案,这里有一个带有文本输入的纯 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 "/>