Checking the nodeName
of event.target
doesn't work if your links have descendent elements (e.g. <span>
or <img>
).
Instead, try walking up the tree from event.target
(the deepest element) to event.currentTarget
(the event the event handler was registered on) and checking whether any of those elements are clickable:
$("div").click(function(event) {
if (clickableBetweenTargetAndCurrentTarget(event))
return; // This click was probably already handled.
doSomething();
});
function clickableBetweenTargetAndCurrentTarget(event) {
for (var el = event.target; el && el != event.currentTarget; el = el.parentNode) {
if (isClickable(el))
return true;
}
return false;
}
function isClickable(el) {
// TODO: Customize this as appropriate for your webpage.
return el.nodeName == 'A' || el.nodeName == 'BUTTON';
}
Demo: http://jsbin.com/fojaco/2/
Note that you'll have to customize isClickable for your particular webpage; it's hard/impossible to tell whether an element is clickable in the general case.
An alternative approach would be to make sure that all clickable descendants call event.preventDefault()
, then your click listener on the div only needs to check event.defaultPrevented
(IE9+). Or the descendants could call event.stopPropagation()
, as suggested on another answer, but calling stopPropagation can lead to subtle bugs.