Search code examples
javascriptjqueryimagebxslider

bxSlider onAfterSlide callback


Good morning all :) I've got an issue here, which is pain in my neck for 2 days already. I'm using bxSlider for images to slide on a page and I'm calling my own function in onAfterSlide callback. Everything works fine except one thing. When I quickly switching between slides my function is being called 2-3 times(I have 3 images on page), which is not good as it returns unexpected results. I can not use newest version of bxSlider, because the markup has been changed. I think this happens, because the animation is still not finished when the onAfterSlide callback is called. This is how I call bxSlider:

$('#slider_bx').bxSlider({
    mode: 'fade',
    speed: 1000,
    pause: 9000,
    auto: true,
    autoControls: false,
    prevText: '',
    nextText: '',
    autoHover: true,
    captions: false,
    pager: true,
    onBeforeSlide: function () {
        if ($('.slide_in').length) {
            $('.slide_in').hide();
        }
    },
    onAfterSlide: function () {
        if ($('.slide_in').length && $('.slide_in').is(':hidden')) {
            doCrazyStuff();
        }
    }
});

And this is my function:

function doCrazyStuff() {
    var $this = $('.slide_in');
    if ($this.length > 0) {
        setTimeout(function () {
            $this.show();
            $this.rotate({
                duration: 2000,
                angle: 90,
                animateTo: -20
            });
        }, 3000);
    }
}

Any help appreciated. Thanks.

EDIT: I've tried to add .stop(), but didn't helped.

$this.show().stop();
$this.stop().show();
$this.stop().rotate({
    duration: 2000,
    angle: 90,
    animateTo: -20
});

$this.rotate({
    duration: 2000,
    angle: 90,
    animateTo: -20
}).stop(); // throws an error

Solution

  • You can cancel a timeout or make a check to see if it's running.
    If you want only the last timeout to run:

    var crazyTimeout;
    function doCrazyStuff() {
        var $this = $('.slide_in');
        if ($this.length > 0) {
            if (crazyTimeout != undefined) {
                clearTimeout(crazyTimeout); // Cancel previous timeout
            }
            crazyTimeout = setTimeout(function () {
                crazyTimeout = undefined;
                $this.show();
                $this.rotate({
                    duration: 2000,
                    angle: 90,
                    animateTo: -20
                });
            }, 3000);
        }
    }
    

    If you want only the first timeout to run:

    var crazyTimeout;
    function doCrazyStuff() {
        var $this = $('.slide_in');
        if ($this.length > 0) {
            if (crazyTimeout != undefined) {
                return; // A timeout is still running: don't create new one
            }
            crazyTimeout = setTimeout(function () {
                crazyTimeout = undefined;
                $this.show();
                $this.rotate({
                    duration: 2000,
                    angle: 90,
                    animateTo: -20
                });
            }, 3000);
        }
    }