why the e.stopPropagation() function does not work?
It does work. Observe:
$(document).on("click", ".outer", function(e) {
alert(3);
});
$(document).on("click", ".el", function(e) {
e.stopPropagation();
alert(2);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="outer">
<div class="el" onclick="alert(1)";>Click</div>
</div>
In your code the event propagation is indeed being stopped. However, there are no further event handlers up the DOM tree so there's no propagation to observe in the first place. What you have are two separate click
handling events on the same element, both of which are being processed independently.
In the example shown here, a parent element (div.outer
) does have an event handler, and the propagation stops before it reaches that handler. Without stopping propagation, you'd see that event handler invoked:
$(document).on("click", ".outer", function(e) {
alert(3);
});
$(document).on("click", ".el", function(e) {
alert(2);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="outer">
<div class="el" onclick="alert(1)";>Click</div>
</div>
You might be looking for stopImmediatePropagation()
instead? This will prevent further event handlers from being invoked on the same element. For example:
$(document).on("click", ".el", function(e) {
e.stopImmediatePropagation();
alert(2);
});
$(document).on("click", ".el", function(e) {
e.stopImmediatePropagation();
alert(3);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="el" onclick="alert(1)";>Click</div>
In this case The second click
handler on the target element stopped further click
handlers on that same element from being processed. Note that this has no effect on the first click
handler, which was already invoked by then.
Edit: Your updated code demonstrates a slightly different problem. (Which was being obscured in the original code by the original problem addressed above.)
Notice how you are attaching your jQuery event handler. Which DOM object are you attaching it to?... document
. Which is much further up the DOM hierarchy and isn't reached until after the parent element has already processed its inline click
handler.
If you attach a click
handler directly to the element, you can see the difference:
$(".stop").on("click", function(e) {
e.stopPropagation();
alert(2);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="el" onclick="alert(1)">
<div class="stop">X</div>
Click
</div>
Another edit for the ongoing moving target...
You're still essentially running into the same issue. One click handler is on the element itself, another is on the document
object. The latter won't be processed before the former.
Appending the elements to the DOM after the fact may indeed complicate things a little in this case, and you may need to attach the click handler to the element(s) themselves after appending them. For example, this stops the propagation:
$(document).ready(function() {
var el = '<div class="el" onclick="alert(1);"><div class="stop">X</div>Click</div>';
$("body").append(el);
$(".stop").on("click", function(e) {
e.stopPropagation();
alert(2);
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
</body>
The key difference here is that the jQuery click
handler isn't being attached to the document
or relying on event delegation/propagation in the first place. It's being attached directly to the target element, and as such needed to be attached after the element is added to the DOM.