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
Zoltan Lederer
10,722 PointsDOM Sibling Traversal
Hello,
I was doing a challenge under the Javascript and the DOM course.
I could solved the challenge, but I was testing to solve it in different ways.
The challenge task is the following:
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.
My first working solution is:
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let p = e.target.previousElementSibling;
p.className = 'highlight'; }
});
The second solution is:
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let li = e.target.parentNode;
let p = li.querySelector('p');
console.log(p);
p.className = 'highlight';
}
});
In the third which is not working, I wanted to use the getElementsByTagName('p') method:
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let li = e.target.parentNode;
let p = li.getElementsByTagName('p');
console.log(p);
p.className = 'highlight';
}
});
Could someone explain me why I cannot use the getElementsByTagName('p') method here?
5 Answers
Steven Parker
243,266 PointsIt's because getElementsByTagName returns a collection, not a single element.
Just like when you established list on the top line, you need to add an index to select a single element from the collection.
To format posted code, use the instructions from the Markdown Cheatsheet pop-up found below the "Add an Answer" area. Or watch this video on code formatting.
Zoltan Lederer
10,722 PointsThank you, I understand now. I also made some research about the HTMLcollection and it makes sense.
Chris Carr
Front End Web Development Techdegree Student 12,900 PointsIt should be a one line solution on line 5.
e.target.previousElementSibling.className = 'highlight';
Chris Carr
Front End Web Development Techdegree Student 12,900 PointsShaqib, it's always a good thing to redo the courses if you don't fully understand them. If the videos are not concise enough then check the teacher's notes. Google the term too and watch Youtube videos.
Justin Hicks
14,290 PointsThis was a huge help for me. I was on the right track but I had a dumb rookie syntax problem. This is what I had.
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let pTag = e.target.previousSibling;
pTag.className (highlight);
}
});
After trying various ways and reading for an hour I finally read this and Made the switch to this which works perfectly!!
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let pTag = e.target.previousSibling;
pTag.className = 'highlight';
}
});
Jonathon Irizarry
9,154 PointsHow is the code in the second solution to the op working if you are using console.log(p); before the node's class attribute is set like so: p.className = 'highlight'; ? I thought it would only return the element <p>lorem ipsum</p> since the <p> element is modified after the console.log() method, but instead when I click a button in the console it returns <p class="highlight">lorem ipsum</p>. I guess I'm wondering how the p.className = 'highlight'; is being hoisted above the console.log(p); when it is being called before the function even adds the class to it. Here is the code (HTML and JS):
<!DOCTYPE html>
<html>
<head>
<title>JavaScript and the DOM</title>
</head>
<body>
<section>
<h1>Making a Webpage Interactive</h1>
<p>Things to Learn</p>
<ul>
<li><p>Lorem Ipsum</p><button>Highlight</button></li>
<li><p>Lorem Ipsum</p><button>Highlight</button></li>
<li><p>Lorem Ipsum</p><button>Highlight</button></li>
<li><p>Lorem Ipsum</p><button>Highlight</button></li>
</ul>
</section>
<script src="app.js"></script>
</body>
</html>
/*jshint esversion: 6 */
const list = document.getElementsByTagName('ul')[0];
list.addEventListener('click', function(e) {
if (e.target.tagName == 'BUTTON') {
let li = e.target.parentNode;
let p = li.querySelector('p');
console.log(p);
p.className = 'highlight';
}
});
Saqib Ishfaq
13,912 PointsSaqib Ishfaq
13,912 Pointsafter seeing this and copying it i was able to complete the challenge! otherwise i had no idea what m i doin :( does it mean i need to go back and retake the whole chapter of node,child ,parent,previous,next sibling :/ as i am still confused a bit abt the whole concept! any advice peeps would help a great deal1 i am stil beginner i guess after reaching here............ or may be i have to take different approach towards it! do i need to start techdegree or some sort to get a better understanding of it??? thanks in advance