在Chrome中检测阻止的popup窗口

我知道javascript技术来检测popup窗口是否在其他浏览器被阻止(如在这个问题的答案中所述 )。 这是基本的testing:

var newWin = window.open(url); if(!newWin || newWin.closed || typeof newWin.closed=='undefined') { //POPUP BLOCKED } 

但是这在Chrome中不起作用。 当popup窗口被阻止时,“POPUP BLOCKED”部分永远不会到达。

当然,这个testing在某种程度上是有效的,因为Chrome实际上并没有阻止popup窗口,而是在右下angular的一个微小的窗口中打开,列出了“被阻止”的popup窗口。

我想要做的是能够判断popup窗口是否被Chrome的popup式窗口拦截器阻止。 我试图避免浏览器嗅探有利于function检测。 有没有办法做到这一点没有浏览器嗅探?

编辑 :我现在已经尝试使用newWin.outerHeightnewWin.left和其他类似的属性来完成这一点。 Google Chrome在popup窗口被阻止时将所有位置和高度值都返回为0。

不幸的是,即使popup窗口实际打开了不知道的时间,它也会返回相同的值。 经过一段神奇的时期(在我的testing中几秒钟),位置和大小信息被返回为正确的值。 换句话说,我现在还没有弄明白这一点。 任何帮助,将不胜感激。

那么你所说的“魔法时间”可能是popup窗口的DOM被加载的时候。 否则,它可能是当一切(图像,外部的CSS等)已被加载。 您可以通过在popup窗口中添加一个非常大的graphics来轻松地进行testing(首先清除caching!)。 如果您使用的是像jQuery(或类似的)类似的Javascript框架,您可以使用ready()事件(或类似的东西)来等待DOM加载,然后再检查窗口偏移量。 其中的危险之处在于,Safari检测以相互冲突的方式工作:popup窗口的DOM将永远不会在Safari中准备好(),因为它会为您尝试打开的窗口提供有效的句柄 – 无论是实际打开还是不。 (事实上​​,我相信上面的popup式testing代码不适用于Safari浏览器。)

我认为你可以做的最好的事情是将你的testing包装在一个setTimeout()中,并在运行testing之前给popup的3-5秒来完成加载。 这不是完美的,但至less95%的时间应该工作。

以下是我用于跨浏览器检测的代码,没有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; } 

我所做的是从父级运行此testing,并将其包装在一个setTimeout()中,给子窗口加载3-5秒。 在子窗口中,你需要添加一个testing函数:

functiontesting() {}

popup式窗口拦截器检测器testing以查看“testing”函数是否作为子窗口的成员存在。

新增2015年6月15日:

我认为现代的方式来处理这将是使用window.postMessage()让孩子通知父窗口已被加载。 方法是类似的(孩子告诉父母它被加载),但通信手段已经改善。 我能够从孩子这个跨领域做到这一点:

 $(window).load(function() { this.opener.postMessage({'loaded': true}, "*"); this.close(); }); 

父母使用以下方式侦听此消息:

 $(window).on('message', function(event) { alert(event.originalEvent.data.loaded) }); 

希望这可以帮助。

只是InvisibleBacon snipet的一个改进(在IE9,Safari 5,Chrome 9和FF 3.6中testing):

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

Rich的答案不再适用于Chrome。 看起来像Chrome现在在popup窗口中实际执行任何Javascript。 我结束了检查screenX值为0来检查被阻止的popup窗口。 我也想我find一种方法来保证这个属性是最终检查之前。 这只适用于你的域上的popup窗口,但你可以像这样添加一个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); }; } 

正如许多人所报道的,即使在onload之后,“screenX”属性有时也会报告失败popup窗口的非零值。 我也遇到过这种情况,但是如果在零毫秒超时之后添加检查,则screenX属性总是输出一致的值。

让我知道是否有办法使这个脚本更健壮。 似乎为我的目的而工作。

以下是popup窗口阻止程序检查的jQuery解决scheme。 已经在FF(v11),Safari(v6),Chrome(v23.0.127.95)和IE(v7和v9)中进行了testing。 更新_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); 

希望这可以帮助! 🙂

这对我工作:

  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中不起作用。

检查窗口相对于父级的位置。 Chrome使窗口几乎在屏幕外显示。

我在popup窗口中遇到类似的问题,在Chrome中无法打开。 我很沮丧,因为我没有试图做一些鬼鬼祟祟的事情,就像一个popup窗口,当用户点击时打开一个窗口。 我很沮丧,因为运行我的function,包括从萤火虫命令行的window.open()工作,而实际上点击我的链接没有! 这是我的解决scheme:

错误的方法:从事件监听器(在我的情况下,dojo.connect到DOM节点的onclick事件方法)运行window.open()。

 dojo.connect(myNode, "onclick", function() { window.open(); } 

正确的方法:为调用window.open()的节点的onclick属性分配一个函数。

 myNode.onclick = function() { window.open(); } 

当然,如果需要的话,我仍然可以为同一个onclick事件做事件监听器。 有了这个变化,即使Chrome设置为“不允许任何网站显示popup式窗口”,我也可以打开我的窗户。 喜悦。

如果任何聪明的人都能告诉我们其他人为什么会有所作为,我很乐意听到这个消息,尽pipe我怀疑这只是试图closures恶意程序popup窗口。

这是一个目前在Chrome中使用的版本。 只是从Rich的解决scheme中稍作改动,尽pipe我在一个处理时间的包装器中添加了一个。

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

如果popup窗口被阻止,5秒钟宽限期后将显示警告消息(您可以调整,但5秒钟应该是相当安全的)。

这个片段包含了所有上述内容 – 出于某种原因,StackOverflow在下面的代码块中排除了第一行和最后一行代码,所以我写了一个博客。 有关完整的解释和(可下载的)代码的其余部分,请查看我的博客: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(); 

哇,那里肯定有很多解决scheme。 这是我的,它使用从当前接受的答案取得的解决scheme(这不适用于最新的Chrome浏览器,并要求在超时包装),以及相关的解决scheme(这实际上是香草JS,而不是jQuery) 。

Mine使用了一个callback体系结构,当popup窗口被阻塞时它将被发送,否则返回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); } }; 

杰森的回答是我能想到的唯一方法,但依靠这样的立场有点狡猾!

现在,您并不需要问这个问题:“我的未经请求的popup窗口被阻止了吗?”,因为答案总是“是” – 所有主stream浏览器都默认打开popup式窗口拦截器。 最好的办法是只有window.open()响应直接点击,这几乎总是允许的。

您好

我稍微修改了上述解决scheme,并认为它至less在Chrome上工作。 我的解决scheme是检测popup窗口是否在主页面打开时被阻塞,而不是在打开popup窗口的时候,但是我确定有一些人可以修改。:-)这里的缺点是显示popup窗口几秒钟(可能会缩短一点),当没有popup式窗口拦截器。

我把它放在我的“主”窗口的部分

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

popuptest看起来像这样:

 <!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毫秒之后的popup页面上调用testing函数时,Chrome已经正确设置了内部高度。

我使用variablespopUpsBlocked来知道popup窗口是否显示在其他javascript中。 即

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

我要复制/粘贴DanielB提供的答案: https ://stackoverflow.com/a/27725432/892099。 在铬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."); } } 

据我所知(从我testing的)铬返回一个窗口对象的位置“约:空白”。 所以,以下内容适用于所有浏览器:

 var newWin = window.open(url); if(!newWin || newWin.closed || typeof newWin.closed=='undefined' || newWin.location=='about:blank') { //POPUP BLOCKED }