Mentalhead
Mentalhead

Reputation: 1505

Animate() doesn't work with scrollTop properly

I'm trying to make a script that scrolls the page automatically to the specific element when I scroll my mouse, but for some reason my animation gets repeated and the scroll goes back and forth.

Edit: I would like to point out that this doesn't happen if the page scrolls to the last element on the page, but if it scrolls to the second element it will bounce instantly back to the top.

Here's my jQuery:

$(document).ready(function(){
comp = 0;
current_scroll_position = $(window).scrollTop();
console.log("CURRENT SCROLL POSITION = " +current_scroll_position);

second = $("#second").offset().top;




$(window).scroll(function(scroll_action){

    $('body').on({
        'mousewheel': function(e) {
                e.preventDefault();
                e.stopPropagation();
        }
    });

    if(comp==0){

        console.log("COMP =" +comp);
        comp++;

        new_scroll_position = $(window).scrollTop();

        console.log("YOU SCROLLED, NEW CURRENT POSITION IS :" +new_scroll_position);

        if (new_scroll_position > current_scroll_position){ //scroll going down



            console.log(new_scroll_position +" > "+ current_scroll_position +" GOING DOWN");




                $('body').animate({

                    scrollTop: second
                }, 500,
                function(){ //callback function for completed animation
                    completed_animation_scroll = true;
                    current_scroll_position = $(window).scrollTop();

                    console.log(" ANIMATING ");
                    console.log("CURRENT SCROLL POSITION = " +current_scroll_position);
                    console.log("NEW SCROLL POSITION = " +new_scroll_position);
                    console.log("ANIMATION COMPLETED = " +completed_animation_scroll);
                    console.log(" ******************* ************************ ******************");

                    $('body').unbind('mousewheel');
                    comp = 0;




                 });




        }
        else{

            console.log(new_scroll_position +" > "+ current_scroll_position +" GOING DOWN");

                $('body').animate({

                    scrollTop: 0
                }, 500,
                function(){ //callback function for completed animation
                    completed_animation_scroll = true;
                    current_scroll_position = $(window).scrollTop();

                    console.log(" ANIMATING ");
                    console.log("CURRENT SCROLL POSITION = " +current_scroll_position);
                    console.log("NEW SCROLL POSITION = " +new_scroll_position);
                    console.log("ANIMATION COMPLETED = " +completed_animation_scroll);
                    console.log(" ******************* ************************ ******************");

                    $('body').unbind('mousewheel');
                    comp = 0;




                 });

        }
    }
});
});

Try it: http://jsfiddle.net/81t6w6zv/2/

Upvotes: 1

Views: 567

Answers (1)

Regent
Regent

Reputation: 5178

The problem is in fact that when scrolling animation is done (including success callback), $(window).scroll handler is triggered and works again (because scrolling animation is actually scrolling and comp becomes equal to 0).

The easiest way to fix it is to wrap comp = 0 in scrolling animation callback function with setTimeout (I changed type of comp variable to bool):

setTimeout
(
    function()
    {
        comp = false;
    },
    100
);

There are also some "not good things" like binding mousewheel event handler but not unbinding it (if comp not equals to 0), so please take a look at updated fiddle to fix such problems in your code.

And full code:

$(document).ready(function()
{
    var comp = false;
    var current_scroll_position = $(window).scrollTop();
    var secondOffsetTop = $("#second").offset().top;  

    $(window).scroll(function()
    {
        if (comp)
        {
            return;
        }
        comp = true;

        $('body').on('mousewheel', function()
        {
            return false;
        });

        var scrollTo = 0;
        if ($(window).scrollTop() > current_scroll_position)
        {
            scrollTo = secondOffsetTop;
        }

        $('body').animate
        (
            {
                scrollTop: scrollTo
            },
            500,
            function()
            {
                current_scroll_position = $(window).scrollTop();
                $('body').off('mousewheel');
                setTimeout
                (
                    function()
                    {
                        comp = false;
                    },
                    100
                );
            }
        );
    });
});

Upvotes: 1

Related Questions