обнаружение поддержки перед загрузкой - PullRequest
20 голосов
/ 01 октября 2008

Я хотел бы проверить, поддерживает ли текущий браузер событие onbeforeunload. Обычный способ сделать это на JavaScript не работает:

if (window.onbeforeunload) {
    alert('yes');
}
else {
    alert('no');
}

На самом деле, он только проверяет, был ли какой-либо обработчик прикреплен к событию. Есть ли способ определить, поддерживается ли onbeforeunload, без определения конкретного имени браузера?

Ответы [ 10 ]

27 голосов
/ 12 августа 2009

Я писал о более-менее надежном выводе для обнаружения поддержки событий в современных браузерах некоторое время назад. На демонстрационной странице вы можете увидеть, что «beforeunload» поддерживается как минимум в Safari 4+, FF3.x + и IE.

Редактировать : Этот метод теперь используется в jQuery, Prototype.js, Modernizr и, вероятно, других скриптах и ​​библиотеках.

7 голосов
/ 09 августа 2013

К сожалению ответ Кангакса не работает для 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() работал даже на первой странице. Но мне это не нужно, поэтому я не включил это в свою демонстрацию.

6 голосов
/ 19 июня 2010

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

$(window).bind('unload', function(){
    alert('unload event');
});

window.onbeforeunload = function(){
    $(window).unbind('unload');
    return 'beforeunload event';
}

Это должно отсоединить событие unload, если событие beforeunload сработало. В противном случае он просто выстрелит.

2 голосов
/ 01 октября 2008

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)

Надеюсь, эта информация поможет некоторым

2 голосов
/ 01 октября 2008
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, поэтому это работает.

0 голосов
/ 18 октября 2018

Мобильные браузеры, как правило, не поддерживают 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");
    });
}
0 голосов
/ 30 сентября 2014

Я вижу, что это очень старая тема, но принятый ответ неправильно обнаруживает поддержку 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

0 голосов
/ 16 декабря 2008

onbeforeunload также поддерживается FF, поэтому тестирование браузера не поможет.

0 голосов
/ 01 октября 2008

Другой подход, получите typeof

if(typeof window.onbeforeunload == 'function')

{
alert("hello functionality!");
}
0 голосов
/ 01 октября 2008

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

if( $.browser.msie ) {
  alert( 'no' );
}

... и т.д.

$.browser.msie - это синтаксис jQuery, большинство фреймворков имеют схожие встроенные функции, так как они так часто используют их внутри. Если вы не используете фреймворк, я бы посоветовал просто взглянуть на реализацию этих функций в jQuery.

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