13

Nhờ Perfection kills, chúng ta có thể sử dụng JavaScript sau để phát hiện hỗ trợ sự kiện:Làm cách nào để phát hiện hỗ trợ `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; 
} 

này hoạt động trong khoảng thời gian duy nhất tôi cần nó: phát hiện mouseenter hỗ trợ; hasEvent('mouseenter') sẽ trả về false trong Chrome, Firefox, v.v.

Nhưng giờ tôi đang cố gắng "sửa" các trình duyệt không hỗ trợ các sự kiện focusinfocusout. According to PPK, về cơ bản chỉ là Firefox. Rất tiếc, Chrome và Safari được liệt kê là có hỗ trợ "không đầy đủ" vì lý do sau:

Safari và Chrome chỉ kích hoạt những sự kiện này với addEventListener; không phải với đăng ký truyền thống.

Nói chung, điều đó tốt; Tôi vẫn chỉ sử dụng addEventListener. Tuy nhiên, số có nghĩa là có nghĩa là phát hiện hỗ trợ qua elem.onfocusin !== undefined sẽ không hoạt động. Tôi đã thử nghiệm nó ra, và đó là sự thật:

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

Các cảnh báo trên No... trong Chrome !! Có cách nào để phát hiện xem trình duyệt có hỗ trợ focusin mà không sử dụng trình duyệt đánh hơi không?

+0

có sự khác biệt giữa mouseenter và mouseover không? hoặc tập trung và tập trung? hoặc tập trung và làm mờ? – Ibu

+1

@Ibu 'mouseenter' không bong bóng, trong khi' mouseover' có; 'focusin' /' focusout' * làm * bong bóng, 'focus' /' blur' thì không. – sdleihssirhc

+1

Một thực tế quan trọng khác là đối tượng sự kiện focusin và focusout có thuộc tính 'relatedTarget' trỏ đến phần tử bị mất/nhận tiêu điểm. –

Trả lời

3

Điều này sử dụng thực tế là gọi focus() trình kích hoạt focusin: http://jsfiddle.net/pimvdb/YXeD3/.

Phần tử phải hiển thị và được chèn vào DOM, nếu không focusin sẽ không được kích hoạt vì một lý do nào đó.

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

Tôi thích ý tưởng nhưng phương pháp phát hiện này hơi khó hiểu vì nó thay đổi thành phần hoạt động trên trang. –

+0

Câu trả lời này sẽ được thực hiện tốt hơn nếu nó cũng ngăn cản phần tử neo tạm thời nhận được tiêu điểm. Sau đó, nó sẽ không có tác dụng phụ quan sát được. (Giống như ăn cắp tiêu điểm. Điều gì sẽ xảy ra nếu một phần tử trên trang cố tự động lấy nét khi tải trang?) –

4

focusin & focusout nên bị sa thải TRƯỚC tử target nhận tập trung, sự kiện đặt hàng cũng được dường như buggy

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

hiện nay, chỉ có IE làm việc theo spec:

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

Vâng, thông số kỹ thuật đã được viết theo hành vi của IE, vì vậy nó không thực sự đáng ngạc nhiên. –

+1

nhưng hành vi của IE là tốt, tức là hỗ trợ event.toElement/event.fromElement, các trình duyệt khác không hỗ trợ relativeTarget/toElement/fromElement cho sự kiện này – 4esn0k

-1

Bạn có thể kiểm tra ("onfocusin" in document).

Phương pháp này có lợi thế là nhẹ và không phô trương và nó sẽ cho bạn biết liệu trình duyệt có hỗ trợ sự kiện focusin hay không. (không phải trên Chrome, xin lỗi)

Bạn có thể sử dụng đoạn mã sau để có được những hành vi tương tự như trường hợp focusin trên tất cả các trình duyệt (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 fiddle đây : https://jsfiddle.net/d306qm92/2/

thông tin thêm về Firefox workaround ở đây: https://developer.mozilla.org/en-US/docs/Web/Events/focus#Event_delegation

CẬP NHẬT: Như đã nói ở trên, các thử nghiệm sẽ sai giả sử "sai" trên Chrome, tuy nhiên mẫu mã sẽ hoạt động như dự định khi Chrome hỗ trợ cả hai phương thức (focusinfocus với useCapture).

Các vấn đề liên quan