Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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

Dan Warren
Dan Warren
9,125 Points

What am I missing?

I think my mistake is in how I'm trying to add a class name to the previous p element, I keep getting the message "One or more of the buttons is not affecting their previous paragraph element." Any ideas what I'm missing?

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

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    let li = event.target.parentNode;
    let prevLi = li.previousElementSibling;
    let ul = li.parentNode;
    if (prevLi) {
      let p = document.getElementById('p');
      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>

2 Answers

Gergely Bocz
Gergely Bocz
14,244 Points

Hi Dan!

There are problems with your selections! I added some styling and console logs to your code, so you can see what you are selecting on each click. Here's the code:

var list = document.getElementsByTagName('ul')[0];

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    let li = event.target.parentNode;
    li.style.backgroundColor = 'red';
    console.log(li);

    let prevLi = li.previousElementSibling;
    prevLi.style.backgroundColor = 'blue';
    console.log(prevLi);

    let ul = li.parentNode;
    ul.style.backgroundColor = 'green';
    console.log(ul);

    let p = document.getElementsByTagName('p')[0];
    p.className += "highlight";
    console.log(p);
  }
});

Notice, that i rewrote your selection of the p tag, as originally it was trying to select based on id, instead of tagname. Here you can see, that the p tag selected by this code isn't even the right p tag! It is absolutely the first in whole page, and not relatively the first before the selected button!

To select relatively to the button that is being clicked, you don't even have to select the li element (as it would be a parent, and not a sibling) or any of the others. Just target the button's sibling, with button.previousElementSibling, this should be the p tag that you have to give the class of 'highlight' to.

Hope i could clear things up for you; if you are still stuggling, let me know and ill try to explain my solution!

Good luck!

Dan Warren
Dan Warren
9,125 Points

Ok I copied in the parts of your code and it's starting to work the way I need it to but I keep getting this error message:

TypeError: 'null' is not an object (evaluating 'prevLi.style')

I know it's recognizing prevLi because I'm getting the blue background when I click a button, but why is it also not recognizing prevLi as an object in my code?

var list = document.getElementsByTagName('ul')[0];

list.addEventListener('click', function(e) { if (e.target.tagName == 'BUTTON') { let li = event.target.parentNode; let prevLi = li.previousElementSibling; prevLi.style.backgroundColor = 'blue'; let ul = li.parentNode; let p = document.getElementsByTagName('p')[0]; p.className += "highlight"; console.log(p); } });

Also, I couldn't figure out how to use the 'button.previousElementSibling' because it was telling me 'button' was not declared as a variable and I wasn't sure how to declare it so it functions the way I want it to. Maybe that's the part I'm missing to put it all together?

Gergely Bocz
Gergely Bocz
14,244 Points

The error comes from trying to select a previous element when there is no parent element. It happens with the first li item. It is the first child of the ul element, so it doesn't have a previous sibling.

As for the button, you don't even have to declare it! Just do what you did and use the event target, or if you find it easier, you can declare it inside the if like so:

const targetButton =  e.target;

If you call the previousElementSibling on this button, then you get the paragraph proceeding the clicked button. Then add the class of 'highlight' to it, with something like:

targetParagraph.className += 'highlight';

Now you are all set!

Also a reminder, that you should use the same name for the function parameter name [e] and what you are targeting [event]. In the if conditinal, you used [e], and when you declared li, you used [event]. Some older browsers may not recognize the event because of this.