2

I am having trouble adding more than one flip card on a card game I'm working on. My code works well for one card, but since I'm using getElementById to make it work, it stops working when I'm adding more cards, since ID's are unique. Any idea? I want to achieve this with vanilla javascript.

HTML:

<body>
<div class="flexbox">
  <div class="flip-card" style="margin: 100px 0 0 100px">
    <div class="flip-card-inner">
      <div class="flip-card-front" id="front" onclick="flip()">
        <img
          src="/images/strawman.png"
          alt="Avatar"
          style="width:100px;height:auto"
        />
        <h2>The strawman</h2>
      </div>
      <div class="flip-card-back" id="back" onclick="flip()">
        <div style="vertical-align: middle;">
          <h3>The strawman</h3>
          <p>
            Transforming your opponent's argument into a caricature that you
            can more easily attack
          </p>
        </div>
      </div>
    </div>
  </div>
  <div class="flip-card" style="margin: 100px 0 0 100px">
    <div class="flip-card-inner">
      <div class="flip-card-front" id="front" onclick="flip()">
        <img
          src="/images/strawman.png"
          alt="Avatar"
          style="width:100px;height:auto"
        />
        <h2>The strawman</h2>
      </div>
      <div class="flip-card-back" id="back" onclick="flip()">
        <div style="vertical-align: middle;">
          <h3>The strawman</h3>
          <p>
            Transforming your opponent's argument into a caricature that you
            can more easily attack
          </p>
        </div>
      </div>
    </div>
  </div>
</div>

Javascript :

 <script>
  let toggle = true;

  function flip() {
    if (toggle == true) {
      document.getElementById("front").style.transform = "rotateY(180deg)";
      document.getElementById("back").style.transform = "rotateY(0deg)";
      toggle = !toggle;
      console.log(toggle);
    } else {
      document.getElementById("front").style.transform = "rotateY(0deg)";
      document.getElementById("back").style.transform = "rotateY(-180deg)";
      toggle = !toggle;
      console.log(toggle);
    }
  }
</script>

Thanks for the help :)

2 Answers2

1

The first step would be to avoid inline handlers, they have way too many problems to be worth using nowadays. Attach the event listeners using addEventListener instead.

Consider using CSS classes to toggle between the different rotations instead, something like:

.flip-card-inner .flip-card-front {
  transform: rotateY(180deg);
}
.flip-card-inner .flip-card-back {
  transform: rotateY(0deg);
}

.flip-card-inner.flipped .flip-card-front {
  transform: rotateY(0deg);
}
.flip-card-inner.flipped .flip-card-back {
  transform: rotateY(-180deg);
}
for (const frontOrBack of document.querySelectorAll('.flip-card-inner *')) {
  frontOrBack.addEventListener('click', () => {
    frontOrBack.parentElement.classList.toggle('flipped');
  });
}
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

First, remove the IDs -- they must be unique on a single page.

Then, pass in this (the element itself) into the function.

Then, inside the function, you don't need to select the element by ID, or class, or anything -- you already have it (as an argument).

You can get the front/back divs by selecting on the class name -- then, you apply the transform as before.

Consider this simple working snippet, which applies the above reasoning to your existing HTML/JS.

let toggle = true;

function flip(elem) {
  const wrapper = elem.parentElement;
  const front = wrapper.getElementsByClassName('flip-card-front')[0];
  const back = wrapper.getElementsByClassName('flip-card-back')[0];
  if (toggle == true) {
    front.style.transform = "rotateY(180deg)";
    back.style.transform = "rotateY(0deg)";
  } else {
    front.style.transform = "rotateY(0deg)";
    back.style.transform = "rotateY(-180deg)";
  }
  toggle = !toggle;
  console.log(toggle);
}
<div class="flexbox">
  <div class="flip-card" style="margin: 100px 0 0 100px">
    <div class="flip-card-inner">
      <div class="flip-card-front" onclick="flip(this)">
        <img
          src="/images/strawman.png"
          alt="Avatar"
          style="width:100px;height:auto"
        />
        <h2>The strawman</h2>
      </div>
      <div class="flip-card-back" onclick="flip(this)">
        <div style="vertical-align: middle;">
          <h3>The strawman</h3>
          <p>
            Transforming your opponent's argument into a caricature that you
            can more easily attack
          </p>
        </div>
      </div>
    </div>
  </div>
  <div class="flip-card" style="margin: 100px 0 0 100px">
    <div class="flip-card-inner">
      <div class="flip-card-front" onclick="flip(this)">
        <img
          src="/images/strawman.png"
          alt="Avatar"
          style="width:100px;height:auto"
        />
        <h2>The strawman</h2>
      </div>
      <div class="flip-card-back" onclick="flip(this)">
        <div style="vertical-align: middle;">
          <h3>The strawman</h3>
          <p>
            Transforming your opponent's argument into a caricature that you
            can more easily attack
          </p>
        </div>
      </div>
    </div>
  </div>
</div>
costaparas
  • 5,047
  • 11
  • 16
  • 26
  • Thanks, this does work for front or back element at a time, but how do you make it so whenever I trigger the function while passing this on back or front, it does take into account the other face inside the function? – Charlie Maréchal Dec 29 '20 at 02:28
  • Sure, @charlie, updated the example to account for this – costaparas Dec 29 '20 at 02:46