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

StackOverflow https://stackoverflow.com/questions/1273566

  •  16-09-2019
  •  | 
  •  

Вопрос

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

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

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

function hideTip(oi) {
    setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}
Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

$("#player").ismouseover()

Я протестировал его на IE7 +, Chrome 1 + и Firefox 4, и он работает должным образом.

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

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

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

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

Как менее лаконичная альтернатива, которая работает в 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());
});

ПРОСТО К вашему сведению, для будущих искателей этого.

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

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

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

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

Поскольку я не могу комментировать, поэтому я напишу это в качестве ответа!

Пожалуйста, поймите разницу между css-селектором ":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" и запустить его с помощью .trigger("наведение").В документах это название уже называется "настоятельно не рекомендуется для нового кода", я бы хотел официально отменить его для версии 1.8 и в конечном итоге удалить.

Почему они удалили usage is(":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% процентах всех случаев есть другой способ!

Надеюсь, я смог бы помочь там паре человек.

Приветствую Энди

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

Это заняло у меня некоторое время, но я воспользовался обоими вашими предложениями и придумал то, что сработало бы для меня.

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

$("[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, это позволяет использовать несколько очень приятных всплывающих подсказок при наведении курсора мыши.Кстати, мне понадобилась задержка при наведении курсора мыши из-за крошечных пробелов между флажками и текстом, из-за которых справка мигала при наведении курсора мыши.Но это работает как заклинание.Я также сделал нечто подобное для событий фокусировки / размытия.

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

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).

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

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

Вы можете протестировать с помощью jQuery если какой-либо дочерний 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"));
        }
    });

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

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

Вот метод, который не полагается на jquery и использует собственный DOM matches API.Он использует префиксы поставщика для поддержки браузеров, возвращающихся к IE9.Видишь селектор совпадений включен 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 голосов "за")

В принципе, вы можете сделать что-то вроде:

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', обязательно используйте функцию jquery .data() для сохранения идентификатора тайм-аута.Это делается для того, чтобы вы могли очень легко получить идентификатор тайм-аута, когда позже для этого же элемента будет активирован '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");
 });

Кажется, у меня это работает.Надеюсь, это кому-то поможет.

Редактировать:Теперь, понимая, что этот подход не работает корректно в IE.

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

Поэтому я делаю это:

№ 1. сохраняйте положение мыши по x, y каждый раз, когда она перемещается, когда вам нужно,
№ 2. проверьте , наведен ли указатель мыши на какой - либо из элементов , соответствующих запросу do stuff ...например, вызвать событие 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');

});

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top