0

I'm trying to add a $('body').live('click') listener after the user clicks on a div. The purpose is creating a custom dropdown box that the user can open and eventually close by clicking anywhere on the page.

But when I add .live() or .bind() function inside a .click() function, the live() function is triggered for some reason:

$('#myDiv').click(function(){
    $('#myDiv .child').show().addClass('showing');
    $('body').live('click', function(){
           $('#myDiv .child').hide();
           $('body').die();
    })
})

#myDiv is shown but immediately hides, evidenced by the lingering .showing class.

Am I using live() wrong? How do I avoid this recursion?

podcastfan88
  • 970
  • 2
  • 13
  • 28
  • explain what are you trying to do rather than explaining what you are currently doing. maybe we can provide an alternative rather than fixing a potentially buggy code. – Joseph Apr 05 '12 at 02:47

4 Answers4

3

return false will stop event propagation:

    $('#myDiv').click(function(){
    $('#myDiv .child').show().addClass('showing');
    $('body').live('click', function(){
           $('#myDiv .child').hide();
           $('body').die();
    });
    return false;
})
Ilia Frenkel
  • 1,969
  • 13
  • 19
  • Thanks, this also worked and it's a bit easier than passing an event and using event.stopPropagation(). – podcastfan88 Apr 05 '12 at 02:59
  • 2
    @stuart - FYI, returning `false` isn't exactly the same `e.stopPropagation()`. Returning false causes jQuery to execute both `e.stopPropagation()` and `e.preventDefault()`. Maybe doesn't make a different to you in this case, but you should understand that it isn't exactly the same. As far as the event being passed to the event handler, it is always passed to an event handler whether you declare the argument or not - it's always there. – jfriend00 Apr 05 '12 at 03:03
  • @jfriend00 I totally agree with you. You should always know what you are doing in your code :-) – Ilia Frenkel Apr 05 '12 at 03:08
  • Also, this example is ready made for `.one()`. If you use that instead of `.live()`, then you don't need the `.die()` line. – jfriend00 Apr 05 '12 at 03:10
  • Thanks kindly for the explanation. I'll look into these a bit further. – podcastfan88 Apr 05 '12 at 03:10
0

Use second body click binding without live (also you don't need it, because it always on page) and use timeout:

$('#myDiv').on('click',function(){
    $('#myDiv .child').show().addClass('showing');
setTimeout(function(){
$('body').on('click', function(){
           $('#myDiv .child').hide();
           $('body').off('click');
    });
},0);

});
Rustam
  • 1,875
  • 2
  • 16
  • 33
0

Maybe it should work, maybe it shouldn't. But it doesn't. I'd recommend setting up all your event handlers at the beginning, and just have a global variable (e.g.) that tracks whether or not the second event handler should actually respond or not.

dkamins
  • 21,450
  • 7
  • 55
  • 59
0

You probably have to stop propagation of the current event to keep it from bubbling up to the body where your new event handler will see it. Further, you can use .one() for a one time event handler:

$('#myDiv').on('click',function(e){
    $('#myDiv .child').show().addClass('showing');
    e.stopPropagation();
    $(document.body).one('click', function() {
           $('#myDiv .child').hide();
    });
})
jfriend00
  • 683,504
  • 96
  • 985
  • 979