DOM / pure JavaScript solution to jQuery.closest() implementation?

You can't do this without a loop :

function closest (el, predicate) {
  do if (predicate(el)) return el;
  while (el = el && el.parentNode);
}

Well, actually you can, using recursivity (a disguised loop) :

function closest(el, predicate) {
  return predicate(el) ? el : (
     el && closest(el.parentNode, predicate)
  );
}

A demo (using Sizzle for the DOM queries) :

// s = selectors
// n = number of selectors
// get closest s[i+1] from s[i]
// where 0 <= i < n and i % 2 = 0

function main (s) {
  var i, el, from;
  var n = s.length;
  for (i = 0; i < n; i += 2) {
    from = Sizzle(s[i])[0];
    el = closest(from, function (el) {
      return !!el && el !== document && (
        Sizzle.matchesSelector(el, s[i + 1])
      );
    });
    console.log(el);
  }
}

function closest (el, predicate) {
  do if (predicate(el)) return el;
  while (el = el && el.parentNode);
}

main([
  "#winner" , "b", 
  "#winner" , "p", 
  "#winner" , "div", 
  "#winner" , "div:not(#trump)", 
  "#winner" , "#clinton",
  "#looser" , "html"
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/sizzle/1.10.18/sizzle.min.js"></script>

<div id="main">
  <div id="trump">
    <p>Donald <b id="winner">Trump</b></p>
  </div>
  <div id="clinton">
    <p>Hillary <b>Clinton</b></p>
  </div>
</div>

To add an updated answer, there is now Element.closest(<query_selector>) available.

https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

This isn't supported on IE, but that mozilla doc page includes code for a polyfill for IE8 and IE9+.


Concise and quick (tested with Benchmark.js) way to search for closest element by any css selector:

var ep = Element.prototype;
ep.matches = ep.matches || ep.webkitMatchesSelector || ep.msMatchesSelector || ep.mozMatchesSelector;

function getClosest( elem, selector ) {
    while (elem !== document.body) {
        elem = elem.parentElement;
        if (elem.matches(selector)) return elem;
    }
}

Supports IE9+ and the rest of the browsers you can expect to care about.

Tags:

Javascript

Dom