Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the parent node of an element when the parent has siblings?

Please take a look at the snippet below:

<div>
    <div></div>
    <div><!-- my target node -->
        <div><!-- not my target node -->
            <img /><!-- my source node -->
        </div>
    </div>
</div>

As you can see the img-elment has two enclosing divs. I want the first of those two enclosing divs to be considered the "real" parent (the one I need to find) of the img-elment because it has a brother div before so the search ends and the brother div and the outer enclosing div are ignored.

In the case there are no siblings at all, the outer div has to be yielded; in the case the element is not enclosed, the element itself has to be yielded.

I just would like to know how to target the element as I explained via JavaScript.

like image 213
P5music Avatar asked Oct 12 '12 17:10

P5music


People also ask

How do I get parent node?

Approach: Write a recursive function that takes the current node and its parent as the arguments (root node is passed with -1 as its parent). If the current node is equal to the required node then print its parent and return else call the function recursively for its children and the current node as the parent.

Which method can be used to access the siblings of a node?

jQuery siblings() Method The siblings() method returns all sibling elements of the selected element.


1 Answers

So it sounds like you want the first ancestor that has siblings elements. If so, you can do it like this:

var parent = img.parentNode;

while (parent && !parent.previousElementSibling && !parent.nextElementSibling) {
    parent = parent.parentNode;
}

Or perhaps more appropriately written as a do-while loop:

do {
    var parent = img.parentNode;
} while (parent && !parent.previousElementSibling && !parent.nextElementSibling);

So the loop will end when it finds one with at least one sibling element, or when it runs out of ancestors.

If you know if the sibling comes before or after the parent, you can just test for one or the other.


Also note that you'll need a shim for the ***ElementSibling properties if you're supporting legacy browsers.

You can make a function that will do this:

function prevElement(el) {
    while ((el = el.previousSibling) && el.nodeType !== 1) {
        // nothing needed here
    }

    return el;
}

function nextElement(el) {
    while ((el = el.nextSibling) && el.nodeType !== 1) {
        // nothing needed here
    }

    return el;
}

Then use the functions like this:

do {
    var parent = img.parentNode;
} while (parent && !prevElement(parent) && !nextElement(parent));
like image 76
I Hate Lazy Avatar answered Oct 11 '22 12:10

I Hate Lazy