在Chrome中检测阻止的弹出窗口 [英] Detect blocked popup in Chrome

查看:254
本文介绍了在Chrome中检测阻止的弹出窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  var newWin = window.open(url); 

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

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



当然,由于Chrome并未实际阻止弹出窗口,但在右下角的一个小窗口中打开,其中列出了阻止的弹出窗口。



我想要做的是能够判断弹出窗口是否被Chrome的弹出式窗口拦截器拦截。我尽量避免浏览器嗅探,转而使用功能检测。有没有办法做到这一点,而不浏览器嗅探?



编辑:我现在尝试使用 newWin。 outerHeight newWin.left 和其他类似的属性来完成这个任务。当弹出窗口被阻止时,谷歌浏览器将所有的位置和高度值返回为0.



不幸的是,即使弹出窗口实际打开了未知数量,它也会返回相同的值的时间。经过一段神奇的时期(我的测试中有几秒钟)后,位置和尺寸信息将作为正确的值返回。换句话说,我仍然没有更接近于解决这个问题。任何帮助,将不胜感激。

解决方案

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



我认为您可以做的最好的事情是将测试包装在setTimeout( )并在运行测试之前给弹出窗口3-5秒来完成加载。这不是完美的,但它应该至少有95%的时间。



以下是我用于跨浏览器检测的代码,没有Chrome部分。

 函数_hasPopupBlocker(poppedWindow){
var result = false;
$ b尝试{
if(typeof poppedWindow =='undefined'){
// Safari with popup blocker ...离开弹出窗口句柄undefined
result =真正;
}
else if(poppedWindow&& poppedWindow.closed){
//如果用户打开和关闭客户端窗口,会发生这种情况...
//因为混淆因为手柄仍然可用,但处于关闭状态。
//我们不是说窗口没有被阻塞,我们只是说
//在测试运行之前窗口已经关闭。
result = false;
}
else if(poppedWindow& poppedWindow.test){
//这是实际的测试。客户端窗口应该没问题。
result = false;
}
else {
//否则我们会假定窗口不正确
result = true;
}

} catch(err){
// if(console){
// console.warn(Could not access popup window,err) ;
//}
}

返回结果;
}

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

function test(){}



弹出式窗口拦截器检测器测试以查看测试函数是否作为子窗口的成员存在。



ADDED 2015年6月15日:



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

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

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

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

希望这有助于您。


I am aware of javascript techniques to detect whether a popup is blocked in other browsers (as described in the answer to this question). Here's the basic test:

var newWin = window.open(url);

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

But this does not work in Chrome. The "POPUP BLOCKED" section is never reached when the popup is blocked.

Of course, the test is working to an extent since Chrome doesn't actually block the popup, but opens it in a tiny minimized window at the lower right corner which lists "blocked" popups.

What I would like to do is be able to tell if the popup was blocked by Chrome's popup blocker. I try to avoid browser sniffing in favor of feature detection. Is there a way to do this without browser sniffing?

Edit: I have now tried making use of newWin.outerHeight, newWin.left, and other similar properties to accomplish this. Google Chrome returns all position and height values as 0 when the popup is blocked.

Unfortunately, it also returns the same values even if the popup is actually opened for an unknown amount of time. After some magical period (a couple of seconds in my testing), the location and size information is returned as the correct values. In other words, I'm still no closer to figuring this out. Any help would be appreciated.

解决方案

Well the "magical time" you speak of is probably when the popup's DOM has been loaded. Or else it might be when everything (images, outboard CSS, etc.) has been loaded. You could test this easily by adding a very large graphic to the popup (clear your cache first!). If you were using a Javascript Framework like jQuery (or something similar), you could use the ready() event (or something similar) to wait for the DOM to load before checking the window offset. The danger in this is that Safari detection works in a conflicting way: the popup's DOM will never be ready() in Safari because it'll give you a valid handle for the window you're trying to open -- whether it actually opens or not. (in fact, i believe your popup test code above won't work for safari.)

I think the best thing you can do is wrap your test in a setTimeout() and give the popup 3-5 seconds to complete loading before running the test. It's not perfect, but it should work at least 95% of the time.

Here's the code I use for cross-browser detection, without the Chrome part.

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

What I do is run this test from the parent and wrap it in a setTimeout(), giving the child window 3-5 seconds to load. In the child window, you need to add a test function:

function test() {}

The popup blocker detector tests to see whether the "test" function exists as a member of the child window.

ADDED JUNE 15 2015:

I think the modern way to handle this would be to use window.postMessage() to have the child notify the parent that the window has been loaded. The approach is similar (child tells parent it's loaded), but the means of communication has improved. I was able to do this cross-domain from the child:

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

The parent listens for this message using:

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

Hope this helps.

这篇关于在Chrome中检测阻止的弹出窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆