175

The last example of jQuery's focus() documentation states

$('#id').focus()

should make the input focused (active). I can't seem to get this working.

Even in the console on this site, I'm trying it for the search box

$('input[name="q"]').focus()

and I'm getting nothing. Any ideas?

Sam Selikoff
  • 11,238
  • 9
  • 54
  • 94
  • 2
    Can you show us your code? – Adil Apr 07 '13 at 05:13
  • We'll have to know more, because it works fine for me: http://jsfiddle.net/G7hwR/1/ just click anywhere in the right panel and it focuses... – Rob G Apr 07 '13 at 05:17
  • Shouldn't the focus on this page work, though? The snippet I provided? – Sam Selikoff Apr 07 '13 at 05:18
  • It depends on what it's contained in; if it's not inside anything, it's likely being run before the page even renders... – Rob G Apr 07 '13 at 05:20
  • For those coming here from search: the browser's built in developer tools might interfere with the `focus()` funcionality. [More info](http://stackoverflow.com/a/41474220/722036) – aexl Jan 04 '17 at 22:25

18 Answers18

429

Actually the example you gave for focusing on this site works just fine, as long as you're not focused in the console. The reason that's not working is simply because it's not stealing focus from the dev console. If you run the following code in your console and then quickly click in your browser window after, you will see it focus the search box:

setTimeout(function() { $('input[name="q"]').focus() }, 3000);

As for your other one, the one thing that has given me trouble in the past is order of events. You cannot call focus() on an element that hasn't been attached to the DOM. Has the element you are trying to focus already been attached to the DOM?

Justin Warkentin
  • 8,501
  • 4
  • 30
  • 32
  • That was it. I swore it wasn't a timing issue (it was), but I was going crazy because it wasn't working from the console. I swear I've done it from the console before. Thanks! – Sam Selikoff Apr 07 '13 at 05:24
  • 1
    Great! Did that help with both of your problems? If so, could you mark it as the correct answer? I would much appreciate it :D – Justin Warkentin Apr 07 '13 at 05:35
  • 4
    don't use developer tools when only use $('input[name="q"]').focus();or not work – Amitābha Aug 19 '13 at 12:30
  • 13
    Wow, I'd been struggling on and off with this for months, I only just saw that this is caused by the developer console being open. Mine always is. Thank you! – Alex Turpin Nov 19 '13 at 22:30
  • 23
    +1 for "You cannot call focus() on an element that hasn't been attached to the DOM." Also, it seems you can't call it on hidden elements. – tandrewnichols Apr 20 '15 at 19:49
  • Can someone explain why you have to use setTimeout for this to work? It is working for me, but I would like more info into the "why". – Carey Estes Apr 30 '15 at 13:11
  • Simply because you need time to click on the page to move your browser's focus back to the page. Remember, the problem is that the page cannot steal focus from the developer console. That would be extremely annoying as a developer if the page could steal your focus. – Justin Warkentin Apr 30 '15 at 20:34
  • 1
    Using `setTimeout` to solve order of operations problems makes it a huge pain in the patooty to maintain. If a bug shows up it's really hard to debug. Wherever you are inserting the element into the DOM, it should call `.focus()` there. – Kevin Beal Aug 18 '15 at 21:38
  • 1
    @KevinBeal If you read the text above the example you will see that it is not instructing to use `setTimeout` as a solution. It is simply being used as a demonstration on this site of the dev console focus prevent jQuery `focus()` calls from working. It should never be used as a solution where it creates race conditions. – Justin Warkentin Aug 19 '15 at 06:50
  • I was having the same issue. My issue was happening because I was calling .focus() on an element that had its CSS 'display' property set to 'none'. I moved the call to .focus() to after a call to .show() and this solved it. – JulianDavid Dec 02 '15 at 23:05
  • The length of timeout does not seem to matter. In a similar situation, I was able to get away with a 1 millisecond timeout. – Jason L. Jan 22 '16 at 17:07
  • @JasonL. Your problem sounds like a simple timing issue. You most likely created an element and then tried to focus before attaching it to the DOM. In any case, if 1 ms timeout is working for you then 0 will probably work just as well. All that does immediately add the work to the event queue to run as soon as the current execution context completes. – Justin Warkentin Jan 23 '16 at 03:39
  • @JustinWarkentin, based on your solution, i should put first `$(window).focus();`, right? – ebram khalil Apr 07 '16 at 09:31
  • 1
    @ebramtharwat No, that will not work. The page cannot steal focus from the dev console. If you have the dev console focused you will not see `focus()` calls work on the page. That is why I did a `setTimeout()` in the answer here (don't do that in your code). It gives you time to click back on the page and see the `focus()` call work. – Justin Warkentin Apr 09 '16 at 19:46
  • I was trying to focus onto a field that was appearing in a Bootstrap modal. Adding a timeout with 500 ms fixed this for me. Without the timeout, the field wasn't getting put in focus. – Daniel Dewhurst Jul 26 '16 at 14:52
  • @DanielDewhurst Bootstrap provides an event so you can focus when it's ready. They give an example for focusing at the bottom of the modal section [here](https://getbootstrap.com/javascript/#modals). – Justin Warkentin Jul 26 '16 at 15:01
  • 1
    Should probably be mentioned that 3000 ms is way too much in probably all cases, used 200 ms for an input in a popup window. – David Jan 06 '17 at 11:52
  • 1
    @David The point of 3000 ms was to give time to click out of the dev console to demonstrate that the reason focus() wasn't working on this site was just that you can't steal focus from the dev console. In an app using a timeout is always a hack and a bad idea. Code should be refactored to be properly event driven so focus() is always called after the element is attached to the DOM and there is no possibility of a race condition. – Justin Warkentin Jan 06 '17 at 18:47
  • Thanks a lot @JustinWarkentin. I wanted to upvote 10 times but can't. You saved me. – Bhavik Shah Jun 12 '18 at 06:06
  • "as long as you're not focused in the console" I really feel like an idiot for not realizing that sooner, I just thought .focus() was broken and moved on – Dave Bry Jan 28 '19 at 23:53
  • Had the same problem while trying to set focus to an input field from a select2-enhanced select. A timeout of 1 sec was enough. Thanks – Emanuele Cipolla Oct 05 '19 at 11:31
  • This ultimately helped me solve a similar problem while trying to set focus inside an angular event handler: the element which I was trying to focus was still invisible (`display: none`) until the end of "current job".... turns out I needed a `async` or `animationFrame` scheduler, so angular could have enough time to display said element. – rslemos Sep 07 '20 at 17:22
  • Thanks! I have tried to focus from the code (not the console) - and it works! – Unkas Sep 29 '20 at 11:39
61

Found a solution elsewhere on the net...

$('#id').focus();

did not work.

$('#id').get(0).focus();

did work.

Cymro
  • 859
  • 1
  • 9
  • 23
  • 4
    I upvoted this solution merely because it worked for me when the more popular solution on this page did not. ;-) – chriv Jan 21 '16 at 19:56
  • The second option just seems to be grabbing the dom element and using the regular javascript version instead of the jquery version. – danielson317 Feb 26 '16 at 22:49
  • 7
    Could it be that you have multiple elements with id "id" on your page? The DOM will not break in this case but you can't assign focus to multiple elements either – DerpyNerd Aug 29 '16 at 07:56
  • I found I had to do this with a window.setTimeout with a delay of 0, and then all is well. Thanks. Everything else I tried failed in a bootstrap modal. – Wade Hatler Sep 24 '18 at 22:16
  • If there is a label with for="same_as_input_id", then you have to use .get(0). – Shimbala Sep 09 '20 at 07:14
  • Or even shorter: `$('#id')[0].focus();`. – rodrigocfd Apr 15 '21 at 18:30
  • This is still the only thing that works in 2021. I added first() to my selector but focus() would not work without explicitly adding [0]. ???!!!! – John Ohara May 22 '21 at 12:10
25

Some of the answers here suggest using setTimeout to delay the process of focusing on the target element. One of them mentions that the target is inside a modal dialog. I cannot comment further on the correctness of the setTimeoutsolution without knowing the specific details of where it was used. However, I thought I should provide an answer here to help out people who run into this thread just as I did

The simple fact of the matter is that you cannot focus on an element which is not yet visible. If you run into this problem ensure that the target is actually visible when the attempt to focus it is made. In my own case I was doing something along these lines

$('#elementid').animate({left:0,duration:'slow'});
$('#elementid').focus();

This did not work. I only realized what was going on when I executed $('#elementid').focus()` from the console which did work. The difference - in my code above the target there is no certainty that the target will infact be visible since the animation may not be complete. And there lies the clue

$('#elementid').animate({left:0,duration:'slow',complete:focusFunction});

function focusFunction(){$('#elementid').focus();}

works just as expected. I too had initially put in a setTimeout solution and it worked too. However, an arbitrarily chosen timeout is bound to break the solution sooner or later depending on how slowly the host device goes about the process of ensuring that the target element is visible.

DroidOS
  • 7,220
  • 11
  • 70
  • 142
  • The relevant hint for me was "ensure that the target is actually visible". this becomes relevant when trying to focus on conditionally rendered elements. – salgmachine Nov 04 '17 at 04:25
  • Or when element to focus has `visibility:hidden` - it won't get focused. – bakrall Jan 17 '20 at 11:25
  • ` you cannot focus on an element which is not yet visible` - I love you. By simply adding a 100ms timeout I could trigger the focus on my hidden search box. Thanks! – LuBre Jan 30 '20 at 17:28
  • Beware of timeouts. What works on your development machine may well not work on another one. – DroidOS Jan 30 '20 at 19:46
18

if you use bootstrap + modal, this worked for me :

  $(myModal).modal('toggle');
  $(myModal).on('shown.bs.modal', function() {
    $('#modalSearchBox').focus()
  });
Wolf359
  • 2,019
  • 1
  • 26
  • 48
11

Just in case anybody else stumbles across this question and had the same situation I had - I was trying to set the focus after clicking on another element, yet the focus didn't appear to work. It turns out I just needed an e.preventDefault(); - here's an example:

$('#recipients ul li').mousedown(function(e) {
    // add recipient to list
    ...
    // focus back onto the input
    $('#message_recipient_input').focus();
    // prevent the focus from leaving
    e.preventDefault();
});

This helped:

If you call HTMLElement.focus() from a mousedown event handler, you must call event.preventDefault() to keep the focus from leaving the HTMLElement. Source: https://developer.mozilla.org/en/docs/Web/API/HTMLElement/focus

Ben
  • 3,981
  • 4
  • 28
  • 49
  • 2
    The only one works! Trigger is a popup div, click hides the div and put some value in a text box (not the one need to be focused). Without preventDefault, that text box is always focused no matter what -__- – rlatief Jun 25 '18 at 20:23
4

I realize this is old, but came across it today. None of the answers worked for me, what I did find that worked was setTimeout. I wanted my focus to be placed on the input filed of a modal, using the setTimeout worked. Hope this helps!

  • Me too! AND the length of the timeout really made a difference. Stupid IE. – eaglei22 Mar 03 '17 at 14:21
  • 1
    But it's not working on mobile devices. Mobile browsers are ignoring in most of the cases everything what is inside setTimeout – Kosmonaft Jun 13 '17 at 02:57
  • 1
    As a rule of thumb, using `setTimeout` is a _bad_ solution. You can't guarantee execution time on the user's machine, so time-dependent stuff is extremely fragile. – Nathan Sep 13 '17 at 16:15
4

I also had this problem. The solution that worked in my case was using the tabindex property on the HTML element.

I was using ng-repeat for some li elements inside a list and I was not able to bring focus to the first li using .focus(), so I simply added the tabindex attribute to each li during the loop.

so now <li ng-repeat="user in users track by $index" tabindex="{{$index+1}}"></li>

That +1 was index starts from 0. Also make sure that the element is present in DOM before calling the .focus() function

I hope this helps.

Kumar Shubham
  • 464
  • 5
  • 16
3

Add a delay before focus(). 200 ms is enough

function focusAndCursor(selector){
  var input = $(selector);
  setTimeout(function() {
    // this focus on last character if input isn't empty
    tmp = input.val(); input.focus().val("").blur().focus().val(tmp);
  }, 200);
}
Abel
  • 3,317
  • 27
  • 28
2

For those with the problem of not working because you used "$(element).show()". I solved it the next way:

 var textbox = $("#otherOption");
 textbox.show("fast", function () {
    textbox[0].focus();
  });

So you dont need a timer, it will execute after the show method is completed.

Rolando Retana
  • 343
  • 4
  • 12
2

Had this issue again just now, and believe it or not, all I had to do was close the developer tools. Apparently the Console tab has the focus priority over the page content.

aexl
  • 3,472
  • 2
  • 36
  • 51
0

Make sure the element and its parents are visible. You cannot use focus on hidden elements

mariovials
  • 544
  • 6
  • 11
0

Pro tip. If you want to turn on focus from the dev console then just open the console as a separate window from the options tab. The latest Firefox and Chrome supports this feature.

KMA Badshah
  • 477
  • 2
  • 13
0

I tested code from Chrome's DevTool Console and the focus part not worked. I found out later the issue is only present if i run it from DevTool and if i implement the code to the website it works fine. Actually, the element got focused but the DevTool removed it immediately.

Tomer Shetah
  • 7,646
  • 6
  • 20
  • 32
0

In my case, and in case someone else runs into this, I load a form for view, user clicks "Edit" and ajax gets & returns values and updates the form.

Just after this, I tried all of these and none worked except:

setTimeout(function() { $('input[name="q"]').focus() }, 3000);

which I had to change to (due to ajax):

setTimeout(function() { $('input[name="q"]').focus() }, **500**);

and I finally just used $("#q") even though it was an input:

setTimeout(function () { $("#q").focus() }, 500);
Christian
  • 1
  • 2
0

You can try this id is tries

window.location.hash = '#tries';
Madhuka Dilhan
  • 1,224
  • 13
  • 19
0

I faced a similar issue and wrapping the event within setTimout function worked perfectly for me. But somehow it felt like this wasn't the best approach to resolve it (manually delaying the event).

However, In my case the focus event wasn't triggering as the element was invisible/hidden and it turns out that the element was visible after a few milliseconds as I was triggering the focus event within element.on("focus") function (which is a triggered when the element is clicked and the element is focused in).

This worked for me:

element.on("focus", (e) => {
  e.preventDefault();
  if (element.is(":visible")) {
    search_input.trigger("focus");
  }
});

-1

For my case I had to specify a tab index (-1 if only focusable via script)

<div tabindex='-1'>
<!-- ... -->
</div>
Alexandre Daubricourt
  • 1,771
  • 1
  • 17
  • 26
-2

ADDITIONAL SOLUTION Had same issue where focus() didn't seem to work but eventually it turned out that what was needed was scrolling to the correct position:

Community
  • 1
  • 1
Martin
  • 1,285
  • 14
  • 20