I want to add a CSS styling class to all instances of a selective set of elements: for example, all p elements as well as all h4 elements.
I define two JS variables which get all elements of the aforementioned tags, and insert them into an array, so that I can make a function which, in theory, should apply the selected class to all instances of the selected elements/tags.
However, when I run the code, it seems that the function assigns the class only to the first item of the array.
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
.italic { font-style: italic; }
</style>
</head>
<body>
<h4>Text goes in here</h4>
<p>Text goes in here</p>
<script>
function styleTxt() {
let h4Elems = document.getElementsByTagName("H4");
let pElems = document.getElementsByTagName("P");
const elemArray = [pElems, h4Elems];
for (eachElem in elemArray) {
let elemInsts = elemArray[eachElem];
for (eachInst in elemInsts) {
let givenInst = elemInsts[eachInst];
givenInst.classList.add("italic");
}
}
}
styleTxt();
</script>
</body>
</html>
If I invert the order of the element tags inside the array, then the h4 element will get the .italic class but the p element will not.
Perhaps it is not possible to use the "document" directive twice? Is there an alternative method to automatically add the same class to a set of multiple (but not all) html tags?
CodePudding user response:
You are looping through each property of the HTMLCollection, including properties like length
, causing givenInst
to be a number. Since it has no classList
property, calling add
on undefined
creates an error and terminates the loop.
To solve this, you can use isNaN
to check whether the property is a number or not:
However, a better way is to use a for...of
loop instead:
CodePudding user response:
You might want to prefer the for...of loop for this and make use of the spread operator. It will produce a much nicer code output:
function styleTxt() {
let h4Elems = document.getElementsByTagName("H4");
let pElems = document.getElementsByTagName("P");
const elemArray = [...pElems, ...h4Elems];
for (eachElem of elemArray) {
eachElem.classList.add("italic");
}
}
Of course, you can always pick both types of elements in one go with the querySelectorAll
method:
const all = document.querySelectorAll("h4, p");
// Using the for...of loop:
for ( el of all ){
el.classList.add("italic");
}
// Using the `forEach` method:
all.forEach( el => el.classList.add("italic") )
CodePudding user response:
Use Document.querySelectorAll()
to get both types of elements. Iterate the NodeList
with NodeList.forEach()
, and add the class to each element.
function styleTxt() {
document.querySelectorAll('h4, p')
.forEach(el => el.classList.add('italic'));
}
styleTxt();
.italic {
font-style: italic;
}
<h4>Text goes in here</h4>
<p>Text goes in here</p>
CodePudding user response:
Give this a try instead
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
.italic {
font-style: italic;
}
</style>
</head>
<body>
<h4>Text goes in here</h4>
<p>Text goes in here</p>
<script>
function styleTxt() {
const h4Elems = Array.from(document.getElementsByTagName("H4"));
const pElems = Array.from(document.getElementsByTagName("P"));
const elemArray = [...pElems, ...h4Elems];
elemArray.forEach(eachElem => {
eachElem.classList.add("italic");
})
}
styleTxt();
</script>
</body>
</html>