Як я можу виявити, чи браузер блокує спливаюче вікно?


130

Інколи я натрапляю на веб-сторінку, яка намагається відкрити нове вікно (для введення користувача або щось важливе), але блокувальник спливаючих вікон заважає цьому не статися.

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

Відповіді:


160

Якщо ви використовуєте JavaScript для відкриття спливаючого вікна, ви можете використовувати щось подібне:

var newWin = window.open(url);             

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


@ajwaka Ви могли б ласкаво уточнити, якщо ця відповідь не відповідає хрому, чи є причина, що інша відповідь є кращою для хрому? Дякую!
Crashalot

@ajwaka принаймні сьогодні цей код, здається, працює на хромі, звідси і питання.
Crashalot

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

40

Я спробував ряд прикладів вище, але мені не вдалося змусити їх працювати з 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.");
    }
}

1
@Surendra, будь ласка, чи можете ви вказати, що ви маєте на увазі під "не працює"? Помилка під час розбору? Помилка під час виконання? Спливаюче вікно відкривається, але воно позначене як заблоковане? Спливаюче вікно заблоковано, але воно позначене як відкрите? Я не бачу жодної причини, чому дослідник не зміг би цього, якщо виклик фокусу () на NULL не дозволений, тоді тест на NULL до того, як спроба просто спрацює.
FrancescoMM

IE завжди повертає нуль, навіть якщо спливаюче вікно було успішним.
Девін Гарнер

34

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

Сподіваюся, це допомагає! :)


20
Я думаю, вам потрібно більше підкреслити
Якоб Стамм

У Firefox це відображає порожню сторінку, і ви навіть не можете побачити повідомлення блокуючого спливаючих вікон на сторінці відкриття. Як закрити порожню сторінку?
user460114

Зауважте, що якщо спливаючий URL - це завантажуваний файл (який має Content-Disposition: attachment; заголовок відповіді), спливаюче вікно закриється негайно, тому setTimeoutкод не вдасться, і браузер поскаржиться, що "Блокувальник спливаючих вікон включений!". Для Chrome я рекомендую рішення @ DanielB, і він чудово працює.
wonsuc

1
@wonsuc, коли ви відкриваєте посилання із Content-Disposition: attachment;заголовком, не потрібно відкривати його у спливаючому вікні . Просто зробіть пряме посилання на об’єкт, який ви хочете завантажити, і нативну поведінку браузера дозволить вам завантажити, не перенаправляючи вас подалі від поточної сторінки.
Кевін Б

@KevinB Я мушу сказати, що я в конкретній ситуації. Мені потрібно завантажити декілька файлів, які генерують PDF-файли з HTML. І якщо вміст HTML великий, іноді це займає кілька секунд, і якщо я використовую window.locationйого, якщо перший файл забирає занадто багато часу, він буде ігноруватися, коли розпочнеться другий запит. Ось чому я маю використовувати window.open, оскількиwindow.location ніколи не дає мені знати, коли відповідь закінчується.
wonsuc

12

Одне "рішення", яке завжди працюватиме незалежно від компанії чи версії браузера, - просто поставити попереджувальне повідомлення на екран, десь близько до елемента керування, який створить спливаюче вікно, яке ввічливо попереджає користувача про те, що для дії потрібна поп- і, будь ласка, включіть їх для сайту

Я знаю, що це не фантазії чи нічого, але це не може бути простішим і вимагає приблизно 5 хвилин тестування, то ви можете перейти до інших кошмарів.

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


1
На жаль, іноді всі інші рішення в цьому питанні неприйнятні - лише це. Чому? Тому що всі вони намагаються відобразити спливаюче вікно - не просто визначати, чи активовано спливаючі вікна. Що робити, якщо я хочу це зробити мовчки?
Сагі Манн

Тут слід пам’ятати і те, що користувач не завжди може вмикати спливаючі вікна для вашого сайту. Наприклад, у старих версіях сафарі користувач може лише увімкнути або вимкнути блокувальник спливаючих вікон, але білі списки недоступні.
Джеремі

1

Я поєднав рішення @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
isPopupBlockerActivated Функція ніколи не вмикається return (popupWindow.innerHeight > 0) === false;. Функція повертає помилку, коли ваш веб-переглядач не є Chrome. Тому що onload - це асинхронний процес. Ваша функція повертає помилкове, а потім виконується завантаження, але результат не повертається.
Onur Gazioğlu

0

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

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


-1

За допомогою події 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 чорних вікна у фоновому режимі

функція повертає булеве значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.