How do I stop jQuery hover flood? - javascript

I have a problem with my "menu" items that have an image, and by hovering them, jQuery brings out a text and a description for that image. However, I could not find any way to block or stop this effect from flooding.
See the example, from this try moving your cursor around the four boxes, fast, you will see that they kind of queue, and I don't really want that to happen.
This is my jQuery code:
$(document).ready(function() {
$("[rel='tooltip']").tooltip();
if($("#editor").val()!="1")
{
$('.thumbnail').hover(
function(){
$(this).find('.caption').fadeIn(450)
},
function(){
$(this).find('.caption').fadeOut(800)
}
});
});
Ways to stop this?

Try adding .stop() (jQuery API reference) to your selector. It will cancel an ongoing animation
$(this).find('.caption').stop().fadeIn(450)

Related

Animation not completing transition on SVG hover animation, when hover out occurs fast

I have made a very simple hover animation for a thumbnail by using a SVG icon. See here. The JS code I used is like so:
var elemRemoveAnim = null;
$('.vedio-thumb').hover(
function(){
$(this).find('.youtube-icon > .youtube-red')[0].classList.add('y-animated' , 'fadeInUp');
$(this).find('.youtube-icon > .youtube-white')[0].classList.add('y-animated' , 'fadeInUp');
},
function(){
removeVedioAnim($(this));
});
function removeVedioAnim(elem) {
elemRemoveAnim = elem;
setTimeout(function(){
elemRemoveAnim.find('.youtube-icon > .youtube-red')[0].classList.remove('y-animated' , 'fadeInUp');
elemRemoveAnim.find('.youtube-icon > .youtube-white')[0].classList.remove('y-animated' , 'fadeInUp');
}, 1000);
}
As you can see, I am trying to remove the animation class, after a delay of 1000ms, that's because iif you hover over and immediately hover out (you'll have to do it really fast), you'll notice that the animation gets stuck, i.e. the white arrow will still only be in half transition. Technically this is happening because the animation class has been removed too soon.
If I add the code in the hover out function, this aggravates the situation even more. Is there a more versatile solution to this problem?
One more problem with the with this solution is that once you hover and then if you hover out and you do it 2-3 times really fast, for the 2-3 time you've hovered the animation will take play only once, simply the setTimeout function will wait 1 second to remove the classes. I wonder if there is a more elegant way to do this.
SEE DEMO
Use "animationend" event to capture the end of fadingInUp motion on the arrow, that runs longer (the white one).
$utube_white.one("animationend webkitAnimationEnd oAnimationEnd",function() {
$utube_red.get(0).classList.remove('y-animated' , 'fadeInUp');
$utube_white.get(0).classList.remove('y-animated' , 'fadeInUp');
isLocked = false;
});
In your example there's no need for a mouseleave function in HOVER event, because you don't do anything particular on it - just remove animation classes without any other motion. This could be done in "Animationend" event in the first "HandlerIn" function.
Instead of a mouseleave function put the empty $.noop to prevent jQuery think that your hover function contains only one argument.
.hover(handlerIn, $.noop) and not .hover( handlerInOut ). You can change it, it's up to you, but in the last case the function will fire on both MouseOn and MouseOut.
Use a flag "isLocked" as well to prevent firing HandlerIn on quick hovers.

How to detect when all animations have stopped?

I'm using this code to stop simultaneous animations on 2 elements:
$('#container').find('*').stop(true, true);
The animation can be stopped by an end user hovering over a button, in which case the animation stops after completion (which is what I want). However, the button hover also initiates another function (removes and reloads the elements), and there's a conflict if that function runs before the animations are complete.
I was thinking that using 'after' or 'complete' with the above code might work, but I can't figure out what the syntax would be.
im not sure what you are trying to achieve, but in order to check whether or not there are running/pending animations on the object using jQuery, you can use .promise().done()
example, somehing of this sort:
var animations_running;
$('#container').promise().done(function() {
animations_running=false;
});
$('#container').on("mouseover",".SomethingInside",function(){
if(animations_running==false){
//...do animations...
animations_running=true;
}
});
you can also add a callback function to your jQuery animations as follows:
$('#container').on("mouseover",".SomethingInside",function(){
if(animations_running==false){
$(this).animate({
left:+=50
},500,function(){
//...this is the callback function...
});
animations_running=true;
}
});

Can anyone think of a better way of stopping a user from clicking on anything?

Currenlty when a page is posting back or something else is going on I display a big grey div over the top of the whole page so that the user can't click the same button multiple times. This works fine 99% of the time, the other 1% is on certain mobile devices where the user can scroll/zoom away from the div.
Instead of trying to perfect the CSS so that it works correctly (this will be an on going battle with new devices) I've decided to just stop the user from being able to click anything. Something like $('a').click(function(e){e.preventDefault();}); would stop people from clicking anchor tags and navigating to the link but it wouldn't stop an onclick event in the link from firing.
I want to try to avoid changing the page too radically (like removing every onclick attribute) since the page will eventually have to be changed back to its original state. What I would like to do is intercept clicks before the onclick event is executed but I don't think that this is possible. What I do instead is hide the clicked element on mouse down and show it on mouseup of the document, this stops the click event firing but doesn't look very nice. Can anyone think of a better solution? If not then will this work on every device/browser?
var catchClickHandler = function(){
var $this = $(this);
$this.attr('data-orig-display', $this.css('display'));
$this.css({display:'none'});
};
var resetClickedElems = function(){
$('[data-orig-display]').each(function(){
$(this).css({display:$(this).attr('data-orig-display')}).removeAttr('data-orig-display');
});
};
$('#btn').click(function(){
$('a,input').on('mousedown',catchClickHandler);
$(document).on('mouseup', resetClickedElems);
setTimeout(function(){
$('a,input').off('mousedown',catchClickHandler);
$(document).off('mouseup', resetClickedElems);
}, 5000);
});
JSFiddle: http://jsfiddle.net/d4wzK/2/
You could use the jQuery BlockUI Plugin
http://www.malsup.com/jquery/block/
You can do something like this to prevent all actions of the anchor tags:
jQuery('#btn').click(function(){
jQuery('a').each(function() {
jQuery(this).attr('stopClick', jQuery(this).attr('onclick'))
.removeAttr('onclick')
.click(function(e) {
e.preventDefault();
});
});
});
That renames the onclick to stopclick if you need to revert later and also stops the default behavior of following the href.
document.addListener('click',function(e){e.preventDefault()})
Modified-
Its your duty to remove the click event from the document after you are done accomplishing with your task.
Eg -
function prevent(e){
e.preventDefault()
}
//add
document.addListener('click',prevent)
//remove
document.removeListener('click',prevent)

Fade in/out buttons on mouseover of an image with jQuery. A few bugs to work out

So, I essentially have what I want already, very simple, but there are some bugs. I just want so when you hover over an image, two left/right buttons appear on the image that allow you to click through other images. Then when you leave the image area (excluding the left/right buttons), the buttons fade out again. Here's what I've got:
$(document).ready(function() {
$('#image-slider').mouseenter(function(){
$('.next').fadeIn('50');
$('.prev').fadeIn('50');
}).mouseout(function(){
$('.next').fadeOut('50');
$('.prev').fadeOut('50');
});
});
Bug #1: However, when you mouseover the image the buttons appear, and if you mouse over the buttons, they disappear. Naturally, of course they do, this is because I told them to fade away when I left the image area. First of all, I need them to stay visible even when you hover over them. So I need to somehow include the buttons as part of my image area in my javascript. That's the first problem/
Bug #2: This is a common problem I see in javascript. When you hover over the image, the buttons fade in, hover off, they fade out. Of course, there's a duration to this, and if you keep hovering in/out/in/out/in/out before the duration can finish, then when you let it fly, it will go on and off and on and off. How can I prevent this? So that is you hover out of the image area while the buttons are fading in, it just stops the animation sequence in its tracks so you don't get that continuous fading in/out.
Thanks in advance!
~ Jackson
ETA: the fix
I got it solved! A combination of your fix and #Pumou's.
I made another div just to wrap the two items and expanded it to cover the image, then I set the mouseover to be that div. Problem #1 solved.
I used puormo's .fadeTo() trick to solve problem #2.
Then, I used tweaks from everyone to shorten up the code so it was neat and tidy. Thanks to all!
I've decided on #jfriend00's solution. It's the shortest, great work!
Here's my final javascript:
$(document).ready(function() {
var b = $('.ps_next, .ps_prev');
$('#slider-wrapper').bind('mouseenter mouseleave', function(e) {
var check = ( e.type === 'mouseenter' ) ?
( b.stop(0,1).fadeIn(100) ) :
( b.stop(0,1).fadeOut(100) ) ;
});
});
Problem #2 can be fixed with .stop() which forces any previous animations to just to their conclusion before starting the next one.
$(document).ready(function() {
$('#imageContainer').hover(function() {
$('.ps_next').stop(true, true).fadeIn(400);
$('.ps_prev').stop(true, true).fadeIn(400);
}, function () {
$('.ps_next').stop(true, true).fadeOut(400);
$('.ps_prev').stop(true, true).fadeOut(400);
});
});
It may be better to use the .hover() jQuery function which handles both enter and leave rather than mouseenter() and mouseout().
You can see both an example of .stop() and .hover() on this jQuery doc page doing almost the exact same thing you are.
For problem #1, I think we'd need to see the structure of your HTML to know how best to advise on that as their are several choices depending upon how things are structured. You could also do the fadeOut on a delay that was cancelled if they hovered over the button so there was time to get the mouse to the buttons before they disappeared. Or, you could use .hover() on a container that contained both image and buttons.
You can see it working here: http://jsfiddle.net/jfriend00/Zk6rY/.
Shortened the code (as seen in the above jsFiddle) even more to this:
$(document).ready(function() {
$('#imageContainer').hover(function() {
$('.ps_button').stop(true, true).fadeIn(400);
}, function () {
$('.ps_button').stop(true, true).fadeOut(400);
});
});
$(document).ready(function() {
var $buttons = $('.next, .prev')
$('#image-slider').mouseenter(function(){
$buttons.stop().fadeTo('50','1');
$buttons.mouseenter(function() { $buttons.show(); });
}).mouseout(function(){
$buttons.stop().fadeTo('50','0');
});
});
I have also used stop();. I've also shortened it to use one selector to select both buttons (in this case, it was set to the variable $buttons).
I noticed that if your mouse entered the image div, and then left, and then entered again, the buttons were fading in to 50% opacity because of the stop();. I fixed this by using the fadeTo(); feature: the first one is the duration, which was set to 50 like yours, and the second one is the opacity to fade to (a number between 0 and 1).
I also solved the problem of keeping the buttons there when you hover over them. See this line:
$buttons.mouseenter(function() { $buttons.show(); });
This just uses show();, which gives the element display:block; on mouseover.
Example here: http://jsfiddle.net/purmou/MM4ba/1/
More about stop(); here: http://api.jquery.com/stop
More about fadeTo(); here: http://api.jquery.com/fadeto
EDIT: Updated the code so that it now uses jQuery's hover(); function. Shorter code is always better.
$(document).ready(function() {
var $buttons = $('.next, .prev')
$('#image-slider').hover(function(){
$buttons.stop().fadeTo('50','1');
$buttons.mouseenter(function() { $buttons.show(); });
},
function(){
$buttons.stop().fadeTo('50','0');
});
});
Example: http://jsfiddle.net/purmou/MM4ba/2/
More on hover(); here: http://api.jquery.com/hover
DEMO FIDDLE
var b = $('.btn');
$('#image-slider').bind('mouseenter mouseleave', function(e) {
var check = ( e.type === 'mouseenter' ) ?
( b.stop(false, true).fadeIn(300) ) :
( b.stop(false, true).fadeOut(300) ) ;
});
(with your markup and the use of ternary-operators)
You all might be looking for this awsmness.....
$(document).ready(function () {
$('#content').hover(function () {
$('.a').stop(true).fadeTo(500, 0.7);
$('.i').stop(true).fadeTo(500, 0.9);
}, function () {
$('.a').stop(true).fadeOut(500);
$('.i').stop(true).fadeTo(500, 1);
});
$('.a').hover(function () {
$('.i').stop(true).fadeTo(500, 0.95);
}, function () {
$('.a').stop(true).fadeTo(500, 0.7);
$('.i').stop(true).fadeTo(500, 0.9);
});
});
http://jsfiddle.net/Sourav242/p0z0oh82/

jQuery mouse out and not hiding a particular element

Let's say I've got two elements: an anchor which causes an occurence of a particular div.
In that single case I'm not able to wrap these two into a parent container, thus the whole markup has to be as following:
click me
<div class="info">info displayed on trigger hover</a>
The very basic question is: when the mouse leaves the trigger I want to hide the info window but only if the cursor is not over it.
How can I do that?
Help appreciated,
regards
If you can't change the markup at all, you can give it a nice fade effect, and take advantage of the fact a fade isn't instant, something like this would handle every .trigger/.info pair:
$(".trigger, .info").hover(function() {
$(this).next().andSelf().filter(".info").stop().animate({opacity: 1 });
}, function() {
$(this).next().andSelf().filter(".info").stop().animate({opacity: 0 });
});​​​​​​
You can try a demo here, you could break this info one function for .trigger and one for .info, I was just keeping it a bit more terse. The two function version would look like this:
$(".trigger, .info").hover(function() {
$(this).next().stop().animate({opacity: 1 });
}, function() {
$(this).next().stop().animate({opacity: 0 });
});
$(".info").hover(function() {
$(this).stop().animate({opacity: 1 });
}, function() {
$(this).stop().animate({opacity: 0 });
});
What this does is on mouseenter it fades in, on mouseleave it fades out (via .animate())...but moving the mouse from one to the other will let the fade happen for 1 frame before putting a .stop() to the fade-out and fade it back in. To the user, they don't see that anything happened, when the mouse leaves both, the fade is allowed to continue.
$('.trigger').live('mouseout',function (event) {
if (!$(event.relatedTarget).is('.info'))
$(this).next().hide();
});

Categories