0

getting this problem,that gameflash is not acting properly Uncaught TypeError: Cannot read properties of null (reading 'classList')

I am not really sure what am I doing wrong in manipulating DOM element for each form field. My form field has an stated name and ID of form and each input field has a name and id of the field as well. But I am still getting an error.

let gameSeq = [];
let userSeq = [];

let btns = ["red", "yellow", "green", "blue"];

let started = false;
let level = 0;

let h2 = document.querySelector("h2");

document.addEventListener("keypress", function() {
  if (started == false) {
    console.log("Game Started.....");
    started = true;

    levelUp();
  }
});

function gameFlash(btn) {
  btn.classList.add("gameflash");
  setTimeout(() => {
    btn.classList.remove("gameflash");
  }, 500);
}

function userFlash(btn) {
  btn.classList.add("userflash");
  setTimeout(() => {
    btn.classList.remove("userflash");
  }, 500);
}

function levelUp() {
  level++;
  h2.innerText = `Level ${level}`;

  let randomidx = Math.floor(Math.random() * 3);
  let randomcol = btns[randomidx];
  let randombtn = document.querySelector(`.${randomcol}`);

  gameSeq.push(randomcol);

  gameFlash(randombtn);
}

function check() {
  let idx = level - 1;
  if (userSeq[idx] === gameSeq[idx]) {
    if (userSeq.length == gameSeq.length) {
      levelUp();
    }
  } else {
    h2.innerText = `Game Over! Press any key to Restart. `
  }
}

function btnPress() {
  let btn = this;
  userFlash(btn);

  usercolor = btn.getAttribute("id");
  userSeq.push(btn);

  check();
}

let allBtns = document.querySelectorAll(".btn");

for (btns of allBtns) {
  btns.addEventListener("click", btnPress);
}
body {
  text-align: center;
}

.btn {
  height: 150px;
  width: 150px;
  border-radius: 20%;
  border: 10px solid black;
  margin: 1.5rem;
}

.btn-container {
  display: flex;
  justify-content: center;
}

.red {
  background: #d95980;
}

.yellow {
  background: #f99b45;
}

.blue {
  background: #819ff9;
}

.green {
  background: #63ffc0;
}

.gameflash {
  background: #fff;
}

.userflash {
  background: #c25744;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Simon Game</title>
</head>

<body>
  <h1>Simon Game</h1>
  <h2>Press any key to start the game</h2>

  <div class="btn-container">
    <div class="box1">
      <div class="btn red" type="button" id="red">1</div>
      <div class="btn yellow" type="button" id="yellow">2</div>
    </div>
    <div class="box2">
      <div class="btn green" type="button" id="green">3</div>
      <div class="btn blue" type="button" id="blue">4</div>
    </div>
  </div>


</body>

</html>

I am trying to expecting that my gameflash error should resolve.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 6
    If `btn` is `null` in `gameFlash` then `randombtn` was `null` in `levelUp`, which means `document.querySelector(`.${randomcol}`)` found no matching element. Now is a good time to start familiarizing yourself with your browser's debugging tools to dig further, in particular using the script debugger to set breakpoints in the code and observe the runtime values and results for each operation. – David Aug 09 '23 at 18:28
  • 2
    Not the problem you're asking about, but worth pointing out: `Math.floor(Math.random()*3);` will mean that the 4th option (blue) is never selected from your button array. – DBS Aug 09 '23 at 18:28
  • 2
    Do some debugging; `randomidx`, `btns[randomidx]` and `document.querySelector(\`.${randomcol}\`)` could very easily produce a `null` result, and `null.classList` is not valid. Add some `console.log()` statements, or set breakpoints, etc. You've got an error, but you don't seem to know _why_. – Tim Lewis Aug 09 '23 at 18:29
  • 1
    `console.log(randomidx, randomcol, `.${randomcol}`, randombtn);` debug it and you will see the first part of the problem. After that you need to figure out why `btns` is not what you think it is. – epascarello Aug 09 '23 at 19:59
  • This is a bad dupe for this one.... – epascarello Aug 09 '23 at 20:00
  • 1
    `for (btns of allBtns) { ` <-- your mistake..... you set the variable holding the array to a new value! Poor choice for a variable name. – epascarello Aug 09 '23 at 20:00
  • 1
    ... in particular because `let` is missing. – CherryDT Aug 09 '23 at 20:12

1 Answers1

0

So you need to debug what is going on. The error is stating that it could not find the element so it is null.

So debug what is happening by looking at the variables before the error happens.

console.log(randomidx, randomcol, .${randomcol}, randombtn);

When you see that you will see that randomcol is undefined and randomidx is a proper number in the range. So debug it again and see what is going on with the array.

console.log(btns);

And you will see that btns is no longer is an array. Now why is that?

The problem here is you end up storing a new value into the variable so when you are accessing it, it is now not the array...

// you defined the array of buttons
let  btns = ["red", "yellow", "green","blue"];

console.log('before', btns);

const allBtns = document.querySelectorAll('.btn');

// you use the variable btns here
for (btns of allBtns) {
    btns.addEventListener("click", ()=>{});
}

console.log('after', btns);
<button class="btn red"></button>
<button class="btn yellow"></button>
<button class="btn green"></button>
<button class="btn blue"></button>

You should use const, not let so you do not do these mistakes when the variable should not be redefined.

const  btns = ["red", "yellow", "green","blue"];

console.log('before', btns);

const allBtns = document.querySelectorAll('.btn');

// you use the variable btns here
for (let btn of allBtns) {
    btn.addEventListener("click", ()=>{});
}

console.log('after', btns);
<button class="btn red"></button>
<button class="btn yellow"></button>
<button class="btn green"></button>
<button class="btn blue"></button>
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • 1
    Another good idea is not using the same variable name. Even if you use `let` and `const` so the scopes are different, it's still confusing. – Barmar Aug 09 '23 at 20:11