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

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

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

Ответов (8)

Решение

Если вы используете 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);

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

Я попробовал несколько приведенных выше примеров, но мне не удалось заставить их работать с 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.");
    }
}

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

Добавьте это в свой список попыток.

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

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

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

Я объединил решения @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.
}

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

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

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