Search code examples
javascriptjqueryfadeinfadeout

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) ) ;
    });
});

Solution

  • 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);
        });
    });