2010-02-03 34 views
6

Tôi đang mắc kẹt khi tìm ra logic để làm cho bàn phím menu thả xuống có thể truy cập được.jQuery tìm ra nếu cha mẹ mất 'tập trung'

HTML được cấu trúc như vậy (tên thêm lớp được sử dụng cho rõ ràng):

<ul> 
    <li class="primaryMenuItem"> 
     <a href="">Link 1</a> 
     <ul class="popUpMenu"> 
      <li><a href="">Sub Link 1</a></li> 
      <li><a href="">Sub Link 2</a></li> 
     </ul> 
    </li> 
    <li class="primaryMenuItem"> 
     <a href="">Link 2</a> 
     <ul class="popUpMenu"> 
      <li><a href="">Sub Link 1</a></li> 
      <li><a href="">Sub Link 2</a></li> 
     </ul> 
    </li>  
</ul> 

Link 1 và Link 2, khi được quét, sẽ hiển thị danh sách sub-menu (trình đơn thả xuống). Tôi có điều này làm việc tốt với một số jQuery và jQuery hoverIntent plugin.

Điều bắt được là thao tác này chỉ hoạt động với chuột tại thời điểm này.

Thách thức tiếp theo là thực hiện thao tác này thông qua bàn phím.

tôi có thể dễ dàng thêm một sự kiện tập trung vào các liên kết cấp cao nhất mà sau đó kích hoạt các menu thứ cấp:

$('ul.primaryMenuItem a:first').focus([call showMenu function]) 

đó làm việc tốt.

Để đóng menu, một tùy chọn là, khi mở một menu khác, hãy kiểm tra xem liệu có một tùy chọn khác đã mở hay không và nếu có, hãy đóng nó.

Điều đó cũng hoạt động tốt.

Trường hợp không thành công, tuy nhiên, nếu bạn có menu cuối cùng mở và thoát ra khỏi nó. Vì bạn chưa đặt tab vào một menu khác, trình đơn này vẫn mở.

Thách thức là tìm ra cách/thời điểm đóng menu và logic cần thiết (jQuery) để tìm ra. Lý tưởng nhất, tôi sẽ đóng menu khi tiêu điểm nằm trên một phần tử trên trang KHÁC so với bất kỳ phần tử con nào của trình đơn.

Một cách logic, tôi đang tìm kiếm này:

$('li.primaryMenuItem').blur([close $(this).find('ul.popUpMenu')) 

Tuy nhiên, bạn không thể làm điều đó, kể từ khi LI không thực sự có trọng tâm, nhưng thay vì thẻ neo bên trong nó.

Mọi đề xuất?

UPDATE:

có lẽ là một/cách tốt hơn đơn giản để đặt câu hỏi:

Via jQuery, là có một cách để 'canh' để xem nếu tập trung đã chuyển bên ngoài của tất cả các trẻ em của một đối tượng cụ thể ?

+0

Có một lỗi đánh máy? '$ ('ul.primaryMenuItem a: first'). focus ([call showMenu function])' -> '$ ('li.primaryMenuItem a: first'). focus ...' – superjos

Trả lời

2

Sử dụng hàm jquery mới 1.4: focusinfocusout thay vì blurfocus. Đây là cách focusout khác:

Sự kiện focusout được gửi đến một yếu tố khi nó, hoặc bất kỳ yếu tố bên trong của nó, mất tập trung. Đây là khác biệt từ sự kiện mờ ở chỗ nó hỗ trợ phát hiện mất tiêu điểm từ phần tử gốc (nói cách khác, nó hỗ trợ sự kiện bubbling).

+0

@Keltex Tôi đã xem xét điều đó . Tuy nhiên, đó không phải là những gì tôi cần. Tôi muốn biết liệu vùng chứa chính có bị mất tiêu điểm hay không. focusout sẽ kích hoạt nếu BẤT CỨ yếu tố con nào mất tập trung. Điều đó có nghĩa là tabbing từ sub-menu đến sub-menu sẽ kích hoạt sự kiện đó. Tôi cần một cái gì đó dọc theo dòng của 'có người tabbed bên ngoài sự kiện loại container. –

0

Hãy thử điều này

$('li.primaryMenuItem:last li a:last').blur([do whatever you need to do]) 

logic, nếu các tab người dùng của bạn ra ông phải được tập trung neo ngoái.

Bạn thậm chí có thể thiết lập xử lý sự kiện của riêng bạn như vậy:

$('li.primaryMenuItem:last').bind('myblur', function() ...); 

và gọi nó trong neo cuối cùng mờ sự kiện:

...blur(function() { 
    $(this).parents('li.primaryMenuItem').trigger('myblur'); ... 
+0

Vấn đề với điều đó là có rất nhiều cách để thoát khỏi menu trước khi tabbing ra khỏi mục cuối cùng. Ví dụ, bạn có thể tabbing ngược, có nghĩa là bạn có thể tab ra khỏi mục cuối cùng, nhưng vẫn còn trong cùng một trình đơn. Ngoài ra, người ta có thể sử dụng lệnh bàn phím hoặc nhấp chuột để làm mờ trong khi nửa chừng menu. –

6

Bạn có thể sử dụng sự kiện bọt để kiểm tra những gì đã tập trung về sự kiện focusin. Tôi đã thành công với mã sau:


$("li:has(ul.popUpMenu)").focusin(function(e) { 
    $(this).children().fadeIn('slow'); 
    }); 
    $('body').focusin(function(e) { 
    if (!$(e.target).parent().is('ul.popUpMenu li')) { 
     $('ul.popUpMenu').fadeOut('slow'); 
    } 
    }); 

Bạn có thể (nên) có thể làm cho nó được tối ưu hóa hơn, nhưng nó hoạt động.

+0

Thú vị! Tôi cảm thấy kỳ lạ, tuy nhiên, gắn một xử lý sự kiện cho cơ thể và tất cả các yếu tố con của nó. Có bất kỳ loại vấn đề hiệu suất nào không? Cuối cùng, giải pháp của bạn là 'trên mọi tiêu điểm, xem nó có trong menu hay không. Nếu không, hãy đóng nó '. Mà chắc chắn có ý nghĩa. –

+0

Vâng, nó sẽ kích hoạt sự kiện focusin bất cứ khi nào một sự kiện trọng tâm xảy ra trong cơ thể, nhưng tiêu điểm thường không thay đổi rất nhanh, và sẽ có một số giới hạn các yếu tố có thể là mục tiêu của sự kiện trọng tâm (liên kết/các yếu tố hình thức) vì vậy cá nhân tôi không nghĩ rằng việc gọi so sánh này trên mọi sự kiện trọng tâm sẽ ảnh hưởng đến hiệu suất quá nhiều. Bạn có thể cố gắng tối ưu hóa so sánh (tôi không chắc là cái nào nhanh hơn $ (e.target) .is ('ul.popUpMenu li a') hoặc ví dụ), và bạn nên nhớ truy vấn phần tử. Nếu hiệu suất là một vấn đề thực sự, bạn cần chạy một số điểm chuẩn để kiểm tra tác động. – emmychan

+2

focusin sẽ không kích hoạt trong một số trình duyệt cho thẻ body (hoặc nhiều thẻ khác). Đặt tabindex thành -1 có vẻ như sửa lỗi đó và làm cho giải pháp này phù hợp - $ ("body"). Attr ("tabindex", -1); – John

0

Điều này đã giúp tôi ... http://plugins.jquery.com/project/focus

Nó sẽ phát hiện nếu bạn vẫn tự động ở trong phụ huynh. Về cơ bản nó thay đổi tập trung jQuery để làm việc theo cách này thay vào đó, mà tôi cảm thấy nó hoạt động như thế nào.

<div class="parent"> 
    <input type="text" /> 
    <input type="text" /> 
</div> 

$('#parent').focusout(function() { 
    console.log('focusout of parent'); 
}); 

Tôi không thấy lý do tại sao nhấn tab để di chuyển textfield giữa các phần tử con sẽ kích hoạt tập trung vào cha mẹ vì bạn vẫn ở trong cha mẹ đó. Một cái gì đó phải xảy ra mà sẽ đưa bạn ra khỏi nó cho một thời điểm và tôi nghi ngờ đó là một lỗi ... bất cứ ai với tôi về điều này? Vâng anyway các plugin ở trên sửa chữa nó. Chỉ cần bao gồm nó trước khi mã của bạn để 'sửa' này. Sẽ yêu một ai đó để giải thích tại sao đây không phải là một lỗi nếu nó không phải là.

Cảm ơn, Dom

2

Làm thế nào về nếu bạn làm như sau:

$('#link_A_id, #link_A_id > *').focusout(function() { 
    if ($(document.activeElement).closest('#link_A_id').length == 0) 
     //focus is out of link A and it's children 
}); 
+0

+1 Điều này giúp tôi đi đúng hướng. Tôi không thấy lý do tại sao bộ chọn thứ hai ('#link_A_id> *') là cần thiết và tôi đã không sử dụng nó. Tôi cũng phải bọc câu lệnh if trong một khoảng thời gian chờ vì phần tử 'body' * đánh cắp * trọng tâm trước khi phần tử tiếp theo được lấy nét. – toxalot

0

Tôi đã có một vấn đề tương tự ... Tôi tạo ra một jsfiddle để xác định khi một fieldset mẹ mất tập trung và sau đó gọi một chức năng. Nó chắc chắn có thể được tối ưu hóa, nhưng đó là một sự khởi đầu.

http://jsfiddle.net/EKhLc/10/

function saveFields() { 
    $.each($('fieldset.save'),function(index, value) { 
    // WHERE THE POST WOULD GO 
    alert('saving fieldset with id '+ value.id); 
    $(value).removeClass('save'); 
    }); 

} 
$('.control-group').focusin(function(){ 
    var thefield = $(this).parent('fieldset'); 
    if (!thefield.hasClass('active')) { 
    if($('fieldset.active').length > 0){ 

     $('fieldset.active').removeClass('active').addClass('save'); 
     saveFields(); 
     } 
    thefield.addClass('active'); 
    } else { 
     console.log('already active'); 
    } 
}); 
Các vấn đề liên quan