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

Определить, блокирует ли браузер всплывающее окно

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

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

9 ответов

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

var newWin = window.open(url);

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}

Вот ответ для хрома: обнаружить заблокированное всплывающее окно в хроме

@ ajwaka, не могли бы вы уточнить, не подходит ли этот ответ для Chrome или есть ли причина, по которой другой ответ лучше подходит для Chrome? Благодарность!

@ ajwaka, по крайней мере, сегодня этот код работает в Chrome, отсюда и вопрос.

@ Crashalot - Вы спрашиваете меня о чем-то, на что я ответил 6 лет назад - к сожалению, я больше не помню ситуацию, и браузеры прошли долгий путь за 6 лет.

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

@ Surendra, пожалуйста, не могли бы вы уточнить, что вы имеете в виду под «не работает»? Ошибка во время синтаксического анализа? Ошибка во время выполнения? Всплывающее окно открывается, но оно помечено как заблокированное? Всплывающее окно заблокировано, но помечено как открытое? Я не вижу причин, по которым проводник не сможет это сделать, если только не разрешен вызов focus() для NULL, и в этом случае проверка на NULL перед попыткой просто сработает.

IE всегда возвращает null, даже если всплывающее окно было успешным.

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

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

Я думаю, вам нужно больше подчеркиваний

В firefox это отображает пустую страницу, и вы даже не можете увидеть сообщение блокировщика всплывающих окон на странице открытия. Как закрыть пустую страницу?

Обратите внимание, что если URL-адрес всплывающего окна является загружаемым файлом (который указан Content-Disposition: attachment;в заголовке ответа), всплывающее окно немедленно закроется, поэтому setTimeout код завершится ошибкой, и браузер сообщит, что «Блокировщик всплывающих окон включен!». Для Chrome я рекомендую решение @ DanielB, и оно отлично работает.

@ wonsuc при открытии ссылки с Content-Disposition: attachment; заголовком вам не нужно открывать ее во всплывающем окне. Просто сделайте прямую ссылку на ресурс, который вы хотите загрузить, и собственное поведение браузера позволит вам загрузить его, не перенаправляя вас с текущей страницы.

@ KevinB Должен сказать, что я в особой ситуации. Мне нужно загрузить несколько файлов, которые генерируют PDF-файлы из HTML. И если содержимое HTML большое, иногда это занимает несколько секунд, и если я использую window.location для этого, если первый файл слишком долго генерируется, он будет проигнорирован при запуске второго запроса. Вот почему я должен использовать window.open, так как window.location никогда не сообщает мне, когда ответ заканчивается.

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

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

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

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

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

Я объединил решения @ 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, а затем выполняется загрузка, но ее результат никогда не возвращается.

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

как насчет того, чтобы поместить это в окно обработчика загрузки.

@ bhansa Мы не можем, потому что проверка происходит в родительском окне, тогда как magicNumber переменная находится в дочернем окне.

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

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

Для некоторых блокировщиков всплывающих окон это не работает, но я использую его как базовое решение и добавляю try {} catch

try {
        const newWindow = window.open(url, '_blank');
        if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined')         {
            return null;
        }

        (newWindow as Window).window.focus();
        newWindow.addEventListener('load', function () {
            console.info('Please allow popups for this website')
        })
        return newWindow;
    } catch (e) {
        return null;
    }

Это попытается вызвать функцию addEventListaner, но если всплывающее окно не открыто, оно сломается и перейдет к перехвату, затем спросит, является ли его объект или null, и запустит остальную часть кода.

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

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

Window.open()

Метод open() интерфейса Window загружает указанный ресурс в новый или существующий контекст просмотра (то есть на вкладку, окно или iframe) под указанным именем.

Синтаксис

open()
open(url)
open(url, target)
open(url, target, windowFeatures)

Параметры

url

(Необязательно) Строка, указывающая URL-адрес или путь к загружаемому ресурсу. Если указана пустая строка ("") или этот параметр опущен, в целевом контексте просмотра открывается пустая страница.

target

(Необязательно) Строка без пробелов, указывающая имя контекста просмотра, в который загружается ресурс. Если имя не идентифицирует существующий контекст, создается новый контекст и ему присваивается указанное имя. Можно также использовать специальные target ключевые слова, _self, _blank, _parent, и _top.

Это имя можно использовать в качестве целевого атрибута<a> или <form> элементов.

windowFeatures

(Необязательно) Строка, содержащая список функций окна, разделенных запятыми, в форме name=value — или для логических функций просто name. Эти функции включают в себя такие параметры, как размер и положение окна по умолчанию, открывать или нет всплывающее окно минимального размера и т. д. Поддерживаются следующие параметры:

popup

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

Если popup не включено и не объявлено оконных функций, новым контекстом просмотра будет вкладка.

Примечание. Указание любых функций в windowFeatures параметре, кроме noopener или noreferrer, также приводит к запросу всплывающего окна.

Чтобы включить эту функцию, укажите popup либо вообще без значения, либо установите для него значение yes, 1, или true.

Пример: popup=yes, popup=1, popup=true, и popup все имеют одинаковые результаты.

width или innerWidth

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

height или innerHeight

Определяет высоту области содержимого, включая полосы прокрутки. Минимальное требуемое значение равно 100.

left или screenX

Указывает расстояние в пикселях от левой стороны рабочей области, как определено операционной системой пользователя, где будет создано новое окно.

top или screenY

Указывает расстояние в пикселях от верхней стороны рабочей области, как определено операционной системой пользователя, где будет создано новое окно.

noopener

Если эта функция установлена, новое окно не будет иметь доступа к исходному окну через Window.opener и возвращает null.

Когда noopener используется, непустые целевые имена, отличные от _top, _self, и _parent, обрабатываются аналогично _blank точки зрения принятия решения об открытии нового контекста просмотра.

noreferrer

Если эта функция установлена, браузер пропустит Referer заголовок, а также установит noopener значение true. См. rel="noreferrer" дополнительную информацию.

Примечание. Запрошенные значения позиции (top, left), и запрошенного размера (width, height) в windowFeatures будут исправлены, если какое-либо из таких запрошенных значений не позволяет отображать все всплывающее окно браузера в рабочей области для приложений операционной системы пользователя. Другими словами, никакая часть нового всплывающего окна не может быть изначально расположена за пределами экрана.

Описание

Объект WindowProxy. Возвращенная ссылка может использоваться для доступа к свойствам и методам нового окна, если она соответствует требованиям безопасности политики того же источника.

Метод Window интерфейса open() принимает URL-адрес в качестве параметра и загружает указанный ресурс в новую или существующую вкладку или окно. Параметр target определяет, в какое окно или вкладку загружать ресурс, и этот windowFeatures параметр можно использовать для управления открытием нового всплывающего окна с минимальными функциями пользовательского интерфейса и управления его размером и положением.

Обратите внимание, что удаленные URL-адреса не будут загружаться сразу. При window.open() возврате окно всегда содержит about:blank. Фактическое извлечение URL-адреса откладывается и начинается после завершения выполнения текущего блока скрипта. Создание окна и загрузка указанного ресурса выполняются асинхронно.

Тройные кавычки - Как разграничить строковый параметр Javascript

Разграничить строковый параметр Javascript

Тройные кавычки? Как разграничить строковый параметр Javascript с привязкой к данным в ASP . NET? Как разграничить строковый параметр с привязкой к данным Javascript в якорном OnClick событии? У меня есть тег привязки в элементе управления ASP . NET Repeater. Событие OnClick якоря содержит вызов функции Javascript. Функция Javascript принимает строку в качестве входного параметра. Строковый параметр заполняется значением с привязкой к данным из повторителя. Мне нужны "двойные кавычки" для файла Container.DataItem . Мне нужны 'одинарные кавычки' для OnClick . И мне все еще нужен еще один разделитель (тройные кавычки?) для входного строкового параметра вызова функции Javascript. Поскольку я не могу снова использовать 'одинарные кавычки', как мне убедиться, что функция Javascript знает, что входной параметр является строкой, а не целым числом? Без дополнительных кавычек вокруг параметра входной строки функция Javascript считает, что я передаю целое…

Подробнее »

Пользовательская проверка ASP . NET на стороне клиента

Проверка на стороне клиента

У меня есть настраиваемая функция проверки в JavaScript в пользовательском элементе управления на веб-сайте .Net 2.0, которая проверяет, не превышает ли уплаченная сумма причитающейся суммы. Я поместил код валидатора в ascx файл, а также попытался использовать его, Page.ClientScript.RegisterClientScriptBlock() и в обоих случаях проверка срабатывает, но я не могу найти функцию JavaScript. Вывод в консоли ошибок Firefox: "feeAmountCheck is not defined" . Вот функция (это было взято непосредственно из исходного кода firefox -> view) <script type="text/javascript"> function…

Подробнее »

Multiply (Умножение) | JavaScript (решено) | codewars

Умножение (Multiply) - JavaScript - codewars

Этот код не выполняется должным образом. Попытайтесь понять, почему. Решение function multiply(a, b) { return a * b; } Умножение Умножение целых чисел можно рассматривать как многократное сложение; то есть умножение двух чисел эквивалентно прибавлению количества копий одного из них, множимого, к количеству другого, множителя. Оба числа можно назвать факторами. Пример: 3 * 4 = 4 + 4 + 4 = 12 return Оператор return завершает выполнение функции и указывает значение, которое должно быть…

Подробнее »