1

I have a menu that open a sub-menu section onclick (let's name the container: "sub-menu"). I would like "sub-menu" to disapear if the user click outside of it / on the rest of the page.

It seems to be solved on How do I detect a click outside an element? But I can't get how to use the code snipet from the second most popular answer:

export function hideOnClickOutside(selector) {
  const outsideClickListener = (event) => {
    const $target = $(event.target);
    if (!$target.closest(selector).length && $(selector).is(':visible')) {
        $(selector).hide();
        removeClickListener();
    }
  }

  const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener)
  }

  document.addEventListener('click', outsideClickListener)
}

Could you please guide me on how to use it?

I edited, and included a basic example. -> I want sub menu to also close when clicking on the "white" space. But not on the parent "main menu" element.

document.getElementById("main-menu").addEventListener("click", function() {bouttonexpand('sub-menu-class')});

  function bouttonexpand(id) {
                var elemeacacher = document.getElementsByClassName(id);

    if (elemeacacher[0].style.display != "none"){
  
       for(var y=0;y<elemeacacher.length;y++)
       elemeacacher[y].style.display = "none";
       }
       
    else {
         for(var y=0;y<elemeacacher.length;y++)
       elemeacacher[y].style.display = "block";
       }
    }
#main-menu {
    display:inline-block;
    height:20px;
    width:100px;
    background: blue;
    padding: 5%;
}
#sub-menu {
    display:inline-block;
    height:50px;
    width:50px;
    background: red;
    display: none;
}
<div><div id="main-menu">Main menu</div></div>
<div><div id="sub-menu" class="sub-menu-class">Sub menu</div></div>

Thanks

dan1st
  • 12,568
  • 8
  • 34
  • 67
Naga
  • 77
  • 6
  • Why would you remove the click listener? Also, please create a [mre]. –  Dec 23 '20 at 14:04
  • Hi Chris, I added an example. Maybe it was not the most suited code, I am quite new to coding :) – Naga Dec 23 '20 at 14:21
  • Had to change things a bit, but here's the gist of it: https://jsfiddle.net/0j7p81sL/ –  Dec 23 '20 at 14:55
  • Thanks ! It indeed works fine. However I've read several time that .stopPropagation is to avoid – Naga Dec 23 '20 at 15:30
  • I've found [this article](https://css-tricks.com/dangers-stopping-event-propagation/) regarding that, and I'm not going to argue with the author about his general point, but in my view the article is more a recommendation to developers of libraries to not use .stopPropagation(). Case in point, the authors suggested way of handling this does not fix the bootstrap bug they introduce earlier. I agree that calling it in document handlers is a bad idea, but I see absolutely no issue with calling it in a single (empty) element's click handler. –  Dec 23 '20 at 17:18

1 Answers1

1

By using jQuery, you can bind to the document click event and hides the div container when the clicked element isn’t the container itself or descendant of the div element.

var container = $("#sub-menu");
if (!container.is(event.target) && !container.has(event.target).length) {
    container.hide();
}

If you want to hide that container without being tested the container itself or descendant of the div element just remove the condition and simply use container.hide();.

Also, rather than setting display: none; on sub-menu in the CSS, set it manually so that you can toggle the sub-menu from the very first click.

Have a look at the snippet below:

var x = document.getElementById("sub-menu");
x.style.display = "none";

$(document).click(function (evt) {

    if ($(evt.target).is('#main-menu')) { // control click event if it's main-menu
        if (x.style.display === "none") {
            x.style.display = "block";
        } else {
            x.style.display = "none";
        }
    }
    else {
        var container = $("#sub-menu");
        if (!container.is(event.target) && !container.has(event.target).length) { // if you don't want that remove the condition and write container.hide(); only
            container.hide();
        }
    }

});
#main-menu {
    display: inline-block;
    height: 20px;
    width: 100px;
    background: blue;
    padding: 5%;
}

#sub-menu {
    display: inline-block;
    height: 50px;
    width: 50px;
    background: red;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
    integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>

<div id="main-menu">Main menu</div>
<div id="sub-menu" class="sub-menu-class">Sub menu</div>
Shahnawaz Hossan
  • 2,695
  • 2
  • 13
  • 24