javascripthtmldomtoggle

I just want to show/hide my divs, but I'm having issues with my variables. Any ideas?


I'm making a mini project for a coding class, featuring a list of poems. I set the poems in divs and the divs in a section (per a suggestion), and I want to toggle the poems' text and images so that they show or hide, and I wanted to change the button text to "Close" when shown from "Read" when hidden.

While I got some help, mainly with setting up the .forEach() method, I still can't find the solution. I've tried everything. Any other advice has been too confusing and too hard to follow.

Any help is appreciated. Thank you.

I tried using the different methods of retrieving elements from the DOM (.querySelector, .querySelectorAll, .getElementById, etc.). I tried changing the class and id names. I tried making it so I didn't shadow my variables. Literally everything.

let selection = document.querySelector(".poem")
const buttons = document.querySelectorAll(".btn");

// show poem or hide poem
// change text to "Read" or "Close"; if the poem is hidden, say "Read"; if it is showing, say "Close"

const readPoem = (poem) => {
  if (selection.style.display == "none") {
    selection.style.display = "block";
  } else {
    selection.style.display = "none";
  }
};

console.log()

buttons.forEach((btn) => {
  btn.addEventListener("click", (selection) => {
    if (selection.style.display == "none") {
      selection.style.display = "block";
      btn.textContent = "Close";
    } else {
      selection.style.display = "none";
      btn.textContent = "Read";
    }
  });
});

Solution

  • Based on your description, I assume that your HTML structure is like this:

    <section>
      <div class="poem-container">
        <button class="btn">Read</button>
        <div class="poem" style="display: none;">
          <!-- Poem content here -->
        </div>
      </div>
      <div class="poem-container">
        <button class="btn">Read</button>
        <div class="poem" style="display: none;">
          <!-- Poem content here -->
        </div>
      </div>
      <!-- More poem containers as needed -->
    </section>
    

    The event handler function accepts an Event object. You are passing the selection, which is not relevant.

    Then we get the poem that is in the same container as the button (they are both in the .poem-container):

    const poem = btn.closest(".poem-container").querySelector(".poem");
    

    And finally, we can continue with the rest of the logic.

    Here is the updated code and demo:

    const buttons = document.querySelectorAll(".btn");
    
    buttons.forEach((btn) => {
      btn.addEventListener("click", (event) => {
        // Find the associated poem div
        const poem = btn.closest(".poem-container").querySelector(".poem");
    
        if (poem.style.display === "none" || poem.style.display === "") {
          poem.style.display = "block";
          btn.textContent = "Close";
        } else {
          poem.style.display = "none";
          btn.textContent = "Read";
        }
      });
    });
    .poem-container {
      margin-bottom: 20px;
      border: 1px solid black;
      padding: 20px;
      width: fit-content;
    }
    <section>
      <div class="poem-container">
        <button class="btn">Read</button>
        <div class="poem" style="display: none;">
          I am a poem
        </div>
      </div>
      <div class="poem-container">
        <button class="btn">Read</button>
        <div class="poem" style="display: none;">
          I am another poem
        </div>
      </div>
      <!-- More poem containers as needed -->
    </section>