Swap mouseenter for hoverintent in code for mega menu lightbox - javascript

I have a mega menu that uses the hoverintent to delay the drop down, I have also set up a lightbox effect for the menu, however the code uses mouseenter and mouseleave, the problem is that whilst the drop down has a delay the lightbox effect doent, so as soon as the mouse passes over the lightbox is triggered. Is there any way that the code below can be changed to use hoverintent instead of mouseenter/mouseleave?
<script>
$(document).ready(function() {
if (document.documentElement.clientWidth > 801) {
$("#mega-menu").mouseenter(function() {
$("#mm-nav-overlay").toggle();
}).mouseleave(function () {
$("#mm-nav-overlay").hide();
});
}
});
</script>
Many Thanks

So I opted in the end to replace the code above with:
$(document).ready(function() {
if (document.documentElement.clientWidth > 801) {
$("#mega-menu").mouseenter(function() {
timer = setTimeout(function(){
$("#mm-nav-overlay").toggle();
},200/* <--- the delay */)
}).mouseleave(function () {
clearTimeout(timer);
$("#mm-nav-overlay").hide();
});
}
});

Related

DIV appear/disappear on mouse enter/leave

I'm trying to make a navigation using jQuery. I'm very new to jQuery so I'm getting a bit stuck here.
Basically what I'm trying to do is have testbutton2 appear and hide when I mouse over/off testbutton1. I was able to get this to work with mouseenter/leave.
The part I'm trying to add is to keep testbutton2 visible when I have the mouse over testbutton2 and to keep testbutton2 visible if I cursor back onto testbutton1 - so only fade in or out once.
You'll see from my code exactly what I encountered and probably have a chuckle.
CSS
#testbutton1 {
float:left;
height:100px;
width:100px;
background:#69C;
}
#testbutton2 {
float:left;
height:100px;
width:100px;
background:#0C6;
display:none;
}
HTML
<div id="testbutton1"></div>
<div id="testbutton2"></div>
jQuery
$("#testbutton1").on({
mouseenter: function() {
$("#testbutton2").fadeIn();
},
mouseleave: function() {
$("#testbutton2").fadeOut();
},
});
$("#testbutton2").on({
mouseenter: function() {
$("#testbutton2").fadeIn();
},
mouseleave: function() {
$("#testbutton2").fadeOut();
},
});
JSFiddle
DEMO
Or you can do it in pure css.
Wrap both buttons in a larger div and show the second button only while the mouse hovers over the larger div:
<div id="buttons">
<div id="testbutton1"></div>
<div id="testbutton2"></div>
</div>
#buttons:hover div {
display:block;
}
http://jsfiddle.net/r267b/1/
You can do something like
$("#testbutton1").on({
mouseenter: function () {
$("#testbutton2").fadeIn();
},
mouseleave: function () {
var $target = $("#testbutton2");
//delay the fade out to see whether the mouse is moved to the second button
var timer = setTimeout(function () {
$target.stop(true, true).fadeOut();
}, 200);
$target.data('hoverTimer', timer);
}
});
$("#testbutton2").on({
mouseenter: function () {
//if mouse is moved inside then clear the timer so that it will not get hidden
clearTimeout($(this).data('hoverTimer'));
$(this).stop(true, true).fadeIn();
},
mouseleave: function () {
$(this).stop(true, true).fadeOut();
}
});
Demo: Fiddle
This is solved with timers, as Arun P Johny said...
But as far as I saw, what you want to do is a menu.
Have you thought about using jQuery UI menu widget?
http://jqueryui.com/menu/
I suggest to use status variables that stores if you are hovering over button1 or over button2.
var isOver1 = false;
var isOver2 = false;
Then, add conditions to mouseleave and mouseenter in order to set hide or to alter the status variables, e.g.:
mouseleave: function() {
isOver1 = false;
window.setTimeout( function() {
if (!isOver2) {
isOver2 = false;
$("#testbutton2").fadeOut();
}
}, 50);
The timeout is necessary because if you leave testbutton1, you are not entering testbutton2 at exact the same time. So waiting a bit allows to fire the testbutton2 enter event.
Here is the full demo:
http://jsfiddle.net/KTULJ/2/
Leaving button1 to button2 keeps button2, leaving back to button1 still keeps button2, leaving any button towards the space around hides button2.
With this approach, you don't need to stop an animation as it doesn't start one if it is not necessary.

jQuery sliding menu error

I'm doing animated menu with jQuery (3 levels). I'm using efects slideDown and slideUp. Sometimes (but no always), when I open submenu of first main item, submenu of second main item won't work until I refresh the page. It works OK with efects fadeIn and fadeOut, but I want to use slide.
Here is my code: http://jsfiddle.net/mcCAx/
The problem was the styling on your <ul class="SubStage"> element was being overridden. So, fight fire with fire by re-overwriting the styling in a callback. Your side menu shows up every time. :)
$(document).ready(function()
{
$('li.MainStage').hover(
function()
{
$(this).find('ul.SubStage').slideDown('slow',function(){
$(this).parent().find('ul.SubStage').css({overflow:"visible"});
});
},
function()
{
$(this).find('ul.SubStage').stop().slideUp('slow');
});
$('li.SubStage').hover(
function()
{
$(this).find('ul.Sub2Stage').slideDown('slow');
},
function()
{
$(this).find('ul.Sub2Stage').stop().slideUp('slow');
});
});​
Check it out here.
This fixed it for me Here
$(document).ready(function()
{
$('li.MainStage').hover( function()
{
$(this).stop();
$(this).find('ul.SubStage').slideDown('slow');
}, function()
{
$(this).stop();
$(this).find('ul.SubStage').slideUp('slow');
});
$('li.SubStage').hover( function()
{
$(this).stop();
$(this).find('ul.Sub2Stage').slideDown('slow');
}, function()
{
$(this).stop();
$(this).find('ul.Sub2Stage').slideUp('slow');
});
});

How do I add a delay timer?

I have this code that makes menu items slide down and up. I want to add a timer so there is a delay in the slide down then back up.
$(function () {
$("#menu").find("li").each(function () {
if ($(this).find("ul").length > 0) {
$(this).mouseenter(function () {
$(this).find("ul").stop(true, true).slideDown();
});
$(this).mouseleave(function () {
$(this).find("ul").stop(true, true).slideUp();
});
}
});
});
It appears like you're writing javascript with jQuery
jQuery has a built in .delay function for animation queues.
In your example, delaying the slidedown animation by 300 ms would look like
$(this).find("ul").stop(true, true).delay(300).slideDown();
See jQuery's delay
A smart approach would be to add a hover intent to wait before triggering mouseleave:
jsBin demo
$("#menu").find("li:has(ul)").on('mouseenter mouseleave',function( e ){
var $UL = $(this).find('ul');
if(e.type==='mouseenter'){
clearTimeout( $(this).data('wait') );
$UL.stop(1,1).slideDown();
}else{
$(this).data('wait', setTimeout(function(){
$UL.stop().slideUp();
},180) );
}
});
instead of using if ($(this).find("ul").length > 0) { just use: ("li:has(ul)") to trigger your events only on li elements that has ul as children.
add an event callback e for the mouseenter mouseleave.
if the e event == mouseenter ..... else is mouseleave.
Than clear the data attribute called 'wait' and slideDown the children ul
Now, leaving the original li element to reach the 'distant' ul we have to cross over a white space (demo) that will usually trigger immediately the 'slideUp()', but we set a timeout counter inside that li's data attribute that will wait ~180ms before running.
Reaching the 'distant' ul element - beeing a children of the timeouted 'li' we clear the timeout (step 1) 'retaining' the mouseenter state.
use ~180ms or how much you think is needed to reach with the mouse the 'distant' UL element

Adding timeout to a dropdown menu not working

I am working on a website and want to modify the current code for a dropdown menu item. Here is the current code:
$(document).ready(function () {
$('#nav li').hover(
function () {
//show its submenu
$('ul', this).slideDown(300);
},
function () {
//hide its submenu
$('ul', this).slideUp(300);
}
);
});
I tried changing the code to add a timeout with the intention of setting the timeout when the user took their mouse off of the menu so the menu didn't toggle the slide up effect right away. The desired effect that I want is that if the user takes their mouse off the menu for like 200 ms but then moves it back to the menu it doesn't do anything. So the menu waits like 300-400 ms to toggle the slide up function. Here is the code that I wrote that didn't work. Part of it was because of the this in $('ul', this).slideUp(250); Anyways, here is the code that I tried to implement that didn't work:
$(document).ready(function () {
var timeoutID;
$('#nav li').hover(
function () {
//show its submenu
$('ul', this).slideDown(250);
window.clearTimeout(timeoutID);
timeoutID = window.setTimeout(SlideUp, 350);
},
);
function SlideUp() {
//hide its submenu
$('ul', this).slideUp(250);
}
});
What is the best way to have the program wait to toggle the slideup function? Any ideas are appreciated. Thanks.
This is what you wanted to do.
$(document).ready(function () {
var timeout;
$('#nav li').hover(function () {
//show its submenu
clearTimeout(timeout);
$('ul', this).slideDown(300);
}, function () {
//hide its submenu
var self = this;
timeout = setTimeout(function(){
$('ul', self).slideUp(300);
}, 300);
});
});​
jQuery.Deferred(), introduced in version 1.5, is a chainable utility
object that can register multiple callbacks into callback queues,
invoke callback queues, and relay the success or failure state of any
synchronous or asynchronous function.
Take a look at this.
Not an answer to your specific question, but I would use transition-delay if possible, fiddle.

Implementing Hover Intent

I just finished developing this Wordpress theme:
http://www.minnesdiner.com/
Everything is working well, but I'm not 100% happy with the navigation.
The sliding position indicator works smoothly, but I'd like to integrate the hover intent jQuery plugin to prevent the sliding indicator from sliding when the user unintentionally passes over the nav.
Any ideas as to how I could integrate this plugin? I'm currently firing a separate jQuery function for each nav item and passing coordinates to the sliding indicator based on which item is being hovered upon.
Here's my current jQuery code:
$(document).ready(function() {
var $currentpos = $("#menu-indicator").css("left");
$("#menu-indicator").data('storedpos', $currentpos);
$(".current-menu-item").mouseenter(function () {
$("#menu-indicator").stop().animate({left: $currentpos}, 150);
});
$(".menu-item-26").delay(500).mouseenter(function () {
$("#menu-indicator").stop().animate({left: "52px"}, 150);
});
$(".menu-item-121").mouseenter(function () {
$("#menu-indicator").stop().animate({left: "180px"}, 150);
});
$(".menu-item-29").mouseenter(function () {
$("#menu-indicator").stop().animate({left: "310px"}, 150);
});
$(".menu-item-55").mouseenter(function () {
$("#menu-indicator").stop().animate({left: "440px"}, 150);
});
$(".menu-item-27").mouseenter(function () {
$("#menu-indicator").stop().animate({left: "570px"}, 150);
});
$(".menu-item-164").mouseenter(function () {
$("#menu-indicator").stop().animate({left: "760px"}, 150);
});
$delayamt = 400;
$("#header-row2").click(function () {
$delayamt = 5000;
});
$("#header-row2").mouseleave(function () {
$("#menu-indicator").stop().delay($delayamt).animate({left: $currentpos}, 600);
});
});
As you can see, I need to bind mousover and mouseout to separate elements (list-item and containing div).
Thanks!
If all you want to do is avoid the user triggering the slide by mousing over the nav, I would just setTimeout in your hover function to call your sliding code after a certain amount of time has passed, and clear the timeout on the mouseout event. No extra plugin needed.
For example:
var hover_timer;
$('.menu-item').hover(
function() {
hover_timer = setTimeout(function() {
...
}, 500);
},
function() { clearTimeout(hover_timer); }
);
EDIT: by the by, you should be combining all those hover functions into one. You can do something like:
$('.menu-item-26').data('slider-pos', '52px');
$('.menu-item-121').data('slider-pos', '180px');
...
And then in the code to slide, call it back:
$this = $(this);
$('#menu-indicator').stop().animate({left: $this.data('slider-pos')}, 150);
And that's just a start - you can generalize it even more, I bet.

Categories

Resources