代码之家  ›  专栏  ›  技术社区  ›  Pablo Fernandez

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

  •  142
  • Pablo Fernandez  · 技术社区  · 16 年前

    我正在开发一个纯javascript的oauth身份验证流,我想在弹出窗口中向用户显示“grant access”窗口,但是它被阻塞了。

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

    8 回复  |  直到 7 年前
        1
  •  253
  •   dthorpe    13 年前

    一般规则是弹出式阻止程序将在 window.open 或者从javascript调用类似的 直接用户操作 . 也就是说,你可以打电话 打开新窗口 作为对按钮单击的响应,弹出窗口阻止程序没有命中,但是如果您将相同的代码放入计时器事件中,它将被阻止。调用链的深度也是一个因素-一些较旧的浏览器只查看直接调用方,较新的浏览器可以稍微回溯,看看调用方的调用方是否是鼠标单击等。尽量保持浅,以避免弹出窗口阻止程序。

        2
  •  155
  •   user229044    8 年前

    基于 Jason Sebring very useful tip ,以及所涵盖的内容 here there ,我找到了一个完美的解决方案:

    带有javascript片段的伪代码:

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

      var importantStuff = window.open('', '_blank');
      

      可选:添加一些“等待”信息消息。实例:

      a)外部html页面:用

      var importantStuff = window.open('http://example.com/waiting.html', '_blank');
      

      b)正文:在上面一行的下面加上以下一行:

      importantStuff.document.write('Loading preview...');
      
    2. 准备好后用内容填充它(例如,当返回ajax调用时)

      importantStuff.location.href = 'http://shrib.com';
      

    丰富通话内容 window.open 无论你需要什么样的选择。

    实际上,我使用这个解决方案进行mailto重定向,它可以在我所有的浏览器(windows 7,android)上运行。这个 _blank 比特帮助邮件重定向到移动工作,顺便说一句。

    你的经验?有什么方法可以改进吗?

        3
  •  20
  •   David    7 年前

    此外,瑞士邮政先生,在我的情况下 打开新窗口 是在一个承诺中启动的,它开启了弹出窗口阻止程序,我的解决方案是: 角度:

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

    浏览器服务:

    this.openNewTab = function(){
         var newTabWindow = $window.open();
         return newTabWindow;
    }
    
    this.updateTabLocation = function(tabLocation, tab) {
         if(!tabLocation){
           tab.close();
         }
         tab.location.href = tabLocation;
    }
    

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

        4
  •  16
  •   FrancescoMM    10 年前

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

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

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

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

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

    这样你将有一个弹出窗口如果它工作,和一个空白窗口如果 不是。

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

    • 打开一个空白窗口,如示例中所示,然后继续
    • 打开一个假弹出窗口(页面内的iframe)
    • 通知用户(“请允许此网站弹出窗口”)
    • 打开一个空白窗口,然后通知用户 等。。
        5
  •  8
  •   King Friday    10 年前

    来自google的oauth javascript api:

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

    请看下面的区域:

    设置身份验证

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

    我想这与上面的真实答案有关,它如何解释如果有立即的响应,它不会触发弹出警报。“gapi.auth.init”正在生成它,因此api会立即发生。

    实际应用

    我使用npm上的node passport和每个提供者的各种passport包创建了一个开源的身份验证微服务。我对第三方使用了一种标准的重定向方法,给它一个返回的重定向url。这是编程的,所以我可以有不同的地方重定向回如果登录/注册和在特定的页面。

    github.com/sebringj/athu

    passportjs.org

        6
  •  0
  •   user3479425    8 年前

    我不想创建新页面,除非回调成功返回,所以我这样做 模拟 用户单击:

    function submitAndRedirect {
      apiCall.then(({ redirect }) => {
          const a = document.createElement('a');
          a.href = redirect;
          a.target = '_blank';
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
      });
    }
    
        7
  •  0
  •   pomobc    8 年前

    我尝试了多种解决方案,但在所有浏览器中只有他的解决方案对我有效

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

        8
  •  -4
  •   Alejandro Vales user1768079    7 年前

    最简单的解决方法是:

    1. 不要使用document.open()。
    2. 相反,请使用this.document.location.ref=location;其中location是要加载的URL

    前任:

    <script>
    function loadUrl(location)
    {
    this.document.location.href = location;
    }</script>
    
    <div onclick="loadUrl('company_page.jsp')">Abc</div>
    

    这对我很有效。 干杯

    推荐文章