views:

49

answers:

3

hi,

I want to execute a function on an event on any element but one:

$(":not('#myelement')").bind('mousedown', function() {
    console.log('mousedown event');
});

but when I click #myelement, the function is executed anyway, because the selector select all the parents. Moreover, the function is executed for every parent. How can I: -execute the function only once? -not execute the function on my element?

Here's the full issue:

$("#current_page a").toggle(
    function(){
        $("#current_menu").hide();                    
        return false;
    },
    function(){
        $("#current_menu").show();
        return false;
    }
);

$(":not(#current_page a)").bind('mousedown',function() {               
    $("#current_menu").hide();
});

When clicking on "#current_page a", the mousedown event is triggered, and I don't want to.

thanks jul

A: 

Two options:

  1. You could have the handler check the event target, and quit if it's the bad one:

     $(':not(#foo)').mousedown(function(ev) {
       if ($(ev.target).is('#foo')) return false;
       // other stuff
     });
    
  2. You could add a handler especially for the bad element and make it kill the event:

    $(':not(#foo)').mousedown(...);
    $('#foo').mousedown(function() { return false; });
    
Pointy
The problem is that $(':not(#foo)') also selects the parent element of #foo. So when I mousedown on foo, I also mousedown on the parent, and the event is triggered.
jul
A: 

Remove your quotes in '#myelement'... Just :not(#myelement). You should be good.

Edit: Add a check in the event by checking the event.target to fix a potential bubbling problem:

function eventFunc(event) { 
    if ($(event.target).attr("id") !== 'myelement') {
        // do work
    }
}
Dmitriy Likhten
It still triggers the event for the parents.
jul
A: 

Here is a full example that should do what you require...

$(":not(#myelement)").bind('mousedown', function(event) {
    console.log('mousedown event');
    event.stopPropagation()
});

Important note (based on Jul's comment)

The event will be added to EVERY element on the page, except for the one element with an id of "myelement". I have put this quick demo together to demonstrate...

You'll notice that the onclick alert("hi") never gets called, no matter where you click - this demonstrates event propagation being prevented. You'll also notice that when you click on "myelement" that the event for the parent is called - because you haven't added the event handler to this element. I'll explain below how you can fix this. Here's the example.

<div oclick="alert('hi');" id="a">
    <div id="b">One</div>
    <div id="c">One</div>
    <div id="d">One</div>
    <div id="e">One</div>
    <div id="f">One</div>
    <div id="myelement">Not One</div>
    <div id="h">One</div>
    <div id="i">One</div>

</div>

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
    $(":not(#myelement)").bind('mousedown', function(event) {
        alert($(this).attr("id"));
        event.stopPropagation()
    });
</script>

And you will need to do the following to stop clicks on "myelement" from causing the parent element to trigger:

$(":not(#myelement)").bind('mousedown', function(event) {
    console.log('mousedown event');
    // event.stopPropagation() - you might not want this anymore - up to you...
    // I think you wanted clicks on "myelement" to be ignored, rather than 
    // event propagation to be prevented
});
$("#myelement").bind('mousedown', function(event) {
    event.stopPropagation()
});
Sohnee
It still triggers the event for the parent.
jul
@jul - See the note in my answer for more information on this.
Sohnee