1

I'm having some trouble figuring out how to close a div by clicking anywhere on the screen.

I'm currently toggling an 'active' class in order to display a drop down div, then attempting to remove that class by clicking on the body:

$(document).ready(function () {

    $('.navbar a').click(function () {
        $(this).next('.navbar-dropdown').toggleClass('active');
    });

    $(body).click(function() {
        if($('.navbar-dropdown').hasClass('active')){
            $('.navbar-dropdown').removeClass('active');
        }
    });

});

<ul class="navbar">
    <li>
        <a href="#">Link</a>
        <div class="navbar-dropdown">
            Dropdown Content
        </div>
    </li>
</ul>

However they are conflicting with each other, so as soon as the class is toggled on, the 'body' click toggles it off at the same time. Have spent some time looking on here and came across this method a few times:

$(document.body).click( function() {
    closeMenu();
});

$(".dialog").click( function(e) {
    e.stopPropagation();
});

However any attempts to configure this to work correctly seemed to fall on deaf ears!

SJOSE
  • 13
  • 4
  • Try some of the answers here https://stackoverflow.com/questions/714471/jquery-hide-element-when-clicked-anywhere-on-the-page –  Mar 01 '19 at 15:30
  • Have you tried $("body").click ? – Doug F Mar 01 '19 at 15:30
  • Of course that code will not work because you never renamed the class!!! You do not have an element with the class `dialog`....... It should be `.navbar-dropdown` – epascarello Mar 01 '19 at 15:58
  • epascarello - 'came across this method a few times' - I was referencing that as an example that I kept coming across, but my adaptations of it weren't working. – SJOSE Mar 01 '19 at 16:46

2 Answers2

2

The click event from the navbar is bubbling up to the body, so both events fire. stopPropagation() is one way to prevent that, but you need to do it in the navbar link's event handler, so it stops that particular event; not in a separate event handler as you had it.

Another change you might consider making is to only assign the body click handler when you need it, instead of firing all the time -- create that handler inside the navbar's click handler, and deactivate it again when it's used:

$(document).ready(function() {
  $('.navbar a').click(function(e) {
    var myDropdown = $(this).next('.navbar-dropdown');
    $('.navbar-dropdown.active').not(myDropdown).removeClass('active'); // close any other open dropdowns
    myDropdown.toggleClass('active'); // open this one
    $('body').click(function() {
      // no need for an if statement here, just use a selector that matches the active elements:
      $('.navbar-dropdown.active').removeClass('active');
      $('body').off('click'); // cancel the body's click handler when it's used
    });
    e.stopPropagation(); // prevent the navbar event from bubbling up to the body
  });
});
.active {
  color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="navbar">
  <li>
    <a href="#">Link</a>
    <div class="navbar-dropdown">
      Dropdown Content
    </div>
  </li>
    <li>
    <a href="#">Link 2</a>
    <div class="navbar-dropdown">
      Dropdown Content 2
    </div>
  </li>
    <li>
    <a href="#">Link 3</a>
    <div class="navbar-dropdown">
      Dropdown Content 3
    </div>
  </li>
</ul>

(If there's a chance you might need more than one separate click event handler on the body, you can namespace the event so you can control which one you're turning off:

$('body').on("click.myNamespace", function() {
  // do other stuff
  $('body').off("click.myNamespace")
})
Daniel Beck
  • 20,653
  • 5
  • 38
  • 53
  • Worked like a charm! Thank you so much Dan. – SJOSE Mar 01 '19 at 16:03
  • Have just noticed something with regards to this solution - If I have two instances of a dropdown and click the second one, the first one still displays at the same time and doesn't close/remove the active class. Any further ideas? or will I need to start assigning specific classes/ID's to each navbar-dropdown and relavant toggles? – SJOSE Mar 01 '19 at 16:49
  • If I'm understanding you correctly you're trying to make sure only one dropdown can be open at a time? I edited the answer above to handle that (you just need to have the "open" event remove the active class from the other dropdowns.) – Daniel Beck Mar 01 '19 at 18:18
  • 1
    That makes so much sense now it's in front of me, thanks again Dan. – SJOSE Mar 04 '19 at 09:15
1

I did the exact thing as you and it works for me. Are you sure you don't have any other event listeners attached? Or maybe a z-index on the menu bringing it underneath other elements?

$(document).click(function(e) {
  $(".dialog").text('closed')
});

$(".dialog").click(function(e) {
  e.target.innerText = 'open';
  e.stopPropagation();
});
.dialog {
  width: 200px;
  height: 200px;
  background: antiquewhite;
  text-align: center;
}
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class="dialog">open</div>
</body>

</html>
iacobalin
  • 523
  • 2
  • 9