我的工作与被调整到使用的postMessage正确的高度跨域iFrame的网站上。 我遇到的唯一问题是确定哪个iframe具有高度。 我目前得到它成立的方式是,当一个IFRAME将其高度与父,所有的I帧的身高被改变。
家长:
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:
var updateHeight = function() {
if(window.parent) {
window.parent.postMessage($('.widget').outerHeight(), '*');
}
};
有没有一些方法来确定哪些iframe中发送的message
的事件吗?
我发现从这里的解决方案: 如何将一个窗口和一个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;
}
}
是的,你可以找出哪些做了该IFRAME postMessage
。 有不同的情况:
源IFRAME具有相同的来源的URL(例如http://example.com/
),其接收消息的窗口:所述IFRAME使用识别
myIFRAME.contentWindow == event.source
源IFRAME具有相同来源,但相对URL(如/myApp/myPage.html
)父HTML页面:在IFRAME使用标识
myIFRAME.contentWindow == event.source.parent
源IFRAME具有横源URL(例如http://example.com/
)不同,其接收的消息(例如在网页的http://example.org/
):上述方法不工作(比较是总是false
和访问的性质event.source
导致Access Denied
错误)和IFRAME必须根据其来源域鉴定;
myIFRAME.src.indexOf(event.origin)==0
为了管理这三种不同的情况下,我使用了以下内容:
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;
}
}
}
对于跨网域网址,请注意,如果我们不能区分真实来源event.origin
是不止一个IFRAME中常见的域。
有些人用===
代替==
但我没有发现在这方面有什么区别,所以我用最短的比较。
这种实现已通过测试并下工作:
作为替代方案(由格里芬的建议),你可以使用一个IFRAME SRC具有独特idenfitier(如时间戳),以及IFRAME'd Web应用程序将在发布的消息发回的这个唯一的标识符。 虽然IFRAME识别会更简单,这种方法需要修改IFRAME'd Web应用程序(这并不总是可能的)。 这也可能会导致安全问题(如IFRAME'd Web应用程序试图猜测其他的IFRAME应用程序的唯一标识符)。
我有一个想法来解决这个问题。 当您创建的iframe赋予一个名字/ id来的iframe。 。
并且,在内部的iframe的脚本发送消息的对象,看起来像
window.parent.postMessage({"height" : $('.widget').outerHeight(), "frmname" : window.name}, '*');
在父母的倾听者,
eventer(messageEvent, function(e) {`enter code here`
$(e.data.frmname).height(e.data.height);
}, false);
如果源的iframe嵌套在多个父iframe中,那么你就需要递归在每个iframe的window.frames财产和比较反对的MessageEvent#源属性。
例如,如果通过该Dom。的#IFRAME Level3的生成的消息。
<iframe Id=level1>
<iframe Id=level2>
<iframe Id=level3 />
</iframe>
</iframe>
您应该能够找到祖先iframe的指数使用当前窗口。
FindMe = event.source
FrameIndex = find(window)
frames[FrameIndex].frameElement == getElByTagName(iframe)[FrameIndex]
function find(target){
for (i=0; I< target.frames.length; i ++)
if(target.frames[i] == FindMe || find(target.frames[i]))
return i
return false
}
它需要注意的是
该Window.frames财产不受跨域策略限制
不管这种技术将工作源iframe的情况如何深度嵌套是
window.frames是窗口对象不是IFRAME元素的集合。
访问window.frames收集的承包商,客人的propetties s被同源resttictred(即你可能无法访问window.frames的frameElement或位置属性[I]
我跨域了以下工作:
window.addEventListener('message', function (event) {
if (event.data.size) {
Array.prototype.forEach.call(document.getElementsByTagName('iframe'), function (element) {
if (element.contentWindow === event.source) {
element.style.height = `${event.data.size.height}px`;
}
});
}
}, false);
经测试,在铬64和Firefox 59。
本次活动还应该有一个属性的“源”,它可以比I帧“contentWindow”属性。