Reputation: 566
Expected behavior: When I click on the .parent
class, an item detail modal will be shown but the modal won't be shown if I click on the .dropdown
or any of it's option.
<div class="parent click-for-item-detail">
<div class="dropdown">
<a href="#" class="dropdown-toggle " data-toggle="dropdown">Options</a>
<ul class="dropdown-menu">
<li><a href="#">option-1</a></li>
<li><a href="#">option-2</a></li>
</ul>
</div>
<div class="item-image"><img class="click-for-item-detail" src="image.jpg></div>
<div class="info">
<a href="#" class="click-for-item-detail">Item title</a>
<div class="click-for-item-detail"> item subtitle</div>
</div>
</div>
So far:
$(".click-for-item-detail").on("click",function(e){
// show the modal if the target itself has been clicked
if(e.target === this) {
$('#itemDetailModal').modal('toggle');
}
});
I have added click-for-item-detail
class in every element that should trigger the item detail modal. Is there a better way to achieve this?
Upvotes: 2
Views: 1031
Reputation: 20450
It is true what Phong is saying and that works. However, imagine now you had many child elements in your parent all matching that selector. With something like below, you would add an event listener to each of those elements.
$(".info, .item-image").on("click", function(){
console.log("Trigger");
});
While with your first approach you were already very close to only have one listener, no matter how many child elements are in the parent.
Consider following example:
<ul class='parent'>
<li>No</li>
<li>Click</li>
<li>Event</li>
</ul>
$(".parent").on("click",function(e) {
if(!e.target.classList.contains('parent')) {
return console.log('no event')
}
console.log('fire event')
});
This is called event delegation, and you pretty much do this already. Here I am checking if the element, I am clicking on, is indeed of class parent, only then I fire my event.
You can of course do all sorts of checks, for example only the <li>
elements.
$(".parent").on("click", (e) => e.target.tagName == 'LI' && console.log('fire event'))
Here check out this example https://codepen.io/bluebrown/pen/xxGVgYd?editors=1111
I would recommend doing a web search for event delegation and event bubbling.
Upvotes: 2
Reputation: 68933
You can use :not()
selector to filter out the element you do not to be clicked:
$('.parent > :not(.dropdown)').click(function(e){
alert('modal');
//show modal
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div class="dropdown">
<a href="#" class="dropdown-toggle " data-toggle="dropdown">Options</a>
<ul class="dropdown-menu">
<li><a href="#">option-1</a></li>
<li><a href="#">option-2</a></li>
</ul>
</div>
<div class="item-image"><img src="image.jpg"></div>
<div class="info">
<a href="#">Item title</a>
<div> item subtitle</div>
</div>
</div>
Upvotes: 1
Reputation: 14198
You can specify some selectors to be able to trigger.
Read the following post to have a better understanding.
Event listener for multiple elements - jQuery
$(".info, .item-image").on("click", function(){
console.log("Trigger");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent click-for-item-detail">
<div class="dropdown">
<a href="#" class="dropdown-toggle " data-toggle="dropdown">Options</a>
<ul class="dropdown-menu">
<li><a href="#" class="dropdown-menu-item">option-1</a></li>
<li><a href="#" class="dropdown-menu-item">option-2</a></li>
</ul>
</div>
<div class="item-image"><img class="click-for-item-detail" src="image.jpg"></div>
<div class="info">
<a href="#" class="click-for-item-detail">Item title</a>
<div class="click-for-item-detail"> item subtitle</div>
</div>
</div>
Upvotes: 2