JavaScript

Stephanie Roberts
Stephanie Roberts
801 Points

How do I add and remove a class on multiple parent elements?

Hey

I have setup in my HTML several team members that all have a description about them with a 'read more' button - when you click on this it should reveal more of the description.. However my javascript is only working for the first one and not the rest? Does anyeone know what I am doing wrong? I am looping over the buttons...

Here is my code

var readMoreEl = document.body.querySelectorAll('[data-action="readMore"]');

for (var i = 0; i < readMoreEl.length; i++) {

readMoreEl[i].addEventListener('click', function(event) {

    parentEl = document.body.querySelector('.teamMember .hold');

    if (parentEl.classList.contains('show')) {

        parentEl.classList.remove('show');

    } else {

        parentEl.classList.add('show');
    }
});

}

Dave StSomeWhere
Dave StSomeWhere
19,768 Points

Probably something do with the event.target. Could you post the relevant html and css?

2 Answers

Eric Butler
Eric Butler
31,888 Points

Looks like the problem is this line:

parentEl = document.body.querySelector('.teamMember .hold');

... because querySelector always and only selects the first element that matches those classes.

If you are sure that the count of .teamMember .hold DOM elements will always match up with the count of [data-action="readMore"] DOM elements, you could simply change that line to:

var parentEl = document.body.querySelectorAll('.teamMember .hold')[i];
// don't forget to add "var" here so the variable is scoped to this function instead of bleeding into the global scope!

...but fair warning, that's overly fragile code, since it relies on the coincidence of those 2 counts being the same. It would be better to use the this keyword somehow to connect the specific button clicked with the parent or sibling element you want to manipulate. Without seeing your HTML, I'm guessing here, but it could be something like:

var parentEl = this.parentElement.querySelector('.hold');

This code takes whatever the clicked-on element was, finds its specific parent element (I'm assuming that's the .teamMember container), then finds its first child element with a class="hold" attribute. Since, in this case, you're scoping the .querySelector to the parentElement, it will only look within that branch of the DOM tree for that element, not across the whole document (<html> tag).

I hope this makes sense to you and helps you understand DOM traversal a little better!

Stephanie Roberts
Stephanie Roberts
801 Points

Thanks so much! That worked!

Seth Kroger
MOD
Seth Kroger
Treehouse Moderator 56,204 Points

I think the issue is when you select parentEl with document.querySelector it's selecting the first element with those two classes, not the parent element for the button. You need a way to distinguish those from each other, or a different way of selecting the element, so the click handler can show the right one.