在safari 11中打开多个弹出窗口

时间:2017-09-23 16:13:41

标签: 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. 如果我设置" setTimeout()"该代码有效。在每个窗口打开至少0.5秒之间 - 这可能是因为Safari的新更新可能不想让我"垃圾邮件"弹出窗口太多的用户。

1 个答案:

答案 0 :(得分:2)

首先,我从测试中观察到了Safari 11的行为:

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

所以,你已经发现了解决这个问题的一种方法:添加延迟。

这是另一种允许您打开多个弹出窗口而不需要延迟的方法,使用以下知识:当“阻止弹出窗口”未选中时,每个窗口可以打开一个弹出窗口而没有延迟。在您的示例中考虑了三个弹出窗口,这是一般流程:

  1. 在您的域上打开一个弹出窗口(空白页)。
  2. 通过注入一个在加载时执行此操作的脚本,将下一个弹出窗口的开头委托给此弹出窗口。
  3. 将第一个弹出窗口重定向到您想要的网址。
  4. 重复操作,直到所有弹出窗口都打开。
  5. 以下是我为处理此流程而构建的内容:

    /**
     * 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 results 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。也可能有很大的改进空间,但我已经花了太多时间在这上面: - ))