如何检测浏览器是否阻塞弹出窗口?

偶尔,我会看到一个网页试图打开一个新窗口(用于用户输入,或者其他重要的事情) ,但是弹出窗口阻止器阻止了这种情况的发生。

调用窗口可以使用什么方法来确保新窗口正确启动?

125761 次浏览

如果你使用 JavaScript 打开弹出窗口,你可以使用这样的东西:

var newWin = window.open(url);


if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
//POPUP BLOCKED
}

更新: 弹窗在很久以前就存在了。最初的想法是在不关闭主窗口的情况下显示另一个内容。到目前为止,还有其他方法可以做到这一点: JavaScript 能够为服务器发送请求,因此很少使用弹出窗口。不过有时候还是很方便的。

在过去,恶意网站滥用弹出窗口很多。一个糟糕的页面可能会打开大量带有广告的弹出窗口。因此,现在大多数浏览器试图阻止弹出窗口和保护用户。

大多数浏览器如果在用户触发的事件处理程序(如 onclick)之外调用它们,就会阻止弹出窗口。

仔细想想,这有点棘手。如果代码直接在 onclick 处理程序中,那么就很容易。但是在 setTimeout 中弹出的是什么呢?

试试这个代码:

 // open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);

弹出窗口在 Chrome 中打开,但在 Firefox 中被阻止。

这个在 Firefox 中也可以使用:

 // open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);

不同之处在于,Firefox 处理的超时时间为2000毫秒或更少是可以接受的,但超时之后——移除了“信任”,假设现在它“在用户操作之外”。所以第一个被屏蔽了,第二个没有。


2012年的最初答案:

这个弹出阻塞检查的解决方案已经在 FF (v11)中进行了测试, Safari (v6) ,Chrome (v23.0.127.95)和 IE (v7 & v9) DisplayError 函数来处理您认为合适的错误消息。

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

希望这个有用! :)

我尝试了上面的一些例子,但是我不能让它们与 Chrome 一起工作。这个简单的方法似乎适用于 Chrome 39、 Firefox 34、 Safari 5.1.7和 IE 11。下面是来自我们的 JS 库的代码片段。

openPopUp: function(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.");
}
}

无论浏览器公司或版本如何,一直都是都能正常工作的一个“解决方案”就是在屏幕上放一个警告信息,在靠近创建弹出窗口的控件的地方,礼貌地警告用户该操作需要弹出窗口,并请允许他们访问网站。

我知道这不是什么新奇的东西,但是它不能再简单了,只需要5分钟的测试,然后你就可以继续做其他的噩梦了。

一旦用户允许为您的网站弹出窗口,它也将是体贴的,如果你没有过多的弹出窗口。你最不想做的就是惹恼你的访客。

我已经尝试了很多解决方案,但是我能想到的唯一一个同样适用于 uBlock Origin 的解决方案,就是利用超时来检查弹出窗口的关闭状态。

function popup (url, width, height) {
const left = (window.screen.width / 2) - (width / 2)
const top = (window.screen.height / 2) - (height / 2)
let opener = window.open(url, '', `menubar=no, toolbar=no, status=no, resizable=yes, scrollbars=yes, width=${width},height=${height},top=${top},left=${left}`)


window.setTimeout(() => {
if (!opener || opener.closed || typeof opener.closed === 'undefined') {
console.log('Not allowed...') // Do something here.
}
}, 1000)
}

很明显,这是一种技巧; 就像所有解决这个问题的方法一样。

您需要在 setTimeout 中提供足够的时间来考虑最初的开启和关闭,因此它永远不会完全准确。这将是一个试错的立场。

将此添加到您的尝试列表中。

通过使用 onbefore 卸载事件,我们可以检查如下内容

    function popup()
{
var chk=false;
var win1=window.open();
win1.onbeforeunload=()=>{
var win2=window.open();
win2.onbeforeunload=()=>{
chk=true;
};
win2.close();
};
win1.close();
return chk;
}

它将在背景中打开2个黑色窗口

函数返回布尔值。

我把“凯文 · B”和“丹尼尔 · B”的解决方案结合起来。
这样简单多了。

var isPopupBlockerActivated = function(popupWindow) {
if (popupWindow) {
if (/chrome/.test(navigator.userAgent.toLowerCase())) {
try {
popupWindow.focus();
} catch (e) {
return true;
}
} else {
popupWindow.onload = function() {
return (popupWindow.innerHeight > 0) === false;
};
}
} else {
return true;
}
return false;
};

用法:

var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
// Do what you want.
}

一个简单的方法也是 如果您拥有子代码,就是在其 html 中创建一个简单的变量,如下所示:

    <script>
var magicNumber = 49;
</script>

然后从父母那里检查它是否存在,类似于下面的内容:

    // Create the window with login URL.
let openedWindow = window.open(URL_HERE);


// Check this magic number after some time, if it exists then your window exists
setTimeout(() => {
if (openedWindow["magicNumber"] !== 32) {
console.error("Window open was blocked");
}
}, 1500);


我们等待一段时间,以确保该网页已加载,并检查其存在。 显然,如果窗口在1500ms 之后没有加载,那么变量仍然是 undefined

对于一些弹出窗口阻止器这不工作,但我使用它作为基本的解决方案,并添加尝试{}捕捉

try {
const newWindow = window.open(url, '_blank');
if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined')         {
return null;
}


(newWindow as Window).window.focus();
newWindow.addEventListener('load', function () {
console.info('Please allow popups for this website')
})
return newWindow;
} catch (e) {
return null;
}

这将尝试调用 addEventListaner 函数,但是如果弹出窗口没有打开,那么它将中断并进入 catch,然后询问它的对象是否为 null 并运行其余代码。