Javascript only goes through the first iteration of a for statement - javascript

I've been trying to figure out why this 'for' only loops once. Having spent about 6 hours re-writing conditions, I was wondering if you could give me a hand with spotting the problem.
Thanks in advance for any piece of advise and your time !
var k;
var i = 1;
function stergeLinie(k) {
var tabel = document.getElementById('produse');
var rowCount = tabel.rows.length;
var row = document.getElementById("tr" + k);
row.parentNode.removeChild(row);
var t = rowCount;
for (y = k; y < t; y++) {
document.getElementById("nrcrtid" + (y + 1)).value = y;
document.getElementById("nrcrtid" + (y + 1)).name = "nr_crt" + y;
document.getElementById("nrcrtid" + (y + 1)).id = "nrcrtid" + y;
document.getElementById("prodid" + (y + 1)).name = "prod" + y;
document.getElementById("prodid" + (y + 1)).id = "prodid" + y;
document.getElementById("umid" + (y + 1)).name = "um" + y;
document.getElementById("umid" + (y + 1)).id = "umid" + y;
document.getElementById("cantitateid" + (y + 1)).name = "cantitate" + y;
document.getElementById("cantitateid" + (y + 1)).id = "cantitateid" + y;
document.getElementById("pretid" + (y + 1)).name = "pret" + y;
document.getElementById("pretid" + (y + 1)).id = "pretid" + y;
document.getElementById("pretfaraTVAid" + (y + 1)).name = "pretfaraTVA" + y;
document.getElementById("pretfaraTVAid" + (y + 1)).id = "pretfaraTVAid" + y;
document.getElementById("tvaid" + (y + 1)).name = "tva" + y;
document.getElementById("tvaid" + (y + 1)).id = "tvaid" + y;
document.getElementById("tr" + (y + 1)).id = "tr" + y;
document.getElementById("buton" + (y + 1)).id = "buton" + y;
document.getElementById("butons" + (y + 1)).onclick = function onclick(event) {
stergeLinie(y);
}
document.getElementById("butons" + y).id = "butons" + (y);
}
alert(y);
document.getElementById("tr" + i).style.height = "100%";
i--;
}

The main problem is this line:
document.getElementById("butons" + (y + 1)).onclick = function onclick(event) {
stergeLinie(y);
}
y is getting incremented each time the loop runs (y++), so when the button is actually clicked, y has the value it had on the final iteration - which is just enough to get the loop to run once.
Another issue you're having is this line:
var rowCount = tabel.rows.length;
Where your ids are 1-based, that is the lowest number is 1, whereas the length property is 0 based. If there are 4 rows, rowCount will be 3, meaning that your loop will never reach 4 because the condition is y < rowCount.
Here's a cut down version of your script: http://jsfiddle.net/trolleymusic/XTzjb/ -- I also had to run the function once at the beginning to bind the click in the way that you're doing it.
Here's an updated version that loops correctly: http://jsfiddle.net/trolleymusic/Z8UYp/
var k;
var i = 1;
function stergeLinie(k) {
console.log("k: " + k);
var tabel = document.getElementById('produse');
// Add 1 to the rowCount because the elements have been assigned
// ids starting with 1, and length is 0-based
var rowCount = tabel.rows.length + 1;
var row = document.getElementById("tr" + k);
row.parentNode.removeChild(row);
var t = rowCount;
console.log(t, k);
for (var y = k; y < t; y++) {
console.log("Loop: " + y);
// If the elements don't exist anymore because they were removed
// skip the loop
if (!document.getElementById("butons" + (y + 1))) {
continue;
}
document.getElementById("butons" + (y + 1)).onclick = function onclick(event) {
// Get the number out of the
// id of the element that was clicked
var x = parseInt(this.id.replace("butons",""));
console.log("x: " + x);
stergeLinie(x);
}
}
}
metadings helpfully added below that you could use a closure for y (http://jsfiddle.net/trolleymusic/dxy6N/)
for (var y = k; y < t; y++) {
(function (y) {
document.getElementById("butons" + (y + 1)).onclick = function onclick(event) {
console.log(y);
stergeLinie(y);
}
}(y));
}
It looks much more complicated, but it's not really. You're putting all of the actions into another function, and passing the value of y to that function as an argument - that means that y is not the same variable as the y that you're incrementing in the loop, it belongs to the function inside the loop. This is closure. The accepted answer to this question: How do JavaScript closures work? gives an excellent explanation of closure.

Related

how do i correctly output the number of entrys in a grid that have passed in reading order using only x and y positions in javascript?

var len = 5
var wid = 5
var g = "aaaaa" +
"aaaaa" +
"aaaaa" +
"aaaaa" +
"aaaaa";
for (var x = 0; x < len; x++) {
for (var y = 0; y < wid; y++) {
var yC = x % len
var xC = Math.floor(x / len)
console.log(x + y * xC)
}
}
this code is just a mockup of what im trying to do. currently, if you were to check the console after running this, it would log the numbers 0-4 5 times each, but what i am trying to do i output the numbers 0-24 1 time each.
note that i cant simply just loop the length of the string and output the current character index as i need to use the x and y for something else that is not present here.
https://jsfiddle.net/g19bmnsh/
I guess this is what you want.
var len = 5
var wid = 5
var g = "aaaaa" +
"aaaaa" +
"aaaaa" +
"aaaaa" +
"aaaaa";
for (var x = 0; x < len; x++) {
for (var y = 0; y < wid; y++) {
var yC = x % len
var xC = Math.floor(x / len)
console.log("x: " + x, "y: " + y, "k: " + (x + y * xC), "i:" + (y + (x * len)))
}
}

How should I use setInterval() in my code

/*Declare each backgroundColor value for each divs*/
var RR;
var GG;
var BB;
/*Declare the numbers of divs for making boxes*/
var y_end = 70;
var x_end = 70;
/*Declare the position*/
var x;
var y;
/*the time now*/
var now = new Date();
/*CSS*/
document.write("<style>");
for (y = 1; y <= y_end; y++) {
for (x = 1; x <= x_end; x++) {
if (x < 6) RR = "0" + (x * 3).toString(16);
else RR = (x * 3).toString(16);
if (y < 6) GG = "0" + (y * 3).toString(16);
else GG = (y * 3).toString(16);
BB = (4 * now.getSeconds()).toString(16);
if (now.getSeconds() < 4) BB = "0" + (4 * now.getSeconds()).toString(16);
var hex = "#" + GG + BB + RR;
document.write(" .r" + x + "g" + y + "{ margin:0; padding:0;width:1vw; height:0.5vh; background-color:" + hex + "; }");
}
}
document.write("</style>");
/*makes divs for cubes*/
document.write("<div id='cube' style='display:block'>");
for (y = 1; y <= y_end; y++) {
document.write("<div style='display:table-cell;'>");
for (x = 1; x <= x_end; x++) {
document.write("<div class='r" + x + "g" + y + "'></div>");
}
document.write("</div>");
}
<script src="cube.js"></script>
I am making a color-square that changes in every single second.
but I can't find where should I put setInterval() in my code.
first, I use it only at /CSS/ but it doesn't work. also a bunch of error come.
You can't use document.write for anything else than initialising a html document.
If you want to use setInterval to change CSS values you can use dom manipulation, for example:
setInterval(function(){
var div = document.getElementById("mydiv");
div.style.background-color = "rgb(155, 102, 102)";
},1000);

Which function would you use - Javascript

I'm new to javascript and I have the following code:
<p id="demo"></p>
<script>
var text = "";
var x = 1;
var y = 1;
while(x < 9) {
text += "<br>" + x +"," + y;
x++;
}
document.getElementById("demo").innerHTML = text;
</script>
It prints out a list of coordinates:
1,1
2,1
3,1
4,1
5,1
6,1
7,1
8,1
The question is once it gets to 8,1 What would you use to get it to continue to:
1,2
2,2
3,2
4,2
5,2
6,2
7,2
8,2
then
1,3
and so on until it reaches 3,4 (this could be variable) then it stops.
In an ideal world I would be able to get it to go up to a maximum of 8,12.
You could use another while structure for the seconde value.
var text = "",
x,
y = 1;
while (y <= 12) {
x = 1;
while (x <= 8) {
text += "<br>" + x + "," + y;
x++;
}
y++;
}
document.getElementById("demo").innerHTML = text;
<p id="demo"></p>
Or you could use a for statement
The for statement creates a loop that consists of three optional expressions, enclosed in parentheses and separated by semicolons, followed by a statement (usually a block statement) to be executed in the loop.
var text = "",
x,
y;
for (y = 1; y <= 12; y++) {
for (x = 1; x <= 8; x++) {
text += "<br>" + x + "," + y;
}
}
document.getElementById("demo").innerHTML = text;
<p id="demo"></p>
Write it like this:
var text = "", x,y;
for (y=1; y<= 12; y++) {
for (x=1; x<= 8; x++) {
text += "<br>" + x + "," + y;
}
}
document.getElementById("demo").innerHTML = text;
<p id="demo"></p>
You can nest loops. The best solution here is to use two nested for loops:
let text = '';
for (let y = 1; y <= 12; ++y) {
for (let x = 1; x <= 8; ++x) {
text += "<br>" + x + "," + y;
}
}
document.getElementById("demo").innerHTML = text;
<output id="demo"></output>
As you can see, it stops at 8,12, exactly like you wanted :)
You can find more about different types of loops and iteration on MDN.
Here is a fun solution. It is not what I would do but for educational purposes, so take it for what it is.
It uses Array.prototype.reduce on inner and outer arrays. The accumulated result of the inner array on each iteration gets added to the accumulator of the outer array. The inner reduce is where all the actual data is added. The outer reduce just accumulates the inner results.
It uses some ECMAScript 2015 features also like the spread syntax and arrow functions.
str = [...Array(12)].reduce((s, _, i) =>
s + [...Array(8)].reduce((ss, _, j) =>
ss + (j + 1) + ',' + (i + 1) + "\n", ""),
"");
console.log(str);
I used "\n" instead of "<br>" so that it shows up in console.
Don't actually use this. Its just to show different way. I would use a nested loop in practice.
Have fun!

I can't get eval() to work with my javascript calculation

I am working on a javascript code which calculates the value of Pi. So here's the problem. When eval() calculates the string which is generated by the code it returns 1. It is supposed to return 1.49138888889 (which is a rough value of Pi^2/6).
Here's the code. It returns the correct calculation as a string, But eval() doesn't calculate it properly.
function calculate() {
var times = 10;
var functionpart1 = "1/";
var functionpart2 = "^2+";
var x;
for (var functionpistring = "", x = 1; times != 0; times--, x++) {
functionpistring = functionpistring + functionpart1 + x.toString() + functionpart2;
}
document.getElementById("value").innerHTML = eval(functionpistring.slice(0, functionpistring.length - 1));
}
function calculate() {
var times = 20, // max loops
x, // counter
f = 0, // value representation
s = ''; // string representation
function square(x) {
return x * x;
}
function inv(x) {
return 1 / x;
}
function squareS(x) {
return x + '²';
}
function invS(x) {
return '1 / ' + x;
}
for (x = 0; x < times; x++) {
f += square(inv(x));
s += (s.length ? ' + ' : '') + squareS(invS(x));
document.write(f + ' = ' + s);
}
}
calculate();

Dice roll in javascript

function rolldice() {
var x = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var y = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var dicetotal = x + y;
var double = 0;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" + y);
if (x == y) { //<----checking if there is a double
var double = double++; //<---increment double count
//Now reroll the dice, but if you hit 3 doubles in a row, you get message go to jail.
}
};
I want to know if I am going to need some loop...Please help me. This is part of a monopoly game. What do i have to add in the code, to make it loop if there is a double.
You only need to make an recursive call:
var dbl = 0;
function rolldice() {
var x = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var y = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var dicetotal = x + y;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" + y);
if (x == y) { //<----checking if there is a double
dbl++; //<---increment double count
if(dbl%3==0) $('.out').attr('id', "jail");
//Now reroll the dice, but if you hit 3 doubles in a row, you get message go to jail.
rolldice();
}
};
I think you need to create something like this:
var double = 0;
function rolldice(){
var x = Math.floor(Math.random() * ((6-1)+1) + 1);
var y = Math.floor(Math.random() * ((6-1)+1) + 1);
var dicetotal = x + y;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" +y);
if(x==y) {
if (double < 3) {
double++; // increase dobule
rolldice(); // Call rolldice again...
} else {
// Here there is 3 in a row....
}
}
}
This has some complications. When there is a change of player, you need to reset the value of your variable for checking double rolls.
Do the following:
var dblRolls;
function userChange(){//call this on change of user
dblRolls=0;
rollDice();
}
function rolldice() {
var x = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var y = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var dicetotal = x + y;
var double = 0;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" + y);
if (x == y) { //<----checking if there is a double
dblRoll++; //<---increment double count
if(dblRoll==3)
//jail
else
rollDice();
}
};
Don't use a loop.
Instead add the doubles counter as a parameter for the rolldice() function and call the function from within itself:
function rolldice(doubleCount) {
var x = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var y = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var dicetotal = x + y;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" + y);
if (x == y) { //<----checking if there is a double
doubleCount++;
if (doubleCount == 3)
{
//go to jail
}
else
{
rolldice(doubleCount);
}
}
};
The initial call for a player's first roll would look like rolldice(0);
Ok, besides this is more than two hours old and has already 4 answers, I want to add my 2 cents.
You state you want to make a Monopoly game. After most, if not all, dice rolls the player has to make decisions. That means after each roll you wait for user input (e.g., some button presses).
All other answers postet suggest to use recursive calls in some way. Instead I suggest to store the number of doubles alongside with the current player in some global variable. You do not use a loop, but instead something like:
var doubleCount = 0;
function rolldice() {
var x = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var y = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
var dicetotal = x + y;
$('.dice1').attr('id', "dice" + x);
$('.dice2').attr('id', "dice" + y);
if (x == y) { //<----checking if there is a double
doubleCount++; //<---increment double count
if (doubleCount > 2) {
// Got to Jail
}
}
// Proceed as usual and come back to this, when the user presses the "Roll" Button again
};
This script works:
function rollDice(){
var dice1 = document.getElementById("dice1");
var dice2 = document.getElementById("dice2");
var status = document.getElementById("status");
var d1 = Math.floor(Math.random() * 6) + 1;
var d2 = Math.floor(Math.random() * 6) + 1;
var diceTotal = d1 + d2;
dice1.innerHTML = d1;
dice2.innerHTML = d2;
status.innerHTML = "You rolled "+diceTotal+".";
if(d1 == d2){
status.innerHTML += "<br />DOUBLES! You get a free turn!!";
}
}
This is one possible solution.
function rolldice(dbl=0){
var x = Math.floor(Math.random()*((6-1)+1) + 1);
var y = Math.floor(Math.random()*((6-1)+1) + 1);
if(x===y){
if(dbl!==3){
dbl++;
rolldice(dbl);
}else{
//goto jail
}
}else{
//no double
dbl=0;
}
}
or
function rolldice(dbl=0){
var x = Math.floor(Math.random()*((6-1)+1) + 1);
var y = Math.floor(Math.random()*((6-1)+1) + 1);
if(x===y&&dbl!==3)
dbl++;
rolldice(dbl);
}else if(x===y&&dbl===3){
//goto jail
}else{
//no double
dbl=0;
}
}

Categories

Resources