Chrome window.open после запроса ajax действует как всплывающее окно

У меня есть ситуация, когда пользователь нажимает кнопку, я выполняю запрос ajax, а затем использую результат запроса ajax для создания URL-адреса, который я хочу открыть на новой вкладке. Тем не менее, в chrome, когда я вызываю window.open в обработчике успеха для запроса ajax, он открывается в новом окне, как всплывающее окно (и блокируется всплывающими блоками). Я предполагаю, что, поскольку код успеха асинхронен из кода обработки кликов, который хром считает, что он не был вызван щелчком, хотя он причинно связан с щелчком. Есть ли способ предотвратить это, не делая синхронный запрос ajax?

EDIT Вот несколько минимальных кодов, которые демонстрируют это поведение:

$('#myButton').click(function() {
    $.ajax({
        type: 'POST',
        url: '/echo/json/',
        data: {'json': JSON.stringify({
            url:'http://google.com'})},
        success: function(data) {
            window.open(data.url,'_blank');
        }
    });
});

http://jsfiddle.net/ESMUA/2/

Одна нота пояснений: меня больше беспокоит ее открытие в отдельном окне, а не в виде вкладки, чем я о том, что он блокируется блокировщиком всплывающих окон.

Ответы

Ответ 1

Попробуйте добавить

window.open(url,'_blank');

редактировать

Ну, я не думаю, что вы можете обойти всплывающие блокираторы при открытии страницы, которая не является непосредственным результатом действия пользователя (т.е. Не async).

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

var $a = $('<a>', {
        href: url,
        target: '_blank' 
    });

$(document.body).append($a);
$a.click();

Изменить 2

Похоже, вам лучше синхронизировать ситуацию.

Пока новое окно является "одним и тем же источником", у вас есть возможность манипулировать им с помощью JS.

$('#a').on('click', function(e){
    e.preventDefault();
    var wi = window.open('about:blank', '_blank');

    setTimeout(function(){ // async
        wi.location.href = 'http://google.com';
    }, 500);
});

Ответ 2

Попробуйте добавить async: false. Он должен работать

$('#myButton').click(function() {
$.ajax({
    type: 'POST',
    async: false,
    url: '/echo/json/',
    data: {'json': JSON.stringify({
        url:'http://google.com'})},
    success: function(data) {
        window.open(data.url,'_blank');
    }
});
});

Ответ 3

Ответ, отправленный на @pstenstrm выше (Edit 2), в основном работает, но я добавил только одну строку, чтобы сделать решение более элегантным. В моем случае вызов ajax занял больше секунды, и пользователь, столкнувшийся с пустой страницей, столкнулся с проблемой. Хорошо, что есть способ разместить содержимое HTML в новом окне, которое мы только что создали.

например:

$('#a').on('click', function(e){
    e.preventDefault();
    var wi = window.open('about:blank', '_blank');
    $(wi.document.body).html("<p>Please wait while you are being redirected...</p>");

    setTimeout(function(){ // async
        wi.location.href = 'http://google.com';
    }, 500);
});

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

Ответ 4

Что для меня работало:

var win = window.open('about:blank', '_blank');

myrepository.postmethod('myserviceurl', myArgs)
.then(function(result) {
    win.location.href = 'http://yourtargetlocation.com/dir/page';
});

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

Ответ 5

Нет надежного способа. Если ваша вкладка/окно заблокирована поп-блокером в FF и IE6 SP2, тогда window.open вернет значение null.

https://developer.mozilla.org/en-US/docs/Web/API/Window/open#FAQ

Как я могу узнать, когда окно заблокировано блокировщиком всплывающих окон? С помощью встроенных блокировщиков всплывающих окон Mozilla/Firefox и Internet Explorer 6 SP2 вы должны проверить возвращаемое значение window.open(): оно будет null, если окно не было разрешено открывать. Однако для большинства других блокировщиков всплывающих окон нет надежного способа.