13

感谢Perfection kills,我们可以使用下面的JavaScript来检测事件支持:如何检测`focusin`支持?

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支持;因为它应该会在Chrome,Firefox等中返回错误hasEvent('mouseenter')

但现在我试图“修复”不支持focusinfocusout事件的浏览器。 According to 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,而不使用浏览器嗅探?

+0

mouseenter&mouseover有没有区别?或聚焦和聚焦?或聚焦和模糊? – Ibu

+1

@Ibu'mouseenter'不会起泡,而“mouseover”会起泡; 'focusin' /'focusout' * do *泡泡,'focus' /'blur'不要。 – sdleihssirhc

+1

另一个重要的事实是focusin和focusout事件对象具有指向已丢失/接收焦点的元素的'relatedTarget'属性。 –

回答

3

这使用调用focus()触发focusinhttp://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 
})(); 
+1

我喜欢这个想法,但是这种检测方法有点让人困惑,因为它会改变页面上的活动元素。 –

+0

如果这个答案也阻止了临时锚元素获得焦点,那么这个答案会更好。那么它不会有明显的副作用。 (就像偷窃的焦点,如果网页上的元素在页面加载时试图自动对焦怎么办?) –

4

的focusIn BEFORE目标元素获得焦点&事件的内容应该被解雇,事件顺序也似乎马车

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 
+0

好吧,spec已经写在IE的行为之后,所以这并不令人惊讶。 –

+1

但IE行为很好,即支持event.toElement/event.fromElement,其他浏览器不支持此事件的relativeTarget/toElement/fromElement – 4esn0k

-1

您可以测试("onfocusin" in document)

该方法具有轻便和不显眼的优势,并且它会告诉您浏览器是否支持focusin事件。(无法在Chrome,抱歉)

您可以使用下面的代码,以获得相同的行为在所有浏览器(IE9 +,Chrome浏览器,火狐,边缘)focusin事件:

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

UPDATE:正如上面所说的,测试将错误在Chrome上说“false”,但代码示例将按预期工作,因为Chrome支持这两种方法(focusinfocususeCapture)。