2017-09-23 77 views
2

由於Safari 9在9月20日更新 - 下面的代碼(Javascript)一次只能打開1個窗口(在Safari 10.1上它將全部打開)。在safari中打開多個彈出式窗口11

是否有可能在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的新更新並不想讓我用過多的pop窗戶。
+0

可能是因爲safari默認設置不啓用新窗口彈出。您必須將瀏覽器配置爲接受彈出窗口。 – 2017-09-23 16:21:20

回答

1

首先,這裏是我的測試中觀察到野生動物園11的行爲:

  • 一個彈出窗口總是允許打開(即使在全球性的「阻止彈出窗口」設置被選中)。當選中「阻止彈出窗口」時,訪問彈出窗口的window對象將受到限制(而不是在「阻止彈出窗口」未選中時)。
  • 正如您所描述的,當「阻止彈出式窗口」未選中時,多個window.open調用必須延遲(在我的測試中需要> 1秒)。
  • 當「Block pop-up windows」被選中時,似乎只有一個彈出窗口被允許打開(儘管使用了延遲)。

所以,你已經發現了一種解決這個問題的方法:添加延遲。

還有一種方法可以讓您在不需要延遲的情況下打開多個彈出窗口,使用「取消選中」阻止彈出窗口「的知識時,每個窗口可以毫不拖延地打開一個彈出窗口。以您的示例中的三個彈出窗口爲例,以下是一般流程:

  1. 在您的域上打開一個彈出窗口(空白頁)。
  2. 通過注入一個在加載時執行它的腳本來委託下一個彈出窗口的打開。
  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 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。也可能有很大的改進空間,但我已經花費了太多的時間在這:-)
+0

嗨馬特,謝謝你的回答! 我沒有使用你的代碼(主要是因爲我很難理解),但我確實理解它背後的理念(每個窗口打開下一個彈出窗口) - 它工作! 這是一個工作,做到這一點,但至少它的工作原理:) 非常感謝。 –

+0

不用擔心。超時對我的用例來說不夠用,所以它變得有點必要。它仍然傷害我的大腦! –