12

I have a page with a large iframe that contains a majority of the content. The user interacts with the website by clicking around within the iframe. The functionality I'm trying to build is: When a user navigates away from my site, I do them a favor and bust out of the iframe.

The iframe has an onload event which is fired every time a new page is loaded, cross-domain or not.

<iframe id="testframe" src="http://mysite.com" onload="testframe_loaded()"></iframe>

Each time the event is fired, I'm looking for some way to:

A) Detect when the user navigates to a different domain

B) Bust out of the iframe.

I suspect that B isn't possible, since browsers don't give access to

document.getElementById("testframe").contentDocument.location.href

when the iframe is cross-domain. I'm also not sure whether or not A is possible.

If anybody has ideas as to how to accomplish this, or is positive that it can't be done, I'd appreciate the advice.

Thanks

rook
  • 66,304
  • 38
  • 162
  • 239
Emmett
  • 14,035
  • 12
  • 56
  • 81

3 Answers3

8

You can do A, since if you get a security error (which you can catch), that's means they're cross-domain :) Then you can resize the iframe to be the whole page. But I think you're right you can't actually bust out, without explicit cooperation from the other domain.

EDIT: You're right you don't need to poll. Here's the basic code:

<html>
<head>
<title>Cross-domain frame test</title>
<!-- http://stackoverflow.com/questions/2365822/detect-when-iframe-is-cross-domain-then-bust-out-of-it/2365853#2365853 -->
<script type="text/javascript">
function checkForCross()
{
  var iframe = document.getElementById("myFrame");
  try
  {
    var loc = iframe.contentDocument.location.href;
  } catch(e)
  {
    iframe.setAttribute("style", "border: 0; margin: 0; padding: 0; height: 100%; width: 100%;");
  }
}
</script>
</head>
<body>
<iframe name="myFrame" id="myFrame" src="child.html" style="height: 50%; width: 50%;" onload="checkForCross()"></iframe>
</body>
</html>
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 1
    I'll test the try/catch approach.. I always forget that JavaScript supports that :) Polling isn't necessary though, since I can just test it each time the iframe's onload event is fired. – Emmett Mar 02 '10 at 19:07
  • This definitely works and demonstrates that A is possible. Unfortunately B still seems impossible -- expanding the iframe works, but it's still wonky because the url in the browser's location bar won't match the site being displayed. I'll try to play around a bit with solutions involving modifying the the links that the other answers suggest, e.g. attaching a click handler to every link that checks if the href attribute is cross-domain. – Emmett Mar 02 '10 at 20:35
  • Emmett, the click handler works, but only for /your/ links, not links within the iframe. – Matthew Flaschen Mar 02 '10 at 20:48
  • 2
    As far as I can tell, the try/catch block doesn't prevent an error from appearing in Chrome or Safari's error console. Anyone know how to do A in those browsers? – JW. Aug 26 '11 at 14:59
  • 3
    the error isn't catch-able (at least on chrome). Execution continues but access to any cross-domain variable is returned as undefined. See my answer below for a code example. – NSjonas Jul 30 '12 at 20:23
2

set the 'target' attribute on external links to '_top'.

kennebec
  • 102,654
  • 32
  • 106
  • 127
1

This works for chrome at least (not tester on other browsers)

   if(parent.location.host != undefined){ 
       alert("hello world!");
    }else{
       throw "cannot access parent!";
    }

It will still throw the "unsafe javascript attempt" warning, but this doesn't stop code execution. Instead the variable is returned as undefined.

NSjonas
  • 10,693
  • 9
  • 66
  • 92