-2

I am making a text to notecard program in HTML, CSS and JS. I wanted to add a button where you could flip all flashcards over. Right now it only works flipping from the back face to the front:

Video of issue

function flipAll() {
  const cards = document.querySelectorAll('.card');
  cards.forEach(card => {
    card.addEventListener('click', () => {
      card.classList.toggle('flipped');
    });
  });
}

function storeValue() {
  var inp = document.getElementById("input").value.toString();
  const terms = []
  const definitions = []
  const defobj = {}

  let symbol = document.getElementById("symbol").value.toString();
  const regex = new RegExp(`\\s*${symbol}\\s*(.*)`);
  inp.split('\n').forEach(line => {
    if (line.includes(symbol)) {
      [term, definition, _] = line.split(regex)
      terms.push(term)
      definitions.push(definition)
      defobj[term] = definition
    }
  })

  console.log(inp)
  console.log(terms)
  console.log(definitions)
  console.log(defobj)

  const flashcards = document.getElementById("flashcards");
  flashcards.innerHTML = "";

  for (let i = 0; i < terms.length; i++) {
    const card = document.createElement("div");
    card.classList.add("card");

    const cardInner = document.createElement("div");
    cardInner.classList.add("card-inner");
    card.appendChild(cardInner);

    const cardFront = document.createElement("div");
    cardFront.classList.add("card-front");
    cardFront.innerHTML = `<h2>${terms[i]}</h2>`;
    cardInner.appendChild(cardFront);

    const cardBack = document.createElement("div");
    cardBack.classList.add("card-back");
    cardBack.innerHTML = `<p>${definitions[i]}</p>`;
    cardInner.appendChild(cardBack);

    card.addEventListener("click", function() {
      card.classList.toggle("flipped");
    });

    flashcards.appendChild(card);
  }
}
body {
  background-color: #222;
  color: #fff;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  font-size: 16px;
  overflow-x: hidden;
}

textarea::-webkit-resizer {
  background-color: #222;
  border: 1px solid #444;
  border-radius: 10px;
  width: 2px;
  height: 2px;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background-color: #222;
}

::-webkit-scrollbar-thumb {
  background-color: #555;
  border-radius: 10px;
}

::-webkit-scrollbar-thumb:hover {
  background-color: #888;
}

.custom-shape-divider-bottom-1678203398 {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  overflow: hidden;
  line-height: 0;
  transform: rotate(180deg);
}

.custom-shape-divider-bottom-1678203398 svg {
  position: relative;
  display: block;
  width: calc(181% + 1.3px);
  height: 421px;
  transform: rotateY(180deg);
}

.custom-shape-divider-bottom-1678203398 .shape-fill {
  fill: #2E2E2E;
}

form {
  background-color: #444;
  border-radius: 10px;
  padding: 30px;
  margin: 50px auto;
  max-width: 800px;
}

label {
  display: block;
  margin-bottom: 20px;
}

textarea,
input[type="text"] {
  width: 100%;
  border: none;
  border-radius: 10px;
  background-color: #252525;
  color: #fff;
  padding: 15px;
  margin-bottom: 20px;
  font-size: 18px;
  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.2);
  resize: none;
  box-sizing: border-box;
}

textarea::placeholder,
input[type="text"]::placeholder {
  color: #A0A0A0;
  font-size: 18px;
}

button {
  background-color: #007bff;
  border: none;
  border-radius: 10px;
  color: #fff;
  cursor: pointer;
  font-size: 18px;
  margin-top: 20px;
  padding: 15px 30px;
  width: 100%;
  transition: background-color 0.3s ease;
}

button:hover {
  background-color: #0056b3;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  grid-gap: 50px;
  margin: 50px auto;
  max-width: 1200px;
  padding: 30px;
}

.card {
  width: 400px;
  height: 250px;
  background-color: #252525;
  border-radius: 10px;
  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.2);
  transition: transform 0.3s;
  margin: 50px auto;
  position: relative;
}

.card:hover {
  transform: scale(1.05);
  background-color: #2e2e2e;
}

.card .card-inner {
  position: absolute;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.3s;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

.card .card-front,
.card .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.card .card-front {
  transform: rotateY(0deg);
}

.card .card-back {
  transform: rotateY(180deg);
}

.card .card-back p {
  transform: rotateY(180deg);
}

.card.flipped .card-inner {
  transform: rotateY(180deg);
}

.card.flipped {
  transform: rotateY(180deg);
}

.card.flipped .card-front {
  transform: rotateY(0deg);
}
<body onload="storeValue()">
  <div class="custom-shape-divider-bottom-1678203398">
    <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
      <path d="M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z" opacity=".25" class="shape-fill"></path>
      <path d="M0,0V15.81C13,36.92,27.64,56.86,47.69,72.05,99.41,111.27,165,111,224.58,91.58c31.15-10.15,60.09-26.07,89.67-39.8,40.92-19,84.73-46,130.83-49.67,36.26-2.85,70.9,9.42,98.6,31.56,31.77,25.39,62.32,62,103.63,73,40.44,10.79,81.35-6.69,119.13-24.28s75.16-39,116.92-43.05c59.73-5.85,113.28,22.88,168.9,38.84,30.2,8.66,59,6.17,87.09-7.5,22.43-10.89,48-26.93,60.65-49.24V0Z" opacity=".5" class="shape-fill"></path>
      <path d="M0,0V5.63C149.93,59,314.09,71.32,475.83,42.57c43-7.64,84.23-20.12,127.61-26.46,59-8.63,112.48,12.24,165.56,35.4C827.93,77.22,886,95.24,951.2,90c86.53-7,172.46-45.71,248.8-84.81V0Z" class="shape-fill"></path>
    </svg>
  </div>
  <script src="script.js"></script>
  <form onsubmit="storeValue(); return false;">
    <label for="input">Enter notes:</label>
    <textarea id="input" name="input" rows="10" cols="78" placeholder="[list of terms and definitions]">
Note 1 - Definition 1
Note 2 - Definition 2
Note 3 - Definition 3</textarea>
    <input type="text" id="symbol" value="-" placeholder="[symbol seperating terms and definitions]">
    <button type="submit">Generate</button>
    <button onclick="flipAll()">Flip All</button>
  </form>
  <div class="grid" id="flashcards"></div>
</body>

Repository with code: https://github.com/Subwaey/Notes2Cards

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339

1 Answers1

1

You have two issues

  1. In flipAll(), you are adding additional click event listeners to each card, rather than actually toggling their "flip" class
  2. Your "Flip All" button is the submit button for a form, and everytime you submit this form, you are running the storeValue function, which is regenerating all 3 of your cards.

Fixed code is below:

  1. In flipAll(), we just toggle the flipped class on every card
  2. I changed your onSubmit handler to just return false (aka, do nothing special). This may or may not be what you want long term, but it will solve this current problem.

function flipAll() {
  const cards = document.querySelectorAll('.card');
  cards.forEach(card => {
      card.classList.toggle('flipped');
  });
}

function storeValue() {
  var inp = document.getElementById("input").value.toString();
  const terms = []
  const definitions = []
  const defobj = {}

  let symbol = document.getElementById("symbol").value.toString();
  const regex = new RegExp(`\\s*${symbol}\\s*(.*)`);
  inp.split('\n').forEach(line => {
    if (line.includes(symbol)) {
      [term, definition, _] = line.split(regex)
      terms.push(term)
      definitions.push(definition)
      defobj[term] = definition
    }
  })

  console.log(inp)
  console.log(terms)
  console.log(definitions)
  console.log(defobj)

  const flashcards = document.getElementById("flashcards");
  flashcards.innerHTML = "";

  for (let i = 0; i < terms.length; i++) {
    const card = document.createElement("div");
    card.classList.add("card");

    const cardInner = document.createElement("div");
    cardInner.classList.add("card-inner");
    card.appendChild(cardInner);

    const cardFront = document.createElement("div");
    cardFront.classList.add("card-front");
    cardFront.innerHTML = `<h2>${terms[i]}</h2>`;
    cardInner.appendChild(cardFront);

    const cardBack = document.createElement("div");
    cardBack.classList.add("card-back");
    cardBack.innerHTML = `<p>${definitions[i]}</p>`;
    cardInner.appendChild(cardBack);

    card.addEventListener("click", function() {
      card.classList.toggle("flipped");
    });

    flashcards.appendChild(card);
  }
}
body {
  background-color: #222;
  color: #fff;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  font-size: 16px;
  overflow-x: hidden;
}

textarea::-webkit-resizer {
  background-color: #222;
  border: 1px solid #444;
  border-radius: 10px;
  width: 2px;
  height: 2px;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background-color: #222;
}

::-webkit-scrollbar-thumb {
  background-color: #555;
  border-radius: 10px;
}

::-webkit-scrollbar-thumb:hover {
  background-color: #888;
}

.custom-shape-divider-bottom-1678203398 {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  overflow: hidden;
  line-height: 0;
  transform: rotate(180deg);
}

.custom-shape-divider-bottom-1678203398 svg {
  position: relative;
  display: block;
  width: calc(181% + 1.3px);
  height: 421px;
  transform: rotateY(180deg);
}

.custom-shape-divider-bottom-1678203398 .shape-fill {
  fill: #2E2E2E;
}

form {
  background-color: #444;
  border-radius: 10px;
  padding: 30px;
  margin: 50px auto;
  max-width: 800px;
}

label {
  display: block;
  margin-bottom: 20px;
}

textarea,
input[type="text"] {
  width: 100%;
  border: none;
  border-radius: 10px;
  background-color: #252525;
  color: #fff;
  padding: 15px;
  margin-bottom: 20px;
  font-size: 18px;
  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.2);
  resize: none;
  box-sizing: border-box;
}

textarea::placeholder,
input[type="text"]::placeholder {
  color: #A0A0A0;
  font-size: 18px;
}

button {
  background-color: #007bff;
  border: none;
  border-radius: 10px;
  color: #fff;
  cursor: pointer;
  font-size: 18px;
  margin-top: 20px;
  padding: 15px 30px;
  width: 100%;
  transition: background-color 0.3s ease;
}

button:hover {
  background-color: #0056b3;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  grid-gap: 50px;
  margin: 50px auto;
  max-width: 1200px;
  padding: 30px;
}

.card {
  width: 400px;
  height: 250px;
  background-color: #252525;
  border-radius: 10px;
  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.2);
  transition: transform 0.3s;
  margin: 50px auto;
  position: relative;
}

.card:hover {
  transform: scale(1.05);
  background-color: #2e2e2e;
}

.card .card-inner {
  position: absolute;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.3s;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

.card .card-front,
.card .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.card .card-front {
  transform: rotateY(0deg);
}

.card .card-back {
  transform: rotateY(180deg);
}

.card .card-back p {
  transform: rotateY(180deg);
}

.card.flipped .card-inner {
  transform: rotateY(180deg);
}

.card.flipped {
  transform: rotateY(180deg);
}

.card.flipped .card-front {
  transform: rotateY(0deg);
}
<body onload="storeValue()">
  <div class="custom-shape-divider-bottom-1678203398">
    <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
      <path d="M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z" opacity=".25" class="shape-fill"></path>
      <path d="M0,0V15.81C13,36.92,27.64,56.86,47.69,72.05,99.41,111.27,165,111,224.58,91.58c31.15-10.15,60.09-26.07,89.67-39.8,40.92-19,84.73-46,130.83-49.67,36.26-2.85,70.9,9.42,98.6,31.56,31.77,25.39,62.32,62,103.63,73,40.44,10.79,81.35-6.69,119.13-24.28s75.16-39,116.92-43.05c59.73-5.85,113.28,22.88,168.9,38.84,30.2,8.66,59,6.17,87.09-7.5,22.43-10.89,48-26.93,60.65-49.24V0Z" opacity=".5" class="shape-fill"></path>
      <path d="M0,0V5.63C149.93,59,314.09,71.32,475.83,42.57c43-7.64,84.23-20.12,127.61-26.46,59-8.63,112.48,12.24,165.56,35.4C827.93,77.22,886,95.24,951.2,90c86.53-7,172.46-45.71,248.8-84.81V0Z" class="shape-fill"></path>
    </svg>
  </div>
  <script src="script.js"></script>
  <form onsubmit="storeValue(); return false;">
    <label for="input">Enter notes:</label>
    <textarea id="input" name="input" rows="10" cols="78" placeholder="[list of terms and definitions]">
Note 1 - Definition 1
Note 2 - Definition 2
Note 3 - Definition 3</textarea>
    <input type="text" id="symbol" value="-" placeholder="[symbol seperating terms and definitions]">
    <button type="submit">Generate</button>
    <button type="button" onclick="flipAll()">Flip All</button>
  </form>
  <div class="grid" id="flashcards"></div>
</body>
Jake
  • 862
  • 6
  • 10
  • That fixes the flipping issue, though now you can't Generate new cards... Do you know how that would be fixed, @Jake? –  Mar 07 '23 at 21:00
  • Restored the `storeValue()` call in `onSubmit` and added `type="button"` to the FlipAll button, per the conversation [here](https://stackoverflow.com/questions/2825856/html-button-to-not-submit-form). I might also suggest not using a `
    ` at all here, and just attaching `storeValue()` as an `onclick` handler to the Generate button directly.
    – Jake Mar 07 '23 at 21:12