[英]How do you detect if a popup to another domain was blocked in Chrome?
[英]Detect blocked popup in Chrome
我知道 javascript 技術可以檢測彈出窗口是否在其他瀏覽器中被阻止(如該問題的答案中所述)。 這是基本測試:
var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
//POPUP BLOCKED
}
但這在 Chrome 中不起作用。 當彈出窗口被阻止時,永遠不會到達“POPUP BLOCKED”部分。
當然,測試在一定程度上是有效的,因為 Chrome 實際上並沒有阻止彈出窗口,而是在右下角的一個最小化的 window 中打開它,其中列出了“被阻止”的彈出窗口。
我想做的是能夠判斷彈出窗口是否被 Chrome 的彈出窗口阻止程序阻止。 我盡量避免瀏覽器嗅探以支持特征檢測。 有沒有辦法在沒有瀏覽器嗅探的情況下做到這一點?
編輯:我現在嘗試使用newWin.outerHeight
、 newWin.left
和其他類似屬性來完成此操作。 當彈出窗口被阻止時,谷歌瀏覽器將所有 position 和高度值返回為 0。
不幸的是,即使彈出窗口實際上打開了未知的時間,它也會返回相同的值。 經過一段神奇的時間(在我的測試中幾秒鍾),位置和大小信息作為正確的值返回。 換句話說,我還沒有更接近弄清楚這一點。 任何幫助,將不勝感激。
好吧,您所說的“神奇時間”可能是彈出窗口的 DOM 已加載時。 否則可能是所有內容(圖像、舷外 CSS 等)都已加載。 您可以通過在彈出窗口中添加一個非常大的圖形(首先清除緩存)來輕松測試這一點。如果您使用的是 Javascript 框架,如 jQuery(或類似的東西)。 您可以使用 ready() 事件(或類似事件)等待 DOM 加載,然后再檢查 window 偏移量:這樣做的危險在於 Safari 檢測以相互沖突的方式工作。 彈出窗口的 DOM 將永遠不會在 Safari 中准備好(),因為它會為您嘗試打開的 window 提供有效的句柄 - 無論它是否真的打開,(事實上。我相信你上面的彈出測試代碼贏了不適用於野生動物園。)
我認為您可以做的最好的事情是將測試包裝在 setTimeout() 中,並在運行測試之前給彈出窗口 3-5 秒來完成加載。 它並不完美,但它至少應該在 95% 的時間內工作。
這是我用於跨瀏覽器檢測的代碼,沒有 Chrome 部分。
function _hasPopupBlocker(poppedWindow) {
var result = false;
try {
if (typeof poppedWindow == 'undefined') {
// Safari with popup blocker... leaves the popup window handle undefined
result = true;
}
else if (poppedWindow && poppedWindow.closed) {
// This happens if the user opens and closes the client window...
// Confusing because the handle is still available, but it's in a "closed" state.
// We're not saying that the window is not being blocked, we're just saying
// that the window has been closed before the test could be run.
result = false;
}
else if (poppedWindow && poppedWindow.test) {
// This is the actual test. The client window should be fine.
result = false;
}
else {
// Else we'll assume the window is not OK
result = true;
}
} catch (err) {
//if (console) {
// console.warn("Could not access popup window", err);
//}
}
return result;
}
我所做的是從父級運行此測試並將其包裝在 setTimeout() 中,給子級 window 3-5 秒的加載時間。 在子window中,需要添加一個測試function:
function 測試(){}
彈出窗口攔截器檢測器測試以查看“測試”function 是否作為子 window 的成員存在。
2015 年 6 月 15 日添加:
我認為處理這個問題的現代方法是使用 window.postMessage() 讓孩子通知父母 window 已加載。 方法類似(孩子告訴父母它已加載),但溝通方式有所改進。 我能夠從孩子做這個跨域:
$(window).load(function() {
this.opener.postMessage({'loaded': true}, "*");
this.close();
});
父母使用以下方法偵聽此消息:
$(window).on('message', function(event) {
alert(event.originalEvent.data.loaded)
});
希望這可以幫助。
僅對 InvisibleBacon 的片段進行了一項改進(在 IE9、Safari 5、Chrome 9 和 FF 3.6 中測試):
var myPopup = window.open("popupcheck.htm", "", "directories=no,height=150,width=150,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,top=0,location=no");
if (!myPopup)
alert("failed for most browsers");
else {
myPopup.onload = function() {
setTimeout(function() {
if (myPopup.screenX === 0) {
alert("failed for chrome");
} else {
// close the test window if popups are allowed.
myPopup.close();
}
}, 0);
};
}
以下是jQuery解決彈出窗口攔截器檢查的方法。 它已在 FF (v11)、Safari (v6)、Chrome (v23.0.127.95) 和 IE (v7 & v9) 中進行了測試。 更新 _displayError function 以處理您認為合適的錯誤消息。
var popupBlockerChecker = {
check: function(popup_window){
var _scope = this;
if (popup_window) {
if(/chrome/.test(navigator.userAgent.toLowerCase())){
setTimeout(function () {
_scope._is_popup_blocked(_scope, popup_window);
},200);
}else{
popup_window.onload = function () {
_scope._is_popup_blocked(_scope, popup_window);
};
}
}else{
_scope._displayError();
}
},
_is_popup_blocked: function(scope, popup_window){
if ((popup_window.innerHeight > 0)==false){ scope._displayError(); }
},
_displayError: function(){
alert("Popup Blocker is enabled! Please add this site to your exception list.");
}
};
用法:
var popup = window.open("http://www.google.ca", '_blank');
popupBlockerChecker.check(popup);
希望這可以幫助: :)
Rich 的回答不再適用於 Chrome。 看起來 Chrome 現在實際上在彈出 window 中執行任何 Javascript 。 我最終檢查了 screenX 值為 0 以檢查是否有被阻止的彈出窗口。 我還認為我找到了一種方法來保證這個屬性在檢查之前是最終的。 這僅適用於您域上的彈出窗口,但您可以添加一個 onload 處理程序,如下所示:
var myPopup = window.open("site-on-my-domain", "screenX=100");
if (!myPopup)
alert("failed for most browsers");
else {
myPopup.onload = function() {
setTimeout(function() {
if (myPopup.screenX === 0)
alert("failed for chrome");
}, 0);
};
}
正如許多人所報告的那樣,“screenX”屬性有時會為失敗的彈出窗口報告非零值,即使在 onload 之后也是如此。 我也遇到過這種行為,但是如果您在零毫秒超時后添加檢查,則 screenX 屬性似乎總是與 output 一致。
讓我知道是否有辦法讓這個腳本更健壯。 似乎為我的目的工作。
這對我有用:
cope.PopupTest.params = 'height=1,width=1,left=-100,top=-100,location=no,toolbar=no,menubar=no,scrollbars=no,resizable=no,directories=no,status=no';
cope.PopupTest.testWindow = window.open("popupTest.htm", "popupTest", cope.PopupTest.params);
if( !cope.PopupTest.testWindow
|| cope.PopupTest.testWindow.closed
|| (typeof cope.PopupTest.testWindow.closed=='undefined')
|| cope.PopupTest.testWindow.outerHeight == 0
|| cope.PopupTest.testWindow.outerWidth == 0
) {
// pop-ups ARE blocked
document.location.href = 'popupsBlocked.htm';
}
else {
// pop-ups are NOT blocked
cope.PopupTest.testWindow.close();
}
outerHeight 和 outerWidth 用於 chrome,因為上面的 'about:blank' 技巧不再適用於 chrome。
我將復制/粘貼此處提供的答案:DanielB 的https://stackoverflow.com/a/27725432/892099 。 適用於 chrome 40,非常干凈。 沒有骯臟的黑客或等待涉及。
function popup(urlToOpen) {
var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");
try {
popup_window.focus();
}
catch (e) {
alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
}
}
哇,這里肯定有很多解決方案。 這是我的,它使用從當前接受的答案中獲取的解決方案(在最新的 Chrome 中不起作用並且需要在超時中包裝它),以及這個線程上的相關解決方案(實際上是 vanilla JS,而不是 jQuery) .
我的使用回調架構,當彈出窗口被阻止時發送true
,否則發送false
。
window.isPopupBlocked = function(popup_window, cb)
{
var CHROME_CHECK_TIME = 2000; // the only way to detect this in Chrome is to wait a bit and see if the window is present
function _is_popup_blocked(popup)
{
return !popup.innerHeight;
}
if (popup_window) {
if (popup_window.closed) {
// opened OK but was closed before we checked
cb(false);
return;
}
if (/chrome/.test(navigator.userAgent.toLowerCase())) {
// wait a bit before testing the popup in chrome
setTimeout(function() {
cb(_is_popup_blocked(popup_window));
}, CHROME_CHECK_TIME);
} else {
// for other browsers, add an onload event and check after that
popup_window.onload = function() {
cb(_is_popup_blocked(popup_window));
};
}
} else {
cb(true);
}
};
我在 Chrome 中沒有打開彈出窗口時遇到了類似的問題。 我很沮喪,因為我並沒有試圖做一些鬼鬼祟祟的事情,比如一個加載彈出窗口,只是在用戶點擊時打開一個 window。 我很沮喪,因為運行我的 function 包括來自 firebug 命令行的 window.open() 有效,而實際上單擊我的鏈接卻沒有:這是我的解決方案:
錯誤的方式:從事件監聽器運行 window.open() (在我的例子中,dojo.connect 到 DOM 節點的 onclick 事件方法)。
dojo.connect(myNode, "onclick", function() {
window.open();
}
正確方法:將 function 分配給調用 window.open() 的節點的 onclick 屬性。
myNode.onclick = function() {
window.open();
}
當然,如果需要,我仍然可以為同一個 onclick 事件做事件監聽器。 通過此更改,即使 Chrome 設置為“不允許任何網站顯示彈出窗口”,我也可以打開我的 windows。 喜悅。
如果任何在 Chrome 方面有智慧的人可以告訴我們 rest 為什么它會有所作為,我很想聽聽,盡管我懷疑這只是試圖關閉惡意程序彈出窗口的大門。
這是當前在 Chrome 中運行的版本。 與 Rich 的解決方案稍有不同,盡管我也添加了一個處理時間的包裝器。
function checkPopupBlocked(poppedWindow) {
setTimeout(function(){doCheckPopupBlocked(poppedWindow);}, 5000);
}
function doCheckPopupBlocked(poppedWindow) {
var result = false;
try {
if (typeof poppedWindow == 'undefined') {
// Safari with popup blocker... leaves the popup window handle undefined
result = true;
}
else if (poppedWindow && poppedWindow.closed) {
// This happens if the user opens and closes the client window...
// Confusing because the handle is still available, but it's in a "closed" state.
// We're not saying that the window is not being blocked, we're just saying
// that the window has been closed before the test could be run.
result = false;
}
else if (poppedWindow && poppedWindow.outerWidth == 0) {
// This is usually Chrome's doing. The outerWidth (and most other size/location info)
// will be left at 0, EVEN THOUGH the contents of the popup will exist (including the
// test function we check for next). The outerWidth starts as 0, so a sufficient delay
// after attempting to pop is needed.
result = true;
}
else if (poppedWindow && poppedWindow.test) {
// This is the actual test. The client window should be fine.
result = false;
}
else {
// Else we'll assume the window is not OK
result = true;
}
} catch (err) {
//if (console) {
// console.warn("Could not access popup window", err);
//}
}
if(result)
alert("The popup was blocked. You must allow popups to use this site.");
}
要使用它,只需這樣做:
var popup=window.open('location',etc...);
checkPopupBlocked(popup);
如果彈出窗口被阻止,警報消息將在 5 秒寬限期后顯示(您可以調整它,但 5 秒應該是相當安全的)。
這個片段包含了以上所有內容——出於某種原因——StackOverflow 排除了下面代碼塊中的第一行和最后一行代碼,所以我寫了一篇關於它的博客。 有關完整說明和(可下載)代碼的 rest,請查看我的博客 codeabode.blogspot.com
var PopupWarning = {
init : function()
{
if(this.popups_are_disabled() == true)
{
this.redirect_to_instruction_page();
}
},
redirect_to_instruction_page : function()
{
document.location.href = "http://thecodeabode.blogspot.com";
},
popups_are_disabled : function()
{
var popup = window.open("http://localhost/popup_with_chrome_js.html", "popup_tester", "width=1,height=1,left=0,top=0");
if(!popup || popup.closed || typeof popup == 'undefined' || typeof popup.closed=='undefined')
{
return true;
}
window.focus();
popup.blur();
//
// Chrome popup detection requires that the popup validates itself - so we need to give
// the popup time to load, then call js on the popup itself
//
if(navigator && (navigator.userAgent.toLowerCase()).indexOf("chrome") > -1)
{
var on_load_test = function(){PopupWarning.test_chrome_popups(popup);};
var timer = setTimeout(on_load_test, 60);
return;
}
popup.close();
return false;
},
test_chrome_popups : function(popup)
{
if(popup && popup.chrome_popups_permitted && popup.chrome_popups_permitted() == true)
{
popup.close();
return true;
}
//
// If the popup js fails - popups are blocked
//
this.redirect_to_instruction_page();
}
};
PopupWarning.init();
Promise
方法怎么樣?
const openPopUp = (...args) => new Promise(s => {
const win = window.open(...args)
if (!win || win.closed) return s()
setTimeout(() => (win.innerHeight > 0 && !win.closed) ? s(win) : s(), 200)
})
你可以像經典的window.open
一樣使用它
const win = await openPopUp('popuptest.htm', 'popuptest')
if (!win) {
// popup closed or blocked, handle alternative case
}
您可以更改代碼,使其失敗 promise 而不是返回undefined
,我只是認為在這種情況下, if
比try / catch
更容易控制流。
檢查window相對於父的position。 Chrome 使 window幾乎出現在屏幕外。
你好
我稍微修改了上面描述的解決方案,並認為它至少適用於 Chrome。 我的解決方案是在打開主頁時檢測彈出窗口是否被阻止,而不是在打開彈出窗口時檢測,但我相信有些人可以修改它。:-) 這里的缺點是顯示彈出窗口當沒有彈出窗口阻止程序時,持續幾秒鍾(可能會縮短一點)。
我把它放在我的“主要”部分 window
<script type="text/JavaScript" language="JavaScript">
var mine = window.open('popuptest.htm','popuptest','width=1px,height=1px,left=0,top=0,scrollbars=no');
if(!mine|| mine.closed || typeof mine.closed=='undefined')
{
popUpsBlocked = true
alert('Popup blocker detected ');
if(mine)
mine.close();
}
else
{
popUpsBlocked = false
var cookieCheckTimer = null;
cookieCheckTimer = setTimeout('testPopup();', 3500);
}
function testPopup()
{
if(mine)
{
if(mine.test())
{
popUpsBlocked = false;
}
else
{
alert('Popup blocker detected ');
popUpsBlocked = true;
}
mine.close();
}
}
</script>
彈出測試看起來像這樣:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Popup test</title>
<script type="text/javascript" language="Javascript">
function test() {if(window.innerHeight!=0){return true;} else return false;}
</script>
</head>
<body>
</body>
</html>
當我在 3500 毫秒后在彈出頁面上調用測試功能時,Chrome 已正確設置了內部高度。
我使用變量 popUpsBlocked 來了解彈出窗口是否顯示在其他 javascript 中。 IE
function ShowConfirmationMessage()
{
if(popUpsBlocked)
{
alert('Popups are blocked, can not display confirmation popup. A mail will be sent with the confirmation.');
}
else
{
displayConfirmationPopup();
}
mailConfirmation();
}
function openPopUpWindow(format)
{
var win = window.open('popupShow.html',
'ReportViewer',
'width=920px,height=720px,left=50px,top=20px,location=no,directories=no,status=no,menubar=no,toolbar=no,resizable=1,maximize:yes,scrollbars=0');
if (win == null || typeof(win) == "undefined" || (win == null && win.outerWidth == 0) || (win != null && win.outerHeight == 0) || win.test == "undefined")
{
alert("The popup was blocked. You must allow popups to use this site.");
}
else if (win)
{
win.onload = function()
{
if (win.screenX === 0) {
alert("The popup was blocked. You must allow popups to use this site.");
win.close();
}
};
}
}
傑森的回答也是我能想到的唯一方法,但是像這樣依賴 position 有點狡猾!
這些天來,你真的不需要問“我的主動彈出窗口被阻止了嗎?”,因為答案總是“是”——所有主要瀏覽器都默認打開了彈出窗口阻止程序。 最好的方法只是響應直接點擊 window.open() ,這幾乎總是被允許的。
據我所知(根據我的測試),Chrome 返回一個 window object,位置為“about:blank”。 因此,以下內容應該適用於所有瀏覽器:
var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined' || newWin.location=='about:blank')
{
//POPUP BLOCKED
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.