What is the pure JavaScript equivalent of jQuery's .parents() method? [duplicate]
Asked Answered
M

2

9

Apologies for this kind of question, but I can't find an answer on You Might Not Need jQuery or anywhere else online and I'd really like to know:

What is the pure JavaScript equivalent of jQuery's .parents() method?

For example, it would be great to know how to do this in pure JavaScript:

jQuery(element).parents('.className');
Monney answered 19/7, 2016 at 22:57 Comment(6)
"What is the pure JavaScript equivalent of jQuery's .parents() method?" There is none. Do you mean "What's the DOM API version of jQuery's parents() method?"Gross
while ((element = element.parentElement)) { if (element.matches('.className')) { result.push(element) } }Assorted
I was pretty sure this is a duplicate but I can't find it.Inventive
You can always look at jQuery's github for their source: .parents() -> dir()Gladysglagolitic
Ah, yes this is what I was looking forInventive
I went straight to their github and searched, but it seems "bitten" did have an answer below that also listed the transversing moduleGladysglagolitic
G
9

There is no one function/property in the DOM API that equates to jQuery's parents, but you can easily build one with few lines of code using a loop with:

  • parentElement, which provides a reference to the element's parent element or null. (Or you could use parentNode, but you have to check for both null and document to know when to stop.)
  • matches if you want only parent elements matching a selector

(jQuery takes a set-based approach to DOM manipulation and traversal, whereas the DOM API takes a per-element/node approach. I won't address doing the set thing here.)

Example:

function getParents(element, selector) {
    const parents = [];
    let parent = element;
    while (parent) {
        // Include this "parent" if either we don't have a selector at all,
        // or we have one and it matches
        if (!selector || parent.matches(selector)) {
            parents.push(parent);
        }
        parent = parent.parentElement;
    }
    return parents;
}

Runnable version:

const elm = document.getElementById("target");

console.log("All divs:");
showElements(getParents(elm));

console.log("Only divs with a data-test attribute:");
showElements(getParents(elm, "[data-test]"));

function getParents(element, selector) {
    const parents = [];
    let parent = element;
    while (parent) {
        // Include this "parent" if either we don't have a selector at all,
        // or we have one and it matches
        if (!selector || parent.matches(selector)) {
            parents.push(parent);
        }
        parent = parent.parentElement;
    }
    return parents;
}

function showElements(elements) {
    console.log(Array.from(elements,(e) => e.nodeName + (e.id ? "#" + e.id : "")));
}
.as-console-wrapper {
    max-height: 100% !important;
}
<div id="outermost" data-test>
    <div id="middle">
        <div id="inner" data-test>
            <div id="target"></div>
        </div>
    </div>
</div>

The site https://youmightnotneedjquery.com/#parents has lots of information for doing jQuery-like things only with native DOM functions (for instance: parents, which has a function very very similar to the above, but using parentNode rather than parentElement and therefore including the check for document).

Gross answered 19/7, 2016 at 22:59 Comment(0)
B
2

When you get a HTML via some method (document.getElementById(), document.querySelector(), etc) it will return a Node object, the .parentNode property of the object is the parent Node object


To get all parent nodes, akin to jQuery's `.parents()`:

I wrote this function a while back:

function parents(node) {
   let current = node,
       list    = [];
   while(current.parentNode != null && current.parentNode != document.documentElement) {
     list.push(current.parentNode);
     current = current.parentNode;
   }
    return list
}

Please note this is only slightly tested, so take it with a grain of salt

Birdella answered 19/7, 2016 at 22:59 Comment(9)
Not really the same thing, although you can recursively traverse the DOM backwards using the .parentNode property to achieve similar functionality to the jQuery .parents() method. But it requires writing some code.Managing
I certainly wouldn't downvote based on that, though.Gross
@T.J.Crowder Agreed. Reversed the downvote, to harsh :-)Managing
Using parentElement there is no need to check != document.Pouf
You need to make sure current isn't null before accessing .parentNode.Assorted
Isn't the parentElement of body the document?Birdella
It's the document.documentElement.Assorted
Ok. See? Very little tested. I will update the function accordinglyBirdella
I wrote it recursively originally, than make it just loopBirdella

© 2022 - 2024 — McMap. All rights reserved.