7

When I use .bind to bind event on child and parent, child event can stop event propogation with return false; But when I use delegate, return false; does not stop event propagation.

http://jsfiddle.net/J3EAQ/

html:

<div class="parent">
    <div class="child"></div>
    <div class="child"></div>
</div>

js:

$('.parent').delegate('.child','click',function(e){
    alert('child click');
    return false;
});
$('.parent').bind('click',function(e){
    alert('parent click');
});
codez
  • 1,381
  • 1
  • 18
  • 28

6 Answers6

8

e.stopPropagation() won't work in this case. Use e.stopImmediatePropagation() instead. Here's a fiddle

aziz punjani
  • 25,586
  • 9
  • 47
  • 56
4

Why two click handlers when you can have one:

$( '.parent' ).click(function ( e ) {
    if ( $( e.target ).is( '.child' ) ) {
        alert( 'child click' );
    } else {
        alert( 'parent click' );
    }    
});

Live demo: http://jsfiddle.net/J3EAQ/2/


A generalization of this pattern:

$( element ).click(function ( e ) {
    if ( e.target === this ) {
        // this element was clicked directly
    } else {
        // this element was NOT clicked directly
        // a descendant of this element was clicked
    }    
});

Separate handlers?

$( '.parent' ).click(function ( e ) {
    if ( this ==== e.target ) {
        parentClicked.call( e.target, e );
    } else {
        childClicked.call( e.target, e );
    }    
});

function childClicked( e ) {
    // child click handler
}

function parentClicked( e ) {
    // parent click handler
}
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • technically it solves problem, but I like to separate functionality of different elements, so I need a solution with 2 event handlers. – codez Sep 16 '11 at 18:33
  • Then don't use `.delegate`, just use `.click` in both places. – Blazemonger Sep 16 '11 at 18:36
  • @mblase But that would mean that you have to bind one click handler for each child element - that's hardly the best solution... – Šime Vidas Sep 16 '11 at 18:39
  • @mblase75, I want to use delegate because I dynamically add child elements and I dont want to bind events every time I add elements. – codez Sep 16 '11 at 18:39
  • @Šime Vidas, child elements and their manager and parent container are different widgets and I want to fully separate their functionality, in your last solution container (parent) element functionality still has to know about child elements. – codez Sep 16 '11 at 18:42
  • @codez You can make a `this ==== e.target` check - so you just check if the parent was clicked directly... If that check returns false, you call `childClicked`, ergo, you transfer control to the child widget. – Šime Vidas Sep 16 '11 at 18:44
  • But that pattern can be improved.. you should use a switch where you check of an attribute you give to the element. This way you apply, an event of click using delegate to all elements of class " trigger-event" for example, and then for the elements that have "trigger-action='do_this' " and the switch should case based on the trigger-action match. – Miguel Aug 23 '17 at 16:18
1

You should be using e.stopPropagation() to prevent the propagation, not by returning false.

return false is technically two things; 1) prevent the default action, and 2) stop propagation. Try switching to the method invocation on e and see if that fixes your problem.

Tejs
  • 40,736
  • 10
  • 68
  • 86
  • @Interstellar_Coder - Correct, your solution is better. Never knew about `stopImmediatePropagation()`. THanks! – Tejs Sep 16 '11 at 18:51
0

What worked for me was to check the class name of the click target in the click handler that you don't want to get triggered by other click event. Something like this.

    if(e.target.className.toString().indexOf("product-row") > -1){ 
      // Only do stuff if the correct element was clicked 
    }
Jack Vial
  • 2,354
  • 1
  • 28
  • 30
0

You can always use e.stopPropagation()

Mike C
  • 3,077
  • 22
  • 29
-1

your event is not being propagated. you are binding a click handler to the .parent, and you are clicking on .parent

Einacio
  • 3,502
  • 1
  • 17
  • 21