Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Close iframe cross domain

I am trying to do something similar to the Clipper application here http://www.polyvore.com/cgi/clipper

I can make the iframe appear in another website (cross domain). But I cannot make the "close" button to work.

This is what I used but it doesn't work for cross domain (basically remove the iframe element)

window.parent.document.getElementById('someId').parentNode.removeChild(window.parent.document.getElementById('someId'));    

Can you help? Thanks.

like image 726
HP. Avatar asked Feb 02 '10 05:02

HP.


People also ask

How do I close an iframe?

display = 'block'; } }); On the iframe side of things, this could now be triggered by the following script: parent. postMessage('close-iframe', PRODUCT_CONFIGURATOR_URL);

Is iframe cross domain?

A cross domain inline frame (iframe) is a type of web technology that can be used to embed a small portion of one website within a larger "parent" page hosted on a different domain.

How do I get cross domain iframe content?

To access cross-domain iframe, the best approach is to use Javascript's postMessage() method. This method provides a way to securely pass messages across domains.

How do I turn off iframe parent window?

window. close(); or this: top. window. close(); you should be able to close it.


2 Answers

You should use a library that abstracts this (e.g. http://easyxdm.net/wp/ , not tested). Fragment ID messaging may not work in all browsers, and there are better approaches, such as postMessage.

However, your example (Clipper) is using a hack called fragment id messaging. This can be cross-browser, provided the page containing your iframe is the top level. In other words, there are a total of two levels. Basically, the child sets the fragment of the parent, and the parent watches for this.

This is a similar approach to Clipper's:

parent.html

<html>
<head>
<script type="text/javascript">
function checkForClose()
{
    if(window.location.hash == "#close_child")
    {
      var someIframe = document.getElementById("someId");
      someIframe.parentNode.removeChild(someIframe);
    }
    else
    {
      setTimeout(checkForClose, 1000)
    }
}
setTimeout(checkForClose, 1000);
</script>
</head>
<body>
<iframe name="someId" id="someId" src="child.html" height="800" width="600">foo</iframe>
</body>
</html>

child.html:

<html>
<head>
<script type="text/javascript">
setTimeout(function(){window.parent.location.hash = "close_child";}, 5000);
</script>
<body style="background-color: blue"></body>
</html>

EDIT2: Cross-domain and independently controlled are different. I dug into the (heavily minified/obfuscated) Polyvore code to see how it works (incidentally, it doesn't in Firefox). First remember that bookmarklets, such as the Clipper, live in the context of the page open when they start. In this case, the bookmarklet loads a script , which in turn runs an init function which generates an iframe, but also runs:

Event.addListener(Event.XFRAME, "done", cancel);

If you digg into addListener, you'll find (beautified):

if (_1ce2 == Event.XFRAME) {
                        if (!_1cb3) {
                            _1cb3 = new Monitor(function () {
                                return window.location.hash;
                            },
                            100);
                            Event.addListener(_1cb3, "change", onHashChange);
                        }
                    } 

cancel includes:

removeNode(iframe);

Now, the only remaining piece is that the iframe page loads another script with a ClipperForm.init function that includes:

Event.addListener($("close"), "click", function () {
            Event.postMessage(window.parent, _228d, "done");
        });

So we see clearly they are using fragment ID messaging.

like image 68
Matthew Flaschen Avatar answered Oct 04 '22 11:10

Matthew Flaschen


Try hiding the contents of the iframe, and don't worry about actually getting rid of the iframe element in the parent.

like image 38
Bruce Avatar answered Oct 04 '22 12:10

Bruce