Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Break out of Javascript recursive function on .click()

Hi,

I've been trying to improve my minimal Javascript / jQuery skills by making an image slider. I have got most of it working but hit a brick wall with one aspect.

The project is in a jsfiddle here: http://jsfiddle.net/SimonPratt/xj8ko9ne/

I want the slider to autoplay on load which I've done by using a recursive (I think?!!) function called autoPlay() (see line 50). However, I want the user to be able to interact with the slider using previous/next and pagination buttons. I have set these up and they work (see below autoPlay function).

The problem is that autoplay and the navigation don't work together. I can't get the autoPlay function to stop / break when user clicks one of the navigation buttons.

I have tried using the jQuery .stop(), attached to .click() events to try and get the .animate() used in the autoPlay function to stop the autoplay animation, but the problem is that this only stops that particular animation and the way I've set the autoplay up with a continually looping function means that it seems to never break out of the function.

Sorry if that's quite confusing - hopefully with the code it will make sense.

So, what I want is to find a way to break out of the autoPlay function when a user clicks one of the navigation buttons. I think maybe the way I've set up the autoPlay function as continually looping is the problem and if so, need to find a better solution to doing autoplay.

I'd also ideally like to make the autoplay resume following user interaction, after a small time interval, but that's a bonus!

Any help with this problem would be really really great!

Thanks!

p.s. I'm sure there is loads of bad code in this, if you spot any and can suggest better practices, please let me know.

2 Answers

Hugo Paz
Hugo Paz
15,622 Points

A way to do what you want is to use a global variable in there and check it on each iteration.

So at the start of your code you set a variable:

var stop = false;

Then you check if stop is false each time you animate:

function autoPlay() {
        var position = $("#inner-slider").position();

        if (position.left <= outerLimit) {
            $("#inner-slider")
                .delay(1000)
                .animate({
                left: '0px'
            }, function () {
                setFilled()
                if(stop === false){
                autoPlay()
                }
            });
        } else {
            $("#inner-slider")
                .delay(1000)
                .animate({
                left: '-=' + imageWidth
            }, function () {
                setFilled()
                if(stop === false){
                autoPlay()
                }
            });
        }    
    } 

When a user clicks on a navigation button, we set stop to true:

//PREVIOUS
    $("#nav-prev").click(function () {
        stop = true;
        var position = $("#inner-slider").position();

        if (position.left != 0) {
            $("#inner-slider").stop().animate({
                left: '+=' + imageWidth
            }, function () {
                setFilled()
            });
        }
    });

    //NEXT
    $("#nav-next").click(function () {
        stop = true;

        var position = $("#inner-slider").position();

        if (position.left <= outerLimit) {
            $("#inner-slider").stop().animate({
                left: '0px'
            }, function () {
                setFilled()
            });
        }
        else {
            $("#inner-slider").stop().animate({
                left: '-=' + imageWidth
            }, function () {
                setFilled()
            });
        }

    });

I see what you mean. I will try this now and get back to you - thanks very much!

Hugo, thanks very much for this - that has solved the problem.

I'm going to try and extend that solution to a stop and play button. My instinct is that the stop button will work like the current nav buttons and if I set the var stop to false on the play button and call autoPlay(), that should work..?

And following on from that, I should also be able to restart the autoPlay following user clicking next/prev/pagination buttons using the same process as described above for the play button?

Hope that makes sense!

Thanks again, really useful knowledge.

Jonathan Grieve
MOD
Jonathan Grieve
Treehouse Moderator 91,253 Points

Put a function call of autoplay(); in line 109 and 124 of your code.

I hope I understood your problem correctly? :-)

Thanks for your reply Jonathan. I did actually try this, but it doesn't break the autoPlay function loop and so effectively seems to result in autoPlay being called twice...