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 trialJuan Garcia
10,577 PointsJavascript 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?
9 Answers
Sean T. Unwin
28,690 PointsThe 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
10,577 PointsI just realized I was missing an extra "=". Thank you Sean :)
Alexander Fernandez
4,856 PointsSomehow 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
Courses Plus Student 2,670 PointsQuestion -- 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
7,969 Pointslist.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
7,969 Pointsor :
list.addEventListener('click', e => {
if( e.target.tagName === 'BUTTON') {
let p = e.target.previousElementSibling;
p.className = "highlight";
}
});
Thomas Matic
4,249 PointsThanks that makes sense
Marcell Ciszek
7,255 PointsThank you , this helped a lot John
Micah Doulos
17,663 PointsWhat worked for me, and is shorter than the other code answers here ( for better or worse ) :
event.target.previousElementSibling.className = 'highlight' ;
Alan McClenaghan
Full Stack JavaScript Techdegree Graduate 56,501 PointsExcellent 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
Rod Sanati
Full Stack JavaScript Techdegree Graduate 20,177 PointsThank you. Micah.
Michael Walker
45,428 PointsPretty sure it should be e.target instead of event.target as e was the argument variable used in the function.
yk2
8,550 Pointscan you explain in detail step by step the way you got the answer?
Manuela Sabatino
9,515 PointsThat 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
6,880 PointsWould 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?
Kazim Noori
12,911 PointsI 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
10,577 PointsSure.
<!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
10,577 PointsAlexander Fernandez, You forgot to add a semi-colon at the end of ''let p = e.target.previousElementSibling'' Hope this helps :)
Alexander Fernandez
4,856 PointsYeah, I realized moments after writing (lol). Thank you
Minh Le
Courses Plus Student 4,264 Pointslist.addEventListener('click', (e) => { if (e.target.tagName == 'BUTTON') { let li = event.target; let p = li.previousElementSibling; p.className = 'highlight'; }
Óscar Hernández sandoval
9,257 PointsHey, 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
9,257 PointsFirst 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
Greg Kaleka
39,021 PointsGreg Kaleka
39,021 PointsJuan, can you also include your HTML? Hard to tell what's wrong with just the JS.