tags:

views:

43

answers:

4

I am trying to figured out how to make a menu disappear when the user clicks outside of it. my approach is this :

$(*).not(menu).bind('click', function() { $(menu).hide() })

for some reason this is not working. any idea what I might be doing wrong? thank you

+3  A: 

this

$('*').

is evil, mad and bad karma!

use instead

$(document.body).bind('click', function(e){
    if(e.target.id !== 'yourmenuid' || $(e.target).parents().is('#yourmenuid'))
       $('#menuid').hide();
});

Try to avoid the universal selector * at all times. Sizzle will indeed query all available elements in your markup which is terribly expensive.

jAndy
Works Great! thanks for the tip.
salmane
This can't work. `parents` is a method -- not a collection.
J-P
And shouldn't the condition be `if (target is NOT within menu)` ... as opposed to `if (target is within menu)` as you have here.
J-P
+2  A: 

This is a bad idea.

Writing $('*') will add your click handler to every single element in the document, which will be slow. In addition, it won't handle clicks on any new elements added later. (Unless they bubble up)

Instead, you should handle the click event for the root element, like this:

$(document).click(function(e) {
    if (e.target === menu || $(e.target).parents().is(menu))
        return;
    $(menu).hide();
});

All click events on any element will eventually bubble up to the root element (unless you cancel it), so this will handle every single click.

SLaks
`parents` is a method -- not a collection or jQuery object.
J-P
@J-P: You're right; I forgot the parentheses.
SLaks
A: 

As an alternative, have you considered jQuery.hover?

$('#menu > ul > li').hover(
    function() { $('ul', this).show(); }, 
    function() { $('ul', this).hide(); }
);

Appearing/disappearing on mouseover/mouseout is a more common practice. You could even make it more smooth using jQuery.slideDown() and jQuery.slideUp().

$('#menu > ul > li').hover(
    function() { $('ul', this).slideDown(250); }, 
    function() { $('ul', this).slideUp(100); }
);
BalusC
+1  A: 

Quickest and easiest way to do this:

jQuery(document).delegate(':not(#menu-id)', 'click', function(){
    $('#menu-id').hide();
});

Alternatively:

$(document).click(function(){
    if ( e.target !== menu && !$.contains(e.target, menu) ) {
        $(menu).hide();
    }
});
J-P