Избегайте блокировки всплывающих окон браузера
Я разрабатываю поток аутентификации OAuth исключительно в JavaScript, и я хочу показать пользователю окно "предоставить доступ" во всплывающем окне, но оно блокируется.
Как я могу предотвратить всплывающие окна, созданные как window.open или window.showModalDialog от блокировки всплывающих блокировщиков разных браузеров?
8 ответов:
общее правило заключается в том, что блокировщики всплывающих окон будет заниматься, если
window.openили подобное вызывается из javascript, который не вызывается прямое действие пользователя. То есть, вы можете позвонитьwindow.openв ответ на нажатие кнопки в блокировщик всплывающих окон, но если поставить тот же код в событие таймера, он будет заблокирован. Глубина цепочки вызовов также является фактором-некоторые старые браузеры смотрят только на непосредственного вызывающего абонента, новые браузеры могут немного отступить, чтобы увидеть, есть ли у вызывающего абонента звонивший мыши и т. д. Держите его как можно более мелким, чтобы избежать блокировки всплывающих окон.
на основе Джейсон Себринг ' s очень полезный совет, и на вещи, покрытые здесь и здесь, я нашел идеальное решение для моего случая:
псевдо-код, с фрагменты JavaScript-кода:
немедленно создать пустое всплывающее окно на действие пользователя
var importantStuff = window.open('', '_blank');необязательно: добавьте некоторое информационное сообщение "ожидание". Примеры:
a) внешняя HTML-страница: замените приведенную выше строку с
var importantStuff = window.open('http://example.com/waiting.html', '_blank');B) текст: добавить следующую строку ниже приведенной выше:
importantStuff.document.write('Loading preview...');заполните его содержимым, когда он будет готов (например, при возврате вызова AJAX)
importantStuff.location.href = 'http://shrib.com';обогатить вызов
window.openС любыми дополнительными опциями вам нужно.Я на самом деле использую это решение для перенаправления mailto, и он работает на всех моих браузерах (windows 7, Android). Элемент
_blankнемного помогает для электронной почты перенаправление на работу на мобильном телефоне, кстати.ваш опыт? Любой способ улучшить это?
кроме того швейцарский Мистер пост, в моем случае окно.открой был запущен внутри обещания, которое включило блокировщик всплывающих окон, мое решение было: в угловом:
$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; }вот как вы можете открыть новую вкладку, используя ответ promise и не вызывая блокировщик всплывающих окон.
в качестве хорошей практики я думаю, что это хорошая идея тест если всплывающее окно было заблокировано и принять меры в случае. Ты должен знать это окно.открытие имеет возвращаемое значение, и это значение может быть null, если произошла ошибка. Например, в следующем коде:
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; }если всплывающее окно заблокировано, окна.open вернет значение null. Таким образом, функция вернет false.
в качестве примера, представьте себе вызов этой функции непосредственно из любой ссылки с
target="_blank": если всплывающее окно успешно открыто, возвратfalseзаблокирует действие ссылки, иначе, если всплывающее окно заблокировано, возвращениеtrueпозволит поведение по умолчанию (открыть новый _blank окно) и идти дальше.<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >таким образом, у вас будет всплывающее окно, если оно работает, и _blank окно, если не.
если всплывающее окно не открывается, вы можете:
- откройте пустое окно, как в Примере, и продолжайте
- открыть a поддельные всплывающие окна (iframe внутри страницы)
- сообщить пользователю ("разрешите всплывающие окна для этого сайта")
- откройте пустое окно и сообщите об этом пользователю так далее..
из Google OAuth JavaScript API:
http://code.google.com/p/google-api-javascript-client/wiki/Authentication
смотрите область, где он читает:
настройка аутентификации
клиентская реализация OAuth 2.0 использует всплывающее окно, чтобы предложить пользователю войти в систему и утвердить приложение. Первый звонок в gapi.автор.авторизация может вызвать блокировку всплывающих окон, так как она открывает всплывающее окно косвенно. Чтобы предотвратить запуск блокатора всплывающих окон при вызовах auth, вызовите gapi.автор.init (обратный вызов) при загрузке клиента. Предоставленный обратный вызов будет выполнен, когда библиотека будет готова к выполнению вызовов auth.
Я бы предположил, что это связано с реальным ответом выше в том, как он объясняет, если есть немедленный ответ, он не будет отключать всплывающий сигнал тревоги. В "гапи.автор.init " делает это так, что api происходит немедленно.
практические Применение
Я сделал микросервис аутентификации с открытым исходным кодом, используя Node passport на npm и различные пакеты паспортов для каждого поставщика. Я использовал стандартный подход перенаправления к третьей стороне, давая ему URL-адрес перенаправления, чтобы вернуться. Это было программно, поэтому у меня могли быть разные места для перенаправления обратно, если вход/регистрация и на определенных страницах.
Я не хотел создавать новую страницу, если обратный вызов не вернулся успешно, поэтому я сделал это с моделирование пользователя нажмите:
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); }); }
Я пробовал несколько решений, но его единственный, который на самом деле работал для меня во всех браузерах
let newTab = window.open(); newTab.location.href = url;
самый простой способ избавиться от этого, который работал для меня очень хорошо -
- не использовать документ.открытый.)(
- вместо этого используйте это.документ.местоположение.с href = место; где расположение является URL, который будет загружен
Ex:
<script> function loadUrl(location) { this.document.location.href = location; }</script> <div onclick="loadUrl('company_page.jsp')">Abc</div>это работает очень хорошо. Ура
Comments