Question

I hope someone can help me understand why the scenario below fails. I have a parent ul tag with an event handler that conditions for a given descendent li element in another ul tag nested within it. The markup is:

<ul id="outerUL">
    <li>LIST ITEM 1</li>
    <li>LIST ITEM 2</li>
    <li>
        <ul id="innerUL">
            <li>LIST ITEM 3</li>
            <li>LIST ITEM 4</li>
            <li>
                <ul id="inMostUL">
                    <li>LIST ITEM 5</li>
                    <li>LIST ITEM 6</li><!-- we condition for this element -->
                    <li>LIST ITEM 7</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

The javascript is: (it seems a conditional .stopPropagation() in an ancestor call fails...)

var outerMostUL = document.getElementById("outerUL");
outerMostUL.addEventListener('click', 
    function(e){

        if(e.target.innerHTML === "LIST ITEM 6"){
           e.stopPropagation();
           alert("you clicked LIST ITEM 6. Event travel stops.");
           // return; // a return WILL work
        }

     // below runs if propagation continues...
     alert("outerMostUL event handler fired!");

    },
    false);

Now if i decide to put in a discreet .addEventListener() call on that li tag, .stopPropagation() works as expected, eg:

// A discreet event handler does work
var inMostUL = document.getElementById("inMostUL");
inMostUL.children[1].addEventListener('click', function(e){

    e.stopPropagation();
    alert("The descendent event fires, but stops now.");

});

So my question is: SHOULD you be able to use a condition in an ancestor's handler for a given e.target and stop propagation of its event, if bubbling is enabled? It seems that an element must have its own handler bound to originate an event, but perhaps I confuse a propagating event traveling the ancestor chain with actually adding an event listener via that method. Any light shedding will be greatly appreciated. I'm am just trying to conceptualize js event handling through simple examples. Thanks for any consideration of this.

Was it helpful?

Solution

The event bubbling propagation can be stopped with e.stopPropagation() at any point along the ancestor chain and that will stop the event from propagating any further up to other ancestors.

And, there's no issue with stopping propagation conditionally only under certain circumstances.


I think some of your confusion just has to do with your javascript function, not with propagation. In this code:

var outerMostUL = document.getElementById("outerUL");
outerMostUL.addEventListener('click', function(e){
   if(e.target.innerHTML === "LIST ITEM 6"){
       e.stopPropagation();
       alert("you clicked LIST ITEM 6. Event travel stops.");
   }
   // below runs ALWAYS, regardless of the result of the previous "if" statement
   alert("outerMostUL event handler fired!");
}, false);

The second alert happens without the return statement NOT because of propagation, but just because your javascript function continues to execute after the conditional if block. This has nothing to do with propagation, but just with javascript program flow. If you add the return statement, you are ending your event handler callback early so the rest of it is not executed. Without the return statement, execution in that function continues after the if block whether the if statement is satisfied or not.


In conceptually understanding event propagation, just think of a piece of code in the browser that initiates an event that bubbles. That event is first sent to the event handler of the target object and if propagation isn't canceled there, it is then sent to the next ancestor and if propagation isn't canceled there, it is then sent on up the ancestor chain until it gets to the document object or until propagation is canceled.


Also, keep in mind that if you aren't using a cross-platform library like jQuery and you want to support older versions of IE that the stopping of propagation works differently in those older versions of IE.

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