Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I select the "shallowest" matching descendant?

How can I select the first "shallowest" input?

My current selection will be the div marked "selected".
I won't know how many levels down it will be.

<div class="selected"> <!-- already have this -->
  <div class="unknown-number-of-wrapper-panels">
    ...
    <div class="collection">    
      <div class="child">
        <input type="text" value="2" /> <!-- don't want this -->
      </div>
    </div>
    <input type="text" value="2" /> <!-- need this -->
    <input type="text" value="2" />
    ...
  </div>
</div>

It seems like find().first() gives me the deepest one.

Edited for clarity. I need to find it based on the fact that it is shallower, not based on other unique attributes.

This might be like a reverse of closest() ?

like image 565
Benjamin Avatar asked Aug 13 '11 16:08

Benjamin


2 Answers

If I understand your issue, you need to recursively check the child nodes for elements with that class.

function findShallowest( root, sel ) {
    var children = root.children();
    if( children.length ) {
        var matching = children.filter( sel );
        if( matching.length ) {
            return matching.first();
        } else {
            return findShallowest( children, sel );
        }
    } else {
        return null;
    }
}

var selected = $('.selected');

findShallowest( selected, ':text' );

Example: http://jsfiddle.net/Qf2GM/


EDIT: Had forgotten a return statement, and had an ID selector instead of a class selector for the initial .selected.


Or make it into your own custom plugin:

Example: http://jsfiddle.net/qX94u/

(function($) {
    $.fn.findShallowest = function( sel) {
        return findShallowest( this, sel );
    };
    function findShallowest(root, sel) {
        var children = root.children();
        if (children.length) {
            var matching = children.filter(sel);
            if (matching.length) {
                return matching.first();
            } else {
                return findShallowest(children, sel);
            }
        } else {
            return $();
        }
    }
})(jQuery);

var result = $('.selected').findShallowest( ':text' );


alert( result.val() );
like image 114
user113716 Avatar answered Sep 19 '22 19:09

user113716


You are after a breadth-first search rather than the depth-first search (which jQuery's find() uses). A quick google has found: http://plugins.jquery.com/project/closestChild

This could be used like this:

$(...).closestChild('input')
like image 44
a'r Avatar answered Sep 20 '22 19:09

a'r