2010-09-10 11 views
10

En una biblioteca que estoy usando Tengo la tarea de mover un elemento al frente del Dom cuando está sobrevolado. (Lo hago más grande, así que necesito verlo, luego lo encojo cuando sale el mouse).El elemento activo Mover pierde el evento mouseout en Internet Explorer

La biblioteca que estoy usando tiene una solución ordenada que usa appendChildren en el elemento activo para moverlo al final de su matriz, más hacia el final del dom y, a su vez, hacia la parte superior.

El problema es que creo que debido a que el elemento que está moviendo es el que está sobrepasando el mouseout se pierde el evento. Su mouse aún está sobre el nodo pero el evento mouseout no se está disparando.

He eliminado la funcionalidad para confirmar el problema. Funciona bien en Firefox pero no en ninguna versión de IE. Estoy usando jquery aquí para la velocidad. Las soluciones pueden estar en un simple javascript antiguo ... que sería una preferencia, ya que podría necesitar volver a la secuencia de subida.

No puedo usar z-index aquí ya que los elementos son vml, la biblioteca es Raphael y estoy usando la llamada toFront. Muestra usando ul/li para mostrar tema en un ejemplo sencillo

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<script src="js/jquery.min.js" type="text/javascript"></script> 
<style> 
    li 
    { 
     border:1px solid black; 
    } 
</style> 
</head> 
<body> 
<ul><li>Test 1</li></ul> 
<ul><li>Test 2</li></ul> 
<ul><li>Test 3</li></ul> 
<ul><li>Test 4</li></ul> 
<script> 
$(function(){ 
    $("li").mouseover(function(){ 
     $(this).css("border-color","red"); 
     this.parentNode.appendChild(this); 
    }); 

    $("li").mouseout(function(){ 
     $(this).css("border-color","black"); 
    }); 
}); 
</script> 
</body> 
</html> 

Editar: Aquí hay un enlace a un contenedor de pasta de JS para verlo en acción. http://jsbin.com/obesa4

** Editar 2: ** Ver todos los comentarios en todas las respuestas antes de publicar, ya que hay mucha más información sobre eso.

+0

No puedo entender tu publicación. ¿Quieres que el evento 'mouseout' se dispare mientras tu mouse aún está sobre el elemento? ¿Cuál es tu pregunta real? – lincolnk

+0

Y para this.parentNode.appendChild (this) ;, ¿está intentando volver a agregar el elemento LI existente? ¿Por qué no simplemente agregarle una clase de CSS en lugar de agregar/eliminar el mismo elemento con un nuevo CSS? ¿O su código original implica agregar un elemento completamente nuevo desde otro lugar dentro de la UL para imitar su efecto de tamaño "expandido" que mencionó al principio? – Gary

+0

Linkol Estoy intentando que funcione el código de ejemplo, es decir, como en Firefox. El evento de mouseout no se dispara. Estoy usando li elementos como un ejemplo. Como digo en mi publicación, los elementos son en realidad elementos VML. Por lo tanto, cosas como el índice Z o la adición de clases no funcionarán, a menos que las personas puedan demostrar lo contrario. – johnwards

Respuesta

12

El problema es que IE maneja mouseover de manera diferente, porque se comporta como mouseenter y mousemove combinados en un elemento. En otros navegadores es solo mouseenter.

Así que incluso después de que su mouse ingrese el elemento objetivo y haya cambiado su aspecto y lo vuelva a agregar a su matriz mouseover se disparará por cada movimiento del mouse, el elemento se volverá a agregar, lo que impedirá que otros manejadores de eventos siendo llamado.

La solución es emular el comportamiento correcto mouseover por lo que las acciones en onmouseover se ejecutan sólo una vez.

$("li").mouseover(function() { 
    // make sure these actions are executed only once 
    if (this.style.borderColor != "red") { 
     this.style.borderColor = "red"; 
     this.parentNode.appendChild(this); 
    } 
}); 

Ejemplos

  1. Extented demo of yours
  2. Example que demuestra la diferencia entre los navegadores mouseover (bonus: javascript nativo)
+0

Brillante, exactamente lo que estaba esperando cuando configuré la recompensa. Mi código está funcionando mucho mejor ahora que no tengo que hackear esto también. – johnwards

+0

Soy gald Puedo ayudar :) – galambalazs

+3

Aquí hay un ejemplo simple en Raphael 2.0.2 http://jsfiddle.net/K2bSY/2/ para las personas que enfrentan el mismo problema al usar toFront(), que muestra una solución de ejemplo usando Raphael's. Función data() – user568458

0

Eso es poco claro, y parece ser solo de IE (pero también lo es VML). Si el elemento principal tiene una altura especificada, puede adjuntar el manejador de mouseout al padre ... pero parece que eso no funcionará en su situación. Su mejor alternativa es utilizar mouseover en elementos adyacentes para ocultarlo:

$(function() 
{ 
    $("li").mouseover(function() 
    { 
     $("li").css("border-color", "black"); 
     $(this).css("border-color", "red"); 
     this.parentNode.appendChild(this); 
    }); 
}); 

O SVG. Puede usar z-index en SVG.

+0

Hmm la alternativa es creo que la solución aquí. Básicamente, tendré que llamar a una función de reinicio en todos los otros elementos en mouseover, que disparará la animación de contracción. Es muy torpe pero podría funcionar. Voy a votar esta respuesta por ahora, y ver si alguien más puede pensar en algo. – johnwards

1

que era capaz de conseguir que funcione con divs anidados y un evento MouseEnter en la matriz:

<div id="frame"> 
    <div class='box'></div> 
    <div class='box'></div> 
    <div class='box'></div> 
    <div class='box'></div> 
</div> 
... 
$('#frame').mouseenter(function() { 
    $(".box").css("border-color", "black"); 
}); 

Aquí hay una versión de trabajo utilizando Raphael:

http://jsfiddle.net/xDREx/

+0

Puede 'conseguir que funcione en absoluto. No pasa nada cuando muevo el mouse sobre los cuadros. – johnwards

+0

¿Has probado el enlace? ¿Qué navegador estás usando? Lo tengo para trabajar en IE6, IE7 e IE8. – webXL

+0

Ooh mouseenter en el padre, eso es básicamente lo que estás haciendo. Que dispara el reinicio. Bonito. Sin embargo, no resuelve el problema central de los eventos que se pierden. (¡Haz clic en el evento también!) Deffo vale la mitad de los 200 puntos. Si pudiera conseguir el elemento para llegar a la cima sin perder los eventos, sería un hombre feliz. (JSFiddle debe haber estado inactivo, funciona bien ahora) – johnwards

0

que modifican la respuesta @galambalazs' porque encontré que fallado si flotaba muy rápido sobre los elementos li, como algunos de los elementos aún conservaría el efecto mouseover.

Se me ocurrió una solución que elimina el estado de desplazamiento en los elementos que no pudieron desencadenar el evento mouseover al empujar estos elementos a una pila cada vez que se activa el mouseover. En cualquier momento, ya sea el evento mouseover o mouseout se llama, I pop los elementos de esta matriz y quitar los estilos colocados en él:

$(function(){ 

    // Track any hovered elements 
    window.hovered = []; 

    $("li").mouseover(function() { 
     // make sure that these actions happen only once 
     if ($(this).css("border-color") != "red") { 
      resetHovered(); // Reset any previous hovered elements 
      $(this).css("border-color","red"); 
      this.parentNode.appendChild(this); 
      hovered.push(this); 
     } 
    }); 

    $("li").mouseout(function(){ 
     resetHovered(); // Reset any previous hovered elements 
    }); 

    // Reset any elements on the stack 
    function resetHovered() { 
     while (hovered.length > 0) { 
      var elem = hovered.pop(); 
      $(elem).css("border-color","black"); 
     } 
    } 
}); 

He probado esta solución con IE 11. Un ejemplo funcional se pueden encontrar here.

Cuestiones relacionadas