当前位置:  开发笔记 > 编程语言 > 正文

检测Chrome中阻止的弹出窗口

如何解决《检测Chrome中阻止的弹出窗口》经验,为你挑选了5个好方法。

我知道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以及其他类似性质的做到这一点.当弹出窗口被阻止时,Google Chrome会将所有位置和高度值返回为0.

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



1> Ringo..:

那么你所说的"神奇时间"可能是弹出窗口的DOM被加载的时候.或者可能是在加载了所有内容(图像,外置CSS等)之后.您可以通过在弹出窗口中添加一个非常大的图形来轻松测试它(首先清除缓存!).如果您使用的是JQuery框架(如jQuery(或类似的东西)),您可以使用ready()事件(或类似的东西)在检查窗口偏移量之前等待DOM加载.这样做的危险在于Safari检测以一种冲突的方式工作:在Safari中,弹出窗口的DOM永远不会就绪(因为它会为你试图打开的窗口提供一个有效的句柄 - 无论它实际打开还是不.(事实上​​,我相信你上面的弹出测试代码不适用于safari.)

我认为你能做的最好的事情是将你的测试包装在一个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()中,使子窗口加载3-5秒.在子窗口中,您需要添加测试功能:

功能测试() {}

弹出窗口阻止程序检测器测试以查看"test"函数是否作为子窗口的成员存在.

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

希望这可以帮助.


对此有任何更新?似乎不再起作用......特别是在Chrome中
基本上Chrome中存在一个错误.虽然它隐藏了弹出窗口,但它仍然执行,你仍然得到窗口对象 - 所以定期检查不起作用.这是适用于我的解决方案:var popup = window.open(url); if(popup){popup.onload = function(){console.log(popup.innerHeight> 0?'open':'blocked'); }} else {console.log('blocked'); 这里的工作示例:http://jsbin.com/uticev/3/

2> 小智..:

对InvisibleBacon的snipet只进行了一次改进(在IE9,Safari 5,Chrome 9和FF 3.6中测试过):

var myPopup = window.open("popupcheck.htm", "", "directories=no,height=150,);
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而不是onload,我会做$(myPopup).ready().在本地运行我的IE太快了,"onload"已经发生了.

3> Kevin B..:

以下是弹出窗口阻止程序检查的jQuery解决方案.它已经在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);

希望这可以帮助!:)



4> InvisibleBac..:

Rich的答案不再适用于Chrome.看起来Chrome现在在弹出窗口中实际执行任何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);
    };
}

正如许多人所报告的那样,即使在onload之后,"screenX"属性有时会报告失败弹出窗口的非零值.我也遇到过这种情况,但如果在零ms超时后添加检查,则screenX属性似乎总是​​输出一致的值.

如果有办法让这个脚本更健壮,请告诉我.似乎为我的目的工作.



5> Predrag Stoj..:

这对我有用:

    cope.PopupTest.params = 'height=1,;
    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.

推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有