Search code examples
javascriptjquerydelegation

How to stopPropagation when there are multiple event delegations


I have a table row in which there is an element with an event handler delegated to document element, and the row itself also has another handler delegated to the tbody element. Codes like below:

// first part is defined in an initiating script file, so no jQuery used.
document.addEventListener('click', function(e) {
    var el = e.srcElement || e.target;

    if (el && el.classList && el.classList.contains('gotocontact')) {
        e.stopPropagation();
        alert('going to contact...')
    }
})
// second part is defined after the jQuery included...
$('#list').on('click', 'tr', function() {alert('click tr...')})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table class="table">
    <tbody id="list">
        <tr>
            <td><a class="gotocontact">John Doe</a></td>
            <td>Male</td>
        </tr>
        <tr>
            <td><a class="gotocontact">Jane Doe</a></td>
            <td>Female</td>
        </tr>
    </tbody>
</table>

I put the stopPropagation there but it doesn't work as I expected: when I click the a element, the tr handler should not be triggered. Anyone can provide some hints?


Solution

  • If you want to prevent the jQuery listener from triggering, you should call stopPropagation in the capturing phase rather than in the bubbling phase, by passing a third true argument to addEventListener:

    document.addEventListener('click', function(e) {
        var el = e.srcElement || e.target;
    
        if (el && el.classList && el.classList.contains('gotocontact')) {
            e.stopPropagation();
            alert('going to contact...')
        }
    }, true)
    // ^^^^ add third parameter
    
    $('#list').on('click', 'tr', function() {alert('click tr...')})
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
    <table class="table">
        <tbody id="list">
            <tr>
                <td><a class="gotocontact">John Doe</a></td>
                <td>Male</td>
            </tr>
            <tr>
                <td><a class="gotocontact">Jane Doe</a></td>
                <td>Female</td>
            </tr>
        </tbody>
    </table>