PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Monday, November 7, 2022

[FIXED] How to close sidenav menu when click out of container div

 November 07, 2022     css, html, javascript, jquery, menu     No comments   

Issue

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()" class="mob_menu_button">Open Menu</button>
<div class="mts_mob_container">
  <div class="mts_sidenav_box">
      
   <div id="mts_mobile_menu" class="mts_sidenav_content">
       
    <div class="user_menu header">
        <span class="display name">Ciao [display_name]</span>
        <span class="display mail">[display_email]</span>
    </div>   
      
     <hr class="solid">  
     
    <div class="user_menu item">
        <a href="/account">
         <i class="icn_menu fa-regular fa-user"></i>
         <span class="link_text">Dashboard</span>
        </a>
    </div>
    
     <div class="user_menu item">
        <a href="ordini">
         <i class="icn_menu fa-regular fa-basket-shopping"></i>
         <span class="link_text">I miei ordini</span>
        </a>
    </div>
    
    <div class="user_menu item">
        <a href="libreria">
         <i class="icn_menu fa-regular fa-cloud-arrow-down"></i>
         <span class="link_text">Downloads</span>
        </a>
    </div>
    
    <div class="user_menu item">
        <a href="impostazioni">
         <i class="icn_menu fa-regular fa-gear"></i>
         <span class="link_text">Impostazioni</span>
        </a>
    </div>
    
    <div class="user_menu item">
        <a href="wp-login.php?action=logout">
         <i class="icn_menu fa-regular fa-arrow-right-from-bracket"></i>
         <span class="link_text">Logout</span>
        </a>
    </div>
   </div>
    
  </div>
</div>


Solution

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)" class="mob_menu_button">Open menu</button>

    <div class="closing_div">
      <div class="mts_mob_container">
        <div class="mts_sidenav_box">
          <div id="mts_mobile_menu" class="mts_sidenav_content">
            <div class="user_menu header">
              <span class="display name">Ciao [display_name]</span>
              <span class="display mail">[display_email]</span>
            </div>

            <hr class="solid" />

            <div class="user_menu item">
              <a href="/account">
                <i class="icn_menu fa-regular fa-user"></i>
                <span class="link_text">Dashboard</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="ordini">
                <i class="icn_menu fa-regular fa-basket-shopping"></i>
                <span class="link_text">I miei ordini</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="libreria">
                <i class="icn_menu fa-regular fa-cloud-arrow-down"></i>
                <span class="link_text">Downloads</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="impostazioni">
                <i class="icn_menu fa-regular fa-gear"></i>
                <span class="link_text">Impostazioni</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="wp-login.php?action=logout">
                <i class="icn_menu fa-regular fa-arrow-right-from-bracket"></i>
                <span class="link_text">Logout</span>
              </a>
            </div>
          </div>
        </div>
      </div>
    </div>



Answered By - user2495207
Answer Checked By - David Marino (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing