46

Is there something I can do like this (perhap via a plugin)

if ( ! $('form#contact input]').hasFocus()) {
  $('form#contact input:first]').focus();
}

Basically, set focus to the first input, but only if the user has not already clicked into anything?

I know this will work too, but is there anything more elegant?

$(function() {
  var focused = false;
  $('form#contact input]').focus(function() {
    focused = true;
  }); 
  setTimeout(function() {
    if ( ! focused) {      
      $('form#contact input:first]').focus();
    }
  }, 500);
});
alex
  • 479,566
  • 201
  • 878
  • 984

10 Answers10

63

There is no native solution but yes there is a more elegant way you can do it:

jQuery.extend(jQuery.expr[':'], {
  focus: "a == document.activeElement"
});

You're defining a new selector. See Plugins/Authoring. Then you can do:

if ($("...").is(":focus")) {
  ...
}

or:

$("input:focus").doStuff();
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 6
    Perhaps you should submit this for newer versions of jQuery, it would be useful. – gnarf Apr 21 '10 at 16:01
  • Any idea why `jQuery.expr` uses `==` rather than `===`? – Matt Ball Aug 26 '10 at 14:49
  • 4
    This can cause false positives. See http://stackoverflow.com/questions/967096/using-jquery-to-test-if-an-input-has-focus/5391608#5391608 for more information and a simple fix (thanks to Ben Alman and Diego Perini). – Mathias Bynens Mar 22 '11 at 13:02
  • @MLL: Is it just `eval()`'d? I've always written [my custom selectors](https://github.com/alexanderdickson/waitForImages/blob/master/jquery.waitforimages.js#L29) in a different way. – alex Dec 19 '11 at 23:13
  • 4
    as mentioned by others jquery now natively supports this :focus http://api.jquery.com/focus-selector/ – Simon_Weaver Mar 02 '13 at 08:25
27

$('input:focus')

It's CSS. You don't need to create a "custom selector." It already exists! http://www.w3schools.com/CSS/pr_pseudo_focus.asp

Just attach whatever process you want to do to that selector, and it will weed it out if the element in question is not focused. I did this recently to keep a keyup from instantiating an email input error check when the e-mail input wasn't being used.

If all you're trying to do is check if the user has focused on anything themselves, just do this:

if($('input:focus').size() == 0){
    /* Perform your function! */
}
dclowd9901
  • 6,756
  • 9
  • 44
  • 63
  • 1
    You are wrong. jQuery, unlike CSS, does not have `:focus` or `:hover` selectors. – SLaks Apr 21 '10 at 14:52
  • 1
    jQuery uses CSS selectors. If it works in CSS, it works in jQ. Trust me. If you have any doubt, try the form in this page and then inspect the JS: http://www.ddrewdesign.com/contact/ Trigger code is on line 124. I haven't tried `:hover` before though, so I can't speak for that. The trick is getting the JS to do the legwork so it is able to check, so you have to put it inside of an action of some sort. – dclowd9901 Apr 21 '10 at 14:55
  • Correct. jQ only recognizes pseudoclasses that its browser recognizes. – dclowd9901 Apr 21 '10 at 15:03
  • 3
    Someone ran through and downvoted (almost) all these answers for no readily apparent reason so +1 from me to counter – cletus Apr 22 '10 at 00:46
  • I'd say it would work due to being passed directly to `querySelectorAll()` or one of its cousins. If you used it with a jQuery custom thing, such as `:input`, it might not work (haven't tested it, would depend on how jQuery tokenizes the selector). – alex Jun 09 '15 at 12:34
12

jQuery 1.6 now has a dedicated :focus selector.

alex
  • 479,566
  • 201
  • 878
  • 984
9

I had trouble with cletus approach, using jQuery 1.3.2 and Firefox 3.6.8, because the string "a == document.activeElement" was not a valid function.

I fixed it defining a function for the focus key. In fact, all other keys defined in jQuery.expr[':'] are defined as functions. Here's the code:

jQuery.extend(jQuery.expr[':'], {
    focus: function(e){ return e == document.activeElement; }
});

So, now it works as expected.

However, I was experiencing some strange behaviour in Firefox 3.6.8 (maybe a bug in FF?). If I clicked on an input text while the page was rendering, and if I called is(":focus") on page load, I would get an error from the browser, reported by FireBug, and the script would break.

To solve this, I surrounded the code with a try...catch block, returning false on error. Use it if you want to prevent your users from experiencing the same error:

jQuery.extend(jQuery.expr[':'], {
    focus: function(e){
        try{ return e == document.activeElement; }
        catch(err){ return false; }
    }
});
luistamawong
  • 803
  • 8
  • 10
8

Frustratingly difficult to find a solution to this problem considering the solution is actually very simple:

if (document.activeElement == this) {
  // has focus
}

if (document.activeElement != this) {
  // does not have focus
}
user5185370
  • 81
  • 1
  • 2
7

No, there isn't.

However, you can simulate it like this:

$(':input')
    .data('focused', false)
    .focus(function() { $.data(this, 'focused', true); })
    .blur(function() { $.data(this, 'focused', false); });
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • all the answer's were except Vincent's (click on them). I'm +1'ing them all to counter that. – cletus Apr 22 '10 at 00:45
  • Don't know about the downvotes. Perhaps they did it when your answer was only the first line. Anyway, I gave you a +1 :) – alex Apr 22 '10 at 12:34
  • Note that you could use `$(this).data('focused', true)` now, etc. – alex Jun 09 '15 at 12:32
3

There is a plugin http://plugins.jquery.com/project/focused

Also you can check Using jQuery to test if an input has focus

Community
  • 1
  • 1
kasp3r
  • 310
  • 1
  • 13
  • Someone ran through and downvoted (almost) all these answers for no readily apparent reason so +1 from me to counter – cletus Apr 22 '10 at 00:46
2

Here is a succinct way to do it.

$(document.activeElement)

or to plug it into your example..

if ($('form#contact input]')[0]!=$(document.activeElement)) { ... }
JohnFx
  • 34,542
  • 18
  • 104
  • 162
  • 1
    The bottom one will never work as they will always be different jQuery collections. – alex Jun 09 '15 at 12:31
  • A minor change would work. A jquery element is an array with the javascript element in first position. It would work if you tweaked it to ($('form#contact input]')[0]!=document.activeElement) { ... } Your answer really helped me. – ShrapNull Jun 05 '18 at 20:31
1

I know this is an old question, but may be my solution will help someone :)

since this didnt worked for me:

if ($(this)!=$(document.activeElement)) { ... }

..were "this" is returned from blur function. So i did this:

if ($(document.activeElement).attr("class") != "input_textbox"){ ... }
ExEdzy
  • 129
  • 1
  • 8
  • The first solution wraps both in jQuery collections for no reason, and it will also fail as they will be the different objects. The second one is rarely a good way to check if an element is the one you match something as elements can have multiple classes. – alex Jun 09 '15 at 12:31
-2
    $('*:focus')

(Necro ftw, but still valid and useful)

Kafoso
  • 7
  • 1
  • The `*` shouldn't be required. – alex Jan 29 '14 at 01:57
  • Necroing is fine - questions and answers are timeless, and there's even a couple of badges for answering a question much later with a good score, like Necromancer. _However,_ I am downvoting this as it provides no guidance on how to check if specific elements have focus. Are you able to add that? – doppelgreener Mar 09 '15 at 01:19