Differentiate between mouse and keyboard triggering onclick

20,928

Solution 1

You can create a condition with 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));

The inline onClick="" will not help you as it will always pass that click event since that's how it's trapped.

EDIT: Here's a working demo to prove my case with native 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.

Solution 2

Could check if event.screenX and event.screenY are zero.

$('a#foo').click(function(evt) {
  if (evt.screenX == 0 && evt.screenY == 0) {
    window.alert('Keyboard click.');
  } else {
    window.alert('Mouse click.');
  }
});

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

Note: One place I found using this method is Chromium

Solution 3

You can use event.detail

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

Solution 4

You can differentiate between a click and a keyboard hit capturing and discarding the keydown event originated at the moment of the key press:

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

http://jsfiddle.net/NuP2g/

Solution 5

I use the following

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

Works in evergreen browsers via detail and IE11 via pointerType. Does not work for the case where e.g. radio button <input> is wrapped by a <label> element.

Share:
20,928
Craig
Author by

Craig

http://pct2007.org http://onemanwalking.com

Updated on January 06, 2022

Comments

  • Craig
    Craig over 2 years

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

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

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

    always returns "key = undefined mouse button = 0"

    Can you help?

  • mu is too short
    mu is too short over 12 years
    I'm seeing an event.type of "click" in both cases.
  • Craig
    Craig over 12 years
    This worked for me. Since the save button only gets rendered if the row has become editable I'll look into jQuery Live for hooking up the mousedown and keypress events. Cheers.
  • Ben
    Ben over 11 years
    +1 Excellent! This is not just the most elegant answer, but really the only actual working answer to the question that preserves the meaning of the "click" concept. The other answers switch out click (the original question) for either mousedown or mouseup, which are only part of a click. Nobody wants a mouseup that began as a mousedown on a different element to be handled as a click. Nice!
  • Ben
    Ben over 11 years
    Cool, but this doesn't really answer the question. A mousedown is not a click. This is a workaround that perverts the meaning of a click, which is a mousedown followed by a mouseup on the same element. Gonzalo's solution preserves the meaning of the concept.
  • Wernight
    Wernight over 8 years
    It doesn't take "click" behavior into account. A click is mouse down and mouse up on same item, handling also long touch or drag touch on touch-sensitive devices, handling also various keyboard "clicks".
  • Wernight
    Wernight over 8 years
    There are various ways to "click" from keyboard. Usually its [ctrl+][alt+]enter but many of those open in a new tab so that should remain consistent, and sometimes other keyboard shortcuts.
  • Roman Royter
    Roman Royter almost 8 years
    This doesn't work with "Enter" key. It fires both events sequentially.
  • SimplGy
    SimplGy over 5 years
    Clever. This is the only working solution on the page as of Sep 2018
  • Prid
    Prid almost 5 years
    almost perfect. Doesn't work for Bootstrap 4 radio buttons, as when the active radio button is Mouse-clicked twice, two events are triggered (one for the aesthetic button label, and one for the input radio button behind). The first one (for <label>) returns event.detail === 1 as expected, but the second one (for <input radio>) return event.detail === 0, probably because Bootstrap is handling the change in background. +1 for promising answer, and it'll work in most cases :)
  • lenny
    lenny over 4 years
    @Prid maybe you can figure out a workaround using event.stopPropagation? I'm not sure whether the label always fires even when you click directly on the radio button.
  • Craig Kovatch
    Craig Kovatch over 4 years
    Doesn't work in Safari, though. Safari defaults the screen coordinates to the center of the target element. :(
  • Craig Kovatch
    Craig Kovatch over 4 years
    IE11 event.detail is 0 for both mouse and keyboard click events :(
  • Jussi Virtanen
    Jussi Virtanen almost 4 years
    I had used this method too, but after @CraigKovatch's comment about Safari I noticed that that's indeed the case: it doesn't work on Safari (v13.1.1).
  • Mingwei Samuel
    Mingwei Samuel almost 3 years
    mousedown is not the same as click (although it may be close enough in some situations)
  • terryoboy
    terryoboy almost 2 years
    As of 2022, this is still the only working solution. At least in this thread. All ENTER, ARROW DOWN, and MOUSE CLICK events trigger the same evt.type value of click.