eventos - mouseout jquery
¿Cómo verifico si el mouse está sobre un elemento en jQuery? (24)
SOLO FYI para los futuros buscadores de esto.
Hice un plugin de jQuery que puede hacer esto y mucho más. En mi complemento, para obtener todos los elementos sobre los que se encuentra actualmente el cursor, simplemente haga lo siguiente:
$.cursor("isHover"); // will return jQ object of all elements the cursor is
// currently over & doesn''t require timer
Como mencioné, también tiene muchos otros usos, como se puede ver en el
jsFiddle encontrado aquí
¿Hay una forma rápida y fácil de hacer esto en jQuery que me estoy perdiendo?
No quiero usar el evento mouseover porque ya lo estoy usando para otra cosa. Solo necesito saber si el mouse está sobre un elemento en un momento dado.
Me gustaría hacer algo como esto, si solo hubiera una función "IsMouseOver":
function hideTip(oi) {
setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}
¡Como no puedo comentar, entonces escribiré esto como una respuesta!
¡Comprenda la diferencia entre el selector css ": hover" y el evento hover!
": hover" es un selector css y, de hecho, se eliminó con el evento cuando se usó de esta manera $("#elementId").is(":hover")
, pero en su significado realmente no tiene nada que ver con el evento jQuery. .
Si codifica $("#elementId:hover")
, el elemento solo se seleccionará cuando se desplace con el mouse. La declaración anterior funcionará con todas las versiones de jQuery, ya que seleccionará este elemento con una selección css pura y legítima.
Por otro lado el evento hover que es
$("#elementId").hover(
function() {
doSomething();
}
);
De hecho, está obsoleto como jQuery 1.8 aquí el estado del sitio web de jQuery:
Cuando se utiliza el nombre del evento "hover", el subsistema de eventos lo convierte a "mouseenter mouseleave" en la cadena del evento. Esto es molesto por varias razones:
Semántica: desplazarse no es lo mismo que el mouse que entra y sale de un elemento, implica cierta desaceleración o retraso antes de disparar. Nombre del evento: el event.type devuelto por el controlador adjunto no es flotante, sino mouseenter o mouseleave. Ningún otro evento hace esto. Cooptar el nombre de "desplazamiento": No es posible adjuntar un evento con el nombre de "desplazamiento" y dispararlo con .trigger ("desplazamiento"). Los documentos ya llaman a este nombre "fuertemente desaconsejado para obtener un nuevo código", me gustaría descartarlo oficialmente por 1.8 y finalmente eliminarlo.
Por qué se eliminó el uso es (": hover") no está claro, pero bueno, todavía puedes usarlo como arriba y aquí hay un pequeño truco para seguir usándolo.
(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, y no recomendaría la versión de tiempo de espera ya que esto trae mucha complejidad , use las funciones de tiempo de espera para este tipo de cosas si no hay otra forma y créanme, ¡en el 95% de los casos hay otra manera !
Espero poder ayudar a un par de personas por ahí.
Greetz Andy
¡Esta sería la forma más fácil de hacerlo!
function(oi)
{
if(!$(oi).is('':hover'')){$(oi).fadeOut(100);}
}
Ampliando lo que dijo ''Happytime harry'', asegúrate de usar la función jQuery .data () para almacenar la identificación del tiempo de espera. Esto es para que pueda recuperar el identificador de tiempo de espera muy fácilmente cuando el ''mouseenter'' se active en ese mismo elemento más adelante, permitiéndole eliminar el disparador para que desaparezca su información sobre herramientas.
Aquí hay una función que le ayuda a verificar si el mouse está dentro de un elemento o no. Lo único que debe hacer es llamar a la función donde puede tener un EventObject asociado al mouse en vivo. algo como esto:
$("body").mousemove(function(event){
element_mouse_is_inside($("#mycontainer", event, true, {});
});
Puedes ver el código fuente aquí en github o al final de la publicación:
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;
}
}
Aquí hay una técnica que no se basa en jquery y utiliza la API nativa de matches
DOM. Utiliza prefijos de proveedores para admitir navegadores que se remontan a IE9. Vea matchesselector en caniuse.com para detalles completos.
Primero crea la función matchesSelector, así:
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);
Luego, para detectar hover:
var mouseIsOver = matchesSelector(element, '':hover'');
Combiné ideas de este tema y se me ocurrió esto, que es útil para mostrar / ocultar un submenú:
$("#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");
});
Parece funcionar para mi. Espero que esto ayude a alguien.
EDIT: Ahora se da cuenta de que este enfoque no funciona correctamente en IE.
En jQuery puedes usar .is ('': hover''), así que
function IsMouseOver(oi)
{
return $(oi).is('':hover'');
}
Ahora sería la forma más concisa de proporcionar la función solicitada en el OP.
Nota: lo anterior no funciona en IE8 o inferior
Como alternativa menos sucinta que funciona en IE8 (si puedo confiar en el modo IE8 de IE9), y lo hace sin disparar $(...).hover(...)
todas partes, ni requiere saber un selector para el elemento (en cuyo caso la respuesta de Ivo es más fácil):
function IsMouseOver(oi)
{
return oi.length &&
oi.parent()
.find('':hover'')
.filter(function(s){return oi[0]==this})
.length > 0;
}
Establezca un tiempo de espera en el mouseout para desaparecer y almacenar el valor de retorno a los datos en el objeto. Luego onmouseover, cancele el tiempo de espera si hay un valor en los datos.
Eliminar los datos en la devolución de llamada del fadeout.
En realidad, es menos costoso usar mouseenter / mouseleave porque no se activan para el menú cuando los niños mouseover / mouseout disparan.
Este código ilustra lo que happytime harry y yo estamos tratando de decir. Cuando el mouse entra, aparece una información sobre herramientas, cuando el mouse se va, establece un retraso para que desaparezca. Si el mouse ingresa el mismo elemento antes de que se active la demora, entonces destruimos el disparador antes de que se dispare utilizando los datos que almacenamos 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);
});
Gracias a los dos. En algún momento tuve que renunciar a intentar detectar si el mouse aún estaba sobre el elemento. Sé que es posible, pero puede requerir demasiado código para lograrlo.
Me tomó un poco de tiempo, pero tomé tus dos sugerencias y se me ocurrió algo que funcionaría para mí.
Aquí hay un ejemplo simplificado (pero 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);
}
);
Y luego, para hacer este trabajo en algún texto, esto es todo lo que tengo que hacer:
<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.
Junto con una gran cantidad de CSS sofisticado, esto permite algunas sugerencias de ayuda muy útiles con el mouseover. Por cierto, necesitaba la demora en la salida del mouse debido a los pequeños huecos entre las casillas de verificación y el texto que causaba que la ayuda parpadeara a medida que se mueve el mouse. Pero esto funciona como un encanto. También hice algo similar para los eventos de enfoque / desenfoque.
He respondido esto en otra pregunta, con todos los detalles que pueda necesitar:
Detecta SI sobrevolando el elemento con jQuery (tiene 99 votos al momento de escribir)
Básicamente, puedes hacer algo como:
var ishovered = oi.is(":hover");
Esto funciona solo si oi
es un objeto jQuery que contiene un solo elemento. Si hay varios elementos coincidentes, debe aplicar a cada elemento, por ejemplo:
var hoveredItem = !!$(''ol>li'').filter(function() { return $(this).is(":hover"); });
// not .filter('':hover''), as we can''t apply :hover on multiple elements
Esto fue probado a partir de jQuery 1.7.
Necesitaba algo exactamente como esto (en un entorno un poco más complejo y la solución con muchos ''mouseenters'' y ''mouseleaves'' no funcionaba correctamente), así que creé un pequeño plugin jquery que agrega el método ismouseover. Ha funcionado bastante bien hasta ahora.
//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);
Luego, en cualquier lugar del documento, lo llamo así y devuelve verdadero o falso:
$("#player").ismouseover()
Lo probé en IE7 +, Chrome 1+ y Firefox 4 y está funcionando correctamente.
No pude usar ninguna de las sugerencias anteriores.
¿Por qué prefiero mi solución?
Este método verifica si el mouse está sobre un elemento en cualquier momento elegido por Usted .
Mouseenter y : hover son geniales, pero el mouseenter se activa solo si mueves el mouse, no cuando el elemento se mueve debajo del mouse.
: hover es bastante dulce pero ... IE
Así que hago esto:
No 1. almacene la posición del mouse x, y cada vez que se mueva cuando lo necesite,
No 2. verifique si el mouse está sobre alguno de los elementos que coinciden con la consulta, haga cosas ... como desencadenar un 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");
}
});
Puede utilizar is('':visible'');
en jquery Y por $ (''. item: hover'') también está funcionando en Jquery.
Este es un código 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>
y este es el 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'');
});
esto de lo que estaba hablando :)
Puede utilizar el evento de desplazamiento de jQuery para realizar un seguimiento manual:
$(...).hover(
function() { $.data(this, ''hover'', true); },
function() { $.data(this, ''hover'', false); }
).data(''hover'', false);
if ($(something).data(''hover''))
//Hovered!
Puedes probar con jQuery
si algún div niño tiene cierta clase. Luego, aplicando esa clase cuando pasas el mouse sobre un div determinado, puedes probar si el mouse está sobre él, incluso cuando pasas el mouse sobre un elemento diferente en la página. Mucho menos código de esta manera. Utilicé esto porque tenía espacios entre divs en una ventana emergente, y solo quería cerrar la ventana emergente cuando salía de la ventana emergente, no cuando movía el mouse sobre los espacios en la ventana emergente. Así que llamé a una función de mouseover en el div contenido (que había salido la ventana emergente), pero solo activaría la función de cierre cuando pasé el ratón sobre el div contenido, ¡Y estaba fuera de la ventana emergente!
$(".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")); } });
Puedes usar los eventos mouseenter y mouseleave de jQuery. Puede establecer una bandera cuando el ratón entra en el área deseada y desarmar la bandera cuando abandona el área.
Solo una nota sobre la popular y útil respuesta de Arthur Goldsmith: Si está moviendo el mouse de un elemento a otro en IE (al menos hasta IE 9), es posible que tenga problemas para que esto funcione correctamente si el nuevo elemento tiene una fondo transparente (que por defecto lo haría). Mi solución fue darle al nuevo elemento una imagen de fondo transparente.
Tomé la idea de SLaks y la envolví en una clase pequeña .
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());
});
Un cheque de vuelo limpio y elegante:
if ($(''#element:hover'').length != 0) {
// do something ;)
}
Veo que los tiempos de espera se usan mucho para esto, pero en el contexto de un evento, ¿no puedes ver las coordenadas de esta manera ?:
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);
}
Dependiendo del contexto, es posible que deba asegurarse (este == e.target) antes de llamar a areXYInside (e).
fyi- Estoy considerando utilizar este enfoque dentro de un controlador dragLeave, para confirmar que el evento dragLeave no se activó al ingresar a un elemento secundario. Si no verifica de alguna manera que todavía está dentro del elemento padre, podría tomar por error acciones que solo están destinadas a cuando realmente deja el padre.
EDITAR: esta es una buena idea, pero no funciona lo suficientemente consistente. Tal vez con algunos pequeños retoques.
ADVERTENCIA: is('':hover'')
está en desuso en jquery 1.8+. Vea este post para una solución.
También puede usar esta respuesta: https://.com/a/6035278/8843 para probar si el mouse se encuentra sobre un elemento:
$(''#test'').click(function() {
if ($(''#hello'').is('':hover'')) {
alert(''hello'');
}
});
$(document).hover(function(e) {
alert(e.type === ''mouseenter'' ? ''enter'' : ''leave'');
});