Обнаружение поддержки перед загрузкой
Я хотел бы проверить, поддерживает ли текущий браузер событие onbeforeunload. Обычный способ сделать это на JavaScript не работает:
if (window.onbeforeunload) {
alert('yes');
}
else {
alert('no');
}
На самом деле, он только проверяет, был ли какой-либо обработчик прикреплен к событию. Есть ли способ определить, поддерживается ли onbeforeunload, без определения конкретного имени браузера?
10 ответов
Я писал о более или менее надежном выводе для определения поддержки событий в современных браузерах некоторое время назад. На демонстрационной странице вы можете увидеть, что "beforeunload" поддерживается как минимум в Safari 4+, FF3.x+ и IE.
Редактировать: этот метод теперь используется в jQuery, Prototype.js, Modernizr и, вероятно, других скриптах и библиотеках.
К сожалению , ответ Кангакса не работает для Safari на iOS. В моем тестировании beforeunload
поддерживался в каждом браузере, который я пробовал, кроме Safari на IOS:-(
Вместо этого я предлагаю другой подход:
Идея проста. На самом первом посещении страницы мы еще не знаем,beforeunload
поддерживается. Но на той самой первой странице мы создалиunload
и beforeunload
обработчик. Если beforeunload
обработчик срабатывает, мы устанавливаем флаг, говорящий, что beforeunload
поддерживается (на самом деле beforeunloadSupported =
"yes"
). Когда unload
обработчик срабатывает, если флаг не был установлен, мы устанавливаем флаг, который beforeunload
не поддерживается
В следующем мы будем использовать localStorage
(поддерживается во всех браузерах, которые меня интересуют - см. http://caniuse.com/namevalue-storage), чтобы получить / установить флаг. Мы могли бы также использовать печенье, но я выбрал localStorage
потому что нет причин отправлять эту информацию на веб-сервер при каждом запросе. Нам просто нужен флаг, который выживает при перезагрузке страницы. Как только мы обнаружим это один раз, оно останется обнаруженным навсегда.
С этим теперь вы можете позвонить isBeforeunloadSupported()
и это скажет тебе.
(function($) {
var field = 'beforeunloadSupported';
if (window.localStorage &&
window.localStorage.getItem &&
window.localStorage.setItem &&
! window.localStorage.getItem(field)) {
$(window).on('beforeunload', function () {
window.localStorage.setItem(field, 'yes');
});
$(window).on('unload', function () {
// If unload fires, and beforeunload hasn't set the field,
// then beforeunload didn't fire and is therefore not
// supported (cough * iPad * cough)
if (! window.localStorage.getItem(field)) {
window.localStorage.setItem(field, 'no');
}
});
}
window.isBeforeunloadSupported = function () {
if (window.localStorage &&
window.localStorage.getItem &&
window.localStorage.getItem(field) &&
window.localStorage.getItem(field) == "yes" ) {
return true;
} else {
return false;
}
}
})(jQuery);
Вот полный jsfiddle с примером использования.
Обратите внимание, что он будет обнаружен только при второй или последующих загрузках вашего сайта. Если вам важно, чтобы он работал на самой первой странице, вы можете загрузить iframe
на этой странице с src
Атрибут, указывающий на страницу в том же домене с обнаружением здесь, убедитесь, что он загружен, а затем удалите его. Это должно гарантировать, что обнаружение было сделано так isBeforeunloadSupported()
работает даже на первой странице. Но мне это не нужно, поэтому я не включил это в свою демонстрацию.
Я понимаю, что немного опоздал с этим, но сейчас я имею дело с этим, и я думал, что что-то более похожее на следующее будет проще и надежнее. Это специфично для jQuery, но оно должно работать с любой системой, которая позволяет связывать и отменять привязку событий.
$(window).bind('unload', function(){
alert('unload event');
});
window.onbeforeunload = function(){
$(window).unbind('unload');
return 'beforeunload event';
}
Это должно отвязать unload
событие, если beforeunload
событие пожары. В противном случае он просто выстрелит.
alert('onbeforeunload' in window);
Оповещения "правда", если onbeforeunload
является собственностью window
(даже если это ноль).
Это должно сделать то же самое:
var supportsOnbeforeunload = false;
for (var prop in window) {
if (prop === 'onbeforeunload') {
supportsOnbeforeunload = true;
break;
}
}
alert(supportsOnbeforeunload);
И, наконец:
alert(typeof window.onbeforeunload != 'undefined');
Снова, typeof window.onbeforeunload
кажется "объектом", даже если в данный момент он имеет значение null
так что это работает.
Cruster,
"Beforeunload" не определено в спецификации DOM-Events, это особенность IE. Я думаю, что он был создан для того, чтобы запуск мог запускаться до стандартного события "unload". В других браузерах IE вы могли использовать прослушиватель событий "unload" фазы захвата, таким образом получая код, выполняемый перед, например, встроенным событием onunload тела.
Кроме того, DOM не предлагает никаких интерфейсов для проверки поддержки определенного события, вы можете проверить только поддержку группы событий (MouseEvents, MutationEvents и т. Д.).
Между тем вы также можете обратиться к спецификации DOM-Events http://www.w3.org/TR/DOM-Level-3-Events/events.html (к сожалению, не поддерживается в IE)
Надеюсь, эта информация поможет некоторым
Другой подход, получите typeof
if(typeof window.onbeforeunload == 'function')
{
alert("hello functionality!");
}
onbeforeunload также поддерживается FF, поэтому тестирование браузера не поможет.
Мобильные браузеры не поддерживают beforeunload
поскольку браузер может перейти в фоновый режим, не выгружая страницу, он может быть убит операционной системой в любое время.
Однако все современные не мобильные браузеры поддерживают его. Таким образом, вы можете просто проверить, является ли браузер мобильным браузером.
Для решения проблемы я использую:
var isMobile = navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) || navigator.userAgent.match(/Opera Mini/i) || navigator.userAgent.match(/IEMobile/i);
if (isMobile)
{
window.addEventListener("visibilitychange", function(e)
{
if (document.visibilityState == 'hidden')
{
console.log("beforeunload");
location.reload();
}
});
}
else
{
window.addEventListener("beforeunload", function(e)
{
console.log("beforeunload");
});
}
Я вижу, что это очень старая тема, но принятый ответ неправильно обнаруживает поддержку Safari на iOS, что заставило меня исследовать другие стратегии:
if ('onbeforeunload' in window && typeof window['onbeforeunload'] === 'function') {
// onbeforeunload is supported
} else {
// maybe bind to unload as a last resort
}
Вторая часть if-проверки необходима для Safari на iOS, свойство которой установлено в null
,
Протестировано в Chrome 37, IE11, Firefox 32 и Safari для iOS 7.1
Вероятно, было бы лучше просто вручную узнать, какие браузеры его поддерживают, а затем сделать ваши условия более похожими на:
if( $.browser.msie ) {
alert( 'no' );
}
...так далее.
$.browser.msie
Это синтаксис jQuery, большинство фреймворков имеют аналогичные встроенные функции, так как они используют их так много внутри. Если вы не используете фреймворк, я бы посоветовал взглянуть на реализацию этих функций в jQuery.