I have a click event on li
tag and then in that li
i have another nested li.
When clicked on parent li
everything works fine. But onclick nested or child li
the parent li
click event is fired.
I have used event.stopPropagation()
method but it does not work in my case.
$("li").on("click",function() {
console.log(this.firstChild.textContent)
})
$('#testUl > li').on('click', function(e) {
e.stopPropagation();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
$('#testUl .innerUl li').on('click', function(e) {
e.stopPropagation();
});
// or
$('#testUl li').on('click', function(e) {
e.stopPropagation();
});
$('#testUl > li').on('click', function(e) {
alert('test');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- #testUl -->
<ul id="testUl">
<!-- #testUl > li -->
<li>
<!-- #testUl > li > a or #testUl a -->
<a href="#">Test A</a>
<!-- #testUl > li > .innerUl or #testUl .innerUl -->
<div class="innerUl">
<!-- #testUl > li > .innerUl > ul or #testUl ul -->
<ul>
<!-- #testUl > li > .innerUl > ul > li or #testUl li or #testUl .innerUl li or .innerUl li -->
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
You are using a wrong selector for stop propagation
When you use #testUl > li
you call the first li
child element, but you have li
elements inside your li
on #testUl
, so call #testUl li
or #testUl .innerUl li
CodePudding user response:
Without jQuery you can use event delegation and determine to act using Element.closest()
document.addEventListener(`click`, handle);
function handle(evt) {
console.clear();
if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
console.log(`You clicked (something within) the first li of ul#testUl`);
}
}
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Same idea with jQuery
$("#testUl").on("click", evt => {
console.clear();
if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
console.log(`You clicked ${evt.target.outerHTML}`);
}
});
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js">
</script>
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can compare e.target
which is element that have click
event and e.currentTarget
that is element you actually clicked. If they don't match then you return without performing rest of function
$('#testUl > li').on('click', (e) => {
if (e.target !== e.currentTarget) {
return;
}
console.log('parent');
});
$('.innerUl li').on('click', (e) => {
if (e.target !== e.currentTarget) {
return;
}
console.log('child');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="testUl">
<li>
Test A
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can try with stopImmediatePropagation()
See here: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation