Reputation: 3474
Basically I have an iframe loaded that is accessed from the parent whenever it trigger the onload event. It works fine but I'm getting errors when the contents of the iframe are no longer on the same domain, which is to be expected.
Only thing is, I'd like to suppress these errors. Unfortunately a try/catch doesn't catch this exception and trying to access any of these properties to validate them produces the same error again, thus defeating the purpose.
Is there a reliable way for me to simply check if the iframe contents are accessible without producing any error messages?
Thanks
Edit:
For the sake of context and not having people answer with irrelevant comments; I am writing a small script that auto resizes the iframe on the parent page based on the height of the iframes document. When a user clicks a link inside the iframe that points outside the domain I obviously won't be able to detect the height of the page, but I'd prefer not to trigger any errors in the console and instead handle the exception gracefully.
I am aware that there are workarounds available, I am simply trying to educate myself by figuring out if there is a graceful way to handle these kinds of cases, rather than just resorting to an ugly workaround.
Upvotes: 12
Views: 8809
Reputation: 1200
The jQuery approach can also be done with regular JS:
function iframe_accessible(theiframe) {
var thedoc, debug=true;
try{
thedoc = (theiframe.contentWindow || theiframe.contentDocument);
if (thedoc.document)
thedoc = thedoc.document;
if (debug)
console.log('Accessible');
return true;
}
catch(err) {
if (debug)
console.log("Not accessible because of\n" + err);
return false;
}
}
var elm = document.querySelector('iframe'); // If it exists, of course
console.log(iframe_accessible(elm));
Upvotes: 1
Reputation: 111
Try this:
var $frame = $("#frameId"); // swap with the id of the iframe
try {
var canAccess = $frame.contents();
if(!!canAccess) {
// same domain yay you have access
// do your thing here
}
}
catch( e ) {
// bummer can't do much with it
return false;
}
EDIT: add a try and catch, no error will return false.
Upvotes: 4
Reputation: 2849
If you can add a little JavaScript to all of the pages from your domain you'd like to load in the iframe you could use window.postMessage
, which is exempt from the Same Origin Policy. Probably the simplest way would be to have the child window post a message to the parent when it loads and use that instead of onload
. For example, you could add this to each page:
if (window.parent) document.addEventListener( 'load', function() {
window.parent.postMessage( "child loaded", "/" );
}, false );
That will post a message to the parent window whenever the page is loaded in a frame with the same origin. You would then listen for it like this:
var iframe = document.getElementById( 'your-iframe' );
var origin = window.location.protocol + '://' + window.location.host;
if (window.location.port != 80) origin += ':' + window.location.port;
window.addEventListener( 'message', function (event) {
if (event.source != iframe.contentWindow
|| event.origin != origin || event.data != "child loaded")
return;
// do here what you used to do on the iframe's load event
}, false );
Note that the examples use the W3C/Netscape event API and thus won't work in Internet Explorer before version 9.
Upvotes: 5
Reputation:
How about not rendering IFRAME at all (within parent page) if its href is not pointing to the same protocol and host as the parent page? I'm possibly misunderstanding things related to whether you own both sites, or only one of them (and which one). But if you own the parent-page site, you should be able to do this, whether on the server (before IFRAME is even included), or at some point on the client (page-load/doc-load).
Upvotes: 0
Reputation: 982
could you tell me how you set the iframe's src?
if you use javascript to change it dynamiclly,your problem is easy to be handle with.
var isXdm = false;
function setSrc(id,src){
//detect whether src is cross domain then set the variable isXdm
...
}
even so,i do not think it is a good way to solve this.
hope anyone could find a better solution.
Upvotes: 0
Reputation: 8540
Ok this is overkill, not much but a hack and maybe not possible in your situation but anyway :
You could add a javascript inclusion in all the pages from your site that tries to access the opener(the parent frame) and set a flag(a variable like bool stillOnMySite) to true.
Then
Time based : The script in your website pages sets the flag every second to true, the script in your parent iframe sets the flag every second to false. Poll the iframe in a setTimeOut(xxx,1). If the flag is not true again, then the user left your site and you shouldn't poll the iframe if the flag is true, the user is still on your website you can poll the iframe.
Click based : Using jquery for unobtrusive javascript, the script in your website pages monitors clickevents in all the links in the page. If a link is going outside your domain, this sets the flag in the parent iframe to false.
Of course this all theory crumbles to pieces if you can't add script in your website pages.
Alternatively, I just thought : If your iframe always start on your website, no need to modify your website pages, simply inject the n°2 solution from the parent iframe into the iframed page.
Upvotes: 0
Reputation: 6441
Can't you access the src
attribute from the parent?
As I understand it, the iframe
element belongs to the 'parent' page, whereas the window
object contained with the iframe belongs to the 'child' page.
This works for me:
<html>
<head>
</head>
<body>
<iframe id="ifr" name="ifr" src="http://www.example.com"></iframe>
<input type="button" onclick="showSrc()" value="showSrc" />
<input type="button" onclick="showHref()" value="showHref" />
<script>
var ifr = document.getElementById('ifr');
function showSrc() {
// no warning
alert(ifr.src);
}
function showHref() {
// warning
alert(window.frames['ifr'].contentWindow.location.href);
}
</script>
</body>
</html>
Upvotes: 0