skip to Main Content

I am having issues with my click events due to nested elements and the nature of what I am trying to accomplish.

When I click on the .main, the selected class is added. However when I click on .close, the selected class is removed and then added back again. Is there anyway to get around this?

The reason why I have it setup this way is because I want to maximize my clickable area (the entire element).

$('.main').off('click.a').on('click.a', function() {
  $('.child2', $(this)).addClass('selected');
});

$('.close').off('click.B').on('click.B', function() {
  $(this).parent().removeClass('selected')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div class="main">
  <div>some content</div>
  <div class="child2">
    <span class="close">X</span>
  </div>
</div>

2

Answers


  1. The issue is because the .close element is a child of the .main. This means that the event fires on .close, and the class is removed. The event then propagates up the DOM to the .main element where it’s caught by the other event handler and the class gets added on again.

    To prevent the event from propagating up the DOM, call stopPropagation() on it from within the .close click handler:

    $('.main').off('click.a').on('click.a', function() {
      $(this).find('.child2').addClass('selected');
    });
    
    $('.close').off('click.B').on('click.B', function(e) {
      e.stopPropagation();
      $(this).parent().removeClass('selected')
    });
    .selected { color: #C00; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <div class="main">
      <div>some content</div>
      <div class="child2">
        <span class="close">X</span>
      </div>
    </div>

    As a side note, using .off('event').on('event', fn) is a code smell. You may be better off using a single delegated event handler which you can bind only once when the page loads. It would depend on your exact use case, though.

    Login or Signup to reply.
  2. You could double check it’s actually the correct item.

    $('.main').off('click.a').on('click.a', function(e) {
      if (!$(e.target).hasClass('.main')){ return };
      $('.child2', $(this)).addClass('selected');
    });
    $('.close').off('click.B').on('click.B', function(e) {
      if (!$(e.target).hasClass('.close')){ return };
      $(this).parent().removeClass('selected')
    });
    

    I’ve had similar issues when I wanted an event to go off when I click the whitespace in Table Cells but not the contents itself.. if that makes any sense

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search