mouseover $() - Como faço para verificar se o mouse está sobre um elemento no jQuery?




on click (21)

Graças a vocês dois. Em algum momento eu tive que desistir de tentar detectar se o mouse ainda estava sobre o elemento. Eu sei que é possível, mas pode exigir muito código para realizar.

Demorei um pouco, mas peguei as duas sugestões e inventei algo que funcionaria para mim.

Aqui está um exemplo simplificado (mas funcional):

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

E então, para fazer este trabalho em algum texto, isso é tudo que tenho que fazer:

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

Juntamente com um monte de CSS extravagante, isso permite algumas dicas muito agradáveis ​​de ajuda do mouseover. By the way, eu precisava do atraso no mouseout por causa de pequenas lacunas entre caixas de seleção e texto que estava causando a ajuda a piscar enquanto você move o mouse. Mas isso funciona como um encanto. Eu também fiz algo semelhante para os eventos de foco / desfoque.

Existe uma maneira rápida e fácil de fazer isso no jQuery que estou perdendo?

Eu não quero usar o evento mouseover porque eu já estou usando para outra coisa. Eu só preciso saber se o mouse está sobre um elemento em um determinado momento.

Eu gostaria de fazer algo assim, se houvesse uma função "IsMouseOver":

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

Você pode usar o evento hover do jQuery para acompanhar manualmente:

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

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

Eu precisava de algo exatamente como isso (em um ambiente um pouco mais complexo e a solução com muitos 'mouseenters' e 'mouseleaves' não estava funcionando corretamente) então eu criei um pequeno plugin jquery que adiciona o método ismouseover. Tem funcionado muito bem até agora.

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

Então, em qualquer lugar do documento, você o chama assim e retorna verdadeiro ou falso:

$("#player").ismouseover()

Eu testei no IE7 +, no Chrome 1+ e no Firefox 4 e está funcionando corretamente.


Eu peguei a ideia de SLaks e a envolvi em uma pequena aula .

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

Defina um tempo limite no mouseout para eliminar e armazenar o valor de retorno para os dados no objeto. Em seguida, em caso de cancelamento, cancele o tempo limite se houver um valor nos dados.

Remova os dados no retorno de chamada do fadeout.

Na verdade, é menos dispendioso usar mouseenter / mouseleave, porque eles não disparam para o menu quando as crianças passam o mouse sobre o mouse.


Um cheque limpo e elegante:

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

Eu não pude usar nenhuma das sugestões acima.
Por que eu prefiro minha solução?
Este método verifica se o mouse está sobre um elemento a qualquer momento escolhido por você .
Mouseenter e : hover são legais, mas o mouseenter dispara somente se você mover o mouse, não quando o elemento se mover sob o mouse.
: hover é bem legal mas ... ou seja

Então eu faço isso:

Não 1. guarde a posição x, y do mouse toda vez que for movido quando precisar,
Não 2. verifique se o mouse está sobre qualquer um dos elementos que correspondem à consulta, faça coisas ... como acionar um evento 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");
    }
});

Eu vejo muito os tempos de espera usados ​​para isso, mas no contexto de um evento, você não consegue ver as coordenadas, assim:

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

Dependendo do contexto, você pode precisar ter certeza (this == e.target) antes de chamar o areXYInside (e).

fyi- Estou olhando para usar essa abordagem dentro de um manipulador dragLeave, a fim de confirmar que o evento dragLeave não foi acionado indo para um elemento filho. Se, de alguma forma, você não verificar que ainda está dentro do elemento pai, você pode, por engano, agir apenas para quando realmente deixar o pai.

EDIT: esta é uma boa idéia, mas não funciona de forma consistente o suficiente. Talvez com alguns pequenos ajustes.


Esse código ilustra o que happytime harry e eu estamos tentando dizer. Quando o mouse entra, uma dica de ferramenta sai e, quando o mouse sai, define um atraso para que ele desapareça. Se o mouse entrar no mesmo elemento antes que o atraso seja disparado, destruímos o gatilho antes que ele se apague usando os dados que armazenamos anteriormente.

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

Você pode testar com jQuery se qualquer div filho tiver uma determinada classe. Então, aplicando essa classe quando você passa o mouse sobre uma determinada div, você pode testar se o mouse está sobre ela, mesmo quando você passa o mouse sobre um elemento diferente na página. Muito menos código dessa maneira. Eu usei isso porque eu tinha espaços entre divs em um pop-up, e eu só queria fechar o pop up quando saía do pop up, não quando eu estava movendo o mouse sobre os espaços no pop up. Então, eu chamei uma função mouseover no div do conteúdo (que acabou com o pop-up), mas isso só acionava a função close quando eu passava o conteúdo do div, E estava fora do pop up!

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


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

FIDDLE


Apenas uma nota sobre o popular e útil Arthur Goldsmith resposta acima: Se você está movendo o mouse de um elemento para outro no IE (pelo menos até o IE 9) você pode ter problemas para fazer isso funcionar corretamente se o novo elemento tiver um fundo transparente (que seria por padrão). Minha solução alternativa era dar ao novo elemento uma imagem de fundo transparente.


No jQuery você pode usar .is (': hover'), então

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

agora seria a maneira mais concisa de fornecer a função solicitada no OP.

Nota: O acima não funciona no IE8 ou inferior

Como alternativa menos sucinta que funciona no IE8 (se eu posso confiar no IE8 do IE9), e faz isso sem acionar $(...).hover(...) todo lugar, nem requer conhecer um seletor para o elemento (nesse caso, a resposta de Ivo é mais fácil):

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

AVISO: is(':hover') está obsoleto no jquery 1.8+. Veja este post para uma solução.

Você também pode usar esta resposta: https://.com/a/6035278/8843 para testar se o mouse está em um elemento:

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

Aqui está uma função que ajuda você a verificar se o mouse está dentro de um elemento ou não. A única coisa que você deve fazer é chamar a função onde você pode ter um EventObject associado ao mouse ao vivo. algo assim:

$("body").mousemove(function(event){
     element_mouse_is_inside($("#mycontainer", event, true, {});
});

Você pode ver o código fonte aqui no github ou na parte inferior da postagem:

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

Você pode usar is(':visible'); em jquery E por $ ('. item: hover') está funcionando no Jquery também.

este é um snnipet de código htm:

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

e este é o código 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');

});

isso que eu estava falando :)


Estendendo-se sobre o que 'Happytime harry' disse, certifique-se de usar a função jquery .data () para armazenar o id de timeout. Isso é para que você possa recuperar o ID de tempo limite com muita facilidade quando o 'mouseenter' for acionado no mesmo elemento mais tarde, permitindo que você elimine o gatilho para a sua dica de ferramenta desaparecer.


Como não posso comentar, vou escrever isso como resposta!

Por favor, entenda a diferença entre o seletor css ": hover" e o evento hover!

": hover" é um seletor css e de fato foi removido com o evento quando usado como este $("#elementId").is(":hover") , mas em seu significado não tem nada a ver com o hover do evento jQuery .

Se você codificar $("#elementId:hover") , o elemento só será selecionado quando você passar o mouse. A declaração acima irá trabalhar com todas as versões do jQuery como sua seleção deste elemento com pura e legítima seleção css.

Por outro lado, o evento hover que é

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

é de fato deprecadado como jQuery 1.8 aqui o estado do site da jQuery:

Quando o nome do evento "hover" é usado, o subsistema de eventos o converte em "mouseenter mouseleave" na cadeia de eventos. Isso é chato por vários motivos:

Semântica: Pairar não é o mesmo que o mouse entrar e sair de um elemento, implica em alguma quantidade de desaceleração ou atraso antes de disparar. Nome do evento: O event.type retornado pelo manipulador anexado não é focalizado, mas mouseenter ou mouseleave. Nenhum outro evento faz isso. Cooptando o nome do "hover": Não é possível anexar um evento com o nome "hover" e dispará-lo usando .trigger ("hover"). Os docs já chamam este nome de "fortemente desencorajado por novos códigos", eu gostaria de deprecá-lo oficialmente para 1.8 e, eventualmente, removê-lo.

Por que eles removeram o uso é (": hover") não é claro, mas oh bem, você ainda pode usá-lo como acima e aqui está um pequeno truque para usá-lo ainda.

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

Ah, e eu não recomendo a versão timeout pois isso traz muita complexidade , use funcionalidades de timeout para esse tipo de coisa se não houver outra forma e acredite, em 95% de todos os casos existe outra maneira !

Espero que eu possa ajudar algumas pessoas lá fora.

Greetz Andy


Você pode usar os eventos mouseenter e mouseleave do jQuery. Você pode definir um sinalizador quando o mouse entra na área desejada e desmarca o sinalizador quando sai da área.


Essa seria a maneira mais fácil de fazer isso!

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

Tente testar para o elemento DOM

if (!!$(selector)[0]) // do stuff




jquery mouseover