0

I have structures that look like this :

<div class="wanted" id="but-not-really">
    <div class="wanted">
        <div class="dad">
            <input class="reference"/>
            <input class="wanted"/>
            <input class="bro3"/>
        </div>
    </div>
</div>

And I want to get the width of either an ancestor (div.wanted) or a sibling (input.wanted) of my .reference element (which is $(this) in my JS loop), depending of which is the closest.

If I only wanted to seek through the ancestors, I would use $(this).closest('.wanted').width(). If I only wanted to seek through the siblings, I would use $(this).siblings('.wanted').width().

I tried to use $(this).parents().find('.wanted').width() but the webpage contains other elements up the document that are interfering. That's why I'm looking for the closest .wanted element among the siblings and the ancestors.

SOLUTION N°1 (thanks to @undefined) :

At first check the siblings using siblings method, if the collection is empty then use closest.

var width = $(this).siblings('.wanted').length === 0
             ? $(this).closest('.wanted').css('width')
             : $(this).siblings('.wanted').css('width');
Seeven
  • 969
  • 1
  • 8
  • 24
  • You might have to manually iterate up and down the tree and keep a record of the 'degree of separation' to compare at the end of your loop. I don't know of any inbuilt jQuery function that will do this for you. – DvS Sep 16 '14 at 09:53
  • 1
    At first check the siblings using `siblings` method, if the collection is empty then use `closest`. – Ram Sep 16 '14 at 09:55
  • @undefined The question is the find the closest between ancestors and descendants, not which exists – DvS Sep 16 '14 at 09:58
  • What is `this` in your loop? Show your code. – Satpal Sep 16 '14 at 09:58
  • @Satpal: `$(this)` is the `.reference` element. My code is a little complicated and not relevant for this question. – Seeven Sep 16 '14 at 10:03
  • @undefined: I was hoping there was a JQuery function to avoid this. Anyway I came up with this solution : `var width = input.siblings(selector).length === 0 ? input.closest(selector).css('width') : input.siblings(selector).css('width');` – Seeven Sep 16 '14 at 10:04
  • @SeevenByakko You can also define a method, something like `nearest`? Unfortunately jQuery doesn't have such method. – Ram Sep 16 '14 at 10:23
  • @undefined: Yes, it would be a useful JQuery method IMHO. – Seeven Sep 16 '14 at 10:27

1 Answers1

0

How about something like this?

var closestNextDistance = $(this).nextUntil('.wanted').length;
var closestPrevDistance = $(this).prevUntil('wanted').length;
var closestParentDistance = $(this).parentsUntil('.wanted').length;

Then compare the distances to check which one is the closest element, if the parent is closer, call

$(this).closest(selector).css('width')

else if one of the siblings is closer then call

$(this).prevAll('.wanted').css('width')

or

$(this).nextAll('.wanted').css('width')

See http://jsfiddle.net/3z7t5gqn/

You'll need to add few checks there to see if there's a next('.wanted') sibling when nextUntil returns 0 but if you turn it into a little function, you could re-use it.

artm
  • 8,554
  • 3
  • 26
  • 43