views:

132

answers:

3

Hey everyone

I created a date picker that uses ajax to populate an element with an id of calendarContainer. When the user clicks on a button to bring the calendar up, I want the user to be able to click anywhere else on the screen besides the calendar and have it hide. The calendarContainer is at the root of the dom and I have tried everything I can think of to get this working.

I have gotten the calendar to go away when it is not clicked on. However, when I click on the calendar it is also going away. I only want the calendar to go away when it is not clicked on.

Here are all of the things I have tried.

$(":not(#calendarContainer > table)").live('click', function() { $.Calendar.hide(); });
$(":not(#calendarContainer").live('click', function() { $.Calendar.hide(); });
$(":not(#calendarContainer)").click(function() { $.Calendar.hide(); });
$("body:not(#calendarContainer)").click(function() { $.Calendar.hide(); });
$(":not(#calendarContainer, #calendarData)").live('click', function() { $.Calendar.hide(); });

Thanks for any help, Metropolis

A: 

You need to select something. Does

$("*:not(#calendarContainer").live('click', function() { $.Calendar.hide(); });

work?

Tom
Thanks for the help Tom. That is doing the same thing as before. I thought if you do $(":not(#calendarContainer").live('click', function() { $.Calendar.hide(); });, that it was the same thing as *.
Metropolis
I also had tried $("body:not(#calendarContainer)").click(function() { $.Calendar.hide(); });before and it was also doing the same thing, which I thought would be the same as *.
Metropolis
'body:not' would look for body tags without that id.
Tom
A: 

You should have a look at the click outside plug in. Basically what's it's doing is setting a click event on the body element and then comparing the event target to see if it's equal to the selector you need and stopping propagation from there.

Victor
+1  A: 

You're seeing this behavior because events bubble, when you click on the calendar, you're still firing a click on each of it's parent elements because it bubbles up. To stop this, you need to stop the bubble, like this:

$("body").click(function() { $.Calendar.hide(); });

$("#calendarContainer").click(function(e) {
  e.stopPropagation(); //Stop click from bubbling to the body element
});
Nick Craver
Awesome! Thanks alot Nick. I have never completely understood bubbling. I thought that may have been the case here, but I was not positive. I understand how bubbling works on a small scale, but not on the entire dom. Do you have any good tips for bubbling or a good tutorial?
Metropolis
@Metropolis - Quirksmode has a decent explanation of it I think: http://www.quirksmode.org/js/events_order.html It's really no different on small vs large scale, events just keep bubbling all the way up the DOM unless you stop them. Some events don't bubble, or don't in some browsers (though jQuery compensates for this in most cases), so there are a few quirks, but nothing extremely complicated over the basics.
Nick Craver
If I stop propagation though.....does that interfere with any events after it? How do I know what I am stopping and what I want to keep working? I have read that article on bubbling before, It is pretty good. Thanks for the help.
Metropolis
@Metropolis - `stopPropagation()` only stops that particular click from bubbling higher to the body, it doesn't affect any other events. In this case you're only stopping a bubble of a click that originated inside `#calendar`, nothing else.
Nick Craver
Ah, that makes alot more sense. Ill think about that for a little bit and make sure I understand it. Ill put another comment in if I can think of anything else. Thanks again Nick
Metropolis