How To Detect Which Element Was Clicked, Using jQuery

Sometimes we would like to find out which particular element (or set of elements) has user clicked on. However, binding click events on each element manually might not be the most practical way of accomplishing this. Or we might want to fire a certain event if user clicks on anything but particular element(s). I will describe one of such scenarios below and offer one of possible solutions to it using jQuery.

Example

In our example we have a menu toggle button which shows/hides menu item list. We want the item list to stay open until user clicks on the menu toggle button or somewhere outside the item list.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Menu Toggle</title>
  <style>
    .item-list { display: none; }
    .show-list { display: block; }
  </style>
</head>
<body>
  <div class="main">
    <header>
      <div class="toggle"></div>
      <ul class="item-list">
        <li id="item-1"></li>
        <li id="item-2"></li>
        <li id="item-3"></li>
        <li id="item-4"></li>
      </ul>
    </header>
  </div>
</body>
</html>

Implementing Toggle Button

We have a basic layout with menu list being hidden by default. We have a CSS class .show-list which we can apply to the item list to override display: none; and show the list to the user. Now we need to bind the functionality to .toggle button to add/remove .show-list class to menu list. We can easily do this using jQuery:

// $('.toggle').on('click', function() {}); 
// is equivalent of $('.toggle').click(function() {});
$('.toggle').on('click', function() {
  $('.item-list').toggleClass('show-list');
});

Detecting Out-of-Bounds Clicks

Great, we have toggle button functionality! All we need to do now is figure out a way to detect clicks outside of the menu list and hide the list when out of bounds click is detected. Again, jQuery makes this task an easy one.

// Bind click event listener on the body
// Hide main menu if user clicks anywhere off of the menu itself.
$('body').on('click.hideMenu', function(e) {
  // Check to see if the list is currently displayed.
  if ($('.item-list').hasClass('show-list')) {
    // If element clicked on is NOT one of the menu list items,
    // hide the menu list.
    if (!$(e.target).parent().hasClass('item-list')) {
      $('.item-list').removeClass('show-list');
    }
  }
});

Code Breakdown

$('body').on('click.hideMenu', callbackFunction);

does the same thing as

$('body').on('click', callbackFunction);

jQuery allows us to namespace event handlers. This way if someone unbinds 'click' event on the body, it will not break our hideMenu handler. If we want to remove this we have to unbind 'click.hideMenu' handler directly.

$(e.target)- Contains DOM element user clicked on.

We can use this object to get anything and everything regarding object user has clicked on. In the code above, I'm checking for parent class of the clicked element. If the parent class is .item-list, then user clicked on one of the menu items.

NOTE: e.target is always going to be the top element clicked. In our scenario, child element is always going to be on top of the parent element. So while every click on the screen is technically click on the body, e.target will always return the furthest child element in the tree that occupies clicked area. However, we might have multiple absolutely positioned elements occupying the same area. In this case, the element with higher z-index will be returned.

Comments

Thank you

Yeah, thanks for the tips, I was looking for something similar.

Very useful!

nice and clean. Thank You!

Add new comment