How to prevent delegated handlers on a parent without preventing default in jQuery?
Is there any way to prevent a click from an <a>
triggering delegated click handlers on its parent, while allowing the the <a>
's default behavior to occur (navigating to the href
).
Here's an example that illustrates what I'm asking.
<div class="top">
<div class="middle">
<a href="google.com" class="link">link</a>
</div>
</div>
And my JavaScript:
$(".top").delegate(".middle", "click", function(event) {
alert("failure");
});
$(".top").delegate(".link",开发者_JAVA技巧 "click", function(event) {
// ???
});
In this case, I want to be navigated to google.com when I click the link, but must NOT see the alert("failure")
on my way out.
There are a few restrictions to the solution:
- All event handlers must be delegated off of
$(".top")
, as I potentially have thousands of these in the page. - The navigation must be accomplished using browser default behavior, rather than
window.location = $(this).attr("href")
or similar
Using normal event binding, I could do an e.stopPropagation()
in a click handler for the <a>
, but that won't work due to the nature of delegation. jQuery provides another method called .stopImmediatePropagation()
that describes what I want (preventing other handlers on current element, in this case the element that holds the delegated handlers), but does not actually accomplish it in this case. That might be a bug in .delegate()
, I'm not sure.
Returning false
from the <a>
's click handler will prevent the other handler from running, but will also do a .preventDefault()
, so the browser will not navigate. Basically, I'm wondering what return false;
does that e.stopImmediatePropagation(); e.preventDefault();
does not. Based on the docs, they should be equivalent.
For a live demo of the above code, here's a JSFiddle: https://jsfiddle.net/CHn8x/
event.stopImmediatePropagation()
is indeed what you're after, but remember that order matters here since .delegate()
listens at the same level, so you need to reverse your bindings, like this:
$(".top").delegate(".link", "click", function(event) {
event.stopImmediatePropagation();
});
$(".top").delegate(".middle", "click", function(event) {
if(!event.isPropagationStopped())
alert("failure");
});
Here's a working version of your demo with this change
The order you bound the handlers is the order they will execute, so you need that .link
handler to execute and stop the propagation before the other handler runs, checking it with event.isPropagationStopped()
or event.isImmediatePropagationStopped()
.
This normally isn't an issue at different levels, but since .delegate()
is listening on the same element, it does matter.
精彩评论