Reputation: 187
In "demo" div I want to show getAttribute id and style of all elements (in this case two elements demone and demotwo). If I remove the loop then only the first elements id and style are displayed and everything works normally. As soon as I add the loop stops working, where I'm wrong.
function myFunction() {
var divs = document.querySelectorAll('*'),
i;
for (i = 0; i < divs.length; ++i) {
var div = divs[i];
var id = document.getElementById(div).getAttribute("id");
var sty = document.getElementById(div).getAttribute("style");
document.getElementById("demo").innerHTML = "Id element: " + id + " Style element: " + sty + "";
}
}
<div id="demoone" style="width:50px;height:60px;">One</div>
<div id="demotwo" style="width:30px;height:40px;">Two</div>
<button onclick="myFunction()">Try it</button>
<div id="demo"></div>
Upvotes: 0
Views: 1600
Reputation: 65863
The main problem is that you are using the loop index to isolate a div
element and then using the actual div
element as the argument that you pass to getElementById()
. To get an element by its id
you must pass a string that matches the actual id
attribute used in the HTML.
But, there is a simpler way that doesn't involve knowing the id
of any element. Instead of a counting loop, loop over the array of elements you find with the Array.forEach()
method. This avoids having to maintain a counter. Also, if you intend to only look at div
elements, change your selector from *
to div
.
Also, at the end when you are writing your results to your demo
element, you are setting the .innerHTML
with =
. This will cause any previous value to be thrown out, so you won't get a report of all the elements, you'd just wind up seeing the information from the last element that the loop went over. Instead, use +=
, which concatenates the new value onto the last value. Also, never update .innerHTML
in a loop as it will cause the DOM to update many times and that will cause many repaints and reflows, which can be expensive. Instead, build up a string as you move through the loop and when the loop is done, update your element, just once with that string.
Finally, it's not a good practice to set up events via HTML attributes (onclick
). Instead, separate your JavaScript from your HTML and do the event handling with .addEventListener()
.
<div id="demoone" style="width:50px;height:60px;">One</div>
<div id="demotwo" style="width:30px;height:40px;">Two</div>
<button>Try it</button>
<div id="demo"></div>
<script>
// Do event handling the modern way, not with inline HTML:
document.querySelector("button").addEventListener("click", myFunction);
function myFunction() {
// Get reference to the output element
let output = document.getElementById("demo");
// Get all the elements and convert the collection into an Array
var divs = Array.prototype.slice.call(document.querySelectorAll('div'));
// Loop over the array
let results = "";
divs.forEach(function(div){
results += "<br>Id element: " + div.id + " Style element: " + div.getAttribute("style") + "";
});
output.innerHTML = results; // Inject string into the element
}
</script>
Upvotes: 0
Reputation: 782653
querySelectorAll()
doesn't return IDs, it returns the elements themselves. So you don't need to call getElementById()
before getting the attribute.
If you want to see the info for all the elements, you need to append the message to the DIV's HTML, not overwrite it each time through the loop.
function myFunction() {
var divs = document.querySelectorAll('*'),
i;
document.getElementById("demo").innerHTML = ''; // start with empty DIV
for (i = 0; i < divs.length; ++i) {
var div = divs[i];
var id = div.getAttribute("id");
var sty = div.getAttribute("style");
document.getElementById("demo").innerHTML += "Id element: " + id + " Style element: " + sty + "<br>";
}
}
<div id="demoone" style="width:50px;height:60px;">One</div>
<div id="demotwo" style="width:30px;height:40px;">Two</div>
<button onclick="myFunction()">Try it</button>
<div id="demo"></div>
Upvotes: 0