jQuery Dropdown Menu Doesn't Stay Down - javascript

I've created a dropdown menu in a site built on Wordpress. It works, but there's a problem; when the mouse hovers over the menu items, the dropdown menu keeps sliding up and down.
HTML
<nav>
<div class="menu-main-menu-container">
<ul id="menu-main-menu" class="menu">
<li id="menu-item-20" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-20">Art Services
<ul class="sub-menu">
<li id="menu-item-93" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-93">Home</li>
<li id="menu-item-92" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-92">Business</li>
</ul>
</li>
</ul></div>
</nav>
jQuery
$(document).ready(function() {
$(".menu-item").hover(function() { //When trigger is clicked...
//Following events are applied to the subnav itself (moving subnav up and down)
$(this).find(".sub-menu").slideDown('fast').show(); //Drop down the subnav on click
$(this).hover(function() {
}, function(){
$(this).find(".sub-menu").slideUp('slow'); //When the mouse hovers out of the subnav, move it back up
});
//Following events are applied to the trigger (Hover events for the trigger)
}).hover(function() {
$(this).addClass("subhover").css('display','block'); //On hover over, add class "subhover"
}, function(){ //On Hover Out
$(this).removeClass("subhover"); //On hover out, remove class "subhover"
});
});
Thanks!

The ".sub-menu" list is nested inside the 'menu-item', right? So you don't need a to trigger another hover() event. You can trim it down to:
$(document).ready(function () {
$(".menu-item").hover(function () {
//HOVER IN
$(this).addClass("subhover");
$(this).find(".sub-menu").stop().slideDown('fast');
}, function () {
//HOVER OUT
$(this).removeClass("subhover");
$(this).find(".sub-menu").stop().slideUp('slow');
});
});
And add stop() to stop extra running animation when user hover's in and out.
See demo here: jsfiddle.net/AbkXM/

Related

Collapse/hide mobile nav menu after nav link click

I have got an ajax page load working on my wordpress site with both the official twenty sixteen and storefront themes.
The only hitch is that the mobile nav menu does not close once a link has been clicked and the new page has been fetched and loaded by the ajax script.
I've looked through most of the other similar topics and tried various snippets of jquery but have not been able to get it working.
The code for the menu toggle button on twentysixteen is :
<button id="menu-toggle" class="menu-toggle toggled-on" aria-expanded="true" aria-controls="site-navigation social-navigation">Menu</button>
The menu container html is :
<div class="menu-main-container">
<ul id="menu-main" class="primary-menu">
<li id="menu-item-292" class="menu-item menu-item-type-post_type menu-item-
object-page menu-item-292"><a href="https://example.com/my-account/">My
account</a></li>
<li id="menu-item-293" class="menu-item menu-item-type-post_type menu-item-
object-page menu-item-293">Labels
</li></ul>
</div>
From my research into the matter it would seem that there is potentially two ways to achieve what I'm after.
Changing the aria attribute on click from expanded="true" to expanded="false" could do the trick?
I found this code snippet but have no idea how I would actually implement
$(function () {
$('li').on('click', function (e) {
var menuItem = $( e.currentTarget );
if (menuItem.attr( 'aria-expanded') === 'true') {
$(this).attr( 'aria-expanded', 'false');
} else {
$(this).attr( 'aria-expanded', 'true');
}
});
});
Use a jquery click function to trigger the toggle button.
$( "#menu-main" ).click(function() {
$( "#menu-toggle" ).click();
});
Any help would be greatly appreciated! Thank you!
try this
$(function () {
$('#menu-main li>a').on('click', function (e) {
$( "#menu-toggle" ).click();
});
});
or
$(function () {
$('#menu-main li>a').on('click', function (e) {
// i set $(".toggled-on") because i dunno which is your main menu
//<div class="menu-main-container">
// or
//<ul id="menu-main" class="primary-menu">
$(".toggled-on").attr("aria-expanded","false");
$(".toggled-on").removeClass(".toggled-on");
});
});
Hope this is solves your problem,thanks
$("#menu-toggle").click(function(e){ /*for click on menu*/
$('.menu-main-container').toggle()
})
$('.menu-item').click(function(e){ /*for click on link*/
$("#menu-toggle").trigger('click')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="menu-toggle" class="menu-toggle toggled-on" aria-expanded="true" aria-controls="site-navigation social-navigation">Menu</button>
<div class="menu-main-container">
<ul id="menu-main" class="primary-menu">
<li id="menu-item-292" class="menu-item menu-item-type-post_type menu-item-
object-page menu-item-292"><a href="https://example.com/my-account/">My
account</a></li>
<li id="menu-item-293" class="menu-item menu-item-type-post_type menu-item-
object-page menu-item-293">Labels
</li></ul>
</div>

Navigation menu items conflict

The problem is with 2nd and 3rd menu item. Whenever I click the 3rd menu item, the 2nd menu item automatically gets selected/active along with the 3rd one. However, this doesn't happen with other menu items.
For instance(when clicking on the third menu item);
<ul id="menu-1" class="navmenu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-464">
list item 1
</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-456 current_page_item menu-item-466">
list item 2
</li>
<li class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-446">
list item 3
</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-448">
list item 4
</li>
</ul>
Note: I have no clue where those different class on click are coming from.
I tried to add an active class on click and style accordingly but this didn't work. For instance;
JQuery(function(){
jQuery('.navmenu li').on('click', function(){
jQuery(this).addClass('active').siblings().removeClass('active');
});
});
Here is the css :
.navmenu .current_page_item>a, .navmenu .current_page_ancestor>a, .navmenu .current-menu-item>a, .navmenu .current-menu-ancestor>a {
outline: none;
background-color: #7CD0AE;
color: #fff;
}
It's strange why the class on 2nd menu item has current-menu-item and current-page-item indexed when i click on the third one.
Do you have the CSS to look at? A github or jsfiddle of the relevant code would make it lot easier to help.
I replicated what you have here, and if you hover over each list item you can see they have the correct link. Seems like it's probably in the css, or else something not shared here.
https://jsfiddle.net/xpvt214o/814134/
The code below is because they make me add code when I link a jsfiddle
// find elements
var banner = $("#banner-message")
var button = $("button")
// handle click and add class
button.on("click", function(){
banner.addClass("alt")
})
JQuery(function(){
jQuery('.navmenu li').on('click', function(){
jQuery(this).addClass('active').siblings().removeClass('active');
});

After link's first click, make link unclickable, wait for transition end + 1s, then make link clickable again

I have a main menu.
The sub-menu opens when the link of any of the PARENT <li> that have children is clicked.
At this point, a class moves-out is added to the main menu and a CSS transition is started.
After the transition ends, the sub-menu is displayed.
The sub-menu contains the clicked <li> (if clicked again will take us back to the main menu) and it's children.
Here, my goal is to disable the click event on the parent <li> for 1 second,
then after this 1 second give it back the ability to be clicked so we can go back to the main menu.
An example of the navigation would be :
<ul class="main-nav">
<li>Home</li>
<li>Blog</li>
<li>About</li>
<li>Contact</li>
<li>
<span>PARENT</span>
<ul>
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
And so on...
</ul>
</li>
</ul> <!-- .main-nav -->
The only way that worked for me was to hide/show the PARENT when the main menu has the moves-out class added to it like so :
$('.subnav-trigger').on('click', function(event) {
event.preventDefault();
if ($('.main-nav').hasClass('moves-out')) {
var $this = $(this);
$this.hide();
setTimeout(function(){
$this.show();
}, 1000);
}
}
I've tried A LOT off things, this is the only one that is near to my goal.
Instead off $this.hide(), $this.off('click') is working
but inside the setTimeout what ever I do to regain the click doesn't work.
Any help would be greatly appreciated.
NOTE : I want this to prevent fast click/re-click. Don't forget the transition ;)
Thanks again in advance for any help.
SYA :)
Try setting pointer-events on the li tag and resetting it after 1 second.
$('.subnav-trigger').on('click', function(event) {
event.preventDefault();
var $this = $(this);
$this.parent().css("pointer-events","none");
if ($('.main-nav').hasClass('moves-out')) {
$this.hide();
setTimeout(function(){
$this.show();
$this.parent().css("pointer-events","auto");
}, 1000);
}
});
Here's a way using a recursive function that enabled the click handler, disables it on click, enables the transitionend event, adds your class that enables the transition, then re-enables the function. Enabled a 3s transition to slow it down for the example.
var $lis = $('li'),
clicker = function() {
$lis.on('click', function() {
$lis.off('click');
$(this).on('transitionend', function() {
clicker();
}).addClass('color');
});
}
clicker();
li {
transition: background 3s;
}
li.color {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="main-nav">
<li>Home</li>
<li>Blog</li>
<li>About</li>
<li>Contact</li>
</ul>
More like a debounce problem, you might want to take a look at it if you have not used it before, it will help a lot in design you code.
For the following example, I added moves-out to ul for testing, you can check the console.log to see the result. To use in your app don't forgot to remove it (moves-out) from the <ul...>
<ul class="main-nav moves-out">
function debounce() {
if ($('.main-nav').hasClass('moves-out')) {
console.log("Clicked - click event Disabled..");
$(this).off('click');
setTimeout(function() {
$(".subnav-trigger").on('click', debounce);
console.log("click event enabled!");
}.bind(this), 1000);
}
};
$(".subnav-trigger").on('click', debounce);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul class="main-nav moves-out">
<li>Home</li>
<li>Blog</li>
<li>About</li>
<li>Contact</li>
<li>
<span>PARENT</span>
<ul>
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
And so on...
</ul>
</li>
</ul>
<!-- .main-nav -->

jQuery Animated List - Cant click nested items

I'm trying to create an animated nested list using jQuery Animations but I'm not sure what the best way to go about solving this problem is.
The way I've been doing this is by changing the length of the parent list-item and then making the nested list items visible.
The problem is that the length of the parent list item covers the nested list-items. I want to be able to click on a nested list item (such as Edit Profile, Add Music, Playlists, etc) and have it perform something else. For now, I'm trying to just get alerts to prompt to the screen for testing.
HTML
<div id="sidebar-menu" class="col-md-12">
<ul>
<li class="sidebar-menu-item" data-length="2"><span id="IWantToClickHere">Profile</span>
<ul class="blue-special sublist">
<li>Edit Profile</li>
<li>Other</li>
</ul>
</li>
<li class="sidebar-menu-item" data-length="2">Library [<span class="purple-special">3537</span>]
<ul class="blue-special sublist">
<li>Add Music</li>
<li>Playlists</li>
</ul>
</li>
<li class="sidebar-menu-item" data-length="0">Friends</li>
<li class="sidebar-menu-item" data-length="0">Stations</li>
<li></li>
<li class="sidebar-menu-item" data-length="0">Settings</li>
<li class="sidebar-menu-item" data-length="0">Logout</li>
</ul>
</div>
JS
$(document).ready(function() {
$('.sidebar-menu-item').click(function() {
//When: Menu is opened,
if ($(this).hasClass('opened-menu-item')) {
$(this).removeClass('opened-menu-item');
//Reset Menu-Item to default height of 20px per menu-item
$(this).animate({
height: "20px"
},
1000,
//Hide nested content
function() {
$(this).find('.sublist').css('display', 'none');
});
} else {
//When: Menu is closed
$(this).addClass('opened-menu-item');
$(this).find('.sublist').css('display', 'inherit');
//Set Menu-Item length to be the number of nested li * 35
var animateHeight = Number($(this).data("length")) * 35;
if (animateHeight != 0) {
$(this).animate({
height: animateHeight + "px"
},
1000);
}
}
});
});
I put together a simple jsfiddle here: http://jsfiddle.net/W4Km8/8065/
Use event.stopPropagation()
http://jsfiddle.net/W4Km8/8066/
$('.blue-special.sublist').click(function(e){
alert('click');
e.stopPropagation();
})
This prevents the click event from "bubbling" up to the parent. Without this function, an alert would fire, but the parent list would also close.

Add and Remove Class to Element with JavaScript on mouseEnter

I'd like to be able to add and remove classes based on the users mouse moving over certain areas. Below is the navigation code as generate by WordPress:
<nav id="site-navigation" class="main-navigation" role="navigation" data-small-nav-title="Navigation">
<ul id="menu-new-blog-main-2" class="nav-bar clearfix">
<li id="menu-item-10168" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10168">About Proforma</li>
<li id="menu-item-10169" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10169">Proforma.com</li>
<li id="menu-item-10170" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10170">Contact Us</li>
</ul>
</nav>
I've come up with the following JavaScript that targets the <li> in order to change the class of the link within the <li>:
<script>
$(document).ready(function(){
$('#site-navigation li').mouseenter(function(){
$(this).find('li.menu-item a').addClass('animated, bounceIn');
//$(this).find('.span').addClass('fadeInUp');
});
$('#site-navigation li'').mouseleave(function(){
$('#site-navigation li'').find('li.menu-item a').removeClass('animated, bounceIn');
//$('#site-navigation li').find('.span').removeClass('animated, fadeInUp');
});
});
</script>
I've checked the Console and it looks like the event isn't even firing for the code to work. Any help is greatly appreciated.
Check out this fiddle.
Here is the snippet. (I have added alert on enter and leave events for testing).
$(document).ready(function() {
$('#site-navigation li').mouseenter(function() {
alert("Enter " + $(this).text());
$(this).find('li.menu-item a').addClass('animated, bounceIn');
//$(this).find('.span').addClass('fadeInUp');
});
$('#site-navigation li').mouseleave(function() {
alert("Leave " + $(this).text());
$('#site-navigation li').find('li.menu-item a').removeClass('animated bounceIn');
//$('#site - navigation li ').find('.span ').removeClass('animated, fadeInUp ');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav id="site-navigation" class="main-navigation" role="navigation" data-small-nav-title="Navigation">
<ul id="menu-new-blog-main-2" class="nav-bar clearfix">
<li id="menu-item-10168" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10168">About Proforma
</li>
<li id="menu-item-10169" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10169">Proforma.com
</li>
<li id="menu-item-10170" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10170">Contact Us
</li>
</ul>
</nav>
When adding/removing classes with jQuery, they should be space separated, not comma separated. So:
$(this).find('li.menu-item a').addClass('animated bounceIn');
Also, you shouldn't nest your mouseleave inside your mouseenter functions. Also, you should use $.on instead.
Also, within your event handlers, you aren't accessing your elements correctly. $(this) refers to the element that has been entered or left. Since you've set the mouseenter handler on the <li> elements, $(this).find('li.menu-item a') finds nothing.
Try this:
// It's often best practice to cache jQuery objects
// so you're not looking up the elements multiple times.
var $listItems = $('#site-navigation li');
$listItems.on('mouseenter', function(){
$(this).find('a').addClass('animated bounceIn');
});
$listItems.on('mouseleave', function(){
$(this).find('a').removeClass('animated bounceIn');
});
All of this said, if you're simply trying to have an animation on hover, you can achieve that in CSS only with a single class on your <a> elements. The jQuery might be overkill, here.
$('#site-navigation li'')
should be either
$('#site-navigation li')
or
$("#site-navigation li")
(You have wrong quote marks)
and prevent using selector's repetition, do it like this:
var $el = $('#site-navigation li')
$el.mouseenter(function(){
$(this).find('li.menu-item a').addClass('animated bounceIn');
$(this).find('.span').addClass('fadeInUp');
});
$el.mouseleave(function() {
$(this).find('li.menu-item a').removeClass('animated bounceIn');
}
For further reading: http://www.sitepoint.com/efficient-jquery-selectors/
Good Luck

Categories