2011-10-05 25 views
23

This answer cho biết yếu tố HTML nào có thể nhận tiêu điểm. Có một bộ chọn jQuery khớp chính xác với các phần tử này không?Có bộ chọn jQuery để nhận tất cả các phần tử có thể lấy tiêu điểm không?

Hiện tại tôi chỉ đang sử dụng $('input,select,textarea,a'), nhưng tôi tự hỏi liệu có điều gì chính xác hơn không.

+0

Có thể là không. Có lẽ thử bộ chọn [': input'] (http://api.jquery.com/input-selector/)? – Bojangles

+0

Bạn đang cố gắng làm gì khi bạn có danh sách các yếu tố có thể đặt tiêu điểm? – Dennis

+0

@Dennis - cuộn xuống để đảm bảo chúng hiển thị khi chúng được lấy nét. http://stackoverflow.com/questions/7650892/how-to-scroll-down-the-page-when-a-covered-input-box-is-focused – ripper234

Trả lời

5

Bạn có thể kiểm tra các yếu tố có focus() chức năng:

$('*').each(function() { 
    if(typeof this.focus == 'function') { 
    // Do something with this element 
    } 
}) ; 

Sửa Suy nghĩ nhiều hơn một chút, nó có lẽ sẽ làm cho tinh thần để có *:visible thay vì chỉ * như chọn cho hầu hết các ứng dụng của điều này.

+0

Chắc chắn là con đường để đi. Tôi không nghĩ rằng nó có thể xa như selectors rõ ràng đi, kể từ khi chọn jQuery được xây dựng trên http://sizzlejs.com. – ifightcrime

+0

ngoại trừ, nếu bạn đọc bài đăng được liên kết trong OP, nó nói: 'các phần tử duy nhất có phương thức focus() là HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement và HTMLAnchorElement. Điều này đáng chú ý bỏ qua HTMLButtonElement và HTMLAreaElement.' Vì vậy, kiểm tra cho '.focus()' sẽ không làm điều đó (rõ ràng). – Lee

+0

Các phần tử DOM là các đối tượng lưu trữ, chúng không cần phải tuân thủ các quy tắc của ECMAScript và do đó phản hồi của chúng đối với toán tử * typeof * có thể là bất cứ điều gì, bao gồm cả việc ném một lỗi. Trong IE 8, 'typeof element.focus' trả về * đối tượng * trên một đầu vào văn bản, vì vậy phép thử ở trên sẽ thất bại trong khoảng 1: 5 trình duyệt đang được sử dụng, có thể nhiều hơn. – RobG

28

Từ other SO answer referred to by the OP:

trình duyệt ngày nay xác định trọng tâm() trên phần tử html, ...

Vì vậy, điều này có nghĩa thử nghiệm cho focus như một thành viên của nguyên tố này là không hiệu quả , bởi vì tất cả các yếu tố sẽ có, bất kể chúng có thực sự chấp nhận tiêu điểm hay không.

... nhưng một phần tử sẽ không thực sự mất tập trung trừ khi đó là một trong:

  • HTMLAnchorElement/HTMLAreaElement với một href * HTMLInputElement/HTMLSelectElement/HTMLTextAreaElement/HTMLButtonElement nhưng không phải với disabled (IE thực sự cung cấp cho bạn một lỗi nếu bạn cố gắng), và các tệp tải lên có hành vi bất thường vì lý do bảo mật
  • HTMLIFrameElement (mặc dù tập trung vào nó không làm gì hữu ích). Các yếu tố nhúng khác cũng có thể, tôi chưa thử nghiệm tất cả.
  • Bất kỳ phần tử với một tabindex

Vì vậy, những gì về cách đặt tên tất cả những người rõ ràng trong một jQuery Selector?

$('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]') 

Update # 1:

tôi updated your jsFiddle here. Dường như nó hoạt động.

Tôi cũng đã thêm các phần tử có thuộc tính contenteditable vào danh sách ở trên.


Update # 2:

Như @ jfriend00 chỉ ra, "Tùy thuộc vào việc sử dụng, người ta có thể muốn lọc ra các yếu tố mà không phải là có thể nhìn thấy". Để thực hiện điều này, chỉ cần áp dụng .filter(':visible') cho bộ được tạo từ bộ chọn ở trên.


Update # 3:

Như Xavin pointed out: jQuery UI bây giờ có một selector, :focusable, mà thực hiện chức năng này. Nếu bạn đã sử dụng jQuery UI, đây có thể là cách để đi. Nếu không, bạn có thể muốn check out how jQuery UI does it. Trong mọi trường hợp, mô tả trên trang jQuery UI cho :focusable là hữu ích:

Các yếu tố của các loại sau đây là có thể đặt tiêu nếu họ không bị khuyết tật: input, select, textarea, nút, và đối tượng. Neo là có thể tập trung nếu chúng có một href hoặc thuộc tính tabindex. các phần tử vùng có thể tập trung nếu chúng nằm trong một bản đồ có tên, có thuộc tính href và có một hình ảnh hiển thị bằng bản đồ. Tất cả các yếu tố khác đều có thể tập trung chỉ dựa trên thuộc tính và khả năng hiển thị tabindex của chúng.

Vì vậy, bộ chọn tôi đề xuất ở trên gần nhưng không tính đến một vài sắc thái.

Đây là chức năng tách từ giao diện người dùng jQuery, với các chỉnh sửa nhỏ để làm cho nó độc lập. (các bản chỉnh sửa chưa được kiểm tra, nhưng nên hoạt động):

function focusable(element) { 
    var map, mapName, img, 
     nodeName = element.nodeName.toLowerCase(), 
     isTabIndexNotNaN = !isNaN($.attr(element, "tabindex")); 
    if ("area" === nodeName) { 
     map = element.parentNode; 
     mapName = map.name; 
     if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") { 
      return false; 
     } 
     img = $("img[usemap=#" + mapName + "]")[0]; 
     return !!img && visible(img); 
    } 
    return (/input|select|textarea|button|object/.test(nodeName) ? 
     !element.disabled : 
     "a" === nodeName ? 
      element.href || isTabIndexNotNaN : 
      isTabIndexNotNaN) && 
     // the element and all of its ancestors must be visible 
     visible(element); 

    function visible(element) { 
     return $.expr.filters.visible(element) && 
     !$(element).parents().addBack().filter(function() { 
      return $.css(this, "visibility") === "hidden"; 
     }).length; 
    } 
} 

Lưu ý: chức năng trên vẫn phụ thuộc vào jQuery, nhưng không yêu cầu jQuery UI.

+0

Tùy thuộc vào việc sử dụng, người ta có thể muốn lọc ra các yếu tố không hiển thị. – jfriend00

+0

Có lẽ không có cách nào tốt hơn, nhưng vấn đề với loại mã này là nó dễ vỡ. Nó sẽ phải được duy trì mỗi khi có một loại phần tử có thể chỉnh sửa mới hoặc một thuộc tính mới làm cho một cái gì đó có thể chỉnh sửa được. – jfriend00

+0

@ jfriend00 - điểm tốt. Tôi đã cập nhật câu trả lời của tôi để bao gồm đề xuất của bạn. – Lee

0

Kiểm tra chung để biết liệu yếu tố có hỗ trợ một loại người nghe cụ thể hay không là để xem liệu phần tử đó có thuộc tính liên quan hay không, ví dụ: để kiểm tra hỗ trợ cho các tập trung sự kiện, sử dụng:

if ('focus' in element) { 
    // element supports the focus event 
} 

Tuy nhiên, có một số trường hợp ngoại lệ. Xem câu trả lời cho How do you programmatically determine to which events an HTML object can listen for?.

0

Thay vì nhận danh sách các yếu tố có thể đặt tiêu điểm, bạn có thể thử thiết lập trình xử lý tiêu điểm ở phần body để nắm bắt các sự kiện trọng tâm.

$(document.body).on("focus", "*", function(e) { 
    //Scroll to e.target 
}); 
+4

Ngoại trừ việc chúng tôi đã chứng minh rằng việc kiểm tra loại 'this.focus' không hoạt động. – jfriend00

4

Một đơn giản, nhưng đầy đủ, jQuery selector có thể là một điều này:

$('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]') 
.not('[tabindex=-1], [disabled], :hidden') 
+1

'*' ở phía trước '[tabindex]' là không cần thiết – Omu

+0

Có, bạn đã đúng! – tzi

0

tôi có một giải pháp tương đối đơn giản mà trả về tất cả trẻ em tabbable, theo thứ tự tab của họ, mà không sử dụng jQuery.

function tabbable(el) { 
    return [].map.call(el.querySelectorAll([ 
     'input', 
     'select', 
     'a[href]', 
     'textarea', 
     'button', 
     '[tabindex]' 
    ]), function(el, i) { return { el, i } }). 
     filter(function(e) { 
      return e.el.tabIndex >= 0 && !e.el.disabled && e.el.offsetParent; }). 
     sort(function(a,b) { 
      return a.el.tabIndex === b.el.tabIndex ? a.i - b.i : (a.el.tabIndex || 9E9) - (b.el.tabIndex || 9E9); }); 
} 

Đối với IE, hãy xem xét triển khai kiểm tra mức độ hiển thị khác với e.el.offsetParent. jQuery có thể giúp bạn ở đây.

Nếu bạn không cần các yếu tố được sắp xếp, hãy thoát khỏi cuộc gọi đến sort().

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