S.I.
S.I.

Reputation: 3375

Dropdown isn't closed when click outside of it

I'm trying to hide the dropdown menu when is clicked outside, but no success so far.

I've read about 10 or more threads here and tried different solutions.

This is the dropdown menu that I have

<div class="dropdown">
  <button onclick="myFunction()">Per Page</button>
  <div id="openmenu" class="dropdown-content">
    <a href="">15</a>
    <a href="">20</a>
  </div>
</div>

And the showing part

function myFunction() {
    document.getElementById("openmenu").classList.toggle("show");
}

I've tried this so far

Try 1:

function boxCloser(e){
  if(e.target.id != 'openmenu'){
     document.body.removeEventListener('click', boxCloser, false);
     $('.dropdown-content').hide();
  }
} 

Try 2:

$(document).on("click touchend", function(){
    $(".dropdown-content").removeClass("open");
});

Try 3:

$('body').not(".dropdown").off('click').on('click',function(){$(".dropdown").removeClass("show")});

and try 4

function hideDiv(){
    document.getElementsByClassName('dropdown')[0].classList.remove('hidden');
}

document.addEventListener("click", hideDiv, false);

None of them close the menu when I click outside the dropdown part.

Upvotes: 0

Views: 4056

Answers (4)

Khalid Khan
Khalid Khan

Reputation: 3185

 $(document).on("click", function(event){

        var $trigger = $(".dropdown");

        if($trigger !== event.target && !$trigger.has(event.target).length){

            $(".dropdown-content").slideUp("fast");

        }            

    });

try this

Upvotes: 0

Alex Grin
Alex Grin

Reputation: 3183

Looks like you're puzzled with class names of your elements. In different attempts you provided you use either openmenu ID, or dropdown-content class, or dropdown class for selecting the element, as well as different methods for hiding and showing the dropdown (show, hidden, open classes, etc.)

To fully answer your question one would need to see the corresponding CSS code: what styles do you use for showing and hiding dropdown? Also, how do you bind that boxCloser() function to some user event?

Anyway, assuming that you're able to open the dropdown, and the problem is only when closing it, try the following.

1. Update HTML

Update HTML of the button: remove onclick attribute and add a class name to it

<button class="dropdown-button">Per Page</button>

2. Use the following script (instead of yours)

  function onClick(event) {
    // if clicked on .dropdown-button, find .dropdown-content near it and toggle it
    if (event.target.classList.contains("dropdown-button")) {
      var content = event.target.parentElement.getElementsByClassName("dropdown-content")[0];
      if (content)
        content.classList.toggle("show");
    } else if (!event.target.matches(".dropdown *")) {
      // if clicked outside of dropdown, hide all dropdowns
      var allDropdowns = document.getElementsByClassName("dropdown-content");
      for (var i = 0; i < allDropdowns.length; i++)
        allDropdowns[i].classList.remove("show");
    }
  }

  document.addEventListener("click", onClick);

3. Update CSS

I don't know what your CSS is, so make sure you do not refer to #openmenu element by ID and use class name instead:

  .dropdown-content {
    display: none;
  }
  .dropdown-content.show {
    display: block;
  }

This should also work for multiple dropdowns and without jQuery.

If you want to use jQuery, the script can be simplified:

  function onClick(event) {
    if ($(event.target).is(".dropdown-button"))
      $(event.target).parent().find(".dropdown-content").toggleClass("show");
    else if ($(event.target).closest(".dropdown").length === 0)
      $(".dropdown-content").removeClass("show");
  }

  $(document).click(onClick);

Note that this code prevents dropdowns from hiding when you click inside of open dropdowns. It also allows multiple dropdowns to be opened simultaneously. You can modify the code to achieve the other behavior in these aspects, but it's outside of the scope of this question.

Upvotes: 0

Ekim
Ekim

Reputation: 1105

I'm assuming you have jQuery included as some of the question examples use it. The 'isMenuOpen' variable would have to be set to true when opening the menu. Though it is not strictly necessary and you can omit it.

working example: https://jsfiddle.net/3ut2yqj1/

<button id="open_menu"> open menu </button>    
<div id="menu" style="border: 1px solid black; width:100px; height:100px; display:none"> </div>

 var isMenuOpen= false;

 $("#open_menu").on('click',function()
 {
   isMenuOpen = true;
   $("#menu").show();
 });

  $(document).on('click', function (e) {
    if (($(e.target).closest('#menu').length == 0) && ($(e.target).closest('#open_menu').length == 0)) {
      if (isMenuOpen == true) {
        isMenuOpen = false;
        $("#menu").hide();
      }
    }
  });

Upvotes: 1

BenM
BenM

Reputation: 53198

Since you seem to have jQuery as an option, the following code is more suited as it will support multiple dropdowns (it isn't dependent upon the ID of the elements involved).

You need to stop the event propagating up the DOM when you click on the button, and then assign a click handler to document. This is achieved by returning false from the click handler on the button.

Please see the working demo below:

$(document).on("click touchend", function(e){
  $(".dropdown-content").removeClass("show");
});

$('.dropdown-content').prev('button').on('click', function(e) {  
  $(this).siblings('.dropdown-content').toggleClass('show');
  return false;
});
.dropdown-content {
  display: none;
}

.dropdown-content.show {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dropdown">
  <button>Per Page</button>
  <div id="openmenu" class="dropdown-content">
    <a href="">15</a>
    <a href="">20</a>
  </div>
</div>

Upvotes: 1

Related Questions