首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >postMessage源IFrame

postMessage源IFrame
EN

Stack Overflow用户
提问于 2013-03-11 09:01:12
回答 6查看 19.4K关注 0票数 22

我在一个跨域iframe的网站上工作,它使用postMessage调整到正确的高度。我遇到的唯一问题是识别哪个iframe有哪个高度。我目前设置的方法是,当一个iframe将其高度发送给父iframe时,所有iframe的高度都会改变。

父级:

代码语言:javascript
复制
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

eventer(messageEvent, function(e) {
    $('iframe').height(e.data);
}, false);

Iframe:

代码语言:javascript
复制
var updateHeight = function() {
    if(window.parent) {
        window.parent.postMessage($('.widget').outerHeight(), '*');
    }
};

有没有办法确定是哪个iframe发送了message事件?

EN

回答 6

Stack Overflow用户

发布于 2013-12-05 23:38:41

是的,您可以识别执行postMessage的IFRAME。有不同的情况:

  • 源IFRAME与接收消息的窗口具有同源URL(例如http://example.com/):IFRAME使用

HTML源IFRAME与父myIFRAME.contentWindow == event.source

  • the页面有一个同源但相对的URL(例如/myApp/myPage.html):

myIFRAME.contentWindow == event.source.parent

  • the源IFRAME具有与接收消息的页面(例如http://example.org/)不同的跨域URL (例如http://example.com/):以上方法不起作用(比较总是false,访问event.source的属性会导致Access Denied错误),IFRAME必须根据其原始域进行识别;

myIFRAME.src.indexOf(event.origin)==0

为了管理这三种不同的情况,我使用了以下方法:

代码语言:javascript
复制
var sourceFrame = null; // this is the IFRAME which send the postMessage
var myFrames = document.getElementsByTagName("IFRAME");
var eventSource = event.source; // event is the event raised by the postMessage
var eventOrigin = event.origin; // origin domain, e.g. http://example.com

// detect the source for IFRAMEs with same-origin URL
for (var i=0; i<myFrames.length; i++) {
    var f = myFrames[i];
    if (f.contentWindow==eventSource || // for absolute URLs
        f.contentWindow==eventSource.parent) { // for relative URLs
        sourceFrame = f;
        break;
    }
}

// detect the source for IFRAMEs with cross-origin URL (because accessing/comparing event.source properties is not allowed for cross-origin URL)
if (sourceFrame==null) {
    for (var i=0; i<myFrames.length; i++) {
        if (myFrames[i].src.indexOf(eventOrigin)==0) {
            sourceFrame = myFrames[i];
            break;
        }
    }
}

对于跨域URL,请注意,如果event.origin是多个IFRAMEs的公共域,则我们无法区分真正的源。

有些人使用===而不是==,但我在这个上下文中没有发现任何区别,所以我使用最短的比较器。

此实现已经过测试,并在以下环境下工作:

  • MSIE 9
  • Firefox 17

作为替代方案(由Griffin建议),您可以使用带有唯一标识符(例如时间戳)的IFRAME src,并且IFRAME的web应用程序将在发布的消息中返回此唯一标识符。虽然IFRAME标识会更简单,但这种方法需要修改IFRAME的web应用程序(这并不总是可能的)。这也可能导致安全问题(例如,IFRAME的web应用程序试图猜测其他IFRAME应用程序的唯一标识符)。

票数 23
EN

Stack Overflow用户

发布于 2013-08-16 14:51:23

我已经在这里找到了解决方案:How to share a data between a window and a frame in JavaScript

父级:

代码语言:javascript
复制
var frames = document.getElementsByTagName('iframe');
for (var i = 0; i < frames.length; i++) {
    if (frames[i].contentWindow === event.source) {
        $(frames[i]).height(event.data); //the height sent from iframe
        break;
    }
}
票数 20
EN

Stack Overflow用户

发布于 2015-03-10 08:49:43

我有一个解决这个问题的想法。在创建iframe时,为iframe指定一个名称/id。。

并且,在iframe内的脚本中,将消息作为对象发送,如下所示

代码语言:javascript
复制
window.parent.postMessage({"height" : $('.widget').outerHeight(), "frmname" : window.name}, '*');

在父监听程序中,

代码语言:javascript
复制
eventer(messageEvent, function(e) {`enter code here`
    $(e.data.frmname).height(e.data.height);
}, false);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15329710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档