<iframe> javascript access parent DOM across domains?
Solution 1
Hate to say it but I'm like 99% sure that ain't happening directly because of security.
You can try it out here.
bhh
Solution 2
It is possible.
You were right to mention postMessage in your edits. For those looking, there is a great backwards-compatible, javascript-only way to communicate across domains. Short, easy code as well. Perfect solution? As long as you can request modifications to the parent and the child:
http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/
Solution 3
Yes you can.
You can implement window.postMessage to communicate accross iframes and/or windows across domains.
But you need to do it in an asynchronous way.
If you need it synchronously, you need to implement wrappers around those asynchronous methods.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
<!--
<link rel="shortcut icon" href="/favicon.ico">
<link rel="start" href="http://benalman.com/" title="Home">
<link rel="stylesheet" type="text/css" href="/code/php/multi_file.php?m=benalman_css">
<script type="text/javascript" src="/js/mt.js"></script>
-->
<script type="text/javascript">
// What browsers support the window.postMessage call now?
// IE8 does not allow postMessage across windows/tabs
// FF3+, IE8+, Chrome, Safari(5?), Opera10+
function SendMessage()
{
var win = document.getElementById("ifrmChild").contentWindow;
// http://robertnyman.com/2010/03/18/postmessage-in-html5-to-send-messages-between-windows-and-iframes/
// http://stackoverflow.com/questions/16072902/dom-exception-12-for-window-postmessage
// Specify origin. Should be a domain or a wildcard "*"
if (win == null || !window['postMessage'])
alert("oh crap");
else
win.postMessage("hello", "*");
//alert("lol");
}
function ReceiveMessage(evt) {
var message;
//if (evt.origin !== "http://robertnyman.com")
if (false) {
message = 'You ("' + evt.origin + '") are not worthy';
}
else {
message = 'I got "' + evt.data + '" from "' + evt.origin + '"';
}
var ta = document.getElementById("taRecvMessage");
if (ta == null)
alert(message);
else
document.getElementById("taRecvMessage").innerHTML = message;
//evt.source.postMessage("thanks, got it ;)", event.origin);
} // End Function ReceiveMessage
if (!window['postMessage'])
alert("oh crap");
else {
if (window.addEventListener) {
//alert("standards-compliant");
// For standards-compliant web browsers (ie9+)
window.addEventListener("message", ReceiveMessage, false);
}
else {
//alert("not standards-compliant (ie8)");
window.attachEvent("onmessage", ReceiveMessage);
}
}
</script>
</head>
<body>
<iframe id="ifrmChild" src="child.htm" frameborder="0" width="500" height="200" ></iframe>
<br />
<input type="button" value="Test" onclick="SendMessage();" />
</body>
</html>
Child.htm
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
<!--
<link rel="shortcut icon" href="/favicon.ico">
<link rel="start" href="http://benalman.com/" title="Home">
<link rel="stylesheet" type="text/css" href="/code/php/multi_file.php?m=benalman_css">
<script type="text/javascript" src="/js/mt.js"></script>
-->
<script type="text/javascript">
/*
// Opera 9 supports document.postMessage()
// document is wrong
window.addEventListener("message", function (e) {
//document.getElementById("test").textContent = ;
alert(
e.domain + " said: " + e.data
);
}, false);
*/
// https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
// http://ejohn.org/blog/cross-window-messaging/
// http://benalman.com/projects/jquery-postmessage-plugin/
// http://benalman.com/code/projects/jquery-postmessage/docs/files/jquery-ba-postmessage-js.html
// .data – A string holding the message passed from the other window.
// .domain (origin?) – The domain name of the window that sent the message.
// .uri – The full URI for the window that sent the message.
// .source – A reference to the window object of the window that sent the message.
function ReceiveMessage(evt) {
var message;
//if (evt.origin !== "http://robertnyman.com")
if(false)
{
message = 'You ("' + evt.origin + '") are not worthy';
}
else
{
message = 'I got "' + evt.data + '" from "' + evt.origin + '"';
}
//alert(evt.source.location.href)
var ta = document.getElementById("taRecvMessage");
if(ta == null)
alert(message);
else
document.getElementById("taRecvMessage").innerHTML = message;
// http://javascript.info/tutorial/cross-window-messaging-with-postmessage
//evt.source.postMessage("thanks, got it", evt.origin);
evt.source.postMessage("thanks, got it", "*");
} // End Function ReceiveMessage
if (!window['postMessage'])
alert("oh crap");
else {
if (window.addEventListener) {
//alert("standards-compliant");
// For standards-compliant web browsers (ie9+)
window.addEventListener("message", ReceiveMessage, false);
}
else {
//alert("not standards-compliant (ie8)");
window.attachEvent("onmessage", ReceiveMessage);
}
}
</script>
</head>
<body style="background-color: gray;">
<h1>Test</h1>
<textarea id="taRecvMessage" rows="20" cols="20" ></textarea>
</body>
</html>
Here, you would modify the child to send postmessages to parent. e.g. in child.htm, you do
window.parent.postMessage("alert(document.location.href); document.location.href = 'http://www.google.com/ncr'", "*");
and in parent, you do (in receiveMessage) eval(evt.data);
Not that using eval is insecure, so you would instead pass an enum, and call the corresponding function that you need to put on the parent page.
aaaidan
I'm a Kiwi living in The Bay Area with my wife and son. Technical adventures have included React, Figma, ES6, SASS/LESS/CSS, Hypertalk, THREE.js, ActionScript 3, PHP, Java, MySQL, C#, Kotlin, Knockout.js, Web Audio API.
Updated on July 09, 2022Comments
-
aaaidan almost 2 years
I control the content of an iframe which is embedded in a page from another domain. Is there any way for javascript in my iframe to make changes to the parent's DOM?
For example, I would like to have my iframed script add a bunch of html elements to the parent DOM. This seems like a pretty tall order - thoughts?
Edit: There exists a technique called "Fragment ID Messaging" which might be a way to communicate between cross-domain iframes.
Edit: Also, Firefox 3.5, Opera, Chrome (etc) seem to be adopting the html5 "postMessage" api, which allows secure, cross-domain data transmission between frames, iframes and popups. It works like an event system. IE8 supports this feature, apparently, which is perhaps a little surprising.
Summary: No, you can't directly access/edit the DOM of a page from another domain. But you can communicate with it, and it can co-operate to make the changes you want.
-
aaaidan over 14 yearsThanks, that link demonstrates the problem very well.
-
aaaidan over 14 yearsThanks for your answer, warpech. I think my edits confused my original question though, which was asking how I can alter the dom on a parent page from within an iframe from another domain. The short answer seems to be "you can't". So I'm now exploring inter-frame communication methods, and a server-side proxy is certainly one of those. Thanks!
-
Hayden Crocker over 10 yearsWhat you can do is have an iframe back to the parent domain from the child domain and any scripts there can access parent.parent because it's on the same domain, this is used by a few advertising companies who will ask you to host a file (the inner iframe) on your site in order to allow them to resize the adds.
-
lmiguelmh about 8 yearsThe loading of the child iframe is not going to work in a mixed-mode environment. For example, the main page in https and the child page in an iframe (http).
-
Marco Panichi over 6 yearsPlease read the answer of @Stefan Steiger below. You can communicate between cross origin frames using postMessage(). Of course, you have to own both domains.
-
Stefan Steiger almost 6 years@lmiguelmh: A http page should not load in an https page in the first place.