#jquery #jquery-selectors
#jquery #jquery-селекторы
Вопрос:
Я ищу способ выбрать элементы, содержащие определенный элемент, а затем отфильтровать результаты, чтобы получить только самый высокий уровень. Сложно объяснить, но стало проще на примере:
<div id="one">
<div id="two">
<div id="three" class="find-me"></div>
</div>
</div>
<div id="four">
<div id="five" class="find-me"></div>
</div>
В этом случае я бы хотел, чтобы мой набор содержал # один и # четыре. Если я попытаюсь сделать что-то вроде этого:
var elements = $('div').has('.find-me');
Я получаю элементы # один, # два и # четыре.
Примечание: В данном случае ‘самый высокий уровень’ относится к самому верхнему элементу в первом селекторе $('div')
.
Ответ №1:
Ну, определение того, что highest level
такое, немного неоднозначно, потому что на практике, если на вашей странице есть что-либо .find-me
, родительским элементом самого высокого уровня будет html
тег! что бесполезно.
Определив вашу проблему более конкретно, вы можете придумать более четкое определение для этого highest-definition
и, например, сказать the farthest div parent
et . а для обхода родительских элементов элемента вы можете использовать методы .parents()
и .closest()
.
var farthestDiv = $(".find-me").parents("div").last();
очевидно, что если у вас более одного появления, find-me
вам нужно запустить это в .each()
цикле.
смотрите пример здесь: http://jsfiddle.net/GsQDb/3 /
Комментарии:
1. Хороший момент — я предполагаю, что это самый высокий уровень первого набора;
$('div')
в данном случае. Мне нравится мысль делать это «задом наперед» вот так. Скорость — большая проблема на этой странице (2 мб html для обхода), поэтому было бы интересно узнать разницу в скорости между этим ответом и ответом @karnyj
Ответ №2:
Предполагая, что под «верхним уровнем» вы подразумеваете прямого потомка тега body, вы можете использовать эту строку. Он находит все объекты с .find-me
классом, затем выполняет поиск родительского тега, который является потомком тега body (который будет верхнего уровня).
$(".find-me").parents("body > *")
Вы можете увидеть, как это работает здесь: http://jsfiddle.net/jfriend00/9LF6u /
Это имеет следующие преимущества:
- Тегом верхнего уровня может быть любой тип тега (не только div)
- Это должен быть один из самых быстрых способов сделать это, поскольку он находит
.find-me
объекты (что будет быстрой внутренней операцией в большинстве браузеров черезgetElementsByClassName
) и просто поднимается по их родительской иерархии. - Он автоматически обрабатывает дубликаты, поэтому данный элемент верхнего уровня никогда не будет указан более одного раза.
- Если когда-либо вы захотите изменить определение верхнего уровня (например, на объект контейнера), вы можете просто изменить селектор, переданный
.parents(selector)
методу, чтобы отразить это изменение.
Комментарии:
1. Моя неосведомленность об автоматической обработке дубликатов jQuery — вот почему я выбрал обычный маршрут js в своем ответе: P Я преклоняюсь перед мастером
2. Объекты jQuery, созданные с помощью селекторов фильтров, никогда не имеют дубликатов, поскольку большинство методов jQuery заканчиваются внутренним вызовом
.unique()
, который отфильтровывает дубликаты и расставляет селекторы по порядку документов.
Ответ №3:
используйте filter, чтобы отфильтровать элементы, которые не соответствуют тому, что вы хотите, после вашего первого выбора. пример:
var elements = $('div.find-me').filter(function(idx){
return !$(this).parents('div.find-me').length;
});
Ответ №4:
Это сделает то, что вы хотите, сначала найдет элементы, а затем найдет из них самые высокие элементы и создаст объект jQuery из найденных самых высоких элементов.
var elements = $('div.find-me'), highest = [];
elements.each( function(){
var parent = this, body = document.body;
while( parent amp;amp; parent.parentNode !== body ) {
parent = parent.parentNode;
}
if( $.inArray( parent, highest ) < 0 ) {
highest.push( parent );
}
});
highest = jQuery( highest );
jsfiddle:
Ответ №5:
Если вы поместите их все в один большой контейнер div, вы можете использовать:
$('.container div.find-me').parents($('.container').children());
Это ДОЛЖНО сработать, хотя у меня нет возможности протестировать это прямо сейчас.
Дайте мне знать, если нет, поскольку существуют и более сложные решения.
Ответ №6:
Можете ли вы назначить класс большинству верхних разделов? Если это так, вы можете сделать что-то вроде этого:
var elements = $("div.topMost").has(".find-me");
Ответ №7:
$(".find-me").map(function() {
return $(this).parents("div").last().get();
});