Reputation: 3666
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
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
Reputation: 288220
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
Reputation: 10849
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