【问题标题】:Close iframe cross domain关闭 iframe 跨域
【发布时间】:2011-01-12 00:39:06
【问题描述】:

我正在尝试在http://www.polyvore.com/cgi/clipper 处做类似于 Clipper 应用程序的事情

我可以让 iframe 出现在另一个网站(跨域)中。但我无法使“关闭”按钮起作用。

这是我用的,但它不适用于跨域(基本上删除了 iframe 元素)

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

你能帮忙吗?谢谢。

【问题讨论】:

    标签: javascript jquery html iframe cross-domain


    【解决方案1】:

    您应该使用一个对其进行抽象的库(例如 http://easyxdm.net/wp/ ,未经测试)。 Fragment ID 消息传递可能不适用于所有浏览器,有更好的方法,例如postMessage

    但是,您的示例 (Clipper) 使用了一个名为 fragment id messaging 的 hack。这可以是跨浏览器的,前提是包含您的 iframe 的页面是顶层。换句话说,总共有两个级别。基本上,孩子设置了父母的片段,父母对此进行监视。

    这与 Clipper 的方法类似:

    父.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:跨域和独立控制是不同的。我深入研究了(高度缩小/混淆的)Polyvore 代码,看看它是如何工作的(顺便说一下,它在 Firefox 中没有)。首先要记住,诸如 Clipper 之类的小书签在它们启动时存在于打开的页面的上下文中。在这种情况下,小书签会加载 a script ,然后运行一个生成 an iframe 的 init 函数,但也会运行:

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

    如果您深入了解 addListener,您会发现 (beautified):

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

    取消包括:

    removeNode(iframe);
    

    现在,剩下的唯一部分是 iframe page 使用 ClipperForm.init 函数加载 another script,其中包括:

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

    所以我们清楚地看到他们正在使用片段 ID 消息传递。

    【讨论】:

    • 这太复杂了,超出了我的需要。我只需要关闭 iframe。有什么简单的方法吗?如果没有,你能举例说明这个是如何做到的吗?谢谢
    • 我无法控制父文档。这就是为什么我说“跨域”。就像 Polyvore 示例一样,它们也不能控制父级,但它们仍然可以关闭 iframe。奇怪!
    • 正如我上面刚刚解释的那样,它们/do/ 控制父级,并且/are/ 使用片段 ID 消息传递。
    • 我不认为这个答案是正确的 - 所描述的方法仍然被大多数浏览器阻止,包括谷歌浏览器。您应该首先使用跨域消息传递(如此处所述 - stackoverflow.com/questions/17798618/…),然后您显示的方法可以用作旧浏览器的备份。
    • @Matthew,我认为您的编辑很好,并清楚表明这不是一个完美的答案,但仍然很有用。我已经删除了我的反对票!欢呼
    【解决方案2】:

    尝试隐藏 iframe 的内容,不要担心实际上会删除父级中的 iframe 元素。

    【讨论】:

    • 如何隐藏?我收到此错误xxx.com> 的权限被拒绝以从 yyyy.com> 获取属性 Window.document。所以基本上我找不到用 iframe 做任何事情的方法
    • 我猜如果你在 iframe 里面的东西上设置 document.style.visibility = none (或者你可以隐藏所有的 iframe 内容),你最终还是会得到一个大的白色方块?在这种情况下,您可能确实需要一些 Matthew Flaschen 建议的跨框架通信机制。在注入 iframe 本身的同时,也注入脚本来处理通信的一侧;并且在 iframe 中加载的页面具有处理另一端的脚本。
    【解决方案3】:

    旧的哈希黑客还有另一种实现。它是向后兼容的,简单的仅限 javascript,并且非常容易实现:

    http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/

    【讨论】:

      猜你喜欢
      • 2012-05-04
      • 2019-07-24
      • 2012-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 2017-05-09
      相关资源
      最近更新 更多