简体   繁体   English

鼠标和键盘触发 onclick 的区别

[英]Differentiate between mouse and keyboard triggering onclick

I need to find a way to determine if a link has been activated via a mouse click or a keypress.我需要找到一种方法来确定链接是否已通过鼠标单击或按键激活。

<a href="" onclick="submitData(event, '2011-07-04')">Save</a>

The idea is that if they are using a mouse to hit the link then they can keep using the mouse to choose what they do next.这个想法是,如果他们使用鼠标点击链接,那么他们可以继续使用鼠标来选择下一步做什么。 But if they tabbing around the page and they tab to the Save link, then I'll open then next line for editing (the page is like a spreadsheet with each line becoming editable using ajax).但是,如果他们在页面上切换并切换到“保存”链接,那么我将打开下一行进行编辑(该页面就像一个电子表格,每一行都可以使用 ajax 进行编辑)。

I thought the event parameter could be queried for which mouse button is pressed, but when no button is pressed the answer is 0 and that's the same as the left mouse button.我认为可以查询事件参数以了解按下了哪个鼠标按钮,但是当没有按下任何按钮时,答案为 0,这与鼠标左键相同。 They I thought I could get the keyCode from the event but that is coming back as undefined so I'm assuming a mouse event doesn't include that info.他们我以为我可以从事件中获取 keyCode ,但它以未定义的形式返回,所以我假设鼠标事件不包含该信息。

function submitData(event, id)
{
    alert("key = "+event.keyCode + "  mouse button = "+event.button);
}

always returns "key = undefined mouse button = 0"总是返回“key = undefined mouse button = 0”

Can you help?你能帮我吗?

Could check if event.screenX and event.screenY are zero.可以检查event.screenXevent.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 CodePen 上的演示

I couldn't find a guarantee that it works in all browsers and all cases, but it has the benefit of not trying to detect a "click" done via the keyboard.我无法保证它适用于所有浏览器和所有情况,但它的好处是不尝试检测通过键盘完成的“点击”。 So this solution detects "click" more reliably at the cost of detecting if it's from keyboard or mouse somewhat less reliably .因此,该解决方案更可靠地检测“点击”,代价是检测它是来自键盘还是鼠标的可靠性稍差 If you prefer the reverse , look as the answer from @Gonzalo .如果您更喜欢相反的方式,请查看@Gonzalo答案

Note: One place I found using this method is Chromium注意:我发现使用这种方法的一个地方是Chromium

You can create a condition with event.type您可以使用event.type创建条件

function submitData(event, id)
{
    if(event.type == 'mousedown')
    {
        // do something
        return;
    }
    if(event.type == 'keypress')
    {
        // do something else
        return;
    }
}

Note: You'll need to attach an event which supports both event types.注意:您需要附加一个支持这两种事件类型的事件。 With JQuery it would look something like $('a.save').bind('mousedown keypress', submitData(event, this));使用 JQuery,它看起来像$('a.save').bind('mousedown keypress', submitData(event, this));

The inline onClick="" will not help you as it will always pass that click event since that's how it's trapped.内联onClick=""不会帮助你,因为它总是会传递点击事件,因为这就是它被困的方式。

EDIT : Here's a working demo to prove my case with native JavaScript: http://jsfiddle.net/AlienWebguy/HPEjt/编辑这是一个工作演示,用原生 JavaScript 证明我的情况: http : //jsfiddle.net/AlienWebguy/HPEjt/

I used a button so it'd be easier to see the node highlighted during a tab focus, but it will work the same with any node.我使用了一个按钮,因此在选项卡焦点期间更容易看到突出显示的节点,但它对任何节点的工作方式都相同。

You can use event.detail您可以使用 event.detail

if(event.detail === 0) {
    // keypress
} else {
    // mouse event
}

You can differentiate between a click and a keyboard hit capturing and discarding the keydown event originated at the moment of the key press:您可以区分单击和键盘点击捕获和丢弃在按键时产生的 keydown 事件:

jQuery(function($) {
    $("a#foo").keydown(function() {
        alert("keyboard");
        return false;
    }).click(function() {
        alert("mouse");
        return false;
    })
})

http://jsfiddle.net/NuP2g/ http://jsfiddle.net/NuP2g/

I know this is an old question but given how much time I lost looking for a working, no jquery and IE-compatible solution, I think it won't be a bad idea to put it here (where I came first).我知道这是一个老问题,但考虑到我浪费了多少时间寻找一个有效的、没有 jquery 和 IE 兼容的解决方案,我认为把它放在这里(我首先来的地方)并不是一个坏主意。

I tested this and found it working fine :我对此进行了测试,发现它工作正常:

let mouseDown = false;

element.addEventListener('mousedown', () => {
  mouseDown = true;
});

element.addEventListener('mouseup', () => {
  mouseDown = false;
});

element.addEventListener('focus', (event) => {
  if (mouseDown) {
    // keyboard
  } else {
    // mouse
  }
});

Source link : https://www.darrenlester.com/blog/focus-only-on-tab来源链接: https : //www.darrenlester.com/blog/focus-only-on-tab

Wasn't able to come up with solution relying entirely on the events but you can position an anchor tag over a button and give it a tabindex of -1 .无法提出完全依赖于事件的解决方案,但您可以在按钮上放置一个锚标记,并为其提供-1tabindex This gives you a button that can be focused and engaged with keyboard enter/spacebar, as well as giving you a clickable surface that gives you an option to differentiate the two codepaths.这为您提供了一个可以聚焦并与键盘输入/空格键接合的按钮,并为您提供一个可点击的表面,让您可以选择区分两个代码路径。

 .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>

I use the following我使用以下

const isKeyboardClick = nativeEvent.detail === 0 && !nativeEvent.pointerType;

Works in evergreen browsers via detail and IE11 via pointerType .通过detail在常绿浏览器中工作,通过pointerType在 IE11 中工作。 Does not work for the case where eg radio button <input> is wrapped by a <label> element.不适用于例如单选按钮<input><label>元素包裹的情况。

Nowadays, you can make use of instanceof which even has full browser support .如今,您可以使用具有完整浏览器支持instanceof

function onMouseOrKeyboardSubmit(event, id) {
    if (event instanceof KeyboardEvent) {
        alert("Submitted via keyboard");
    } else if (event instanceof MouseEvent) {
        alert("Submitted via mouse");
    } else {
        alert("Unexpected submit event");
    }
}

Handle the mouseup event.处理mouseup事件。
If you get a click right afterwards, it was probably done with the mouse.如果您之后立即click ,则可能是用鼠标完成的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM