Как проверить, находится ли мышь над элементом в jQuery?

есть ли быстрый и простой способ сделать это в jQuery, что я упускаю?

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

Я хотел бы сделать что-то подобное, если бы только была функция "IsMouseOver":

function hideTip(oi) {
    setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}

24 ответов


установите тайм-аут в mouseout на fadeout и сохраните возвращаемое значение для данных в объекте. Затем onmouseover отменяет тайм-аут, если в данных есть значение.

удалите данные о обратном вызове fadeout.

на самом деле дешевле использовать 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); 
});

чистая и элегантная проверка наведения:

if ($('#element:hover').length != 0) {
    // do something ;)
}

предупреждение: 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'), so

function IsMouseOver(oi)
{
   return $(oi).is(':hover');
}

теперь будет самым кратким способом предоставить функцию, запрошенную в OP.

Примечание: выше не работает в IE8 или ниже

как менее лаконичная альтернатива, которая работает в IE8 (если я могу доверять модусу IE9 IE8), и делает это без запуска $(...).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.

С другой стороны, событие hover, которое является

$("#elementId").hover(
     function() { 
         doSomething(); 
     }
); 

действительно deprecaded как 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 Энди


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

вот упрощенный (но функциональный) пример:

$("[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);
    }
);

и затем, чтобы сделать эту работу над некоторым текстом, это все, что мне нужно do:

<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, вы можете проверить, находится ли ваша мышь над ним, даже если вы наведете указатель мыши на другой элемент на странице гораздо меньше кода таким образом. Я использовал это, потому что у меня были пробелы между дивами во всплывающем окне, и я только хотел закрыть всплывающее окно, когда я отошел от всплывающего окна, а не когда я перемещал мышь над пробелами во всплывающем окне. Поэтому я вызвал mouseover функция на содержимом 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 matches API. Он использует префиксы для поддержки браузеров возвращаясь для 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 Гарри" сказал, Обязательно используйте.функция 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. что-то вроде этого:--3-->

$("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');

});

вот о чем я говорил:)