Grodriguez
Grodriguez

Reputation: 21995

Efficient check for a CSS class in any of the parents of a DOM node

I am looking for an efficient way to check if any of the parents of a DOM node has a given CSS class.

My question is very similar to this one: Check if class exists somewhere in parent - vanilla JS, except that I am explicitly looking for advice on how to implement this in the most efficient way (this code will be called very often).

The accepted answer to the above question suggests a recursive solution. I am wondering if there is a more efficient way.

Upvotes: 2

Views: 221

Answers (3)

Evan Trimboli
Evan Trimboli

Reputation: 30082

How about something like this?

var hasClass = (function() {
    var hasClassList = !!document.documentElement.classList;

    return function(dom, cls) {
        var spaced = ' ' + cls + ' ';
        while (dom.parentNode) {
            if (hasClassList) {
                if (dom.classList.contains(cls)) {
                    return true;
                }
            } else {
                if ((' ' + dom.className + ' ').indexOf(spaced) !== -1) {
                    return true;
                }
            }
            dom = dom.parentNode;
        }
        return false;
    }
})();

Upvotes: 1

Stefan Dunn
Stefan Dunn

Reputation: 5513

Use jQuery:

$(document).ready(function(){
    var parentIsOfClass = ($("[DOM ID or CLASS]").parents().filter("[PARENT CLASS]").length > 0);
});

http://jsfiddle.net/

Will return true or false

Upvotes: 0

Rob W
Rob W

Reputation: 348992

If you like a nice syntax, use the matchesSelector method (caniuse).

This method has undergone some name changes, and it's still prefixed, so to use it, normalize the name:

var matchesSelector;
['webkitM', 'mozM', 'msM', 'oM', 'm'].some(function(prefix) {
    var name = prefix + 'atches';
    if (name in document.documentElement) {
        matchesSelector = name;
    }
    name += 'Selector';
    if (name in document.documentElement) {
        matchesSelector = name;
    }
    return matchesSelector; // If found, then truthy, and [].some() ends.
});

After determining the name, you can use it as follows:

// Usage
element[matchesSelector]('.someclass *');

Or just extend the prototype:

Element.prototype.matches = Element.prototype[matchesSelector];
// Usage
element.matches('.someclass *');

Upvotes: 2

Related Questions