Sir.Nathan Stassen
Sir.Nathan Stassen

Reputation: 1881

Checking how an element gained focus

Context

I have a backbone app with an event listener for focus events on a textarea. Backbone uses jQuery events, so core of my question centers around jQuery focus events.

Question

Is there a way to tell how an element came into focus, be it by click or tab?

The behavior of how the cursor gets positioned needs to be handled differently between these two cases, however there doesn't seem to be a way to distinguish between the two offhand.

I could listen to click events, however will still need to listen to focus to capture tabbing - this will overlap with click event as it will also focus the textarea resulting in double events.

I may to rethink this entirely.

JSBin Example

$('textarea')
  .focus(function(event){
    console.log('You focused me by' + event.type);
  // Here I wish I know if the focus came from a 'click' or 'tab' events
  });
<!DOCTYPE html>
<html>
<head>
    <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
    <form>
        <input placeholder="focus me, then tab" type="text"><br>
        <textarea>Focus me via click.   Now try via tabbing.</textarea> 
    </form>
</body>
</html>

Upvotes: 0

Views: 1619

Answers (4)

Sir.Nathan Stassen
Sir.Nathan Stassen

Reputation: 1881

.onfocus() listener can get called in a number of ways which makes it a tricky even to bind to.

  • Click on element
  • Tab or Shift-Tab to element
  • jQuery programatic focus $( "#target" ).focus();
  • Switching between programs, and refocusing the internet browser

There is no unique identifier in the onfocus event to determine how it came into focus.

From what I found it is best to be more explicit and listen to click() and onkeyup() events to handle unique behaviors between them and avoid unexpected function calls (like the browser is refocused).

onkeyup() is great for capturing tab events as the tab key will be released 'up' when tabbing in, but not when tabbing out.

JSBin

$('textarea')
 .click(focusedBy)
 .keyup(checkTab);

function checkTab(event){
 if (event.keyCode === 9) {
  focusedBy(event);
 }
}

function focusedBy (event){
 console.log('You focused me by ' + event.type);
}

Upvotes: 1

dandavis
dandavis

Reputation: 16726

here's a scaling way to do it without rerouting events or simulating extra actions:

var targ=$('textarea');

targ.focus(function(event){
    console.log('You focused me by ' + targ.eventType);
  // Here I wish I know if the focus came from a 'click' or 'tab' events
  });

$("body").mousedown(function(e){
   targ.eventType="mouse";
 }).keydown(function(e){
   targ.eventType="keyboard";
 });

this uses the jQuery collection to store the last event type, which is set by document-wide handlers.

if you need to re-use this functionality on other input types, just add more selectors to targ and differentiate in the handler using event.target.

http://jsbin.com/ruqekequva/2/edit

Upvotes: 0

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

You could set a clicked variable on mousedown.

You'll need to blur the textarea on mousedown so that focus will will be triggered on mouseup:

var clicked= false;

$('textarea')
  .focus(function(event) {
    if(clicked) {
      $('#status').html('clicked');
      clicked= false;
    }
    else {
      $('#status').html('tabbed');
    }
  })
  .mousedown(function(event) {
    clicked= true;
    $(this).blur();
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <input placeholder="focus me, then tab" type="text"><br>
  <textarea>Focus me via click.   Now try via tabbing.</textarea> 
</form>
<div id="status"></div>

Upvotes: 0

japrescott
japrescott

Reputation: 5025

you will need a combo of focus, click and blur events to determine the origin of "getting focus". click->set value, focus -> check if that clickvalue was set -> do what you must -> reset on blur. you might also want to be looking out for ontouchdown

Upvotes: 0

Related Questions