152

I have a handler attached to an event and I would like it to execute only if it is triggered by a human, and not by a trigger() method. How do I tell the difference?

For example,

$('.checkbox').change(function(e){
  if (e.isHuman())
  {
    alert ('human');
  }
});

$('.checkbox').trigger('change'); //doesn't alert
felipsmartins
  • 13,269
  • 4
  • 48
  • 56
Dziamid
  • 11,225
  • 12
  • 69
  • 104

9 Answers9

225

You can check e.originalEvent: if it's defined the click is human:

Look at the fiddle http://jsfiddle.net/Uf8Wv/

$('.checkbox').change(function(e){
  if (e.originalEvent !== undefined)
  {
    alert ('human');
  }
});

my example in the fiddle:

<input type='checkbox' id='try' >try
<button id='click'>Click</button>

$("#try").click(function(event) {
    if (event.originalEvent === undefined) {
        alert('not human')
    } else {
        alert(' human');
    }


});

$('#click').click(function(event) {
    $("#try").click();
});
Nicola Peluchetti
  • 76,206
  • 31
  • 145
  • 192
  • 1
    @Nicola Is this documented anywhere? – Šime Vidas Jul 14 '11 at 11:15
  • @Sime i don't know, but i think it's standard. look here:http://api.jquery.com/category/events/event-object/ – Nicola Peluchetti Jul 14 '11 at 11:28
  • @Nicola I see, it's a jQuery thing. jQuery stores the original event object inside this property. Btw, what do you mean you don't know? You just provided the link to the documentation `:)` – Šime Vidas Jul 14 '11 at 11:41
  • @Sime i just meant that i didn't know if it was some kinf od ECMA standard! :) – Nicola Peluchetti Jul 14 '11 at 12:20
  • Doesn't work for delegated events as originalEvent is always undefined, e.g. http://jsfiddle.net/Uf8Wv/60/ – notacouch Nov 27 '13 at 02:22
  • I had to use `if( e.timeStamp )` instead. – skobaljic Feb 20 '15 at 14:46
  • 1
    Looks like you can also use `event.isTrigger` – avoliva May 28 '15 at 18:33
  • @avoliva i tested with jQuery 2.1.3 and it doesn't work – Nicola Peluchetti May 29 '15 at 18:57
  • This doesn't seem to work for scroll events either. originalEvent seems to always be defined. – kldavis4 Jul 27 '15 at 16:08
  • Doesn't work for me, though I am using jQuery 1.7. I don't have a choice. The workaround I figured out is that the originalEvent has mouse click coordinates; if the coordinates are both 0, I assume that it was a click triggered by jQuery. – Ten Bitcomb Nov 09 '15 at 18:31
  • @Nicola Peluchetti if event is dispatched using dispatchEvent then originalEvent wont be null and instead isTrusted will be false. so solution is not working for me. – Umer Hayyat Feb 08 '16 at 12:11
  • well it doesn't work for `$("#try")[0].click();` for which it show the click as 'human'. [The only solution worth mentioning](http://stackoverflow.com/a/29798519/3098962) and seem to be working on all scenarios and combination of clicks either from DOM or jQuery. But it doesn't work for keyboard focused button clicks using enter. – Anurag Aug 10 '16 at 22:44
  • 1
    @Anurag, I was running into the same issue just now. It looks like jQuery populates `originalEvent` when the event is triggered by `DOM.click()`, but you can use `$($("#try")[0]).click();`, which is clunky, but works. – Daniel Garrett Aug 11 '16 at 16:06
  • Useful for jQuery events, but using vanilla JavaScript to trigger events will remain undetected :( – jbob77435 Jan 08 '19 at 13:15
  • Whenever I am clicking on your fiddle example its showing "not human". Your answer isn't working @NicolaPeluchetti – Curious Developer Jun 11 '21 at 13:49
20

More straight forward than above would be:

$('.checkbox').change(function(e){
  if (e.isTrigger)
  {
    alert ('not a human');
  }
});

$('.checkbox').trigger('change'); //doesn't alert
Kenneth Spencer
  • 1,392
  • 12
  • 15
  • This is the best answer. For explanation, see: http://stackoverflow.com/questions/10704168/in-javascript-what-is-event-istrigger – jaredjacobs May 10 '13 at 21:42
  • 3
    While this is tempting and probably cozy in practice, note that the jQuery developers do not wish to graduate `isTrigger` to the public API [as of this time](https://github.com/jquery/api.jquery.com/issues/319). – Jon Sep 23 '13 at 12:53
11

Currently most of browsers support event.isTrusted:

if (e.isTrusted) {
  /* The event is trusted: event was generated by a user action */
} else {
  /* The event is not trusted */
}

From docs:

The isTrusted read-only property of the Event interface is a Boolean that is true when the event was generated by a user action, and false when the event was created or modified by a script or dispatched via EventTarget.dispatchEvent().

felipsmartins
  • 13,269
  • 4
  • 48
  • 56
  • 2
    Note that `isTrusted` doesn't actually mean "generated by a human", even though some docs summarize it that way. Those "or" clauses are important. See: https://stackoverflow.com/questions/36656858/why-does-calling-window-scroll-give-a-trusted-event – thomas88wp Aug 22 '22 at 20:30
8

I think that the only way to do this would be to pass in an additional parameter on the trigger call as per the documentation.

$('.checkbox').change(function(e, isTriggered){
  if (!isTriggered)
  {
    alert ('human');
  }
});

$('.checkbox').trigger('change', [true]); //doesn't alert

Example: http://jsfiddle.net/wG2KY/

detaylor
  • 7,112
  • 1
  • 27
  • 46
  • 1
    you can check out the property originalEvent of the event object: if the event doesn't come from a click, it's undefined – Nicola Peluchetti Jul 14 '11 at 11:13
  • [Passing data along with trigger](http://api.jquery.com/trigger/) is definitely the way to go for delegated events. [At least the click event doesn't seem to take parameters](http://jsfiddle.net/notacouch/Uf8Wv/69/). But [if you make a custom event then passing parameters should be no issue](http://jsfiddle.net/notacouch/Uf8Wv/68/). – notacouch Nov 27 '13 at 02:35
  • 1
    For some reason the event.originalEvent wasn't working for me (just kept returing 1) when using the 'click' handler of Zepto. So I tried the solution above. Worked like a charm. – larrydalmeida Sep 27 '16 at 07:48
7

Accepted answer didn't work for me. It's been 6 years and jQuery has changed a lot since then.

For example event.originalEvent returns always true with jQuery 1.9.x. I mean object always exists but content is different.

Those who use newer versions of jQuery can try this one. Works on Chrome, Edge, IE, Opera, FF

if ((event.originalEvent.isTrusted === true && event.originalEvent.isPrimary === undefined) || event.originalEvent.isPrimary === true) {
    //Hey hooman it is you
}
Ergec
  • 11,608
  • 7
  • 52
  • 62
1

Incase you have control of all your code, no alien calls $(input).focus() than setFocus().

Use a global variable is a correct way for me.

var globalIsHuman = true;

$('input').on('focus', function (){
    if(globalIsHuman){
        console.log('hello human, come and give me a hug');
    }else{
        console.log('alien, get away, i hate you..');
    }
    globalIsHuman = true;
});

// alien set focus
function setFocus(){
    globalIsHuman = false;
    $('input').focus();
}
// human use mouse, finger, foot... whatever to touch the input

If some alien still want to call $(input).focus() from another planet. Good luck or check other answers

vanduc1102
  • 5,769
  • 1
  • 46
  • 43
  • This only prevents people from calling `setFocus()` - it doesn't prevent people from triggering the focus event. Not writing `setFocus()` at all would also prevent people from calling it, so I don't see the benefit. In fact, people could still call `$('input').focus()` and have it pass. – Rob Jul 27 '17 at 05:38
  • If you are working in a closed environment with no other/3rd party scripting this would work in a perfect world. However most practical applications are for client sites that have all kinds of plugins and scripts added to them that very well may call that focus. One thing that might help this is to wrap your code (and any code that needs to call that function) in a scoped function like this: `(function(){/*your code here*/})();` This would keep the setFocus function safe from being called and the boolean from being changed by outside scripts. – Xandor Nov 13 '19 at 16:28
1

I needed to know if calls to the oninput handler came from the user or from undo/redo since undo/redo leads to input events when the input's value is restored.

  valueInput.oninput = (e) => {
    const value = +valueInput.value
    update(value)
    if (!e.inputType.startsWith("history")) {
      console.log('came from human')
      save(value)
    }
    else {
      console.log('came from history stacks')
    }
  }

It turns out that e.inputType is "historyUndo" on undo and "historyRedo" on redo (see list of possible inputTypes).

Ronald C
  • 171
  • 6
0

You can use onmousedown to detect mouse click vs trigger() call.

boateng
  • 910
  • 11
  • 21
  • 1
    I may not work on the following scenario : Sometimes is possible to select page's elements using the Tab key. For example, if I have selected in this way a checkbox, I can check/uncheck using the space key . Or even open a drodpdown using the down arrow key . – Diego Favero Nov 22 '17 at 13:18
-1

I would think about a possibility where you check the mouse position, like:

  • Click
  • Get mouse position
  • Overlaps the coords of the button
  • ...
Oldskool
  • 34,211
  • 7
  • 53
  • 66
Luke
  • 8,235
  • 3
  • 22
  • 36
  • 1
    I may not work on the following scenario : Sometimes is possible to select page's elements using the Tab key. For example, if I have selected in this way a checkbox, I can check/uncheck using the space key . Or even open a drodpdown using the down arrow key . – Diego Favero Nov 22 '17 at 13:18