2010-01-19 24 views
6

Tôi có một vùng chứa thả xuống giống như trình đơn ẩn qua ràng buộc sự kiện "mouseleave".Hành vi mouseleave Funky jQuery

<div id="container"> 
<select> 
    <option>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
    <option>5</option> 
</select> 
</div> 

Vấn đề tôi gặp phải là khi các phần tử con của vùng chứa chứa đối tượng SELECT nơi OPTIONS của SELECT mở rộng ra ngoài giới hạn của vùng chứa. Do đó, di chuột qua OPTIONS bên ngoài giới hạn kích hoạt sự kiện "mouseleave" để kích hoạt và đóng trình đơn thả xuống của tôi. SELECT là con của vùng chứa, vì vậy trong trường hợp này, tôi mong đợi sự kiện mouseleave nhận ra điều này.

+0

Tại sao không làm cho các container luôn luôn đủ lớn để chứa con của nó? –

+0

Số lượng tùy chọn lớn hơn nhiều so với phần tử chứa. Tôi muốn giữ giao diện người dùng càng đơn giản càng tốt. – Blocka

Trả lời

4

Cập nhật về giải pháp Blocka như nó không hoạt động với Firefox một cách chính xác:

if ((typeof e.fromElement != 'undefined' && !e.fromElement.length) || 
    (typeof e.fromElement == 'undefined' && e.target.tagName != 'SELECT')) { 
    // perform your mouseleave logic 
} 
1

Có lẽ khi menu thả xuống được mở rộng, bạn có thể đặt cờ. Xóa cờ khi một mục được chọn. Khi một mouseleave xảy ra, không ẩn menu trừ khi cờ rõ ràng.

Tôi luôn lo lắng về việc hack các sự kiện giao diện người dùng ở mức độ này, vì có khả năng bạn sẽ kết thúc một số trình duyệt ở một trạng thái hoàn toàn không sử dụng được.

+0

Cảm ơn bạn đã phản hồi. Lý tưởng nhất là tôi muốn sự kiện mouseleave cháy khi tôi rời khỏi thẻ OPTION mà không quay trở lại CHỌN hoặc DIV chứa. Bí quyết là tránh các sự kiện ràng buộc với các thẻ OPTION. Có một số hacks nhỏ tôi có thể thử nhưng tôi đang tìm kiếm một giải pháp có cấu trúc cốt lõi hơn. – Blocka

1

Hầu hết các trình kết xuất (tất cả ngoại trừ Gecko, tôi nghĩ) thực hiện mở các menu <select> và các tùy chọn của chúng trong một "cửa sổ" riêng biệt, không phải là thành phần trên trang. Sau đó, trang không nhất thiết phải nhận thức được tương tác của người dùng với một menu mở <select>. Rất khó để bạn có thể đạt được hiệu quả mong muốn trên tất cả các trình duyệt chính ...

Chỉnh sửa: ... nhưng có thể vậy. Điều này làm việc cho tôi trong Safari và Firefox. Tôi không thể kiểm tra trong IE ngay bây giờ, nhưng cho nó một shot:

var timer; 
$('#container').mouseleave(function(e) { 
    if($(e.target).parents('#container').length) { 
     return; 
    } 
    timer = setTimeout(function() { 
     $('#container select').blur(); 
    }, 50); 
}).mouseenter(function(e) { 
    if(timer) { 
     clearTimeout(timer); 
    } 
}); 

Chỉnh sửa 2: trên thực tế, Safari không cháy mouseleave (hoặc mouseout) ở tất cả khi "cửa sổ" <select> đang mở.

2

Cảm ơn không có mí mắt! Tôi thực sự tìm thấy một câu trả lời cho vấn đề này đêm qua rất giống với những gì bạn đăng.

.bind("mouseleave", function(e) { // ANSWER HERE!!! 
    if (!e.fromElement.length) { 
     _state.filterTrigger.data("open", false); 
     setTimeout(function() { _toggleFilter(_state.filterTrigger); }, 2000); 
    } 
}); 

Đối tượng e.fromElement cung cấp số đối tượng OPTION trong SELECT. Đối tượng này không được xác định cho các thẻ HTML khác. Tôi đã không thử giải pháp của bạn nhưng điều này làm việc cho tôi là tốt.

4

Một giải pháp rất đơn giản và hiệu quả cho điều này là để kiểm soát con trỏ chuột phối trước khi thực hiện hành động. Nếu vùng chứa nằm ngoài tiêu điểm để tập trung vào phần tử "chọn", nó sẽ kiểm tra con trỏ. Nếu con trỏ bên trong container, nó không thực hiện bất kỳ hành động, tuy nhiên nếu điều này là hành động yếu tố container được thực hiện

$('#div_solapa_lateral').bind("mouseenter",function(){ 
      $(this).animate({left:'0'},500); 
     }); 

    $('#div_solapa_lateral').bind("mouseleave",function(e){ 
      if (e.clientX>360 || e.clientY<60 || e.pageY>625) 
      $(this).animate({left:'-320'},500); 
     }); 

clientX và clientY để "position:relative;" Trang X và Trang Y để "position:absolute;"