Блокировать всплывающее окно Bypass на window.open, когда установлен JQuery event.preventDefault()
Я хочу условно отобразить диалог 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();
из кода, блокиратор popoup не блокирует страницу, однако для условия 1 он открывает диалог, а также открывает страницу "href".
Если я решаю один, он создает проблему для другого. Я не могу одновременно отдать должное обоим условиям.
Не могли бы вы помочь мне решить эту проблему?
Как только это будет решено, у меня есть еще одна проблема для решения, то есть навигации по диалогу OK event:)
Ответы
Ответ 1
Блокировщики всплывающих окон обычно будут использовать только window.open
, если они используются во время обработки пользовательского события (например, щелчок). В вашем случае вы вызываете window.open
позже, а не во время события, потому что $.getJSON
является асинхронным.
У вас есть два варианта:
-
Сделайте что-то еще, а не window.open
.
-
Сделайте синхронный вызов 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, если вы можете найти любой другой способ достижения своей цели. Но если вы не можете, вы идете.
Вот пример кода, который не прошел тест из-за асинхронного вызова:
Живой пример | Live source (прямые ссылки больше не работают из-за изменений в 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");
});
});
});
И вот пример, который работает, используя синхронный вызов:
Живой пример | Live source (прямые ссылки больше не работают из-за изменений в 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");
}
});
});
});
Ответ 2
вы можете вызвать window.open без блокировки браузера только в том случае, если пользователь выполняет прямое действие.
Браузер отправляет некоторый флаг и определяет это окно, открытое действием пользователя.
Итак, вы можете попробовать этот сценарий:
- var myWindow = window.open('')
- нарисовать любое загружаемое сообщение в этом окне
- при выполнении запроса просто вызовите myWindow.location = 'http://google.com'
Ответ 3
У меня была эта проблема, и у меня не было готового url до тех пор, пока обратный вызов не вернет некоторые данные. Решение заключалось в том, чтобы открыть пустое окно перед началом обратного вызова, а затем просто установить местоположение, когда возвращается обратный вызов.
$scope.testCode = function () {
var newWin = $window.open('', '_blank');
service.testCode().then(function (data) {
$scope.testing = true;
newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
});
};
Ответ 4
попробуйте это, он работает для меня,
$('#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/
Ответ 5
Окна должны быть созданы в том же стеке (также известной как микрозадача), что и инициированное пользователем событие, например, обратный вызов щелчка - чтобы они не могли быть созданы позже, асинхронно.
Тем не менее, вы можете создать окно без 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 в основном работает нормально. Если вместо этого вы хотите отобразить загрузочное сообщение (или что-либо еще) в окне, пока пользователь ждет, вы можете использовать Data URI.
window.open('data:text/html,<h1>Loading...<%2Fh1>');
Ответ 6
Этот код поможет мне. Надеюсь, что это поможет некоторым людям.
$('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';
});
});
Ответ 7
Попробуйте использовать элемент ссылку и щелкните по нему с помощью javascriipt
<a id="SimulateOpenLink" href="#" target="_blank" rel="noopener noreferrer"></a>
и script
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
Ответ 8
Наблюдение, которое событие должно было инициировать пользователем, помогло мне разобраться в первой части этого, но даже после этого 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');
});
Ответ 9
var url = window.open("", "_blank");
url.location = "url";
это сработало для меня.
Ответ 10
Я использую этот метод, чтобы избежать блокировщика всплывающих окон в моем коде React. это будет работать во всех других кодах JavaScript также.
Когда вы делаете асинхронный вызов по событию click, просто сначала откройте пустое окно, а затем введите URL-адрес в него позже, когда завершится асинхронный вызов.
const popupWindow = window.open("", "_blank");
popupWindow.document.write("<div>Loading, Plesae wait...</div>")
при успешном выполнении асинхронного вызова напишите следующее
popupWindow.document.write(resonse.url)