Search code examples
jqueryjquery-pluginsjquery-animatemarquee

jQuery .hover() or .animate() causing bubbled animations in Marquee plugin


I'm playing with Giva Labs jQuery Marquee plugin. Example jsFiddle here.

There are two toggling lines of text in the example: First line and Second row. When you start to continuously move mouse cursor over and out the light-blue box, the text goes crazy: the lines start to move over each other like randomly, out of order. The craziness is strongest when you change speed of mouse movements from slow to fast in a loop.

I googled for "jquery animate stop" and found the .stop() and .clearQueue() effects. I tried attaching these to the marquee effect like this:

$("#marquee").marquee().stop();

and this:

$("#marquee").marquee().clearQueue();

and also like this:

$("#marquee").marquee()
    .hover(function() {
        $(this).clearQueue();
    });

I also tried with the plugin's build-in methods:

$("#marquee").marquee()
    .hover(function() {
        $(this).marquee("pause");
    })
    .mouseout(function() {
        $(this).marquee("resume");
    });

None of them worked.

How to get rid of this glitch?


Solution

  • UPDATE/SOLVED:

    Code: jsFiddle


    Solution summary:

    • added var timedout
    • set timedout inside scroll()
    • call clearTimeout(timedout) inside pause()

    The bug doesn't occur when you put a very low pauseSpeed (like 2 for example), which leads me to believe the bug it happens because of the interaction between pause() and resume()

    Concretely, this bit of code in pause():

    if( $marquee.data("marquee.showing") != true ){
        // we must dequeue() the animation to ensure that it does indeed stop animation
        $lis.filter("." + options.cssShowing).dequeue().stop();
    }
    

    this bit of code in resume():

    if ($marquee.data("marquee.showing") != true) scroll($lis.filter("." + options.cssShowing), 1);
    

    and this bit of code in scroll():

    setTimeout(function() {
        // if paused, stop processing (we need to check to see if the pause state has changed)
        if (paused == true) return false;
    
        // scroll the message down
        $li.animate({
            top: (options.yScroll == "top" ? "+" : "-") + $marquee.innerHeight() + "px"
        }, options.showSpeed, options.fxEasingScroll);
        // finish showing this message
        finish($li);
    }, delay);​
    

    As far as I can see the problem occurs because dequeue().stop() [which makes sense] is immediate and and scroll(...) has some code that happens with a delay (pauseSpeed).

    So what happens is the following:

    1. the animation is cancelled in pause()
    2. then resume() calls scroll() which in turns sets a timeout function to occur in 2000 ms
    3. actually it creates one for every time you hover over and move out
    4. which is what ends up messing everything up... don't ask me how, I'm pretty tired now

    To fix this I would suggest editing jquery.marquee.js code and actually calling clearTimeout() every time you stop the animation.