Reputation: 2737
I am in the process of building a revolving text generator. The generator combines sentences (text) from a number of arrays, 'cycles' through them visually and appends them. I thought it best to create a Fiddle with a basic version of the generator as I have constructed it now:
Explanation
The basic workings are as follows:
Array1
, Array2
and Array3
in the fiddle)combo0
and combo1
in the fiddle)Generate
is called, which visually cycles the sentences from an array of sentences (combo0[0]
in the fiddle)var times = 8
in the fiddle)Generate
again, this time with the second array (combo0[1]
in the fiddle)The reason for the callback is that I need to 'wait' for the cycling effect to complete, and then move on.
The issue
While this does exactly what I need (and besides the fact that I'm highly doubtful if this is the way to do it; I always feel a bit odd when writing a function that loops itself), I have the following problem:
In the combo
arrays, I define which of the 'sentence' arrays can be possible combinations. This works fine if there are two combinations, but with more than two, I have a problem:
Generate(combo0[0], i, function(i) { //generate from first array element of combo0, callback to generating from second array of combo0
Generate(combo0[1], i, function(i) {
$('div#status').html('Done!'); //show status
$('input#generate').removeAttr("disabled"); //enable button
});
})
I would have to recursively rewrite this to accommodate the possibility of a combo
array consisting of 3 or even 4 options. And probably this will break the script if a combo
array contains just 2 (or 1) arrays.
This is where I'm stuck. The main issue is that if I loop over the combo
array, e.g. with an .each();, the generate
function is called multiple times synchronously, so the whole 'cycling' effect is lost.
I have tried writing various loops, which take into account the array length of the given combo
array, but I have crashed more browsers today than ever before, and I can't work out what to do.
Upvotes: 8
Views: 500
Reputation: 2737
I have managed to fix it. Some time away from the screen is a good thing.
What I did is add an 'n' counter which increases if the multiple of the times
variable is reached, causing the function to continue iteration, but outputting (see third-to-last line) from the next array (lists[n]
). Finally, a check to see how much arrays are left will determine if we're done. If done, write the sentence one last time, run the optional callback and return false. This way, the function will accept the entire array, and not just the subarray (combo
as opposed to combo[0]
):
//Generate from array 'lists', simulating a 'slot machine
function Generate(lists, n, i, callbackFnk) {
if (!(i >= 0)) { i= 0; }
setTimeout((function(msg){
i++;
return function(){
if (i % times != 0){
//We haven't reached a multiple of the times variable yet, keep going.
Generate(lists, n, i, callbackFnk);
} else if (i % times === 0 && i != 0 && n < (lists.length-1)) {
//Multiple reached, increase n
n++;
Generate(lists, n, i, callbackFnk);
} else if (n == (lists.length-1)) {
//we are done as there are no more arrays to go over
showMessage(msg, i);
if (callbackFnk) callbackFnk.call(this, i);
return false;
}
showMessage(msg, i);
}
})(
//output using the given n value
lists[n][Math.floor(Math.random() * lists[n].length)]
), speed);
}
See the working fiddle here: http://jsfiddle.net/c_kick/kuNrA/1/
I hope this helps others!
Upvotes: 0
Reputation: 341
This should do the trick:
var Array1 = new Array("Sentence 1 - A ", "Sentence 1 - B ", "Sentence 1 - C ", "Sentence 1 - D ", "Sentence 1 - E ", "Sentence 1 - F ", "Sentence 1 - G ");
var Array2 = new Array("Sentence 2 - A", "Sentence 2 - B", "Sentence 2 - C", "Sentence 2 - D", "Sentence 2 - E", "Sentence 2 - F", "Sentence 2 - G");
var Array3 = new Array("Sentence 3 - A", "Sentence 3 - B", "Sentence 3 - C", "Sentence 3 - D", "Sentence 3 - E", "Sentence 3 - F", "Sentence 3 - G");
//define acceptable combinations of arrays
var combo0 = new Array(Array1, Array2);
var combo1 = new Array(Array1, Array2, Array3);
//define global vars
var speed = 140;
var content = '';
//write sentence to box. If counter is a multiple of the 'times' var: append instead of write
function showMessage(list, i, e) {
$('div#generated').html(content + list[i]);
if ((i + 1) % (e + 1) == 0) content += list[i];
}
//Generate from array 'list', simulating a 'slot machine
function Generate(lists, end, l, i, e) {
if (l == undefined) l = 0;
if (i == undefined) i = 0;
if (e == undefined) e = Math.floor(Math.random() * lists[l].length);
setTimeout(function() {
showMessage(lists[l], i, e);
if ((i + 1) % (e + 1) != 0)
Generate(lists, end, l, i+1, e);
else if (lists.length - 1 > l)
Generate(lists, end, l + 1);
else end();
}, speed);
}
$(document).ready(function() {
$('input#generate').click(function() {
$(this).attr("disabled", true); //disable button
content = ''; //reset content
$('div#status').html('Running..'); //show status
Generate(combo0, function() {
$('div#status').html('Done!'); //show status
$('input#generate').removeAttr("disabled"); //enable button});
});
});
});
Upvotes: 1