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

Juan Garcia
Juan Garcia
10,577 Points

Javascript and the DOM sibling traversal

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.

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

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    if(e.target.className == 'highlight'){
      let li = e.target.parentNode;
      let p = li.previousElementSibling;
      let ul = li.parentNode;
      if (p) {
        ul.insertBefore(p, li);
      }
    }
  }
});

What am I doing wrong here?

Greg Kaleka
Greg Kaleka
39,021 Points

Juan, can you also include your HTML? Hard to tell what's wrong with just the JS.

9 Answers

Sean T. Unwin
Sean T. Unwin
28,690 Points

The second if statement is looking for a className when one is not set on the Button.

Perhaps you are looking for the text of the button? If that's the case then use textContent instead of className: if(e.target.textContent === 'highlight'). Notice the lowercase "highlight", to account for this we can use toLowerCase() on the textContent so that we don't have have to care about the case of the button text -- if(e.target.textContent.toLowerCase() === 'highlight').

Within the body of that second if statement, the line, let p = li.previousElementSibling;, should be let p = e.target.previousElementSibling; so that you are selecting the previous paragraph tag of the clicked button.

Finally, the line, ul.insertBefore(p, li);, should be ul.classList.add('highlight'); if your goal is to add a class of .highlight to the paragraph.

The working code would be:

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

list.addEventListener('click', function(e) {
  if (e.target.tagName === 'BUTTON') {
    if(e.target.textContent.toLowerCase() === 'highlight') {
      let li = e.target.parentNode; // Can be removed; not needed
      let p = e.target.previousElementSibling;
      let ul = li.parentNode; // Can be removed; not needed
      if (p.tagName === 'P') { // Just to be safe that we are highlighting a paragraph tag
        p.classList.add('highlight');
      }
    }
  }
});

As an added tip, it is considered best practice to use strict comparison operators, which means using 3 equals signs ( === ) as opposed to equality operators ( == ). Strict comparison will match the value as well as the type. Learn more at MDN.

Great start and attempt! Keep at it. :-)

Juan Garcia
Juan Garcia
10,577 Points

I just realized I was missing an extra "=". Thank you Sean :)

Alexander Fernandez
Alexander Fernandez
4,856 Points

Somehow it doesnt accept my code as a possible answer, I believe it is one possible asnwer.

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.

list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    let p = e.target.previousElementSibling
    p.className += " highlight";
  }
});
Paul Janson
Paul Janson
Courses Plus Student 2,670 Points

Question -- why did you include both .tagName and .textContent? It seems redundant, and in fact when .textContent line was removed it still passed. Wondering if there's a 'just to be safe' reason as with inclusion of p.tagName.

John Baldwin
John Baldwin
7,969 Points
list.addEventListener('click', function(e) {
  if (e.target.tagName == 'BUTTON') {
    let p = e.target.previousElementSibling
    p.className = "highlight";
  }
});

this was the way I tackled it...

John Baldwin
John Baldwin
7,969 Points

or :

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

Thanks that makes sense

Marcell Ciszek
Marcell Ciszek
7,255 Points

Thank you , this helped a lot John

Micah Doulos
Micah Doulos
17,663 Points

What worked for me, and is shorter than the other code answers here ( for better or worse ) :

event.target.previousElementSibling.className = 'highlight' ;
Alan McClenaghan
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alan McClenaghan
Full Stack JavaScript Techdegree Graduate 56,501 Points

Excellent work Micah. The answers above using variables are just complicating things for me. I had the previousElementSibling.className = 'highlight' but the event.target was eluding me. Seems obvious now that I see it. Thanks

Michael Walker
Michael Walker
45,428 Points

Pretty sure it should be e.target instead of event.target as e was the argument variable used in the function.

yk2
yk2
8,550 Points

can you explain in detail step by step the way you got the answer?

Manuela Sabatino
Manuela Sabatino
9,515 Points

That is my answer:

list.addEventListener('click', (e) => {
    if(e.target.tagName == 'BUTTON') {
      let li = e.target.parentNode;
      let p = e.target.previousElementSibling;
      p.className = "highlight";
    }
});
Libor Gess
Libor Gess
6,880 Points

Would you please explain to me this line of code: let p = e.target.previousElementSibling; How the e.target know what was preview ??? Because you did not use any another reference of the li var. It is because of the previousElementSibling?

I did like below and it worked:

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

list.addEventListener('click', function(e) { if (e.target.tagName === 'BUTTON') { if(e.target.textContent.toLowerCase() === 'highlight') { let li = e.target.parentNode; // Can be removed; not needed let p = e.target.previousElementSibling; let ul = li.parentNode; // Can be removed; not needed if (p.tagName === 'P') { // Just to be safe that we are highlighting a paragraph tag p.classList.add('highlight'); } } } });

Juan Garcia
Juan Garcia
10,577 Points

Sure.

<!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>
Juan Garcia
Juan Garcia
10,577 Points

Alexander Fernandez, You forgot to add a semi-colon at the end of ''let p = e.target.previousElementSibling'' Hope this helps :)

Alexander Fernandez
Alexander Fernandez
4,856 Points

Yeah, I realized moments after writing (lol). Thank you

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

Óscar Hernández sandoval
Óscar Hernández sandoval
9,257 Points

Hey, took me the whole Sunday, but I did it here my code:

const list = document.getElementsByTagName('p')[0];

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

Óscar Hernández sandoval
Óscar Hernández sandoval
9,257 Points

First I calle the 'p' Tag I created an eventlister using and the ' li.addEventListener ' elements by click function, and using if as e.target.TagName ==button conditioning if you clicked add the p tag as simbing. See some examples :

https://www.digitalocean.com/community/tutorials/how-to-traverse-the-dom