How to Loop Through Selected Elements With Document.Queryselectorall

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 .links 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 of document.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