I have a function that supposed to do a toggle after a click,
but this line of code doesn't do the job after first click.
var toggle = document.querySelector('header nav ul').className = (toggle) ? '' : 'open';
only if i execute it in the console it works..
Plunker:
https://embed.plnkr.co/B5iFwB/
var toggle is inside a block that is not global, you need to write code like:
var toggle;
document.querySelector('.btn-menu').addEventListener('click', function(){
toggle = document.querySelector('header nav ul').className = (toggle) ? '' : 'open';
});
You're seeing this behaviour because your code references a variable toggle which is declared in the same statement. It works in the console because by the time the expression is evaluated for the second time toggle now exists.
I can't suggest an improvement because I don't know how you expect the function to work, given you don't define an initial value for toggle before your statement evaluates.
Also, you're using jQuery, but using Vanilla.js code-style within your jQuery event-handler. You should change your code to be more consistent: either only use idiomtic jQuery or idiomatic Vanilla.js.
There is no need for toggle
You should check if open class is available on element, then remove it else add it. You can use .classList.add and .classList.remove to achieve this:
Updated Code
Sample:
document.querySelector('.btn-menu').addEventListener('click', function() {
var nav = document.querySelector('header nav ul');
if (nav.classList.contains('open'))
nav.classList.remove('open')
else
nav.classList.add('open')
})
body {
margin-top: 80px;
}
header {
width: 100%;
}
header .btn-menu{
background: #e5e5e5;
direction: rtl;
font-size: 25px;
padding-right: 10px;
cursor: pointer;
}
header nav ul {
margin: 0;
list-style-type: none;
text-align: center;
background-color: #1b2125;
height: 0;
}
header nav ul.open {
height: auto;
}
header nav li a {
color: #fff;
}
<header>
<nav>
<div class="btn-menu">≡</div>
<ul>
<li>Home
</li>
<li>About
</li>
<li>Services
</li>
</ul>
</nav>
</header>
Add this to your code it will do top to bottom toggle,
$('.btn-menu').on('click',function(){
$('header nav ul').slideToggle( "slide" );
});
also you need to add JQuery to your code. Add this in your head
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
Related
I've never used jQuery before. I probably messed something up with it. The js is working fine to hide / show the menu. The animation isn't doing anything tho.
Here is my js:
//show / hide menu on mobile
mobileMenuButton.addEventListener("click", function() {
$('mainMenu').slideToggle(200)
if (mainMenu.style.display !== "none") {
mainMenu.style.display = "none";
}
else {
mainMenu.style.display = "flex";
}
})
This is at the top of my js:
//jQuery???
const script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.4.1.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
any help would be appreciated
If you define display: flex within your CSS stylesheet then you do not need to specify it in your javascript. To hide your menu you can use an inline style of display: none on load, as this will be overridden by the slideToggle() function. This will really simplify your code.
A working example is shown below, I've added some basic structure and styling to the demo to help.
DEMO
// Add click event listener
$("#mobileMenuButton").click(function() {
// Slide toggle
$('#mainMenu').slideToggle(200);
})
#navbar {
width: 100%;
background: blue;
padding: 12px;
}
#mainMenu {
display: flex;
background: yellow;
padding: 12px;
flex-wrap: wrap;
}
li {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="navbar">
<button id="mobileMenuButton">Mobile Menu</button>
</div>
<div id="mainMenu" style="display:none;">
<li>Menu item</li>
<li>Menu item</li>
<li>Menu item</li>
</div>
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>
I am trying to make a show content on mouseover and make it stay visible while the mouse is hovered on the list since I am planning to put a button there, but when I do hover, hidden content kept bouncing for some reason.
jQuery code
$('li.employers').mouseover(function () {
$('.employer_content').show("slow");
$(this).addClass("bluehover");
});
$('li.employers').mouseout(function () {
$('.employer_content').hide("fast");
$(this).removeClass("bluehover");
});
HTML
<li class="employers">
<div>employer</div>
<div class="employer_content">some content.</div>
</li>
<li class="court">
<div>court</div>
<div class="court_content">some content.</div>
</li>
http://jsfiddle.net/zLdnnxnh/3/
You can use only CSS to show/hide the contents.
You can take advantage of :hover class in CSS.
Demo using CSS only
.whatwedo {
padding: 20px;
color: #fff;
max-width: 480px;
margin: 0 auto;
}
ul li {
list-style-type: none;
}
ul > li {
background-color: #08588c;
display: inline-block;
width: 100%;
cursor: pointer;
float: left;
max-width: 100px;
padding: 10px;
}
.whatwedo {} ul.wwd_list {
padding: 0;
margin: 0;
}
.employer_content,
.court_content,
.companies_content,
.labor_content {
display: none;
clear: right;
}
.bluehover {
background-color: #01395d;
}
.content {
padding-top: 10px;
display: none;
}
.wwd_list li:hover .content {
display: block;
}
<div class="whatwedo">
<ul class="wwd_list">
<li class="employers">
<div>employer</div>
<div class="content">some content.</div>
</li>
<li class="court">
<div>court</div>
<div class="content">some content.</div>
</li>
<li class="companies">
<div>companies</div>
<div class="content">some content.</div>
</li>
<li class="laborunion">
<div>labour union</div>
<div class="content">some content.</div>
</li>
</ul>
</div>
CSS Demo with Animation
If you still want to use jQuery:
You are using mouseover event that is causing the handler to run when the mouse is moved over the element, use mousein instead
Use hover instead of mousein and mouseout
Your code is not flexible, you can optimize your code as follow
Use stop() to stop the previous animations
Demo
$('.wwd_list li').hover(function() {
$(this).find('div.content').stop().show("slow");
$(this).addClass("bluehover");
}, function() {
$(this).find('div.content').stop().hide("slow");
$(this).removeClass("bluehover");
});
.whatwedo {
padding: 20px;
color: #fff;
max-width: 480px;
margin: 0 auto;
}
ul li {
list-style-type: none;
}
ul > li {
background-color: #08588c;
display: inline-block;
width: 100%;
cursor: pointer;
float: left;
max-width: 100px;
padding: 10px;
}
.whatwedo {} ul.wwd_list {
padding: 0;
margin: 0;
}
.employer_content,
.court_content,
.companies_content,
.labor_content {
display: none;
clear: right;
}
.bluehover {
background-color: #01395d;
}
.content {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div class="whatwedo">
<ul class="wwd_list">
<li class="employers">
<div>employer</div>
<div class="content">some content.</div>
</li>
<li class="court">
<div>court</div>
<div class="content">some content.</div>
</li>
<li class="companies">
<div>companies</div>
<div class="content">some content.</div>
</li>
<li class="laborunion">
<div>labour union</div>
<div class="content">some content.</div>
</li>
</ul>
</div>
You can use hover instead of mouseover and mouseout. Something like this:
$('li.employers').hover(function () {
$('.employer_content').show("slow");
$(this).addClass( "bluehover" );
console.log('mouse in');
}, function() {
$('.employer_content').hide("slow");
$(this).removeClass( "bluehover" );
console.log('mouse out');
});
Here's an example
How about this?
You can use stop() to stop the animation and continue the new animation from where it has stopped
$('.employer_content').stop().show("slow");
$('.employer_content').stop().hide("slow");
As recommended by others, use mouseenter than mouseover
Replace mouseover function with mouseenter and mouseout with mouseleave.
You can see this fiddle is working.
http://jsfiddle.net/ebilgin/zLdnnxnh/7/
Try using mouseenter and mouseleave instead:
From https://api.jquery.com/mouseover/:
This event type can cause many headaches due to event bubbling. For
instance, when the mouse pointer moves over the Inner element in this
example, a mouseover event will be sent to that, then trickle up to
Outer. This can trigger our bound mouseover handler at inopportune
times. See the discussion for .mouseenter() for a useful alternative.
$('li.employers').mouseenter(function () {
$('.employer_content').show("slow");
$(this).addClass("bluehover");
});
$('li.employers').mouseleave(function () {
$('.employer_content').hide("fast");
$(this).removeClass("bluehover");
});
http://jsfiddle.net/zLdnnxnh/5/
Just remove fast from your hide function. It is WORKING. Check this fiddle: http://jsfiddle.net/zp3jr43u/
The JavaScript code should like the following.
$('li.employers').mouseover(function () {
$('.employer_content').show("slow");
$(this).addClass("bluehover");
});
$('li.employers').mouseout(function () {
$('.employer_content').hide();
$(this).removeClass("bluehover");
});
Somehow the mouseover event gets triggered multiple times. I got it working by using the .stop() method before toggling the element.
http://jsfiddle.net/zLdnnxnh/4/
There's no need to have separate classes for each list item you have. Even with these separate classes the code below should get you up and running with ease.
$('.wwd_list li').hover(function () {
$('div:last-child',this).show("slow");
$(this).addClass( "bluehover" );
}, function(){
$('div:last-child',this).hide("slow");
$(this).removeClass( "bluehover" );
});
Note the fact that you only need to use one hover function instead of mouse in and mouse out. This works because you have two divs in the wwd_lsit class and the last one just so happens to be the one you want to target. So be careful with this if you ever want to change something!
Replace mouseover with mouseenter and mouseout with mouseleave.
See a more factorised form :
$('li').on({
mouseenter: function() {
jQuery("div.content", this).show('slow');
$(this).addClass( "bluehover" );
},
mouseleave: function() {
jQuery("div.content", this).hide('fast');
$(this).removeClass( "bluehover" );
}
});
(content class has been added to each content divs)
See the updated fiddle
I'm building a Tumblr site and I want that when a user clicks on the tags span, it should display the tags. It was working properly until today, and now when you click on, it comes back immediately. I can't figure out what is wrong.
HTML
<span class="tags-link">Tags</span>
{block:HasTags}
<ul class="tags tags-close">
{block:Tags}
<li>
{Tag}
</li>
{/block:Tags}
</ul>
{/block:HasTags}
CSS
.tags{
list-style-type: none;
padding: 0;
margin: 24px 0 0 0;
}
.tags-open{
display: block;
}
.tags li{
font-size: 14px;
}
.tags li a{
color: #9CA8B3;
margin-right: 12px;
}
.tags-close{
display: none;
}
jQuery
$(document).ready(function(){
$(".tags-link").click(function() {
$(this).next(".tags").slideToggle(500, function(){
$(this).toggleClass("tags-open");
$(".tags li").css("display","inline-block");
//end animation
});
}); // end tags
}); // end ready
try using .toggle() instead, i believe through JQuery UI you can achieve the slide effect.
$(document).click(function(){
var tags = $(this).next('.tags');
tags.toggle('slide', {direction:'up'},500);
$(this).animate(500).toggleClass("tags-open"); //animate fades class changes
$("li.tags").animate(500).css("display","inline-block");
});
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>