How to tell .hover() to wait? - javascript

I have a drop down menu. Now when it's slided down to multiple levels, I'd like it to add wait time for like 2 secs, before it disappears, so the user can get back in, when he breaks the .hover() by mistake.
Is it possible?
my code for the slide:
$('.icon').hover(function() {
$('li.icon > ul').slideDown('fast');
}, function() {
$('li.icon > ul').slideUp('fast');
});

This will make the second function wait 2 seconds (2000 milliseconds) before executing:
$('.icon').hover(function() {
clearTimeout($(this).data('timeout'));
$('li.icon > ul').slideDown('fast');
}, function() {
var t = setTimeout(function() {
$('li.icon > ul').slideUp('fast');
}, 2000);
$(this).data('timeout', t);
});
It also clears the timeout when the user hovers back in to avoid crazy behavior.
This is not a very elegant way of doing this, however. You should probably check out the hoverIntent plugin, which is designed to solve this particular problem.

personally I like the "hoverIntent" plugin:
http://cherne.net/brian/resources/jquery.hoverIntent.html
from the page: hoverIntent is a plug-in that attempts to determine the user's intent... like a crystal ball, only with mouse movement! It works like (and was derived from) jQuery's built-in hover. However, instead of immediately calling the onMouseOver function, it waits until the user's mouse slows down enough before making the call.
Why? To delay or prevent the accidental firing of animations or ajax calls. Simple timeouts work for small areas, but if your target area is large it may execute regardless of intent.
var config = {
sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)
interval: 200, // number = milliseconds for onMouseOver polling interval
over: makeTall, // function = onMouseOver callback (REQUIRED)
timeout: 500, // number = milliseconds delay before onMouseOut
out: makeShort // function = onMouseOut callback (REQUIRED)
};
$("#demo3 li").hoverIntent( config )
Configuration Options
sensitivity:
If the mouse travels fewer than this number of pixels between polling intervals, then the "over" function will be called. With the minimum sensitivity threshold of 1, the mouse must not move between polling intervals. With higher sensitivity thresholds you are more likely to receive a false positive. Default sensitivity: 7
interval:
The number of milliseconds hoverIntent waits between reading/comparing mouse coordinates. When the user's mouse first enters the element its coordinates are recorded. The soonest the "over" function can be called is after a single polling interval. Setting the polling interval higher will increase the delay before the first possible "over" call, but also increases the time to the next point of comparison. Default interval: 100
over:
Required. The function you'd like to call onMouseOver. Your function receives the same "this" and "event" objects as it would from jQuery's hover method.
timeout:
A simple delay, in milliseconds, before the "out" function is called. If the user mouses back over the element before the timeout has expired the "out" function will not be called (nor will the "over" function be called). This is primarily to protect against sloppy/human mousing trajectories that temporarily (and unintentionally) take the user off of the target element... giving them time to return. Default timeout: 0
out:
Required. The function you'd like to call onMouseOut. Your function receives the same "this" and "event" objects as it would from jQuery's hover method. Note, hoverIntent will only call the "out" function if the "over" function has been called on that same run.

The general idea is to use setTimeout, like so:
$('.icon').hover(function() {
$('li.icon > ul').slideDown('fast');
}, function() {
setTimeout(function() {
$('li.icon > ul').slideUp('fast');
}, 2000);
});
But this may do counterintuitive things if the user mouses out and then mouses in again quickly—this doesn't account for clearing the timeout when the user hovers over it again. That would require additional state.

The following will stop the sliding from triggering by 2 seconds:
$('.icon').hover(function() {
$('li.icon > ul').delay(2000).slideDown('fast');
}, function() {
$('li.icon > ul').slideUp('fast');
});

$('.icon').on("mouseenter mouseleave","li.icon > ul",function(e){
var $this = $(this);
if (e.type === 'mouseenter') {
clearTimeout( $this.data('timeout') );
$this.slideDown('fast');
}else{ // is mouseleave:
$this.data( 'timeout', setTimeout(function(){
$this.slideUp('fast');
},2000) );
}
});

or you could simply use
transition:all 2s ease-in-out.
make sure that you add -webkit, -moz and -o for different browsers.

I think this is code your need:
jQuery( document ).ready( function($) {
var navTimers = [];
$('.icon').hover(function() {
var id = jQuery.data( this );
var $this = $( this );
navTimers[id] = setTimeout( function() {
$this.children( 'ul' ).slideDown('fast');
navTimers[id] = "";
}, 300 );
},
function () {
var id = jQuery.data( this );
if ( navTimers[id] != "" ) {
clearTimeout( navTimers[id] );
} else {
$( this ).children( "ul" ).slideUp('fast');
}
}
);
});

var timer;
var delay = 200;
$('#hoverelement').hover(function() {
on mouse hover, start a timeout
timer = setTimeout(function() {
Do your stuff here
}, delay);
}, function() {
Do mouse leaving function stuff here
clearTimeout(timer);
});
//edit: instert code

I would like to add to Paolo Bergantino that you can do this without the data attribut:
var timer;
$('.icon').hover(function() {
clearTimeout(timer);
$('li.icon > ul').slideDown('fast');
}, function() {
timer = setTimeout(function() {
$('li.icon > ul').slideUp('fast');
}, 2000);
});

Related

Display the image preview only when the mouse is hovered after 1 sec delay

I am showing the image preview when hovering over the image. Now I do keep the interval before displaying the preview image. say I set the delay as 1 sec, and within this if I dragged the mouse out of image, it still displays the preview since it is triggered during the mouse enter . How to fix this?
I need to display a preview only on hover after 1sec delay and not if the mouse is not with in the image?
On jQuery 1.9+, you could use delay/finish:
DEMO jsFiddle
$("#preview").hover(function(){
$("img").delay(1000).show(0); // passing 0 to show() will put animation in queue
}, function(){
$("img").finish().hide(); // finish() will clear any previous delay(), despite what argues the DOC
});
A basic skeleton using setTimeout() can be
var timer;
$('img').hover(function () {
timer = setTimeout(function () {
//do your stuff here
$('div').show();
timer = undefined;
}, 1000);
}, function () {
if (timer) {
clearTimeout(timer);
timer = undefined;
} else {
//hide the preview
$('div').hide();
}
})
Demo: Fiddle
Assign the setTimeout to a variable on mouseover event like this:
var timer = setTimeout(function() { doSomething(); }, 1000);
And then clear it on mouseout event so it doesn't show when you hover out of it:
clearTimeout(timer);

Delay Javascript hover action

I have an image on my site that has a jquery hover action assigned to it. But it's easy to accidentally mouse over that area, and if you do it more than once, the hover keeps appearing, disappearing, appearing, etc, until it's shown and disappeared once for every time you moused over it. Is there a way to make it so the action doesn't fire unless you hover for a few seconds? I don't want to just delay the action, because it would still happen for every mouseover, I want to see if there's a way the mouseover doesn't count unless you're on the image for a few seconds.
Script so far:
$("img.badge").hover(
function() {
$("h3.better").animate({"left": "125px"}, 1200);
},
function() {
$("h3.better").animate({"left": "-500px"}, 800);
});
You could use setTimeout to launch the action and bind a function calling clearTimeout on the mouseout event :
$('img.badge').hover(function(){
window.mytimeout = setTimeout(function(){
$("h3.better").animate({"left": "125px"}, 1200);
}, 2000);
}, function(){
clearTimeout(window.mytimeout);
});
Or you could use a plugin for that, like hoverintent.
Use a .stop() before animate, to cancel the previous animation. I believe this is what you are looking for, and will solve your current problem.
$("img.badge").hover(
function() {
$("h3.better").stop().animate({"left": "125px"}, 1200);
},
function() {
$("h3.better").stop().animate({"left": "-500px"}, 800);
});
You can use a timer to not fire the hover action until you've been hovered a certain amount of time like this and then, if the hover leaves before the timer fires, you clear the timer so nothing happens if you're only hovered a short period of time:
$("img.badge").hover(function() {
var timer = $(this).data("hover");
// if no timer set, set one otherwise if timer is already set, do nothing
if (!timer) {
// set timer that will fire the hover action after 2 seconds
timer = setTimeout(function() {
$("h3.better").stop(true).animate({"left": "125px"}, 1200);
$(this).data("hover", null);
}, 2000);
// save timer
$(this).data("hover", timer);
}
}, function() {
var timer = $(this).data("hover");
if (timer) {
clearTimeout(timer);
$(this).data("hover", null);
} else {
// probably would be better to make this an absolute position rather
// than a relative position
$("h3.better").stop(true).animate({"left": "-500px"}, 800);
}
});
Note: I also added .stop(true) to your animation so animations will never pile up.

Fading Latest News Ticker

I'm looking to get the most efficient way to produce a latest news ticker.
I have a ul which can hold any number of li's and all I need to to loop through them fading one in, holding it for 5 seconds and then fading it out, one li at a time. The list is displaying with an li height of 40px and the well it displays in is also 40px which with overflow: hidden which produces the desired effect. Also to be able to hold the li in place if the cursor hovers over it while its being displayed would be great to build it.
I know there is the jQuery ticker plugin that is widely used (ala the old BBC style) but I've tried to use it and it seems so bulky for the simplicity I need and it plays havoc with the styling I use.
I've been using this so far:
function tickOut(){
$('#ticker li:first').animate({'opacity':0}, 1000, function () {
$(this).appendTo($('#ticker')).css('opacity', 1); });
}
setInterval(function(){ tickOut () }, 5500);
But it doesn't actually fade in the next li so the effect is a bit messy.
If someone could suggest some alternations to help produce the effect I need that would be so useful.
Thanks
hide() and call fadein() the element after it becomes the top of the list.
function tickOut(){
$('#ticker li:first').animate({'opacity':0}, 1000, function () {
$(this).appendTo($('#ticker'))
$('#ticker li:first').hide()
$('#ticker li:first').fadeIn(1000)
$('#ticker li:not(:first)').css('opacity', '1')
});
}
setInterval(function(){ tickOut () }, 5500);
see:
http://codepen.io/anon/pen/lHdGb
I woudl do it like that:
function tickOut(){
$('#ticker li:first').animate({'opacity':0}, 1000, function () {
$(this).appendTo($('#ticker')).css('opacity', 1); });
}
var interval;
$(function() {
interval = setInterval(function(){ tickOut () }, 5500);
$('#ticker').hover(function() {
if(interval)
clearInterval(interval);
$('#ticker li:first').stop();
$('#ticker li:first').css('opacity', 1).stop();
}, function(){
interval = setInterval(function(){ tickOut () }, 5500);
});
});
See $('#ticker').hover which clears interval and stops animation and returns opacity to 1 when mouse got inside UL (may be changed to do that when only some special element inside LI is under mouse) and starts it again once it left that UL. Demo: http://jsfiddle.net/KFyzq/6/

finish animation before starting another

Problem: Whenever I click faster or slower I need last .click() call to finish before the next one starts. If you click the button faster , in the given example, you can see it's leaving divisions with 0 opacity.
What I want to achieve is stacking up till 3-4. I tried some queue code examples, couldn't make it work.
$("#addNew").click(function(){
var _this = $("#scrollable");
//Switch classes
_this.find("div.first").switchClass("first","second",500);
_this.find("div.second").switchClass("second","third",500);
_this.find("div.third").switchClass("third","fourth",500);
_this.find("div.fourth").switchClass("fourth","fifth",500);
// Insert first/new line
$("<div class='first'>Hello!</div>").css("opacity","0").hide().prependTo(_this).slideDown(function(){$(this).stop().animate({opacity:1},300)})
$("div.fifth").fadeOut().remove();
});
Here is example: http://jsfiddle.net/gtFyP/5/
Use setInterval
You could combine the below flag solution with setInterval, and thus be able to process clicks occurring during an animation.
Updated your JS Fiddle again with this alternate solution.
$(function() {
var clicking = false;
var clickCache = 0;
window.setInterval(function(){
if (!clicking && clickCache) {
processClick();
clickCache--;
}
}, 100);
var processClick = function() {
var _this = $("#scrollable");
//Switch classes
_this.find("div.first").switchClass("first", "second", 500);
_this.find("div.second").switchClass("second", "third", 500);
_this.find("div.third").switchClass("third", "fourth", 500);
_this.find("div.fourth").switchClass("fourth", "fifth", 500);
clicking = true;
// Insert first/new line
$("<div class='first'>Hello!</div>").css("opacity", "0").hide().prependTo(_this).slideDown(function() {
$(this).stop().animate({
opacity: 1
}, 300, function(){
clicking = false;
});
});
$("div.fifth").fadeOut().remove();
};
$("#addNew").click(function() {
clickCache++;
});
});
Use a Flag
You could use a flag - only start an animation if it's false. When you start animating, set it to true, when the animation is done, set it back to false.
I've modified your JS Fiddle.

Show image after there is hover on a link for 1500ms

I want to show an image after there is hover on link for atleast 1500ms or there is a click. How can I implement this minimal period hover condition while showing up the image ?
The image should remain visible until there is hover on the link or on itself. & should disappear as the mouse moves out of both. How can I implement this ? Thanks in advance!
http://jsfiddle.net/sSBxv/
$('a').click(function() {
alert(1); // alert on click
})
.hover(function() { // when mouse is entering
var $this = $(this);
// set timeout, save timeout id on element to clear later
$this.data('timeout', setTimeout(function() {
$this.click(); // click after 1500ms
}, 1500));
}, function() { // when mouse is leaving
clearTimeout($(this).data('timeout')); // stop the timeout
});
Try this
var hoverTimer;
$("linkSelector").hover(function() {
hoverTimer = setTimeout(function() {
$("imgSelector").show();
}, 1500);
}, function(){
clearTimeout(hoverTimer);
}).click(function(){
clearTimeout(hoverTimer);
$("imgSelector").show();
});
Something to the effect of...
$("#MyLinkSelectorId").hover(function() {
//Do anything you need to do here when it is clicked/hovered
setTimeout(function() {
//Do all of the other things here
}, 1500);
});
Switch out hover with click or bind multiple events to take care of both event types. To hide the images, you can either use a selector on the images with the .hide() method or you can set the opacity if the browser supports it.
$("a.class").hover( function (){ //First parameter is onmouseenter, show the image
$("img").show();
}, function (){ //second is onmouseleave, set a timeout that will hide the image
setTimeout( function(){
$("img").hide();
}, 1500);
}).click( function() { //on click, hide the image right away.
$("img").hide();
});
Since it looks like you haven't already tried something I'll give you the simplest way using jQuery (please note I haven't tested this):
$("#idOfDiv").mouseover(function() {
setTimeout("alertMsg()",1500);
});
function alertMsg()
{
alert('Ive been entered for 1500ms')
}
Also if you're serious about software development you should've been able to come up with this yourself.

Categories

Resources