自 9 月 20 日 safari 11 更新以来 - 以下代码 (Javascript) 一次仅打开 1 个窗口(在 safari 10.1 上它会打开所有窗口)。
是否可以在 safari 11 中执行此操作,如果可以,如何操作?
我的代码(只是一个例子):
window.open("https://www.stackoverflow.com");
window.open("https://www.google.com");
window.open("https://www.youtube.com");
更新:
- 浏览器首选项设置为启用弹出窗口并且不阻止任何内容。
- 如果我在每个打开的窗口之间设置一个至少 0.5 秒的“setTimeout()”,代码就会工作——这可能是因为 safari 的新更新可能不想让我向用户“发送垃圾邮件”太多流行音乐打开 window 。
最佳答案
更新:这个问题和解决方案在 Safari 13 中仍然有效。
首先,这是我在测试中观察到的 Safari 11 的行为:
- 始终允许打开一个弹出窗口(即使选中了全局“阻止弹出窗口”设置)。选中“阻止弹出窗口”时,对弹出窗口的
window
对象的访问将受到限制(未选中“阻止弹出窗口”时则不然)。 - 如您所述,当“阻止弹出窗口”未选中时,必须延迟多个
window.open
调用(在我的测试中需要 >1s)。 - 选中“阻止弹出窗口”时,似乎只允许打开一个弹出窗口(尽管使用了延迟)。
因此,您发现了一种解决此问题的方法:添加延迟。
这是另一种方法,可以让您无需延迟地打开多个弹出窗口,利用当“阻止弹出窗口”未选中时,每个窗口可以立即打开一个弹出窗口的知识。考虑到示例中的三个弹出窗口,一般流程如下:
- 在您的域上打开一个弹出窗口(空白页)。
- 通过注入(inject)在加载时执行的脚本,将下一个弹出窗口的打开委托(delegate)给此弹出窗口。
- 将第一个弹出窗口重定向到您想要的 URL。
- 重复直到打开所有弹出窗口。
以下是我为处理此流程而构建的内容:
/**
* Handle the passed hrefs for Safari, which requires special/different
* handling than other browsers. Open each one in a new window (popup)
* and delegate the opening of the next popup to each new popup. Handle
* Safari's global popup blocker setting and inform the primary page
* (via postMessage) when the blocker is enabled, so a notification can
* be shown to the user.
*
* @param {Array} hrefs hrefs of popups to open
* @param {Function} safariPopupOpener Self reference. Required for
* injecting into next popup.
* @param {Window} primaryWindow Reference to the primary page
* Window object. Required for
* sending postMessage back.
* @param {string} blockedMessage Message body to send back in
* postMessage.
*/
var safariPopupOpener = function(
hrefs,
safariPopupOpener,
primaryWindow,
blockedMessage
) {
var newWindow = window.open('//url/of/the/blank/page/on/your/domain');
var popupOpenerScript = document.createElement('script');
// Must add these all to the popup's window object as the
// execution context of opener() below where they're used is the
// next popup, not the current window
newWindow.openAllResultHrefs = hrefs;
newWindow.openAllResultOpener = safariPopupOpener;
newWindow.primaryWindow = primaryWindow;
newWindow.blockedMessage = blockedMessage;
/**
* Logic to inject into the popup
*/
function opener() {
var hrefsCopy = window.openAllResultHrefs.slice();
// Delete the first item from the array for injecting into
// the next popup
hrefsCopy.shift();
if (hrefsCopy.length > 0) {
// Even when popups are blocked in Safari, one popup is
// always allowed to open. However any other popups
// opened sequentially are blocked. Also, access to the
// one popup's window object is restricted, so this
// tries to open the second popup, if window object is
// restricted (which occurs before another popup is
// opened), catches the resulting error, closes the
// first popup and sends a message back to the primary
// page that popups are blocked.
try {
window.openAllResultOpener(
hrefsCopy,
window.openAllResultOpener,
window.primaryWindow,
window.blockedMessage
);
} catch (e) {
// Optional: Send a message back to the primary page that
// popups have been blocked
window.primaryWindow.postMessage(
window.blockedMessage,
window.primaryWindow.origin
);
// Close the (first) popup window (first because
// we only reach this case when popups are blocked
// and we've only successfully opened one popup)
window.close();
}
}
// Redirect to the popup href
window.location.href = window.openAllResultHrefs[0];
}
// Inject the self-executing opener function so it'll run on load in
// the opened popup
popupOpenerScript.innerHTML = '(' + opener.toString() + '());';
newWindow.addEventListener('load', function() {
// Append the script to the new window's body
this.document.body.appendChild(popupOpenerScript);
});
}
- 请注意,我也在检测阻塞并将
postMessage
发送回主窗口,以便它可以处理阻塞(例如向用户显示消息)。因此,需要在主页上设置一个message
监听器。 postMessage
可能不是必需的,但当弹出窗口被阻止时我无法访问window.opener
。也可能有很大的改进空间,但我已经在这上面花了太多时间:-))
关于javascript - safari 11 打开多个弹窗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46381681/