How to loop through selected elements with document.querySelectorAll
for in
loop is not recommended for arrays and array-like objects - you see why. There can be more than just number-indexed items, for example the length
property or some methods, but for in
will loop through all of them. Use either
for (var i = 0, len = checkboxes.length; i < len; i++) {
//work with checkboxes[i]
}
or
for (var i = 0, element; element = checkboxes[i]; i++) {
//work with element
}
The second way can't be used if some elements in array can be falsy (not your case), but can be more readable because you don't need to use []
notation everywhere.
How to loop through elements inside a foreach()
You could get the .link
s per box like below:
const box = document.querySelectorAll('.box');
box.forEach((singleBox) => {
let boxLinks = singleBox.querySelectorAll('.link');
singleBox.addEventListener("mouseenter", () => {
boxLinks.forEach(boxLink => {
boxLink.classList.add('top');
});
});
singleBox.addEventListener("mouseleave", () => {
boxLinks.forEach(boxLink => {
boxLink.classList.remove('top');
});
});
});
.box {
position: relative;
width: 30rem;
height: 25rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
transition: all 1s ease-out;
}
.img-holder {
background: #fff;
width: 18rem;
height: 18.8rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
justify-content: center;
align-items: center;
}
.link {
position: absolute;
width: 200px;
height: 200px;
background-color: transparent;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -35;
}
.top {
z-index: 35;
cursor: pointer;
transition: all .5s ease-in;
background-color: red; // Changing he bg-color just for visualizing whats going on //
}
/* first box I'm looping through (using foreach) */
<div class="box">
<a href="#" class="link"></a> /* first link */
<div class="img-holder">
<img src="" alt="image">
<img src="" alt="another image">
</div>
</div>
/* second box I'm looping through (using foreach) */
<div class="box">
<a href="#" class="link"></a> /* second link */
<div class="img-holder">
<img src="" alt="image">
<img src="" alt="another image">
</div>
</div>
Iterate through multiple elements of querySelectorAll with forEach
You are currently adding a keydown
event listener to each audio
tag. However, the audio
tag is hidden, so you can't execute the keydown
event on it. Thus, your code will not work.
Add the event listener to the document instead.
document.addEventListener('keydown', function(e) {
const ss = document.querySelector(`audio[data-key="${e.keyCode}"]`);
console.log(ss);
ss.play();
})
<audio class="audioz" data-key="65" src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"></audio> press the A key
How can I loop through ALL DOM elements on a page?
You can pass a *
to getElementsByTagName()
so that it will return all elements in a page:
var all = document.getElementsByTagName("*");
for (var i=0, max=all.length; i < max; i++) {
// Do something with the element here
}
Note that you could use querySelectorAll()
, if it's available (IE9+, CSS in IE8), to just find elements with a particular class.
if (document.querySelectorAll)
var clsElements = document.querySelectorAll(".mySpeshalClass");
else
// loop through all elements instead
This would certainly speed up matters for modern browsers.
Browsers now support foreach on NodeList. This means you can directly loop the elements instead of writing your own for loop.
document.querySelectorAll('*').forEach(function(node) {
// Do whatever you want with the node object.
});
Performance note - Do your best to scope what you're looking for by using a specific selector. A universal selector can return lots of nodes depending on the complexity of the page. Also, consider using
document.body.querySelectorAll
instead ofdocument.querySelectorAll
when you don’t care about<head>
children.
Using querySelectorAll inside a for-in-loop
Replace
elements[i].style.setProperty("display", "none");
with
elements[i].style.display = "none";
As the HTMLElement.style
property returns a CSSStyleDeclaration
object that represents the element's inline styles as properties, i.e. style.property = 'value'
And use a regular for loop when iterating over array-like objects that has a length, like nodeLists
var elements = document.querySelectorAll("div");
for ( var i=0; i<elements.length; i++) {
elements[i].style.display = "none";
}
How to add all selected elements into an array and iterate through it?
You can do this using querySelectorAll
with selector .parent_1 > div
to get all direct div
inside .parent_1
then use forEach
and cloneNode
to add them to .parent_2
.
Demo:
var divs = document.querySelectorAll('.parent_1 > div');var parent_2 = document.querySelector('.parent_2');divs.forEach((div) => { parent_2.appendChild(div.cloneNode(true));})
<div class="parent_1"> <div> <div></div> </div> <div></div> <div></div></div>
<div class="parent_2"> <!-- add here --></div>
Loop through more querySelectorAll matches
You return
from your function prior to doing anything with any element other than the first one returned from querySelectorAll
. In addition, replace
does not modify the string, it returns a new copy. Thus, the count you are returning is that of wordCountTemp[i].innerHTML.split(" ").length
.
Your original code: (with comments)
function() {
var wordCounts;
var wordCountTemp = document.querySelectorAll("#text-block-10, #text-block-12");
var i;
for(i = 0; i < wordCountTemp.length; i++){
wordCounts = wordCountTemp[i].innerHTML;
wordCounts.replace(/(^\s*)|(\s*$)/gi,""); //Has no effect
wordCounts.replace(/[ ]{2,}/gi," "); //Has no effect
wordCounts.replace(/\n /,"\n"); //Has no effect
//This next line returns your result in the first pass through the loop.
// Only the first element returned by querySelectorAll is acted upon.
// No other element is processed other than the first one.
return wordCounts.split(" ").length;
}
}
Note: I am changing innerHTML
to textContent
. I'm assuming that you only want to count the words which are text (i.e. not HTML code, scripts, etc.). I also changed the variable name wordCountTemp
to nodeList
as that is more descriptive of what it is (it is, in fact, a NodeList)
To use a similar structure to what you are already using:
function countWords() {
var wordCounts;
var totalWordCount=0;
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
wordCounts = nodeList[i].textContent;
wordCounts = wordCounts.replace(/(^\s*)|(\s*$)/gi,"");
wordCounts = wordCounts.replace(/[ ]{2,}/gi," ");
wordCounts = wordCounts.replace(/\n /,"\n");
totalWordCount += wordCounts.split(" ").length;
}
return totalWordCount; //return the total count after all passes through loop
}
Instead of assigning your result of each replace
to wordCounts
over and over again to progressively modify it, you could just directly act on the new string returned by replace
:
function countWords() {
var totalWordCount=0;
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
totalWordCount += nodeList[i].textContent
.replace(/(^\s*)|(\s*$)/gi,"")
.replace(/[ ]{2,}/gi," ")
.replace(/\n /,"\n")
.split(" ").length;
}
return totalWordCount; //return the total count after all passes through loop
}
Using regular expressions is, relatively, expensive. not really that much, but there is no reason not to optimize in this situation. Instead of performing all of the replace
functions for each element, it is more efficient to, within the loop, concatenate the strings returned by textContent
. Then, after you have one big long string with all the text from all the elements, you can perform the replace
and split
actions once.
function countWords() {
var allText='';
var nodeList = document.querySelectorAll("#text-block-10, #text-block-12");
for(var i = 0; i < nodeList.length; i++){
allText += ' ' + nodeList[i].textContent;
}
//return the total count after getting the textContent from all elements
return allText.replace(/(^\s*)|(\s*$)/gi,"")
.replace(/[ ]{2,}/gi," ")
.replace(/\n /,"\n")
.split(" ").length;
}
Note: All of the above assume that none of the elements returned by the querySelectorAll
are children of other elements which are returned. If they are, you will be counting the same text twice.
How to loop through children of querySelectorAll matches
because you have used i
variable in both loop so loop key length 2
reset due to children DOM element have 2 length, you should another variable like j
in inner loop then work fine
var allElements = document.querySelectorAll("[class]");for (var i = 0; i < allElements.length; i++) { var element = allElements[i];
for (var j = 0; j < element.children.length; j++) { var child = element.children[i]; console.log(child) }
element.style.color = "red";}
<div class="test1"> <div>Child 1</div> <div>Child 2</div></div>
<div class="test2"> <div>Child 3</div> <div>Child 4</div></div>
<div class="test2"> <div>Child 3</div> <div>Child 4</div></div>
How to Loop Through Elements Ending with a number
You can use a class instead and then loop through the input
and check if value is non empty
const inputs = document.querySelectorAll('.ipt');
for (const ipt of inputs) {
if (ipt.value !== "") {
console.log(ipt.value);
}
}
<input class="ipt" id="phone1" type="text" value="1111111111">
<input class="ipt" id="phone2" type="text" value="">
<input class="ipt" id="phone3" type="text" value="3333333333">
<input class="ipt" id="phone4" type="text" value="4444444444">
<input class="ipt" id="phone5" type="text" value="">
Related Topics
Why Is Using Onclick() in HTML a Bad Practice
How to Check Whether a Checkbox Is Checked in Jquery
JavaScript Code to Stop Form Submission
Retrieve the Position (X,Y) of an HTML Element
Why Isn't My JavaScript Working in Jsfiddle
Html5 Form Required Attribute. Set Custom Validation Message
Frame Buster Buster ... Buster Code Needed
Check If Checkbox Is Checked With Jquery
How to Escape HTML Special Chars in JavaScript
Get Cursor Position (In Characters) Within a Text Input Field
Capture HTML Canvas as Gif/Jpg/Png/Pdf
Communication Between Tabs or Windows
Why Calling Setstate Method Doesn't Mutate the State Immediately
Why Can't I Call a Function Named Clear from an Onclick Attribute