如何防止 Google Chrome 阻止我的弹出窗口?

IT技术 javascript google-chrome popup popup-blocker
2021-03-21 22:15:44

在我的网站上有一个按钮,它只是用来调用一个调用的函数window.open,但是,最近需要进行调整以在打开弹出窗口之前进行服务器端检查。

自从添加了执行 AJAX 调用的代码后,浏览器就会阻止success在 AJAX 调用回调中打开的弹出窗口我读到,如果不是由用户单击事件调用,浏览器可能会阻止弹出窗口,因此我尝试将 AJAX 请求设置为async: false,这解决了 Firefox 中的问题,但 Google Chrome 仍会阻止我的弹出窗口。有什么办法可以解决这个问题吗?

我可以将服务器端检查移到在弹出窗口中打开的页面,但如果可能的话,我想在打开弹出窗口之前执行此操作。

代码:

<a id="attackButton" href="#">Attack Base!</a>

<script type="text/javascript">
$(function() {
    $('#attackButton').click(function() {
        $.ajax({
            url: baseurl + '/index.php?option=com_pbbgs&format=raw&getinfo=goingame',
            data: { 'gameid': 618 },
            dataType: 'text',
            async: false,
            type: 'POST',
            success: function(data) {
                eval(data);

                if (window.gameURL) {
                    goingameRaw();
                }
            }
        });

        return false;
    });
});

function goingameRaw()
{
    window.open(window.gameURL,'test','left=20,top=20,width=1024,height=640,toolbar=0,resizable=0,location=0');
}
</script>

示例响应正文:

window.gameURL="http://mydomain.com/index.php?option=com_pbbgs&format=raw&startgame=618&width=1024&height=640";checktutorial('js','attack');
6个回答

是的,弹出窗口应该是用户操作的直接结果。在 ajax 回调中执行它们不会成功。此外,使用async:false是不好的 - 在 FF 中,已知会阻止整个浏览器。想想其他一些方法来进行检查:

  • 这可能是你在弹出窗口中做的第一件事
  • 您可以在单击时打开弹出窗口并稍后在回调触发时对其进行操作
  • 您可以要求用户再次单击某个按钮以触发弹出窗口(可能是最糟糕的解决方案)
  • 您可以在页面加载时执行此操作
@Emil 为什么 3 是最糟糕的?在 Javascript 上单击一次确认 UI 何时与登录状态不同步,因为用户点击了后退按钮或其他什么?我要试试看。
2021-05-04 22:15:44
是的,我同意这很糟糕。
2021-05-04 22:15:44
我也是这么怀疑的,谢谢。我实施了你的第二个建议。
2021-05-10 22:15:44
这里有一个很好的例子theandystratton.com/2012/...
2021-05-16 22:15:44
@埃米尔·伊万诺夫。第二个选项对我有用。即首先打开窗口然后操作。谢谢。
2021-05-16 22:15:44

跟进 Emil 的出色回答,“您可以在单击时打开弹出窗口,稍后在回调触发时对其进行操作”。我使用了这个实现。

$('#attackButton').click(function() {

新代码在这里

    var win = window.open('');
    window.oldOpen = window.open;
    window.open = function(url) { // reassignment function
        win.location = url;
        window.open = oldOpen;
        win.focus();
    }

结束新代码

    $.ajax({
        url: baseurl + '/index.php',
        data: { 'gameid': 618 },
        type: 'POST',
        success: function(data) {
            window.open('some url'); // will call reassignment function above 
        }
    });

    return false;
});
无需添加全局变量“oldOpen”并重载本机全局“open”。这都在同一个闭包内,作用域链非常好。只需创建一个本地函数“myWinGo”或其他任何并使用它。
2021-04-24 22:15:44
哇,天才小功能!它甚至会在之后恢复 window.open。
2021-04-27 22:15:44
这是本示例的一个好点。但是,如果 window.open 调用位于您不想更改的库中,或者如果您希望将调用保留为 window.open 以提高可读性,那么覆盖是一个不错的选择。
2021-05-03 22:15:44
@BenjaminCrouzier 不幸的是,那种与用户点击断开连接的窗口弹出窗口似乎是 Chrome 阻止的。
2021-05-07 22:15:44
一旦var win = window.open('');执行,我就会得到一个空白的新标签理想情况下,我希望新窗口仅在 ajax 成功时打开。
2021-05-16 22:15:44

您可以在 onclick 事件下打开一个未被阻止的窗口,如果您在 ajax 调用中打开它,则它被视为弹出窗口。但是我成功地使用了这种方法一段时间来打开一个弹出窗口并且没有被阻止。

http://en.nisi.ro/blog/development/javascript/open-new-window-window-open-seen-chrome-popup/

在我的情况下,它window.open是在一个promise角度内启动的,它打开了弹出窗口阻止程序,我的解决方案是:

$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响应打开新选项卡而不调用弹出窗口阻止程序。

以前的解决方案对我不起作用,但我基于它并使用了命名窗口。

internalCounter++;
var tabbedWin = window.open('','windowName_'+internalCounter);
$.ajax({
        url: url,
        async: false,
        indexValue:internalCounter,
        success: function(){
            var w= window.open(url, 'windowName_'+this.indexValue);                
            w.focus();
        }
})
参考 gabe 的解决方案
2021-04-26 22:15:44