0

/*Note that the column of the matrix is row of the tetris board and vice versa,
So going left to right ----> in this matrix would be the same as going top
to bottom in the actual tetris board*/
var a = [
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];

//Generates random integer between given range
function getRandomInteger(min, max) {
    return Math.round(Math.random() * (max - min)) + min;
}

function getColor() {
  //an array of red, blue ,green, yellow, orange, purple and salmon color
    var colorArray = ["#C0392B" ,"#2980B9", "#27AE60", "#F1C40F", "#E67E22", "#8E44AD", "#FFA07A"]
    return colorArray[getRandomInteger(0, 7)];
}


//Creates a random set of block on the top
function createBlocks() {
  var i = getRandomInteger(0, 9);
  blockHeight = getRandomInteger(2, 4);
  var blockColor = getColor();
  for (var j= 0; j<blockHeight; j++)
     {
       a[i][j] = 1;
       nthBoxToColor =i+10*j+1;
       document.querySelector('td:nth-of-type('+nthBoxToColor+')').style.backgroundColor = blockColor;
     }
};

//Moves the set of block one step down
function moveOneStepDown() {
    //For testing, to be removed later
    console.log(a[i]);
    for (var i = 0; i < 10; i++) {
        a[i].pop();
        a[i].unshift(0);

        //For testing, to be removed later
        console.log(a[i]);
    };
    //For testing, to be removed later
    console.log("-------------------------------------");
};

/*the setInterval function of javascript executes the code infinite number of
times, so a new function is defined to carry it out finite no of times*/
function setIntervalX(callback, delay, repetitions) {
    var x = 0;
    var intervalID = window.setInterval(function () {

       callback();

       if (++x === repetitions) {
           window.clearInterval(intervalID);
       };
    }, delay);
};


//Code execution
createBlocks();
setIntervalX(moveOneStepDown, 100, a[0].length-blockHeight);
gameContainer {
    margin-left: 10vw;
    width: 80vw;
    background-color: blue;
}

.tetris-board {
  margin-left: 30vw;
  width: 20vw;
}

td {
 height: 2vw;
}
<!DOCTYPE html>
<html>
<head>
 <title></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link type="text/css" rel="stylesheet" href="assets\css\style.css"></link>
 <script type="text/javascript" src="assets\js\jquery-3.3.1.slim.min.js"></script>
 <script type="text/javascript" src="assets\js\bootstrap.min.js"></script>
 <script type="text/javascript" src="assets\js\popper.min.js"></script>
</head>
<body>
<div class="gameContainer">
<table class="table table-bordered table-dark tetris-board">
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
</div>
</body>
<script type="text/javascript" src="assets\js\script.js"></script>
</body>
</html>

I have an integer variable nthBoxToColor whose value changes along with the loop. And I want to color some specific table blocks according to the current value of nthBoxToColor.

So I tried the following code by concatenating strings with the variable:

document.querySelector('td:nth-of-type(' + nthBoxToColor + ')').style.backgroundColor = "blue";

But I got an error:

 Uncaught TypeError: Cannot read property 'style' of null
        at createBlocks (script.js:39)
        at script.js:74
    createBlocks @ script.js:39
    (anonymous) @ script.js:74

What went wrong? What is the right code to do it?

Edit:

The loop I ran the code inside is:

for (var j= 0; j<blockHeight; j++)
     {
       a[i][j] = 1;
       var nthBoxToColor =i+10*j+1;
       document.querySelector('td:nth-of-type(' + nthBoxToColor + ')').style.backgroundColor = blockColor;
     }

Where i is a random integer between 0 and 9 and blockHeight is also a random integer between 2 and 4.

hiccup
  • 29
  • 3
  • Sounds like the selector is wrong, nothing more can be said without a [MCVE] – CertainPerformance Oct 21 '19 at 07:17
  • I think when you're looping you're starting from 0 which wouldn't get any element, try starting from 1 and enclose the statement with an if condition – shrys Oct 21 '19 at 07:21
  • @CertainPerformance there is nothing wrong with the selector. I verified it by replacing the string inside document.querySelector() with just "td" and it worked with no problems. The problem lies in the concatenation of string inside document.querySelector() which I don't understand. Maybe there is an alternative to this method, which I don't know of. Also I don't understand how this is a duplicate to post you marked. Can you please remove the duplicate mark? Or is there something more I need to change before that can happen? – hiccup Oct 21 '19 at 07:58
  • Your selector isn't working, so there *is* something wrong with it, clearly, but again, there's not enough code in the question to say for sure what the solution might be (need a [MCVE]) – CertainPerformance Oct 21 '19 at 08:04
  • @CertainPerformance But if there was something wrong with the selector why did the same selector work for "tr" but not for the string 'td:nth-of-type(' + nthBoxToColor + ')' – hiccup Oct 21 '19 at 08:14
  • Those are different selectors - one selector string is not the same as the other. A selector string `#foo` will work if there's a `#foo` element in the document, but a selector string `#bar` will not work if there is no `#bar` element in the document - because the selector is wrong – CertainPerformance Oct 21 '19 at 08:17
  • Thanks for the Stack Snippet, now the question is answerable! – CertainPerformance Oct 21 '19 at 08:26

1 Answers1

0

Right now, you're adding 10 to the number being passed to nth-of-type on every iteration:

nthBoxToColor = i + 10 * j + 1;

So on the first iteration, if the selector is

td:nth-of-type(9)

then on the second iteration, the selector will be

td:nth-of-type(19)

But you only have 10 TDs in a single TR, so the selector fails.

While you could select the first TR first and then call querySelector on it to get the right TD:

  for (var j = 0; j < blockHeight; j++) {
    a[i][j] = 1;
    nthBoxToColor = i + 1;
    const tr = document.querySelector(`tr:nth-child(${j + 1})`);
    tr.querySelector(`td:nth-of-type(${nthBoxToColor})`).style.backgroundColor = blockColor;
  }

It would be easier just use bracket notation to look up the appropriate nested child:

const tbody = document.querySelector('.table > tbody');

and then, inside the loop:

tbody.children[j].children[i].style.backgroundColor = blockColor;

/*Note that the column of the matrix is row of the tetris board and vice versa,
So going left to right ----> in this matrix would be the same as going top
to bottom in the actual tetris board*/
var a = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];

//Generates random integer between given range
function getRandomInteger(min, max) {
  return Math.round(Math.random() * (max - min)) + min;
}

function getColor() {
  //an array of red, blue ,green, yellow, orange, purple and salmon color
  var colorArray = ["#C0392B", "#2980B9", "#27AE60", "#F1C40F", "#E67E22", "#8E44AD", "#FFA07A"]
  return colorArray[getRandomInteger(0, 7)];
}


//Creates a random set of block on the top
function createBlocks() {
  var i = getRandomInteger(0, 9);
  blockHeight = getRandomInteger(2, 4);
  var blockColor = getColor();
  const tbody = document.querySelector('.table > tbody');
  for (var j = 0; j < blockHeight; j++) {
    a[i][j] = 1;
    tbody.children[j].children[i].style.backgroundColor = blockColor;
  }
};

//Moves the set of block one step down
function moveOneStepDown() {
  //For testing, to be removed later
  // console.log(a[i]);
  for (var i = 0; i < 10; i++) {
    a[i].pop();
    a[i].unshift(0);

    //For testing, to be removed later
    // console.log(a[i]);
  };
  //For testing, to be removed later
  // console.log("-------------------------------------");
};

/*the setInterval function of javascript executes the code infinite number of
times, so a new function is defined to carry it out finite no of times*/
function setIntervalX(callback, delay, repetitions) {
  var x = 0;
  var intervalID = window.setInterval(function() {

    callback();

    if (++x === repetitions) {
      window.clearInterval(intervalID);
    };
  }, delay);
};


//Code execution
createBlocks();
setIntervalX(moveOneStepDown, 100, a[0].length - blockHeight);
gameContainer {
  margin-left: 10vw;
  width: 80vw;
  background-color: blue;
}

.tetris-board {
  margin-left: 30vw;
  width: 20vw;
}

td {
  height: 2vw;
}
<!DOCTYPE html>
<html>

<head>
  <title></title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link type="text/css" rel="stylesheet" href="assets\css\style.css"></link>
  <script type="text/javascript" src="assets\js\jquery-3.3.1.slim.min.js"></script>
  <script type="text/javascript" src="assets\js\bootstrap.min.js"></script>
  <script type="text/javascript" src="assets\js\popper.min.js"></script>
</head>

<body>
  <div class="gameContainer">
    <table class="table table-bordered table-dark tetris-board">
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
    </table>
  </div>
</body>
<script type="text/javascript" src="assets\js\script.js"></script>
</body>

</html>
CertainPerformance
  • 260,466
  • 31
  • 181
  • 209
  • this question : https://stackoverflow.com/questions/58484209/how-to-apply-css-nth-of-type-selector-to-nth-tr-inside-nth-td# do not seemed to be a duplicate of this question , **it doesn't ask for javascript, nor is tagged JavaScript** but pure CSS selector and only tagged with CSS :( – G-Cyrillus Oct 21 '19 at 10:37