Ejecución de una acción al pasar el ratón sobre (y dejando) un elemento (o sus elementos secundarios)

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

Pregunta

Imagínese que tengo los siguientes elementos:

+------------------+
|                  |
|    +----------------+
|    |                |
|    |                |
|    +----------------+
|                  |
+------------------+

El elemento interior tiene posicionamiento que quiere decir que se puede sentar visualmente el exterior de su padre, y me puso un detector de eventos en la matriz, como por ejemplo:

parent.addEventListener('mouseover', function(e) {
  // log mouse is over me
}, false);

Si ratón directamente sobre el padre de la parte inferior, aparece un evento directa, pero debido a eventos de enrutamiento si el cursor sobre el lado de (golpear al niño en primer lugar), también voy a recibir el evento del niño como que se propaga hacia arriba.

Si sigo yendo hacia la izquierda hasta que esté fuera del elemento secundario y en el espacio de los padres, voy a conseguir un evento directa, si voy a la derecha de nuevo, voy a conseguir otro evento burbujear del elemento secundario.

Esto es por diseño y el diseño es absolutamente bien, sin embargo- si quiero hacer una acción SOLO cuando el ratón (incluyendo mi elementos secundarios) en off, tengo que hacer un trabajo extra para bloquear los acontecimientos no estoy interesado en .. por ejemplo, esto funcionaría:

var isOver = false;

parent.addEventListener('mouseover', function(e) {
  if (isOver) return;
  isOver = true;
  // log mouse is over me
}, false);

parent.addEventListener('mouseout', function(e) {
  if (e.relatedTarget == this || e.relatedTarget.isDescendantOf(this)) return;
  isOver = false;
  // log mouse is leaving me
}, false);

En esencia, el código tiene una variable de estado para determinar si el ratón ha 'overed' el padre (ya sea a través de su hijo o no), y si se activa el evento de nuevo, mientras que 'overed' esos eventos son ignorados .. también capturan la ratón fuera del evento y pedir a ella .. es la relatedTarget (el objetivo que está a punto de entrar) ME? (El padre), o un niño eventual de la EM? Si es así, entonces no hacer nada .. de lo contrario establecer el estado 'overed' false.

Así que el código funciona realmente, pero imagino que no puedo utilizar la propiedad relatedTarget para determinar el próximo objetivo, ¿cómo se van haciendo sobre este comportamiento?

espero que tenga sentido, tengo los theres sensación no es suficiente contexto en los eventos hacerlo sin relatedTarget pero sentía que podría muy bien ser un ángulo en relación con el cambio de comportamiento en la propiedad eventPhase (para determinar si el evento es directa o burbujear ).

Además, no estoy en busca de respuestas que dicen 'esto no funcionará en IE, bla bla' .. Estoy trabajando en contra de los navegadores de especificaciones del W3C caso solamente en este momento.

Gracias de antemano, Stephen.


Editar, sólo para aclarar, quiero que los acontecimientos a suceder como si tuviera un solo elemento que se veía así (si el elemento era en realidad que el anterior ejemplo):

+------------------+
|                  |
|                  +--+
|                     |
|                     |
|                  +--+
|                  |
+------------------+
¿Fue útil?

Solución

Creo que lo que está después de IE son "mouseenter" evento (se activa cuando el usuario mueve el puntero del ratón dentro de los límites del objeto) y evento "mouseleave" (incendios cuando el usuario mueve el puntero del ratón fuera de los límites del objeto):

  

A diferencia del caso onmouseover, la   onmouseenter caso no burbujea. En   Es decir, el evento onmouseenter   no se dispara cuando el usuario mueve el   puntero del ratón sobre elementos contenidos   por el objeto, mientras que onmouseover   hace fuego.

Lo mismo ocurre con onmouseleave.

Este es un ejemplo: http://jsbin.com/uputi (añadir /edit a la URL para editar el código fuente):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<title>Sandbox</title> 
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen"> 
#outer { width:200px; height:200px; border:1px solid #333; }
#inner { float:right; width:125px; height:80px; margin-right:-80px; border:1px solid #333; }
</style> 

<script> 
window.onload = function() {
  function mouseenter() {
    document.getElementById('dbg').innerHTML = 'mouse entered #outer boundary';
  }

  function mouseleave() {
    document.getElementById('dbg').innerHTML = 'mouse left #outer boundary';
  }

  var outer = document.getElementById('outer');

  if ('onmouseenter' in document.body) {
    // browser supports mouseenter/mouseleave natively (i.e., IE)
    outer.onmouseenter = mouseenter;
    outer.onmouseleave = mouseleave;
  }
  else {
    // simulate mouseenter/mouseleave in other browsers
    function wrap(fn) {
      return function(event) {
        var parent = event.relatedTarget;

        // Check if we're still within the same parent (traverse up parentNodes)
        while (parent && parent != this) {
          parent = parent.parentNode
        }

        if(parent != this) {
          // call the *real* mouseover/mouseout handler
          fn.call(this, event)
        }
      }
    }

    outer.onmouseover = wrap(mouseenter);
    outer.onmouseout = wrap(mouseleave);
  }
}
</script> 
</head> 
<body> 
  <div id="outer"> 
    <div><code>#outer</code></div> 
    <div>&nbsp;</div> 
    <div>&nbsp;</div> 
    <div id="inner"><code>#inner</code></div> 
  </div> 
  <div id="dbg"></div> 
</body> 
</html>

relatedTarget como lo hace (que funciona bien en los navegadores estándares FYI), pero sin la bandera del estado. Consulte este artículo para más detalles de la emulación que se muestra aquí. Se puede ver un solo evento mouseenter se activa al entrar en el elemento #outer, así como el elemento #inner. Este es el efecto "límite" que se va después (creo).

Si usted tiene la opción de incluir jQuery en su aplicación, j de consulta trae estos fantásticos eventos a otros navegadores . (Nota jQuery utiliza la técnica de su esbozó internamente, con algunas modificaciones menores).

también tiene estos acontecimientos simulado.

Otros consejos

Creo que sólo hay que stopPropagation

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top