javascript using settimeout() with a loop - javascript

ive got a table with 8x10 cells.. each sell got an input element with its own id (11, 12, ... , 21,22,23,...)
now i want to fill these inputs after and after (lets say 0.5 sec)
i just entered some values for testing
Betrag = new Array();
Betrag[0] = new Array();
Betrag[1] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","513.000,00");
Betrag[2] = new Array("asd","adsd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[3] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[4] = new Array("asd","uisgui","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[5] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[6] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[7] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
Betrag[8] = new Array("asd","asd","asd","asd","asd","asd","asd","asd","asd","asd","asd");
for(i=1; i<=8; i++){
for(k=1; k<=10; k++){
setTimeout(function schreiben(){document.getElementById(''+i+k+'').value= Betrag[i][k];}, 1000);
//document.getElementById(''+i+k+'').value= Betrag[i][k];
}
}
the compiler says "TypeError: Cannot read property '11' of undefined"
if i would not use the settimeout() function the whole loop is working fine, but with this function ive got this mistake..

You can try something like this:
var i = 1;
var k = 1;
var obj = setInterval( function () {
document.getElementById(i + '' + k).value= Betrag[i][k];
if(k <= 10)
k++;
else
{
k = 1;
if(i<=8)
i++;
else
clearInterval(obj);
}
}, 1000);
Here's a running example at http://jsfiddle.net/Ex98V/

This should work the way you wanted.
for(i=1; i<=8; i++){
for(k=1; k<=10; k++){
(function(i, k){
setTimeout(function schreiben(){document.getElementById(''+i+k+'').value= Betrag[i][k];}, 1000*k + 10000*i);
//document.getElementById(''+i+k+'').value= Betrag[i][k];
})(i, k);
}
}
To make things a bit clearer, consider refactoring like this :
for(i=1; i<=8; i++){
for(k=1; k<=10; k++){
setSchreibTimeout(i, k);
}
}
function setSchreibTimeout(i, k){
setTimeout(function schreiben(){document.getElementById(''+i+k+'').value= Betrag[i][k];}, 1000*k + 10000*i);
//document.getElementById(''+i+k+'').value= Betrag[i][k];
}

Bart Friederichs is right. Not sure why you want to do this that way, but you can declare a couple of vars inside the schreiben function and increment them inside the same screiben function.

k and i are read after the for loop ended (1 second to be precise). Their values are then 9 and 11, leading to an array overflow problem.
One option to fix it, is to create a function that does the work, and create a fixed string from the k and i variables to call it:
function schreiben(__i, __k) {
document.getElementById(''+__i+__k+'').value= Betrag[__i][__k];
}
Then call the setTimeout like this:
setTimeout("schreiben("+i+","+k+")", 1000);
Not the most elegant way, but it works.

Related

Java Script trouble with loops

I've just started learning Java Script and I was having trouble with loops. I'm trying to make a program that rolls a die 100 times and prints out the results. When I run this program, it prints out one roll 100 times, instead of printing out each roll once. Could anyone tell me what i'm doing wrong?
function start(){
var roll = Randomizer.nextInt(1 , 6);
for(var i = 0; i < 100; i++ ){
roll;
println("you rolled a " + roll);
}
}
Thanks for the help guys!
You'll need to run "roll" each time the loop is happening, so instead of just roll; you'll need to have roll = Randomizer.nextInt(1 , 6); inside the loop as well.
Or a better practice (since you're learning, it could help better your understanding), create a function called roll() and save what the function returns to a result variable, then print result out.
function roll () {
return Randomizer.nextInt(1 , 6);
}
function start () {
var result;
for (var i = 0; i < 100; i++ ) {
result = roll();
println('you rolled a ' + result);
}
}
Hope that helps you understand how to call a function to roll the dice again.
var dice = function() {
var roll = 1,
counter = 0,
LIMIT = 100,
DIE_TOP = 6,
result = [];
for (; counter < LIMIT; counter++, roll = Math.floor((Math.random() * DIE_TOP) + 1)) result.push(roll);
return result;
};
var test = dice();
document.write(test);

How do I return a value out of a javascript some loop?

I'm iterating over an array with a some loop to see if a time is in the past but I also want to return how many times the loop has run, how do I do that?
arr.some(function(a, i){
var date = Date.parse(a.start);
var now = new Date().getTime();
console.log(i);
return now-date < 0;
});
Edit: Solved this by just doing a for loop instead.
You can't return multiple objects in javascript. However, you can return a list of objects.
return [now-date < 0, i]
Count = 0;
arr.some(function(a, i){
Count = +Count + 1;
var date = Date.parse(a.start);
var now = new Date().getTime();
console.log(i);
return now-date < 0;
});
You could be able to make a counter, something like this.. basicly set count to 0 first and everytime the loop runs, count = old count + 1.

Strings in array not appearing as strings in HTML

First, my HTML:
<p id="p"></p>
<input id="input" />
<button onclick="fill()">Fill</button>
Then my Javascript:
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
for (var i = 0; i < y.length; i++) {
if (i == 0) {
setTimeout(function() {
document.getElementById('p').innerHTML = y[i];
},(i * 50));
}
setTimeout(function() {
document.getElementById('p').innerHTML += y[i];
},(i * 50));
}
}
What it does is take text from a textfield, cut each character including spaces into an array, then loop through the array, displaying each character at 50ms intervals. The effect is supposed to look like it is typing itself out.
The effect works fine, but the values of the array don't seem to be. If I were to type "abc123" then I would expect that to come right back out, but instead I get:
undefinedundefinedundefinedundefinedundefinedundefined
Using console.log(), when I check the array it looks fine, when I check the typeof of the individual array values I get string, but when I check the typeof for the array, I get object. Maybe this is what's wrecking it...
I have tried use toString() on the y[i] which just spits out "[object Window]", I have tried defining the array like this var y = new Array; and then doing the split(), nothing works. I am at a complete loss. Really would love some help here. Thanks!
I believe there must be closure problem. Try this js code. I wrapped everything inside loop in a IIFE function. I think it is well explained here Please explain the use of JavaScript closures in loops
<script>
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
for (var i = 0; i < y.length; i++) {
(function(i){
if (i == 0) {
setTimeout(function() {
document.getElementById('p').innerHTML = y[i];
},(i * 50));
}
setTimeout(function() {
document.getElementById('p').innerHTML += y[i];
},(i * 50));
})(i);
}
}
</script>
By calling setTimeout you're scheduling something to happen in the future. By the time the function you're delaying with setTimeout is executed, the loop has executed all the way through and i is now equal to y.length. So if you input test when the function executes it tries to add y[4] as a letter which is undefined. To fix it, you can do something like this:
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
console.log(y);
for (var i = 0; i < y.length; i++) {
timeOutAdd(y[i], i*50)
}
}
function timeOutAdd(c, delay){
setTimeout(function() {
document.getElementById('p').innerHTML += c;
}, delay);
}
<p id="p"></p>
<input id="input" />
<button onclick="fill()">Fill</button>
By adding the timeOutAdd function which is called immediately instead of delayed we can hang on to the values of the parameters until the setTimeout function runs.
Note: I also removed the second call to setTimeout, it wasn't necessary and caused a bug where the first character of the string was output twice.
This solves the closure problem, plus it simplifies the logic for outputting the data. No need for splitting the string into an array:
function fill() {
var x = document.getElementById('input').value,
p = document.getElementById('p');
for(var i = 0; i < x.length; i++) {
(function(i) {
setTimeout(
function() {
p.innerHTML= x.substr(0, i+1);
},
i*50
)
})(i);
}
}
<p id="p"></p>
<input id="input" value="abcde" />
<button onclick="fill()">Fill</button>

JS crashes sometimes with Timer scramble

My Javascript timer is for people with a rubiks cube with generates a scramble (nevermind all this, but just to tell you I'm generating after each solve a new scramble will be generated) and my scrambles do actually have a while (true) statement. So that does crash my script, but it 95/100 times stops just before the script crashes but I don't wanna have any times.
Let me explain a bit more detailed about the problem.
Problem: javascript crashes because my script takes too long to generate a scramble.
Below you have 3 functions I use.
This function generates a scramble with the Fisher-Yates shuffle.
Timer.prototype.generateScramble = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
This function validates the input e.g. I receive an array as the following:
Here I only have to check the first character. That's why I use the seconds [ ] notation. I don't want people get an F with an F2 e.g.
var scr = ["F","R","U","B","L","D","F2","R2","U2","B2","L2","D2","F'","R'","U'","B'","L'","D'"]
Timer.prototype.validateScramble2 = function(array) {
var last = array.length-1;
for (var i = 0; i < array.length-1; i++) {
if (array[i][0] == array[i+1][0]) {
return false;
}
}
for (var i = 0; i < array.length-2; i++) {
if (array[i][0] == array[i+2][0]) {
return false;
}
}
if (array[0][0] == [last][0]) {
return false;
}
return true;
};
The above functions are just waiting to be called. Well in the function below I use them.
Timer.prototype.updateScramble2 = function(scrambleArr, len, type) {
var self = this;
var scramble = '', j, updatedArr = [];
while (updatedArr.length < len) {
j = (Math.floor(Math.random() * scrambleArr.length));
updatedArr.push(scrambleArr[j]);
}
while (!self.validateScramble2(updatedArr)) {
updatedArr = self.generateScramble(updatedArr);
}
for (var i = 0; i < updatedArr.length; i++) {
scramble += updatedArr[i] + ' ';
}
scrambleDiv.innerHTML = scramble;
};
I assume you guys understand it but let me explain it briefly.
The first while-loop adds a random value from the given array(scrambleArr) into a new array called updatedArr.
The next while-loop calls the validateScramble2() function if there isn't in an array F next to an F2.
The for-loop adds them into a new variable added with a whitespace and then later we show the scramble in the div: scrambleDiv.innerHTML = scramble;
What do I need know after all this information?
Well I wanna know why my updateScramble2() functions lets my browser crash every time and what I do wrong and how I should do it.
I'm not entirely sure I understand the question, but from the way your code looks, I think you have an infinite loop going on. It appears as if validateScramble2 always returns false which causes your second loop in updateScramble2 to perpetually run.
I suggest you insert a breakpoint in your code and inspect the values. You could also insert debugger; statements in your code, works the same way. Open dev tools prior to doing these.
A suggestion is instead of using loops, use a timer. This breaks up your loop into asynchronous iterations rather than synchronous. This allows the browser breathing space for other operations. Here's an example of a forEachAsync:
function forEachAsync(array, callback){
var i = 0;
var timer = setInterval(function(){
callback.call(null, array[i]);
if(++i >= array.length) clearInterval(timer);
}, 0);
}
forEachAsync([1,2,4], function(item){
console.log(item);
});
You can take this further and use Promises instead of callbacks.

Can't manage to sleep inside a loop

I want to pause 1 second for every time it loops, it is usually easy to do similar pauses on other cases, but when working with loops, it seems it get harder:
for (var i=0 ; i < 10 ; i++) {
document.write (i + "<br>");
// I want to wait 1 second here
}
This is one example of my thousands failed attempts:
function writeMsg (index) {
document.write (index + "<br>");
}
for (var i=0 ; i < 10 ; i++) {
setTimeout (writeMsg(i), 1000);
}
Any ideas of how to get this to work?
This function works more like a normal for loop while it isn't
You need to take into account that a for gets 3 arguments inbetween semicolons.
Before starting (ie var i=0 you define a variable)
A condition before running the code again (ie i < 10 while i is under 10)
An action everytime it finishes the code again (i++ add one to i)
Code
(function() {
// Define a variable
var i = 0,
action = function() {
// Condition to run again
if (i < 10) {
document.write(i + "<br>");
// Add one to i
i++;
setTimeout(action, 1000);
}
};
setTimeout(action, 1000);
})();
Here is a jsfiddle for this code demonstrating its working:
http://jsfiddle.net/sg3s/n9BNQ/
You pass the return value of a function call to setTimeout instead of a function. Try the following code:
for (var i = 0; i < 10; i++) {
(function(i) {
setTimeout(function() {
writeMsg(i);
}, 1000*i);
})(i);
}
In case you wonder why the call is wrapped inside an anonymous function: Without that function each setTimeout callback would receive the same i so when the callbacks fire it would always be 10. The anonymous function creates a new i inside that is not connected to the loop variable.
Classic function-in-a-loop problem. One archetypal solution:
function createCallback(i) {
return function () {
writeMsg(i);
};
}
function writeMsg (index) {
document.write (index + "<br>");
}
for (var i=0 ; i < 10 ; i++) {
setTimeout (createCallback(i), 1000*i);
}
The 10 timeouts are all based on the time that setTimeout() is called. So, they are all triggered at the same time.
for (var i=0; i < 10; i++) {
(function(idx){
setTimeout(function(){
document.write(idx+"<br/>");
},1000*idx);
})(i);
};
try this it will definitely help who all are think how to make it work wait property inside For Loop...
try this code in this URL http://www.shopjustice.com/the-collections/C-10329.
var var2;
var tmp;
var evt;
var i=0;
var res = document.getElementsByClassName('mar-plp-filter-content nav nav--stacked')[0].children.length;
tmp = document.getElementsByClassName('mar-plp-filter-content nav nav--stacked')[0].children;
function myfunc()
{
if(i<res)
{
var2 = tmp[i].getElementsByTagName("span")[0].getElementsByClassName("inverted")[0];
// alert(var2.innerHTML);
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( 'mouseover', true, false );
var2.dispatchEvent(evObj);
var2.style.backgroundColor="GREEN";
i++;
setTimeout(myfunc,3000);
}
};
setTimeout(myfunc,3000);

Categories