TarranJones
TarranJones

Reputation: 4242

jQuery find .Selector but not nested selector (.selector .selector)

I would like to find all elements which match a selector but not if it is already contained in a matching element.

$('#container').find('.child').not('.child .child');

note that the .child elements are not necessary direct descendants.

why doesn't this work ?

I would like to select all element which would appear in $('#container').find('.child') but exclude/filter() any which would be in here $('#container').find('.child .child') because one of its ancestors is a .child

var children = $('#container').find('.child').filter(function (i, el) {
    return !$(el).closest('.child').length;
});

for some reason this doesn't work either JSFIDDLE

snippet adapted from @RonenCypis answer

var selector = ' .child ';
var children = $('#container').find(selector).filter(function(i, el) {
  return !$(el).closest(selector).length;
});
children.css('background-color', 'blue');
#container div {
  float: left;
  display: inline-block;
  width: 50px;
  height: 50px;
  color: #fff;
  margin: 10px;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div class="child">one
    <div class="child">one one</div>
  </div>
  <div class="child">two
    <div class="child">two one</div>
  </div>
  <div class="child">three</div>
  <div class="child">four
    <div class="child">four one</div>
  </div>
</div>

Upvotes: 4

Views: 816

Answers (3)

Heretic Monkey
Heretic Monkey

Reputation: 12113

You can use parents instead of closest to find ancestors of the current element. closest matches the current element in addition to ancestors.

var selector = ' .child ';
var children = $('#container').find(selector).filter(function(i, el) {
  return !$(el).parents(selector).length;
});
children.css('background-color', 'blue');
#container div {
  float: left;
  display: inline-block;
  width: 50px;
  height: 50px;
  color: #fff;
  margin: 10px;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div class="child">one
    <div class="child">one one</div>
  </div>
  <div class="child">two
    <div class="child">two one</div>
  </div>
  <div class="child">three</div>
  <div class="child">four
    <div class="child">four one</div>
  </div>
</div>

Upvotes: 1

Ronen Cypis
Ronen Cypis

Reputation: 21470

Demo in the JsFiddle

You can use filter() for that:

HTML

<div id="container">
    <div class="child">
        <div class="child"></div>
    </div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child">
        <div class="child"></div>
    </div>
</div>

CSS

#container div {
    display: inline-block;
    width: 50px;
    height: 50px;
    margin: 10px;
    background-color: red;
}

Javascript

var selector = '.child';
var children = $('#container').find(selector).filter(function(i, el){
    return $(el).find(selector).length == 0;
});

children.css('background-color', 'blue');

This code will change the background color only for .child elements that doesn't have additional .child elements inside them.

Upvotes: -1

Satpal
Satpal

Reputation: 133403

You can use :has() Selector in conjunction with :not() selector

$('div').find('[role="tabpanel"]:not(:has([role="tabpanel"]))');

Upvotes: 1

Related Questions