Поиск всех потомков "X-поколения" с помощью jQuery - PullRequest
5 голосов
/ 17 сентября 2011

Решено ( сорт )

Ну, я думаю, что я решил это ( исключая крайние случаи ), используя следующее:

function findByDepth(parent, child, depth){
    var children = $();
    $(child, $(parent)).each(function(){
        if($(this).parentsUntil(parent, child).length == (depth - 1)){
            children = $(children).add($(this));
        }
    });
    return children;
}

// this would successfully return the 3.X elements of an HTML snippet structured
// as my XML example, where <parent> = #parent, etc.
var threeDeep = findByDepth('#parent', '.child', 3);

Однако кто-то должен получить здесь принятый ответ, и я не собираюсь отвечать на него сам и скрываюсь от вашего заслуженного представителя.Так что, если кто-то захочет что-то добавить, например, дать представление об оптимизации этой функции ( перед тем, как я уйду, и $.extend() - в ), я, скорее всего, отмечу ваш ответ правильным, иначе вернусь к отметке того, ктосначала на мой начальный вопрос.

Кстати, проверьте это в скрипке: http://jsfiddle.net/5PDaA/

Суб-обновление

Снова глядя на @Ответ CAFxX, я понял, что его подход, вероятно, быстрее, используя преимущества querySelectorAll в браузерах, которые могут.В любом случае, я пересмотрел его подход к следующему, но он все еще дает мне раздражение:

$.fn.extend({
    'findAtDepth': function(selector, depth){
        var depth = parseInt(depth) || 1;
        var query = selector;
        for(var i = 1; i < depth; i++){
            query += (' ' + selector);
        }
        return $(query, $(this)).not(query + ' ' + selector);
    }
});

В первый раз он работает нормально, однако, когда контекст меняется на элемент, найденный в selector, он не работает дляпо какой-то причине.


Обновление

Хорошо, я был по-дурацки неясен и не осведомлен о спецификациях того, что я делаю.Поскольку я рассмотрел мою реализацию, я обновлю здесь;Я отмечу самый ранний ответ, который отвечает моим первоначальным требованиям, учитывая, что люди считают меня дураком за такое бесплатное обновление ( Я бы не стал винить вас ), однако мой бонус , упомянутый ниже, по сути являетсятребование.Я бы отправил другой вопрос, но он, вероятно, был бы закрыт от дублирования.В любом случае, + 1 означает ваше терпение:

Требуется указание глубины данного ребенка (, если оно заключено в функцию или иным образом ), таким образом изолируя ребенкаи одинаково вложенные ( не обязательно родные элементы ) совпадающие элементы.

Например ( XML для краткости ):

<!-- depth . sibling-index-with-respect-to-depth -->

<parent>
    <child>                     <!-- 1.1 -->
        <child>                 <!-- 2.1 -->
            <child>             <!-- 3.1 -->
                <child></child> <!-- 4.1 -->
            </child>            
            <child>             <!-- 3.2 -->
                <child></child> <!-- 4.2 -->
            </child>            
        </child>                
        <child>                 <!-- 2.2 -->
            <child></child>     <!-- 3.3 -->
        </child>                
    </child>                    
</parent>

При заданной глубинеиз 2, все 2.X элементы выбраны.Учитывая 4 все 4.X и т. Д.


Оригинальный вопрос

Используя встроенную функциональность jQuery, есть ли способ выбрать только «первое поколение»потомков, соответствующих селектору?Например:

Примечание : Ниже приведен только пример..child элементы вложены в родительский элемент на произвольном уровне.

Bonus : Как показывает предложенный ниже синтаксис, ответ, предоставляющий способ указатьглубина, на которую должен пройти выбор, составит невероятно .

// HTML
<div id="parent">
    <div>
        <div class="child"> <!-- match -->
            <div>
                <div class="child"> <!-- NO match -->
                </div>
            </div>
        </div>
        <div class="child"> <!-- match -->
            <div>
                <div class="child"> <!-- NO match -->
                </div>
            </div>
        </div>
    </div>
</div>

И:

// jQuery
$('#parent').find('.child:generation(1)'); // something in that vein

Попытка выбрать из контекста #parentjQuery :first здесь не работает, так как он попадает только в первое совпадение .child.

Ответы [ 3 ]

2 голосов
/ 17 сентября 2011

Попробуйте это (ПОЦЕЛУЙ!):

$("#parent .child").not(".child .child");

изменить: чтобы получить второй уровень:

$("#parent .child .child").not(".child .child .child");

третий:

$("#parent .child .child .child").not(".child .child .child .child");

и так далее ... чтобы вы могли (без проверки):

function findChildrenDeepDown(parentSelector, level) {
  level = parseInt(level);
  var firstSelctor = parent, notSelector = ".child", i;
  for (i=0; i<level; i++) {
    firstSelector += " .child";
    notSelector += " .child";
  }
  return $(firstSelector).not(notSelector);
}

findChildrenDeepDown("#parent", 3); // find third-level children of #parent
1 голос
/ 17 сентября 2011

В общем, я думаю, вам нужно найти все элементы .child, а затем выбросить те, которые имеют .child предков:

$('#parent .child').filter(function() {
    return $(this).parent().closest('.child').length == 0;
});

Это не относится к таким вещам, как этохотя:

<div id="parent">
    <div class="child"> <!-- match -->
        <div>
            <div class="child"> <!-- NO match -->
            </div>
        </div>
    </div>
    <div>
        <div>
            <div class="child"> <!-- NO match wanted but it will match -->
            </div>
        </div>
    </div>
</div>

но, возможно, этого будет достаточно для структуры вашего HTML.

1 голос
/ 17 сентября 2011

вы можете получить это так:

$("#parent").find(">div>.child")

РЕДАКТИРОВАТЬ

Если первый ребенок может быть на произвольной глубине, вы можете использовать

$("#parent").find(".child").siblings();
...