tags:

views:

60

answers:

3

I have the following div:

<div class='amazingmenu' id='menupull'>
    <img src='images/down.png' width=20 height=20 align='right'/>
    <div id='menupullhideme'>click the arrow to read the rest!<br /></div>
    more jokes on <a href='http://www.amazingjokes.com'&gt;amazingjokes.com&lt;/a&gt;
</div>

clicking the DIV or the image should execture some function in jQuery:

$('#menupull').click( function() {
          alert( 'pullmenu clicked' );
});

I want to make it so that it only alerts the message when I click the DIV or the image, but not the link. Tried this:

     $('#menupull:not(a)').click( function() {...

but that didn't work. Any ideas?

A: 

The problem is probably event bubbling.. what you could do, is inside your "click" event check if the nodeName/tagName is A or not, if it is, abort the rest of your function and let the anchor just do it's thing.

My jQuery is a little rusty as I don't use it much myself, but I think something like this..

$('#menupull').click( function(e) {
    var target  = $(e.target);
    if( target.is('a') ) {
        return true; // True, because we don't want to cancel the 'a' click.
    }
});
CharlesLeaf
With your code as is, it's very important to state that the `alert` should be included only **after** the `if` statement.......... Also, there is really no need to `return true`, simply put the `alert` inside an `if( ! target.is('a') ) { ... }` and the native functionality of the anchor is not interfered with.
Peter Ajtai
That's true, as for putting the alert inside if, in my opinion it depends on how much code you put in there.. I prefer to avoid nesting too deep to keep my code clean.
CharlesLeaf
+3  A: 

This is happening because the event bubbles to the div when you click on the link, so what you want to do is stop it from bubbling when you click on the link, by using the event.stopPropagation() method. As you can see, you pass the event object as an argument to the function. You want to still catch the event on the <a> and then stop it from propagating, like this:

$('#menupull').click( function() {
    alert( 'pullmenu clicked' );
});
$('#menupull a').click( function(e) {
    e.stopPropagation();
});

Edit:

Another way you could fix this is by using a different selector, which attaches an event listener to all child nodes of the element, except for <a> elements, however this will not work when you click on an area of the element with no child nodes.

$('#menupull>*:not(a)').click( function(event) {
        alert( 'pullmenu clicked' );
});

http://jsfiddle.net/zCsLm/3/

Andrew Dunn
Your method does work, but the cause of the OP's problem is an incorrect selector, and not event propagation. It's actually happening, since ` $('#menupull:not(a)')` is equivalent to ` $('#menupull')` because `#menupull` is a `div` and not an `a`.
Peter Ajtai
While his selector is incorrect, the bubbling of events is the reason for the unexpected behavior. But yes, it could also be fixed using a better selector.
Andrew Dunn
A: 

Your problem is that $('#menupull:not(a)') selects the element with the id of menupull that is not an A element.... well, clearly #menupull is a div., so the previous doesn't really accomplish much. Instead check what the target of the click is.

The simplest way is to simply only do the alert in the cases where not an A was clicked. If an A is clicked everything proceeds as normal (link is followed, etc). You can achieve this by using event.target.nodeName:

$(function() {

    $('#menupull').click( function(event) {

        if (event.target.nodeName != 'A') {
            alert( 'pullmenu clicked' ); }
    });
});​

jsFiddle example

Peter Ajtai