skip to Main Content

I want to add more "read more" buttons, but every response only for 1st one. Buttons open only first element.
I tried some versions with querySelectorAll but I can’t figure that out unfortunately…
How can I resolve this?

function myFunction() {
  const dots = document.getElementById("dots");
  const moreText = document.getElementById("more");
  const btnText = document.getElementById("myBtn");

  if (dots.style.display === "none") {
    dots.style.display = "inline";
    btnText.innerHTML = "Przeczytaj więcej";
    moreText.style.display = "none";
  } else {
    dots.style.display = "none";
    btnText.innerHTML = "Zwiń";
    moreText.style.display = "inline";
  }
}
<div class="quote__box__text">
  lorem ipsum <span id="dots">...</span>
  <span id="more" Lorem ipsum</span>
  <button onclick="myFunction()" id="myBtn">Read more</button>
</div>

<div class="quote__box__text">
  lorem ipsum <span id="dots">...</span>
  <span id="more" Lorem ipsum</span>
  <button onclick="myFunction()" id="myBtn">Read more</button>
</div>

2

Answers


  1. As per my comment, ids should be unique – instead use classes and then you can bind the click to each button and get the elements based on the clicked element

    const buttons = document.querySelectorAll('.myBtn');    // get all buttons
    
    buttons.forEach(button => {                             // loop through the buttons and add an click event listener
      button.addEventListener('click', e => {
        const container = e.currentTarget.closest('.quote__box__text'); // get the container the clicked button is in
        const dots = container.querySelector('.dots');  // get the dots element in the container
        const more = container.querySelector('.more');  // get the more element in the contanier
    
      if (dots.style.display === "none") {  // do your logic
        dots.style.display = "inline";
        more.style.display = "none";
        e.currentTarget.innerHTML = "Przeczytaj więcej";
      } else {
        dots.style.display = "none";
        more.style.display = "inline";
        e.currentTarget.innerHTML = "Zwiń";
      }
      });
    });
    .more {
      display:none;
    }
    <div class="quote__box__text">
      lorem ipsum <span class="dots">...</span>
      <span class="more">Lorem ipsum</span>
      <button class="myBtn">Przeczytaj więcej</button>
    </div>
    
    <div class="quote__box__text">
      lorem ipsum <span class="dots">...</span>
      <span class="more">
    Lorem ipsum</span>
      <button class="myBtn">Przeczytaj więcej</button>
    </div>
    Login or Signup to reply.
  2. Your HTML is invalid, you can’t use the same id on more than one element. Use a class instead, and hook up the handler dynamically. Then, in the click handler, use the specific button that was clicked to find the elements in that same div that you want to change. I also strongly recommend using classes rather than inline styles.

    For instance:

    function clickHandler(event) {
        // Because we attached this handler to each button directy, the
        // button that was clicked is available as `event.currentTarget`.
        const button = event.currentTarget;
        // Find the containing element with the class `quote__box__text`,
        // then toggle a class on it
        const div = button.closest(".quote__box__text");
        if (!div) {
            return;
        }
        div.classList.toggle("open");
        
        // Update the button text depending on whether the div
        // now has the class or not
        button.textContent = div.classList.contains("open")
            ? "Zwiń"
            : "Przeczytaj więcej";
    }
    for (const button of document.querySelectorAll(".myBtn")) {
        button.addEventListener("click", clickHandler);
    }
    /* Normally, .more elements inside .quote__box__text are hidden */
    .quote__box__text .more {
        display: none;
    }
    
    /* But they're shown when .quote__box__text has .open */
    .quote__box__text.open .more {
        display: inline;
    }
    
    /* ...but the .dots elements are hidden */
    .quote__box__text.open .dots {
        display: none;
    }
    <div class="quote__box__text">
        lorem ipsum <span class="dots">...</span>
        <span class="more">Lorem ipsum</span>
        <button class="myBtn">Przeczytaj więcej</button>
    </div>
    
    <div class="quote__box__text">
        lorem ipsum <span class="dots">...</span>
        <span class="more">Lorem ipsum</span>
        <button class="myBtn">Przeczytaj więcej</button>
    </div>

    In that example, see how the CSS classes and structure drive the hiding and display of the elements.

    We could change the button text in a similar way if we want; I’ll leave that as an exercise for the reader. 🙂 (Hint: Use elements inline the button you show/hide.)

    More to explore:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search