【问题标题】:Javascript communicating cross-domain to parent window of iframeJavascript跨域与iframe的父窗口通信
【发布时间】:2013-03-13 00:14:44
【问题描述】:

我写了一个工具来做笔记,从网页上抓取图像。它通过使用 javascript 书签将自身加载为当前窗口中的 iFrame:

javascript:(function(){   _my_script=document.createElement('SCRIPT');   _my_script.type='text/javascript';   _my_script.src='http://basereality.test/js/bookmarklet.js?rand='+(Math.random());   document.getElementsByTagName('head')[0].appendChild(_my_script); })();

当用户单击关闭按钮时,我希望能够通过从父窗口中删除 iFrame 来关闭该工具。

执行此操作的最简单方法是什么 - 是否可以在其内部关闭 iFrame?

我尝试过使用跨域消息发布。我有从父窗口到子 iFrame 的跨域发布,但不能从 iFrame 到父窗口。

我目前的代码(大概包含问题)如下。

在父窗口中通过动态加载Javascript:

function    addiFrame(domain){
    var iframe_url = "http://" + domain + "/bookmarklet";

    var div = document.createElement("div");
    div.id = bookmarkletID;

    var str = "";

    iframe_url += "?description=" + encodeURIComponent(document.title);
    iframe_url += "&URL=" + encodeURIComponent(document.URL);

    str += "<div>";
    str += "<iframe frameborder='0' class='toolPanelPopup dragTarget' style='z-index: 1000'  name='bookmarklet_iframe' id='bookmarklet_iframe' src='" + iframe_url + "' width='550px' height='255px' style='textalign:right; backgroundColor: white;' />";

    str += "</div>";

    div.innerHTML = str;

    document.body.insertBefore(div, document.body.firstChild);
}


function jQueryLoadedCallback(){

    jQueryAlias = jQuery.noConflict();
    jQueryAlias('#' + bookmarkletID).bind('basereality.removeFrame', removeFrame);
}

function removeFrame(){
    alert("Calling remove frame");
    $("#" + bookmarkletID).remove();
}

在iFrame中,关闭iFrame的按钮调用:

function removeFrame(){
    var params = {};
    params.message = 'basereality.removeFrame';
    parent.postMessage(params, "*");
}

iFrame 中的 removeFrame 调用不会导致在父窗口中调用 removeFrame。

那么我应该如何实际删除 iFrame。

【问题讨论】:

  • 你不能把按钮放在 iframe 的外面吗?
  • 我可以,但我更愿意将它放在 iFrame 中,以便它与其他按钮并排放置。
  • 我有一个项目,我正在做一些类似于 Xymotech 的想法的事情,我将按钮放在 iframe 的外部,然后操纵按钮的 css 使其出现在 iframe 上。这对我来说是最快的解决方案。

标签: javascript iframe cross-domain


【解决方案1】:

postMessage 可能是您正在寻找的。 Mozilla 已经记录了这一点,并且它具有相当不错的跨浏览器支持:

https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

我还围绕这个概念编写了一个库,它可能需要一点调试,但它可以在 github 上找到:https://github.com/tsharp/OF.Core.js/blob/master/js/of/window.messaging.js

从这里开始,您需要父窗口上的事件侦听器来处理所有传入请求...这将从父上下文中删除 iframe。下面是注册消息接收事件的示例。

function registerWindowHandler() {
    if (typeof window.addEventListener !== 'undefined') {
    window.addEventListener('message', receiveMessage, false);
    } else {
    // Support for ie8
    window.attachEvent('onmessage', receiveMessage);
    }
}

【讨论】:

  • 嗨,特拉维斯,谢谢。我确实已经有 postMessage 了。我忘记做的是将事件侦听器添加到父框架。这就是为什么我从父母到孩子的帖子都有效,但反之则不行。