Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery: click everywhere but some element

I have some elements which i can select with .click() function and they became highlighted. There is menu above them with some actions. I want to cancel highlight when I click any element but not menu.

Structure:

<body>
    <div id="menu">
    </div>
    <div id="elements">
        /* selectable elements here */
    </div>
</body>

Executable Example

$().ready(function(){
	$("#elements a").click(function(){
  	$(this).css('color', 'red');
  	return false;
  });
  $(document).click(function(e) {
    if ( $(e.target).closest('#menu').length === 0 ) {
        $("#elements a").css('color', 'blue');
    }
	});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu">
        <a href="#">Menu 1</a>
        <a href="#">Menu 2</a>
        <a href="#">Menu 3</a>
    </div>
    <div id="elements">
        <a href="#">Element 1</a>
        <a href="#">Element 2</a>
        <a href="#">Element 3</a>
    </div>
    <div>
      Click any element to highlight it. Click anywhere to reset highlighting. Click menu to keep highlighting.
    </div>

Jsfiddle

I tried to bind $("body *").not("#menu").click(...); but when I click on #menu then body's onclick event fired too because #menu is body's children.

like image 749
ink Avatar asked Mar 18 '11 22:03

ink


4 Answers

$(document).click(function(e) {
    if ( $(e.target).closest('#menu').length === 0 ) {
        // cancel highlighting 
    }
});

An alternative solution would be to call stopPropagation() at the end of the #menu click handler and element click handlers. That way, if a click event bubbles to the document object, you know that neither the menu nor the elements were clicked and you can safely cancel the highlighting:

$('#menu').click(function(e) {
    // do stuff
    e.stopPropagation();
});

$('.element').click(function(e) {
    //do stuff
    e.stopPropagation();
});

$(document).click(function() {
    // cancel highlighting
});
like image 101
Šime Vidas Avatar answered Nov 09 '22 23:11

Šime Vidas


.closest will propagate and check if one of the parents is the unclickable element.

$(document).on('click', '.clickable_parent', function(e){
  if(e.target.closest(".UnClickable_child") === null){
   //do stuff
  }
});
like image 21
Kareem Avatar answered Nov 10 '22 00:11

Kareem


An alternative to writing your own delegated handler for this is to use Ben Almans "outside events" plugin to achieve this. Does pretty much the same thing mentioned by Šime Vidas but hey - choices are a good thing!

http://benalman.com/projects/jquery-outside-events-plugin/

So something like this

$('#menu').bind("clickoutside", function(){
    // cancel highlighting
})
like image 31
James Hughes Avatar answered Nov 09 '22 23:11

James Hughes


You should handle the click event on body, then check whether $.contains($('#menu'), e.target).

like image 1
SLaks Avatar answered Nov 10 '22 00:11

SLaks