Need help with the Simon Game

Hello. Ever since the new certifications were announced, I’ve been going on a journey to earn the legacy front-end, just for fun before it possibly forever vanishes.

Right now I’m working with the Simon game.

However, I’m having some issues with the button’s event listeners, which appear to remain persistent even after I call removeEventListener()

To recreate the bug, just start the game, score the first point, click reset and start the game again, score the first point, and look in the console

The project is below. Help would really be appreciated.

Hi there!

Ensure the same function reference is used for both addEventListener and removeEventListener.

Example code
const handleClick = () => console.log("Clicked!");
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick); // Same reference!

If you’re unsure whether a listener is attached, log or inspect it during runtime.
Do not use anonymous functions directly in addEventListener. Always assign them to a variable or constant first.

Example code
const handleClick = function () {
    console.log("Clicked!");
};
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);

If you’re unable to track down the issue, remove all listeners for a specific event:

Example code
const newButton = button.cloneNode(true);
button.parentNode.replaceChild(newButton, button);

If you’re working with dynamic elements or frameworks, ensure you track and clean up listeners when elements are removed from the DOM.
Use once: true in the event listener options if you only need the listener to trigger once:

Example code
button.addEventListener("click", handleClick, { once: true });

Now the listeners don’t even work. Idk what went wrong

My magic ball is not working today. I can’t see, what you did to your code.

I just did what you told me to. Use a defined function in the listeners instead of an anonymous one. Nothing else

Edit: Ok, that’s fixed now, but the buttons just light up all at once instead of following a sequence

Your issue likely arises because the event listener functions are being redefined every time you call the cycle function. This creates a new function reference for registerBlueClick, registerRedClick, etc., which prevents removeEventListener from removing the previously attached listeners.

In JavaScript, removeEventListener works only if the function reference provided is exactly the same as the one used with addEventListener. Since you’re redefining registerBlueClick and others each time cycle is called, the previous listeners remain active.

Define the event listener functions only once at the top level, outside of cycle.
Use these predefined functions for both addEventListener and removeEventListener.

Code
const registerBlueClick = () => {
  blueAudio.play();
  handleUserClick('1');
};

const registerRedClick = () => {
  redAudio.play();
  handleUserClick('2');
};

const registerYellowClick = () => {
  yellowAudio.play();
  handleUserClick('3');
};

const registerGreenClick = () => {
  greenAudio.play();
  handleUserClick('4');
};

// Handle user clicks
const handleUserClick = (colorCode) => {
  userSequence += colorCode;
  console.log(userSequence, sequence.join(''));

  if (userSequence[userIdx] == sequence[userIdx]) {
    userIdx++;
    if (userSequence == sequence.join('')) {
      cycle(sequence.length); // User completed the sequence
    }
  } else {
    // Handle incorrect input
    if (!strict) {
      cycle(sequence.length, true); // Replay the sequence
    } else {
      reset();
      toggle.innerText = 'You lost in strict mode! Try again?';
    }
  }
};

// Main game logic
const cycle = (repeats, replay = false) => {
  // Remove listeners
  blue.removeEventListener('click', registerBlueClick);
  red.removeEventListener('click', registerRedClick);
  yellow.removeEventListener('click', registerYellowClick);
  green.removeEventListener('click', registerGreenClick);

  let userSequence = '';
  let userIdx = 0;

  // Simulate the sequence
  sequence.forEach((press, index) => {
    setTimeout(() => {
      switch (press) {
        case 1:
          blue.id = 'lit';
          blueAudio.play();
          break;
        case 2:
          red.id = 'lit';
          redAudio.play();
          break;
        case 3:
          yellow.id = 'lit';
          yellowAudio.play();
          break;
        case 4:
          green.id = 'lit';
          greenAudio.play();
          break;
      }
      setTimeout(() => {
        blue.id = '';
        red.id = '';
        yellow.id = '';
        green.id = '';
      }, 500);
    }, 1000 * index);
  });

  // Reactivate buttons after the sequence
  setTimeout(() => {
    blue.disabled = false;
    red.disabled = false;
    yellow.disabled = false;
    green.disabled = false;

    blue.addEventListener('click', registerBlueClick);
    red.addEventListener('click', registerRedClick);
    yellow.addEventListener('click', registerYellowClick);
    green.addEventListener('click', registerGreenClick);
  }, 1000 * sequence.length + 500);
};