1025
votes

I am using this code:

$('body').click(function() {
   $('.form_wrapper').hide();
});

$('.form_wrapper').click(function(event){
   event.stopPropagation();
});

And this HTML:

<div class="form_wrapper">
   <a class="agree" href="javascript:;">I Agree</a>
   <a class="disagree" href="javascript:;">Disagree</a>
</div>

The problem is that I have links inside the div and when they no longer work when clicked.

30
Using plain javascript you can try something like this: jsfiddle.net/aamir/y7mEYAamir Afridi
using $('html') or $(document) would be better than $('body')Adrien Be

30 Answers

2595
votes

Had the same problem, came up with this easy solution. It's even working recursive:

$(document).mouseup(function(e) 
{
    var container = $("YOUR CONTAINER SELECTOR");

    // if the target of the click isn't the container nor a descendant of the container
    if (!container.is(e.target) && container.has(e.target).length === 0) 
    {
        container.hide();
    }
});
210
votes

You'd better go with something like this:

var mouse_is_inside = false;

$(document).ready(function()
{
    $('.form_content').hover(function(){ 
        mouse_is_inside=true; 
    }, function(){ 
        mouse_is_inside=false; 
    });

    $("body").mouseup(function(){ 
        if(! mouse_is_inside) $('.form_wrapper').hide();
    });
});
97
votes

This code detects any click event on the page and then hides the #CONTAINER element if and only if the element clicked was neither the #CONTAINER element nor one of its descendants.

$(document).on('click', function (e) {
    if ($(e.target).closest("#CONTAINER").length === 0) {
        $("#CONTAINER").hide();
    }
});
78
votes

You might want to check the target of the click event that fires for the body instead of relying on stopPropagation.

Something like:

$("body").click
(
  function(e)
  {
    if(e.target.className !== "form_wrapper")
    {
      $(".form_wrapper").hide();
    }
  }
);

Also, the body element may not include the entire visual space shown in the browser. If you notice that your clicks are not registering, you may need to add the click handler for the HTML element instead.

45
votes

Live DEMO

Check click area is not in the targeted element or in it's child

$(document).click(function (e) {
    if ($(e.target).parents(".dropdown").length === 0) {
        $(".dropdown").hide();
    }
});

UPDATE:

jQuery stop propagation is the best solution

Live DEMO

$(".button").click(function(e){
    $(".dropdown").show();
     e.stopPropagation();
});

$(".dropdown").click(function(e){
    e.stopPropagation();
});

$(document).click(function(){
    $(".dropdown").hide();
});
21
votes
$(document).click(function(event) {
    if ( !$(event.target).hasClass('form_wrapper')) {
         $(".form_wrapper").hide();
    }
});
18
votes

Updated the solution to:

  • use mouseenter and mouseleave instead
  • of hover use live event binding

var mouseOverActiveElement = false;

$('.active').live('mouseenter', function(){
    mouseOverActiveElement = true; 
}).live('mouseleave', function(){ 
    mouseOverActiveElement = false; 
});
$("html").click(function(){ 
    if (!mouseOverActiveElement) {
        console.log('clicked outside active element');
    }
});
17
votes

A solution without jQuery for the most popular answer:

document.addEventListener('mouseup', function (e) {
    var container = document.getElementById('your container ID');

    if (!container.contains(e.target)) {
        container.style.display = 'none';
    }
}.bind(this));

MDN: https://developer.mozilla.org/en/docs/Web/API/Node/contains

10
votes

Live demo with ESC functionality

Works on both Desktop and Mobile

var notH = 1,
    $pop = $('.form_wrapper').hover(function(){ notH^=1; });

$(document).on('mousedown keydown', function( e ){
  if(notH||e.which==27) $pop.hide();
});

If for some case you need to be sure that your element is really visible when you do clicks on the document: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();

9
votes

Wouldn't something like this work?

$("body *").not(".form_wrapper").click(function() {

});

or

$("body *:not(.form_wrapper)").click(function() {

});
7
votes

Even sleaker:

$("html").click(function(){ 
    $(".wrapper:visible").hide();
});
7
votes

Instead of listening to every single click on the DOM to hide one specific element, you could set tabindex to the parent <div> and listen to the focusout events.

Setting tabindex will make sure that the blur event is fired on the <div> (normally it wouldn't).

So your HTML would look like:

<div class="form_wrapper" tabindex="0">
    <a class="agree" href="javascript:;">I Agree</a>
    <a class="disagree" href="javascript:;">Disagree</a>
</div>

And your JS:

$('.form_wrapper').on('focusout', function(event){
    $('.form_wrapper').hide();
});
7
votes

So many answers, must be a right of passage to have added one... I didn't see a current (jQuery 3.1.1) answers - so:

$(function() {
    $('body').on('mouseup', function() {
        $('#your-selector').hide();
    });
});
6
votes

And for Touch devices like IPAD and IPHONE we can use following code

$(document).on('touchstart', function (event) {
var container = $("YOUR CONTAINER SELECTOR");

if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
    {
        container.hide();
    }
});
6
votes

Here's a jsfiddle I found on another thread, works with esc key also: http://jsfiddle.net/S5ftb/404

    var button = $('#open')[0]
    var el     = $('#test')[0]

    $(button).on('click', function(e) {
      $(el).show()
      e.stopPropagation()
    })

    $(document).on('click', function(e) {
      if ($(e.target).closest(el).length === 0) {
        $(el).hide()
      }
    })

    $(document).on('keydown', function(e) {
      if (e.keyCode === 27) {
        $(el).hide()
      }
    })
6
votes

Built off of prc322's awesome answer.

function hideContainerOnMouseClickOut(selector, callback) {
  var args = Array.prototype.slice.call(arguments); // Save/convert arguments to array since we won't be able to access these within .on()
  $(document).on("mouseup.clickOFF touchend.clickOFF", function (e) {
    var container = $(selector);

    if (!container.is(e.target) // if the target of the click isn't the container...
        && container.has(e.target).length === 0) // ... nor a descendant of the container
    {
      container.hide();
      $(document).off("mouseup.clickOFF touchend.clickOFF");
      if (callback) callback.apply(this, args);
    }
  });
}

This adds a couple things...

  1. Placed within a function with a callback with "unlimited" args
  2. Added a call to jquery's .off() paired with a event namespace to unbind the event from the document once it's been run.
  3. Included touchend for mobile functionality

I hope this helps someone!

5
votes

if you have trouble with ios, mouseup is not working on apple device.

does mousedown /mouseup in jquery work for the ipad?

i use this:

$(document).bind('touchend', function(e) {
        var container = $("YOURCONTAINER");

          if (container.has(e.target).length === 0)
          {
              container.hide();
          }
      });
5
votes

(Just adding on to prc322's answer.)

In my case I'm using this code to hide a navigation menu that appears when the user clicks an appropriate tab. I found it was useful to add an extra condition, that the target of the click outside the container is not a link.

$(document).mouseup(function (e)
{
    var container = $("YOUR CONTAINER SELECTOR");

    if (!$("a").is(e.target) // if the target of the click isn't a link ...
        && !container.is(e.target) // ... or the container ...
        && container.has(e.target).length === 0) // ... or a descendant of the container
    {
        container.hide();
    }
});

This is because some of the links on my site add new content to the page. If this new content is added at the same time that the navigation menu disappears it might be disorientating for the user.

4
votes
var n = 0;
$("#container").mouseenter(function() {
n = 0;

}).mouseleave(function() {
n = 1;
});

$("html").click(function(){ 
if (n == 1) {
alert("clickoutside");
}
});
4
votes
 $('body').click(function(event) {
    if (!$(event.target).is('p'))
    {
        $("#e2ma-menu").hide();
    }
});

p is the element name. Where one can pass the id or class or element name also.

3
votes

Return false if you click on .form_wrapper:

$('body').click(function() {
  $('.form_wrapper').click(function(){
  return false
});
   $('.form_wrapper').hide();
});

//$('.form_wrapper').click(function(event){
//   event.stopPropagation();
//});
3
votes

Attach a click event to top level elements outside the form wrapper, for example:

$('#header, #content, #footer').click(function(){
    $('.form_wrapper').hide();
});

This will also work on touch devices, just make sure you don't include a parent of .form_wrapper in your list of selectors.

3
votes

var exclude_div = $("#ExcludedDiv");;  
$(document).click(function(e){
   if( !exclude_div.is( e.target ) )  // if target div is not the one you want to exclude then add the class hidden
        $(".myDiv1").addClass("hidden");  

}); 

FIDDLE

3
votes

$(document).ready(function() {
	$('.modal-container').on('click', function(e) {
	  if(e.target == $(this)[0]) {
		$(this).removeClass('active'); // or hide()
	  }
	});
});
.modal-container {
	display: none;
	justify-content: center;
	align-items: center;
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0,0,0,0.5);
	z-index: 999;
}

.modal-container.active {
    display: flex;  
}

.modal {
	width: 50%;
	height: auto;
	margin: 20px;
	padding: 20px;
	background-color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modal-container active">
	<div class="modal">
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac varius purus. Ut consectetur viverra nibh nec maximus. Nam luctus ligula quis arcu accumsan euismod. Pellentesque imperdiet volutpat mi et cursus. Sed consectetur sed tellus ut finibus. Suspendisse porttitor laoreet lobortis. Nam ut blandit metus, ut interdum purus.</p>
	</div>
</div>
3
votes

Copied from https://sdtuts.com/click-on-not-specified-element/

Live demo http://demos.sdtuts.com/click-on-specified-element

$(document).ready(function () {
    var is_specified_clicked;
    $(".specified_element").click(function () {
        is_specified_clicked = true;
        setTimeout(function () {
            is_specified_clicked = false;
        }, 200);
    })
    $("*").click(function () {
        if (is_specified_clicked == true) {
//WRITE CODE HERE FOR CLICKED ON OTHER ELEMENTS
            $(".event_result").text("you were clicked on specified element");
        } else {
//WRITE CODE HERE FOR SPECIFIED ELEMENT CLICKED
            $(".event_result").text("you were clicked not on specified element");
        }
    })
})
2
votes

What you can do is bind a click event to the document that will hide the dropdown if something outside the dropdown is clicked, but won't hide it if something inside the dropdown is clicked, so your "show" event (or slidedown or whatever shows the dropdown)

    $('.form_wrapper').show(function(){

        $(document).bind('click', function (e) {
            var clicked = $(e.target);
            if (!clicked.parents().hasClass("class-of-dropdown-container")) {
                 $('.form_wrapper').hide();
            }
        });

    });

Then when hiding it, unbind the click event

$(document).unbind('click');
2
votes

i did it like this:

var close = true;

$(function () {

    $('body').click (function(){

        if(close){
            div.hide();
        }
        close = true;
    })


alleswasdenlayeronclicknichtschliessensoll.click( function () {   
        close = false;
    });

});
2
votes
dojo.query(document.body).connect('mouseup',function (e)
{
    var obj = dojo.position(dojo.query('div#divselector')[0]);
    if (!((e.clientX > obj.x && e.clientX <(obj.x+obj.w)) && (e.clientY > obj.y && e.clientY <(obj.y+obj.h))) ){
        MyDive.Hide(id);
    }
});
2
votes

By using this code you can hide as many items as you want

var boxArray = ["first element's id","second element's id","nth element's id"];
   window.addEventListener('mouseup', function(event){
   for(var i=0; i < boxArray.length; i++){
    var box = document.getElementById(boxArray[i]);
    if(event.target != box && event.target.parentNode != box){
        box.style.display = 'none';
    }
   }
})
1
votes

According to the docs, .blur() works for more than the <input> tag. For example:

$('.form_wrapper').blur(function(){
   $(this).hide();
});