jQuery tooltip menu does not hide properly - javascript

I'm trying to do a homegrown jQuery tooltip menu, as I don't really need all of the functionality (and overhead) of a plugin.
My site features a typical top menu with some items that need dropdown/tooltip submenus. Markup is as follows:
<ul class="topmenu">
<li class="topmenu" id="flink">
Link Text For Submenu 1
<div id="fmenu" style="display: none;" class="submenu">
Submenu Link 1<br>
Submenu Link 2<br>
Submenu Link 3<br>
Submenu Link 4<br>
</div>
</li>
<li class="topmenu">About</li>
<li class="topmenu">Contact Us</li>
<li class="topmenu" id="ulink">
Link Text For Submenu 2
<div id="umenu" style="display: none;" class="submenu">
Submenu Link 1a<br>
Submenu Link 2a<br>
Submenu Link 3a<br>
Submenu Link 4a<br>
</div>
</li>
</ul>
And here is the jQuery I'm using:
$("#ulink").hover(function(){
$('#fmenu').slideUp(300);
$('#umenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
// $('#umenu').slideUp(300);
}, 800);
});
$("#umenu").hover(function(){
$('#fmenu').slideUp(300);
$('#umenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#umenu').slideUp(300);
}, 800);
});
$("#flink").hover(function(){
$('#umenu').slideUp(300);
$('#fmenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
// $('#fmenu').slideUp(300);
}, 800);
});
$("#fmenu").hover(function(){
$('#umenu').slideUp(300);
$('#fmenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#fmenu').slideUp(300);
}, 800);
});
This almost gives me what I need. If I mouse over either of the main links, the correct submenu slides open - and if the other submenu is currently open, it slides closed. So far, so good.
If I roll the mouse down to a submenu, it stays open for as long as the mouse is over any portion of it. Once the mouse moves out of the submenu, it slides closed after a short delay. Perfect.
However, if I simply move the mouse off of a main link WITHOUT either mousing over the other main link or the created submenu (say, I move the mouse to the side, then around the submenu), then the subenu will stay open until the end of time (or the browser window is refreshed, whichever comes first).
You note that I have commented out the slideUp() portion related to the parent link LI elements, as they would slide my submenu up once the mouse left the parent link, even if I had moused over the appropriate submenu. This behavior obviously made the menus unusable, whereas now they are simply slightly annoying.
What stupid obvious solution am I missing?
Thanks for your help.

After looking into all sorts of answers - stop(true, true), playing with classes, etc, I finally settled on a kludgy solution that does at least work.
I have set up a hidden field for each submenu. On page load, this the value is set to zero.
On mouseover of the submenu, the hidden field is set to a value of 1. On mouseout of the submenu, the hidden field's value is set to 0.
I have re-enabled the mouseout portions of the hover code on the links themselves, but added an if statement to them. If the hidden field is set to zero (i.e. the user is not currently moused over the submenu), then the submenu slides up. If the hidden field is currently set to one (the user is moused over the submenu), then nothing happens.
HTML:
<input type="hidden" id="fph" value="0">
<input type="hidden" id="uph" value="0">
<ul class="topmenu">
<li class="topmenu" id="flink">
Link Text For Submenu 1
<div id="fmenu" style="display: none;" class="submenu">
Submenu Link 1<br>
Submenu Link 2<br>
Submenu Link 3<br>
Submenu Link 4<br>
</div>
</li>
<li class="topmenu">About</li>
<li class="topmenu">Contact Us</li>
<li class="topmenu" id="ulink">
Link Text For Submenu 2
<div id="umenu" style="display: none;" class="submenu">
Submenu Link 1a<br>
Submenu Link 2a<br>
Submenu Link 3a<br>
Submenu Link 4a<br>
</div>
</li>
</ul>
And the updated jQuery:
$("#ulink").hover(function(){
$('#fmenu').slideUp(300);
$('#umenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
if($('#uph').val()==0){
$('#umenu').slideUp(300);
}
}, 800);
});
$("#umenu").hover(function(){
$('#uph').val(1);
$('#fmenu').slideUp(300);
$('#umenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#umenu').slideUp(300);
$('#uph').val(0);
}, 800);
});
$("#flink").hover(function(){
$('#umenu').slideUp(300);
$('#fmenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
if($('#fph').val()==0){
$('#fmenu').slideUp(300);
}
}, 800);
});
$("#fmenu").hover(function(){
$('#fph').val(1);
$('#umenu').slideUp(300);
$('#fmenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#fmenu').slideUp(300);
$('#fph').val(0);
}, 800);
});
Works like a charm.

Since the submenus are part of the li (you call it "link"), it makes sense to just have the slide up on li out. I'm not seeing any problem with the submenu sliding back up while you are moused over it. Care to elaborate on what browser and version you're seeing this?
$("#ulink").hover(function(){
$('#fmenu').slideUp(300);
$('#umenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#umenu').slideUp(300);
}, 800);
});
$("#flink").hover(function(){
$('#umenu').slideUp(300);
$('#fmenu').slideDown(300);
}, function(){
var link = $(this);
window.setTimeout(function(){
$('#fmenu').slideUp(300);
}, 800);
});
http://jsfiddle.net/vau9jtos/1/
EDIT:
http://jsfiddle.net/vau9jtos/2/
absolutely positioned the menu
static positioned submenu
submenu container with width of 0 to keep main navbar from expanding

Related

Stop slide in javascript

I used this parallax slider http://codepen.io/suez/pen/ByvKXE in my project.
Then I added a hover menu on the top of the page.
<ul class="menu">
<li class="list-menu fa-home"></li>
<li class="list-menu fa-suitcase"></li>
<li class="list-menu fa-flask"></li>
<li class="list-menu fa-user"></li>
<li class="list-menu fa-contact"></li>
</ul>
I would like to stop parallax slider when I put my mouse on the menu to click on the buttons.
How could I do that ?
Thanks for answer.
Have a look at http://codepen.io/anon/pen/YwGjNd. I have made following changes.
stopAutoSlide : variable to allow or block autoslide
mouseenter, mouseleave: events to change stopaAutoSlide state
if (!stopAutoSlide): to change current slide only if stopAutoSlide is false.
I hope this helps.
$(document).on("mouseenter", ".slider-pagi", function() {
stopAutoSlide = true;
});
$(document).on("mouseleave", ".slider-pagi", function() {
stopAutoSlide = false;
});

Javascript navigation, hover show, unhover hide with timeout, how?

I have navigation:
<li class="sliding-element zobrazSubMenu">
AntivĂ­rusy
<div class="sub-content">Bla blabla</div>
</li>
<li class="sliding-element zobrazSubMenu">
Virusy
<div class="sub-content">Some content</div>
</li>
I need to show sub-content div if I hover on the <li> element, but if I leave mouse, I need add some timeout (1sec) to hide sub-content.
And if I hover first <li>, and second <li>, and again rist <li>, before timeout end (1sec), do not hide the first sub-content.
Live example what I want: http://www.designchemical.com/lab/jquery-mega-drop-down-menu-plugin/advanced-styling/ the black navigation hover.
Move mouse to "Vehicles" and then move mouse to "About us" and fast again "Vehicles". This is effect what I dont know.
I need this apply to my custom VERTICAL menu.
Assuming you use jQuery you can do it like this:
HTML
<li class="sliding-element zobrazSubMenu" onmouseenter="showSubContent(this)" onmouseleave="hideSubContent(this)">
AntivĂ­rusy
<div class="sub-content">Bla blabla</div>
</li>
<li class="sliding-element zobrazSubMenu" onmouseenter="showSubContent(this)" onmouseleave="hideSubContent(this)">
Virusy
<div class="sub-content">Some content</div>
</li>
Javascript
function showSubContent(sender) {
if (sender.timerHandle === undefined) {
$(sender).find(".sub-content").show();
} else {
clearTimeout(sender.timerHandle);
sender.timerHandle = undefined;
}
}
function hideSubContent(sender) {
sender.timerHandle = setTimeout(function () {
$(sender).find(".sub-content").hide();
sender.timerHandle = undefined;
}, 1000);
}
Working demo

jquery show and hide mouseout() issue

I have set up a jquery hover show and hide function click here for site however it doesn't work the way i want it to. When you hover over the link "store" it reveals the hidden div, which is a submenu, once the mouse cursor has been moved from the link "store" the hidden div slides.
I want the submenu to stay activate unless one the links in the submenu have been click on or the mouse cursor is have been moved outside of the submenu area.
below is a snippet of my code...
$(document).ready(function(){
$(".slidingDiv").hide();
$(".show_hide").show();
$('.show_hide').hover(function(){
$(".slidingDiv").slideToggle();
});
$('.slidingDiv').mouseout(function(){
$(".slidingDiv").slideUp();
});
});
<div id="menu_store" class="slidingDiv transparent">
<div class="menu">
<h3>clothing</h3>
<ul class="navigation">
<li>sweats / knitwear</li>
<li>shirts</li>
<li>denim</li>
<li>outwear</li>
<li>footwear</li>
</ul>
</div>
<div class="menu">
<h3>lifestyle</h3>
<ul class="navigation">
<li>books</li>
<li>art</li>
<li>objects</li>
</ul>
<div id="menu">
<ul class="cl">
<li><a class="show_hide" href="#">store</a></li>
<li>daily</li>
<li>featured</li>
<li>contact</li>
</ul>
Does anyone have a solution for this...?
I figured it out. http://jsfiddle.net/vtFfv/
Relevant documentation: http://api.jquery.com/mouseleave/
$(document).ready(function () {
$(".slidingDiv").hide();
$(".show_hide").show();
$('.show_hide').mouseenter(function () {
$(".slidingDiv").slideDown();
$(".slidingDiv").mouseleave(function () {
$(".slidingDiv").slideUp();
});
$('.slidingDiv a').each(function () {
$(this).click(function () {
$(".slidingDiv").slideUp();
});
});
});
});
When you hide slidingDiv, mouse events aren't registered. So the solution is to attach a mouseleave event to it once you decide to show it (that is, on mouseenter). And then registering clicking on the links is easy.

jQuery: Delay showing of a dropdown menu content

I have built a dropdown menu that works fine. It goes like this:
Main menu items are in horizontal bar, then
When hover on any item, big dropdown box (with submenu links) is shown.
And here is my code for this:
HTML:
<!-- Based on Bootstrap -->
<div class="navbar navbar-inverse">
<div class="nav-collapse collapse">
<ul class="nav">
<li>First item
<div id="about-horizontal-submenu" class="horizontal-submenu">
<div class="submenu-container span3">
<ul>
<li>Links</li>
<li>Links</li>
</ul>
</div>
<!-- and 4x similar div (to have 12 cols) -->
</div>
</li>
<li>Dropdown
<div id="about-horizontal-submenu" class="horizontal-submenu">
<!-- 3x similar div (like above) and then: -->
<div class="submenu-container span3">
<ul>
<li>I want to go here</li>
<li>Links</li>
</ul>
</div>
</div>
</li>
<!-- And then goes another main menu item... -->
</ul>
</div>
</div>
</div>
JS:
jQuery(document).ready(function($) {
'use strict';
$('.navbar .nav > li').hover(function() {
var $el = $(this);
$el.addClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':hidden')) {
$submenu.slideDown(200);
}
}, function() {
var $el = $(this);
$el.removeClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':visible')) {
$submenu.hide();
}
});
});
Problem
I think I need to add a little delay before both - sliding Down submenu on very first hover and - changing submenu content (when switching/hovering to another menu item).
Why?
When you hover on "Dropdown" and want to choose "I want to move here":
You have to go down from "Dropdown" item and then to the right - which is ok (but not very usable).
Problem is, when you go like the image is showing (from the "Dropdown" straight to the "I want to move here" - you catch "Third item" on your way and immidiatelly see the content that belongs to "Third item". And that's not very good.
If you could show me how to delay/ignore hover on my menu items for very short time, I would be grateful. (I found great example behavior of menu on: http://FEI.com)
Ben Kamens from Khan Academy wrote an article regarding this exact problem, outlining how Amazon.com solved it. It is a great read!
http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown
He also put together a jQuery plugin to solve this problem with a working demo. You can find it on GitHub here:
https://github.com/kamens/jQuery-menu-aim
http://htmlpreview.github.io/?https://github.com/kamens/jQuery-menu-aim/blob/master/example/example.html
$(function($) {
var m;
var timer="";
var wait=200;
active=function(){
$('.navbar .nav > li').mouseover(function() {
m = $(this);
if(timer==""){
test();
unb();
timer = setTimeout(reb,wait);
}
});
}
test = function(){
$(".horizontal-submenu").stop().hide(300);
m.find(".horizontal-submenu").stop().show(300);
};
unb = function(){
$('.navbar .nav > li').unbind('mouseover');
};
reb = function(){
timer="";
active();
};
$(".horizontal-submenu").hide(300);
active();
});
Adjust 'wait' for your best timing; You can just copy and try on your script.
This might be what you are looking for:-
http://cherne.net/brian/resources/jquery.hoverIntent.html
From this you need 2 lines on your web page to activate the hover to working properly
1) Loading script hoverIntent
2) Change from hover to hoverIntent in your jQuery
please try setTimeout. It always does the trick.

jQuery .toggle woes

My 1st question on here so I'll try to be as concise as possible.
I have a series of nav elements, some of which have nav sub-elements. My basic structure is:
<nav role="navigation" class="primary-nav main-nav">
<ul>
<li>home</li>
<li class="about-item">about</li>
<li class="study-item">study</li>
<li class="apply-item">apply</li>
<li>people</li>
<li>shows</li>
<li>contact</li>
</ul>
</nav>
<!-- secondary navs -->
<!-- about -->
<nav role="navigation" class="sec-nav sec-nav-about">
<ul>
<li>history</li>
<li>facility</li>
<li>alumni</li>
<li>friends</li>
<li>patrons</li>
<li>singers</li>
</ul>
</nav>
<!-- study -->
<nav role="navigation" class="sec-nav sec-nav-study">
<ul>
<li>foundation</li>
<li class="study-undergrad-item">undergrad</li>
<li class="study-postgrad-item">postgrad</li>
<li>part time</li>
<li>exams</li>
<li>saturday school</li>
<li>sunday school</li>
<li>summer school</li>
</ul>
</nav>
<!-- apply -->
<nav role="navigation" class="sec-nav sec-nav-apply">
<ul>
<li>loans</li>
<li>auditions</li>
<li>fees</li>
<li>exams</li>
<li>saturday school</li>
<li>sunday school</li>
<li>summer school</li>
</ul>
</nav>
(I know these lists could - and should - be nested but this is code I've inherited rather than written myself and I don't want to screw with anything else that might be in the styles).
So - what I want is when the 3rd, 4th and 5th main-nav items are clicked, their corresponding submenu animates using margin-left.
I'm currently using jQuery .toggle() to try and achieve this effect. Here is my jQuery:
$(document).ready(function(){
$('.main-nav .about-item a').toggle (
function(){
$('.sec-nav-about').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-about').animate({marginLeft: "-250"}, 500);
});
$('.main-nav .study-item a').toggle (
function(){
$('.sec-nav-study').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-study').animate({marginLeft: "-250"}, 500);
});
$('.main-nav .apply-item a').toggle (
function(){
$('.sec-nav-apply').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-apply').animate({marginLeft: "-250"}, 500);
});
});
Up to this point, its fine. However, I cannot get beyond this point. I have no idea how to re-work the code to achieve the following:
1) When each main menu item is clicked, if it has a sub-menu and if its not already showing, then the sub-menu animates out (this is working fine).
2) If a sub-menu is already showing, then when its main menu item is clicked then the sub menu animates back in until its not showing (this is also working).
3) If a sub menu is showing and another sub menu item is clicked, the first sub-menu animates back in until its not showing and the new sub-menu animates out. This not working.
I have attempted to add/remove an .active class to each sub-menu like so (just one here for illustrative purposes but all three sub-menus have this applied to them):
$('.main-nav .about-item a').toggle (
function(){
$('.active').animate({marginLeft: "-250"}, 500).removeClass('active');
$('.sec-nav-about').animate({marginLeft: "480"}, 500).addClass('active');
},
function(){
$('.sec-nav-about').animate({marginLeft: "-250"}, 500).removeClass('active');
});
});
Then what happens is that, it seems to work and then after awhile, it stops removing/adding the .active class. I double checked in Chrome's Element Inspector and can see it (not) happening. I need to click the links twice to get the toggle() to work and drive the animation.
Any ideas/suggestions/solutions would be very gratefully appreciated.
(edited for spelling errors).
Thanks,
Will Moore's answer explains why your current method doesn't work. The following should fix your problem. Using the regex on the className property means that we can apply this to all items in your list without having to set each one up individually.
Also, note that we query the 'sub menus to hide' before adding the .active class to the currently selected sub-menu; this avoids hiding it as soon as we show it.
$('.main-nav li').click(function() {
var itemType = this.className.match(/(^| )([^ ]+)-item( |$)/);
if(itemType != null) {
itemType = itemType[2];
}
$secNavItem = $('.sec-nav-' + itemType);
$subMenusToHide = $('.active');
if(!$secNavItem.hasClass('active')) {
$secNavItem
.addClass('active')
.animate({marginLeft: "480"}, 500);
}
$subMenusToHide
.animate({marginLeft: "-250"}, 500)
.removeClass('active');
});
You can see it working in this fiddle: http://jsfiddle.net/ET475/23/
When you click 'Study' it SHOWS the study submenu.
Then you click the 'About' and it HIDES the study menu (shows the about menu).
Now you click 'Study' again. This is only the second click on the study button, so it's going to do the opposite of the last time you clicked it: ie it's going to HIDE the study submenu when you want it to show the study menu.
This works for me:
$('.main-nav .about-item a').click (function(){
var $submenu = $('.sec-nav-about');
// if the submenu you want isn't showing...
if (!$submenu.hasClass('active')) {
// if any other submenu is showing, hide it...
if ($('.active').length > 0){
$('.active').animate({marginLeft: "-250"}, 500, function(){
// ...show submenu AFTER previous submenu is hidden
$submenu.animate({marginLeft: "480"}, 500).addClass('active');
}).removeClass('active');
} else {
// no submenus showing: simply display
$submenu.animate({marginLeft: "480"}, 500).addClass('active');
}
}
});

Categories