2011-01-11 8 views
26

Supongamos que tengo un div en mi página. cómo detectar al usuario hacer clic en el contenido div o fuera del contenido div a través de JavaScript o JQuery. ayuda con un pequeño fragmento de código. gracias.Detectar hacer clic dentro/fuera del elemento con controlador de evento único

Editar: Como comenté en una de las respuestas a continuación, solo deseo adjuntar un controlador de eventos a mi cuerpo, y también quiero saber en qué elemento se hizo clic.

Respuesta

63

En JavaScript (a través de jQuery):

$(function() { 
 
    $("body").click(function(e) { 
 
    if (e.target.id == "myDiv" || $(e.target).parents("#myDiv").length) { 
 
     alert("Inside div"); 
 
    } else { 
 
     alert("Outside div"); 
 
    } 
 
    }); 
 
})
#myDiv { 
 
    background: #ff0000; 
 
    width: 25vw; 
 
    height: 25vh; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="myDiv"></div>

+4

Esto no controlará los casos en que el usuario haga clic en un elemento secundario del div; informará '" div externo "'. – Phrogz

+0

Agradable. El uso de 'parents()' me ha inspirado a actualizar mi respuesta para usar más jQuery y menos recorrido de la vieja escuela. – Phrogz

+0

Esto no funcionará si hay elementos fuera del div que usan stopPropagation, vea el ejemplo aquí: http://jsfiddle.net/Flandre/YdrTA/ – Andre

12

Usando jQuery, y suponiendo que usted tiene <div id="foo">:

jQuery(function($){ 
    $('#foo').click(function(e){ 
    console.log('clicked on div'); 
    e.stopPropagation(); // Prevent bubbling 
    }); 
    $('body').click(function(e){ 
    console.log('clicked outside of div'); 
    }); 
}); 

Editar: Para un solo controlador:

jQuery(function($){ 
    $('body').click(function(e){ 
    var clickedOn = $(e.target); 
    if (clickedOn.parents().andSelf().is('#foo')){ 
     console.log("Clicked on", clickedOn[0], "inside the div"); 
    }else{ 
     console.log("Clicked outside the div"); 
    }); 
}); 
+0

gracias por su esfuerzo, pero lo quiero en forma diferente.Quiero capturar el ID del elemento donde ocurrió el clic y quiero manejarlo a nivel del cuerpo, no quiero adjuntar un controlador de evento click con div. – Thomas

+0

si hago clic en #foo que también desencadena los manipuladores del cuerpo porque foo está dentro del cuerpo – amosrivera

+0

@amosRivera No, no es así, porque la llamada a 'stopPropagation' evita que burbujee. Puede probar esto usted mismo aquí: http://jsfiddle.net/Qh2MN/ – Phrogz

4

¿Y esto?

<style type="text/css"> 
div {border: 1px solid red; color: black; background-color: #9999DD; 
width: 20em; height: 40em;} 
</style> 

<script type="text/javascript"> 
function sayLoc(e) { 
e = e || window.event; 
var tgt = e.target || e.srcElement; 

// Get top lef co-ords of div 
var divX = findPosX(tgt); 
var divY = findPosY(tgt); 

// Workout if page has been scrolled 
var pXo = getPXoffset(); 
var pYo = getPYoffset(); 

// Subtract div co-ords from event co-ords 
var clickX = e.clientX - divX + pXo; 
var clickY = e.clientY - divY + pYo; 

alert('Co-ords within div (x, y): ' 
+ clickX + ', ' + clickY); 
} 

function findPosX(obj) { 
var curleft = 0; 
if (obj.offsetParent) { 
while (obj.offsetParent) { 
curleft += obj.offsetLeft 
obj = obj.offsetParent; 
} 
} else if (obj.x) { 
curleft += obj.x; 
} 
return curleft; 
} 

function findPosY(obj) { 
var curtop = 0; 
if (obj.offsetParent) { 
while (obj.offsetParent) { 
curtop += obj.offsetTop 
obj = obj.offsetParent; 
} 
} else if (obj.y) { 
curtop += obj.y; 
} 
return curtop; 
} 

function getPXoffset(){ 
if (self.pageXOffset) { // all except Explorer 
return self.pageXOffset; 
} else if (document.documentElement 
&& document.documentElement.scrollTop) {// Explorer 6 Strict 
return document.documentElement.scrollLeft; 
} else if (document.body) { // all other Explorers 
return document.body.scrollLeft; 
} 
} 

function getPYoffset(){ 
if (self.pageYOffset) { // all except Explorer 
return self.pageYOffset; 
} else if (document.documentElement 
&& document.documentElement.scrollTop) {// Explorer 6 Strict 
return document.documentElement.scrollTop; 
} else if (document.body) { // all other Explorers 
return document.body.scrollTop; 
} 
} 
</script> 

<div onclick="sayLoc(event);"></div> 

(de http://bytes.com/topic/javascript/answers/151689-detect-click-inside-div-mozilla, utilizando el Google.)

+1

Esa es una gran cantidad de código para algo que ahora se puede hacer en una sola línea: http://stackoverflow.com/a/28432139/288906 –

-1

En lugar de utilizar el cuerpo puede crear una cortina con z-index de 100 (para elegir un número) y dar al elemento interior un valor más alto z-index mientras que todos los demás Los elementos r tienen un índice z más bajo que la cortina.

Ver ejemplo de trabajo aquí: http://jsfiddle.net/Flandre/6JvFk/

jQuery:

$('#curtain').on("click", function(e) { 

    $(this).hide(); 
    alert("clicked ouside of elements that stand out"); 

}); 

CSS:

.aboveCurtain 
{ 
    z-index: 200; /* has to have a higher index than the curtain */ 
    position: relative; 
    background-color: pink; 
} 

#curtain 
{ 
    position: fixed; 
    top: 0px; 
    left: 0px; 
    height: 100%; 
    background-color: black; 
    width: 100%; 
    z-index:100; 
    opacity:0.5 /* change opacity to 0 to make it a true glass effect */ 
} 
7

En lugar de utilizar la función de jQuery .parents (como se sugiere en la respuesta aceptada), es mejor para usar .closest para este propósito. Como explained in the jQuery api docs, .closest comprueba el elemento pasado y todos sus padres, mientras que .parents simplemente comprueba los padres. En consecuencia, esto funciona:

$(function() { 
    $("body").click(function(e) { 
     if ($(e.target).closest("#myDiv").length) { 
      alert("Clicked inside #myDiv"); 
     } else { 
      alert("Clicked outside #myDiv"); 
     } 
    }); 
}) 
22

Aquí hay un chiste que no requiere el uso de jQuery Node.contains:

// Get arbitrary element with id "my-element" 
var myElementToCheckIfClicksAreInsideOf = document.querySelector('#my-element'); 
// Listen for click events on body 
document.body.addEventListener('click', function (event) { 
    if (myElementToCheckIfClicksAreInsideOf.contains(event.target)) { 
     console.log('clicked inside'); 
    } else { 
     console.log('clicked outside'); 
    } 
}); 

Si usted se pregunta sobre el caso borde de comprobar si el clic en el el elemento en sí, Node.contains devuelve verdadero para el elemento en sí (por ejemplo, element.contains(element) === true) por lo que este fragmento siempre debería funcionar.

El soporte del navegador parece cubrir prácticamente todo según la página de MDN.

0

Esta pregunta puede ser respondida con coordenadas X e Y, y sin jQuery:

 var isPointerEventInsideElement = function (event, element) { 
      var pos = { 
       x: event.targetTouches ? event.targetTouches[0].pageX : event.pageX, 
       y: event.targetTouches ? event.targetTouches[0].pageY : event.pageY 
      }; 
      var rect = element.getBoundingClientRect(); 
      return pos.x < rect.right && pos.x > rect.left && pos.y < rect.bottom && pos.y > rect.top; 
     }; 

     document.querySelector('#my-element').addEventListener('click', function (event) { 
      console.log(isPointerEventInsideElement(event, document.querySelector('#my-any-child-element'))) 
     }); 
Cuestiones relacionadas