Reputation: 1842
I know there are lots of ways to detect the click outside of an element. Mostly all of them use event.stopPropagation
. Since event.stopPropagation
will break other stuff, I was wondering if there is another way to achieve the same effect. I created a simple test for this:
HTML:
<div class="click">Click me</div>
Javascript:
$(function() {
var $click = $('.click'),
$html = $('html');
$click.on( 'click', function( e ) {
$click.addClass('is-clicked').text('Click outside');
// Wait for click outside
$html.on( 'click', clickOutside );
// Is there any other way except using .stopPropagation / return false
event.stopPropagation();
});
function clickOutside( e ) {
if ( $click.has( e.target ).length === 0 ) {
$click.removeClass('is-clicked').text('Click me');
// Remove event listener
$html.off( 'click', clickOutside );
}
}
});
This works, but only because i stop the bubbling with event.stopPropagation();
. How can i get rid of event.stopPropagation();
in this case?
Upvotes: 1
Views: 1783
Reputation: 5741
If the element in question has child elements, then those may show up as e.target
, and you can't simply compare it to your element.
In that case, capture the event in both the event and in the document, and detect events which only occurred on the document, for example by recording and comparing e.target
:
var lastTarget = undefined;
$("#interesting-div").click(function(e) {
// remember target
lastTarget = e.target;
});
$(document).click(function(e) {
if (e.target != lastTarget) {
// if target is different, then this event didn't come from our
// interesting div.
// do something interesting here:
console.log("We got a click outside");
}
});
var lastTarget = undefined;
$("#interesting-div").click(function(e) {
// remember target
lastTarget = e.target;
});
$(document).click(function(e) {
if (e.target != lastTarget) {
// if target is different, then this event didn't come from our
// interesting div.
// do something interesting here:
console.log("We got a click outside");
}
});
#interesting-div {
background: #ff0;
border: 1px solid black;
padding: .5em;
}
#annoying-childelement {
background: #fa0;
border: 1px solid black;
margin: 1em;
padding: .5em;
width: 20em;
}
#large-div {
background: #ccc;
padding: 2em 2em 20em 2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="large-div">
<div id="interesting-div">
This is our interesting element
<div id="annoying-childelement">
child element
</div>
</div>
</div>
</div>
Upvotes: 0
Reputation: 1
HTML code:
<div id="box" style="width:100px; height:100px; border:1px solid #000000; background-color:#00ff00;"></div>
JavaScript code:
function Init()
{
$(document).click(function(event){
if(event.target.id == "box")
{
$(event.target).css("backgroundColor", "#ff0000");
}
else
{
$("#box").css("backgroundColor", "#00ff00");
}
})
}
$(document).ready(Init);
Upvotes: 0
Reputation: 1325
You could do something like this to achieve the same effect
$(document).on("click", function(e){
var target = $(e.target);
if(target.hasClass("click")){
$click.addClass('is-clicked').text('Click outside');
}else{
$click.removeClass('is-clicked').text('Click me');
}
});
Upvotes: 0
Reputation: 59252
It can be done in a simpler way, can't it be? Why complicate things when something as simple as below could work.
$(document).click(function(e){
var elm = $('.click');
if(elm[0] == e.target){
elm.addClass("is-clicked").text("click outside");
} else { elm.removeClass("is-clicked").text("click inside"); }
});
Upvotes: 1