menu close on click on body page - javascript

i have created a dropdown menu which opens on clicking the nav button. But i couldn't find a way to close the dropdown menu when the mouse clicks on the body of the page.
I you can figure it out, please help me
(function(){
var bodyEl = $('body'),
navToggleBtn= bodyEl.find('.nav-toggle-btn');
navToggleBtn.on('click', function(e){
bodyEl.toggleClass('active-nav');
e.preventDefault();
});
})();
active-nav is created within css and linked with menu and body

You can bind click event to body, then check if the event is generated from a particular element using event.target
var bodyEl = $('body');
navToggleBtn = bodyEl.find('.nav-toggle-btn');
$('body').on('click', function (e) {
if ($(e.target).hasClass("nav-toggle-btn")) {
bodyEl.toggleClass('active-nav');
e.preventDefault();
e.stopPropagation();
}
else
{
//close the menu here
}
});

I don't know if it is the right solution, but I would add a div element that covers the entire page.
The menu is on top of that div, but the rest is below. If you click the div, it closes itself and the menu.
So basically, it's a lightbox (as for showing images), but without the shade. Or width a shade, because it will make your menu stand out a little more, and it will fit the expectations of disabling clicks on specific elements in the body.
Another advantage of having an extra element instead of just capturing clicks on the main level on the body, it that it won't interfere with other event handlers on the body itself, which could capture the click and therefor have unexpected results for someone who just wants to close the menu.
A rough example can be found below:
$('header > ul > li').on('click', function() {
// Deactive all menu items
$('ul.active').removeClass('active');
// Activate the one clicked.
$(this).closest('li').addClass('active');
// If there is no lightbox setup a new one.
var box = $('.lightbox');
if (box.length == 0) {
// It's just a div with a class.
$('<div>')
.prependTo($('body'))
.addClass('lightbox')
.on('click', function() {
// Lightbox clicked? Remove it, and deactivate the menu.
$('.lightbox').remove();
$('li.active').removeClass('active');
});
}
});
li {
padding: 1em;
}
header > ul > li {
display: inline-block;
vertical-align: top;
position: relative;
background-color: #eee;
}
li > ul {
display: none;
background-color: #ddd;
position: absolute;
top: 100%;
left: 0;
}
li.active > ul {
display: block;
}
.lightbox {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0,0,0, 0.2); /* Just for show */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
Header, page title
<ul>
<li>Main
<ul>
<li>sub</li>
<li>sub</li>
<li>sub</li>
<li>sub</li>
</ul>
</li>
<li>Other</li>
<li>About</li>
</ul>
</header>
<section>
Main content
</section>

Related

jQuery activate href if element on top

I have a simple menu, everytime i click an element the others fadeOut and the clicked one goes up if it's not the first element, and after that i activate the href of the link.
To activate the link i need to make sure that the element is in the top of the page, after the addClass slideUpSm the clicked item gets new position top but i think the position top needs to be refreshed because the addClass slideUpSm gets the css top 0
setTimeout(function() {$('.main-nav li').addClass('slideUpSm')}, 1200);
After that, i can activate the window location, i have tried the hasClass methode and also tried to check if the new position top equals zero, here is my attempt https://jsfiddle.net/n37kgv4r/
setTimeout(function() {window.location = href}, 100);
If you just want to hide the other links and navigate to only the clicked node, we dont need to use the css top. We can achieve this with simple jquery code.
$(document).ready(function(){
$('.main-nav li a').click(function(e){
$(this).parent().addClass('show');
$('.main-nav li').not('.show').slideUp(1200);
var obj = $(this);
setTimeout(function(){
//remove the alert
alert("Navigating to "+ obj.attr('href'));
window.location.href=obj.attr('href');},2000)
return false;
});
});
a {
text-decoration: none;
color: black;
}
.main-nav {
position: relative;
}
.main-nav li {
position: sticky;
display: flex;
font-size: 60px;
line-height: 43px;
letter-spacing: -3px;
margin-bottom: 11px;
transition: all 2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<ul class="main-nav">
<li>Page 1</li>
<li>Page 2</li>
<li>Page 3</li>
</ul>

hover on dynamically created list

I have a menu with a list of items created dynamically using javascript.
They have different colour and country attributes created using setAttribute.
$("#menuList a").hover(
function() {
var countryName = $(this).attr('country');
var fruitColour = $(this).attr('colour');
$('#toshow').append($("countryName \n fruitColour"));
},
function() {}
);
.toshow {
display: none;
}
#menuList a:hover div.toshow {
top: 0;
right: 0;
display: block;
position: absolute;
z-index: 99999;
background: red;
width: 200px;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menubar" id="menuList">
<li>Watermelon</li>
<li>Grapes</li>
<li>Strawberry</li>
<li>Blueberry</li>
</ul>
<div class="toshow" id="toshow"></div>
Here, I want to have a separated hidden div (display at top right of the page or next to the menuList) that does not have any content until any of the <a> tag being hovered, and show its responding two attributes until no more mouse hovered.
The code does not have errors. But I don't see anything in red when the mouse hovered through the list. Is it possible to achieve what I am looking for?
You can use the mouseout event to hide the toshow div with hide as you leave a list element. And at each hover event, you can change the html of toshow to the values of the li element which the user is hovering over and use show to display it.
Also make sure you attach the event handlers after you've inserted the html of the dynamically generated list.:
function displayGeneratedList() {
$('#menuList').html(`
<li>Watermelon</li>
<li>Grapes</li>
<li>Strawberry</li>
<li>Blueberry</li>
`);
$("#menuList a").hover(function() {
var countryName = $(this).attr('country');
var fruitColour = $(this).attr('colour');
$('#toshow').html(`${countryName}<br>${fruitColour}`).show();
});
$('#menuList a').mouseout(function() {
$('#toshow').hide();
});
}
$(document).ready(function() {
displayGeneratedList();
});
#menuList {
display: inline-block;
}
.toshow {
display: none;
float: right;
background: maroon;
width: 200px;
height: 100px;
padding: 5px;
color: white
}
<ul class="menubar" id="menuList">
</ul>
<div class="toshow" id="toshow"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

All sub-menus are showing up on click

I want to only show the sub-menu that is the child of the clicked li and button when it is clicked. Currently the click and show and hide are working but the code below shows both the sub-menus on click, I want only the child sub-menu of the li button to show on click.
<ul id="menu-main-menu" class="nav-menu">
<li class="menu-item">Menu link
<button aria-expanded="false" class="dropdown-toggle"></button>
<ul class="sub-menu">
<li class="menu-item">link1</li>
<li class="menu-item">link1</li>
</ul>
</li>
<li class="menu-item">Menu link 2
<button aria-expanded="false" class="dropdown-toggle"></button>
<ul class="sub-menu">
<li class="menu-item">link1</li>
<li class="menu-item">link1</li>
</ul>
</li>
</ul>
<div class="site-content"></div>
jQuery:
jQuery(document).ready(function ($) {
$("#menu-main-menu").on('click', 'button', function (event) {
$('ul.sub-menu').appendTo('.site-content');
if($('ul.sub-menu:visible').length)
$('ul.sub-menu').hide();
else
$('ul.sub-menu').show();
});
});
CSS:
#menu-main-menu ul.sub-menu {
display: none;
}
ul.sub-menu {
display: none;
position: absolute;
z-index: 200000;
top: 0;
left: 1.5%;
right: 1.5%;
margin: 0 auto 0 auto;
padding: 20px;
list-style: none;
}
ul.sub-menu li {
width: 24%;
display: inline-block;
padding: 8px 9px;
text-align: center;
}
ul.sub-menu .toggled-on {
display: block;
}
.site-content {
display: block;
position: relative;
}
Solution: So the solution here was to not use appendTo(), as I had to put the element back where it came from when toggled off. The solution was to merely toggle the menu item using correct position: absolute CSS for the .sub-menu and $()on('click' to toggle it.
jQuery('#menu-main-menu').on('click', 'button', function(event) {
if($(this).closest("li.menu-item").children("ul.sub-menu").length > 0)
{
$(this).closest("li.menu-item").children("ul.sub-menu").slideToggle('fast');
return false;
}
});
See it working here: http://jsfiddle.net/abdqt6d9/
The problem is that you are writing incorrect selectors for your jquery:
$('ul.sub-menu')
That means it will grab all matching elements within the page.
What you need to do is grab the corresponding li. Within your click(), the $(this) becomes the button that is clicked. Using .parent() will give you the li element. From there, search for your corresponding sub-menus within the li_element:
var $li_element = $(this).parent()
var $sub_menu = $li_element.find(".sub-menu")
if ($li_element.find(".sub-menu:visible").length > 0) {
$sub_menu.hide()
} else {
$sub_menu.show()
}
The other problem is that perhaps your styling for your sub-menu is above the buttons. so once you show it, you can no longer press the button. So you need to restyle your sub-menus.
$("ul.sub-menu") will apply to all the sub-menus, so you need to change it to only look for the sub-menu within the buttons parent. You can do this using .closest (or just .parent()) and then .find
//closest("li") will find the closest parent that is an li
//find(".sub-menu") will find the sub-menu within
$(this).closest("li").find(".sub-menu").show();
If you your button is always going to be before the sub-menu you can slim it down to just .next(".sub-menu")
$(this).next(".sub-menu").show();

Fading one div out and another one in, in it's place

There are 3 divs and 3 links.
Only one div should be displayed at a time. When user clicks on a link for one of the other divs, the current one should fade out and the selected one should fade in, in place of the previous div.
Here is the code at the moment:
Javascript
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
switches = $('#switches > li');
slides = $('#slides > div');
switches.each(function(idx) {
$(this).data('slide', slides.eq(idx));
}).click(
function() {
switches.removeClass('active');
slides.removeClass('active').fadeOut('slow');
$(this).addClass('active');
$(this).data('slide').addClass('active').fadeIn('slow');
});
});
</script>
CSS
<style style="text/css">
ul {
list-style: none;
}
li:hover {
text-decoration: underline;
}
#switches .active {
font-weight: bold;
}
#slides div {
display: none;
}
#slides div.active {
display: block;
}
.outer {
position: absolute;
}
.outer div {
width: 600px;
height: 300px;
}
#uno {
background-color: red;
}
#dos {
background-color: blue;
}
#tres {
background-color: green;
}
</style>
HTML
<ul id="switches">
<li class="active">First slide</li>
<li>Second slide</li>
<li>Third slide</li>
</ul>
<div class="outer" id="slides">
<div class="active" id="uno">
First div.
</div>
<div id="dos">
Second div.
</div>
<div id="tres">
Third div.
</div>
</div>
You can view the page here:
http://dl.dropbox.com/u/6920023/proofOfConcept.html
I'm attempting to use standard Jquery to do this, but clearly there is something wrong with my javascript code.
Can you spot what's wrong and how to fix it?
Your CSS defines a div that's not active as hidden. So as soon as you remove the active class, it will be hidden immediately.
So, remove this entry:
#slides div {
display: none;
}
And add something like this on page load:
$(function() {
$('#slides div:not([class="active"])').hide();
}); // will hide inactive slides initially but not always
The issue is that you use slides.removeClass('active').fadeOut('slow');. So first it will remove the active class, which means (according to your CSS) that it will be a regular div, thus with the property display: none;.
So your div is automatically hidden. It's only afterwards that you do your fadeOut('slow'), on a hidden div thus.
Better would be to do something like:
$('div.active').fadeOut(1000).delay(1000).removeClass('active');
$(this).delay(2000).fadeIn(1000).delay(1000).addClass('active');
This works, if I understand the question correctly.
The issue is that you can't fade in an element that is hot hidden or unchcanged.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
switches = $('#switches > li');
slides = $('#slides > div');
switches.each(function(idx) {
$(this).data('slide', slides.eq(idx));
}).click(
function() {
switches.removeClass('active');
slides.removeClass('active').fadeOut('slow').hide();
$(this).addClass('active');
$(this).data('slide').addClass('active').fadeIn('slow');
});
});
</script>

Jquery Drop Down menu blinks only on IE

I am starting a Jquery drop down menu for a new project and it is working as expected on Google Chrome, Firefox, Safari but of course it is giving me some headache on Internet Explorer.
here's the thing,
See this page
http://www.universidadedoingles.com.br/dev/index.ASP
on mouse over the menu HOME, the drop down appers, when you move over the links in IE you see some flashes of the background, which doesn't happens on Chrome and ETC.
here's the js coda I am using to do the dd menu.
<script type="text/javascript">
$(document).ready(function() {
$("ul.mainmenu li.menuhome").mouseover(function(){
$(".arrow-spacer").show(); //When mouse over ...
//Following event is applied to the subnav itself (making height of subnav 150px)
$(this).find('.submenu').show().animate({height: '150px', opacity:'1'},{queue:false, duration:300})
});
$("ul.mainmenu li.menuhome").mouseout(function(){ //When mouse out ...
//Following event is applied to the subnav itself (making height of subnav 0px)
$(this).find('.submenu').hide().animate({height:'0px', opacity:'0'},{queue:false, duration:200})
});
//menu itembackground color animation
$("li").hover(function() {
$(this).animate();},
function() {
$(".arrow-spacer").hide();
});
});
</script>
That's it, I guess it may be simple, but it's been weeks and I still can't get it to work.
Thanks a lot.
I noticed that the anchor <a> tags have a margin on them. My first thing would be to try using padding instead. IE doesn't treat a hover in the margin the same way as other browsers.
in some cases it helps to set a z-index on elements that should placed in top of other elements.
In your case I would try to set the z-index on <ul class="submenu">
No blinks anymore! I changed one word hide() to stop (), now there is no blinking on iE. but...
After you show the menu 1 time, everytime you get your mouse below the link or close the link, the menu shows up again.
check this
www.universidadedoingles.com.br/dev
you'll be able to see its behavior
The thing is that the focus to <li> is lost when you mouse over an <a> element.
Here is something you could use to overcome this. I avoided using the <a> tag, instead I used a JavaScript function to send the user to the preferred location. I used JavaScript rather than jQuery hoping to make it more self-explanatory.
<script type="text/javascript" src="jquery.js" ></script>
<script type='text/javascript'>
$(document).ready(function() {
$('#n li').hover(function() {
$('ul', this).slideDown(200);
$(this).children('a:first').addClass('h');
}, function() {
$('ul', this).slideUp(200);
$(this).children('a:first').removeClass('h');
});
});
function gotoPage(pnumber){
var goto;
if(pnumber==1){
goto="home.html";
}else if(pnumber==2){
goto="watsnew.html";
}else if(pnumber==3){
goto="aboutus.html";
}else if(pnumber==4){
goto="contactus.html";
}
window.location.href=goto;
}
</script>
<style type="text/css">
#n {
padding: 0;
list-style: none;
padding-left: 15px;
padding-right: 15px;
width:5em;
}
#n li {
/*display:inline;*/
background: none;
position: relative;
z-index: 1;
font-weight:bold;
margin: 0 auto;
}
#n li .h {
background-color: #fff;
border-left: 1px solid #CF3;
border-right: 1px solid #CF3;
color: #576482;
height:20px; }
#n ul {
position: absolute;
display: none;
margin: 0; padding: 0;
list-style: none
padding-bottom: 3px;
width:200px;
}
#n ul li {
list-style-type:none;
padding:10px;}
#n ul li:hover {
background:#960;}
</style>
<div>
<ul id="n">
<li>MENU
<ul >
<li value="1" onclick="gotoPage(this.value)">HOME</li>
<li value="2" onclick="gotoPage(this.value)">WATS NEW</li>
<li value="3" onclick="gotoPage(this.value)">ABOUT US</li>
<li value="4" onclick="gotoPage(this.value)">CONTACT US</li>
</ul>
</li>
<ul>
</div>

Categories