Search code examples
javascriptjquerytoggledelay

jquery delay toggle searchbar


I'm new to coding and I'm trying to get my searchbar to toggle when hovering over a button. I want it to toggle with a delay. Here's what I've come up with so far:

$( document ).ready(function() {
    console.log( "ready!" );
    $("#search-form").hover(
      function(){
          $("#search-input").delay(700).toggleClass("collapse");
      }
  )
});

And here the HTML:

<form id="search-form" style="display:flex-end;" class="form-inline my-2 my-lg-0">
          <button class="btn btn-search" type="submit" data-toggle="collapse">
          </button>
          <input id="search-input" class="collapse form-control" type="text" placeholder="Search..." name="search">
        </form>

So the toggle works, but it seems to just ignore the delay. Where did I go wrong? Not sure if relevant, but I'm using bootstrap 4.5.
Appreciate the help!


Solution

  • From the jQuery API documentation:

    The .delay() method is best for delaying between queued jQuery effects. Because it is limited—it doesn't, for example, offer a way to cancel the delay—.delay() is not a replacement for JavaScript's native setTimeout function, which may be more appropriate for certain use cases. (https://api.jquery.com/delay/)

    It is not perfectly documented (as far as I can tell), but toggleClass() is not a function that uses the built-in effects queue.

    Easiest solution is to use the vanilla window.setTimeout() function:

    $( document ).ready(function() {
        console.log("ready!");
        $("#search-form").hover(function() {
          window.setTimeout(function() {
              $("#search-input").toggleClass("collapse");
          }, 700)
        });
    });
    

    PS: The above solution, while it will technically work, it will not behave how you'd expect to, when you're moving fast on/off the form with the mouse pointer. See the simulation below:

    $( document ).ready(function() {
        console.log("ready!");
        $("#search-form").hover(function() {
          window.setTimeout(function() {
              $("#search-input").toggleClass("collapse");
          }, 700)
        });
    });
    /* Border - just to highlight the form */
    #search-form {
      border: 2px solid red;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form id="search-form" style="display:flex-end;" class="form-inline my-2 my-lg-0">
              <button class="btn btn-search" type="submit" data-toggle="collapse">BUTTON
              </button>
              <input id="search-input" class="collapse form-control" type="text" placeholder="Search..." name="search">
            </form>

    Instead, you might want to opt for a CSS-only solution which avoids the above misbehavior automatically (using the transition CSS property and its delay option):

    // No JavaScript needed :)
    /* Border - just to highlight the form */
    #search-form {
      border: 2px solid red;
    }
    
    #search-form #search-input {
      visibility: hidden;
      transition: visibility 0s linear 0.7s;
    }
    #search-form:hover #search-input {
      visibility: visible;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <form id="search-form" style="display:flex-end;" class="form-inline my-2 my-lg-0">
              <button class="btn btn-search" type="submit" data-toggle="collapse">BUTTON
              </button>
              <input id="search-input" class="form-control" type="text" placeholder="Search..." name="search"><!-- NOTE: no `collapse` class here anymore -->
            </form>