0

So I am trying to make a more/less content toggle feature, it worked just fine until I started adding more boxes to be toggled. I read up on using multiple event handlers and the suggestion was to use document.getElementsByClassName(); and iterate through them, but the second button when clicked does not show/hide the correct content, only the first one.

Any help is appreciated. The simpler way would be to use jQuery or assign different IDs to the buttons and call the function on each one but I'm sure it must be possible to just create/call the event listener once and have it work on every subsequently added element.

Here is my code:

HTML

<div class="card">
  <div class="cardLessContent">
    <h1>Here is a card</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent auctor mi sollicitudin, tristique tortor eget, tempus elit. Vestibulum ante leo, aliquam ac dapibus at, auctor vitae ligula.</p>
  </div>
  <div id="cardMoreContent" class="cardMoreContent">
    <p> Nam finibus nec augue at semper. Quisque sit amet ex eu augue rutrum aliquet. Suspendisse dui enim, gravida quis turpis a, auctor pellentesque velit.</p>
  </div>
  <button id="toggleContent" class="toggleContent toggledOff">More</button>
</div>

<div class="card">
  <div class="cardLessContent">
    <h1>Here is a card</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent auctor mi sollicitudin, tristique tortor eget, tempus elit. Vestibulum ante leo, aliquam ac dapibus at, auctor vitae ligula.</p>
  </div>
  <div id="cardMoreContent" class="cardMoreContent">
    <p> Nam finibus nec augue at semper. Quisque sit amet ex eu augue rutrum aliquet. Suspendisse dui enim, gravida quis turpis a, auctor pellentesque velit.</p>
  </div>
  <button id="toggleContent" class="toggleContent toggledOff">More</button>
</div>

JavaScript

const btnToggleContent = document.getElementsByClassName("toggleContent");
const cardMoreContent = document.getElementById("cardMoreContent");

var toggleContent = function() {
    cardMoreContent.classList.toggle("showing");
    this.classList.toggle("toggledOff");

    if(this.classList.contains("toggledOff")) {
      this.innerHTML = "More";
    }
    else {
      this.innerHTML = "Less";
    }
}

for (var i = 0; i < btnToggleContent.length; i++) {
  btnToggleContent[i].addEventListener("click", toggleContent);
}

JSFiddle: https://jsfiddle.net/jw3qe9xf/6/

J. Daykin
  • 45
  • 5
  • 3
    you are using the same id (cardMoreContent) for multiple elements. an id is something unique you dont use the same id in multiple elements – Stakvino Aug 02 '18 at 11:34

3 Answers3

1

Id attribute should be unique in HTML.Otherwise it will only pick the first occurence of that Id.In your case you will always toggle the first cardMoreContent

Here is a simple solution for you by using event.target

Javascript

const btnToggleContent = document.getElementsByClassName("toggleContent");
const cardMoreContent = document.getElementById("cardMoreContent");

var toggleContent = function(e) {
    e.target.previousElementSibling.classList.toggle("showing");
    this.classList.toggle("toggledOff");

    if(this.classList.contains("toggledOff")) {
      this.innerHTML = "More";
    }
    else {
      this.innerHTML = "Less";
    }
}

for (var i = 0; i < btnToggleContent.length; i++) {
  btnToggleContent[i].addEventListener("click", toggleContent);
}

JSFiddle : https://jsfiddle.net/c1gdjk25/

Nuwan Attanayake
  • 1,161
  • 9
  • 20
0

Yes , works only for first. This is reason : you have multiply use ' id="toggleContent" ' same id value for more than one element it is wrong in basic.

Id attribute must be uniq !

Use example from this answer : How to get child element by class name?

You will need only childNodes and loop trow it.

Count on that you can search child from child element also ...

Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75
0

after you remove all ids attributes change your javascript code to :

const btnToggleContent = document.getElementsByClassName("toggleContent");

var toggleContent = function(e) {

/*e.target will get the clicked element which is the button clicked and parentElement 
gives you the parent element of this button which is the card you want to modify*/
    var card = e.target.parentElement;
    
/*when you have the card you can use on its getElementsByClassName to retreive all 
elements that have the class (cardMoreContent) in this case theres only one so you take
the first element from the array returned with [0]*/
    var cardMoreContent = card.getElementsByClassName("cardMoreContent")[0];
    
    //then rest of the code stays the same
    cardMoreContent.classList.toggle("showing");

    if(this.classList.contains("toggledOff")) {
      this.innerHTML = "More";
    }
    else {
      this.innerHTML = "Less";
    }
}



for (var i = 0; i < btnToggleContent.length; i++) {
  btnToggleContent[i].addEventListener("click", toggleContent);
}
Stakvino
  • 642
  • 4
  • 9