jqueryjquery-animatemouseentermouseleaveanimated

Stop and rollback other jQuery animate objects when mouseenter a new one


I'm working on a jQuery slider with an active class .slider-active when mouseEnter a figure.

In this way, I want to animate my .slider-imgcontainer and my figcaption in a cool effet:

When the .slideractive change, the previous object have to reduce the width of .slider-imgcontainer to 250px and after the width and padding of the figcaption to 0. When I reduce the width of figcaption, the text was too high, so I just use .hide and .show to correct this.

Then the slider begin to work, but... when the mouse roll over mutliple figure, all of them is animated. I've tried to correct this but I cannot find any solutions (with .clearQueue() et .stop()).

Result: current slider

Main animation code:

$(document).ready(function(){


    var GLOBAL = {
        window:$(window),
        slider:$('.slider-work'),
        container:$('#container'),
        figure:$("figure")
    }

    /********* SLIDER MAIN *************/
    // INIT LARGEUR ---
    GLOBAL.slider.width($(".slider-work img").size() * 250 + 900);

    // save width of figcaption in attr to animate them after (no auto animate)
    GLOBAL.slider.find("figcaption").each(function(i) {
        var t = $(this);
        if(!t.parent().hasClass("slider-active"))
            t.hide();

        t.attr("largeur", t.width());


    });


    // hover
    GLOBAL.slider.children("figure").mouseenter( function () {


        var oldActive = $(".slider-active");
        var thiss = $(this);

        oldActive.removeClass("slider-active");
        thiss.addClass("slider-active");

        oldActive.find("figcaption").animate({
            width: 0,
            padding: 0
            }, 220, 'linear', function() {
                oldActive.find(".slider-imgcontainer").animate({
                    width : 250
                    }, 400, 'linear', function() {

                            // Animation de l'ancien active fini , alors : 

                            //$(".slider-imgcontainer").removeAttr("style");


                            thiss.removeAttr("style").children(".slider-imgcontainer").animate({
                                    width : 400
                                }, 400, 'linear', function(){
                                    var largeurFigcaption = thiss.find("figcaption").show().attr("largeur");

                                    thiss.find("figcaption").animate({
                                        width : largeurFigcaption,
                                        padding : " 0 20px 20px 20px"
                                        }, 220, 'linear', function(){


                                    });
                            });


                    });
        });
    });
    // END MouseEnter


//End ready
});

And my code for debugging the slider

 GLOBAL.slider.children("figure").mouseout( function () {
            var thiss = $(this);
            //$("#title span").append(" toto");


            var myChildrenBehave =  GLOBAL.slider.filter(function() {
                var filtered = $(this).children().is(":animated");
                return filtered;
            });

            myChildrenBehave.clearQueue().stop();



        });

I accept all idee :)


Solution

  • There are multiple ways to deal with this, but the one I prefer is after the animation of the initial mouseover completes you check to see if the mouse is still over that item. If it is not you close it back down.

    jQuery doesn't have a built in check for mouse still over an object that I am aware of, but I wrote one of my own for the situation that is pretty simple.

    var mouse = {
    mouseX: null,
    mouseY: null,
    mouseInWindow: true,
    init: function() {
        $(document).bind('mousemove', function(event) {
            mouse.mouseX = event.pageX;
            mouse.mouseY = event.pageY;
            mouse.mouseInWindow = true;
        });
        $(document).bind("mouseleave", function(event) {
            mouse.mouseInWindow = false;
        });
        $(document).bind("mouseenter", function(event) {
            mouse.mouseInWindow = true;
        });
    },
    isOver: function($element) {
        $elementPosition = $($element).offset();
        $elementWidth = $($element).width();
        $elementHeight = $($element).height();
        $returnValue = true;
        if (mouse.mouseX !== null) {
            if (mouse.mouseX < $elementPosition.left) { $returnValue = false; }
            if (mouse.mouseY < $elementPosition.top) { $returnValue = false; }
            if (mouse.mouseX > $elementPosition.left + $elementWidth) { $returnValue = false; }
            if (mouse.mouseY > $elementPosition.top + $elementHeight) { $returnValue = false; }
            if (!mouse.mouseInWindow) { $returnValue = false; }
        }
        return $returnValue;
    }
    

    }

    You will need to run mouse.init() before your other code, but then you can use mouse.isOver($(yourSlideActivator));