document click to hide menu - javascript

My document click function isn't hiding my menu when I click the document outside of my menu. When I click the img it shows the menu and when I click the img again it hides it but when I document click I want it to hide the menu does any one know what I'm doing wrong and how to make it work.
var visible = false;
var id = $(this).attr('id');
$(document).not('#' + id + ' div:eq(1)').click(function () {
if (visible) {
$('.dropdownlist .menu').hide();
visible = false;
}
});
$(this).find('div:eq(1)').click(function (e) {
var menu = $(this).parent().find('.menu');
if (!visible) {
menu.show();
visible = true;
} else if (visible) {
menu.hide();
visible = false;
}
menu.css({ 'left': $(this).position().left + $(this).width() - menu.find('ul').width(),
'top': $(this).position().top + $(this).height() });
})

I had a similar problem and solved it with the following code:
$("body").mouseup(function(){
if (visible) {
$('.dropdownlist .menu').hide();
visible = false;
}
});
instead of your $(document).not(.. code.

//add event.stopPropagation() when the user clicks on a .menu element
$('.menu').on('click', function (event) {
//.stopPropagation() will stop the event from bubbling up to the document
event.stopPropagation();
});
//add the click event handler to the image that will open/close .menu elements
$('img').on('click', function (event) {
//we call .stopPropagation() again here so the document won't receive this event
event.stopPropagation();
//cache .menu element
var $div = $('.menu');
//this if statement determines if the .menu should be shown or hidden, in my example I'm animating its top property
if ($div.css('top') == '-50px') {
$div.stop().animate({top : 0}, 250);
} else {
$div.stop().animate({top : '-50px'}, 150);
}
});
//add click event handler to the document to close the .menu
$(document).on('click', function () {
$('div').stop().animate({top : '-50px'}, 150);
});
jsfiddle: http://jsfiddle.net/jasper/n5C9w/1/

Related

Href links inside my mobile menu bar doesn't work

$(document).click(function (event) {
if ($("#sidenav").width() != 0) {
$("#sidenav").css({ 'width': '0' });
}
});
$("#sidenav").click(function (e) {
e.stopPropagation();
return false;
});
$("#navHome").click(function () {
$("#navHome").attr("href", "/public/templates/default/index.html");
$("#sidenav").css({ 'width': '0' });
});
1) The $(document).click(function (event) function closes the nav bar if user click anywhere outside the navbar
2) The $("#sidenav").click(function (e) function prevents nav bar from closing if user click anywhere inside the navbar
3) Now because of the e.stopPropagation(); in the second function, when I click on the navHome it did close the navBar but didn't take me to the index page. In other words, $("#navHome").attr("href","/public/templates/default/index.html"); doesn't work.
Is there a work around for this? Thanks!
Do not cancel the click if the target is a link
$("#sidenav").click(function (e) {
if(!$(e.target).closest("a").length) {
e.stopPropagation();
return false;
}
});

How to add event listener using jQuery?

Have this code and tried to hide my side navbar when clicked outside the #nav, got this error.
Cannot read property 'addEventListener' of null
$( document ).ready( function() {
setTimeout(function(){
$('.menu-opener').click(function(){
$('#nav').toggleClass('active');
});
let slide = document.querySelector('#nav .active');
slide.addEventListener('click', function(e) {
if (e.target !== slide) return;
$('#nav').removeClass('active');
});
}, 1000);
});
answer is that you need to detect click outside of div you are trying to hide:
$(window).click(function() {
//Hide the menus if visible
});
//stopping above function from running when clicking on #nav itself
$('#nav').click(function(event){
event.stopPropagation();
});
Try this inside setTimeout
$('body').on('click','#nav .active', function(e){
// your logic
})
OR
$( "'#nav .active'" ).bind( "click", function(e) {
// your logic
});
instead of
let slide = document.querySelector('#nav .active');
slide.addEventListener('click', function(e) {
if (e.target !== slide) return;
$('#nav').removeClass('active');
});
Got this working with
$(document).click(function(event) {
if(!$(event.target).closest('#nav').length && !$(event.target).closest(".menu-opener").length)
{
$('#nav').removeClass('active');
}
});

Click outside to close dropdown only works when click outside <nav>

The following nav I'm building works just fine, however I noticed that when click outside the nav buttons but still inside <nav> container the open dropdown doesn't close as it should however it does close when click outside <nav>.
How can that be? Thank you for your help.
See Demo here
JQuery
$(document).ready(function() {
$(".click").on("click", function(e) {
var menu = $(this);
toggleDropDown(menu);
});
$(document).on('mouseup',function(e) {
var container = $("nav");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if ($('a.active').hasClass('active')) {
$('a.active').removeClass('active');
}
});
}
});
});
function toggleDropDown(menu) {
var isActive = $('a.active').length;
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if (menu.hasClass('active')) {
menu.removeClass('active');
} else {
$('a.active').removeClass('active');
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
});
if (!isActive) {
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
}
You have to change your container, something like:
var container = $("nav .top-bar-section ul");

Conditionally binding/unbinding event listeners

With the help of this post I was able to put together a menu that closes either by toggling a link or clicking outside of it (via mouseup). The problem is that because this mouseup event handler is bound to the document object this is constantly being fired regardless of whether the menu is open or not.
I was wondering how could I conditionally set this handler up only when the menu is visible? I don't necessarily want to invoke: $(document).off("mouseup"); outright in that this toggle is ever fired to initiate the event listener inside $toggleMenu.on("click", function() {...}) via $(document).on("mouseup")
$(function() {
var $toggleMenu = $(".toggle-menu"),
$menu = $(".menu");
$toggleMenu.on("click", function(e) {
e.preventDefault();
toggleUserMenu();
});
$toggleMenu.on("mouseup", function(e) {
e.stopPropagation();
});
$(document).on("mouseup", function (e) {
console.log("Event is still firing");
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>
Toggle Menu
<div class="menu">
Menu Item 1
Menu Item 2
Menu Item 3
</div>
I would move your $(document).on("mouseup") code to the toggleUserMenu like this:
function toggleUserMenu() {
var menuIsVisible = $menu.is(":visible");
if (menuIsVisible) {
$menu.hide();
$(document).off("mouseup.my-menu");
} else {
$menu.show();
$(document).on("mouseup.my-menu", function (e) {... });
}
Note, I am using events with namespaces there to avoid cases when $(document).off("mouseup"); will unsubscribe all mouseup handlers.
You could attach the event handler only when the menu is displayed and unattach the event handler when the menu is closed.
So, every time you show the menu, you attach the mouseup handler to allow closing the menu by clicking off menu.
When the menu is closed (by click off menu or by clicking the toggle link), hideMenu hides the menu and unsets the event handler so it won't be called upon further mouseup events.
Note that the mouseup handler is factored out of the .on() code so that .off() is able to reference and remove only that handler--that is to say, if you have other mouseup handlers present, they will remain intact.
http://jsfiddle.net/qmLucq9r/
$(function() {
var $toggleMenu = $(".toggle-menu"),
$menu = $(".menu");
$toggleMenu.on("click", function(e) {
e.preventDefault();
toggleUserMenu();
});
$toggleMenu.on("mouseup", function(e) {
e.stopPropagation();
});
var hideMenu = function() {
$menu.hide();
$(document).off("mouseup", mouseupHandler);
};
var mouseupHandler = function (e) {
console.log("Event is still firing");
if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
hideMenu();
}
};
function toggleUserMenu() {
var menuIsVisible = $menu.is(":visible");
if (menuIsVisible) {
hideMenu();
} else {
$menu.show();
$(document).on("mouseup", mouseupHandler);
}
}
});

jQuery menu with click to show and hide on mouseleave

At the moment it shows the divs instead of hiding them and on click it hides just so you can see the movement. Should be .show instead of .hide. On clicking the link, li should slide down and on mouseleave slide back up.
Working example http://jsfiddle.net/DTqDD/3/
jQuery:
$(function() {
var toggleMenu = function(e) {
var self = $(this),
elemType = self[0].tagName.toLowerCase(),
//get caller
menu = null;
if (elemType === 'a') {
//anchor clicked, nav back to containing ul
menu = self.parents('ul').not('ul#mainmenu');
} else if (elemType === 'ul') {
//mouseleft ul, ergo menu is this.
menu = self;
}
if (menu) {
menu.hide('medium');
}
e.preventDefault();
return false;
};
$(document).ready(function() {
$('a.drop').click(function(e) {
$('li#mainmenudrop').show('medium');
console.log('div clicked');
e.preventDefault();
return false;
});
$('li#mainmenudrop a').click(toggleMenu);
$('li#mainmenudrop').mouseleave(toggleMenu);
});
});
On li tags change id="mainmenudrop" to class="mainmenudrop" since it ain't valid HTML. Then use the following jQuery code.
$(document).ready(function() {
$('a.drop').click(function(e) {
$(this).next("div").show('medium');
console.log('div clicked');
e.preventDefault();
return false;
});
$('li.mainmenudrop').mouseleave(function() {
$(this).children("div").hide('medium');
});
});​
Could this possibly be what you are trying to accomplish?
EDIT:
If you want the divs hidden at the beginning, just add this CSS:
.mainmenudrop div {
display: none;
}

Categories