Home > Blockchain >  How to close sidenav menu when click out of container div
How to close sidenav menu when click out of container div

Time:05-15

I'm building a sidenav menu that appears and disappears when click a button. I learned a lot here about stacks, users have helped me up to this point, but now I can't integrate a function.

As you can see in the code, if you click button menu, the sidenav opens or closes if you press again. In addition to the button that works correctly, I would like to be able to close the menu when clicking outside the div container. I tried to do something and got half result, the problem is that now the menu opens even when don't click on the button and all the other elements on the page obviously don't work. I suppose this happens because the .mts_mob_container takes full width, but if I don't do so how can I close the menu by clicking outside the div?

I'm doing something obvious wrong, but I can't figure out what. I'm still a beginner, sorry for the many mistakes. Can someone help me ? I appreciate any response, thanks.

Edit: The code works here on stack and jsfiddle, except on my website. Thanks to the intervention of @user2495207 the menu works as I wanted! I tried to put everything on my website (I have it in the header menu), it opens and closes with the button, but when I click outside the div it doesn't close.

As you can see here it works. Am I missing something?

var menu = document.querySelector(".mob_menu_button");
function mobile_menu() {
  var x = document.getElementById("mts_mobile_menu");
  if (!x.classList.contains("side_show")) {
    x.classList.add ("side_show");
    menu.innerHTML = 'Close Menu';
    
  } else { 
    x.classList.add("side_hide");
    menu.innerHTML = 'Open Menu';

    setTimeout(function(){
     x.classList.remove("side_show");
     x.classList.remove("side_hide");  
    },300)
  }
}

document.addEventListener("click", function (e) {
        var x = document.getElementById("mts_mobile_menu");
        if (e.target.localName == "html" && x.classList.contains("side_show")) {

          x.classList.add("side_hide");
          menu.innerHTML = "<span>Open menu</span>";

          setTimeout(function () {
            x.classList.remove("side_show");
            x.classList.remove("side_hide");
          }, 300);
        }
      });
/*Items menu*/
.user_menu {
  display: flex;
  flex-direction: column;
}


/*Menu header info*/
.display.name {
  font-size: 15px;
  font-weight: 500;
  color: #303238;
}

.display.mail {
  font-size: 13px;
  color: #3d5afe;
}

hr.solid {
  border-top: 1px solid #e0e0e0;
  margin: 10px 0px 10px 0px;
}


/*Text Link css*/
.user_menu.item>a {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  padding: 8px 0;
  font-size: 13px;
  color: #75777D;
}

.user_menu.item:hover>a {
  color: #2E323A;
}

/*Icon Button Toggle Menu*/
.mob_menu_button {
    display: flex;
    align-items: center;
    width: 120px;
    position: absolute;
    top: 10px;
    right: 10px;
    background: #fbfbfb!important;
    font-weight: 500!important;
    justify-content: center;
}

.icn_button {
  margin: 0;
  font-size: 14px;
}

.icn_button:before {
  margin: 0;
}

.icn_button:after {
  margin: 0;
}


/*Icon Items Menu*/
.icn_menu:before,
.icon_menu:after {
  margin: 0px;
  padding: 0px;
  font-size: 16px
}

.icn_menu {
  margin-right: 10px;
  display: flex !important;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
}


/* User Menu For header website */

.mts_mob_container {
  display:flex;
  position:fixed;
  z-index: 999;
  height: 100%;
  top: 0;
  left: 0;
}

.mts_sidenav_box {
    display: block;
}

.mts_sidenav_content {
  display: none;
  padding: 20px;
  background-color: #fff;
  min-width: 160px;
  width: 280px;
  border-radius: 3px;
  overflow-x: hidden;
  overflow-y: auto;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 999;
  position: relative;
  animation: animateFromLeft .3s;
}

@keyframes animateFromLeft {
  from {
    left: -500px;
    opacity: 0;
  }
  to {
    left: 0;
    opacity: 1;
  }
}

@keyframes animateToLeft {
  from {
    left: 0;
    opacity: 1;
  }
  to {
    left: -500px;
    opacity: 0;
  }
}

.side_show {
  display: block !important;
  height: 100vh;
  overflow: hidden;
  width: 100%;
}

.mts_sidenav_content.side_hide {
  animation: animateToLeft .4s;
}
<button onclick="mobile_menu()" >Open Menu</button>
<div >
  <div >
      
   <div id="mts_mobile_menu" >
       
    <div >
        <span >Ciao [display_name]</span>
        <span >[display_email]</span>
    </div>   
      
     <hr >  
     
    <div >
        <a href="/account">
         <i ></i>
         <span >Dashboard</span>
        </a>
    </div>
    
     <div >
        <a href="ordini">
         <i ></i>
         <span >I miei ordini</span>
        </a>
    </div>
    
    <div >
        <a href="libreria">
         <i ></i>
         <span >Downloads</span>
        </a>
    </div>
    
    <div >
        <a href="impostazioni">
         <i ></i>
         <span >Impostazioni</span>
        </a>
    </div>
    
    <div >
        <a href="wp-login.php?action=logout">
         <i ></i>
         <span >Logout</span>
        </a>
    </div>
   </div>
    
  </div>
</div>

CodePudding user response:

If you inspect the .mts_mob_container element in your browser you'll realize it's covering the button (the button isn't triggering any event) so i had to comment its dimensions:

.mts_mob_container {
        display: flex;
        position: fixed;
        z-index: 999;
        /* height: 100%; */
        top: 0;
        left: 0;
        /* width: 100%;*/
      }

I also added this block, an event when the user clicks outside the sidenav, the code inside is the same as the else part of the mobile_menu function to close the sidenav.

      document.addEventListener("click", function (e) {
        var x = document.getElementById("mts_mobile_menu");
        if (e.target.id !== "mts_mobile_menu" && x.classList.contains("side_show")) {
          x.classList.add("side_hide");
          menu.innerHTML = "<span>Open menu</span>";

          var y = document.getElementById("closing_div");
          if (!x.classList.contains("side_show")) {
            x.classList.add("side_hide");
          }

          setTimeout(function () {
            x.classList.remove("side_show");
            x.classList.remove("side_hide");
          }, 500);
        }
      });

UPDATE:
The button event was propagating to its parent document so i added e.stopPropagation();.
In the event of the document; the if statement if(e.target.id !== "mts_mobile_menu" && x.classList.contains("side_show")) means that it'll execute if the target clicked isn't the sidenav and is showed

var menu = document.querySelector(".mob_menu_button");
      function mobile_menu(e) {
        e.stopPropagation();
        var x = document.getElementById("mts_mobile_menu");
        if (!x.classList.contains("side_show")) {
          x.classList.add("side_show");
          menu.innerHTML = "<span>Close menu</span>";
        } else {
          x.classList.add("side_hide");
          menu.innerHTML = "<span>Open menu</span>";

          var y = document.getElementById("closing_div");
          if (!x.classList.contains("side_show")) {
            x.classList.add("side_hide");
          }

          setTimeout(function () {
            x.classList.remove("side_show");
            x.classList.remove("side_hide");
          }, 500);
        }
      }
      document.addEventListener("click", function (e) {
        var x = document.getElementById("mts_mobile_menu");
        if (e.target.id !== "mts_mobile_menu" && x.classList.contains("side_show")) {
          x.classList.add("side_hide");
          menu.innerHTML = "<span>Open menu</span>";

          var y = document.getElementById("closing_div");
          if (!x.classList.contains("side_show")) {
            x.classList.add("side_hide");
          }

          setTimeout(function () {
            x.classList.remove("side_show");
            x.classList.remove("side_hide");
          }, 500);
        }
      });
  * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      /*Items menu*/
      .user_menu {
        display: flex;
        flex-direction: column;
      }

      /*Menu header info*/
      .display.name {
        font-size: 15px;
        font-weight: 500;
        color: #303238;
      }

      .display.mail {
        font-size: 13px;
        color: #3d5afe;
      }

      hr.solid {
        border-top: 1px solid #e0e0e0;
        margin: 10px 0px 10px 0px;
      }

      /*Text Link css*/
      .user_menu.item > a {
        display: flex;
        justify-content: flex-start;
        align-items: center;
        padding: 8px 0;
        font-size: 13px;
        color: #75777d;
      }

      .user_menu.item:hover > a {
        color: #2e323a;
      }

      /*Icon Button Toggle Menu*/
      .mob_menu_button {
        display: flex;
        align-content: center;
        justify-content: center;
        align-items: center;
        width: 100px;
        position: absolute;
        top: 10px;
        right: 10px;
        background: #fbfbfb !important;
        font-weight: 500 !important;
      }

      .icn_button {
        margin: 0;
        font-size: 14px;
      }

      .icn_button:before {
        margin: 0;
      }

      .icn_button:after {
        margin: 0;
      }

      /*Icon Items Menu*/
      .icn_menu:before,
      .icon_menu:after {
        margin: 0px;
        padding: 0px;
        font-size: 16px;
      }

      .icn_menu {
        margin-right: 10px;
        display: flex !important;
        align-items: center;
        justify-content: center;
        width: 22px;
        height: 22px;
      }

      /* User Menu For header website */
      .mts_mob_container {
        display: flex;
        position: fixed;
        z-index: 999;
        /* height: 100%; */
        top: 0;
        left: 0;
        /* width: 100%;*/
      }

      .mts_sidenav_box {
        display: block;
      }

      .mts_sidenav_content {
        display: none;
        padding: 20px;
        background-color: #fff;
        min-width: 160px;
        width: 280px;
        border-radius: 3px;
        overflow-x: hidden;
        overflow-y: auto;
        box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
        z-index: 999;
        position: relative;
        animation: animateFromLeft 0.6s;
      }

      @keyframes animateFromLeft {
        from {
          left: -500px;
          opacity: 0;
        }
        to {
          left: 0;
          opacity: 1;
        }
      }

      @keyframes animateToLeft {
        from {
          left: 0;
          opacity: 1;
        }
        to {
          left: -500px;
          opacity: 0;
        }
      }

      .side_show {
        display: block !important;
        height: 100vh;
        overflow: hidden;
        width: 100%;
      }

      .mts_sidenav_content.side_hide {
        animation: animateToLeft 0.6s;
      }
    <button onclick="mobile_menu(event)" >Open menu</button>

    <div >
      <div >
        <div >
          <div id="mts_mobile_menu" >
            <div >
              <span >Ciao [display_name]</span>
              <span >[display_email]</span>
            </div>

            <hr  />

            <div >
              <a href="/account">
                <i ></i>
                <span >Dashboard</span>
              </a>
            </div>

            <div >
              <a href="ordini">
                <i ></i>
                <span >I miei ordini</span>
              </a>
            </div>

            <div >
              <a href="libreria">
                <i ></i>
                <span >Downloads</span>
              </a>
            </div>

            <div >
              <a href="impostazioni">
                <i ></i>
                <span >Impostazioni</span>
              </a>
            </div>

            <div >
              <a href="wp-login.php?action=logout">
                <i ></i>
                <span >Logout</span>
              </a>
            </div>
          </div>
        </div>
      </div>
    </div>

  • Related