Как запретить Google Chrome блокировать мое всплывающее окно?

На моем сайте есть кнопка, которая просто используется для вызова функции, которая вызывает 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 блокируется весь браузер. Подумайте о другом способе проверки:

  • это может быть первое, что вы делаете во всплывающем окне
  • Вы можете открыть всплывающее окно при нажатии и манипулировать им позже, когда обратный вызов срабатывает
  • Вы можете потребовать, чтобы пользователь снова нажал какую-то кнопку, чтобы вызвать всплывающее окно (вероятно, худшее решение)
  • Вы можете сделать это при загрузке страницы

В ответ на отличный ответ Эмиля: "Вы можете открыть всплывающее окно при нажатии и манипулировать им позже, когда сработает обратный вызов". Я использовал эту реализацию.

$('#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;
});

Вы можете открыть окно, которое не заблокировано только под событием onclick, если вы открываете его при вызове ajax, оно считается всплывающим. Однако я использовал этот метод с успехом в течение некоторого времени, чтобы открыть всплывающее окно и не быть заблокированным.

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

Вот ванильное решение JavaScript, которое я использую для одного из своих веб-сайтов, чтобы обойти блокировщик всплывающих окон в Chrome.

Допустим, у нас есть следующая кнопка HTML:

<button id="clickMe">Click Me!</button>

Теперь, когда пользователь нажимает кнопку, первое, что вам нужно сделать, это открыть новое пустое окно. После завершения запроса Fetch обновите фактический URL-адрес окна. Если запрос не прошел, просто закройте окно:

const button = document.querySelector('#clickMe');

// add click event listener
button.addEventListener('click', () => {

    // open an empty window
    const tab = window.open('about:blank');

    // make an API call
    fetch('https://reqres.in/api/users')
        .then(res => res.json())
        .then(json => {

            // TODO: do something with JSON response

            // update the actual URL
            tab.location = 'https://attacomsian.com';
            tab.focus();
        })
        .catch(err => {
            // close the empty window
            tab.close();
        });
});

В моем случае window.open был запущен внутри promise в angular, который включил блокировку всплывающих окон, мое решение было:

$scope.gotClick = function(){

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

browserService:

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

Я использую этот метод:

  1. Перенаправить на ту же страницу с URL загрузки, добавленным в качестве параметра:
window.location.href = window.location.protocol + '//' +
                    window.location.host + window.location.pathname +
                    "?download=" + encodeURIComponent(urlToDownload)
  1. Определите этот параметр при инициализации страницы и перенаправьте на загрузку:
function param(name){
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (!results) { return 0; }
    return results[1] || 0;
}

var downloadParam = param('download');
if (downloadParam) {
    window.location = decodeURIComponent(downloadParam);
}
Другие вопросы по тегам