jQuery selector to target clicks on an element by class and its children as long as it does not also have a specific class

Viewed 19

I want to target clicks on elements that have a specific class or a children of an element with that specific class, but I also want to exclude clicks on elements with another class even if they are inside an element with the first class.

Here's my test case:

<div class="xxx-exclude">
  <button type="button">
  Excluded
  </button>
  <button type="button" class="xxx-include">
  Included
  </button>
</div>
<button type="button">
Included
</button>
<button type="button" class="xxx-exclude">
Excluded
</button>

When "Excluded" buttons are clicked they should alert "Excluded", but when "Included" buttons are clicked they should do nothing.

This code works for include classes inside of an exclude class, but does not work if the element clicked has the exclude class:

$(".xxx-exclude *:not(.xxx-include)").click(function (e) {
    alert("excluded");
    return false;
});

I thought this should work but the include class inside of the exclude class now incorrectly reports "Excluded":

$(".xxx-exclude:not(.xxx-include),.xxx-exclude *:not(.xxx-include)").click(function (e) {
    alert("excluded");
    return false;
});

I feel like I'm missing something really simple here...

jsFiddle

1 Answers

I don't think this can be done in a reasonable manner with a single selector. Have the listener added to .xxx-exclude check if there's a .closest (an ancestor, or the clicked element) that matches .xxx-include - and only alert/log if there is no such element:

$(".xxx-exclude").click(function(e) {
  if (!e.target.closest('.xxx-include')) {
    console.log("excluded");
    return false;
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="xxx-exclude">
  <button type="button">
  Excluded
  </button>
  <button type="button" class="xxx-include">
  Included
  </button>
</div>
<div>
  <button type="button">
  Included
  </button>
</div>
<button type="button" class="xxx-exclude">
Excluded
</button>

Related