Core · jQuery-compatible

DOM traversal

Move around the tree from wherever you are: up with .closest(), down with .find(), sideways with .siblings(), and narrow down with .filter() and .not().

Traversal methods return new, de-duplicated collections, so you can chain them freely. .filter(), .not() and .is() accept a selector, an element, a collection, or a predicate function (index, element) => boolean.

.closest() is the workhorse of event handling: from the element that was clicked, climb to the card, row or form that owns it. It is built on the native Element.closest().

Live · Traversal playground

The outlined node is the starting point. Each button highlights what the method returns.

  • root
    • branch A
      • leaf A1
      • leaf A2 (start)
      • leaf A3 (.special)
    • branch B
      • leaf B1
      • leaf B2 (.special)
View the source for this demo
HTML
<p class="muted" style="margin:0 0 10px;font-size:14.5px">The outlined node is the starting point. Each button highlights what the method returns.</p>
<ul class="tree" id="tree" aria-label="Example tree">
  <li>root
    <ul>
      <li class="branch">branch A
        <ul><li class="leaf">leaf A1</li><li class="leaf anchor" id="anchor-node">leaf A2 (start)</li><li class="leaf special">leaf A3 (.special)</li></ul>
      </li>
      <li class="branch">branch B
        <ul><li class="leaf">leaf B1</li><li class="leaf special">leaf B2 (.special)</li></ul>
      </li>
    </ul>
  </li>
</ul>
<div class="row" id="trav-buttons" style="margin-top:12px">
  <button type="button" data-m="siblings">.siblings()</button>
  <button type="button" data-m="next">.next()</button>
  <button type="button" data-m="prev">.prev()</button>
  <button type="button" data-m="parent">.parent().closest('li')</button>
  <button type="button" data-m="parents">.parents('.branch')</button>
  <button type="button" data-m="find">$('#tree').find('.leaf')</button>
  <button type="button" data-m="filter">.filter('.special')</button>
  <button type="button" data-m="notfn">.not(fn)</button>
</div>
<pre class="out" id="trav-out" aria-live="polite"></pre>
JavaScript
const $start = $('#anchor-node');
const methods = {
  siblings: () => $start.siblings(),
  next:     () => $start.next(),
  prev:     () => $start.prev(),
  parent:   () => $start.parent().closest('li'),
  parents:  () => $start.parents('.branch'),
  find:     () => $('#tree').find('.leaf'),
  filter:   () => $('#tree .leaf').filter('.special'),
  notfn:    () => $('#tree .leaf').not((i, el) => el.textContent.includes('B')),
};

$('#trav-buttons').on('click', 'button', function () {
  $('#tree li').removeClass('hit');
  const $result = methods[this.dataset.m]();
  $result.addClass('hit');
  $('#trav-out').text($(this).text() + ' → ' + $result.length + ' element(s)\n' +
    'start.is(".leaf") = ' + $start.is('.leaf') + ' · start.is(".special") = ' + $start.is('.special'));
});

More examples

Climb, then search

JavaScript
$(document).on('click', '.remove', function () {
  $(this).closest('.cart-row').remove();
});
const $form = $('#email').closest('form');
$form.find('[required]').filter((i, el) => !el.value).addClass('missing');

API

.find(selector) → KJ

All descendants matching a selector.

Reference: .find() →
.filter(selector | fn) → KJ

Keep only matching elements. Accepts a selector or a predicate (i, el) => boolean.

Reference: .filter() →
.not(selector | fn(i, el) | element | collection) → KJ

Drop matching elements. Accepts a selector, an element or collection, or a predicate function.

Reference: .not() →
.is(selector | fn(i, el) | element) → boolean

Test whether any element in the set matches a selector, element, collection or predicate.

Reference: .is() →
.closest(selector) → KJ

Nearest matching ancestor (including the element itself). The backbone of event delegation.

Reference: .closest() →
.parent() · .parents([selector]) → KJ

Direct parent, or all ancestors (optionally filtered).

Reference: .parent() / .parents() →
.children([selector]) → KJ

Direct children, optionally filtered.

Reference: .children() →
.siblings([selector]) → KJ

All siblings, optionally filtered.

Reference: .siblings() →
.next([selector]) · .prev([selector]) → KJ

Adjacent siblings, optionally required to match a selector.

Reference: .next() / .prev() →

Migrating

Coming from jQueryCore traversal matches jQuery. .nextAll(), .prevAll(), .nextUntil(), .parentsUntil(), .has(), .contents(), .end() and .addBack() are not included.

Related features