2013-02-25 86 views
6

我有一些JavaScript依赖于使用window.open和窗口间通信(其中新的'子窗口'communicates success/failure to the 'parent' window)。检测浏览器对窗口间通信的支持

这种(窗口间通信)在大多数情况下工作正常,但对于某些不支持窗口间通信的浏览器不起作用。例子包括Windows PhoneiPhone's UIWebView

我目前正在做客户端(基于javascript)user-agent sniffing来检测这些场景 - 并回退到不同的代码路径来解决该问题。

是否有替代用户代理嗅探,我可以使用?

要清楚,window.open的作品(工作意味着'它打开请求的网址')。什么不是可靠是使用window.opener和postMessage进行从'孩子'到'父母'的窗口间通信。

+0

孩子也可以访问window.opener属性 - 应该是null - 但不幸的是这不是一个可靠的检测技术。例如,如果直接打开子窗口(不使用父窗口中的window.open),那么即使子窗口实际上确实支持窗口间通信,window.opener也将为空。 – mjwills 2013-02-25 06:43:01

+0

我知道window.open会工作,但函数会返回子窗口ID吗? – Raptor 2013-02-25 06:49:56

+0

我不确定如何获得该信息将有所帮助。我想要的是在子窗口内部的特征检测,以确定它是否可以与其父对话。 window.open函数调用的返回值显然仅适用于父类 - 所以'它涉及到这个密封舱口的另一侧'。 所有这一切说,检查返回值在移动IE9中产生空,并在UIWebView中的窗口对象。并注意,在这两种情况下,新窗口加载正确(但将无法与其父母通信)。 – mjwills 2013-02-25 08:51:14

回答

2

在您的揭幕战窗口消息回调您可以发送回复给子窗口是这样的:

function yourMessageCallback(event) { 
    // your other handler stuff here... 
    event.source.postMessage('Yeah I got it', event.origin); 
} 

然后你就可以做在发送端,当回复到达,你可以清除一个计时器:

// do your postmessage here 

function notReceived() { 
    // do stuff if the message didn't go through 
} 

var messageTimer = setTimeout(notReceived, 500); // 500ms should be enough for everyone? 

window.addEventListener('message', function(event) { 
    // do necessary origin checks first etc... (not shown here) 

    if (event.data == 'Yeah I got it') { 
    clearTimeout(messageTimer); 
    // do stuff if the message went through 
    } 
}, false); 

我知道这可能是一个有点骇人听闻的解决方案,但可能不如用户代理嗅探?

+0

我担心我可能会误解你的建议@sactor。第一个代码块放在父窗口内,第二个代码块放在子窗口内?请记住,[父邮件消息将无法工作](http://stackoverflow.com/a/12265816/34092)。 – mjwills 2013-02-25 22:46:13

+0

或者你建议'只是尝试postMessage,如果我们没有得到'ack',那么我们知道它不起作用。这可能会起作用,但可能与我原来发布的第二条评论有同样的问题。因此,如果最终用户在浏览器中直接打开子窗口而不是父窗口打开,那么您的建议技术将无法检测是否支持帧间通信。 – mjwills 2013-02-25 22:56:00

+0

是的,我只是建议检查我们是否回复。我认为你的目标是检查你是否真的可以把消息传达给父母,而不是如果它在理论上是可能的(如果它不是以错误的方式打开的话)。为此我不幸有一个答案。 – sactor 2013-02-26 09:16:13