I've got a parent HTML file that contains multiple iframes that are hosted at the same domain. Now I would like to loop though all iframes and change their visual appearing by adding CSS styles with plain javascript to them:
<!DOCTYPE html>
<html>
<head>
<title>
Altering CSS in iframe
</title>
</head>
<body>
<h1>Parent HTML</h1>
<iframe id="frameID1" name="frameID1" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #1</p>
</body>
</html>
"></iframe>
<iframe id="frameID2" name="frameID2" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #2</p>
</body>
</html>
"></iframe>
<iframe id="frameID3" name="frameID3" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #3</p>
</body>
</html>
"></iframe>
<script>
var iframes = document.getElementsByTagName("iframe");
for (var i = 0; i < iframes.length; i ) {
iframes.item(i).addEventListener("load", function() {
var node = document.createElement('style');
node.appendChild(document.createTextNode('body { background: red; }'));
window.frames[i].document.head.appendChild(node)
})
}
</script>
</body>
</html>
But the loop in the javascript code doesn't work. I've set up a fiddle, where I changed window.frames[i].document.head.appendChild(node)
to window.frames[i-2].document.head.appendChild(node)
which shows an effect, but only changes the style in ONE iframe instead in all iframes:
https://jsfiddle.net/5a8bdynm/
What di I have to alter in order to effect all iframes?
CodePudding user response:
You're using var
to define your index i in the for
loop. So, your index is a global variable.
But your event (load) is asynchronous (1), so when the first iframe loads, the index has already the value of 3. In this case, window.frames[i]
will ALWAYS refer to the window.frames[3]
that doesn't even exist.
If you replace var
with let
, each loop cycle will receive its own separate index value and window.frames[i]
will refer to the proper iframe.
const iframes = document.getElementsByTagName("iframe")
for (let i = 0; i < iframes.length; i ) { // your code}
In general, you should AVOID using var
.
Prefer let
and const
as a best practice.
(1) EDIT: BTW, the asyncronous nature of the load event isn't that relevant in this case as the code is part of an event handler; so, no matter what the event is, it will be anyway executed AFTER the loop ends (and then, after the global index variable got the value of 3)