Reputation: 3337
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 div
s. I want the first of those two enclosing div
s 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.
Upvotes: 12
Views: 30033
Reputation: 128417
Just in case you're curious, here's how you might implement user1689607's answer using jQuery.
function getAncestorWithSiblings(element) {
var ancestor = element.parent();
while (ancestor && ancestor.siblings().length === 0) {
ancestor = ancestor.parent();
}
return ancestor;
}
Whether it makes sense to use this library for your purposes depends on a great deal of context we don't have. As others have rightfully pointed out, you don't need jQuery to solve this problem, and it may be an unnecessarily heavyweight solution. That said, it can be a very useful library and is certainly worth your consideration if you weren't aware of it or hadn't already looked into it.
Upvotes: 0
Reputation: 48789
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));
Upvotes: 21
Reputation: 156
If you don't know how many levels up the parent element is, it will be difficult to select it using methods like element.getParent
alone. However, you CAN iterate through parent nodes until the node you're looking at has siblings and is the child of a body
element. Let's assume that your img
tag is referred to by imgNode
.
function getParentWithSiblings(imgNode) {
for( ; n; n = imgNode.parentNode) {
if (n.nextSibling && n.parentNode.tagName == 'body') {
return n;
}
}
}
In the code above, we progressively iterate through the parents of the image node. At each iteration, we check whether the current node (some parent of the img
node) has a sibling and is the child of a body
tag.
Upvotes: 0