44

I have a floating div that gets displayed, and I want it to be hidden when the user clicks off the div. This would be similar to the .hover() function callback when hovering off an element. Only I want to do this for click.

I tried just setting a click event for the body, which would hide the div, but that gave unexpected results.

Anyone have ideas on how I could easily do this?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Nic Hubbard
  • 41,587
  • 63
  • 251
  • 412

15 Answers15

86

If you want to clear the div when you click somewhere else in the page, you can do something like:

$('body').click(function(event) {
    if (!$(event.target).closest('#myDiv').length) {
        $('#myDiv').hide();
    };
});
David Bennett
  • 1,885
  • 1
  • 12
  • 13
  • This is the only one that works for me for my situation. Thanks! – Dom Sep 20 '11 at 07:44
  • 5
    The [.closest](http://api.jquery.com/closest/) method returns a jQuery object. If it doesn't find anything, it returns an empty jQuery object. [.length](http://api.jquery.com/length/) is just a good way to determine if anything was found because 0==false and 1==true, while a jQuery object is "true" regardless of whether it's empty or not. – David Bennett Feb 25 '12 at 06:52
  • This is awesome, I spent 2-3 days looking for an answer. This works! Quick question, how does this affect performance as it's called on every click. – netwire Jul 31 '12 at 02:55
  • This worked great. Added this to account for trigger. (!$(event.target).closest('#myDiv').length && !$(event.target).closest('#trigger').length ) – noWayhome Mar 04 '13 at 23:33
19

Another, possibly simpler, option would be to add a transparent div between the floating DIV and the rest of the page.

A simple click event on the transparent DIV could handle the hiding, and it would avoid the issues you are encountering with the click event.

PhillFox
  • 839
  • 6
  • 16
  • Great idea. I had done something like this in the past for a different situation. Thanks for bringing this one to my attention. – Nic Hubbard Sep 14 '09 at 20:43
  • Your welcome, and thanks for accepting the answer. I almost didn't post because I don't really know what you are designing and thought that the option may not work - but sometimes an outsiders perspective is the best way to solve a problem. Good luck! – PhillFox Sep 14 '09 at 22:38
  • 4
    How is this simpler than DavidB's answer? – JPot Sep 15 '09 at 02:22
  • 1
    I called it a simpler solution because Nic was reporting unexpected results when using the click event on the body. My solution may not be as elegant as DavidB's, I'm not as proficient at JQuery, but it would get the job done by simply waiting for a click event on the hidden DIV. I was just throwing out another option for him to consider... – PhillFox Sep 18 '09 at 18:35
  • 4
    @PhillFox Just stumbled upon this via Google and thought I'd comment. The advantage to PhillFox's solution is that the transparent div will block any actual link or button clicks. Sometimes if there's a floating div shown, users will just click randomly off the div to make it go away. The transparent div prevents any mis-clicks, while DavidB's solution does not. – CaptSaltyJack May 19 '11 at 04:05
  • PhillFox - Also, this solution means that your script isn't run on EVERY click event. A minor efficiency concern maybe, but I definitely think it's cleaner. Along with @CaptSaltyJack reasons above (stop user accidentally clicking a link), I think this is a better solution. – dazbradbury Mar 22 '12 at 02:29
11

If you're using Jquery, you could use a selector like:

$("*:not(#myDiv)").live("click", function(){
    $("#myDiv").hide();
});
Kelly
  • 121
  • 1
  • 2
10

Surely you're looking for the blur event?

annakata
  • 74,572
  • 17
  • 113
  • 180
9

The Best way to do this is:-

    
$(document).bind('click', function(e) {  

 var $clicked = $(e.target);

    if (!$clicked.parents().hasClass("divtohide")) {
        $(".divtohide").hide();
    }

});
Samuel Katz
  • 24,066
  • 8
  • 71
  • 57
2

This worked for me,

var mouseOver = false;
$("#divToHide").mouseover(function(){mouseOver=true;});
$("#divToHide").mouseout(function(){mouseOver=false;});
$("body").click(function(){
      if(mouseOver == false) {
           $("#divToHide").hide();
      }
});
cupa
  • 21
  • 5
1
     $('body').click(function (event) {        
if ($("#divID").is(':visible')) {
            $('#divID').slideUp();
        }
});

This can be used to check if the div is visible, if it is visible, it will then slide the object up.

TGarrett
  • 562
  • 4
  • 15
1

This is a function to handle the click out event, I feed it the selector of the popup, and the jquery element. Probably better served as a jquery plugin, but this is simple enough.

clickOut = function(selector, element) {
 var hide = function(event) {
  // Hide search options if clicked out
  if (!$(event.originalEvent.target).parents(selector).size())
   $(element).hide();
  else
   $(document).one("click",hide);
 };

 $(document).one("click", hide);
};

So if you have a popup element like <div class='popup'>test</div> you can use my function like clickOut("div.popup", $("div.popup"));

Blazemonger
  • 90,923
  • 26
  • 142
  • 180
user467043
  • 11
  • 1
1

example you click a link element to display div menu , you simply bind blur function to link element to hide div menu

$('a#displaymenu').click(function(){
   $("#divName").toggle();
}).blur(function() {$("#divName").hide()})
Nick Hoàng
  • 417
  • 2
  • 6
0

Here's a full-fledged event-driven approach

  • Custom events handle the "summoning" and "dismissing" of the layer as to not step on the toes of other click-based events
  • document.body listens to for a dismiss event only when the layer in question is actually visible

Zee code:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">

$(function()
{
  var $layer = $('#layer');
  var $body  = $('html');

  $layer
    .bind( 'summon', function( e )
    {
      $layer.show();
      $body.bind( 'click', dismissLayer );
    } )
    .bind( 'dismiss', function( e )
    {
      $layer.hide();
      $body.unbind( 'click', dismissLayer );
    } )
    .click( function( e )
    {
      e.stopPropagation();
    })
    .trigger( 'dismiss' )
  ;

  function dismissLayer( e )
  {
    $layer.trigger( 'dismiss' );
  }

  // This is optional - this just triggers the div to 'visible'
  $('#control').click( function( e )
  {
    var $layer = $('#layer:hidden');
    if ( $layer.length )
    {
      $layer.trigger( 'summon' );
      e.stopPropagation();
    }
  } );
});

</script>

<style type="text/css">
#layer {
  position: absolute;
  left: 100px;
  top: 20px;
  background-color: red;
  padding: 10px;
  color: white;
}
#control {
  cursor: pointer;
}
</style>

</head>
<body>

<div id="layer">test</div>
<span id="control">Show div</span>

</body>
</html>

It's a lot of code I know, but here just to show a different approach.

Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
0

You can try this. http://benalman.com/projects/jquery-clickoutside-plugin/

rado
  • 4,040
  • 3
  • 32
  • 26
0

Using an event handler on the document works well for me:

function popUp( element )
{
    element.onmousedown = function (event) { event.stopPropagation(); };
    document.onmousedown = function () { popDown( element ); };

    document.body.appendChild( element );
}

function popDown( element )
{
    document.body.removeChild( element );

    document.onmousedown = null;
}
Gali
  • 1
  • 1
0

I've found the solution in a forum... but I can't find it back to credit the orginal author. Here is the version (modified that lives in my code).

 $(document).bind('mousedown.yourstuff', function(e) {
            var clicked=$(e.target); // get the element clicked                 
            if( clicked.is('#yourstuff')
                 || clicked.parents().is('#yourstuff')) {
                // click safe!
            } else {
                // outside click
                closeIt();
            }
        });

 function closeIt() {
        $(document).unbind('mousedown.emailSignin');
        //...
}

I also have ESC keyup bindings and a 'close' html anchor not pictured above.

Yann
  • 170
  • 7
0

If you do not want to hide the element that you will show by clicking itself:

var div_active, the_div;

the_div = $("#the-div");
div_active = false;

$("#show-the-div-button").click(function() {
  if (div_active) {
    the_div.fadeOut(function(){
      div_active = false;
    });
  } else {
    the_div.fadeIn(function(){
      div_active = true;
    });
  }
});

$("body").click(function() {
  if div_active {
    the_div.fadeOut();
    div_active = false;
  }
});

the_div.click(function() {
  return false;
});
Edison Machado
  • 1,410
  • 19
  • 29
-2

You're going to need to monitor the mouseDown event for the whole page, but you'll have to take note when the user is clicking inside your floating div.

I would suggest adding a hover event to your floated div so when the user is hovering over it, mouseDown is disregarded, but when it is not being hovered over mouseDown would close it

idrumgood
  • 4,904
  • 19
  • 29