mrksbnch
mrksbnch

Reputation: 1842

Click outside element without using event.stopPropagation

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 );
        }
    }
});

http://jsfiddle.net/8p4jhvqn/

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

Answers (4)

roeland
roeland

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

Someone
Someone

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

twain
twain

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

Amit Joki
Amit Joki

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"); }
});

DEMO

Upvotes: 1

Related Questions