Избегайте блокировщиков всплывающих окон браузера - PullRequest
148 голосов
/ 06 апреля 2010

Я разрабатываю поток аутентификации OAuth исключительно на JavaScript и хочу показать пользователю окно «Предоставить доступ» во всплывающем окне, но оно заблокировано.

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

Ответы [ 8 ]

261 голосов
/ 06 апреля 2010

Общее правило заключается в том, что блокировщики всплывающих окон включаются, если window.open или аналогичный вызывается из JavaScript, который не вызывается прямым действием пользователя .То есть, вы можете вызвать window.open в ответ на нажатие кнопки, не нажимая блокировщик всплывающих окон, но если вы добавите тот же код в событие таймера, он будет заблокирован.Глубина цепочки вызовов также является фактором - некоторые старые браузеры смотрят только на непосредственного абонента, более новые браузеры могут немного откатить назад, чтобы увидеть, был ли вызывающий абонент щелчком мыши и т.д.

163 голосов
/ 31 июля 2014

На основании Джейсона Себринга очень полезного совета , и на материале, покрытом здесь и там , я нашел идеальный решение для моего случая:

Псевдокод с фрагментами Javascript:

  1. немедленно создать пустое всплывающее окно при действии пользователя

    var importantStuff = window.open('', '_blank');
    

    Необязательно: добавьте некоторое «ожидающее» информационное сообщение. Примеры:

    a) Внешняя HTML-страница: замените вышеуказанную строку на

    var importantStuff = window.open('http://example.com/waiting.html', '_blank');
    

    b) Текст: добавьте следующую строку ниже приведенной выше:

    importantStuff.document.write('Loading preview...');
    
  2. заполнить его содержимым, когда будете готовы (например, когда будет возвращен вызов AJAX)

    importantStuff.location.href = 'http://shrib.com';
    

Обогатите звонок на window.open любыми дополнительными опциями, которые вам нужны.

Я фактически использую это решение для перенаправления почты на почту, и оно работает во всех моих браузерах (windows 7, Android). Бит _blank помогает перенаправлению почты на мобильный телефон, кстати.

Твой опыт? Есть ли способ улучшить это?

21 голосов
/ 27 октября 2016

Кроме сообщения Swiss Mister, в моем случае window.open было запущено внутри обещания, которое включало блокировку всплывающих окон, мое решение было: в угловых:

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateTabLocation(res.url, myNewTab);

    }
  );
};

browserService:

this.openNewTab = function(){
     var newTabWindow = $window.open();
     return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
     if(!tabLocation){
       tab.close();
     }
     tab.location.href = tabLocation;
}

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

17 голосов
/ 25 сентября 2015

Как хорошая практика, я считаю хорошей идеей проверить , если всплывающее окно было заблокировано, и принять меры в случае.Вы должны знать, что window.open имеет возвращаемое значение, и это значение может быть нулевым, если действие не выполнено.Например, в следующем коде:

function pop(url,w,h) {
    n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
    if(n==null) {
        return true;
    }
    return false;
}

, если всплывающее окно заблокировано, window.open вернет значение null.Таким образом, функция вернет false.

Например, представьте, что вызываете эту функцию напрямую из любой ссылки с target="_blank": если всплывающее окно успешно открыто, возвращение false заблокирует действие ссылки,иначе, если всплывающее окно заблокировано, возвращение true разрешит поведение по умолчанию (откройте новое окно _blank) и продолжится.

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >

Таким образом, у вас будет всплывающее окно, если оноработает, и окно _blank, если нет.

Если всплывающее окно не открывается, вы можете:

  • открыть пустое окно, как в примере, и перейти на
  • открыть поддельное всплывающее окно (iframe внутри страницы)
  • сообщить пользователю («пожалуйста, разрешите всплывающие окна для этого сайта»)
  • откройте пустое окно, а затем сообщите пользователю и т. Д...
8 голосов
/ 05 июня 2012

из Google JavaScript oauth:

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

См. Область, где написано:

Настройка аутентификации

Клиентская реализация OAuth 2.0 использует всплывающее окно, чтобы предложить пользователю войти в систему и одобрить приложение.Первый вызов gapi.auth.authorize может вызвать блокировку всплывающих окон, так как он косвенно открывает всплывающее окно.Чтобы запретить блокирование всплывающих окон при вызовах аутентификации, вызовите gapi.auth.init (callback) при загрузке клиента.Предоставленный обратный вызов будет выполнен, когда библиотека будет готова выполнить аутентификационные вызовы.

Я бы догадался, что это связано с реальным ответом, приведенным выше, в том, как он объясняет, если есть немедленный ответ, он не отключит всплывающую тревогу.«Gapi.auth.init» делает так, чтобы API происходил немедленно.

Практическое применение

Я создал микросервис аутентификации с открытым исходным кодом, используя паспорт узла на npm иразличные паспортные пакеты для каждого провайдера.Я использовал стандартный подход перенаправления к третьей стороне, предоставляя ей URL перенаправления для возврата.Это было программно, так что я мог иметь различные места для перенаправления обратно, если вход / регистрация и на определенных страницах.

github.com / sebringj / athu

passportjs.org

0 голосов
/ 03 июня 2018

Я перепробовал несколько решений, но он единственный, который действительно работал для меня во всех браузерах

let newTab = window.open(); newTab.location.href = url;

0 голосов
/ 12 сентября 2017

Я не хотел создавать новую страницу, если обратный вызов не был успешно возвращен, поэтому я сделал это для симуляции клика пользователя:

function submitAndRedirect {
  apiCall.then(({ redirect }) => {
      const a = document.createElement('a');
      a.href = redirect;
      a.target = '_blank';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
  });
}
0 голосов
/ 31 января 2016

Самый простой способ избавиться от этого - это:

  1. Не используйте document.open ().
  2. Вместо этого используйте this.document.location.href = location; где location это URL для загрузки

Пример:

<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>

<div onclick="loadUrl('company_page.jsp')">Abc</div>

Это сработало очень хорошо для меня. Приветствия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...