I'm trying to close dropdown menu by clicking on the body or whatever. To do this I'm using document.addEventListener
but it doesn't work.
By doing several tests I managed to get the code to work by adding a div that simulates a "body". So instead of document.addEventListener
I wrote document.getElementById ("container_test"). AddEventListener
.
the problem is that when there is no getElement it doesn't work. I can't understand what I'm wrong, can someone help me?
Here are two examples:
Not Working Code
var usermenu = document.querySelector(".user_menu_button");
function userMenu() {
var x = document.getElementById("mts_menu");
if (x.classList.toggle("show")) {
usermenu.innerHTML = '<i ></i><span >Account</span>';
} else {
usermenu.innerHTML = '<i ></i><span >Account</span>';
}
}
const closing = document.querySelector("#mts_menu");
document.addEventListener("click", (evt) => {
if (!evt.target.closest("#mts_menu")) closing.classList.remove("show");
});
/*Button Toggle Menu*/
.user_menu_button {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
width: 100%;
height: 32px;
background: #3D4350!important;
border-radius: 4px;
padding: 12px;
font-size: 14px!important;
line-height: 2;
}
.icn_button {
margin: 0;
}
.icn_button:before,
.icn_button:after {
margin: 0;
}
.txt_button {
margin-left: 10px;
color: #fff;
font-size: 14px;
font-weight: 400;
}
/*Items menu*/
.user_menu {
display: flex;
flex-direction: column;
}
.user_menu.header {
padding: 15px 15px;
}
/*Menu header info*/
.display.name {
font-size: 14px;
font-weight: 500;
color: #303238;
line-height: 1.5;
}
.display.mail {
font-size: 13px;
color: #1E70EB;
line-height: 1.5;
}
hr.divider-menu {
border-top: 1px solid #e0e0e0;
}
/*Text Link css*/
.mnu_margin {
margin: 7px 0;
}
.user_menu.item>a {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 8px 15px;
color: #212629;
}
.user_menu.item:hover>a {
color: #fff;
background: #1E70EB;
transition: all 0.2s;
}
.user_menu.item>a .link_text {
font-size: 14px;
color: #212629;
}
.user_menu.item:hover>a .link_text {
color: #fff;
}
/*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_menu_container {
display: flex;
flex-direction: column;
align-content: flex-end;
align-items: flex-end;
}
.dropdown_box {
position: absolute;
margin-top: 20px;
}
.mts_dropdown_content {
background-color: #fff;
min-width: 160px;
width: 240px;
border-radius: 6px;
overflow-x: hidden;
overflow-y: hidden;
box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
z-index: 999;
position: relative;
visibility: hidden;
opacity: 0;
top: 50px;
height: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
.mts_dropdown_content.show {
height: 100%;
visibility: visible;
opacity: 1;
top: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
<button onclick="userMenu()" >
<i ></i>
<span >Account</span>
</button>
<div >
<div >
<div id="mts_menu" >
<div >
<span >Ciao [display_name]</span>
<span >[display_email]</span>
</div>
<hr >
<div >
<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>
Working Code
var usermenu = document.querySelector(".user_menu_button");
function userMenu() {
var x = document.getElementById("mts_menu");
if (x.classList.toggle("show")) {
usermenu.innerHTML = '<i ></i><span >Account</span>';
} else {
usermenu.innerHTML = '<i ></i><span >Account</span>';
}
}
const closing = document.querySelector("#mts_menu");
document.getElementById("container_test").addEventListener("click", (evt) => {
if (!evt.target.closest("#mts_menu")) closing.classList.remove("show");
});
#container_test {
margin-top: 20px;
border: 1px solid;
padding: 20px;
}
/*Button Toggle Menu*/
.user_menu_button {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
width: 100%;
height: 32px;
background: #3D4350!important;
border-radius: 4px;
padding: 12px;
font-size: 14px!important;
line-height: 2;
}
.icn_button {
margin: 0;
}
.icn_button:before,
.icn_button:after {
margin: 0;
}
.txt_button {
margin-left: 10px;
color: #fff;
font-size: 14px;
font-weight: 400;
}
/*Items menu*/
.user_menu {
display: flex;
flex-direction: column;
}
.user_menu.header {
padding: 15px 15px;
}
/*Menu header info*/
.display.name {
font-size: 14px;
font-weight: 500;
color: #303238;
line-height: 1.5;
}
.display.mail {
font-size: 13px;
color: #1E70EB;
line-height: 1.5;
}
hr.divider-menu {
border-top: 1px solid #e0e0e0;
}
/*Text Link css*/
.mnu_margin {
margin: 7px 0;
}
.user_menu.item>a {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 8px 15px;
color: #212629;
}
.user_menu.item:hover>a {
color: #fff;
background: #1E70EB;
transition: all 0.2s;
}
.user_menu.item>a .link_text {
font-size: 14px;
color: #212629;
}
.user_menu.item:hover>a .link_text {
color: #fff;
}
/*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_menu_container {
display: flex;
flex-direction: column;
align-content: flex-end;
align-items: flex-end;
}
.dropdown_box {
position: absolute;
margin-top: 20px;
}
.mts_dropdown_content {
background-color: #fff;
min-width: 160px;
width: 240px;
border-radius: 6px;
overflow-x: hidden;
overflow-y: hidden;
box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
z-index: 999;
position: relative;
visibility: hidden;
opacity: 0;
top: 50px;
height: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
.mts_dropdown_content.show {
height: 100%;
visibility: visible;
opacity: 1;
top: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
<button onclick="userMenu()" >
<i ></i>
<span >Account</span>
</button>
<div >
<div >
<div id="mts_menu" >
<div >
<span >Ciao [display_name]</span>
<span >[display_email]</span>
</div>
<hr >
<div >
<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>
<div id="container_test">container test</div>
CodePudding user response:
When you click on the button to open the menu, the menu is opened, then the event bubbles out to document
. Since the button isn't inside the menu, the menu closes.
Yuo should use event.stopPropagation
in the button code to prevent this.
var usermenu = document.querySelector(".user_menu_button");
function userMenu(event) {
event.stopPropagation();
var x = document.getElementById("mts_menu");
if (x.classList.toggle("show")) {
usermenu.innerHTML = '<i ></i><span >Account</span>';
} else {
usermenu.innerHTML = '<i ></i><span >Account</span>';
}
}
const closing = document.querySelector("#mts_menu");
document.addEventListener("click", (evt) => {
if (!evt.target.closest("#mts_menu")) closing.classList.remove("show");
});
/*Button Toggle Menu*/
.user_menu_button {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
width: 100%;
height: 32px;
background: #3D4350!important;
border-radius: 4px;
padding: 12px;
font-size: 14px!important;
line-height: 2;
}
.icn_button {
margin: 0;
}
.icn_button:before,
.icn_button:after {
margin: 0;
}
.txt_button {
margin-left: 10px;
color: #fff;
font-size: 14px;
font-weight: 400;
}
/*Items menu*/
.user_menu {
display: flex;
flex-direction: column;
}
.user_menu.header {
padding: 15px 15px;
}
/*Menu header info*/
.display.name {
font-size: 14px;
font-weight: 500;
color: #303238;
line-height: 1.5;
}
.display.mail {
font-size: 13px;
color: #1E70EB;
line-height: 1.5;
}
hr.divider-menu {
border-top: 1px solid #e0e0e0;
}
/*Text Link css*/
.mnu_margin {
margin: 7px 0;
}
.user_menu.item>a {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 8px 15px;
color: #212629;
}
.user_menu.item:hover>a {
color: #fff;
background: #1E70EB;
transition: all 0.2s;
}
.user_menu.item>a .link_text {
font-size: 14px;
color: #212629;
}
.user_menu.item:hover>a .link_text {
color: #fff;
}
/*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_menu_container {
display: flex;
flex-direction: column;
align-content: flex-end;
align-items: flex-end;
}
.dropdown_box {
position: absolute;
margin-top: 20px;
}
.mts_dropdown_content {
background-color: #fff;
min-width: 160px;
width: 240px;
border-radius: 6px;
overflow-x: hidden;
overflow-y: hidden;
box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
z-index: 999;
position: relative;
visibility: hidden;
opacity: 0;
top: 50px;
height: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
.mts_dropdown_content.show {
height: 100%;
visibility: visible;
opacity: 1;
top: 0;
transition: visibility 0.2s, max-height 0.2s, opacity 0.2s, top 0.2s, height 0.2s;
}
<button onclick="userMenu(event)" >
<i ></i>
<span >Account</span>
</button>
<div >
<div >
<div id="mts_menu" >
<div >
<span >Ciao [display_name]</span>
<span >[display_email]</span>
</div>
<hr >
<div >
<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>
CodePudding user response:
- In your "not working code" you need to exclude the button that show the menu too.
document.addEventListener("click", (evt) => {
if (!evt.target.closest("#mts_menu") && !evt.target.closest('.user_menu_button')) closing.classList.remove("show");
});