1

I am creating a scrabble game with JavaScript and I have an issue. I have this function that creates scrabble tiles inside a tile rack div. I also have an event listener that listens for when the tile divs are clicked. When a section on the board is clicked, and then the tile div is clicked it places the tile on the board and then it would be removed from the the parent div(tile rack). How this works is this: I create an array which has those tile divs inside and then when I remove the div from inside the array, I would override the parent div(tile rack) with the new array. all this happens very well but the issue now is that when the old tiles overrides the new tiles in the parent div, the event listener does not work again.

here is my code and a link to my entire code explaining this:

let bag = ["A|1","A|1","A|1","A|1","A|1","A|1","A|1","A|1","A|1","B|3","B|3","C|3","C|3","D|2","D|2","D|2","D|2","E|1","E|1","E|1","E|1","E|1","E|1","E|1","E|1","E|1","E|1","E|1","E|1","F|4","F|4","G|2","G|2","G|2","H|4","H|4","I|1","I|1","I|1","I|1","I|1","I|1","I|1","I|1","I|1","J|8","K|5","L|1","L|1","L|1","L|1","M|3","M|3","N|1","N|1","N|1","N|1","N|1","N|1","O|1","O|1","O|1","O|1","O|1","O|1","O|1","O|1","P|3","P|3","Q|10","R|1","R|1","R|1","R|1","R|1","R|1","S|1","S|1","S|1","S|1","T|1","T|1","T|1","T|1","T|1","T|1","U|1","U|1","U|1","U|1","V|4","V|4","W|4","W|4","X|8","Y|4","Y|4","Z|10","|","|"];

// to fill the plate or stick with tiles from the bag array
let player1 = [];
let player2 = [];
let player1plate = document.getElementById("plate1");
let player2plate = document.getElementById("plate2");
// var tile = bag[Math.floor(Math.random() * bag.length)];

// FILL THE PLATE OR STICK WITH TILES
function fillStick(player, numberOfTilesNeeded, playerplate, id) {
  let insert = "";
  for (let i = 0; i < numberOfTilesNeeded; i++) {
    randomIndex = Math.floor(Math.random() * bag.length);
    player.push(bag[randomIndex]);
    bag.splice(randomIndex, 1);
  }
  for (let j = 0; j < player.length; j++) {
    insert += ` 
    <div class="tile" id="${id}${j}">
    <h2> ${player[j].split("|")[0]}</h2>
    <p>${player[j].split("|")[1]}</p>
  </div>`;
  }
  playerplate.innerHTML = insert;
  // console.log(bag);
  console.log(player1);
}
fillStick(player1, 7, player1plate, "tile");
fillStick(player2, 7, player2plate, "rile");

function removeTile(player, playerplate, id) {
  let insert = "";
  
  for (let j = 0; j < player.length; j++) {
    insert += ` 
    <div class="tile" id="${id}${j}">
    <h2> ${player[j].split("|")[0]}</h2>
    <p>${player[j].split("|")[1]}</p>
  </div>`;
  }
  playerplate.insertAdjacentHTML("beforeend",insert);
  console.log(playerplate);
}

// for the tiles on the rack/plate to click and be placed on the board
let tileClicked = 0;
let allTiles = document.querySelectorAll(".tile");


allTiles.forEach((e) => {
  e.addEventListener("click", () => {
    for (let i = 0; i < allTiles.length; i++) {
      allTiles[i].setAttribute("class", "tile");
    }
    if (tileClicked == e.id) {
      e.setAttribute("class", "tile");
      tileClicked = 0;
    } else {
      e.setAttribute("class", "tile active");
      tileClicked = e.id;
      if (clicked != 0) {
        document
          .getElementById(clicked)
          .setAttribute(
            "style",
            "background: #dfb15b; flex-direction: column;"
          );
        document.getElementById(clicked).setAttribute("class", "tilesections");
        document.getElementById(clicked).innerHTML = e.innerHTML;
        if (tileClicked.split("e")[0] == "til") {
          player1.splice(tileClicked.split("e")[1], 1);
          removeTile(player1, player1plate, "tile")
        } else {
          player2.splice(tileClicked.split("e")[1], 1);
          removeTile(player2, player2plate, "rile")// where i stopped
          console.log(player2);
        }

        clicked = 0;
        tileClicked = 0;
        e.setAttribute("class", "tile");
      }
    }
    // console.log(e.id);
    // console.log(player1);
  });
});

to understand the problem better to can check the full code with this link https://codepen.io/crentsil/pen/WNpeoKo

  • 1
    Does this answer your question? [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Heretic Monkey May 04 '21 at 12:32
  • 2
    [This answer](https://stackoverflow.com/a/27373951/215552) on the proposed duplicated shows how to use event delegation without jQuery. – Heretic Monkey May 04 '21 at 12:34

1 Answers1

2

I think you should approach this question a little bit differently. Instead of adding an even listener on every single tile, you should add one on the container of the tiles. When you click an inner tile the event will "bubble" upwards. When it reaches the container div, you can catch it and get the originally clicked tile with the event.target attribute of the event parameter.

HTML:

<div id="board">
  <div id="1"> 1 </div>
  <div id="2"> 2 </div>
  <div id="3"> 3 </div>
</div>

CSS

#board > div
{
  width: 50px;
  height: 50px;
  background-color: gray;
  margin: 10px;
}

JS

document.getElementById('board').addEventListener('click', (e) =>
{
  let t = e.target
  alert(`${t.id} clicked`)
})
Richard Nagy
  • 121
  • 6