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

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

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

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

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

Ответ 1

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

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

На самом деле дешевле использовать mouseenter/mouseleave, потому что они не срабатывают для меню при стрельбе по мыши/мыши.

Ответ 2

Этот код иллюстрирует, что happytime harry, и я пытаюсь сказать. Когда мышь входит, появляется всплывающая подсказка, когда мышь покидает ее, она устанавливает задержку для ее исчезновения. Если мышь входит в тот же элемент до срабатывания задержки, мы уничтожаем триггер до того, как он погаснет, используя ранее сохраненные данные.

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

Ответ 3

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

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

Ответ 4

ПРЕДУПРЕЖДЕНИЕ: is(':hover') устарел в jquery 1.8+. См. этот пост для решения.

Вы также можете использовать этот ответ: fooobar.com/questions/27953/..., чтобы проверить, наводится ли мышка на элемент:

$('#test').click(function() {
    if ($('#hello').is(':hover')) {
        alert('hello');
    }
});

Ответ 5

Вы можете использовать событие jQuery hover для отслеживания вручную:

$(...).hover(
    function() { $.data(this, 'hover', true); },
    function() { $.data(this, 'hover', false); }
).data('hover', false);

if ($(something).data('hover'))
    //Hovered!

Ответ 6

Мне было нужно что-то точно, как это (в немного более сложной среде, и решение с большим количеством "мышь" и "мышь" не работало должным образом), поэтому я создал небольшой плагин 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);

Затем в любом месте документа вы вызываете его так и он возвращает true или false:

$("#player").ismouseover()

Я тестировал его на IE7 +, Chrome 1+ и Firefox 4 и работал нормально.

Ответ 7

В jQuery вы можете использовать .is(': hover'), поэтому

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

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

Примечание. Вышеописанное не работает в IE8 или ниже

Как менее лаконичная альтернатива, которая работает в IE8 (если я могу доверять модулю IE8 IE8), и делает это без запуска $(...).hover(...) по всему месту и не требует знания селектора для элемента (в этом случае ответ Ivo проще):

function IsMouseOver(oi)
{
    return oi.length && 
           oi.parent()
             .find(':hover')
             .filter(function(s){return oi[0]==this})
             .length > 0;
}

Ответ 8

Я взял идею SLaks и завернул ее в малый класс .

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

Ответ 9

JUST FYI для будущих искателей этого.

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

$.cursor("isHover"); // will return jQ object of all elements the cursor is 
                     // currently over & doesn't require timer

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

jsFiddle, найденный здесь

Ответ 10

Как я не могу комментировать, поэтому я напишу это как ответ!

Обратите внимание, что разница между css-селектором ": hover" и событием наведения!

": hover" является селектором css и действительно удаляется с событием при использовании как этот $("#elementId").is(":hover"), но в нем подразумевается, что он действительно не имеет никакого отношения к зависанию события jQuery.

если вы код $("#elementId:hover"), элемент будет выбран только при наведении мыши. приведенный выше оператор будет работать со всеми версиями jQuery, поскольку вы выбираете этот элемент с чистым и законным выбором css.

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

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

действительно дестабилизируется как jQuery 1.8 здесь состояние с сайта jQuery:

Когда используется имя события "hover", подсистема события преобразует его на "mouseenter mouseleave" в строке события. Это раздражает несколько причин:

Семантика: зависание - это не то же самое, что мышь, входящая и выходящая элемент, он подразумевает некоторое замедление или задержку перед обжиг. Название события: Event.type, возвращаемый прикрепленным обработчиком, не наведите курсор, но либо мыши, либо мышь. Никакое другое событие не делает это. Сопоставление имени "hover": невозможно подключить событие с именем "hover" и запустить его с помощью .trigger( "hover" ). docs уже называют это имя "сильно обескураженным для нового кода", я бы как официально отказаться от него 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);

О, а я не буду рекоммендовать версию таймаута, так как эта приносит много сложности, используйте функции тайм-аута для такого рода вещей, если нет другого пути и верьте меня, в 95% процентов всех случаев существует другой способ!

Надеюсь, я смогу помочь пару людей там.

Greetz Andy

Ответ 11

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

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

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

$("[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.

Ответ 12

Вы можете протестировать с помощью jQuery, если какой-либо дочерний div имеет определенный класс. Затем, применяя этот класс, когда вы наводите указатель мыши на определенный div, вы можете проверить, находится ли над ним ваша мышь, даже если вы наведите указатель мыши на другой элемент на странице. Я использовал это, потому что у меня были пробелы между divs во всплывающем окне, и я только хотел закрыть всплывающее окно, когда я отошел от всплывающего окна, а не когда я наводил указатель мыши на пробелы во всплывающем окне. Таким образом, я вызвал функцию mouseover в div содержимого (который был всплыл), но он будет запускать только функцию закрытия, когда я обманывал содержимое 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"));
        }
    });

Ответ 13

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

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);
}

В зависимости от контекста вам может потребоваться убедиться (это == e.target) перед вызовом areXYInside (e).

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

EDIT: это хорошая идея, но она не работает достаточно последовательно. Возможно, с небольшими изменениями.

Ответ 14

Это был бы самый простой способ сделать это!

  function(oi) 
  {
   if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
  }

Ответ 15

Я ответил на это в другом вопросе со всеми подробностями, которые могут вам понадобиться:

Обнаружить IF, зависающий над элементом с помощью 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.

Ответ 16

Вот техника, которая не полагается на jquery и использует собственный DOM matches API. Он использует префиксы поставщиков для поддержки браузеров, возвращающихся в IE9. Подробнее см. matchselector на caniuse.com.

Сначала создайте функцию matchSelector, например:

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');

Ответ 17

Продолжая то, что сказал Happytime harry, обязательно используйте функцию .data() jquery для хранения идентификатора тайм-аута. Это так, что вы можете легко получить идентификатор таймаута, когда "mouseenter" запускается на этом же элементе позже, что позволяет вам исключить запуск триггера для вашей всплывающей подсказки.

Ответ 18

Вы можете использовать события jQuery mouseenter и mouseleave. Вы можете установить флаг, когда мышь входит в нужную область, и удалите флаг, когда он покинет область.

Ответ 19

$(document).hover(function(e) {
    alert(e.type === 'mouseenter' ? 'enter' : 'leave');
});

FIDDLE

Ответ 20

Я объединил идеи из этой темы и придумал это, что полезно для отображения/скрытия подменю:

$("#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.

Ответ 21

Я не мог использовать какие-либо предложения выше.
Почему я предпочитаю свое решение?
Этот метод проверяет, находится ли мышь над элементом в в любое время, выбранным вами.
Mouseenter и : hover - это классно, но триггеры мыши запускаются только при перемещении мыши, а не при перемещении элемента под мышью.
: hover довольно милый, но... IE

Итак, я делаю это:

Нет 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");
    }
});

Ответ 22

Просто обратите внимание на популярный и полезный ответ Артура Голдсмита выше: если вы перемещаете мышь из одного элемента в другой в IE (по крайней мере до IE 9), у вас могут возникнуть проблемы с тем, чтобы это правильно работало, если новый элемент имеет прозрачный фон (который он по умолчанию). Мое обходное решение состояло в том, чтобы дать новому элементу прозрачное фоновое изображение.

Ответ 23

Вот функция, которая помогает вам проверить, находится ли мышь внутри элемента или нет. Единственное, что вам нужно сделать, - это вызвать функцию, в которой вы можете связать объект 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;
    }
}

Ответ 24

Вы можете использовать is(':visible'); в jquery И для $('item: hover') он также работает в JQuery.

это hnm-код 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');

});

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