Search code examples
javascriptjquerymenu

Hide an expanded menu when clicking outside of the container: how to use code snipet


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


Solution

  • 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>