jQuery: селектор только прямого потомка

#jquery #jquery-selectors

#jquery #jquery-селекторы

Вопрос:

У меня есть следующая структура :

 <ul>
    <li><a>link</a>
        <ul>
            <li>
                <a>link</a>
                <ul>
                    <li><a>link</a></li>
                    <li><a>link</a></li>
                    <li><a>link</a></li>
                </ul>
            </li>
             <li>
                <a>link</a>
                 <ul>
                    <li><a>link</a></li>
                    <li><a>link</a></li>
                    <li><a>link</a></li>
                 </ul>
             </li>
        </ul>
    </li>
    <li>
        <div>content 
            <ul>
                <li><a>link</a></li>
                <li><a>link</a></li>
                <li><a>link</a></li>
            </ul>
         </div>
    </li>
    <li><a>link</a></li>
    <li><a>link</a></li>
    <li><a>link</a></li>
</ul>
  

Я хочу выбрать только якоря, которые попадают непосредственно под <li> теги (дочерние элементы), но не те, которые попадают под другие теги (внуки)
если я сделаю

 $('ul li> a')
  

Я также получу ul, который вложен под div. есть ли «чистый» способ сделать это?
Спасибо

ps: Я хотел бы иметь универсальный селектор (это для плагина меню, поэтому я хочу, чтобы он игнорировал все теги привязки, которые не попадают непосредственно в поток меню)

Комментарии:

1. Можете ли вы добавить идентификатор к корню, ul чтобы отличить его от любого ul ? Тогда $('#root > li > a') не будет хватать это глубже ul > li > a . Или вы также хотите, чтобы были захвачены другие deep ul > li > a s, только не тот, который находится под div ?

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

3. Итак, вы хотите захватить все a элементы на любой глубине, если их предками являются только ul или li ? Итак, ul > li > a будет совпадать, и ul > li > ul > li > ul > li > a тоже будет совпадать?

4. да, но в этом случае ul> li> div> ul> li> a также соответствовал бы, не так ли?

5. @wiseguy, да, точно … он не должен соответствовать ничему ПОД div (или чему-либо другому, кроме ul или li)

Ответ №1:

Окончательное решение

Этот ответ был полностью отредактирован, чтобы поддерживать его в актуальном состоянии. Конечное решение — это, по сути, селектор, в котором, начиная с идентификатора исходного <ul> элемента, выберите все привязки в элементах списка, что не нарушает поток структуры меню. То есть, если есть элемент, отличный от <ul> или <li> вложенного внутри, не выбирайте ничего внутри этих элементов, даже если внутри есть меню.

Результирующий селектор ( #root является идентификатором основного <ul> ) :

 $('#root > li > a, #root ul:not(#root :not(ul,li) ul) > li > a')
  

Вы можете попробовать демо-версию здесь: http://jsfiddle.net/9gPzQ/31 /

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

 $('li >a',this.content).not($(':not(ul,li) a',this.content))
  

Другие интересные селекторы

На пути поиска решения возникли некоторые интересные селекторы из-за моего непонимания проблемы, но я все равно включу их сюда просто для справки, кому-то это может пригодиться. 🙂

Этот селектор выбирает привязки элементов списка, которые находятся на верхнем уровне меню, где бы они ни находились на странице:

 $(':not(li) > ul > li > a')
  

Этот селектор выбирает привязки элементов списка, которые находятся на верхнем уровне меню, игнорируя меню, вложенные в другие меню, даже если они вложены в другие контейнеры:

 $('ul:not(ul ul) > li > a')
  

Вы можете попробовать эти селекторы в демо-версии здесь: http://jsfiddle.net/9gPzQ/4 /

Комментарии:

1. 1 Хорошее решение. Производительность должна быть в порядке, поскольку выбор обычно выполняется справа налево, поэтому нет необходимости в дорогостоящем * вызове где бы то ни было.

2. на самом деле это звучит близко, но что-то, что выбирало бы только ul> li> a, которые попадают непосредственно под li .. ваше предложение делает прямо противоположное, или я ошибаюсь?

3. итак, я предполагаю, что это сработает, если я сделаю: (‘li > a’).not(‘:not(li) > ul > li > a’)… Я должен попробовать… @lonesomeday я надеюсь, что ваша оценка производительности остается в силе 🙂

4. Потребовалось немного повозиться, но вот как это выглядит при использовании объекта: $(‘li >a’,this.content).not($(‘:not(ul, li) a’,this.content)) Еще раз спасибо @DarthJDG за вашу помощь 🙂

5. Это действительно хорошее решение. Это было весело.

Ответ №2:

Я думаю, что вы ищете:

 $('ul:parent ul li>a')
  

Это даст вам все li>a без div или чего-либо в нем.

Ответ №3:

Благодаря замечательному вкладу @DarthJDG

это решение

 $('li >a',this.content).not($(':not(ul,li) a',this.content))
  

this.content является объектом, на который ссылается подключение, в данном случае объект является родительским UL

Я надеюсь, что это кому-то поможет