Подтвердить что ты не робот

Как определить поддержку "focusin"?

Благодаря Perfection kill, мы можем использовать следующий JavaScript для обнаружения поддержки событий:

function hasEvent(ev) {
    var elem = document.createElement('a'),
        type = 'on' + ev,
        supported = elem[type] !== undefined;
    if (!supported) {
        elem.setAttribute(type, 'return;');
        supported = typeof elem[type] === 'function';
    }
    elem = null;
    return supported;
}

Это работает в течение единственного времени, в котором я нуждаюсь: обнаружение mouseenter поддержки; hasEvent('mouseenter') вернет false в Chrome, Firefox и т.д., как и должно быть.

Но теперь я пытаюсь "исправить" браузеры, которые не поддерживают события focusin и focusout. Согласно PPK, это в основном просто Firefox. К сожалению, Chrome и Safari указаны как имеющие "неполную" поддержку по следующей причине:

Safari и Chrome запускают эти события только с помощью addEventListener; не с традиционной регистрацией.

В общем, этот штраф; Я бы использовал только addEventListener. Это означает, однако, что обнаружение поддержки через elem.onfocusin !== undefined не будет работать. Я проверил это, и это правда:

<p>Do I support <a href="#">focusin</a>?</p>

<script>
var elem = document.getElementsByTagName('p')[0];

// hasEvent method defined here
function listener() {
    var response = hasEvent('focusin') ? 'Yes!' : 'No...';
    alert(response);
}

elem.addEventListener('focusin', listener, false);
</script>

Вышеуказанные предупреждения No... в Chrome! Есть ли способ определить, поддерживает ли браузер focusin, не используя обнюхивание браузером?

4b9b3361

Ответ 1

Это использует тот факт, что вызов focus() триггеров focusin: http://jsfiddle.net/pimvdb/YXeD3/.

Элемент должен быть видимым и вставлен в DOM, иначе focusin не запускается по какой-либо причине.

var result = (function() {
    var hasIt = false;

    function swap() {
        hasIt = true; // when fired, set hasIt to true
    }

    var a = document.createElement('a'); // create test element
    a.href = "#"; // to make it focusable
    a.addEventListener('focusin', swap, false); // bind focusin

    document.body.appendChild(a); // append
    a.focus(); // focus
    document.body.removeChild(a); // remove again

    return hasIt; // should be true if focusin is fired
})();

Ответ 2

focusin и focusout должны быть запущены до того, как целевой элемент получает фокус, порядок событий также кажется ошибочным

http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order

в настоящее время работает только IE по спецификации:

Chrome/Safari:
focus
focusin
DOMFocusIn
blur
focusout
DOMFocusOut
focus
focusin
DOMFocusIn

Opera 12:
focus
DOMFocusIn
focusin
blur
DOMFocusOut
focusout
focus
DOMFocusIn
focusin

IE 8:
focusin
focus
focusout
focusin
blur
focus

Firefox 14:
focus
blur
focus

Ответ 3

Вы можете проверить ("onfocusin" in document).

Этот метод имеет то преимущество, что он светлый и ненавязчивый, и он скажет вам, поддерживает ли браузер событие focusin. (не в Chrome, извините)

Вы можете использовать следующий код для получения того же поведения, что и событие focusin во всех браузерах (IE9 +, Chrome, Firefox, Edge):

var eventName, useCapture;
if ("onfocusin" in document) {
  eventName = "focusin";
  useCapture = false;
} else {      
  eventName = "focus";
  useCapture = true;
}

document.body.addEventListener(eventName, function( event ) {
    event.target.style.background = "pink";    
  }, useCapture);

JS скрипка здесь: https://jsfiddle.net/d306qm92/2/

Дополнительная информация об обходном пути Firefox здесь: https://developer.mozilla.org/en-US/docs/Web/Events/focus#Event_delegation

ОБНОВЛЕНИЕ. Как было сказано выше, тест ошибочно скажет "ложь" в Chrome, но образец кода будет работать так, как предполагалось, поскольку Chrome поддерживает оба метода (focusin и focus с useCapture).