避免浏览器弹出窗口阻止程序

Pab*_*dez 161 javascript modal-dialog popup popup-blocker

我正在开发纯粹在JavaScript中的OAuth身份验证流程,我想在弹出窗口中向用户显示"授予访问权限"窗口,但它会被阻止.

如何防止由不同浏览器的弹出窗口阻止程序阻止弹出窗口window.open或被window.showModalDialog其阻止?

dth*_*rpe 274

一般规则是弹出窗口阻止程序将window.open从未通过直接用户操作调用的javascript调用if 或类似函数.也就是说,您可以window.open响应按钮单击而不会被弹出窗口阻止程序命中,但如果您在计时器事件中放入相同的代码,它将被阻止.呼叫链的深度也是一个因素 - 一些较旧的浏览器只查看直接呼叫者,较新的浏览器可以稍微回溯以查看呼叫者的呼叫者是否是鼠标点击等.保持尽可能浅,以避免弹出窗口阻止程序.

  • 通过实验,我必须了解堆栈深度与弹出窗口阻止程序无关.它实际上检查在用户操作之后是否在1秒内调用window.open.在Chrome 46和Firefox 42中测试过. (6认同)
  • 没有人说浏览器是一致的.:P (5认同)
  • 有趣的是,通过绑定到 select 元素的更改事件启动的弹出窗口将被阻止(在 Chrome 中,而不是 FF),即使该事件是由直接用户操作(例如单击)启动的。尽管如果绑定到输入,它们是允许的。奇怪的。 (2认同)

Swi*_*ter 174

基于杰森赛百灵非常有用的技巧,并在覆盖的东西在这里那里,我发现我的情况下的完美解决方案:

使用Javascript片段的伪代码:

  1. 立即在用户操作上创建一个空白弹出窗口

    var importantStuff = window.open('', '_blank');
    
    Run Code Online (Sandbox Code Playgroud)

    可选:添加一些"等待"信息消息.例子:

    a)外部HTML页面:将上面的行替换为

    var importantStuff = window.open('http://example.com/waiting.html', '_blank');
    
    Run Code Online (Sandbox Code Playgroud)

    b)文本:在上面的下面添加以下行:

    importantStuff.document.write('Loading preview...');
    
    Run Code Online (Sandbox Code Playgroud)
  2. 准备就绪时填充内容(例如,返回AJAX调用时)

    importantStuff.location.href = 'http://shrib.com';
    
    Run Code Online (Sandbox Code Playgroud)

window.open使用您需要的任何其他选项丰富呼叫.

我实际上使用此解决方案进行mailto重定向,它适用于我的所有浏览器(Windows 7,Android).这个_blank位有助于mailto重定向在移动设备上运行,顺便说一句.

你的经历?有什么方法可以改善吗?

  • `不管你打算做什么,有一个比弹出窗口更好的方法吗?哈哈?奇怪的概括.客户希望他们通过身份验证的页面保持打开状态,并在新身份验证中打开身份验证后的新站点/登录页面.是的,不是我对优秀用户体验的想法......但这似乎是合理的 (5认同)
  • 有用的提示,如果ajax请求失败,请调用`importantStuff.close`来关闭新选项卡并在原始页面中提供并提醒. (3认同)

Dav*_*vid 23

另外瑞士先生的帖子,在我的情况下,window.open是在一个承诺内启动的,它打开了弹出窗口阻止器,我的解决方案是:在角度:

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateTabLocation(res.url, myNewTab);

    }
  );
};
Run Code Online (Sandbox Code Playgroud)

browserService:

this.openNewTab = function(){
     var newTabWindow = $window.open();
     return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
     if(!tabLocation){
       tab.close();
     }
     tab.location.href = tabLocation;
}
Run Code Online (Sandbox Code Playgroud)

这是使用promise响应打开新选项卡而不是调用弹出窗口阻止程序的方法.

  • 这导致了我的解决方案!在那里我创建了一个包含打开的选项卡的变量,然后在数据加载后填充 url。谢谢。`const tab = window.open(); observable.subscribe(dataUrl => tab.location.href = dataUrl);` (2认同)

Fra*_*oMM 19

作为一种好的做法,我认为测试弹出窗口是否被阻止并采取措施以防万一是一个好主意.您需要知道window.open有一个返回值,如果操作失败,该值可能为null.例如,在以下代码中:

function pop(url,w,h) {
    n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
    if(n==null) {
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

如果弹出窗口被阻止,window.open将返回null.所以函数将返回false.

例如,假设直接从任何链接调用此函数target="_blank":如果弹出窗口成功打开,则返回 false将阻止链接操作,否则如果弹出窗口被阻止,则返回true将保留默认行为(打开新的_blank窗口)并继续.

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >
Run Code Online (Sandbox Code Playgroud)

这样,如果有效,你将有一个弹出窗口,如果没有,你将有一个_blank窗口.

如果弹出窗口未打开,您可以:

  • 像示例中一样打开一个空白窗口然后继续
  • 打开假弹出窗口(页面内的iframe)
  • 告知用户("请允许此站点的弹出窗口")
  • 打开一个空白窗口,然后通知用户等.


Jas*_*ing 8

来自Google的oauth JavaScript API:

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

查看它所在的区域:

设置身份验证

客户端的OAuth 2.0实现使用弹出窗口提示用户登录并批准该应用程序.对gapi.auth.authorize的第一次调用可以触发弹出窗口阻止程序,因为它会间接打开弹出窗口.要防止弹出窗口阻止程序在auth调用时触发,请在客户端加载时调用gapi.auth.init(回调).当库准备好进行auth调用时,将执行提供的回调.

我猜它与上面的真实答案有关,它如何解释是否有立即响应,它不会触发弹出警报."gapi.auth.init"正在制作它,以便api立即发生.

实际应用

我在npm上使用节点护照和每个提供商的各种护照包进行了开源认证微服务.我对第三方使用了标准的重定向方法,为其提供了一个重定向网址.这是程序化的,所以我可以有不同的地方重定向到登录/注册和特定页面.

github.com/sebringj/athu

passportjs.org


小智 7

我的用例:在我的 React 应用程序中,用户单击后会向后端执行 API 调用。根据响应,打开新选项卡,并将 api 响应作为参数添加到新选项卡 URL(在同一域中)。

我的用例中唯一需要注意的是,接收 API 响应需要 1 秒以上的时间。因此,在新选项卡中打开 URL 时,会显示弹出窗口阻止程序(如果它处于活动状态)。

为了规避上述问题,这里是示例代码,

var new_tab=window.open()
axios.get('http://backend-api').then(response=>{
    const url="http://someurl"+"?response"
    new_tab.location.href=url;
}).catch(error=>{
    //catch error
})
Run Code Online (Sandbox Code Playgroud)

摘要:创建一个空选项卡(如上面第 1 行),当 API 调用完成后,您可以使用 url 填充该选项卡并跳过弹出窗口阻止程序。


小智 5

我尝试了多种解决方案,但他是唯一一个在所有浏览器中真正对我有用的解决方案

let newTab = window.open(); newTab.location.href = url;

  • 这对启用了弹出窗口阻止程序的人不起作用 (2认同)