Иногда я сталкиваюсь с веб-страницей, которая пытается открыть новое окно (для пользовательского ввода или чего-то важного), но блокировщик всплывающих окон предотвращает это.
Какие методы может использовать вызывающее окно, чтобы убедиться, что новое окно запущено правильно?
Если вы используете JavaScript, чтобы открыть всплывающее окно, вы можете использовать что-то вроде этого:
var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
//POPUP BLOCKED
}
Обновление: всплывающие окна существуют с очень древних времен. Первоначальной идеей было показать другой контент, не закрывая главное окно. На данный момент есть другие способы сделать это: JavaScript может отправлять запросы на сервер, поэтому всплывающие окна используются редко. Но иногда они все еще удобны.
В прошлом злые сайты много злоупотребляли всплывающими окнами. Плохая страница может открыть множество всплывающих окон с рекламой. Поэтому сейчас большинство браузеров пытаются блокировать всплывающие окна и защищать пользователя.
Большинство браузеров блокируют всплывающие окна, если они вызываются вне пользовательских обработчиков событий, таких как onclick.
Если вы думаете об этом, это немного сложно. Если код находится непосредственно в обработчике onclick, то это просто. Но что всплывающее окно открывается в setTimeout?
Попробуйте этот код:
// open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);
Всплывающее окно открывается в Chrome, но блокируется в Firefox.
... И это работает в Firefox тоже:
// open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);
Разница в том, что Firefox обрабатывает тайм-аут в 2000 мс или менее приемлемо, но после него - убирает «доверие», предполагая, что теперь он «вне действия пользователя». Итак, первый заблокирован, а второй нет.
Оригинальный ответ, который был в текущем 2012 году:
Это решение для проверки всплывающих окон было протестировано в FF (v11), Safari (v6), Chrome (v23.0.127.95) и IE (v7 и v9). Обновите функцию displayError, чтобы обрабатывать сообщение об ошибке по своему усмотрению.
var popupBlockerChecker = { check: function(popup_window){ var scope = this; if (popup_window) { if(/chrome/.test(navigator.userAgent.toLowerCase())){ setTimeout(function () { scope.is_popup_blocked(scope, popup_window); },200); }else{ popup_window.onload = function () { scope.is_popup_blocked(scope, popup_window); }; } } else { scope.displayError(); } }, is_popup_blocked: function(scope, popup_window){ if ((popup_window.innerHeight > 0)==false){ scope.displayError(); } }, displayError: function(){ alert("Popup Blocker is enabled! Please add this site to your exception list."); } };
Использование:
var popup = window.open("http://www.google.ca", '_blank'); popupBlockerChecker.check(popup);
Надеюсь это поможет! :)
Content-Disposition: attachment;
в заголовке ответа), всплывающее окно будет закрыто немедленно, поэтому setTimeout
код не будет выполнен, и браузер пожалуется, что «Блокировщик всплывающих окон включен!». Для Chrome я рекомендую решение @ DanielB, и оно отлично работает. Content-Disposition: attachment;
заголовком вам не нужно открывать ее во всплывающем окне. Просто сделайте прямую ссылку на ресурс, который вы хотите загрузить, и встроенное поведение браузера позволит вам загружать, не перенаправляя вас с текущей страницы. window.location
его, если первый файл генерируется слишком долго, он будет игнорироваться при запуске второго запроса. Вот причина, почему я должен использовать window.open
, так как window.location
никогда не дает мне знать, когда ответ заканчивается. Я попробовал несколько приведенных выше примеров, но не смог заставить их работать с Chrome. Этот простой подход, кажется, работает с Chrome 39, Firefox 34, Safari 5.1.7 и IE 11. Вот фрагмент кода из нашей библиотеки JS.
openPopUp: function(urlToOpen) {
var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");
try {
popup_window.focus();
} catch (e) {
alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
}
}
Одно «решение», которое всегда будет работать независимо от компании или версии браузера, - просто поместить предупреждающее сообщение на экране, где-то рядом с элементом управления, который создаст всплывающее окно, которое вежливо предупреждает пользователя о том, что для действия требуется всплывающее окно. и, пожалуйста, включите их для сайта.
Я знаю, что это не фантастика или что-то еще, но это не может быть проще и требует всего около 5 минут тестирования, тогда вы можете перейти к другим кошмарам.
После того, как пользователь разрешил всплывающие окна для вашего сайта, будет также разумно, если вы не переборщите с всплывающими окнами. Последнее, что вы хотите сделать, это раздражать ваших посетителей.
Я перепробовал множество решений, но единственное, что я мог придумать, которое также работало с uBlock Origin, - это использовать тайм-аут для проверки закрытого состояния всплывающего окна.
function popup (url, width, height) {
const left = (window.screen.width / 2) - (width / 2)
const top = (window.screen.height / 2) - (height / 2)
let opener = window.open(url, '', `menubar=no, toolbar=no, status=no, resizable=yes, scrollbars=yes, width=${width},height=${height},top=${top},left=${left}`)
window.setTimeout(() => {
if (!opener || opener.closed || typeof opener.closed === 'undefined') {
console.log('Not allowed...') // Do something here.
}
}, 1000)
}
Очевидно, что это взломать; как и все решения этой проблемы.
Вы должны предоставить достаточно времени в вашем setTimeout для учета первоначального открытия и закрытия, поэтому оно никогда не будет точным. Это будет позиция проб и ошибок.
Добавьте это к вашему списку попыток.
Используя событие onbeforeunload, мы можем проверить следующее
function popup()
{
var chk=false;
var win1=window.open();
win1.onbeforeunload=()=>{
var win2=window.open();
win2.onbeforeunload=()=>{
chk=true;
};
win2.close();
};
win1.close();
return chk;
}
это откроет 2 черных окна в фоновом режиме
функция возвращает логическое значение.
Я объединил решения @Kevin B и @ DanielB.
Это намного проще.
var isPopupBlockerActivated = function(popupWindow) {
if (popupWindow) {
if (/chrome/.test(navigator.userAgent.toLowerCase())) {
try {
popupWindow.focus();
} catch (e) {
return true;
}
} else {
popupWindow.onload = function() {
return (popupWindow.innerHeight > 0) === false;
};
}
} else {
return true;
}
return false;
};
Использование:
var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
// Do what you want.
}
isPopupBlockerActivated
функция никогда не возвращается на return (popupWindow.innerHeight > 0) === false;
. Ваша функция возвращает false, когда ваш браузер не Chrome. Потому что onload - это асинхронный процесс. Ваша функция возвращает false, а затем выполняется onload, но ее результат никогда не возвращается. Простой подход, если у вас также есть дочерний код , заключается в создании простой переменной в его html, как показано ниже:
<script>
var magicNumber = 49;
</script>
А затем проверьте его наличие у родителя что-то похожее на следующее:
// Create the window with login URL.
let openedWindow = window.open(URL_HERE);
// Check this magic number after some time, if it exists then your window exists
setTimeout(() => {
if (openedWindow["magicNumber"] !== 32) {
console.error("Window open was blocked");
}
}, 1500);
Мы ждем некоторое время, чтобы убедиться, что веб-страница была загружена, и проверим ее существование. Очевидно, что если окно не загрузится после 1500 мс, тогда переменная все равно будет undefined
.