jQuery children elements are not cooperate

Viewed 39

How it should work:

  • Open (toggle .show class) on div.user, and displays the .userSub div.
  • If I click on another div.user, close (remove .show class) and opens the clicked div.userSub
  • If I click on the already .show-ed div.user (NOT .userSub), it'd close the target div.user.

Almost works but the problem:

  • when .userSub div is .show-ed, I can only click to close on the .userSub div, not the .user div. However that would be goal. :)

I've tried to eliminate the problem. Probably the .user selection is wrong and I should use stopPropagation() somewhere, or I should be more specific with the child elements, but I can't figure it out.

let $active
$(document).ready(() => {
  $(".user").click(function(e) {
    if ($active != null) {
      $active.toggleClass("show")
    }
    $(e.target).children().toggleClass("show")
    $active = $(e.target).children()
  })
})
.user {
  background-color: gray;
  padding: 20px;
  margin: 5px;
}

.userSub {
  display: none;
  padding: 20px;
  background-color: lightgray;
  color: black;
  margin: 5px;
}

.show {
  display: block;
}

button {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="user">
  name 1
  <div class="userSub">details 1<button>more 1</button></div>
</div>
<div class="user">
  name 2
  <div class="userSub">details 2<button>more 2</button></div>
</div>
<div class="user">
  name 3
  <div class="userSub">details 3<button>more 3</button></div>
</div>

1 Answers

To achieve your goal check that the clicked element was the .user element directly, not a child of it. To do that you can use the target property of the event.

Also note that you can simplify the logic by only applying the .show class to the parent .user and having the CSS rules apply the display: block rule to the child elements based on the class on a parent. Try this:

$(document).ready(() => {
  let $users = $(".user").click(function(e) {
    if (e.target !== this)
      return;
  
    $users.not(this).removeClass('show');
    $(this).toggleClass("show")
  })
})
.user {
  background-color: gray;
  padding: 20px;
  margin: 5px;
}

.userSub {
  display: none;
  padding: 20px;
  background-color: lightgray;
  color: black;
  margin: 5px;
}

.user.show .userSub {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="user">
  name 1
  <div class="userSub">details 1<button>more 1</button></div>
</div>
<div class="user">
  name 2
  <div class="userSub">details 2<button>more 2</button></div>
</div>
<div class="user">
  name 3
  <div class="userSub">details 3<button>more 3</button></div>
</div>

Related