I thought this would do it, but it only delays the animation.
$("#searchsubmit").hover(
function () { $("#quicksearchtip").delay(100).slideDown("slow"); },
function () { $("#quicksearchtip").delay(100).slideUp("slow"); });
I don't want the event to fire if the user happens to accidentally pass the cursor over the element for a few milliseconds.
I want it to only occur when they hover over the element. It's very annoying when the cursor touches the element even for a split second the animation fires even after the mouse has left the element.
You're looking for the hoverIntent plugin.
You may ad a .stop(true) before both of the .delay() to empty the animation queue, so on quick mouse out, the delayed action will be removed.
Related
scenario:
An animation can be called multiple times.
The animation is called by another event such as a click event.
The animation should not fire until it is sure that all other animation events involving this structure are complete.
example: http://jsfiddle.net/xo6ngbfz/
jQuery( document ).ready(function() {
console.log('run');
jQuery("#animation-object").bind("fire-hide", function () {
jQuery(this).toggle();
});
jQuery('#element').on('click', function () {
console.log('click');
jQuery('*').trigger("fire-hide");
});
});
Further understanding:
This is a very simple animation; but say for instance someone had a set of tiles. These tiles slide up and down on the screen after a link has been clicked on.
If we do not wait for all animations to be complete, the slide effect could stop half way through the animation and revert to whatever animation was last clicked.
I did an example with your code. I hope it could be useful for you!
The key was use a counter for total animations you have and pass a function as a callback for each one:
jQuery(this).toggle("slow", animationFinished);
You shoud do it for each jquery function you want to it notify you that it was finished.
(when function not accept callback, it is enough call animationFinished() after it, see line 14 of the example).
When the counter of animations has finished is equal to the total animation counter, then a function is called and the counter is reseted.
It is no the best way to do it, because each time you add an animation, you have to modify the totalAnimations counter, but at least is an option for now.
I have a Website with RoyalSlider and Mousewheel support. http://www.linus.de/mark/drei.php
Everything works fine, but when i use my macbook (touchpad) the thing is that i fire several mousewheel events at a time when scrolling. so basically i want the script to pause for the time (or a bit less) it takes for one slide to change...
What i would need is a javascript which freezes the mousewheel for x milliseconds each time it's been triggered (after sending 1 or -1 to the slider)...
A Timer with a call back and a flag could work. When you start to scroll you set the flag and not allow the scroll wheel to function, see This Answer on how to disable the scroll wheel. When the timer fires (1 second or so) you reset the flag to let the person scroll again. See This page for how to set up a timer with a call back
I can't give you a full code example since you didn't give any code to us but here's the solution.
When you scroll the mouse, a scroll animation begins. Create a variable somewhere outside the event handler, let's say
var animationInProgress = false;
and set it to true right before the animation begining. Then, this RoyalSlider plugin must have some kind of complete handler (I bet it has - it's paid though) - a parameter where you can put a function to be called when the animation is over. So, you put there a function similar to that:
function() {
animationInProgress = false;
}
The last thing is to check the value of the animationInProgress variable each time you want to run an animation
if (false === animationInProgress) {
//run the animation
}
I hope you get the idea.
I have say 5 list items with images inside placed 200px from eachother.
I am trying to animate these list items to slide horizontally left if one presses a link with the id = #next or if one swipes left. And vice versa for sliding the list items right.
Every click or swipe results in a slide animation of 200px on every list item.
I ran into a problem where spamming the #next or #prev button would cancel the current animation and start a new one. This results in list items not sliding 200px+200px+200... but something like this 200px+140px+120... This because like I said the animation is cut and therefore the sliding distance will be shorter.
Now I solved this for the clicking event by disabling the button before the animation starts and then re'enabling it on the end callbak function. But this problem is remaining for the swipe event.
How can I solve this problem for the swipe event?
If you have the code working for your click event handlers, then just .trigger() a click event on the proper element for each of the swiperight and swipeleft events:
$(document).delegate('#next', 'click.my-namespace', function () {
...
}).delegate('#prev', 'click.my-namespace', function () {
...
}).delegate('#my-page-id', 'swipeleft swiperight', function (event) {
if (event.type == 'swipeleft') {
$('#next').trigger('click.my-namespace');
} else {
$('#prev').trigger('click.my-namespace');
}
});
This way you have a single base of code that does the same thing, that gets called by multiple event handlers. I like to do this when I am adding touch events to a desktop design.
Notice I bound the event handlers with name-spaces so you don't accidentally trigger the wrong event handler.
You can also use .stop(true, true) but it may make your animations jittery when playing many in a row. The best solution when using .stop() is to always animate to an absolute value, never use +=200px, that way when you use .stop() the animation can be stopped and instantly restarted to the new absolute position: http://api.jquery.com/stop
One way you can do it is by setting a boolean variable that is global to the script with the default value of false. Then set the variable to true prior to animating and set it back to false once the animation is complete. Prior to setting off the animation, check the state of the variable, run the animation only if it's false. The code would look something like this:
var isAnimating = false;
function animate()
{
if(!isAnimating) {
//Animation code
isAnimating = false;
}
}
If the animation is asynchronous then you should set isAnimating = false in the completion function of the animation.
I have a table with some columns. In each of them is a picture where I have an onmouseover/onmouseout event on it, which shows a message in a div and hides the message.
My problem is, after a user moves quickly from left to right over a lot of images, all mouseover and mouseout events of the images are executed, which looks stupid...
Is it possible to rearrange the internal event stack to avoid this, such that the user executes only the current event (mostly the first one) and then the last one, if it is not the same type?
For example, if mouseover over first image is executed and the mouse moving position stops over an image three times next to the first one. I can avoid all other events firing, because the mouse stopped over an image and the mouseover is like the one where I stopped with the mouse.
How can I avoid this multiple event firing?
You need to check out the hoverIntent plugin, which addresses this problem.
We've had the exact same problem, What we've done is on the mouseover event is to set a variable _mouseOn to true (set to false on mouseout) then set a oneTime event over that fires in say 500 ms.. The one time event will check if the _mouseOn is true and display the image
function Hover() {
_mouseOn = true;
$(document).oneTime(500, "500ms", functionToCheckTheMouseOnAndDisplayTheImage);
};
//Global timeout handle for mouseover and mouseout
var timeoutHandle;
$(document).ready(function() {
BindMouseHover($(".helptext"));
});//closing ready
//bind mouseover and mouseout actions on all elements
function BindMouseHover(elements) {
$(elements).hover(
function() {
timeoutHandle = setTimeout('HandleMouseHover(true)', 1000);
},
function() {
HandleMouseHover(false);
}
);
}
//Handle Mouseover and mouseout events
function HandleMouseHover(bDelay) {
if (bDelay) {
$(".tooltip").show();
}
else {
$(".tooltip").hide();
clearTimeout(timeoutHandle);
}
}
Explanation:
On every mouseover schedule a call to DelayedTooltip(***true*)** after 1000ms and save the setTimeout handle to timeoutHandle
If mouseout happens within that 1000ms interval then simply call clearTimeout(***timeoutHandle*)** to cancel the setTimeout
This can be easily extended to apply to many heterogeneous elements and wire the customize tooltip text based on the element hovered.
Click here to know more about JavaScript Timing Events.
You can't, and shouldn't try to, avoid the events firing. What you should avoid is your code immediately responding to them by doing something that winds up looking stupid. For example, you can have your mouseovers register, with some controller object, which image the user is currently over, and set a short timeout to the function that triggers the actual behavior (removing a previous timeout if it's already running). The mouseout unregisters the image and removes the timeout. That way, when the behavior runs, you only operate on the image that the user moused over most recently.
I think it's better (from http://bavotasan.com/demos/fadehover/, THANKS)
<script>
$(document).ready(function(){
$(".a").hover(
function() {
$(this).stop().animate({"opacity": "0"}, "slow");
},
function() {
$(this).stop().animate({"opacity": "1"}, "slow");
});
});
</script>
I have a page that uses
$(id).show("highlight", {}, 2000);
to highlight an element when I start a ajax request, that might fail so that I want to use something like
$(id).show("highlight", {color: "#FF0000"}, 2000);
in the error handler. The problem is that if the first highlight haven't finished, the second is placed in a queue and wont run until the first is ready. Hence the question: Can I somehow stop the first effect?
I listed this as a comment for the accepted answer, but I thought it would be a good idea to post it as a standalone answer as it seems to be helping some people having problems with .stop()
FYI - I was looking for this answer as well (trying to stop a Pulsate Effect), but I did have a .stop() in my code.
After reviewing the docs, I needed .stop(true, true)
From the jQuery docs:
http://docs.jquery.com/Effects/stop
Stop the currently-running animation on the matched elements....
When .stop() is called on an element, the currently-running animation (if any) is immediately stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, the element will now still be displayed, but will be a fraction of its previous height. Callback functions are not called.
If more than one animation method is called on the same element, the later animations are placed in the effects queue for the element. These animations will not begin until the first one completes. When .stop() is called, the next animation in the queue begins immediately. If the clearQueue parameter is provided with a value of true, then the rest of the animations in the queue are removed and never run.
If the jumpToEnd argument is provided with a value of true, the current animation stops, but the element is immediately given its target values for each CSS property. In our above .slideUp() example, the element would be immediately hidden. The callback function is then immediately called, if provided...
.stop(true,true) will freeze the effect so if it's invisible at the time then it remains invisible. This could be a problem if you are using the pulsate effect.
$('#identifier').effect("pulsate", {times:5}, 1000);
To get around this I added
$('#identifier').stop(true, true).effect("pulsate", { times: 1 }, 1);
In my case, using below code does not work and keep your opacity value remain:
$('#identifier').stop(true, true).effect("pulsate", { times: 1 }, 1);
For me just remove opacity are working:
$('#identifier').stop(true, true).css('opacity','');