JQuery фильтр выбора для удаления вложенных элементов, соответствующих шаблону - PullRequest
6 голосов
/ 22 июня 2010

Принимая во внимание этот пример разметки (при условии случайного числа элементов от .outer до .inner:

<div class="outer">
    <div>
        <div>
            <div class="inner"></div>
        </div>
    </div>
</div>

, я могу настроить jQuery для выбора внешнего и внутреннего div как:

$outer = $('.outer');
$inner = $outer.find('.inner')

Работает нормально.

Однако, допустим, я хочу разрешить неограниченное вложение этой логики, поэтому я могу иметь следующее:

<div class="outer"> div a
    <div class="inner"> div b
        <div class="outer"> div c
            <div class="inner"> div d </div>
        </div>
    </div>
</div>

В такой ситуации, когдавыбрав div a via .outer Я хочу сопоставить его только с div B. Другими словами, я хочу исключить предков вложенного .outer предка.

Я хотел бы иметь соединения внешнего и внутреннего(s) содержится в пределах их уровня вложенности.

Я надеюсь, что .filter() мог бы справиться с этим, но не могу придумать селектор, который бы работал универсально для неограниченных вложенных шаблонов. Это выполнимо с помощью фильтра? Или, может быть, даже шаблон прямого селектора?

ОБНОВЛЕНИЕ:

Я думаю, что-то вроде этого может работать, но не уверен, как можно (или если это разрешено) ссылаться на «это» в селекторе:

$outer = $('.outer');
$inner = $outer.not('this .outer').find('.inner')

ОБНОВЛЕНИЕ 2:

Я долженупомянул это изначально: .inner всегда будет потомком .outer, но не обязательно непосредственным ребенком.

ОБНОВЛЕНИЕ 3:

Вот несколько тестовых примеров HTML, которые можно использовать.В каждом случае я хотел бы иметь возможность выбрать .outer и соединить .inner, который он содержит между собой и вложенным внешним.Для ясности я добавил имена к каждому div (пары external-x с inner-x)

//sample 1
<div class="outer"> outer-a
    <div>
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div class="inner"> inner-b </div>
            </div>
        </div>
    </div>
    <div>
        <div class="inner"> inner-a </div>
    </div>
</div>

//sample 2
<div class="outer"> outer-a
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div>
                    <div class="inner"> inner-b </div>
                </div>
            </div>
        </div>
</div>

//sample 3
<div class="outer"> outer-a
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div class="inner"> inner-b
                    <div class="outer"> outer-c 
                        <div class="inner"> inner-c</div>
                    </div>
                </div>
            </div>
        </div>
</div>

//bonus sample (we're trying to avoid this)
<div class="outer"> outer-a
        <div class="inner outer"> inner-a outer-b
            <div class="inner"> inner-b </div>
        </div>
</div>

UPDATE 4

Я думаю, что в конечном итоге пошел по тому же пути, что и gnarf.Я закончил с этим:

var $outer = $('.outer');
var $inner = $outer.find('.inner').filter(function(){
    $(this).each(function(){
        return $(this).closest('.outer') == $outer; 
  });                                                                  
});

Я на правильном пути там?Это не работает, поэтому я предполагаю, что у меня все еще есть небольшая логическая ошибка.

Ответы [ 6 ]

12 голосов
/ 23 июня 2010

Вот еще один вариант.Предположим, у вас есть .outer o, он выберет все inner s под ним:

o.find('.inner').not(o.find('.outer .inner'))

Он должен работать идентично ответу gnarf, но немного проще.

Сначала он находит все inner с этим outer.
Затем удаляет все inners, которые являются потомками других outers

Интерактивный рабочий пример: http://jsfiddle.net/Zb9gF/

Производительность селектора, кажется, намного лучше при использовании этого метода, в отличие от .filter(): http://jsperf.com/selector-test-find-not

2 голосов
/ 22 июня 2010

Если .inner - это всегда прямые дети .outer s - children(), вероятно, ваша лучшая ставка (ответ jasongetsdown)

Если вам нужно что-то еще более глубокое, вы можете сделать что-то вроде этого:

var $outer = $('.outer').first(); // grab the first .outer
$outer.find('.inner').filter(function() {
    // only if the closest parent .outer is the same as the .outer we are looking in
    return $(this).closest('.outer').get(0) == $outer.get(0);
}).css('border','1px solid #000');

jsfiddle demo

1 голос
/ 22 июня 2010

Если правильно предположить, что вы хотите выбрать все .inner ниже .outer, за исключением случаев, когда между ними стоит .outer, возможно, будет работать следующее (не проверено):

$('.outer:not(.inner):has(:not(.outer) .inner:not(.outer), > .inner:not(.outer))');

updatedпосле теста на OP пример HTML на http://jsfiddle.net/cEwBT/1/

1 голос
/ 22 июня 2010
$('.outer').children('.inner');

Это выберет любой inner, который находится непосредственно под outer.Мне не очень понятно, какой div вы пытаетесь выбрать.Это a, b, c или d?Наличие того, что называется внешним, вложенным во что-то, называемое внутренним, не имеет большого смысла.Может быть, вы могли бы привести более конкретный пример?

0 голосов
/ 23 июня 2010

Интересно, почему бы сначала не выбрать .inner, а затем получить closest .outer?

$inner = $('.inner');
$outer = $inner.closest('.outer');

в случае, если некоторые внутренние блоки могут вообще не находиться внутри внешних блоков, используйте эту первую строку вместо

$inner = $('.outer .inner');

0 голосов
/ 22 июня 2010

Вы можете использовать магию CSS:

$('.outer>.inner')

Shold дает вам только первый уровень .inner элементов. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...