user2828701
user2828701

Reputation: 305

Show/HIde Elements on click of parent/child

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>

Upvotes: 1

Views: 212

Answers (2)

Nealium
Nealium

Reputation: 2268

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

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337560

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.

Upvotes: 1

Related Questions