19

I need to determine what caused a focus event.

Ideally, I want to differentiate between a click, a tab/keyboard input, and a manual (via code) trigger.

How can I do this?

I'm looking at the event object, but I'm not seeing anything too useful.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • Try to bind 'mouseover' event (or 'click'), and if it fires set some mouse flag, then check it in focus event – spacevillain Jul 17 '11 at 21:52
  • @spacevillain: can't click also be triggered by code? – PeeHaa Jul 17 '11 at 21:56
  • What about 'mouseover' followed by 'click'? You can check if mouse coordinates are in right bounds. Ugly, but I think it should work. What do you need this for? :-) – spacevillain Jul 17 '11 at 22:02
  • @spacevillain: an autocomplete feature. I want it to pop open whenever you click the element, or tab into the element and the element is blank, or if it was triggered via code, do nothing. – mpen Jul 17 '11 at 22:12
  • Not a duplicate but similar: http://stackoverflow.com/questions/6674669/in-jquery-how-can-i-tell-between-a-programatic-and-user-click/ – mu is too short Jul 17 '11 at 22:16

1 Answers1

11

If the focus comes from a $x.focus() call, then the event won't have an originalEvent property because there was no event from the browser so:

if(ev.hasOwnProperty('originalEvent')) {
    // Focus event was manually triggered.
}

To differentiate between keyboard and mouse based focus events, you could try binding a keydown handler to everything else to detect a Tab or Shift-Tab but that would be a gross hack and probably not reliable; for example, on an iPad, you don't hit Tab to move to the next field, you hit Next or Previous in the popup keyboard to move around and those may not register as key presses at all.

There's a similar question about click events that might be of interest as well:

In jQuery, how can I tell between a programmatic and user click?

As you note in the comments, you could trap click events to detect a mouse-based focus change and set a flag somewhere to remember it. Then you'd have this:

  1. If there is no originalEvent in the jQuery event then the focus change was triggered manually (i.e. $x.focus() or similar).
  2. If the click handler flag is set then the focus change came from a mouse action.
  3. Otherwise the focus change came from a keyboard event.

You'd have to be careful that your click and focus events came in the right order and you'd need to make sure the flag was cleared when you're done with it. This might not be bullet proof but maybe it doesn't need to be.

Community
  • 1
  • 1
mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 1
    I can use a `.click` handler to detect mouse clicks, and then a `.focus` handler with this `originalEvent` thing to differentiate between keyboard and trigger events. Seems to be working well. Thanks! – mpen Jul 17 '11 at 23:21
  • @Mark: Yeah `click` is probably a better call than trying to detect keyboard events. Then no `originalEvent` means it was triggered manually, click means it was caused by the mouse, otherwise it was from the keyboard. I'll add this to my answer for future reference. – mu is too short Jul 17 '11 at 23:39
  • On some browsers, recent Chrome at least, the `click` event occurs after the `focus` event. However, the `mousedown` event still reliably occurs before `focus`, so you can trap that to detect the focus cause. – DSimon Mar 26 '15 at 18:36
  • 2
    @DSimon But is the ordered guaranteed by any standard? – mu is too short Mar 26 '15 at 19:36
  • @muistooshort As far as I can tell, unfortunately no. :-( – DSimon Mar 27 '15 at 13:33
  • It would be fair to mention, that this is jQuery solution. I googled for 'originalEvent', tried to find it myself in event object, but there is nothing like that in pure JavaScript :/ – Martin Melichar Apr 03 '20 at 23:13
  • @MartinMelichar The question is tagged "jquery" and jQuery is mentioned a few times in the answer. jQuery provides its own version of the event object to (historically) normalize things across the various JavaScript implementations. Not sure if there is a pure-JavaScript solution. – mu is too short Apr 04 '20 at 01:54
  • @muistooshort I know, there are both jQuery and JavaScript tags for this question. So that is why I posted this. – Martin Melichar Apr 04 '20 at 12:18
  • Definitely a no-go with React, even if you rely on `event.nativeEvent`. – Slbox Mar 09 '21 at 19:54