区分鼠标和键盘触发onclick
Posted
技术标签:
【中文标题】区分鼠标和键盘触发onclick【英文标题】:Differentiate between mouse and keyboard triggering onclick 【发布时间】:2011-11-19 20:52:18 【问题描述】:我需要找到一种方法来确定链接是否已通过鼠标单击或按键激活。
<a href="" onclick="submitData(event, '2011-07-04')">Save</a>
这个想法是,如果他们使用鼠标点击链接,那么他们可以继续使用鼠标来选择下一步做什么。但是,如果他们在页面上切换并切换到“保存”链接,那么我将打开下一行进行编辑(该页面就像一个电子表格,每一行都可以使用 ajax 进行编辑)。
我以为可以查询事件参数是哪个鼠标按钮被按下,但是当没有按钮被按下时,答案是0,和鼠标左键一样。他们我认为我可以从事件中获取 keyCode,但它会以未定义的形式返回,所以我假设鼠标事件不包含该信息。
function submitData(event, id)
alert("key = "+event.keyCode + " mouse button = "+event.button);
总是返回“key = undefined mouse button = 0”
你能帮忙吗?
【问题讨论】:
这种策略毫无意义。仅仅因为鼠标单击用于一次交互并不意味着用户想要使用鼠标进行所有交互,对于键盘事件也是如此。为什么要使用行为类似于按钮的链接? 这两个选择都超出了我的工资等级,尽管我明白第一个。这个想法是,某些高级用户(其中很少有人)会希望编辑页面上的每一行,就像电子表格一样,他们不喜欢在键盘和鼠标之间切换。其他用户只想编辑一行然后离开。如果在他们编辑完他们选择的行后,下一行变成了可编辑字段,他们会分心并可能也编辑该行。 【参考方案1】:处理mouseup
事件。
如果您之后立即收到click
,则可能是用鼠标完成的。
【讨论】:
【参考方案2】:您可以使用event.type
创建条件
function submitData(event, id)
if(event.type == 'mousedown')
// do something
return;
if(event.type == 'keypress')
// do something else
return;
注意:您需要附加一个支持这两种事件类型的事件。使用 JQuery,它看起来像 $('a.save').bind('mousedown keypress', submitData(event, this));
内联 onClick=""
不会帮助您,因为它总是会传递该单击事件,因为它就是这样被困住的。
编辑:这是一个工作演示,用原生 javascript 证明我的情况:http://jsfiddle.net/AlienWebguy/HPEjt/
我使用了一个按钮,以便在选项卡焦点期间更容易看到突出显示的节点,但它对任何节点都一样。
【讨论】:
我在这两种情况下都看到event.type
的“点击”。
这对我有用。由于只有在行变得可编辑时才会呈现保存按钮,所以我将研究 jQuery Live 以连接 mousedown 和 keypress 事件。干杯。
酷,但这并不能真正回答问题。鼠标按下不是单击。这是一种变通方法,它扭曲了单击的含义,即在同一元素上单击 mousedown,然后单击 mouseup。 Gonzalo 的解决方案保留了这个概念的含义。
不考虑“点击”行为。单击是鼠标在同一项目上按下和鼠标向上,还可以处理触摸感应设备上的长触摸或拖动触摸,还可以处理各种键盘“点击”。
mousedown
与click
不同(尽管在某些情况下可能足够接近)【参考方案3】:
您可以区分单击和键盘敲击,捕获和丢弃在按键时产生的 keydown 事件:
jQuery(function($)
$("a#foo").keydown(function()
alert("keyboard");
return false;
).click(function()
alert("mouse");
return false;
)
)
http://jsfiddle.net/NuP2g/
【讨论】:
+1 太棒了!这不仅是最优雅的答案,而且是真正唯一对保留“点击”概念含义的问题的实际工作答案。其他答案切换了 mousedown 或 mouseup 的单击(原始问题),这只是单击的一部分。没有人希望以鼠标按下的方式开始的 mouseup 将作为单击处理。不错! 从键盘“点击”有多种方式。通常它的 [ctrl+][alt+]enter 但其中许多在新选项卡中打开,因此应该保持一致,有时还有其他键盘快捷键。 这不适用于“Enter”键。它按顺序触发这两个事件。【参考方案4】:可以检查event.screenX
和event.screenY
是否为零。
$('a#foo').click(function(evt)
if (evt.screenX == 0 && evt.screenY == 0)
window.alert('Keyboard click.');
else
window.alert('Mouse click.');
);
Demo on CodePen
我无法保证它适用于所有浏览器和所有情况,但它的好处是不会尝试检测通过键盘完成的“点击”。因此,此解决方案更可靠地检测“点击”,但代价是检测它是来自键盘还是鼠标的可靠性稍差。如果您更喜欢 reverse,请查看 answer from @Gonzalo。
注意:我使用这种方法找到的一个地方是Chromium
【讨论】:
聪明。这是截至 2018 年 9 月页面上唯一有效的解决方案 但在 Safari 中不起作用。 Safari 默认屏幕坐标为目标元素的中心。 :( 我也使用过这种方法,但在@CraigKovatch 对 Safari 发表评论后,我注意到情况确实如此:它在 Safari (v13.1.1) 上不起作用。【参考方案5】:你可以使用 event.detail
if(event.detail === 0)
// keypress
else
// mouse event
【讨论】:
几乎完美。不适用于 Bootstrap 4 单选按钮,因为当活动单选按钮被鼠标单击两次时,会触发 两个 事件(一个用于美学按钮标签,一个用于后面的输入单选按钮) .第一个(对于 @Prid 也许您可以使用event.stopPropagation
找出解决方法?我不确定标签是否总是在您直接单击单选按钮时触发。
IE11 event.detail 对于鼠标和键盘点击事件都是 0 :(【参考方案6】:
我知道这是一个老问题,但考虑到我浪费了多少时间寻找一个工作的、没有 jquery 和 IE 兼容的解决方案,我认为把它放在这里并不是一个坏主意(我首先来到的地方) .
我对此进行了测试,发现它工作正常:
let mouseDown = false;
element.addEventListener('mousedown', () =>
mouseDown = true;
);
element.addEventListener('mouseup', () =>
mouseDown = false;
);
element.addEventListener('focus', (event) =>
if (mouseDown)
// keyboard
else
// mouse
);
来源链接:https://www.darrenlester.com/blog/focus-only-on-tab
【讨论】:
【参考方案7】:无法提出完全依赖事件的解决方案,但您可以将锚标记放置在按钮上并为其指定 tabindex
或 -1
。这为您提供了一个可以聚焦并与键盘输入/空格键接合的按钮,以及为您提供一个可点击的表面,让您可以选择区分两个代码路径。
.button
position: relative;
.anchor
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
<button id="button" class="button">
button
<a class="anchor" href="#example" tabindex="-1"></a>
</button>
【讨论】:
【参考方案8】:我使用以下
const isKeyboardClick = nativeEvent.detail === 0 && !nativeEvent.pointerType;
通过detail
和IE11 通过pointerType
在常青浏览器中工作。不适用于例如单选按钮 <input>
被 <label>
元素包裹。
【讨论】:
以上是关于区分鼠标和键盘触发onclick的主要内容,如果未能解决你的问题,请参考以下文章