2009-07-21 34 views
12

Similar a this question, pero dando un paso más. Me gustaría para detectar clics fuera de un conjunto de artículos, que estoy manejando de la manera siguiente:¿Detectar un clic fuera del elemento?

$('#menu div').live('click', function() { 
    // Close other open menu items, if any. 
    // Toggle the clicked menu item. 

    $('body').one('click', function(event) { 
     // Hide the menu item. 
     event.stopPropagation(); 
    }); 
}); 

Esto funciona como un encanto, por desgracia, cuando otro elemento de menú está abierto y se hace clic en un segundo , requiere dos clics para abrir el segundo elemento. El primer clic oculta el primer elemento del menú que estaba abierto, el segundo muestra el segundo elemento del menú .

El comportamiento "correcto" funciona de la siguiente manera:

  • Al hacer clic en un elemento de menú que se abre.
  • Al hacer clic en el mismo elemento de menú (o sus elementos secundarios), se cierra.
  • Al hacer clic en otro elemento del menú se cierra el primero, se abre el segundo.
  • Al hacer clic fuera de los elementos del menú (abrir), se cierran.

he intentado lo siguiente en lugar de la $('body').one() orden anterior de ignorar clics en los elementos de menú con poco éxito:

// Captures click on menu items in spite of the not. 
$('*').not('#menu *').one('click', function() { // Hide menu } 
$('*:not(#menu)').one('click', function() { // Hide menu } 

Como siempre, gracias por cualquier ayuda!

Respuesta

29

sólo hay que mover el manejador cuerpo clic fuera y hacer algo como esto:

$('body').bind('click', function(e) { 
    if($(e.target).closest('#menu').length == 0) { 
     // click happened outside of menu, hide any visible menu items 
    } 
}); 

Se señaló incorrectamente en los comentarios que e.target no funciona en IE; esto no es cierto ya que jQuery's Event object soluciona estas incoherencias cuando es necesario (IE, Safari).

+0

Cuál es el propósito de mover el 'body' clic manejador fuera del menú del botón manipulador? Parece que realiza la misma tarea (sin la sobrecarga de atrapar cada clic del cuerpo si el menú nunca se abre) al aplicarlo después de que se abre un elemento del menú. ¿O me estoy perdiendo algo? – chuckg

+0

Es un buen punto; Considero que la sobrecarga de vincular y desvincular un evento cada vez que un usuario hace clic en un elemento del menú es innecesario. Por lo general, no habrá mucho clic en una página aparte de ir a otra página, en cuyo caso el controlador de clic extra es completamente irrelevante. Al final del día, ambos están bien dependiendo de sus necesidades, por lo que puede apegarse al único controlador si se ajusta a sus necesidades. –

+0

e.target no funciona en IE ... –

15

escribí esto hace mucho tiempo, antes de los días de gloria de jQuery ...

function clickedOutsideElement(elemId) { 
    var theElem = getEventTarget(window.event); 
    while(theElem != null) { 
    if(theElem.id == elemId) 
     return false; 
    theElem = theElem.offsetParent; 
    } 
    return true; 
} 

function getEventTarget(evt) { 
    var targ = (evt.target) ? evt.target : evt.srcElement; 
    if(targ != null) { 
    if(targ.nodeType == 3) 
     targ = targ.parentNode; 
    } 
    return targ; 
} 

document.onclick = function() { 
    if(clickedOutsideElement('divTest')) 
    alert('Outside the element!'); 
    else 
    alert('Inside the element!'); 
} 
+0

jQuery corrige que e.target es un navegador cruzado, lo que hace innecesario todo este alboroto. :) –

+0

Todo esto es discutible si solo es compatible con IE9 +, ahora está arreglado http://msdn.microsoft.com/en-us/library/ie/ff974946%28v=vs.85%29.aspx – Gabe

Cuestiones relacionadas