Nesta
Nesta

Reputation: 1008

Close a dropdown completely before open another one

I'm building a dropdown menu and need to add the following functionality to it:

When one dropdown is open and you open another one the previous one needs to close completely before the new one starts to open no matter how fast or slow the dropdown speed is set to.

Click to see DEMO

JQuery

$(document).ready(function() {

$(".click").on("click", function(evt) {
   evt.stopPropagation();
  var th = $(this);

  if (th.hasClass("active")) {
    th.removeClass("active");
   th.parent().find(".showup").slideUp(900);
   $(".main-container").removeClass("black-bg");
  }else{
    $(".active").removeClass("active");
    $(".showup").slideUp(900);
    $(".main-container").removeClass("black-bg");
    setTimeout(function(){
    th.addClass("active");
    th.parent().find(".showup").slideDown(900);
$(".main-container").addClass("black-bg");
    },250);

  }

});
$(".showup").on("click", function(evt) {
    evt.stopPropagation();
});

});

$(document).on("click", function() {
    $(".active").parent().find(".showup").slideUp(900);
    $(".active").toggleClass("active");
    if ($(".main-container").hasClass("black-bg")) {
      $(".main-container").toggleClass("black-bg");
    }
});

Thank you for your help.

Upvotes: 0

Views: 62

Answers (2)

Muhammad Omer Aslam
Muhammad Omer Aslam

Reputation: 23738

You need to use .stop(clearQueue,jumpToEnd) along with the second parameter for the slideUp() and slideDown() i.e complete callback function to call once the animation is complete, called once per matched element.

you should first hide all open and then call the slideDown inside the complete callback of the slideUp so that once the opened menu is completely closed then the new drop-down should be opened.

Notice the 2 parameters passed to the stop() so that when you click simultaneously the animation should not keep on playing instead skips to the last state either shown or hidden

See a demo below.

$(document).ready(function() {
  $(".click").on("click", function(e) {
    var menu = $(this);
    toggleDropDown(menu);
  });

  $(document).on('mouseup',function(e) {
    var container = $("nav");

    // if the target of the click isn't the container nor a descendant of the container
    if (!container.is(e.target) && container.has(e.target).length === 0) {
      $('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
        $(".main-container").removeClass("black-bg");
        if ($('a.active').hasClass('active')) {
          $('a.active').removeClass('active');
        }
      });
    }
  });

});


function toggleDropDown(menu) {
  var isActive = $('a.active').length;
  $('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
    $(".main-container").removeClass("black-bg");
    if (menu.hasClass('active')) {
      menu.removeClass('active');
    } else {
      $('a.active').removeClass('active');
      menu.addClass('active');
      menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
        $(".main-container").addClass("black-bg");
      });
    }
  });
  if (!isActive) {
    menu.addClass('active');
    menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
      $(".main-container").addClass("black-bg");
    });
  }

}
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-size: 12px;
  font-family: Arial;
}

.nav-wrapper {
  width: 100%;
  overflow: hidden;
  background: #424242;
}

nav {
  width: 100%;
  margin: auto;
  overflow: hidden;
  background: #424242;
}

.nav-content {
  width: 100%;
  z-index: 999;
  background: #ccc;
}

.top-bar-section {
  float: right;
}

.top-bar-section a.active {
  background: #c8c8c8;
  color: #000;
}

.showup {
  display: none;
  background: #ccc;
  position: absolute;
  width: 100%;
  top: 50px;
  left: 0;
  z-index: 99;
  padding: 30px 15px 30px 20px;
}

p {
  font-size: 14px;
  line-height: 1.4;
}

li.nav-item {
  display: inline-block;
  background: #f5f5f5;
}

li.nav-item a {
  display: block;
  text-decoration: none;
  padding: 10px;
}

.main-container {
  width: 80%;
  height: 400px;
  margin: auto;
}

.black-bg {
  background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-wrapper">
  <nav>
    <div class="top-bar-section">
      <ul>
        <li class="nav-item">
          <a href="#" class="click">Nav item 1</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 1.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 2</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 2.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 3</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 3.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 4</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 4.
              </p>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </nav>
</div>
<div class="main-container">

</div>

Upvotes: 1

Hikarunomemory
Hikarunomemory

Reputation: 4305

Check if there are any .active, if yes, setTimeout() with 900 miliseconds, if no, setTimeout() with 0 miliseconds(actually it would be 4 miliseconds but it would never 100% accurate).

$(document).ready(function() {

  $(".click").on("click", function(evt) {
    evt.stopPropagation();
    var th = $(this);

    if (th.hasClass("active")) {
      th.removeClass("active");
      th.parent().find(".showup").slideUp(900);
      $(".main-container").removeClass("black-bg");
    } else {
      let ms = $(".active").length>0 ? 900:0;
      $(".active").removeClass("active");
      $(".showup").slideUp(900);
      $(".main-container").removeClass("black-bg");
      setTimeout(function() {
        th.addClass("active");
        th.parent().find(".showup").slideDown(900);
        $(".main-container").addClass("black-bg");
      }, ms);

    }

  });
  $(".showup").on("click", function(evt) {
    evt.stopPropagation();
  });

});

$(document).on("click", function() {
  $(".active").parent().find(".showup").slideUp(900);
  $(".active").toggleClass("active");
  if ($(".main-container").hasClass("black-bg")) {
    $(".main-container").toggleClass("black-bg");
  }
});
* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.nav-wrapper {
  width: 100%;
  overflow: hidden;
  background: #424242;
}

nav {
  /*width: 1024px;*/
  margin: auto;
  overflow: hidden;
  background: #424242;
}

.nav-content {
  width: 100%;
  z-index: 999;
  background: #ccc;
}

.top-bar-section {
  float: right;
}

.top-bar-section a.active {
  background: #f00;
}

.showup {
  display: none;
  background: #ccc;
  position: absolute;
  width: 100%;
  top: 70px;
  left: 0;
  z-index: 99;
  padding: 30px 15px 30px 20px;
}

p {
  font-size: 14px;
  line-height: 1.4;
}

li.nav-item {
  display: inline-block;
  background: #f5f5f5;
}

li.nav-item a {
  display: block;
  text-decoration: none;
  padding: 10px;
}

.main-container {
  width: 80%;
  height: 400px;
  margin: auto;
}

.black-bg {
  background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-wrapper">
  <nav>
    <div class="top-bar-section">
      <ul>
        <li class="nav-item">
          <a href="#" class="click">Nav item 1</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 1.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 2</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 2.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 3</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 3.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 4</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 4.
              </p>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </nav>
</div>
<div class="main-container">

</div>

Upvotes: 1

Related Questions