Here's a demo
The problem is the event has to climb to the parent to find a handler for <img>. So it has to pass through <td> and fires its handler immediately since it's not a delegated handler.
*click* ,-----------------> (1) fire direct td handler
img -> td -> tr -> table
'----> (2) fire delegated img handler
X<---- (3) e.stopPropagation() //too late!
One way to prevent the double event is also add <td>'s handler to the table as well. jQuery will then evaluate the two handlers, start with the deepest event and if any of those handlers has e.stopPropagation(), events higher up will not fire.
$('table#test').on('click', 'img.live', function(e){
e.stopPropagation();
alert('Image clicked!');
});
$('table#test').on('click','td.row', function(e){
alert('Row clicked!');
});
*click*
img -> td -> tr -> table
'----> (1) fire delegated img handler
X<---- (2) e.stopPropagation()
'----> (3) fire delegated td handler //never gets fired