Phát hiện IF di chuột qua phần tử với jQuery


149

Tôi không tìm kiếm một hành động để gọi khi di chuột, mà thay vào đó là một cách để biết liệu một phần tử có đang được di chuột qua hay không. Ví dụ:

$('#elem').mouseIsOver(); // returns true or false

Có một phương thức jQuery thực hiện điều này?


Chỉ trong trường hợp ai đó đang tìm kiếm các giải pháp khác stackoverflow.com/questions/1273566/ Khăn
Jo E.

1
Việc đánh dấu là trùng lặp trông khá sai. Câu hỏi không nói ý định là gì, để người khác đọc được suy nghĩ của OP và quyết định đó là câu hỏi phát hiện va chạm và đánh dấu là trùng lặp.
Meligy

Câu trả lời:


305

Bản gốc (Và đúng) Trả lời:

Bạn có thể sử dụng is()và kiểm tra bộ chọn :hover.

var isHovered = $('#elem').is(":hover"); // returns true or false

Ví dụ: http://jsfiddle.net/Meligy/2kyaJ/3/

(Điều này chỉ hoạt động khi bộ chọn khớp tối đa MỘT phần tử. Xem Chỉnh sửa 3 để biết thêm)

.

Chỉnh sửa 1 (ngày 29 tháng 6 năm 2013): (Chỉ áp dụng cho jQuery 1.9.x, vì nó hoạt động với 1.10+, xem Chỉnh sửa tiếp theo 2)

Câu trả lời này là giải pháp tốt nhất tại thời điểm câu hỏi được trả lời. Công cụ chọn ': hover' này đã bị xóa bằng cách .hover()xóa phương thức trong jQuery 1.9.x.

Điều thú vị là một câu trả lời gần đây của "allicarn" cho thấy có thể sử dụng :hoverlàm bộ chọn CSS (so với Sizzle) khi bạn đặt tiền tố với bộ chọn$($(this).selector + ":hover").length > 0 và có vẻ như nó hoạt động!

Ngoài ra, plugin hoverIntent được đề cập trong một câu trả lời khác trông cũng rất đẹp.

Chỉnh sửa 2 (ngày 21 tháng 9 năm 2013): .is(":hover") tác phẩm

Dựa trên một nhận xét khác tôi đã nhận thấy rằng cách ban đầu tôi đã đăng .is(":hover"), thực sự vẫn hoạt động trong jQuery, vì vậy.

  1. Nó hoạt động trong jQuery 1.7.x.

  2. Nó đã ngừng hoạt động vào 1.9.1, khi ai đó báo cáo với tôi và tất cả chúng tôi đều nghĩ rằng nó có liên quan đến việc jQuery xóa hoverbí danh để xử lý sự kiện trong phiên bản đó.

  3. Nó đã hoạt động trở lại trong jQuery 1.10.1 và 2.0.2 (có thể là 2.0.x), điều này cho thấy rằng lỗi trong 1.9.x là một lỗi hoặc do đó không phải là hành vi có chủ ý như chúng ta đã nghĩ ở điểm trước.

Nếu bạn muốn kiểm tra điều này trong một phiên bản jQuery cụ thể, chỉ cần mở ví dụ JSFidlle ở đầu câu trả lời này, thay đổi thành phiên bản jQuery mong muốn và nhấp vào "Chạy". Nếu màu thay đổi khi di chuột, nó hoạt động.

.

Chỉnh sửa 3 (ngày 9 tháng 3 năm 2014): Nó chỉ hoạt động khi chuỗi jQuery chứa một phần tử duy nhất

Như được thể hiện bởi @Wilmer trong các bình luận, anh ta có một câu đố thậm chí không hoạt động đối với các phiên bản jQuery mà tôi và những người khác ở đây đã thử nghiệm nó. Khi tôi cố gắng tìm những gì đặc biệt về trường hợp của anh ấy, tôi nhận thấy rằng anh ấy đang cố kiểm tra nhiều yếu tố cùng một lúc. Đây là némUncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover .

Vì vậy, làm việc với fiddle của mình, điều này KHÔNG hoạt động:

var isHovered = !!$('#up, #down').filter(":hover").length;

Trong khi điều này không làm việc:

var isHovered = !!$('#up,#down').
                    filter(function() { return $(this).is(":hover"); }).length;

Nó cũng hoạt động với các chuỗi jQuery có chứa một phần tử, như nếu bộ chọn ban đầu chỉ khớp với một phần tử hoặc nếu bạn gọi .first()kết quả, v.v.

Điều này cũng được tham khảo tại Bản tin Tài nguyên & Mẹo dành cho Web + của tôi .


1
Công trình tuyệt vời, đơn giản. Cảm ơn Mohamed!
James Skidmore

18
Ném một lỗi trong IE 8 : Syntax Error, unrecognized expression: hover. jquery-1.7.js line 4179.
RobG

Đúng. Chỉ cần thử nghiệm nó. Đối với IE6, hãy thử bản hack này được mô tả ở đây peterned.home.xs4all.nl/csshover.html hoặc quay lại trạng thái di chuột bình thường thêm một số trạng thái và xóa loại giải pháp sau.
Meligy

1
@Meligy: Tôi đã chia rẽ câu đố của bạn để minh họa rằng nó không hoạt động với nhiều mục trong lựa chọn: jsfiddle.net/p34n8
SuperNova

1
Ngoài ra, nếu bạn đang sử dụng jQuery mobile, điều đó cũng giúp bạn kiểm tra câu trả lời trong câu trả lời của gideons và bật hộp jQuery Mobile 1.4.4 và bạn có thể thấy nó không hoạt động sau đó ... Tôi có thể xác nhận điều tương tự với 1.4.2 cũng như :(
David O'Sullivan

32

Sử dụng:

var hovered = $("#parent").find("#element:hover").length;

jQuery 1.9+


1
Điều này làm việc rất tốt. Giải pháp tốt nhất được tìm thấy trong khi duyệt tìm thay thế cho chức năng .hover và: bộ chọn di chuột. Cảm ơn bạn!
Tyler

1
Hoạt động như một lá bùa! :)
jroi_web

9

Nó không hoạt động trong jQuery 1.9. Tạo plugin này dựa trên câu trả lời của user2444818.

jQuery.fn.mouseIsOver = function () {
    return $(this).parent().find($(this).selector + ":hover").length > 0;
}; 

http://jsfiddle.net/Wp2v4/1/


5

Đặt cờ khi di chuột:

var over = false;
$('#elem').hover(function() {
  over = true;
},
function () {
  over = false;
});

Sau đó, chỉ cần kiểm tra cờ của bạn.


Đơn giản, nhưng không dễ sử dụng lại. : /
Trevor

Có vẻ như không hoạt động trong tình huống cụ thể của tôi, nhưng tôi đồng ý rằng đó là một cách tốt để đi khác. Trong trường hợp của tôi, khi tôi mouseleavemột phần tử, tôi muốn kiểm tra xem chuột có nhập phần tử cụ thể khác không.
James Skidmore

@JamesSkidmore - trong sự kiện mouseleave bạn có thể sử dụng e.fromElemente.toElement. Điều đó sẽ làm việc cho bạn?
mrtsherman

Bạn có thể cập nhật thông tin này để sử dụng bộ chọn bao gồm tất cả các yếu tố có thể áp dụng và lưu trữ cờ trên các thành phần riêng lẻ bằng cách sử dụng .data().
nnnnnn

@Trevor - true - bạn cần lưu trữ trạng thái trên phần tử sau đó tạo một hàm kiểm tra trạng thái (có lẽ là thẻ dữ liệu) của phần tử.
kinakuta

4

Cặp đôi cập nhật để thêm sau khi làm việc về chủ đề này một thời gian:

  1. tất cả các giải pháp với .is (": hover") đều bị hỏng trên jQuery 1.9.1
  2. Lý do có khả năng nhất để kiểm tra xem chuột có còn ở trên một phần tử hay không là để cố gắng ngăn các sự kiện bắn vào nhau. Ví dụ: chúng tôi đã gặp sự cố với mouseleave của chúng tôi được kích hoạt và hoàn thành trước khi sự kiện mouseenter của chúng tôi thậm chí hoàn thành. Tất nhiên điều này là do một chuyển động chuột nhanh chóng.

Chúng tôi đã sử dụng hoverIntent https://github.com/briancherne/jquery-hoverIntent để giải quyết vấn đề cho chúng tôi. Về cơ bản, nó kích hoạt nếu chuyển động chuột có chủ ý hơn. (một điều cần lưu ý là nó sẽ kích hoạt trên cả hai con chuột nhập một phần tử và rời đi - nếu bạn chỉ muốn sử dụng một hàm vượt qua hàm tạo)


4

Bạn có thể lọc elment của bạn từ tất cả các yếu tố di chuột. Mã có vấn đề:

element.filter(':hover')

Lưu mã:

jQuery(':hover').filter(element)

Để trả về boolean:

jQuery(':hover').filter(element).length===0

4

Câu trả lời được chấp nhận không hoạt động với tôi trên JQuery 2.x .is(":hover")trả về sai trên mỗi cuộc gọi.

Tôi đã kết thúc với một giải pháp khá đơn giản mà hiệu quả:

function isHovered(selector) {

    return $(selector+":hover").length > 0

}

3

Mở rộng câu trả lời của @ Mohamed. Bạn có thể sử dụng một chút đóng gói

Như thế này:

jQuery.fn.mouseIsOver = function () {
    if($(this[0]).is(":hover"))
    {
        return true;
    }
    return false;
}; 

Sử dụng nó như:

$("#elem").mouseIsOver();//returns true or false

Ngã ba câu đố: http://jsfiddle.net/cgWdF/1/


6
để làm điều đó, bạn cũng có thể làm: jQuery.fn.mouseIsOver = function () {return $ (this [0]). is (': hover')}; ít mã hơn
Lathan

32
thật khó để làm $ ('# elem'). (': hover')
luckykrrish

không phải là một vấn đề khó khăn nhưng nhiều hơn ý định được thể hiện rõ ràng. Nhưng với mỗi thứ đó là của riêng họ.
gideon

1

Tôi thích phản hồi đầu tiên, nhưng đối với tôi nó thật kỳ lạ. Khi cố gắng kiểm tra ngay sau khi tải trang cho chuột, tôi phải đặt độ trễ ít nhất 500 mili giây để nó hoạt động:

$(window).on('load', function() {
    setTimeout(function() {
        $('img:hover').fadeOut().fadeIn();
    }, 500);
});

http://codepen.io/molokoloco/pen/Grvkx/


0

Đặt cờ cho câu trả lời của kinakuta có vẻ hợp lý, bạn có thể đặt người nghe lên phần thân để bạn có thể kiểm tra xem có phần tử nào đang được di chuột qua ngay lập tức không.

Tuy nhiên, làm thế nào để bạn muốn đối phó với các nút con? Có lẽ bạn nên kiểm tra xem phần tử có phải là tổ tiên của phần tử đang di chuột không.

<script>

var isOver = (function() {
  var overElement;
  return {

    // Set the "over" element
    set: function(e) {
      overElement = e.target || e.srcElement;
    },

    // Return the current "over" element
    get: function() {
      return overElement;    
    },

    // Check if element is the current "over" element
    check: function(element) {
      return element == overElement;
    },

    // Check if element is, or an ancestor of, the 
    // current "over" element
    checkAll: function(element) {
      while (overElement.parentNode) {
         if (element == overElement) return true;
         overElement = overElement.parentNode;
      }
      return false;
    }
  };
}());


// Check every second if p0 is being hovered over
window.setInterval( function() {
  var el = document.getElementById('p0');
  document.getElementById('msg').innerHTML = isOver.checkAll(el);
}, 1000);


</script>

<body onmouseover="isOver.set(event);">
  <div>Here is a div
    <p id="p0">Here is a p in the div<span> here is a span in the p</span> foo bar </p>
  </div>
  <div id="msg"></div>
</body>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.