95

Say I have a click handler defined:

$("#foo").click(function(e){

});

How can I, within the function handler, tell whether the event was fired programmatically, or by the user?

Jorrit Schippers
  • 1,538
  • 12
  • 17
Kevin Owocki
  • 1,368
  • 2
  • 11
  • 9
  • How does the program go about firing an event programmatically? – Clayton Jul 13 '11 at 06:05
  • 5
    Why do you need to distinguish the cases? – Damien_The_Unbeliever Jul 13 '11 at 06:09
  • 1
    @Clayton: `$x.click()` or `$x.trigger('click')`. – mu is too short Jul 13 '11 at 06:19
  • I had a situation with an image-slider that automatically scrolled through the images, and did so by triggering clicks on the correct nav item associated with the image. The trouble is, when the user clicks on the nav, the automatic rotation should stop. – Kasapo Aug 08 '12 at 15:15
  • 2
    This works in latest firefox, chrome and IE9. Why not accept the answer below with the highest votes?? @kevino – OZZIE Oct 10 '13 at 10:00
  • @Damien_The_Unbeliever - Not sure I understand your question, would the OP's answer affect the implementation? FWIW, in my case, I'm writing a click tracking library to track user engagement across my site, to that end, I don't want to gather clicks that were fired programmatically since they wouldn't tell me anything useful. – dyodji Mar 06 '14 at 18:55
  • @dyodji - you're resurrecting on quite an old question. But, for starters, there's not a clear line on programmatic vs user action - i.e. if a user makes use of assistive aids due to disabilities, should their actions be discriminated against? And if you're serious about your software development, you'll make use of automated testing - at which point, distinguishing between user actions and programmatic ones can only be detrimental (because you'll exhibit different behaviour under test) – Damien_The_Unbeliever Mar 06 '14 at 19:03
  • @Damien_The_Unbeliever - fair point about assistive aids, but not knowing how they work (nor how frequently), I can't say for sure that they wouldn't properly back fill click coordinate data or give some other indication of their use. As to the testing, there are definitely ways to code around that issue, akin to running tests against an instrumented build, which would never be pushed out live, yet are still considered valid testing targets. (e.g. possibly using something like [shikiryu's answer](http://stackoverflow.com/a/6674732/677381) below) – dyodji Mar 10 '14 at 17:30
  • @OZZIE What to do with such useless users? – Vishal Kumar Sahu Mar 23 '17 at 17:57

7 Answers7

124

You could have a look at the event object e. If the event was triggered by a real click, you'll have things like clientX, clientY, pageX, pageY, etc. inside e and they will be numbers; these numbers are related to the mouse position when the click is triggered but they will probably be present even if the click was initiated through the keyboard. If the event was triggered by $x.click() then you won't have the usual position values in e. You could also look at the originalEvent property, that shouldn't be there if the event came from $x.click().

Maybe something like this:

$("#foo").click(function(e){
    if(e.hasOwnProperty('originalEvent'))
        // Probably a real click.
    else
        // Probably a fake click.
});

And here's a little sandbox to play with: http://jsfiddle.net/UtzND/

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 4
    That's awesome ... I just thought to myself "maybe jQuery triggered events don't have mouse position information"! w00t! – Kasapo Aug 08 '12 at 15:14
  • 2
    This can be defeated in browsers that support createEvent. http://jsfiddle.net/UtzND/26 – Joe Enzminger Sep 15 '12 at 16:43
  • 2
    @JoeEnzminger yes but why would you defeat your own script so to speak...? – OZZIE Oct 10 '13 at 10:01
  • 3
    I'm concerned about a third party script generating a click event and my script handling it on the assumption that it was user generated (an actual click). – Joe Enzminger Oct 11 '13 at 13:35
  • 2
    @JoeEnzminger: All bets are off once your code is in the browser, there's nothing you can do that can't be defeated by a sufficiently clever person. I think the best you can do is check a bunch of things: Is there an `originalEvent`? Is it the right sort of thing? Are there coordinates anywhere? Are the coordinates consistent? Are the coordinates inside `#foo`? ... – mu is too short Oct 11 '13 at 17:01
  • @SuperUberDuper I'd think it would since it only relies on jQuery's behavior. However, I don't have access to IE8 to verify that. – mu is too short Aug 28 '15 at 17:13
  • This doesn't work with $x[0].click(); In that case, I think you'll have to check other values in the event (layerX, layerY, offsetX, offsetY, pageX, pageY, screenX, screenY). – NoBrainer Nov 11 '15 at 19:50
  • @NoBrainer: Not sure what you mean, the `hasOwnProperty` check seems to work fine with the latest jQuery (http://jsfiddle.net/oq5bk3qh/). Oh wait, you're talking about using the raw DOM function rather than the jQuery version, right? – mu is too short Nov 11 '15 at 20:13
  • @muistooshort correct. Is there a way to tell when using the raw DOM's click function? – NoBrainer Nov 12 '15 at 14:32
  • @NoBrainer: Have you checked the other properties you mentioned? I'm pretty sure any test you come up with can be circumvented. – mu is too short Nov 12 '15 at 19:46
  • How about e.isTrusted, can that be faked? – mohit bansal Jan 22 '16 at 18:42
  • @mohitbansal: I'm not certain but I think you're going about things the wrong way if it matters. You really can't trust anything that happens in a browser. – mu is too short Jan 22 '16 at 18:44
45

You can use an extra parameter as stated in the jQuery trigger manual:

$("#foo").click(function(e, from){
    if (from == null)
        from = 'User';
    // rest of your code
});

$('#foo').trigger('click', ['Trigger']);
reformed
  • 4,505
  • 11
  • 62
  • 88
Shikiryu
  • 10,180
  • 8
  • 49
  • 75
  • 3
    The only problem I see with this is that you can't distinguish between a normal click and `$x.click()`, the `.click()` caller has to explicitly tell you that they're faking it. This may or may not be an issue depending on what Kevin Owocki is up to. – mu is too short Jul 13 '11 at 06:25
  • 1
    @mu : I don't quite understand your difference between a "normal" click (user?) and the `$x.click()` which is the eventHandler (for user click, which may be "normal") – Shikiryu Jul 13 '11 at 07:54
  • 1
    The difference is that one comes from the user but the other from software. The fake click may be coming from a plugin or some other code that can't be modified to add the extra arguments. I'm not critizing your solution, just noting some possible holes. – mu is too short Jul 13 '11 at 08:07
  • Although mu is correct and this will not work in every situation, it was exactly what I was looking for, thank you! Didn't know I could pass the extra parameter like a var, but that's exactly what I needed to test for "real" clicks in a complicated UI that treats some "real" clicks as programmatic. Thanks for both incredibly useful solutions! – Phil Dec 01 '12 at 15:28
9

There is another question answered already.

How to detect if a click() is a mouse click or triggered by some code?

Use the which property of the event object. It should be undefined for code-triggered events

$("#someElem").click(function(e) {
    if (e.which) {
        // Actually clicked
    } else {
        // Triggered by code
    }
});

JsFiddle example - http://jsfiddle.net/interdream/frw8j/

Hope it helps!

reformed
  • 4,505
  • 11
  • 62
  • 88
Swanidhi
  • 2,029
  • 1
  • 20
  • 21
  • 2
    Doesn't always work. E.g. `select` would give an `e.which==undefined` even for a genuine event. – JNF Jan 31 '16 at 08:20
6

I have tried all above solutions.Nothing has been worked in my case. Below solution worked for me. Hope it will help you as well.

$(document).ready(function(){
  //calling click event programmatically
    $("#chk1").trigger("click");
});

$(document).on('click','input[type=checkbox]',function(e) {
  if(e.originalEvent.isTrusted==true){
   alert("human click");
  }
  else{
   alert("programmatically click");
  }
    
    });
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js">
</script>

<input type="checkbox" id="chk1" name="chk1" >Chk1</input>
<input type="checkbox" id="chk2" name="chk2" >Chk2</input>
<input type="checkbox" id="chk3" name="chk3" >Chk3</input>
Gauri Bhosle
  • 4,985
  • 1
  • 15
  • 19
4

DOM Level 3 specifies event.isTrusted. This is only currently supported in IE9+ and Firefox (based on my tests. I've also read (although not thoroughly researched) that it can be overridden in some browsers and is probably not yet 100% ready to actually be trusted (unfortunately).

This is a modified version of @mu's fiddle that works on IE and Firefox.

Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
  • Good point. I don't think anything is going to be 100% solid though. You'd have to mix in some tests to see if `isTrusted` is supported and not writeable. I think the real answer depends on the *why* behind this question and we never found out why. – mu is too short Sep 15 '12 at 16:55
  • @mu, I came to this question after asking a similar, but more general one. My "why" case is I want to make sure I am only performing an action (a financial transaction, albeit a small one) iff the user took direct affirmative action on the page. – Joe Enzminger Sep 15 '12 at 16:58
1

Vanila js solution:

document.querySelector('button').addEventListener('click', function (e){
    if(e.isTrusted){
        // real click.
    }else{
        // programmatic click
    }
});
Abhishek
  • 968
  • 10
  • 16
-1

Not going to participate in the intellectual discussion, the code which worked for me to filter .click() and .trigger('click') is-

$(document).on('click touchstart', '#my_target', function(e) {
    if (e.pageX && e.pageY) { // To check if it is not triggered by .click() or .trigger('click')
        //Then code goes here
    }
});
Vishal Kumar Sahu
  • 1,232
  • 3
  • 15
  • 27