Reputation: 755
I know how to climb up and down the DOM using parentNode, children and id's, but I don't know how to access a sibling or child element by tag name alone.
This code example is a bit contrived, but I'm hoping you can use it to help me with a general answer to navigating using these element tag names.
//fluff to create an example
const outArr = Array(10).fill(0).map( (el, i) => { return (
'<p>Title ' + i + '</p>' +
'<p>Decription ' + i + '</p>' +
'<span>Other ' + i + '</span>' +
'<button>Click to Like' + i + '!</button>'
)});
const output = outArr.join(',');
document.getElementById('ex-container').innerHTML = output;
//targeting inside anon event function for simplicity
document.getElementById('ex-container').addEventListener('click', function(e) {
if (e.target.localName == 'button') {
const curEl = e.target
const parent = curEl.parentNode;
//I can access the parent node. If I had id's, I know I could targert
//children with those. How would I target the siblings, and from the
//parentNode target a specific child by element tagName, such as p?
console.log('curEl: ', curEl);
console.log('parent: ', parent);
}
e.stopPropagation();
});
<div id='ex-container'>
<!-- everything goes here -->
</div>
Bonus: how can I target the nearer p sibling by tag name?
Upvotes: 1
Views: 1684
Reputation: 43853
Added some properties to address the questions commented in source (couldn't understand question). Details are comment by /* */
in the Snippet.
SNIPPET
//fluff to create an example
const outArr = Array(10).fill(0).map((el, i) => {
return (
'<p>Title ' + i + '</p>' +
'<p>Decription ' + i + '</p>' +
'<span>Other ' + i + '</span>' +
'<button>Click to Like' + i + '!</button>'
)
});
const output = outArr.join(',');
document.getElementById('ex-container').innerHTML = output;
//targeting inside anon event function for simplicity
document.getElementById('ex-container').addEventListener('click', function(e) {
/* Compare the currentTarget to the target, this way it
|| will give you target to whatever you clicked not just a
|| button
*/
if (e.target !== e.currentTarget) {
const curEl = e.target
const parent = curEl.parentNode;
// How would I target the siblings,
var bigBro = curEl.previousElementSibling;
var lilBro = curEl.nextElementSibling;
/* Collect all children of parent */
var kids = parent.children;
// from the parentNode target a specific child by element tagName, such as p?
/* Same results for both with one difference being the
|| first one is "live" NodeList the other "static"
|| NodeList. 90% of the time, it's safer to go "static"
|| using querySelectorAll()
*/
var paragraphsByTag = parent.getElementsByTagName('p');
var paragraphsBySel = parent.querySelectorAll('p');
console.log('curEl: ', curEl);
console.log('parent: ', parent);
console.log('bigBro: ', bigBro);
console.log('lilBro: ', lilBro);
/* Add .length property to get total number */
console.log('Total Kids: ', kids.length);
/* NodeLists are array-like but not true arrays, so use
|| Array.from() to convert them into true arrays.
*/
console.log('Paragraphs are: ', Array.from(paragraphsBySel));
}
/* Specific by tagName is almost an oxymoron. If you
|| want to target a specific element but only have
|| tagNames, then as you commented, by index is the way
|| to go.
*/
console.log('The 6th paragraph is: ', Array.from(paragraphsBySel)[5]);
e.stopPropagation();
});
<div id='ex-container'>
<!-- everything goes here -->
</div>
Upvotes: 1
Reputation: 62743
Check out document.querySelector()
. You can use querySelector()
on a node to select child nodes by selector. Ex.
const parent = document.getElementById('someID')
const firstP = parent.querySelector('p:first-child')
parent
would ref the element with ID of someID
, and from there we can use querySelector
on parent
to select the first p
tag.
Here's a working example:
const parent = document.getElementById('someID')
const firstP = parent.querySelector('p:first-child')
firstP.style.color = 'red'
<div id="someOtherID">
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>Fourth</p>
</div>
<div id="someID">
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>Fourth</p>
</div>
You can use the related document.querySelectorAll()
to create an array of matching elements and do something along the lines you want, like this:
const parent = document.getElementById('someID')
const pees = parent.querySelectorAll('p')
parent.pees = Array.from(pees)
parent.pees[0].style.color = 'red'
<div id="someOtherID">
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>Fourth</p>
</div>
<div id="someID">
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>Fourth</p>
</div>
Upvotes: 1