Delegation & bubbling

by LeGEC

HTML

<div><span id="target">Handler is bound to <code>document</code>.<br/>Click events will bubble through <code>div.clickCount</code> (even though the handler calls <code>e.stopPropagation()</code>).</span>
    <br/>
    <br/>Click one of the buttons to change the target :
    <br/>
    <button id="doc">document</button>
    <button id="parent">parent</button>
</div>
<div class="clickCount">
    <div class="parent">
        <div class="child">button</div>
        <div class="child">button</div>
    </div>
    <div class="parent">
        <div class="child">button</div>
    </div>
</div>
<div id="log"> <span id="clickCount">0</span> clicks have been registered by <code>div.clickCount</code> (red border).</div>

CSS

.clickCount {
    border:1px solid red;
    margin: 6px
}
.parent {
    border: 1px solid black;
    margin: 3px
}
.child {
    width : 150px;
    background: green;
    margin: 6px;
    text-align: center
}

JavaScript

// the click handler function :
// it calls e.stopPropagation()
// depending on the node it is bound to, the event will bubble through different layers
function handler(e) {
    var $p = $('<p>Clicked</p>').appendTo('#log').delay(1000).fadeOut();
    e.stopPropagation();
};

// clickCount :
// the ".clickCount" div increments a counter each time it sees a click event
var clickCount = 0;
$('.clickCount').click(function () {
    clickCount++;
    $('#clickCount').html(clickCount);
});


// #doc and #parent buttons :
// change the target of the ".on('click', '.child', handler)" binding
$('#doc').click(function () {
    $('.parent').off('click', '.child');
    $(document).off('click', '.child');
    $('#target').html('Handler is bound to <code>document</code>.<br/> Click events will bubble through <code>div.clickCount</code> (even though the handler calls <code>e.stopPropagation()</code>).');

    $(document).on('click', '.child', handler);
});
$('#parent').click(function () {
    $('.parent').off('click', '.child');
    $(document).off('click', '.child');
    $('#target').html('Handler is bound to <code>.parent</code> nodes (black border).<br/>Click events won\'t bubble through <code>div.clickCount</code> (the handler calls <code>e.stopPropagation()</code> before the event reaches <code>div.clickCount</code>).');

    $('.parent').on('click', '.child', handler);
});

//initially: bound to document
$(document).on('click', '.child', handler);