Как я могу определить, блокирует ли браузер всплывающее окно?

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

Какие методы может использовать вызывающее окно, чтобы убедиться, что новое окно запущено правильно?

125 popup
5.08.2008 22:01:36
8 ОТВЕТОВ
РЕШЕНИЕ

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

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}
150
22.02.2018 16:54:20
ajwaka 18.02.2014 14:08:48
@ajwaka Не могли бы вы уточнить, если этот ответ не подходит для Chrome, или есть причина, по которой другой ответ лучше для Chrome? Спасибо!
Crashalot 6.02.2020 16:00:07
@ajwaka, по крайней мере, сегодня этот код, кажется, работает на Chrome, поэтому вопрос.
Crashalot 7.02.2020 00:58:58
@Crashalot - Вы спрашиваете меня о чем-то, на что я ответил 6 лет назад. К сожалению, я больше не помню ситуацию, и браузеры прошли долгий путь за 6 лет.
ajwaka 3.04.2020 15:09:12

Обновление: всплывающие окна существуют с очень древних времен. Первоначальной идеей было показать другой контент, не закрывая главное окно. На данный момент есть другие способы сделать это: 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);

Надеюсь это поможет! :)

33
28.02.2019 14:08:44
Я думаю, что вам нужно больше подчеркиваний
Jacob Stamm 4.01.2018 21:37:07
В Firefox, это отображает пустую страницу, и вы даже не можете увидеть сообщение блокировщика всплывающих окон на открывающей странице. Как закрыть пустую страницу?
user460114 17.11.2018 23:46:40
Обратите внимание, что если всплывающий URL-адрес является загружаемым файлом (который содержится Content-Disposition: attachment;в заголовке ответа), всплывающее окно будет закрыто немедленно, поэтому setTimeoutкод не будет выполнен, и браузер пожалуется, что «Блокировщик всплывающих окон включен!». Для Chrome я рекомендую решение @ DanielB, и оно отлично работает.
wonsuc 27.02.2019 05:42:51
@wonsuc при открытии ссылки с Content-Disposition: attachment;заголовком вам не нужно открывать ее во всплывающем окне. Просто сделайте прямую ссылку на ресурс, который вы хотите загрузить, и встроенное поведение браузера позволит вам загружать, не перенаправляя вас с текущей страницы.
Kevin B 28.02.2019 13:56:10
@KevinB Я должен сказать, что я в конкретной ситуации. Я должен загрузить несколько файлов, которые генерируют PDF-файлы из HTML. И если содержимое HTML велико, иногда это занимает несколько секунд, и если я использую window.locationего, если первый файл генерируется слишком долго, он будет игнорироваться при запуске второго запроса. Вот причина, почему я должен использовать window.open, так как window.locationникогда не дает мне знать, когда ответ заканчивается.
wonsuc 28.02.2019 14:34:10

Я попробовал несколько приведенных выше примеров, но не смог заставить их работать с 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.");
    }
}
38
22.02.2018 16:57:12
@ Сурендра, пожалуйста, не могли бы вы указать, что вы имеете в виду под словом «не работает»? Ошибка при разборе? Ошибка во время выполнения? Открывается всплывающее окно, но оно помечено как заблокированное? Всплывающее окно заблокировано, но помечено как открытое? Я не вижу никакой причины, по которой проводник мог бы потерпеть неудачу, если только не разрешен вызов focus () для NULL, и в этом случае проверка на NULL перед попыткой будет работать.
FrancescoMM 22.11.2017 12:04:01
IE всегда возвращает ноль, даже если всплывающее окно было успешным.
Devin Garner 22.05.2019 20:41:07

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

Я знаю, что это не фантастика или что-то еще, но это не может быть проще и требует всего около 5 минут тестирования, тогда вы можете перейти к другим кошмарам.

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

12
26.02.2016 22:49:35
К сожалению, иногда все другие решения в этом вопросе неприемлемы - только этот. Почему? Потому что все они пытаются отобразить всплывающее окно, а не просто определить, включены ли всплывающие окна. Что если я хочу сделать это молча?
Sagi Mann 6.03.2018 15:08:13

Я перепробовал множество решений, но единственное, что я мог придумать, которое также работало с 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 для учета первоначального открытия и закрытия, поэтому оно никогда не будет точным. Это будет позиция проб и ошибок.

Добавьте это к вашему списку попыток.

0
22.02.2018 16:57:40

Используя событие 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 черных окна в фоновом режиме

функция возвращает логическое значение.

-1
29.05.2018 15:56:05

Я объединил решения @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.
}
1
27.02.2019 05:53:13
isPopupBlockerActivated функция никогда не возвращается на return (popupWindow.innerHeight > 0) === false;. Ваша функция возвращает false, когда ваш браузер не Chrome. Потому что onload - это асинхронный процесс. Ваша функция возвращает false, а затем выполняется onload, но ее результат никогда не возвращается.
Onur Gazioğlu 12.04.2019 05:18:04

Простой подход, если у вас также есть дочерний код , заключается в создании простой переменной в его 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.

0
31.01.2020 07:04:31