TomDev
TomDev

Reputation: 287

how to refactor this event listener?

I'm a JS learner. I'm trying to build a flip-card game. It's just the beginning stage. I came across a tutorial how to make a single flip-card. But I want to have several flip-cards. I figured out myself how to add event listeners to each card. Yet, I wonder if it is possible to refactor this JS code if I want to add more cards. I would have to copy the same lines of code. Can you help me in some easy vanilla way :)? Or maybe it's the only way?

   <!-- ####### CARD 1 ######### -->
    <div class="card">
      <div class="card__inner">
        <div class="card__face card__face--front">
          <h2>GAME</h2>
        </div>
        <div class="card__face card__face--back">
          <div class="card__content">
            <div class="card__header">
              <img src="" alt="" />
            </div>
            <div class="card__body">
              <h3>Dark Knight</h3>
              <p>Attack 12</p>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- ####### CARD 2######### -->
    <div class="card">
      <div class="card__inner">
        <div class="card__face card__face--front">
          <h2>GAME</h2>
        </div>
        <div class="card__face card__face--back">
          <div class="card__content">
            <div class="card__header">
              <img src="" alt="" />
            </div>
            <div class="card__body">
              <h3>Unicorn</h3>
              <p>Attack 6</p>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- ####### CARD 3 ######### -->
    <div class="card">
      <div class="card__inner">
        <div class="card__face card__face--front">
          <h2>GAME</h2>
        </div>
        <div class="card__face card__face--back">
          <div class="card__content">
            <div class="card__header">
              <img src="" alt="" />
            </div>
            <div class="card__body">
              <h3>Squirrel</h3>
              <p>Attack 1</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  const card = document.querySelectorAll(".card");
  const cardInner = document.querySelectorAll(".card__inner");

  card[0].addEventListener("click", function () {
  cardInner[0].classList.toggle("is-flipped");
  });

  card[1].addEventListener("click", function () {
  cardInner[1].classList.toggle("is-flipped");
  });

  card[2].addEventListener("click", function () {
  cardInner[2].classList.toggle("is-flipped");
  });


Upvotes: 0

Views: 166

Answers (4)

KooiInc
KooiInc

Reputation: 122906

You may want to consider using event delegation. For example:

document.addEventListener(`click`, handle);

function handle(evt) {
  if (evt.target.closest(`.card`)) {
    return evt.target
      .closest(`.card`)
      .querySelector(`.card__inner`)
      .classList.toggle(`is-flipped`);
  }
}
.card {
  cursor: pointer;
}

.is-flipped {
  color: green;
  font-weight: bold;
}
<!-- ####### CARD 1 ######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Dark Knight</h3>
          <p>Attack 12</p>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- ####### CARD 2######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Unicorn</h3>
          <p>Attack 6</p>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- ####### CARD 3 ######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Squirrel</h3>
          <p>Attack 1</p>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

Youssouf Oumar
Youssouf Oumar

Reputation: 45943

You could use forEach() function, like so :

const cards = document.querySelectorAll(".card");
const cardInners = document.querySelectorAll(".card__inner");

cards.forEach((c,index)=>c.addEventListener("click", function () {
  cardInners[index].classList.toggle("is-flipped");
}))
<!-- ####### CARD 1 ######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Dark Knight</h3>
          <p>Attack 12</p>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- ####### CARD 2######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Unicorn</h3>
          <p>Attack 6</p>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- ####### CARD 3 ######### -->
<div class="card">
  <div class="card__inner">
    <div class="card__face card__face--front">
      <h2>GAME</h2>
    </div>
    <div class="card__face card__face--back">
      <div class="card__content">
        <div class="card__header">
          <img src="" alt="" />
        </div>
        <div class="card__body">
          <h3>Squirrel</h3>
          <p>Attack 1</p>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

Mohamed Anas
Mohamed Anas

Reputation: 312

Using foreach

const card = document.querySelectorAll(".card");
const cardInner = document.querySelectorAll(".card__inner");
for(let i=0; i < card.length; i++){
    card.item(i).addEventListener("click", function () {
      cardInner.item(i).classList.toggle("is-flipped");
    });
}

Upvotes: 1

N. Hamelink
N. Hamelink

Reputation: 603

How I would do this is with the .forEach function of JavaScript. Here an example of how I would use this:

const cards = document.querySelectorAll('.card')

const onCardClick = async (e) => {
  // prevent default if you want
  e.preventDefault()
  // your function
}

if (typeof cards !== 'undefined' && cards != null) {
    cards.forEach(function(card) {
        card.addEventListener('click', onCardClick)
    })
}

Upvotes: 0

Related Questions