totalitarian
totalitarian

Reputation: 3666

Struggling with too much recursion

Here is my fiddle (Warning, it locks the page up for a few seconds due to recursion)

It basically changes the text in an element after a delay.

I have a couple of issues. One is too much recursion The second is more to do with design. How can I kick off the function without using the init() method. I'd rather just call rotate.(["example1", "example2", "example3"]); without having to use init();

<span id="rotator"></span>

var rotate = {
    quoteIndex: -1,
    duration: 500,
    delay: 3000,
    play: true,
    quotes: [],
    init: function (quotes) {
        this.quotes = quotes;
        this.showNextQuote();
    },
    showNextQuote: function () {
        ++this.quoteIndex;
        $("#rotator").html(this.quotes[this.quoteIndex])
            .fadeIn(this.duration)
            .delay(this.delay)
            .fadeOut(this.duration, this.showNextQuote);
        if (this.play) {
            this.showNextQuote();
        }
    },
    stop: function () {
        this.play = false;
    }



};

var test = rotate.init(["example1", "example2", "example3"]);

Upvotes: 0

Views: 130

Answers (3)

Rue
Rue

Reputation: 11

Just adding a slight alteration to the response from Aduch. I created an object called rotator inside the immediate function and return a function that executes init when called and returns the rotator object so that you can access the stop method.

var rotate = function(){ // <= wrap object rotator in an immediate function
    // re-wrapped your object 
    var rotator = {
        quoteIndex: -1,
        duration: 500,
        delay: 3000,
        play: true,
        quotes: [],
        init: function (quotes) {
            this.quotes = quotes;
            this.showNextQuote();
        },
        showNextQuote: function () {
            // this is the modulus part that I mentioned above
            this.quoteIndex = (this.quoteIndex + 1) % this.quotes.length;
            // this is our recursion condition which isn't truly recursion in fact
            if (this.play) {
                $("#rotator").html(this.quotes[this.quoteIndex])
                    .fadeIn(this.duration)
                    .delay(this.delay)
                // bind this to our callback
                .fadeOut(this.duration, this.showNextQuote.bind(this));
            }
        },
        stop: function () {
            this.play = false;
        }
    };

    // returning a function so that you execute like you requested.
    return function(ary){
        rotator.init(ary);
        return rotator; // <= returning the rotator so that you can call test.stop()
    };
}(); // <= executes the immediate function

var test = rotate(["example1", "example2", "example3"]);

Upvotes: 1

Oriol
Oriol

Reputation: 288220

Demo

var rotate = (function(){
    var quoteIndex= -1,
        duration= 500,
        delay= 3000,
        play= true,
        quotes= [],
        $rotator;
    function showNextQuote() {
        ++quoteIndex;
        quoteIndex %= quotes.length;
        $rotator
            .html(quotes[quoteIndex])
            .fadeIn(duration);
        if(play) $rotator
            .delay(delay)
            .fadeOut(duration, showNextQuote);
    }
    function init(q) {
        $rotator = $("#rotator");
        quotes = q;
        showNextQuote();
    }
    init.stop = function() {
        play = false;
    };
    return init;
})();
rotate(["example1", "example2", "example3"]);

Upvotes: 1

axelduch
axelduch

Reputation: 10849

I updated your fiddle here

The main problem of your recursion, is that there is no stop condition set. Also, you must be aware that when passing a callback to jQuery this gets passed as a dom element, so you also need to bind your rotate context to it so that you may refer this later without having an error thrown at you. Lastly, I assume that you wanted a rotator, so when incrementing this.quoteIndex you have to make sure it doesn't get out of this.quotes bounds so use modulus to ensure a consistent result: 1 -> 2 -> 3 -> 1 again etc.

var rotate = {
    quoteIndex: -1,
    duration: 500,
    delay: 3000,
    play: true,
    quotes: [],
    init: function (quotes) {
        this.quotes = quotes;
        this.showNextQuote();
    },
    showNextQuote: function () {
        // this is the modulus part that I mentioned above
        this.quoteIndex = (this.quoteIndex + 1) % this.quotes.length;
        // this is our recursion condition which isn't truly recursion in fact
        if (this.play) {
            $("#rotator").html(this.quotes[this.quoteIndex])
                .fadeIn(this.duration)
                .delay(this.delay)
            // bind this to our callback
            .fadeOut(this.duration, this.showNextQuote.bind(this));
        }
    },
    stop: function () {
        this.play = false;
    }



};

var test = rotate.init(["example1", "example2", "example3"]);

Upvotes: 1

Related Questions