Обнаружение IF, если зависание над элементом с помощью jQuery

150

Я не ищу действия для вызова при наведении курсора, а вместо этого, чтобы узнать, находится ли элемент в данный момент. Например:

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

Есть ли метод jQuery, который выполняет это?

Джеймс Скидмор
источник
На всякий случай, если кто-то ищет другие решения stackoverflow.com/questions/1273566/…
Джо Э.
1
Маркировка как дубликат выглядит совершенно неправильно. Вопрос не говорит о том, каково намерение, чтобы кто-то другой прочитал мнение ОП и решил, что это вопрос обнаружения столкновения, и пометил как дубликат.
Мелиги

Ответы:

306

Оригинальный (и правильный) ответ:

Вы можете использовать is()и проверить селектор :hover.

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

Пример: http://jsfiddle.net/Meligy/2kyaJ/3/

(Это работает только тогда, когда селектор соответствует одному элементу максимум. См. Редактирование 3 для более подробной информации)

,

Редактировать 1 (29 июня 2013 г.): (Применимо только к jQuery 1.9.x, так как он работает с 1.10+, см. Следующее Редактирование 2)

Этот ответ был лучшим решением в то время, когда на вопрос был дан ответ. Этот селектор ': hover' был удален .hover()методом удаления в jQuery 1.9.x.

Интересно, что недавний ответ "Allicarn" показывает, что можно использовать :hover качестве селектора CSS (против Sizzle), когда вы префиксируете его селектором $($(this).selector + ":hover").length > 0, и, похоже, это работает!

Кроме того, hoverIntent плагин упомянутый в другом ответе, также выглядит очень хорошо.

Изменить 2 (21 сентября 2013 г.): .is(":hover") работы

Основываясь на другом комментарии, я заметил, что оригинальный способ, которым я разместил .is(":hover"), на самом деле все еще работает в jQuery, так что.

  1. Работало в jQuery 1.7.x.

  2. Он перестал работать в 1.9.1, когда кто-то сообщил мне об этом, и мы все подумали, что это связано с удалением jQuery hover псевдонима для обработки событий в этой версии.

  3. Он снова заработал в jQuery 1.10.1 и 2.0.2 (возможно, 2.0.x), что говорит о том, что сбой в 1.9.x был ошибкой или, скорее, не преднамеренным поведением, как мы думали в предыдущем пункте.

Если вы хотите проверить это в определенной версии jQuery, просто откройте пример JSFidlle в начале этого ответа, перейдите к нужной версии jQuery и нажмите «Выполнить». Если цвет меняется при наведении, это работает.

,

Редактировать 3 (9 марта 2014 г.): работает только тогда, когда последовательность jQuery содержит один элемент

Как показывает @Wilmer в комментариях, у него есть скрипка, которая даже не работает с версиями jQuery, с которыми я и другие здесь тестировали ее. Когда я попытался выяснить, что особенного в его деле, я заметил, что он пытается проверить несколько элементов одновременно. Это было бросатьUncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover .

Итак, работая со своей скрипкой, это НЕ работает:

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

В то время как этого делает работу:

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

Он также работает с последовательностями jQuery, содержащими один элемент, например, если исходный селектор соответствует только одному элементу, или вы вызвали .first()результаты и т. Д.

Об этом также говорится в моем информационном бюллетене «Советы и ресурсы по JavaScript + Web Dev» .

Meligy
источник
1
Работает отлично, просто. Спасибо, Мухаммед!
Джеймс Скидмор
18
Выдает ошибку в IE 8: Syntax Error, unrecognized expression: hover. jquery-1.7.js line 4179.
RobG
Это правда. Просто проверил это. Для IE6 попробуйте этот хак, описанный здесь peterned.home.xs4all.nl/csshover.html или вернитесь к обычному наведению, добавьте какое-нибудь состояние и очистите его для последующего решения.
Meligy
1
@Meligy: я разбудил вашу скрипку, чтобы проиллюстрировать, что она не работает с несколькими элементами в выборе: jsfiddle.net/p34n8
SuperNova
1
Кроме того, если вы используете jQuery mobile, это также приводит его в замешательство - установите флажок в ответе gideons и включите jQuery Mobile 1.4.4, и вы увидите, что он не работает тогда ... Я могу подтвердить, что то же самое с 1.4.2 aswell :(
Дэвид О'Салливан
32

Использование:

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

jQuery 1.9+

user2444818
источник
1
Это прекрасно работает. Лучшее решение, найденное при поиске замены для функции .hover и селектора hover. Спасибо!
Тайлер
1
Работает как шарм! :)
jroi_web
9

Это не работает в jQuery 1.9. Сделал этот плагин на основе ответа пользователя 2444818.

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

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

allicarn
источник
5

Установить флаг при наведении:

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

Тогда просто проверьте свой флаг.

kinakuta
источник
Просто, но не легко использовать повторно. : /
Тревор
Похоже, это не сработало в моей конкретной ситуации, но я согласен, что это хороший способ пойти иначе. В моем случае, когда у меня mouseleaveодин элемент, я хочу проверить, вошла ли мышь в другой конкретный элемент.
Джеймс Скидмор
@JamesSkidmore - в событии mouseleave вы можете использовать e.fromElementи e.toElement. Будет ли это работать для вас?
Мртшерман
Вы можете обновить это, чтобы использовать селектор, который охватывает все применимые элементы, и сохранять флаг для отдельных элементов, используя .data().
nnnnnn
@Trevor - true - вам нужно сохранить состояние элемента, а затем создать функцию, которая проверяет (предположительно, тег данных) состояние элемента.
Кинакута
4

Пара обновлений, чтобы добавить после работы над этой темой некоторое время:

  1. все решения с .is (": hover") ломаются на jQuery 1.9.1
  2. Наиболее вероятная причина проверить, находится ли мышь над элементом, - попытаться предотвратить возникновение событий друг над другом. Например, у нас были проблемы с тем, что наш отпуск мыши был запущен и завершен еще до того, как событие Mouseenter даже завершилось. Конечно, это было из-за быстрого движения мыши.

Мы использовали hoverIntent https://github.com/briancherne/jquery-hoverIntent, чтобы решить эту проблему для нас. По сути это срабатывает, если движение мыши более преднамеренное. (Стоит отметить, что при нажатии и вводе мышью элемента, и выходе из него, он будет срабатывать - если вы хотите использовать один проход, то конструктор - пустая функция)

Дональд Нуммер младший
источник
4

Вы можете отфильтровать свой элемент от всех наведенных элементов. Проблемный код:

element.filter(':hover')

Сохранить код:

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

Чтобы вернуть логическое значение:

jQuery(':hover').filter(element).length===0
Мино
источник
4

Принятый ответ не работал для меня в JQuery 2.x, .is(":hover")возвращает false при каждом вызове.

Я закончил с довольно простым решением, которое работает:

function isHovered(selector) {

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

}
gidim
источник
3

Расширяя ответ @ Мохамеда. Вы могли бы использовать небольшую инкапсуляцию

Как это:

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

Используйте это как:

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

Разветвленная скрипка: http://jsfiddle.net/cgWdF/1/

Гидеон
источник
6
для этого вы также можете сделать следующее: jQuery.fn.mouseIsOver = function () {return $ (this [0]). is (': hover')}; меньше кода
Lathan
32
как трудно просто сделать $ ('# elem'). is (': hover')
luckykrrish
не вопрос тяжелый, а более четко выраженный. Но каждому свое.
Гидеон
1

Мне нравится первый ответ, но для меня это странно. При попытке проверить сразу после загрузки страницы для мыши, я должен поставить по крайней мере 500 миллисекунд задержки для его работы:

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

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

molokoloco
источник
0

Установка флага для ответа кинакуты кажется разумной, вы можете поместить слушателя в тело, чтобы вы могли проверить, находится ли какой-либо элемент в определенный момент.

Тем не менее, как вы хотите иметь дело с дочерними узлами? Возможно, вам следует проверить, является ли элемент предком текущего элемента наведения.

<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>
RobG
источник