1

I am implementing a game of set using javascript. I have a class to discern whether or not the card is being selected and I will add the class to this when this method is called, which is when the card is clicked as there is an eventListener for it. However, the issue I have is implementing a deselect eventListener to be able to click so the selected class is gone but be able to click again and the selected class is back and behaves as it would have earlier. Here is the code for the function that runs when you select the card:

function cardSelected() {
  let setCount = qs('#set-count');
  let board = qs('#board');
  this.classList.add('selected');
  let selected = qsa('#board .selected');
  let count = selected.length;
  if (count === 3 && isASet(selected)) {
    for (let i = 0; i < selected.length; i++) {
      let card = generateUniqueCard(true);
      board.replaceChild(card, selected[i]);
      selected[i].classList.remove('selected');
      let paragraph = createParagraph('SET!');
      let timer = setTimeout((i) => {
        card.classList.add('hide-imgs');
        card.appendChild(paragraph);
      }, 0);
      setTimeout(() => {
        clearTimeout(timer);
        card.classList.remove('hide-imgs');
        card.removeChild(paragraph);
      }, 1000);
    }
    setCount.textContent = parseFloat(setCount.textContent) + 1;
  } else if (count === 3 && !isASet(selected)) {
    for (let i = 0; i < selected.length; i++) {
      selected[i].classList.remove('selected');
      let paragraph = createParagraph('Not a Set');
      let card = generateUniqueCard(true);
      board.replaceChild(card, selected[i]);
      let timer = setTimeout((i) => {
        card.classList.add('hide-imgs');
        card.appendChild(paragraph);
      }, 0);
      setTimeout((i) => {
        clearTimeout(timer);
        card.classList.remove('hide-imgs');
        card.removeChild(paragraph);
      }, 1000);
    }
  }
}
5
  • 2
    you should just have a single click handler that will check if there's the class that marks the element as selected. Based on that condition you'll implement the toggling logic that sets/unsets to respectively select/unselect the item in your domain Commented Apr 26, 2022 at 14:55
  • 3
    element.classList.toggle Commented Apr 26, 2022 at 14:55
  • 1
    And that code is a big mess... it would be much easier to just add a single generic function as click handler to the elements matching a given selectors.. and such function will deal with event.target to make its considerations specific to the single case Commented Apr 26, 2022 at 14:57
  • 1
    A few tips: If you kept references to the HTML elements instead of reselecting them every time you call the handler, the code inside your event handler would be smaller and easier to wrap your head around. You could also maintain the state of the game independently from the HTML elements, dividing the program into smaller problems. Commented Apr 26, 2022 at 15:03
  • Thank you all so much! It really was as simple as toggling :,) I do agree with all your points for fixing my code, I'll fix that right now! Commented Apr 26, 2022 at 15:10

1 Answer 1

0

Here is a working snippet that shows how you could do it with .classList.toggle("selected"):

const cont=document.querySelector("div.cont")

// build a sample deck of cards:
cont.innerHTML=[...Array(16)].map((_,i)=>`<span>card ${i+1}</span>`).join(" ");

// selection
cont.onclick=ev=>{
 if(ev.target.tagName==="SPAN") ev.target.classList.toggle("selected");
}
.cont span {display:inline-block; border: 1px solid grey; 
            padding:8px; margin:4px; background-color: #eee}
span.selected {background-color: red}
<div class="cont"></div>

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.