Избегайте блокировщиков всплывающих окон браузера

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

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

Ответ 1

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

Ответ 2

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

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

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

Ваш опыт? Любой способ улучшить это?

Ответ 3

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

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateLocation(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;
}

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

Ответ 4

Как хорошая практика, я считаю, что неплохо проверить, заблокировано ли всплывающее окно и принять меры в случае. Вы должны знать, что 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 if нет.

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

  • откройте пустое окно, как в примере, и продолжайте
  • открыть фальшивое всплывающее окно (iframe внутри страницы).
  • сообщите пользователю ( "разрешите всплывающие окна для этого сайта" )
  • открыть пустое окно, а затем сообщить пользователю и т.д..

Ответ 5

от JavaScript API JavaScript oauth:

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

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

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

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

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

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

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

github.com/sebringj/athu

passportjs.org

Ответ 6

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

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);
  });
}

Ответ 7

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

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

Ответ 8

Самый простой способ избавиться от этого - это очень хорошо работает для меня -

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

Пример:

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

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

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