Javascript – jQuery: The ‘body’ element is activating the scroll event twice

javascriptjquery

I've implemented an animation for my photo blog. I still have big problem because the 'body' element is activating the animation twice.

I think the problem stems from the $('body').animate. Because I think that when the body is animating, the scroll event would be activated again and thus triggering the event twice.

The problem of my code is scrolling the page up. When I scroll the page upwards. The scrollAnimatePrev will trigger and then $('body') element will animate itself. After the animation the animating variable is set to false. But the $('body') element triggers the scroll event because I guess when I set the scrollTop the scroll event is triggered. So once again currentPos is set to the $(window).scrollTop() then currentPos > previousPos returns true and !animating returns true so it will trigger the scrollAnimate.

Now I want to fix this. How?

    $(function() {
        var record = 0;
        var imgHeight = $(".images").height();
        var offset = $(".images").eq(0).offset();
        var offsetHeight = offset.top;
        var previousPos = $(window).scrollTop();
        var animating = false;
        var state = 0;
        $(window).scroll(function() {
            var currentPos = $(window).scrollTop();
            console.log(currentPos);
            if(currentPos > previousPos && !animating) {
                record++;
                scrollAnimate(record, imgHeight, offsetHeight);
                animating = true;
            } else if (currentPos < previousPos && !animating) {
                record--
                scrollAnimatePrev(record, imgHeight, offsetHeight);
                animating = true;
            }
            previousPos = currentPos;
            console.log(previousPos)
        })


        function scrollAnimate(record, imgHeight, offsetHeight) {
            $('body').animate(
                {scrollTop: (parseInt(offsetHeight) * (record+1)) + (parseInt(imgHeight) * record)},
                1000,
                "easeInOutQuart"                    
            )
            .animate(
                {scrollTop: (parseInt(offsetHeight) * (record)) + (parseInt(imgHeight) * (record))},
                1000,
                "easeOutBounce",
                function() {
                    animating = false;
                }
            )
        }

        function scrollAnimatePrev(record, imgHeight, offsetHeight) {
            $('body').animate(
                {scrollTop: ((parseInt(imgHeight) * record) + (parseInt(offsetHeight) * record)) - offsetHeight},
                1000,
                "easeInOutQuart"
            )
            .animate(
                {scrollTop: ((parseInt(imgHeight) * record) + (parseInt(offsetHeight) * record))},
                1000,
                "easeOutBounce",
                function() {
                    animating = false;
                }
            )
        }
    })

Best Answer

I think it might be firing that callback twice. I had a similar problem recently.

I had something similiar to

$('#id, #id2').animate({width: '200px'}, 100, function() { doSomethingOnceOnly(); })

It was calling my doSomethingOnceOnly() twice, and I thought it must have been the dual selectors in the $ argument. I simply made it 2 different selectors and it worked fine. So like this

$('#id').animate({width: '200px'}, 100);
$('#id2').animate({width: '200px'}, 100, function() { doSomethingOnceOnly(); );