Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript JavaScript and the DOM (Retiring) Traversing the DOM Sibling Traversal

I couldn't solve this javascript challenge can someone help me please

A delegated click event listener has been attached to the selected ul element, which is stored in the variable list. The handler is targeting each button in the list. When any one of the buttons is clicked, a class of highlight should be added to the paragraph element immediately preceding that button inside the parent list item element. Add the code to create this behavior on line 5.

app.js
const list = document.getElementsByTagName('ul')[0];

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    p.className('highlight');
  }
});
index.html
<!DOCTYPE html>
<html>
    <head>
        <title>JavaScript and the DOM</title>
    </head>
    <link rel="stylesheet" href="style.css" />
    <body>
        <section>
            <h1>Making a Webpage Interactive</h1>
            <p>Things to Learn</p>
            <ul>
                <li><p>Element Selection</p><button>Highlight</button></li>
                <li><p>Events</p><button>Highlight</button></li>
                <li><p>Event Listening</p><button>Highlight</button></li>
                <li><p>DOM Traversal</p><button>Highlight</button></li>
            </ul>
        </section>
        <script src="app.js"></script>
    </body>
</html>

3 Answers

Aakash Srivastav
seal-mask
.a{fill-rule:evenodd;}techdegree
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,625 Points

Hey arshia mohammadi , you are doing the right way .
You just need to define the p like this -

     let p = e.target.previousElementSibling;

Hence , you final code will look like this:

list.addEventListener('click', (e) => {
    if(e.target.tagName == 'BUTTON') {
      let p = e.target.previousElementSibling;
      p.className = "highlight";
    }
});

Now , this is just for your additional knowledge .
So , you can see , in the instruction , it's saying to add class. Now , className property
either returns the className of an element or set the className of an element .
So , suppose , the targeted element has any class already , then using className will override the previous class with new class or using another way , you need to use += to concatenate the classes . So , there is a better way to handle such situaltion intruduced in ES6 - the classList property.
Using classList property , the code will look something like this-

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
     let p = e.target.previousElementSibling;
     p.classList.add('hightLight');
  }
});

As an added advantage , using second method will also help you in removing any class like this-

element.classList.remove("otherclass");

So , I will prefer the second one , as it removes any of the sideffects of using className property .
Hope it helps. Thanks you :)

Aakash Srivastav I didn't understand why we have to use "previousElementSibling"?!

Aakash Srivastav
seal-mask
.a{fill-rule:evenodd;}techdegree
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,625 Points

Ok arshia mohammadi . Let's go step by step . According to instruction , we have to add a class of highlight to the <p> element of corresponding button element , when we click at that button. So , we can say , we have to add the class of highlight dynamically i,e every time , it should be added to different button and only when button is clicked.
Now , You have two ways -

  1. either save the refrences of all <p> element and use index to add the highlight . NOw using this approach , suppose you are clicking on third button then you have to find to which paragraph you will add highlight class .
    Also, what if there will be 20 buttons ? You have set if and else condition for each button . That's not a DRY programming and also , it's not a good approach .
  2. use previousSiblingElement to add the class dynamically.
    Thank You :)

the paragraph element immediately preceding that button

    let p = e.target.previousElementSibling;

a class of highlight should be added

    p.className = "highlight";
Carie Pigeon
Carie Pigeon
7,892 Points

These explainations make sense to me. But I'm wondering we it doesn't work if we doing it using something like this: let paragraph = event.target.parentNode; paragraph.className = 'highlight';

This was the first approach I tried and it did't work. Can anyone explain why it didn't work? Thanks!

From MDN previousElementSibling returns the Element immediately prior to the specified one in its parent's children list. In this case the paragraph element ex: <p>Element Selection</p>.

parentNode returns the parent. In this case the list element <li></li>

I have a workspace you can test to see the difference https://w.trhou.se/sfriqspmmk. Just comment/uncomment the obvious in app.js