Обойти блокировку всплывающих окон в window.open, когда JQuery event.preventDefault () установлен - PullRequest
95 голосов
/ 01 марта 2012

Я хочу показать диалог JQuery условно при событии щелчка гиперссылки.

У меня есть требование, как при условии1 открыть диалог JQuery, и если условие1 не выполнено, перейдите на страницу, на которую ссылается тег 'href', чье событие клика идет речь.

Я могу вызвать функцию при событии нажатия ссылки. Эта функция теперь проверяет указанное условие, выполняя другой URL-адрес (который выполняет мой контроллер Spring и возвращает ответ).

Все отлично работает, только блокировщик всплывающих окон блокирует только window.open.

$('a[href*=/viewpage?number]').live('click', function(e) {
    e.preventDefault();
    redirectionURL = this.href;
    pageId= getUrlVars(redirectionURL)["number"];
    $.getJSON("redirect/" + pageId, {}, function(status) {
        if (status == null) {
            alert("Error in verifying the status.");
        } else if(!status) {
            $("#agreement").dialog("open");
        } else {
            window.open(redirectionURL);
        }
    });
});

Если я удаляю e.preventDefault(); из кода, блокировщик всплывающих окон не блокирует страницу, однако для условия1 он открывает диалог, а также открывает страницу 'href'.

Если я решу одно, это создаст проблему для другого. Я не могу судить оба условия одновременно.

Не могли бы вы помочь мне решить эту проблему, пожалуйста?

Как только это будет решено, у меня есть еще одна проблема для решения, т. Е. Навигация по событию OK диалога:)

Ответы [ 10 ]

141 голосов
/ 01 марта 2012

Блокировщики всплывающих окон обычно разрешают window.open, если используется во время обработки пользовательского события (например, щелчка).В вашем случае вы звоните window.open позже , а не во время события, потому что $.getJSON является асинхронным.

У вас есть два варианта:

  1. Сделайте что-нибудь еще, а не window.open.

  2. Сделайте вызов ajax синхронным, чего обычно следует избегать, например чумы, так как он блокирует пользовательский интерфейсбраузер.$.getJSON эквивалентно:

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });
    

    ... и, таким образом, вы можете сделать ваш $.getJSON синхронный вызов, сопоставив свои параметры с приведенным выше и добавив async: false:

    $.ajax({
        url:      "redirect/" + pageId,
        async:    false,
        dataType: "json",
        data:     {},
        success:  function(status) {
            if (status == null) {
                alert("Error in verifying the status.");
            } else if(!status) {
                $("#agreement").dialog("open");
            } else {
                window.open(redirectionURL);
            }
        }
    });
    

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

    Вот пример кода, который не проходит тест из-за асинхронного вызова:

    Живой пример | Живой источник (Живые ссылки больше не работают из-за изменений в JSBin)

    jQuery(function($) {
      // This version doesn't work, because the window.open is
      // not during the event processing
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.getJSON("http://jsbin.com/uriyip", function() {
          window.open("http://jsbin.com/ubiqev");
        });
      });
    });
    

    И вот пример, который работает, используя синхронныйЗвоните:

    Живой пример | Живой источник (Живые ссылки больше не работают из-за изменений в JSBin)

    jQuery(function($) {
      // This version does work, because the window.open is
      // during the event processing. But it uses a synchronous
      // ajax call, locking up the browser UI while the call is
      // in progress.
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.ajax({
          url:      "http://jsbin.com/uriyip",
          async:    false,
          dataType: "json",
          success:  function() {
            window.open("http://jsbin.com/ubiqev");
          }
        });
      });
    });
    
60 голосов
/ 29 октября 2013

Вы можете вызывать window.open без блокировки браузера, только если пользователь выполняет какие-либо действия напрямую. Браузер отправляет какой-либо флаг и определяет, что окно открывается пользовательским действием.

Итак, вы можете попробовать этот сценарий:

  1. var myWindow = window.open ('')
  2. нарисуйте любое загрузочное сообщение в этом окне
  3. когда запрос выполнен, просто вызовите myWindow.location = 'http://google.com'
36 голосов
/ 02 октября 2015

У меня была эта проблема, и у меня не было готового URL, пока обратный вызов не вернет некоторые данные.Решение состояло в том, чтобы открыть пустое окно перед началом обратного вызова, а затем просто установить местоположение, когда обратный вызов возвращается.

$scope.testCode = function () {
    var newWin = $window.open('', '_blank');
    service.testCode().then(function (data) {
        $scope.testing = true;
        newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
    });
};
18 голосов
/ 28 мая 2015

попробуйте это, у меня это работает,

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

Это скрипка для этого http://jsfiddle.net/safeeronline/70kdacL4/1/

7 голосов
/ 25 мая 2016

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

Тем не менее, вы можете создать окно без URL и затем изменить URL этого окна , как только вы его узнаете , даже асинхронно!

window.onclick = () => {
  // You MUST create the window on the same event
  // tick/stack as the user-initiated event (e.g. click callback)
  const googleWindow = window.open();

  // Do your async work
  fakeAjax(response => {
    // Change the URL of the window you created once you
    // know what the full URL is!
    googleWindow.location.replace(`https://google.com?q=${response}`);
  });
};

function fakeAjax(callback) {
  setTimeout(() => {
    callback('example');
  }, 1000);
}

Современные браузеры откроют окно с пустой страницей (часто называемой about:blank), и, если ваша асинхронная задача получить URL-адрес довольно быстро, получающийся в результате UX в основном работает нормально. Если вместо этого вы хотите отобразить загрузочное сообщение (или что-либо еще) в окне, пока пользователь ждет, вы можете использовать URI данных .

window.open('data:text/html,<h1>Loading...<%2Fh1>');
3 голосов
/ 16 октября 2017

Попробуйте использовать элемент ссылка и щелкните по нему с помощью javascriipt

<a id="SimulateOpenLink" href="#" target="_blank" rel="noopener noreferrer"></a>

и сценария

function openURL(url) {
    document.getElementById("SimulateOpenLink").href = url
    document.getElementById("SimulateOpenLink").click()
}

Используйте его следующим образом

//do stuff
var id = 123123141;
openURL("/api/user/" + id + "/print") //this open webpage bypassing pop-up blocker
openURL("https://www.google.com") //Another link
3 голосов
/ 14 мая 2017

Этот код поможет мне.Надеюсь, что это поможет некоторым людям

$('formSelector').submit( function( event ) {

    event.preventDefault();

    var newWindow = window.open('', '_blank', 'width=750,height=500');

    $.ajax({

        url: ajaxurl,
        type: "POST",
        data: { data },

    }).done( function( response ) {

        if ( ! response ) newWindow.close();
        else newWindow.location = '/url';

    });
});
2 голосов
/ 06 января 2014

Замечание о том, что событие должно было инициироваться пользователем, помогло мне понять первую часть этого, но даже после этого Chrome и Firefox все еще блокировали новое окно. Вторая часть добавляла target = "_ blank" к ссылке, которая упоминалась в одном комментарии.

В итоге: вам нужно вызвать window.open из события, инициированного пользователем, в этом случае нажмите на ссылку, и эта ссылка должна иметь target = "_ blank".

В приведенном ниже примере ссылка использует class = "button-twitter".

$('.button-twitter').click(function(e) {
  e.preventDefault();
  var href = $(this).attr('href');
  var tweet_popup = window.open(href, 'tweet_popup', 'width=500,height=300');
});
1 голос
/ 29 августа 2018
var url = window.open("", "_blank");
url.location = "url";

это сработало для меня.

0 голосов
/ 23 мая 2019

Я использую этот метод, чтобы избежать блокировщика всплывающих окон в моем коде React. это будет работать и во всех других кодах javascript.

Когда вы делаете асинхронный вызов по событию click, просто сначала откройте пустое окно, а затем введите URL-адрес в него позже, когда завершится асинхронный вызов.

const popupWindow = window.open("", "_blank");
popupWindow.document.write("<div>Loading, Plesae wait...</div>")

в случае успеха асинхронного вызова, напишите следующее

popupWindow.document.write(resonse.url)
...