Hide mobile menu on click anywhere on a website [duplicate] - javascript

This question already has answers here:
Mobile Menu - Click outside menu to close menu
(2 answers)
Closed 6 months ago.
I have one problem, I want to hide the menu on click anywhere on the website, but nothing works for me :(
Here is my code for closing button:
$('.menu-toggle').on('click',function(e){
e.preventDefault();
if ( $('.lang-mobile').hasClass('is-open') ){
$('.lang-mobile a').trigger('click')
}
if ( !$('header').hasClass('is-open')){
$('header').addClass('is-open');
$('#navbar-main').fadeIn();
}
else {
$('header').removeClass('is-open');
$('#navbar-main').fadeOut();
}
Here is some of my HTML structure
<header class="header clear is-open" role="banner">
<div class="navbar" id="navbar-main" style="display: block;">
<div class="navbar-container" style="height: 797px;">
<div class="navbar-item">
I've tried something like this
$(document).click(function() {
var container = $("#navbar-main");
if (!container.is(event.target) && !container.has(event.target).length) {
container.hide();
}
});
and it's not working, could you please help me? What is incorrect here?

This snippet handles two cases.
Every time there's a click on the page it'll check if the header is open and close it
Every time there's a click on the .menu-toggle item it'll open or close the header
<script>
$(document).on('click', function() {
var header = $(".header");
if ( header.hasClass('is-open') ) {
header.fadeOut();
header.removeClass('is-open');
}
});
$('.menu-toggle').on('click', function() {
var header = $(".header");
if ( !header.hasClass('is-open') ) {
header.fadeIn();
header.addClass('is-open');
} else if ( header.hasClass('is-open') ) {
header.fadeOut();
header.removeClass('is-open');
}
});
</script>

Thank you yousoumar
for sharing this link as an answer - Mobile Menu - Click outside menu to close menu this the only thing that worked for me! I only added some needed parts to this code, so here you go if anyone noob like me and needs more details :D
$(document).mouseup(function(e){
var header = $ (".header, .lang-mobile"); //I have two toggle menus with class that collapse navbars, I also have animation on toggle button that's why I need them also to work
var menu = $(".navbar, .dropdown");//this is to hide menus
if (!menu.is(e.target) // The target of the click isn't the container.
&& menu.has(e.target).length === 0) // Nor a child element of the container
{
header.removeClass('is-open');
menu.hide();
}
});

Related

document.querySelector() always selects the element with the class "Open" even after it has been removed and replaced with the class "Close" | Vue3 js

So I was trying to find a Vue Solution of the jQuery SlideUp() and slideDown() functionality. And I have run into a problem while creating the same for my Side Bar Menu Open and Close funtion. See my code below:
UPDATE: Here's the stackblitz link to the problem: https://stackblitz.com/edit/vue-lvjxmz
I'd really appreciate if someone helps me to solve this problem. Thanks.
export default {
mounted() {
let hasSubmenu = Array.from(document.querySelectorAll(".hasSubmenu.close"));//Select all hasSubmenu
let self = this;
hasSubmenu.forEach(function (el) {//Show Hide Submenu Based On Clicks
el.addEventListener("click", self.menuOpen.bind(this, el));
});
},
methods:{
//Menu Opener Function
menuOpen(el){
let ul = el.querySelector("ul");
ul.style.height = `${ul.scrollHeight}px`;
el.classList.remove("close");//Remove The Class "close"
el.classList.add("open");// add the class "open"
this.menuClose();//Call this function to close the menu
},
//Menu Closer Function
menuClose(){
console.log(document.querySelector(".hasSubmenu.open"));//Log the Selected Element
document.querySelector(".hasSubmenu.open").addEventListener("click", function (e) {
e.currentTarget.querySelector("ul").style.height = "0px";
e.currentTarget.classList.remove("open");
e.currentTarget.classList.add("close");
});
}
},
}
<ul id="main-nav">
<li class="hasSubmenu close">
<div> Main Menu One</div>
<ul style="height: 0px">
<li>
Sub Menu One
</li>
<li>
Sub Menu Three
</li>
</ul>
</li>
</ul>
So what we are doing here is: we are first selecting all the hasSubmenu items with the class close has in it. Then firing the click event where the menu opens and replace the class close with "open". Then we are calling the menuClose function where we are selecting the element which has the .open class. then firing another click event when the menu closes and removes the class .open and adds .close again.
The problem is somehow the menuClose function keeps selecting the element as if it was pointing to the hasSubmenu element and caching it in, it doesn't matter whether the class has been changed or not. I mean, even after the .open class has been removed on the click event it stills selecting it and thus clicking on the menuItem after the first 2 clicks the menuOpen function first opens the menu then calls the menuClose function and immediately closes the menu again although menuClose functionality only added to document.querySelector(".hasSubmenu.open"). As if, it first selected the element itself not the class and cached it in.
Okay, as per James Reply I have managed to solve the problem in another way. So the solution goes as below:
// Simply write one function and check if the submenu's
// height is 0px or not. Based on that write your
// open and close logics
menuOpenClose(el){
let ul = el.querySelector("ul");
let getHeight = ul.style.height;
console.dir(getHeight);
if (getHeight == '0px' || !getHeight.length) {
ul.style.height = `${ul.scrollHeight}px`;
el.classList.remove("close");
el.classList.add("open");
} else{
ul.style.height = `0px`;
el.classList.remove("open");
el.classList.add("close");
}
}

Using A Conditional Statement For A Menu

I have a Menu for a website that is broken into two parts.
A left hand panel and a right hand panel.
When clicking one of the two menu buttons the panel slides in from the side and covers the browser window.
At the moment I have got the function working.
Where I am getting stuck is creating the logic for the function using conditionals that say:
'If the left panel is 'active' / 'visible' and the right panel button is clicked, slide the left panel out of view while sliding in the right panel.'
and Vise Versa.
Here is the js-fiddle and below is the code:
NOTE: I've tried to fire an alert when the class name .panel--oneBtn.is-active yet nothing is happening. Thanks
HTML
<div class="wrapper">
<div class="nav_header">
<div class='nav_header_link_wrap abso-left panel--oneBtn'>
<span class="nav_header_link abso-left open">Eat.Drink.Sleep</span>
<span class="nav_header_link abso-left close">Close</span>
</div>
<div class='nav_header_link_wrap abso-right panel--twoBtn'>
<span class="nav_header_link abso-right open">Bookings/Contact</span>
<span class="nav_header_link abso-right close">Close</span>
</div>
</div>
<div class="menuPanel panel--one"></div>
<div class="menuPanel panel--two"></div>
</div>
JS
function navSlider(){
var $buttonOne = $('.panel--oneBtn'),
$buttonTwo = $('.panel--twoBtn');
$buttonOne.on('click', function() {
$('.panel--one').toggleClass('is-visible');
$buttonOne.find('.open').toggleClass('is-gone');
$buttonOne.find('.close').toggleClass('is-visible');
$(this).toggleClass('is-active');
});
$buttonTwo.on('click', function() {
$('.panel--two').toggleClass('is-visible');
$buttonTwo.find('.open').toggleClass('is-gone');
$buttonTwo.find('.close').toggleClass('is-visible');
$(this).toggleClass('is-active');
});
if ( $buttonOne.hasClass('is-active') ){
alert('Left is active');
} else if ($buttonTwo.hasClass('is-active') ){
alert('Right is active');
}
}
navSlider();
Is this effect what you're looking for?
https://jsfiddle.net/snookieordie/oez0488h/41/
$buttonOne.on('click', function() {
//added this code
if ( $buttonTwo.hasClass('is-active') ) {
$('.panel--two').toggleClass('is-visible');
$buttonTwo.find('.open').toggleClass('is-gone');
$buttonTwo.find('.close').toggleClass('is-visible');
$buttonTwo.toggleClass('is-active');
}
//
$('.panel--one').toggleClass('is-visible');
$buttonOne.find('.open').toggleClass('is-gone');
$buttonOne.find('.close').toggleClass('is-visible');
$(this).toggleClass('is-active');
});
$buttonTwo.on('click', function() {
//added this code
if ( $buttonOne.hasClass('is-active') ) {
$('.panel--one').toggleClass('is-visible');
$buttonOne.find('.open').toggleClass('is-gone');
$buttonOne.find('.close').toggleClass('is-visible');
$buttonOne.toggleClass('is-active');
}
//
$('.panel--two').toggleClass('is-visible');
$buttonTwo.find('.open').toggleClass('is-gone');
$buttonTwo.find('.close').toggleClass('is-visible');
$(this).toggleClass('is-active');
});

Close accordion alike div using jQuery?

I have this simple code which shows 3 items
When I press the header ($(".fileHeader")) , it should open then next element which is the next element (hidden div) ($(".LST_Documents"))
sketch :
JSBIN : it does work.
Most important :
When I press on a $(".fileHeader")- i need to close all other $(".LST_Documents") and then ( that why i used promise) open the relevant $(".LST_Documents").
The problem is (look at the pic) if i press again on the first $(".fileHeader").
what is happening is that it closing and then re opening. and I want it to stay CLOSED.
P.S.
I could solve it with class ( .rowOpen or something like that) but I want to do it via JS/JQ only.
How can I enhance my code to work as expected ?
Just hold the header's content visibility state before sliding it up. And slide down the content only when it was not visible.
Here is the fiddle.
$(".fileHeader").on('click', function () {
var content$ = $(this).next(),
isContentVisible = content$.is(':visible');
$(".LST_Documents:visible").slideUp().promise().done(function () {
if ( ! isContentVisible ) {
content$.slideDown();
}
});
});
How 'bout a simple condition:
$(".fileheader").on('click', function() {
var next = $(this).next();
if(next.is(':visible'))
{
next.slideUp();
}
else
{
$(".LST_Documents:visible").slideUp().promise().done(function() {
next.slideDown();
});
}
});

Show div once clicked and hide when clicking outside

I'm trying to show the #subscribe-pop div once a link is clicked and hide it when clicking anywhere outside it. I can get it to show and hide if I change the:
$('document').click(function() {
TO
$('#SomeOtherRandomDiv').click(function() {
HTML:
<div id="footleft">
Click here to show div
<div id="subscribe-pop"><p>my content</p></div>
</div>
Script:
<script type="text/javascript">
function toggle_visibility(id) {
var e = document.getElementById("subscribe-pop");
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
}
$('document').click(function() {
$('#subscribe-pop').hide(); //Hide the menus if visible
});
$('#subscribe-pop').click(function(e){
e.stopPropagation();
});
</script>
You have to stop the event propagation in your container ('footleft' in this case), so the parent element don't notice the event was triggered.
Something like this:
HTML
<div id="footleft">
<a href="#" id='link'>Click here to show div</a>
<div id="subscribe-pop"><p>my content</p></div>
</div>
JS
$('html').click(function() {
$('#subscribe-pop').hide();
})
$('#footleft').click(function(e){
e.stopPropagation();
});
$('#link').click(function(e) {
$('#subscribe-pop').toggle();
});
See it working here.
I reckon that the asker is trying to accomplish a jquery modal type of display of a div.
Should you like to check this link out, the page upon load displays a modal div that drives your eye into the center of the screen because it dims the background.
Moreover, I compiled a short jsFiddle for you to check on. if you are allowed to use jquery with your requirements, you can also check out their site.
Here is the code for showing or hiding your pop-up div
var toggleVisibility = function (){
if($('#subscribe-pop').is(":not(:visible)") ){
$('#subscribe-pop').show();
}else{
$('#subscribe-pop').hide();
}
}
Changing $(document).click() to $('html').click() should solve the main problem.
Secondly, you do not need the toggle_visibility() function at all, you can simply do:
$('#subscribe-pop').toggle();
Ref: changed body to html as per this answer: How do I detect a click outside an element?

CSS/Javascript Mouseover Popup box

I have table cell with a javascript/css content box that pops up upon mouseover.
There are 20 cells on the page. Everything is working correctly, in that when you mouseover the product link, you see the content box. However, I want to put a LINK inside the content box that the user can click on if they choose. So, the popup box has to stay up long enough for the user to mouseover to click the link.
Really, I want the OnMouseOver to stay open until either a second or two has gone by and/or the user OnMouseOver's another cell.
The problem I'm having is that the pop up box doesn't stay open (due to OnMouseOut) to click the link. If I turn OnMouseOut off (which I tried), then all the pop up boxes just stay open, so this doesn't do the job either.
My CSS looks like this:
<style type="text/css" title="">
.NameHighlights {position:relative; }
.NameHighlights div {display: none;}
.NameHighlightsHover {position:relative;}
.NameHighlightsHover div {display:block;position:absolute;width: 15em;top:1.3em;*top:20px;left:70px;z-index:1000;}
</style>
And the html:
<td>
<span class="NameHighlights" onMouseOver="javascript:this.className='NameHighlightsHover'" onMouseOut="javascript:this.className='NameHighlights'">
Product 1
<div>
# of Votes: 123<br>
% Liked<br>
<a href="product review link>See User reviews</a>
</div>
</span>
</td>
So, how can I make the pop up box stay open long enough to click on the link, but also make it disappear if another content box is activated?
Thanks in advance.
You have to improve your HTML markup for this task, need to get rid of inline event handlers:
<span class="NameHighlights">
Product 1
<div>
# of Votes: 123<br>
% Liked<br>
See User reviews
</div>
</span>
Then you have to bind your events to all .NameHighlights spans:
var span = document.querySelectorAll('.NameHighlights');
for (var i = span.length; i--;) {
(function () {
var t;
span[i].onmouseover = function () {
hideAll();
clearTimeout(t);
this.className = 'NameHighlightsHover';
};
span[i].onmouseout = function () {
var self = this;
t = setTimeout(function () {
self.className = 'NameHighlights';
}, 300);
};
})();
}
http://jsfiddle.net/3wyHJ/
So the idea is to use setTimeout method.
Notes: I used querySelectorAll which is not supported by IE7, if you need to support it then you can use any of implementations of the getElementsByClassName method.
In case anyone is looking for a jQuery version of the accepted answer:
var t;
$(function(){
$('span.NameHighlights').mouseover(
function(e){
hideAll();
clearTimeout(t);
$(this).attr('class', 'NameHighlightsHover');
}
).mouseout(
function(e){
t = setTimeout(function() {
//$(this).attr('class', 'NameHighlights');
hideAll();
}, 300);
}
);
});
function hideAll() {
$('span.NameHighlightsHover').each(function(index) {
console.log('insde hideAll');
$(this).attr('class', 'NameHighlights');
})
};
jsFiddle

Categories

Resources