Reputation: 14434
I've created a function that toggles a menu based on its' visibility. I also assigned a mouseup event to the document where the menu closes if the user clicks anywhere outside of it. The problem is when the mouseup
event listener is added for the document
the toggle no longer works. The visibility test: $menu.is(":visible");
returns false
despite the menu being in plain sight. What's going on here?
$(function() {
var $toggleMenu = $(".toggle-menu"),
$menu = $(".menu");
$toggleMenu.on("click", function(e) {
e.preventDefault();
toggleUserMenu();
});
$(document).on("mouseup", function (e) {
if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
$menu.hide();
}
});
function toggleUserMenu() {
var menuIsVisible = $menu.is(":visible");
if (menuIsVisible) {
$menu.hide();
} else {
$menu.show();
}
}
});
.toggle-menu {
color: #444;
display: inline-block;
margin-bottom: 15px;
text-decoration: none;
}
.menu {
border: 1px solid black;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="" class="toggle-menu">Toggle Menu</a>
<div class="menu">
<a href="#" class="menu-item">Menu Item 1</a>
<a href="#" class="menu-item">Menu Item 2</a>
<a href="#" class="menu-item">Menu Item 3</a>
</div>
Upvotes: 0
Views: 255
Reputation: 15566
One solution can be by preventing the mouseup
in the conflicting area to bubble up.
$(function() {
var $toggleMenu = $(".toggle-menu"),
$menu = $(".menu");
$toggleMenu.on("click", function(e) {
e.preventDefault();
toggleUserMenu();
});
$toggleMenu.on("mouseup", function(e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on("mouseup", function (e) {
if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
$menu.hide();
}
});
function toggleUserMenu() {
var menuIsVisible = $menu.is(":visible");
console.log(menuIsVisible);
if (menuIsVisible) {
$menu.hide();
} else {
$menu.show();
}
}
});
$toggleMenu.on("mouseup", function(e) {
e.preventDefault();
e.stopPropagation();
});
This will catch the mouseup
that is fired along with the click
on Toggle Button and stops it from bubbling up to document
. preventDefault()
doesn't have any specific purpose here, It came with your code that I copied :)
Here is a fiddle
Upvotes: 1
Reputation: 1917
you run $menu.hide twice and it is problem.
$(function() {
var $toggleMenu = $(".toggle-menu"),
$menu = $(".menu");
$toggleMenu.on("click", function(e) {
e.preventDefault();
toggleUserMenu();
});
$(document).on("mouseup", function (e) {
console.log("Event is still firing");
if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
//if you commment this the code work.
// $menu.hide();
}
});
function toggleUserMenu() {
var menuIsVisible = $menu.is(":visible");
if (menuIsVisible) {
$menu.hide();
} else {
$menu.show();
}
}
});
.toggle-menu {
color: #444;
display: inline-block;
margin-bottom: 15px;
text-decoration: none;
}
.menu {
border: 1px solid black;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="" class="toggle-menu">Toggle Menu</a>
<div class="menu">
<a href="#" class="menu-item">Menu Item 1</a>
<a href="#" class="menu-item">Menu Item 2</a>
<a href="#" class="menu-item">Menu Item 3</a>
</div>
Upvotes: 0