簡體   English   中英

Javascript檢測用另一個域加載的關閉彈出窗口

[英]Javascript detect closing popup loaded with another domain

我打開一個彈出窗口並將onbeforeunload事件附加到它上面,如下所示:

win = window.open("http://www.google.com", "", "width=300px,height=300px");
win.onbeforeunload = function() {
    //do your stuff here
    alert("Closed");
};

如果我將URL保留為空,則新彈出窗口將以“about:blank”作為地址打開,但當我關閉它時,我會看到警報。

如果我看到它(使用外部URL)打開,一旦關閉,我就再也看不到警報了。 知道為什么會這樣嗎?

如上所述,相同的源策略會阻止Javascript檢測此類事件。 但是有一個非常簡單的解決方案,允許您檢測這些窗口的關閉。

這是JS代碼:

var openDialog = function(uri, name, options, closeCallback) {
    var win = window.open(uri, name, options);
    var interval = window.setInterval(function() {
        try {
            if (win == null || win.closed) {
                window.clearInterval(interval);
                closeCallback(win);
            }
        }
        catch (e) {
        }
    }, 1000);
    return win;
};

它的作用:它使用提供的參數創建新窗口,然后以1s間隔設置檢查器功能。 然后,該函數檢查窗口對象是否存在並將其closed屬性設置為false。 如果其中任何一個不成立,這意味着窗口(可能)已關閉,我們應該觸發'closeCallback函數'回調。

此功能適用於所有現代瀏覽器。 前一段時間,Opera在從其他域上的窗口檢查屬性時導致錯誤 - 因此try..catch塊。 但我現在已經測試了它,看起來它的確很好用。

我們使用這種技術為不支持SDK(ehem ... Twitter ... ehem)的網站創建“facebook-style”登錄彈出窗口。 這需要一些額外的工作 - 我們無法從Twitter本身獲得任何消息,但是Oauth將我們重新引導回我們的域,然后我們能夠將一些數據放入彈出窗口對象中,這些數據可以從開啟者訪問。 然后在close回調函數中,我們解析了這些數據並顯示了實際結果。

此方法的一個缺點是在窗口關閉后調用回調。 嗯,這是我能夠實現跨域策略的最佳方法。

您可以收聽用戶關閉彈出窗口時觸發的開啟窗口的“焦點”事件。

不幸的是,您嘗試跨域通信,這是JavaScript的相同原始策略所禁止的。 你必須使用服務器端代理或其他一些丑陋的黑客來繞過它。

您可以嘗試在網站上創建一個頁面,在iframe中加載外部網站。 然后,您可以彈出該頁面並聽取它卸載。

我將@ThomasZ的答案與結合起來設置了一個間隔限制(不想使用setTimeout)。

示例(在Typescript中,匿名聲明,以免丟失對“this”的引用):

  private _callMethodWithInterval = (url: string, callback: function, delay: number, repetitions: number) => {      
    const newWindow = window.open(url, "WIndowName", null, true);

    let x = 0;
    let intervalID = window.setInterval(() => {
      //stops interval if newWindow closed or doesn't exist
      try {
        if (newWindow == null || newWindow.closed) {
          console.info("window closed - interval cleared")
          callback();
          window.clearInterval(intervalID);
        }
      }
      catch (e) {
        console.error(`newWindow never closed or null - ${e}`)
      }
      //stops interval after number of intervals
      if (++x === repetitions) {
        console.info("max intervals reached - interval cleared")        
        window.clearInterval(intervalID);
      }
    }, delay)
  }//end _callMethodWithInterval  

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM