Question

I have some DIVs, and other developer bind them a click event name fn_propagation.

And now I want to add a new function to them name fn_stoppropagation.

The problem is when I call e.stopPropagation() in fn_stoppropagation, it will stop event propagation in fn_propagation too.

How can I keep event propagation in fn_propagation but stop propagation in my added function? ( I know add event to each DIV by ID and stop use stopPropagation() can do this, but i don't think it's a good way. )

fiddle : http://jsfiddle.net/android/3GurB/2/

HTML:

<div id='div1'>
    <div id='div2'>
        <div id='div3'>
            Click Me
        </div>
    </div>
</div>

JS:

$('div').click(fn_propagation)      // Other developer add this event
        .click(fn_stoppropagation); // What I going to add.

// I want to keep propagation of this function 
function fn_propagation(){
    alert('propagation '+$(this).attr('id')+' called');
    $(this).toggleClass('green');
}

// But stop propagation of this function
function fn_stoppropagation(e){
    alert('stoppropagation '+$(this).attr('id')+' called');
    e.stopPropagation();
}

When Click Me is clicked, expect output:

   propagation div3 called     // called
   stoppropagation div3 called // called
   propagation div2 called     // expected, but NOT called, 
   propagation div1 called     // expected, but NOT called, 

Thank you.

Was it helpful?

Solution

Propagation happens in the DOM, it can only be on or off for the whole element, not for a specific event handler.

My suggestion: compare the current element with the click target:

function fn_stoppropagation(e){
  if (this===e.target) {
    // the following will only run for the target, not its ancestors
    alert('stoppropagation '+$(this).attr('id')+' called');
  }
}

OTHER TIPS

What you have is nested divs, each handling click. Since they are nested, the event bubbles up - starting with innermost div. So you cannot stopPropogation and expect it to propagate up the bubble. stopPropogation is meant exactly for that - stop bubbling up the event to other handlers.

Your approach is wrong, because event propagation is independent of event handlers, so you can't stop the event for some and don't stop for others.

You may think it makes sense to be able to stop it only for some, but that's because your case is a special one: the target and its ancestors have the same handler.

But in a more general case, a bubbling event triggers event handlers which can be different for each element, so stopping the event propagation only for some handlers has no meaning.

Then, the correct approach is modifying the event handlers instead of the event. For example:

var stopped = false;
function fn_stoppropagation(e){
    if(stopped !== (stopped=true)){
        /* Code here */
    }
}

Demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top