javascript - safari 11 打开多个弹窗

标签 javascript safari

自 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");

更新:

  1. 浏览器首选项设置为启用弹出窗口并且不阻止任何内容。
  2. 如果我在每个打开的窗口之间设置一个至少 0.5 秒的“setTimeout()”,代码就会工作——这可能是因为 safari 的新更新可能不想让我向用户“发送垃圾邮件”太多流行音乐打开 window 。

最佳答案

更新:这个问题和解决方案在 Safari 13 中仍然有效。

首先,这是我在测试中观察到的 Safari 11 的行为:

  • 始终允许打开一个弹出窗口(即使选中了全局“阻止弹出窗口”设置)。选中“阻止弹出窗口”时,对弹出窗口的 window 对象的访问将受到限制(未选中“阻止弹出窗口”时则不然)。
  • 如您所述,当“阻止弹出窗口”未选中时,必须延迟多个 window.open 调用(在我的测试中需要 >1s)。
  • 选中“阻止弹出窗口”时,似乎只允许打开一个弹出窗口(尽管使用了延迟)。

因此,您发现了一种解决此问题的方法:添加延迟。

这是另一种方法,可以让您无需延迟地打开多个弹出窗口,利用当“阻止弹出窗口”未选中时,每个窗口可以立即打开一个弹出窗口的知识。考虑到示例中的三个弹出窗口,一般流程如下:

  1. 在您的域上打开一个弹出窗口(空白页)。
  2. 通过注入(inject)在加载时执行的脚本,将下一个弹出窗口的打开委托(delegate)给此弹出窗口。
  3. 将第一个弹出窗口重定向到您想要的 URL。
  4. 重复直到打开所有弹出窗口。

以下是我为处理此流程而构建的内容:

/**
 * 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/

相关文章:

javascript - 编辑 HighChart 后如何计算其点的总和

javascript - 通过第三方库登录 Meteor

Javascript 循环遍历包含逗号分隔值的数组键

javascript - 如何在 Safari 6 (Mountain Lion) 中查看 JavaScript 错误消息

javascript - Jssor jQuery 在 safari 上没有响应

javascript - getByteFrequencyData 不适用于 Safari 中的实时流

javascript - 正则表达式后向 : Invalid regular expression:/(? <=\.)\S+$/: 无效组

javascript - 添加 jquery 不显眼的 ajax 脚本文件 Controller 操作运行两次

iphone - 是否可以以编程方式更改 iOS Safari 设置

html - Safari Mobile 和对象位置属性