Как проверить, находится ли мышь над элементом в jQuery?
есть ли быстрый и простой способ сделать это в jQuery, что я упускаю?
Я не хочу использовать событие mouseover, потому что я уже использую его для чего-то другого. Мне просто нужно знать, находится ли мышь над элементом в данный момент.
Я хотел бы сделать что-то вроде этого, если бы только была функция "IsMouseOver":
function hideTip(oi) {
setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}
24 ответов:
установите тайм-аут на mouseout для затухания и сохраните возвращаемое значение для данных в объекте. Затем onmouseover, отменить тайм-аут, если есть значение в данных.
удалите данные об обратном вызове затухания.
Это на самом деле дешевле использовать mouseenter/mouseleave, потому что они не срабатывают для меню, когда дети mouseover/mouseout огонь.
этот код иллюстрирует, что happytime Гарри и я пытаюсь сказать. Когда мышь входит, всплывающая подсказка выходит, когда мышь уходит, она устанавливает задержку для ее исчезновения. Если мышь входит в один и тот же элемент до срабатывания задержки, то мы уничтожаем триггер до его срабатывания, используя данные, которые мы хранили ранее.
$("someelement").mouseenter(function(){ clearTimeout($(this).data('timeoutId')); $(this).find(".tooltip").fadeIn("slow"); }).mouseleave(function(){ var someElement = $(this), timeoutId = setTimeout(function(){ someElement.find(".tooltip").fadeOut("slow"); }, 650); //set the timeoutId, allowing us to clear this trigger if the mouse comes back over someElement.data('timeoutId', timeoutId); });
предупреждение:
is(':hover')является устаревшим в jQuery 1.8+. Смотрите этот пост для решения.вы также можете использовать этот ответ:https://stackoverflow.com/a/6035278/8843 чтобы проверить, если мышь наведите элемент:
$('#test').click(function() { if ($('#hello').is(':hover')) { alert('hello'); } });
вы можете использовать jQuery
hoverсобытие для отслеживания вручную:$(...).hover( function() { $.data(this, 'hover', true); }, function() { $.data(this, 'hover', false); } ).data('hover', false); if ($(something).data('hover')) //Hovered!
мне нужно было что-то именно так (в немного более сложной среде и решении с большим количеством "mouseenters" и "mouseleaves" не работал должным образом), поэтому я создал небольшой плагин jquery, который добавляет метод ismouseover. До сих пор это работало довольно хорошо.
//jQuery ismouseover method (function($){ $.mlp = {x:0,y:0}; // Mouse Last Position function documentHandler(){ var $current = this === document ? $(this) : $(this).contents(); $current.mousemove(function(e){jQuery.mlp = {x:e.pageX,y:e.pageY}}); $current.find("iframe").load(documentHandler); } $(documentHandler); $.fn.ismouseover = function(overThis) { var result = false; this.eq(0).each(function() { var $current = $(this).is("iframe") ? $(this).contents().find("body") : $(this); var offset = $current.offset(); result = offset.left<=$.mlp.x && offset.left + $current.outerWidth() > $.mlp.x && offset.top<=$.mlp.y && offset.top + $current.outerHeight() > $.mlp.y; }); return result; }; })(jQuery);затем в любом месте документа yo назовите его так, и он возвращает true или false:
$("#player").ismouseover()Я тестировал его на IE7+, Chrome 1+ и Firefox 4 и работает правильно.
в jQuery вы можете использовать .is ( ': hover'), так что
function IsMouseOver(oi) { return $(oi).is(':hover'); }Теперь был бы самый краткий способ предоставить функцию, запрошенную в OP.
Примечание: выше не работает в IE8 или ниже
как менее лаконичная альтернатива, которая работает в IE8 (если я могу доверять модусу IE8 IE9), и делает это без запуска
$(...).hover(...)повсюду, и не требуется знать селектор для элемента (в этом случае ответ Иво проще):function IsMouseOver(oi) { return oi.length && oi.parent() .find(':hover') .filter(function(s){return oi[0]==this}) .length > 0; }
Я взял идею Слакса и завернул ее в малого класса.
function HoverWatcher(selector){ this.hovering = false; var self = this; this.isHoveringOver = function() { return self.hovering; } $(selector).hover(function() { self.hovering = true; }, function() { self.hovering = false; }) } var box1Watcher = new HoverWatcher('#box1'); var box2Watcher = new HoverWatcher('#box2'); $('#container').click(function() { alert("box1.hover = " + box1Watcher.isHoveringOver() + ", box2.hover = " + box2Watcher.isHoveringOver()); });
просто FYI для будущих искателей этого.
Я сделал плагин jQuery, который может сделать это и многое другое. В моем плагине, чтобы получить все элементы, над которыми в настоящее время наведен курсор, просто выполните следующие действия:
$.cursor("isHover"); // will return jQ object of all elements the cursor is // currently over & doesn't require timerКак я уже упоминал, он также имеет много других применений, как вы можете увидеть в разделе
jsFiddle нашли здесь
поскольку я не могу комментировать, поэтому я напишу это как ответ!
пожалуйста, поймите разницу между селектором css": hover"и событием hover!
": hover " является селектором css и действительно был удален с событием при использовании, как это
$("#elementId").is(":hover"), но в этом смысле он действительно не имеет ничего общего с зависанием события jQuery.если вы код
$("#elementId:hover"), элемент будет выбран только при наведении курсора мыши. вышеуказанное заявление будет работать с все версии jQuery как ваш выбор этого элемента с чистым и законным выбором css.С другой стороны событие наведите который
$("#elementId").hover( function() { doSomething(); } );действительно устарел как jQuery 1.8 здесь состояние с сайта jQuery:
при использовании имени события "hover" подсистема событий преобразует его чтобы "mouseenter mouseleave" в строке события. Это раздражает несколько причин:
семантика: наведение не то же самое, что мышь входит и выходит элемент, он подразумевает некоторое количество замедления или задержки перед обжиг. Имя события: событие.тип возвращаемого обработчики не парить, но либо mouseenter или mouseleave. Ни одно другое событие не делает этот. Совместное использование имени" hover": невозможно прикрепить событие с именем " hover "и запустить его с помощью.триггер("наведении"). Этот документы уже называют это имя "сильно не рекомендуется для нового кода", я бы как официально осудить его за 1,8 и в конце концов удалите его.
Почему они удалили использование ( ": hover") неясно, но о хорошо, вы все еще можете использовать его, как и выше, и вот немного взломать, чтобы все еще использовать его.
(function ($) { /** * :hover selector was removed from jQuery 1.8+ and cannot be used with .is(":hover") * but using it in this way it works as :hover is css selector! * **/ $.fn.isMouseOver = function() { return $(this).parent().find($(this).selector + ":hover").length > 0; }; })(jQuery);и я не подходит по версии timeout, что это приносит много сложности, используйте функции тайм-аута для такого рода вещей, если нет другого способа и поверьте мне, в 95% процентов всех случаев есть еще одна путь!
надеюсь, что я мог бы помочь пару человек там.
Greetz Andy
спасибо вам обоим. В какой-то момент мне пришлось отказаться от попытки обнаружить, если мышь над элементом. Я знаю, что это возможно, но может потребоваться слишком много кода для выполнения.
вот упрощенный (но функциональный) пример:
$("[HoverHelp]").hover ( function () { var HelpID = "#" + $(this).attr("HoverHelp"); $(HelpID).css("top", $(this).position().top + 25); $(HelpID).css("left", $(this).position().left); $(HelpID).attr("fadeout", "false"); $(HelpID).fadeIn(); }, function () { var HelpID = "#" + $(this).attr("HoverHelp"); $(HelpID).attr("fadeout", "true"); setTimeout(function() { if ($(HelpID).attr("fadeout") == "true") $(HelpID).fadeOut(); }, 100); } );и затем, чтобы сделать эту работу над некоторым текстом, это все, что мне нужно делать:
<div id="tip_TextHelp" style="display: none;">This help text will show up on a mouseover, and fade away 100 milliseconds after a mouseout.</div> This is a <span class="Help" HoverHelp="tip_TextHelp">mouse over</span> effect.наряду с большим количеством причудливых CSS, это позволяет некоторые очень хорошие подсказки мыши помощь. Кстати, мне нужна была задержка в mouseout из-за крошечных промежутков между флажками и текстом, который вызывал вспышку справки при перемещении мыши. Но это работает как шарм. Я также сделал что-то подобное для событий focus/blur.
Я вижу тайм-ауты, используемые для этого много, но в контексте события, вы не можете посмотреть на координаты, как это?:
function areXYInside(e){ var w=e.target.offsetWidth; var h=e.target.offsetHeight; var x=e.offsetX; var y=e.offsetY; return !(x<0 || x>=w || y<0 || y>=h); }в зависимости от контекста, вам может потребоваться убедиться (this==e.target) перед вызовом areXYInside(e).
fyi-я рассматриваю использование этого подхода внутри обработчика dragLeave, чтобы подтвердить, что событие dragLeave не было вызвано переходом в дочерний элемент. Если вы каким-то образом не проверяете, что вы все еще внутри родительского элемента, вы может ошибочно принять меры, которые предназначены только для того, когда вы действительно оставите родителя.
EDIT: это хорошая идея, но не работает достаточно последовательно. Возможно, с некоторыми небольшими изменениями.
Вы можете проверить с
jQueryесли какой-либо дочерний div имеет определенный класс. Затем, применяя этот класс при наведении указателя мыши на определенный div, вы можете проверить, находится ли ваша мышь над ним, даже если вы наводите указатель мыши на другой элемент на странице намного меньше кода таким образом. Я использовал это, потому что у меня были пробелы между дивами во всплывающем окне, и я только хотел закрыть всплывающее окно, когда я отошел от всплывающего окна, а не когда я перемещал мышь над пробелами во всплывающем окне. Поэтому я вызвал наведение курсора мыши функция на содержимом div (который всплывал), но он будет только запускать функцию закрытия, когда я moused-над содержимым div, и был вне всплывающего окна!$(".pop-up").mouseover(function(e) { $(this).addClass("over"); }); $(".pop-up").mouseout(function(e) { $(this).removeClass("over"); }); $("#mainContent").mouseover(function(e){ if (!$(".expanded").hasClass("over")) { Drupal.dhtmlMenu.toggleMenu($(".expanded")); } });
Это был бы самый простой способ сделать это!
function(oi) { if(!$(oi).is(':hover')){$(oi).fadeOut(100);} }
вот метод, который не полагается на jquery и использует родной DOM
matchesAPI. Он использует префиксы поставщиков для поддержки браузеров, возвращающихся к IE9. Смотрите matchesselector ВКЛ caniuse.com для более подробной информации.сначала создайте функцию matchesSelector, например:
var matchesSelector = (function(ElementPrototype) { var fn = ElementPrototype.matches || ElementPrototype.webkitMatchesSelector || ElementPrototype.mozMatchesSelector || ElementPrototype.msMatchesSelector; return function(element, selector) { return fn.call(element, selector); }; })(Element.prototype);затем, чтобы обнаружить Ховер:
var mouseIsOver = matchesSelector(element, ':hover');
Я ответил на этот вопрос в другом вопросе, со всеми деталями, которые вам могут понадобиться:
обнаружение при наведении курсора на элемент с помощью jQuery (имеет 99 upvotes на момент написания статьи)
в принципе, вы можете сделать что-то вроде:
var ishovered = oi.is(":hover");это работает только если
oi- это объект jQuery, содержащий один элемент. Если сопоставлено несколько элементов, необходимо применить к каждому элементу, например:var hoveredItem = !!$('ol>li').filter(function() { return $(this).is(":hover"); }); // not .filter(':hover'), as we can't apply :hover on multiple elementsЭто было проверено начиная jQuery 1.7.
продолжая то, что "Happytime harry" сказал, Обязательно используйте.функция data () jquery для хранения идентификатора времени ожидания. Это так, что вы можете получить идентификатор тайм-аута очень легко, когда "mouseenter" запускается на том же элементе позже, что позволяет устранить триггер для вашей подсказки, чтобы исчезнуть.
вы можете использовать события mouseenter и mouseleave jQuery. Вы можете установить флаг, когда мышь входит в нужную область, и снять флаг, когда она покидает эту область.
Я объединил идеи из этой темы и придумал это, что полезно для отображения / скрытия подменю:
$("#menu_item_a").mouseenter(function(){ clearTimeout($(this).data('timeoutId')); $("#submenu_a").fadeIn("fast"); }).mouseleave(function(){ var menu_item = $(this); var timeoutId = setTimeout(function(){ if($('#submenu_a').is(':hover')) { clearTimeout(menu_item.data('timeoutId')); } else { $("#submenu_a").fadeOut("fast"); } }, 650); menu_item.data('timeoutId', timeoutId); }); $("#submenu_a").mouseleave(function(){ $(this).fadeOut("fast"); });Кажется, работает для меня. Надеюсь, это кому-то поможет.
EDIT: теперь реализация этого подхода не работает правильно в IE.
Я не мог использовать ни одно из предложений выше.
Почему я предпочитаю свое решение?
Этот метод проверяет, находится ли мышь над элементом в любое время, выбранное вами.
события мыши: mouseenter и : hover круто, но mouseenter срабатывает только при перемещении мыши, а не при перемещении элемента под мышью.
:навести очень сладкий, но ... Т. е.поэтому я делаю это:
нет 1. хранить мышь x, Y положение каждого время это переместилось, когда вам нужно,
нет 2. проверить, если мышь находится над любым из элементов, которые соответствуют запросу делаю ... как вызвать событие mouseenter// define mouse x, y variables so they are traced all the time var mx = 0; // mouse X position var my = 0; // mouse Y position // update mouse x, y coordinates every time user moves the mouse $(document).mousemove(function(e){ mx = e.pageX; my = e.pageY; }); // check is mouse is over an element at any time You need (wrap it in function if You need to) $("#my_element").each(function(){ boxX = $(this).offset().left; boxY = $(this).offset().top; boxW = $(this).innerWidth(); boxH = $(this).innerHeight(); if ((boxX <= mx) && (boxX + 1000 >= mx) && (boxY <= my) && (boxY + boxH >= my)) { // mouse is over it so you can for example trigger a mouseenter event $(this).trigger("mouseenter"); } });
просто заметка о популярном и полезном ответе Артура Голдсмита выше: если вы перемещаете мышь от одного элемента к другому в IE (по крайней мере, до IE 9), у вас могут возникнуть некоторые проблемы с правильной работой, если новый элемент имеет прозрачный фон (что было бы по умолчанию). Моим обходным путем было дать новому элементу прозрачное фоновое изображение.
$(document).hover(function(e) { alert(e.type === 'mouseenter' ? 'enter' : 'leave'); });
скрипка
вот функция, которая поможет вам проверить, если мышь находится внутри элемента или нет. Единственное, что вам нужно сделать, это вызвать функцию, в которой вы можете иметь живой EventObject, связанный с мышью. что-то вроде этого:
$("body").mousemove(function(event){ element_mouse_is_inside($("#mycontainer", event, true, {}); });вы можете увидеть исходный код здесь, в github или в нижней части сообщения:
https://github.com/mostafatalebi/ElementsLocator/blob/master/elements_locator.jquery.js
function element_mouse_is_inside (elementToBeChecked, mouseEvent, with_margin, offset_object) { if(!with_margin) { with_margin = false; } if(typeof offset_object !== 'object') { offset_object = {}; } var elm_offset = elementToBeChecked.offset(); var element_width = elementToBeChecked.width(); element_width += parseInt(elementToBeChecked.css("padding-left").replace("px", "")); element_width += parseInt(elementToBeChecked.css("padding-right").replace("px", "")); var element_height = elementToBeChecked.height(); element_height += parseInt(elementToBeChecked.css("padding-top").replace("px", "")); element_height += parseInt(elementToBeChecked.css("padding-bottom").replace("px", "")); if( with_margin) { element_width += parseInt(elementToBeChecked.css("margin-left").replace("px", "")); element_width += parseInt(elementToBeChecked.css("margin-right").replace("px", "")); element_height += parseInt(elementToBeChecked.css("margin-top").replace("px", "")); element_height += parseInt(elementToBeChecked.css("margin-bottom").replace("px", "")); } elm_offset.rightBorder = elm_offset.left+element_width; elm_offset.bottomBorder = elm_offset.top+element_height; if(offset_object.hasOwnProperty("top")) { elm_offset.top += parseInt(offset_object.top); } if(offset_object.hasOwnProperty("left")) { elm_offset.left += parseInt(offset_object.left); } if(offset_object.hasOwnProperty("bottom")) { elm_offset.bottomBorder += parseInt(offset_object.bottom); } if(offset_object.hasOwnProperty("right")) { elm_offset.rightBorder += parseInt(offset_object.right); } var mouseX = mouseEvent.pageX; var mouseY = mouseEvent.pageY; if( (mouseX > elm_offset.left && mouseX < elm_offset.rightBorder) && (mouseY > elm_offset.top && mouseY < elm_offset.bottomBorder) ) { return true; } else { return false; } }
можно использовать
is(':visible');в jquery И за $('.item: hover') он также работает в Jquery.это htm код snnipet:
<li class="item-109 deeper parent"> <a class="root" href="/Comsopolis/index.php/matiers"><span>Matiers</span></a> <ul> <li class="item-110 noAff"> <a class=" item sousMenu" href="/Comsopolis/index.php/matiers/tsdi"> <span>Tsdi</span> </a> </li> <li class="item-111 noAff"> <a class="item" href="/Comsopolis/index.php/matiers/reseaux"> <span>Réseaux</span> </a> </li> </ul> </li>и это код JS:
$('.menutop > li').hover(function() {//,.menutop li ul $(this).find('ul').show('fast'); },function() { if($(this).find('ul').is(':hover')) $(this).hide('fast'); }); $('.root + ul').mouseleave(function() { if($(this).is(':visible')) $(this).hide('fast'); });вот о чем я говорил:)
Comments