jQuery collapsible through toggleClass on element - javascript

I have an off canvas navigation menu (classname that is enabled via hover-over using jQuery on my Wordpress site. It is, as it should be, not visible on page load.
For the mobile version, I want the same nav menu to be activated by clicking on a menu icon (that I've given two classes, in this order: mobile-nav-toggle show-nav-mobile). The toggle method seems to only work for a vertical toggle. My solution to replicating the same animation on click rather than hover, is by using the toggleClass method on the icon to toggle between a classname that opens the menu nav (show-nav-mobile) and closes it (hide-nav-mobile) Using the below code:
jQuery(".show-nav-mobile").click(function(){
jQuery(".offcanvasmainnav").animate({left:'0px' }, 250);
});
jQuery(".mobile-nav-toggle").click(function(){
jQuery(".mobile-nav-toggle").toggleClass("show-nav-mobile hide-nav-mobile");
});
jQuery(".hide-nav-mobile").click(function(){
jQuery(".offcanvasmainnav").animate({left:'-640px' }, 250);
});
That doesn't seem to do the job though. The jQuery opens the offcanvasmain div just fine, but doesn't close it again.
What is wrong with my approach?

I assume your element initially looks somewhat like this:
<nav class="mobile-nav-toggle hide-nav-mobile">...</nav>
This means that
a) Both these click handlers will always run when clicking, no matter if the element still has the class hide-nav-mobile:
jQuery(".mobile-nav-toggle").click(function(){
jQuery(".mobile-nav-toggle").toggleClass("show-nav-mobile hide-nav-mobile");
});
jQuery(".hide-nav-mobile").click(function(){
jQuery(".offcanvasmainnav").animate({left:'-640px' }, 250);
});
jQuery finds the element at the moment you define the click handler; it doesn't recheck if the element still has this class when clicking later.
b) This never attaches a click handler:
jQuery(".show-nav-mobile").click(function(){
jQuery(".offcanvasmainnav").animate({left:'0px' }, 250);
});
because at the time of calling jQuery(".show-nav-mobile") it cannot find any element with that class.
To fix it, do this all in a single click handler:
jQuery(".mobile-nav-toggle").on('click', function(){
const that = jQuery(this);
that.toggleClass("show-nav-mobile hide-nav-mobile");
jQuery(".offcanvasmainnav").animate({left: that.hasClass('show-nav-mobile') ? '0px' : '-640px' }, 250);
});

Related

Animate icon don't take his original position on toggle click

I have a accordion menu which have for each parent menu a icon, and this icon is animated with css transition and transform. I added a class with a if condition to the click event. The problem is that when I click for example on Menu1, the icon animation does very well, but if I click directly on Menu2, the menu2 dropdown appear but icon from the menu1 don't take his original position.
This problem applies to each icon in each menu/submenu, I thinks that I have a mistake in my code.
$(document).ready(function() {
// Icons effect
$('#mw_nav .toggle').click(function() {
if($(this).hasClass('rotate_close'))
{
$(this).addClass('rotate_open').removeClass('rotate_close');
}
else {
$(this).addClass('rotate_close').removeClass('rotate_open');
}
});
// Toggle Menu Items
$(function () {
$("#m_nav > ul ul").hide();
$('#m_nav .toggle').click(function (e) {
e.preventDefault();
e.stopPropagation();
var $parentli = $(this).closest('li');
$parentli.siblings('li').find('ul:visible').slideToggle(400);
$parentli.find('> ul').stop().slideToggle(400);
$(this).remove;
});
});
});
FIDDLE
Any help would be appreciated
There are 2 issues I see with your code. The first is a recommendation to NOT have $(function() { // your code }) inside of $(document).ready(). $(function() {}) is actually just shorthand for $(document).ready() so you are adding code you do not need.
The second is an issue with your logic.
$('#mw_nav .toggle') and $('#m_nav .toggle') click listeners are essentially adding a click listener on the same exact element, but both run different logic. When the $('#mw_nav .toggle') click listener is getting called it checks for a class to exist to decide what class it needs to remove and add. When $('#m_nav .toggle') click listener is getting called it calls a slideToggle function on the current nested <ul> regardless if another menu is opened or closed and there is no check in place of whether or not the rotate_open/rotate_close classes exist allowing for the classes to get swapped. There is no relation between the swapping of rotate_open/rotate_close classes and the logic that slideToggles <ul> up/down.
UPDATE
I have edited your code and made updates that will now work seen here: https://jsfiddle.net/vhfn0q5a/9/
I have added a class of .top_level to the top level items in your HTML. I use this as a way of differentiating the top level <li> from the sub menus. Next, at the end of the click event listener I check to see if the .toggle element clicked is a top level element, if so I target all top level elements that are not the current selected and make sure they have the .rotate_close class.
$(function() {}) shorthand reference
Use this code in your first click handler:
$('#mw_nav .toggle').click(function() {
$(this).toggleClass('rotate_close rotate_open');
if ($('#mw_nav .toggle').not(this).hasClass('rotate_open')) {
$('#mw_nav .toggle').not(this).removeClass('rotate_open').addClass('rotate_close');
}
});
I've updated your FIDDLE with an working example.
Cheers!

Once menu item is clicked, close menu and revert the classnames & jquery

Ok... So I have this drop down menu working as I'd like... however I'm trying to figure out how to revert the function back to it's original state after a menu item is clicked.
So first when you trigger the function it does & works great the following:
It swaps out .menu_hide and .lockscreen for .menu_show and .lockscreen_on.
// show and hide mobile menu
$('#triggerMobileMenu').click(function(e) {
e.preventDefault();
// Toggle all 4 classes off or on
$('#mobileMenu').toggleClass('menu_hide menu_show');
$('#mobileScreen').toggleClass('lockscreen_off lockscreen_on');
But now I'm trying to add another piece that says once a menu item is clicked, close the menu and swap the classes back to their original state from .menu_show and .lockscreen_on, to .menu_hide and .lockscreen_off.
$('#mobileMenu ul li a').on('click',function(){
$('#mobileMenu').toggleClass('menu_show menu_hide')({ autoCloseOnClick: true });
$('#mobileScreen').toggleClass('lockscreen_on lockscreen_off')({ autoCloseOnClick: true });
});
});
I should also note that on the same page a scroll to id# may be happening vs just simply taking you to the new url/page. Either case will happen though.
I think that you're making this too complicated. Use the same event handler for both a#triggerMobileMenu and ul#mobileMenu li a since you're having them do the same thing (toggle the visibility of the menu and another element).
$('a#triggerMobileMenu, ul#mobileMenu li a').on('click', function(evt){
evt.preventDefault();
$('#mobileMenu').toggleClass('menu_hide menu_show');
$('#mobileScreen').toggleClass('lockscreen_off lockscreen_on');
});
If you need to know which element was clicked in the event handler, evt.target is available:
if( $(evt.target).is($('a#triggerMobileMenu')) ) {
// do stuff
}
See http://jsfiddle.net/Mph6t/3/
I think it is working as intended. I had to fix some id names that may have been switched in the translation to jsfiddle. Here's a working one as far as I can tell. This leaves the somename2 div still showing. I assume that is going to be blank and just for locking the screen right?
I also changed the link to a new tab for testing purposes. FYI.
Relevant changes are:
$('#somename1 ul li a').on('click',function(){
$('#somename1').toggleClass('menu_show menu_hide')({ autoCloseOnClick: true });
$('#somename2').toggleClass('lockscreen_on lockscreen_off')({ autoCloseOnClick: true });
});

Responsive jQuery Menu

I have created a responsive menu that breaks at 480px and below. I have it to where the following reacts if:
The user clicks on a the "Menu" link.
The menu slideToggles out.
The sub-menus slideToggle out onClick as well.
But you cannot click on any of the pages.
Does this have something to do with the return false?
You may view the example here: http://www.stlredtails.com/construction/
You may need to resize the browser at or belw 480px to see the responsive navigation in action.
Here is the jQuery for the navigation:
jQuery(".navigation ul").hide();
jQuery("#navigation").click(
function() {
jQuery(this).siblings("ul").slideToggle(150, "swing");
return false;
}
);
jQuery(".navigation > ul > li").click(
function() {
jQuery(this).children("ul").slideToggle(150, "swing");
return false;
}
);
Thank you all!
The problem comes from the return false. When you're clicking the links, you're also clicking the ancestors li and ul. Before the link "activates" the functions bound to the ancestors click event execute. Since they return false the default browser behavior (navigating away) is prevented.
There are better solutions for this kind of menu behavior, but using what you already you have (and assuming you won't be changing your html) you can simply add the following to your javascript:
$('.navigation').on('click', 'a:only-child', function(e) {
e.stopPropagation();
});
This searches for all links in the navigation menu that are the only child of their parents (which in this case, happen to be the links you want to continue working as links) and prevents the ancestors click events from executing - the return false shouldn't happen anymore.

How can I prevent the page from scrolling down when using jQuery UI hide("slide")?

here is my code :
$('#pagelinks > a').click(function () {
$('html,body').animate({ scrollTop: 0 }, 200);
setTimeout(function() {$('#my_div').hide("slide",{direction:"right"},500);},250);
return false;
});
My problem is this : When I click on a link, it scrolls up at the top correctly but then automatically scrolls down ( seems to be around where I clicked ) and hide the content of my_div by sliding it and stay there.
I don't want it to scroll down to where I clicked but rather stay at the top. I tried everything I know but nothing works.
Note that if I put just hide() instead of hide("slide",{direction:"right"},500) there is no scroll down. Plus the scroll down occurs on Firefox and Opera but not in Chromium.
Thanks for your help,
Nolhian
I can think of two options:
1) Don't use a-links with anchors if you don't use the anchor part the way it was ment to.
2) stop the default event from occuring by passing on event to the click function and using preventDefault.
example:
.click(function(e){ e.preventDefault(); });

jquery menu, hover and display:none

I have this menu http://jsbin.com/useqa4/3
The hover I think works correct, but what I want is the normal: when the user's cursor isn't on the "Solution" item or on the submenu then I want the div #submenuSolutions to return in "display:none".
How can I achieve this?
If you read the jQuery api more carefuly you will see that the hover function can take handle two events http://api.jquery.com/hover/
$("document").ready(function() {
$("#menuSolutions a").hover(function () {
$("#menuSolutions").addClass("menuHover");
$("#submenuSolutions").show("3000");
},function() {
$("#menuSolutions").removeClass("menuHover");
$("#submenuSolutions").hide("3000")});
});​
This will work only if your menu is a suckerfish menu.
See Demo
Just added this code to hide it back when mouse leaves it:
$("#submenuSolutions").mouseleave(function(){
$(this).hide();
});
Since submenuSolutions is the id of your panel, you can use the mouseleave event which triggers when mouse leaves the area of element specified.

Categories