admin管理员组

文章数量:1336116

Issue

I am creating a page at work for a client, with a slide out search bar. I want the focus (cursor) to move to the search bar (input) when I click a button that opens the search input field (it starts off hidden).

For some strange reason, the ONLY way I can seem to get the focus to switch the the input field is if I put it in a setTimeout with a minimum time of about 50ms (I tried 0, but doesn't work).

Weird caveat - I can momentarily that the input field gets focus/cursor when I close the search bar (click the open/close button that hides the search), but not when it opens, which is what I want. Unless it's in the setTimeout....

What I've tried

Setting the focus to something else, then blurring that, then setting the focus to my input field. [x]

  • Wrapping the .focus() in a setTimeout with 0 ms [x]

  • Setting the focus to a different, 'test' input field I created. [WORKS]

  • Adding tabindex to the input of -1 [x]

const icon = document.getElementById("search-icon");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");

icon.parentElement.addEventListener("click", e => {
  form.classList.toggle("visible");
  icon.classList.toggle("fa-search");
  icon.classList.toggle("fa-times");  

  setTimeout(() => input.focus(), 50);

});
<div class="header__search">
    <i id="search-icon" class="fas fa-search">click me</i>
    <form
      id="search-form"
      class="header__search-area"
      onclick="event.stopPropagation()"
    >
      <input
        id="search-input"
        tabindex="-1"
        type="text"
        placeholder="Enter Search Term..."
      />
      <button type="submit">search</button>
    </form>
</div>

Issue

I am creating a page at work for a client, with a slide out search bar. I want the focus (cursor) to move to the search bar (input) when I click a button that opens the search input field (it starts off hidden).

For some strange reason, the ONLY way I can seem to get the focus to switch the the input field is if I put it in a setTimeout with a minimum time of about 50ms (I tried 0, but doesn't work).

Weird caveat - I can momentarily that the input field gets focus/cursor when I close the search bar (click the open/close button that hides the search), but not when it opens, which is what I want. Unless it's in the setTimeout....

What I've tried

Setting the focus to something else, then blurring that, then setting the focus to my input field. [x]

  • Wrapping the .focus() in a setTimeout with 0 ms [x]

  • Setting the focus to a different, 'test' input field I created. [WORKS]

  • Adding tabindex to the input of -1 [x]

const icon = document.getElementById("search-icon");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");

icon.parentElement.addEventListener("click", e => {
  form.classList.toggle("visible");
  icon.classList.toggle("fa-search");
  icon.classList.toggle("fa-times");  

  setTimeout(() => input.focus(), 50);

});
<div class="header__search">
    <i id="search-icon" class="fas fa-search">click me</i>
    <form
      id="search-form"
      class="header__search-area"
      onclick="event.stopPropagation()"
    >
      <input
        id="search-input"
        tabindex="-1"
        type="text"
        placeholder="Enter Search Term..."
      />
      <button type="submit">search</button>
    </form>
</div>

For a quicker understanding, you click the icon (id=search-icon), and it displays the form alongside it which is position absolute and contains the 'input' I want to focus on.

If anyone can explain this, amazing. Google hath provideth nay answers.

Share edited May 22, 2019 at 16:05 Chris Barr 34.2k28 gold badges103 silver badges153 bronze badges asked May 22, 2019 at 15:49 WillOSWWillOSW 1071 silver badge8 bronze badges 3
  • I've edited your question so the code is runnable, and the icon element is visible & clickable – Chris Barr Commented May 22, 2019 at 16:09
  • What's your browser? – Christian Vincenzo Traina Commented May 22, 2019 at 16:14
  • My browser is Chrome, although the same thing is happening in Firefox and Safari. Chris, the other chat is preventing me from adding ments and I can't 'chat' on SO yet. I am adding a visible class to the input, yes, which unhides it, but that's happening before the focus theoretically? – WillOSW Commented May 22, 2019 at 16:18
Add a ment  | 

1 Answer 1

Reset to default 7

Because you've just clicked something and set the focus with your mouse, and then you are immediately changing it. The first time you focus (when you click) needs to plete first.

instead you click just change the focus immediately without a delay if you did it on the mouseup event instead, since that is when the mouse button is released. See below.


Edit

One second thought... I'm not really sure any more. copied your code and removed the delay, but it works just fine.

const icon = document.getElementById("search-icon");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");

icon.parentElement.addEventListener("click", e => {
  form.classList.toggle("visible");
  icon.classList.toggle("fa-search");
  icon.classList.toggle("fa-times");  
  
  input.focus();

});
<div class="header__search">
    <i id="search-icon" class="fas fa-search">click me</i>
    <form
      id="search-form"
      class="header__search-area"
      onclick="event.stopPropagation()"
    >
      <input
        id="search-input"
        tabindex="-1"
        type="text"
        placeholder="Enter Search Term..."
      />
      <button type="submit">search</button>
    </form>
</div>

本文标签: javascriptWhy does JS focus() only work inside a setTimeout of 50ms or longerStack Overflow