chrisjlee chrisjlee - 7 months ago 112
Javascript Question

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

Here's the markup i'm trying to query. So given the markup:

<table class="non-unique-identifier table">
<tr><td><div id="unique-identifier"></div></td></tr>
</table>


I'm querying for #unique-identifier:

var myDiv = document.getElementById('#unique-identifier');


I'm then trying to select the table. The issue is that i want to make the code not brittle so i don't need to do this:

var myDiv = document.getElementById('#unique-identifier'),
myTable = myDiv.parentNode.parentNode.parentNode.parentNode;


My question

Is there currently a DOM implementation of the jQuery equivalent of $().closest() ? A closest implementation that is efficient without nested for loops would be preferred.

Limitations

I'm required to not use jQuery or sizzle for this particular issue or introduce any new libraries. The code is quite old as well. Thus, that is the reason for such limitations and the existence of
<tables>
.

Answer

You can't do this without a loop :

function closest(el, fn) {
    while (el) {
        if (fn(el)) return el; 
        el = el.parentNode;
    }
}

Well, actually you can, using recursivity :

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

Usage example :

<div class="item">
    <p>Hello <b id="world">World</b></p>
</div>
var world = document.getElementById('world');
var p = closest(world, function (el) {
    return el.tagName.toLowerCase() === 'p';
});
var div = closest(p, function (el) {
    return el.className === 'item';
});

A demo using Sizzle : http://jsfiddle.net/wared/fjM27/.