Climbing the DOM until you get a match using native JavaScript
In jQuery, .parentsUntil()
climbs the DOM tree and returns all parent elements until a matching parent is found. If you include a selector, it will only return those that match. Here’s the vanilla JavaScript equivalent:
var getParentsUntil = function (elem, parent, selector) {
var parents = [];
if ( parent ) {
var parentType = parent.charAt(0);
}
if ( selector ) {
var selectorType = selector.charAt(0);
}
// Get matches
for ( ; elem && elem !== document; elem = elem.parentNode ) {
// Check if parent has been reached
if ( parent ) {
// If parent is a class
if ( parentType === '.' ) {
if ( elem.classList.contains( parent.substr(1) ) ) {
break;
}
}
// If parent is an ID
if ( parentType === '#' ) {
if ( elem.id === parent.substr(1) ) {
break;
}
}
// If parent is a data attribute
if ( parentType === '[' ) {
if ( elem.hasAttribute( parent.substr(1, parent.length - 1) ) ) {
break;
}
}
// If parent is a tag
if ( elem.tagName.toLowerCase() === parent ) {
break;
}
}
if ( selector ) {
// If selector is a class
if ( selectorType === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
parents.push( elem );
}
}
// If selector is an ID
if ( selectorType === '#' ) {
if ( elem.id === selector.substr(1) ) {
parents.push( elem );
}
}
// If selector is a data attribute
if ( selectorType === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 1) ) ) {
parents.push( elem );
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
parents.push( elem );
}
} else {
parents.push( elem );
}
}
// Return parents if any exist
if ( parents.length === 0 ) {
return null;
} else {
return parents;
}
};
And to use it:
var elem = document.querySelector('#some-element');
var parentsUntil = getParentsUntil(elem, '.some-class');
var parentsUntilByFilter = getParentsUntil(elem, '.some-class', '[data-something]');
var allParentsUntil = getParentsUntil(elem);
var allParentsExcludingElem = getParentsUntil(elem.parentNode);