Menu should disappear when clicked somewhere else - javascript

I have a div which should be visible, whenever a button is clicked. It's like a menu. Afterwards, it should disappear (toggle), when the button is clicked again or when the user clicks somewhere else on the page (whole body).
In my current approach, the menu constantly toggles, so both functions (see below) are being triggered.
$("#b1").click(function() {
$("#menu").toggle("slide");
});
$("body").click(function() {
if ($("#menu").is(":visible")) {
$("#menu").toggle("slide");
}
});
How should I improve my code, so that the menu only disappears when the button is clicked again or when the user clicks somewhere else?
Here is a fiddle.

Use $(window) to attach the event, then you can close the menu anywhere.
$("#b1").click(function() {
$("#menu").toggle("slide");
return false;
});
$(window).click(function() {
if ($("#menu").is(":visible")) {
$("#menu").toggle("slide");
}
});
Check demo: https://jsfiddle.net/wru8mvxt/5/

You can use e.target and check whenever it's not the menu or the button which got clicked. Otherwise the menu closed even on the button click or on a click inside.
$("#b1").click(function() {
$("#menu").slideDown();
});
$("body").click(function(e) {
if (!$(e.target).is("#b1") && $("#menu").is(":visible")) {
$("#menu").slideUp();
} else {
e.preventDefault();
}
});
If you want the menu to stay even on click inside, just add && !$(e.target).is("#menu") to the if condition.
Working example.

I think your code looks good.. I see one problem when you click on menu it will be hide.
$("#b1").click(function() {
$("#menu").toggle("slide");
return false; // prevent to pass click event to body
});
$("body").click(function() {
if ($("#menu").is(":visible")) {
$("#menu").toggle("slide");
}
});
$("#menu").click(function(e){
e.preventDefault();
return false;
});

Use something like this:
$(document).mouseup(function (e)
{
var container = $("YOUR CONTAINER SELECTOR");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});

Try this.
$("#b1").click(function() {
event.stopPropagation();
$("#menu").toggle("slide");
});
$("body").click(function() {
if(!$(event.target).closest('#menu').length){
if ($("#menu").is(":visible")) {
$("#menu").toggle("slide");
}
}
});

I think this code will solve your issue. You can use e.target property to find whether user clicked on button or outside button. When user click on button b1 it enters both b1 click event and body click event. So if in order to find where the user is clicked you can use event.target property.
Clicking the button will toggle the menu visibility.
Clicking outside the button will close the menu if it is opened.
$("#b1").click(function() {
$("#menu").toggle("slide");
$("#b1").text() == "hide menu" ? $("#b1").text("show menu") : $("#b1").text("hide menu");
});
$("body").click(function(e) {
if (!$(e.target).is("#b1") && $("#menu").is(":visible")) {
$("#menu").slideUp();
}
else {
e.preventDefault();
}
});
Working fiddle

You have to do following changes.
$(document).ready(function() {
$("#b1").click(function(e) {
$("#menu").slideToggle();
e.stopPropagation();
});
$(document).click(function(e) {
if (!$(e.target).is('#menu, #menu *')) {
$("#menu").slideUp();
}
});
});

Related

bind and unbind along with toggle

I need to show a div .overlay to a user on click and the user must not be able to scroll or move from that page unless he clicks on it again and closes it.
So far i have tried with the below code and it works
$('#clicker').click(function() {
$(".overlay").toggle();
$('html').css('overflow', 'hidden');
$('body').bind('touchmove', function(e) {
e.preventDefault();
});
});
but the problem is when the user clicks again the div disappears but the scroll is missing.
i need to add the below code so it works...
$('html').css('overflow', 'scroll');
$('body').unbind('touchmove');
can someone help me on how unbind and add the above js code on the second click or toggled?
You could test the visibility of the overlay and execute the appropriate code:
$('#clicker').click(function() {
if ($(".overlay").toggle().is(':visible') {
$('html').css('overflow', 'hidden');
$('body').bind('touchmove', function(e) {
e.preventDefault();
});
} else {
$('html').css('overflow', 'scroll');
$('body').unbind('touchmove');
}
});
If you add a conditional into the touchmove function, you can check if the div is shown, and decide like that:
$('body').bind('touchmove', function(e) {
if($(".overlay:visible").length) {
e.preventDefault();
}
});

Display menu on focus and hide when out of focus or clicked other than the menu

I am trying to display menu (#lorem-ipsum-wrapper) when the div (#content) is focused, and again hide the menu if neither the div or the menu is clicked.
js:
$(document).ready(function() {
console.log('ready');
$('#content').on("focus", function(event) {
$('#lorem-ipsum-wrapper').css("display", "block");
event.stopPropagation();
});
$(document).on("click", function() {
$('#lorem-ipsum-wrapper').css("display", "none");
});
});
demo at codepent.io
But the problem is that as soon as the #content is in focus, the menu displays and then again hides itself. Isn't the stopPropagation() method used to stop this? What am I doing wrong? Your help will be very much appreciated. Thank you.
Does this help ?
$(document).click(function(e) {
var e = $(e.target), eid = e.attr("id");
if (!e.parents("#lorem-ipsum-wrapper").length && !e.parents("#content-wrapper").length && eid !== "content-wrapper" && eid !== "lorem-ipsum-wrapper") {
$('#lorem-ipsum-wrapper').css("display", "none");
}
});
or you can use blur event :
$('#content').on("focus", function(event) {
$('#lorem-ipsum-wrapper').css("display", "block");
});
$('#content').on("blur", function(event) {
$('#lorem-ipsum-wrapper').css("display", "none");
});
If I didn't misunderstand, you want to hide #lorem-ipsum-wrapper if #content is not clicked and show the #lorem-ipsum-wrapper on click of #content. Then, your code should be:
$(document).ready(function() {
console.log('ready');
$('#lorem-ipsum-wrapper').css('display','none');
$('#content').on("focus", function(event) {
$('#lorem-ipsum-wrapper').css('display','block');
});
$('#content').on("blur", function() {
$('#lorem-ipsum-wrapper').css("display", "none");
});
$('#lorem-ipsum-wrapper').on("click",function(){
$(this).css("display","block");
});
Explanation:
The third lines ensures that the lorem-ipsum-wrapper is not show before executing any code.
The fourth and fifth lines make the #lorem-ipsum-wrapper visible whenever the focus is on the #content.
The seventh and eighth lines make the lorem-ipsum-wrapper hidden whenever the users clicks somewhere else on the page or make the #lorem-ipsum-wrapper lose focus.

Open/hide div that is already open by clicking link

I have made a nav that opens when you click at the .products link and closes if you click anywhere on the screen. But it seems that if you click on the .product link when it is already open, it will not close. How can I do this?
$('#subnav').hide();
$(document).on('click', function(e) {
if ( $(e.target).closest('.products').length ) {
$("#subnav").show();
}else if ( ! $(e.target).closest('#subnav').length ) {
$('#subnav').hide();
}
});
Demo
js
$("#subnav").hide();
$(".products").click(function (e) { //the usual behavior on click on .prducts
$("#subnav").toggle();
e.stopPropagation();
});
$("#subnav").click(function (e) { //ensures the #subnav will not hide on click on it
e.stopPropagation();
});
$(document).click(function () { //ensures the #subnav will hide on click on document
$("#subnav").hide();
});
You need a click event on the document to hide the block and a click event on the button to show the block. And in the event of the button, you need to stop the propagation of the document's event.
Like that :
$("div").hide();
$("button").bind("click",function(e){
e.stopPropagation();
$("div").toggle(200);
});
$(document).bind("click",function(){
$("div").hide(200);
});
Assuming your code looks like that :
<div></div>
<button>open</button>
See example : http://jsfiddle.net/oqgpceod/1/
Aditionnaly you may add this code to prevent the block from hiding when you click on it :
$("div").bind("click",function(e){
e.stopPropagation();
});
Fiddle: http://jsfiddle.net/r2h57jhu/
$(document).ready(function () {
$('#subnav').hide();
$(document).click(function(e) {
$('#subnav:visible').hide();
});
$('.products').click( function (e) {
$('#subnav:not(:visible)').show();
e.stopPropagation();
});
});

reset toggle in the navigation menu

I am trying to bring my menu button back to its original state once you click the body or close button.
What I mean is when you click the menu button you will see that it switches to an x. Once you click the x it will switch back to the menu icon. I would like to mimic this same event once you click outside the button or the close button.
$(".gn-icon-menu").click(function() {
$(this).toggleClass("on");
});
http://jsfiddle.net/f4fjf/18/
You can add a click event on the document like this:
$(document).click(function() {
if ($(".gn-icon-menu").hasClass('on')) {
$(".gn-icon-menu").removeClass('on');
}
});
You have to stopPropagation on your .gn-icon-menu click event:
$(".gn-icon-menu").click(function(event) {
event.stopPropagation();
$(this).toggleClass("on");
});
Demo JSFiddle
Try this:
$('body').click(function(evt){
if(evt.target.class == ".gn-icon-menu")
return;
$(".gn-icon-menu").removeClass('on')
});
$(".gn-icon-menu").click(function(e) {
e.stopPropagation()
$(this).toggleClass("on");
});
Working Demo
DEMO
Javascript
$("body").not(".gn-icon-menu").click(function() {
$(".gn-icon-menu").removeClass("on");
});
$(".gn-icon-menu").click(function(e) {
e.stopPropagation();
$(this).toggleClass("on");
});
Hope it helps

Close footer by clicking anywhere on the DOM

I have a question concerning collapsing/expanding a footer. I have a simple basic collapse/expand script going, where when the "Open" button is clicked, the hidden footer slides up and when you click "Close" it slides back down and hides again. Now, I want to attach an instance where I can click anywhere on teh DOM when the footer is open and it will close.
This is the script:
$(document).ready(function () {
// Expand Panel
$("#footerOpen").click(function (e) {
e.preventDefault();
$("div#footerPanel").slideDown("slow");
});
// Collapse Panel
$("#footerClose").click(function (e) {
e.preventDefault();
$("div#footerPanel").slideUp("slow");
});
// Switch buttons from "Log In | Register" to "Close Panel" on click
$("#toggle a").click(function () {
$("#toggle a").toggle();
});
});
Thanks
$(document).ready(function () {
// Expand Panel
$("#footerOpen").click(function (e) {
e.preventDefault();
$("div#footerPanel").slideDown("slow");
});
// Collapse Panel
$("#footerClose").click(function (e) {
e.preventDefault();
$("div#footerPanel").slideUp("slow");
});
// Switch buttons from "Log In | Register" to "Close Panel" on click
$("#toggle a").click(function () {
$("#toggle a").toggle();
});
// click anywhere on teh DOM when the footer is open and it will close.
$("body:not(#footerClose)").click(function (e) {
e.preventDefault();
$("div#footerPanel").slideUp("slow");
});
});
try this one, im using jquery not selector.
Attach a click handler to the document, and do the slideUp in there. You can use the event.target to determine whether or not to perform the slideUp:
$(document).on('click', function(e) {
// Don't slideUp if #footerOpen or #footerPanel are clicked
if ($(e.target).is('#footerOpen, #footerPanel')) {
return;
}
// Do the slideUp!
$('#footerPanel').slideUp('slow');
});
Here's a fiddle
If you have other elements within your #footerPanel, the above probably won't work as the target will likely be something other than #footerPanel, the best thing to do would be to add a click handler to #footerPanel, and prevent the event from propagating and triggering the above click handler:
$('#footerPanel').on('click', function(e) {
e.stopPropagation();
});
Here's another fiddle
Try this it worked for me...
$(document).click(function(event) {
var $target = $(event.target);
if(!$target.is("#footerPanel")){
$("#footerPanel").slideUp('slow');
}
});

Categories