Search code examples
javascriptjquerystoppropagationjquery-click-event

stopPropagation not working in this instance


Okay so a simple thing that I don't know how to search for, wasn't able to get an answer anywhere...

Basically, I'm using XML to populate a list. What happens is when clicking on the first tier li, it adds all the different suburbs to the child ul. This generates then the structure below:

<li class="province-active" style="background-image: url(&quot;img/minus-icon-storefinder.png&quot;);">
  <p>Gauteng</p>
  <ul class="province-sub-menu">
    <li class="province-sub-nav-item" data-suburb="Strijdom Park">Strijdom Park,Randburg</li>
    <li class="province-sub-nav-item" data-suburb="Edenvale">Edenvale,Eastrand</li>
    <li class="province-sub-nav-item" data-suburb="Strubens Valley">Strubens Valley,Roodepoort</li>
    <li class="province-sub-nav-item" data-suburb="Centurion">Centurion,Pretoria</li>
  </ul>
</li>

Okay the problem is, using the JQuery below, it first triggers the click event for "province-sub-nav-item" and then triggers the click event for "province-active" (the parent li). This is the JS I'm using for the children li.

$(document).on("click", ".province-sub-nav-item", function(e){
    e.stopPropagation();
    $shop = $(this).attr("data-suburb");
    loadShop($shop);
});

And this is the function for the parent li.

$(".province-active").click(function(e) {
    $li = $(this);
    $province = $li.children("p").text();
    $(".store-locations").css("width", 375);    
    getMap($li, $province, 15); 
});

So basically, I just need to not fire the click event for "province-active" without firing the click event for "province-active" and stopPropagation(); isn't working.

Thanks guys.


Solution

  • It is because you have used used event delegation and bounded the handler to teh document object.

    So when event bubbles up the province-active elements handler will be triggered before the document objects handler is triggered so your stop propagation does not have any effect.

    Demo: Fiddle - see the order of logging in the console

    One possible solution is to use event delegation for the province-active element also

    $(document).on("click", ".province-active", function (e) {
        var $li = $(this);
        var $province = $li.children("p").text();
        $(".store-locations").css("width", 375);    
        getMap($li, $province, 15);
    });
    

    Demo: Fiddle - see the order of logging in the console

    Alternatively this works too:

    $(".province-sub-menu").on("click", ".province-sub-nav-item", function(e){
        e.stopPropagation();
        $shop = $(this).attr("data-suburb");
        loadShop($shop);
    });