Javascript set up Timeout Functions within a for loop - javascript

I have a loop that select and object and fades that object in, but when the loop is executed the object id stays at the last entry;
var ordered = Array(elements.length);
var x = 0;
$('#' + that.options.slide_name + '_' + that.nextslide).children().each(function () {
ordered[x] = $(this);
$(this).fadeOut(1);
$(this).attr('id','current_slide_content_' + x);
x++;
});
//fade each element
var time = that.options.fade_speed / ordered.length
var overlap = time / that.options.fade_step;
//time = time + overlap;
var wait = 0;
var num = 0;
var i = null;
var funcs = Array(ordered.length);
for(var a = 0; a < ordered.length; a++){
var w = wait;
var id = $('#current_slide_content_' + a);
window.setTimeout( function (event) {
id.fadeIn(time);
console.log(id);
},w);
//$('#current_slide_content_' + a).fadeIn(time); <-- on its own works, error is with the wait time
wait = time + wait;
}
I narrowed down the error to be in the final loop that actually adds the timeout function.
for(var a = 0; a < ordered.length; a++){
var w = wait;
var id = $('#current_slide_content_' + a);
window.setTimeout( function (event) {
id.fadeIn(time);
console.log(id);
},w);
//$('#current_slide_content_' + a).fadeIn(time); <-- on its own works, error is with the wait time
wait = time + wait;
}
When the id of the element is logged it should be:
foo_0
foo_1
foo_2
But instead it displays as:
foo_2
foo_2
foo_2
I have been on this for days and restarted several times, how do i format the id correctly for each of my Timeout functions?

should try :
window.setTimeout( (function(time_, id_){
return function (event) {
id_.fadeIn(time_);
console.log(id_);
}
})(time,id),w);
This is a closure to save the value of time and id in the scope of the function

Related

Website not responding - I think due to javascript code

I'm trying to make a game in javascript and display it on my website, but the website isn't responding anymore. The internet connection is just fine.
Here is the code where I think it went wrong:
$(function(){
init();
console.log("Main Init Called")
});
function InitFilesRanksBrd() {
var index = 0;
var file = FILES.FILE_A;
var rank = RANKS.RANK_1;
var sq = SQUARES.A1;
for(index = 0; index < BRD_SQ_NUM; ++index) {
FilesBrd[index] = SQUARES.OFFBOARD;
RanksBrd[index] = SQUARES.OFFBOARD;
}
for(rank = RANKS.RANK_1; rank <= RANKS.RANK_5; ++rank) {
for(file = FILES.FILE_1; rank <= FILES.FILE_E; ++file) {
sq = FR2SQ(file,rank);
FilesBrd[sq] = file;
RanksBrd[sq] = rank;
}
}
console.log("FilesBrd[0]:" + FilesBrd[0] + " RanksBrd[0]:" + RanksBrd[0]);
console.log("FilesBrd[SQUARES.A1]:" + FilesBrd[SQUARES.A1] + " RanksBrd[SQUARES.A1]:" + RanksBrd[SQUARES.A1]);
//console.log("FilesBrd[SQUARES.C5]:" + FilesBrd[SQUARES.C5] + " RanksBrd[SQUARES.C5]:" + RanksBrd[SQUARES.C5]);
console.log(FilesBrd);
console.log(RanksBrd);
}
function init(){
console.log("init() called");
InitFilesRanksBrd();
}
In the inner for, the variable that you are comparing is rank, not file. It should be:
for(file = FILES.FILE_1; file <= FILES.FILE_E; ++file)
Because the rank variable isn't incrementing until the loop content end, but the loop content doesn't end because of the inner loop.

Variable interval for javascript setInterval based on number of inner loop iterations

I'm trying to automate some actions on a webpage but running into some variable setInterval delay issues. The code pulls a list of elements based on classname and iterates over each one performing an action which dynamically creates new elements on the page, once the elements in collection have been processed the code should re-pull the class elements and iterate over the new collection over and over again.
I want the main delay to be dependant on the number of class elements it pulls from the page and iterates over each time. This code will be run on console in Chrome.
Here was my original working code without a variable delay:
var finishedActions = [];
var actionDelaySec = 5;
var totActionsInLoop;
setInterval( function() {
var pageElementsToActOn = document.getElementsByClassName('classname');
totActions = pageElementsToActOn.length;
for(var i =0; i < pageElementsToActOn.length; i++) {
(function(i){
window.setTimeout(function(){
var actionText = pageElementsToActOn[i].textContent;
if (finishedActions.indexOf(actionText) > -1) {
console.log("already finished action");
} else {
finishedActions.push(actionText);
console.log(actionText);
pageElementsToActOn[i].click();
}
}, i * actionDelaySec * 1000);
}(i));
}
console.log("New Loop");
}, 10000);
My first attempt to just change the 10000 figure to a variable caused a crash due to not being able to change setInterval delays while it's running.
After some research I thought I could recursively nest my function and call itself with a new delay each time.
This code also works but for some reason doesn't change the actual delay each time the main function is called but instead sets the delay to whatever is run on the first iteration:
var finishedActions = [];
var actionDelaySec = 160;
var totActionsInLoop = 5;
var totActionsMade = 0;
var myFunction = function(){
var pageElementsToActOn = document.getElementsByClassName('classname');
totActionsInLoop = pageElementsToActOn.length;
for(var i =0; i < pageElementsToActOn.length; i++) {
(function(i){
window.setTimeout(function(){
var actionText = pageElementsToActOn[i].textContent;
if (finishedActions.indexOf(actionText) > -1) {
console.log("already finished action (" + actionText + ").");
} else {
finishedActions.push(actionText);
console.log(actionText + " Connected At: " + timeStamp());
totActionsMade++;
pageElementsToActOn[i].click();
}
}, i * (actionDelaySec * 1000));
}(i));
}
console.log("New Loop -- Actions on page: " + totActionsInLoop + "-- Total actions finished: " + totActionsMade + " -- Started At: " + timeStamp());
setInterval(myFunction, (totActionsInLoop * (actionDelaySec * 1000)));
};
myFunction();
Can anyone explain to me why the delay isn't changing with each new function call and possibly help me fix the code to work as intended?
Thanks.

Why does the second loop execute before the first loop?

so this might be a repost, but I don't really know how to explain my second problem.
I have this code:
var paragraphsArray = new Array();
function setParagraphs(offSet)
{
offSet = offSet * 12;
for (var i = 1; i < 13; i++)
{
var parX = i + offSet;
var testASd = $.get('php/entryParagraphs.php', {idd: parX}).done(function(paragraph)
{
//clear paragraph1 div
document.getElementById("paragraph1").innerHTML = "";
//create p elements
var pElem = document.createElement("p");
pElem.setAttribute("id", "pEntry"+i);
document.getElementById("paragraph1").appendChild(pElem);
$("pEntry"+i).text(paragraph);
});
}
}
edited: I removed the second loop because it was unnecessary, for some reason the p element creation starts on i==13, which is the extra one that shouldn't even do.
for some reason the second loop executes first, so the paragraphArray is printed out as undefined. I managed to "fix" the order with the setTimeout() function, BUT I still get the undefined message, instead of the value. In the first loop the value is printed out fine, but if I try and put it in a $("p").text(paragraph); I also get undefined. So although I was right about the execution order, the problem is still there!
Because first is in ajax call, declare paragraphsArray in global space and use a callback function, try this:
*Updated
var paragraphsArray = [];
function setParagraphs(offSet) {
offSet = offSet * 12;
var request = 0;
for (var i = 1; i < 13; i++) {
var parX = i + offSet;
var testASd = $.get('php/entryParagraphs.php', {idd: parX}).done(function(paragraph) {
request++;
paragraphsArray[request] = paragraph;
console.log(paragraphsArray[request]);
if (request === 12) {
alert('first');
callback();
}
});
}
}
function callback() {
for (var i = 1; i < 13; i++) {
console.log(paragraphsArray[i]);
}
alert('second');
}
Run the second loop inside of the first loop.
function setParagraphs (offSet) {
//paragraphs
var testing = 0;
var paragraphsArray = new Array();
offSet = offSet * 12;
for (var i=1;i<13;i++) {
var parX = i + offSet;
var testASd = $.get('php/entryParagraphs.php', { idd: parX }).done(function(paragraph) {
paragraphsArray[i] = paragraph;
console.log(paragraphsArray[i]);
alert('first');
for (var i=1;i<13;i++) {
console.log(paragraphsArray[i]);
alert('second');
}
});
}
}
$.get is async function. 1st cycle will just send requests and wouldn't wait for response, so 2nd cycle will start right after first, without getting response of $.get function. Thats why console.log(paragraphsArray[i]); in 2nd cycle shows undefined.
You only can handle response in first cylce.
You can use $("p").text(paragraph); only like in this example:
var testASd = $.get('php/entryParagraphs.php', { idd: parX }).done(function(paragraph) {
paragraphsArray[i] = paragraph;
console.log(paragraphsArray[i]);
alert('first');
$("p").text(paragraph);
});
You can't use variables, which are assigned in function
function(paragraph) {
paragraphsArray[i] = paragraph;
console.log(paragraphsArray[i]);
alert('first');
$("p").text(paragraph);
}
outside of this function.
To achieve what you want you have to use another approach.
HTML will be:
<div id='paragraphs'>
</div>
JS code:
var testASd = $.get('php/entryParagraphs.php', { idd: parX }).done(function(paragraph) {
$("#results").append("<p>"+paragraph+"</p>")
});
You should use ~ this code. I just show you approach.

How can I use document.write in setTimout without clearing previous text

I want to create a delay between two document.writes. I used setTimeout to do so, but once it executes, it writes over the previous text. I would like to be able to display text, wait some delay, the display some other text below it without erasing any previous text. This code is appending to an otherwise empty HTML file. Also, I haven't had any success with using <br> for this.
var numOfDice = prompt("How many dice?");
var numOfSides = prompt("How many sides on these dice?");
var rollDice = function(numOfDice) {
var rollResults = [];
for (var i = 0; i < numOfDice; i++) {
rollResults[i] = Math.floor((Math.random() * numOfSides) + 1);
}
return rollResults;
}
var printResults = function() {
var i = 0;
while (i < rollResults.length - 1) {
document.write(rollResults[i] + ", ");
i++;
}
document.write(rollResults[i]);
}
alert("Roll the dice!");
var rollResults = rollDice(numOfDice);
printResults();
setTimeout(function() {document.write("These numbers...")}, 1000);
First, take a look at this answer why you shouldn't be using document.write.
Then, after you understand why using document.write is bad practice, you can replace it with element.appendChild.
For more information about the function, visit the Mozilla Development Network.
Code example:
var numOfDice = prompt("How many dice?");
var numOfSides = prompt("How many sides on these dice?");
var rollDice = function(numOfDice) {
var rollResults = [];
for (var i = 0; i < numOfDice; i++) {
rollResults[i] = Math.floor((Math.random() * numOfSides) + 1);
}
return rollResults;
}
var printResults = function() {
var i = 0;
while (i < rollResults.length - 1) {
var node = document.createElement("p");
node.innerHTML = rollResults[i] + ", ";
document.querySelector("body").appendChild(node);
i++;
}
var node = document.createElement("p");
node.innerHTML = rollResults[i];
document.querySelector("body").appendChild(node);
}
alert("Roll the dice!");
var rollResults = rollDice(numOfDice);
printResults();
setTimeout(function() {
var node = document.createElement("p");
node.innerHTML = "These numbers...";
document.querySelector("body").appendChild(node);
}, 1000);
Note that this code will show each rolled dice on a new line, since I'm creating a new p element for every roll. If you want them to appear on the same line, create one p element, and then in the while loop, append the rollresult to that p elements `innerHTML´
.

Javascript setInterval not making it into function

Ok Im trying to do a setInterval into a sub function and its not making it in there...my alert is not firing off because of this:
var doneVar= 0;
var groupsVar= 4;
var interval = setInterval(process_chunk, 1000);
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
process_chunk = function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
}
process_chunk has not been assigned a value yet, when you pass it into setInterval. Move the line:
var interval = setInterval(process_chunk, 1000);
To right before (and right after the anonymous function is assigned to process_chunk):
doneVar += 1;
Or if you are looking for hoisting the function then use a function declaration rather than an expression:
function process_chunk() {
Both versions will solve your problem.
You need to declare the function before using it.
Put
process_chunk = function() { ... });
Before
var interval = setInterval(process_chunk, 1000);
If you are only using the function from the interval use this (my preferred method, your way is not wrong)
var doneVar= 0;
var groupsVar= 4;
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
var interval = setInterval(function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
},1000);
that should do it, doing it this way and defining the function within the interval prevents many problems, like in this case you need to defined the function before you set it in an interval. Here is another version keeping your style.
var doneVar= 0;
var groupsVar= 4;
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
var process_chunk = function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
}
var interval = setInterval(process_chunk, 1000);
I guess one other thing I noticed just now, you use process_chuck and not var process_chuck witch can cause problems too. Fixed in second answer, not applicable in first.

Categories