Jquery - Delay mouseout event - javascript

Is there a way to make jQuery wait a certain about amount of time before mouseout event is fired?
It is firing too early at the moment and I'd prefer to wait 500ms before it evaluates the mouse out. An example of the code I'm using below.
$('.under-construction',this).bind({
mousemove: function(e) {
setToolTipPosition(this,e);
css({'cursor' : 'crosshair' });
},
mouseover: function() {
$c('show!');
showUnderConstruction();
},
mouseout: function() {
$c('hide!');
hideUnderConstruction();
},
click: function() {
return false;
}
});
Is there a jQuery way to do this or will I have to do it myself?

Split the logic inside the mouseout into another function. in the mouseout even call this function with a setTimeout("myMouseOut", 500). And you can combine the mouseover event with a clearTimeout() to reset the timer if the user moves into a new element.

You could always wrap your logic in a setTimeout() function.
mouseout: function() {
setTimeout(function(){
$c('hide!');
hideUnderConstruction();
}, 500);
}

You might check out the hoverIntent plugin lets you define some vars that help with mouseenter/out interactions

Related

Trigger function with keydown only once?

I have a series of messages on my page that are triggered by a keydown event once people start typing in a textarea. However, I can't figure out how to trigger it only once. Since people are typing longer responses, the function runs every time a key is pressed :/
$(function() {
$(document).on('keydown', function() {
$('.three').delay(1000).fadeOut(1500);
$('.four').delay(2500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.five').delay(7500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.6').delay(12500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.7').delay(17500).fadeIn(1500);
});
});
Instead of "on" use "one". This handles the event only once.
$(function() {
$(document).one('keydown', function() {
$('.three').delay(1000).fadeOut(1500);
$('.four').delay(2500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.five').delay(7500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.6').delay(12500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.7').delay(17500).fadeIn(1500);
});
});
Here's the reference: http://api.jquery.com/one/

How to stop scroll event listener after first trigger?

I want a scroll event listener to fire when the user scrolls the page for the first time, but then to stop firing after a certain amount of time and just allow the user to scroll normally.
Here's how I've currently got it working:
var scrollcount = 0
// Scroll event listener
window.addEventListener("scroll", function() {
setTimeout(function() {
scrollcount ++
if (scrollcount < 40) {
window.scrollTo(0, 0);
}
}, 1200);
});
The scrollcount variable increments along with scrolling, and 40 is about how much it takes for one scroll up on my laptop's trackpad. If the counter is under 40, the page scrolls back up to the top of the page once the user lets go of the scroll wheel, if it's over 40 it doesn't.
I realise that this is a really bad way to go about this, so I'm wondering if anyone has a more reliable way to do it. I tried to have a removeEventListener method turn off the event listener once setTimeout has finished its delay, but I couldn't get it to target the window. I think removeEventListener would work if the scroll event listener was assigned to a container div, and not the window, but when I tried that the scroll event listener wouldn't work in the first place.
I wanted to avoid jQuery or any other library if I could, but at this point I'll use anything that gets it to work reliably.
You need to give a name to your listener to remove it:
var scrollcount = 0
// Scroll event listener
function scrollListener() {
setTimeout(function() {
scrollcount ++
if (scrollcount < 40) {
window.scrollTo(0, 0);
window.removeEventListener("scroll", scrollListener);
}
}, 1200);
});
window.addEventListener("scroll", scrollListener);
This will jump to the top of the page, after 2 sec from when user start scrolling:
/* Create a one-time event */
function onetime(node, type, callback) {
node.addEventListener(type, function(e) {
e.target.removeEventListener(e.type, arguments.callee);
return callback(e);
});
}
onetime(document, 'scroll', function(e) {
setTimeout(function(){ window.scrollTo(0, 0); }, 2000);
});
see it live here
If you are using jQuery, you can use jQuery's one function, and simplify the code to:
$(document).one('scroll', function(e) {
setTimeout(function(){ window.scrollTo(0, 0); }, 2000);
});
If you want to jump to the top of the page after some animations are finished instead of waiting predefined amount of time, then you should call window.scrollTo(0, 0); after you are done animating. If you are animating using jQuery's effect functions, then you can pass callback function as last argument, and it will be called once the animation is complete. For example you can do something like this:
$(document).one('scroll', function(e) {
$('pre').animate(
{fontSize: "106px"},
2000,
function(){ window.scrollTo(0, 0); }
);
});
see it live here

How can I tell if an event is being fired by the same event that created it?

Let's say I have the following events:
$(button).on('mouseup', function (event1) {
$(something).show();
$(document).on('mouseup', function (event2) {
$(something).hide();
});
});
So, it shows "something" when button is clicked and hides it when the document is clicked. How can I make sure the second evnet doesn't trigger in the same event that created it? right now the something will show and hide instantly (at least on firefox).
I need to do this without any globals of any kind, preferably.
How about this:
$(button).on('mouseup', function (event1) {
$(something).show();
event1.stopPropagation();
$(document).one('mouseup', function (event2) {
$(something).hide();
});
});
stopPropagation() will stop the event from going past the button (to the document).
one() will only run the event once and then go away... can be recreated again with another click on the button.
JSFiddle
Here's another solution that doesn't rely on timestamps:
$("button").on('mouseup', function (event1) {
$("#something").show();
setTimeout(function () {
$(document).one('mouseup', function (event2) {
$("#something").hide();
});
}, 0);
});
demo
Using setTimeout with a delay of 0 will make it execute the code as soon as it's finished with this event. Also note I'm using one rather than on because you only need this event handler one time and without it you will end up attaching unlimited numbers of event handlers, every single one of which will need processing when a mouseup fires anywhere on your page.
A less silly solution might look like this:
$("button").on('mouseup', function (event1) {
$("#something").show();
});
$(document).on('mouseup', function (event2) {
if(event2.target != $("button")[0]) {
$("#something").hide();
}
});
demo
Why don't you isolate the event like so:
$(button).on('mouseup', function (event1) {
$(something).show();
});
$(document).on('mouseup', function (event2) {
$(something).hide();
});
I ended up using the event.timeStamp property to check if the two events are distinct. Also added an unbind and a namespace to the document event to prevent event stacking.
$(button).on('mouseup', function (event1) {
$(something).show();
$(document).on('mouseup.'+someIdentifier, function (event2) {
if(event1.timeStamp != event2.timeStamp) {
$(something).hide();
$(document).unbind('mouseup.'+someIdentifier);
}
});
});

How do I add a delay to the mouseover function?

I'm making a calendar app using the jQuery plugin FullCalendar and I made a tab to the left of the calendar with the weeks from 1-6 on it. When the user drags their mouse over one of the weeks the calendar switches to the view of the respective view. This works but it can be annoying for the user if they do it accidentally. So, I want to add a delay to the function so that it will only happen if the user has their mouse on it for a few hundred milliseconds so it will happen less without the user wanting it to happen.
$('#week3').mouseover(function() {
$('#week3').css('color', 'white');
$('#week3').css('background-color', '#6B8BA9');
$('#week3').week3();
I want to add a short delay before $('#week3').css('color', 'white');
If I am understanding you correctly, then you will need a more complete solution like below
var mouse_monitor
$('#week3').mouseover(function() {
mouse_monitor = setTimeout(function(){
$('#week3').css('color', 'white');
$('#week3').css('background-color', '#6B8BA9');
$('#week3').week3();
}, 1500)
});
$('#week3').mouseout(function() { clearTimeout( mouse_monitor ); }
The var mouse_monitor is a global reference to your timeout function. The mouseout function is missing in other post, which assures that your mouseover function will not fire if the user moves the mouse off the hover target before the value of the setTimeout expires. Other examples will still invoke your mouseover function everytime, but with just an added delay, so they won't work for what I think you are trying to achieve.
Use a timeout :
$('#week3').on({
mouseenter: function() {
var that = this;
$(that).data('timer',
setTimeout(function() {
$(that).css('color', 'white');
},1000)
).css('background-color', '#6B8BA9').week3();
},
mouseleave: function() {
clearTimeout( $(this).data('timer') );
}
});
you are looking for setTimeout

jQuery: Prevent stacking animations

I know there are several other posts with solutions to this, but my current problem is a little different.
I have two events on an element - mouseenter and mouseleave. The first changed the color of my element to light and the other back to dark, this makes a flashing effect.
The problem is when I go in and out a couple of times the events stack and it flashes many times even if no new events are triggered. I would like to prevent that, but .stop() does not help.
Here's the catch: I would like to trigger 1 flash no matter what, but not more than 1. So when someone moves in / out - the event mouseenter will be fired, after it mouseleave and after it nothing.. until another in / out is triggered.
I guess this could be made by locking (not listening for) new events when in / out is triggered up until the effect has finished, but I don't know how to do without unbinding and binding it again. Isn't there any lockEvent() or something?
Have you already used .stop(true) or .stop(true, true)?
there is pseudo-class in jQuery ":animated"
you can use it on first mouseenter even like:
if ( $(this).is(':animated')) {
return false;
}
to prevent additional animation
You can try just setting a bool var and firing only if false...
var anim = {
animating: false,
over: function(){
if(!anim.animating)
{
anim.animating = true;
// do you animation here
// and set your animating bool to false before calling outro...
$('#elem').animate({/*some css change*/ }, 1000, function(){
anim.animating = false;
anim.out();
});
}
},
out: function(){
if(!anim.animating)
{
anim.animating = true;
//do your outro animation here
$('#elem').animate({/*some css change*/ }, 1000, function(){
anim.animating = false;
});
}
}
};
then have your listener call anim.over and anim.out...
$('#elem').on('mouseenter', function(){
anim.over();
}).on('mouseleave', function(){
anim.out();
});
This way you will call animation on enter and it will automatically fire off the outro animation when the intro completes.

Categories

Resources