JQuery: find() до появления определенного порогового элемента
У меня есть вложенная структура таблицы, например
<table>
<td id="first">
<div class="wrapper">
<input name=1>
</div>
<input name=2>
<table>
<td id="second">
<input name=3>
У меня есть выбор jQuery $("#first")
. Я хотел бы пройти и find()
всех детей <input>s
в этом контексте <td>
, но не спускаться во вложенные <table>
s.
Мне нужен трюк jQuery, который
-
Будет ли find()
все дочерние элементы определенного элемента
-
Снизет n уровней вниз в дереве DOM
-
Но останавливается нисходящий, если встречается определенный элемент (<table>
), так что селектор не выбирает входы вложенных таблиц (которые будут обрабатываться отдельно)
-
Может быть любое количество вложенных уровней <table>
, поэтому решение должно работать независимо от того, сколько родительских <table>
или детей <table>
встречается в пределах $( "# first" ) <td>
или любой другой <td>
Я проверил другой поиск jQuery до вопросов. У них есть ответы, но похоже, что они не заполняют последние критерии.
Ответы
Ответ 1
У меня была аналогичная проблема в этом другом вопросе. В конце концов я окончательно выяснил плагин, когда я возвращался туда и обратно, и некоторые люди пытались найти селектор поиска.
ИСПОЛЬЗОВАНИЕ:
ExclusiveInputs = $('#first').findExclude('input','table');
// Find-like method which masks any descendant
// branches matching the Mask argument.
$.fn.findExclude = function( Selector, Mask, result){
// Default result to an empty jQuery object if not provided
var result = typeof result !== 'undefined' ?
result :
new jQuery();
// Iterate through all children, except those match Mask
this.children().each(function(){
var thisObject = jQuery( this );
if( thisObject.is( Selector ) )
result.push( this );
// Recursively seek children without Mask
if( !thisObject.is( Mask ) )
thisObject.findExclude( Selector, Mask, result );
});
return result;
}
(Конденсированная версия):
$.fn.findExclude = function( selector, mask, result )
{
var result = typeof result !== 'undefined' ? result : new jQuery();
this.children().each( function(){
var thisObject = jQuery( this );
if( thisObject.is( selector ) )
result.push( this );
if( !thisObject.is( mask ) )
thisObject.findExclude( selector, mask, result );
});
return result;
}
Ответ 2
Обновление: пусть у нас будет еще один вариант.
В принципе, вы хотите сопоставить все элементы <input>
, которые являются потомками #first
и которые не являются дочерними элементами элементов <td>
, вложенными более чем на один уровень под #first
.
(Я не уверен в этой последней части under #first
, но ее реализация позволяет нам поддерживать элементы <td>
выше #first
в цепочке предков.)
Технически, один из следующих селекторов должен выполнить ваши требования:
var inputs = $("#first td:not(#first td td) > input");
Если это не работает в вашем браузере (Sizzle должен соответствовать задаче, я думаю, но сложные селектора типа :not()
всегда сложны), вы можете делегировать обработку методам jQuery:
var inputs = $("#first td").not("#first td td").children("input");
Оригинальный ответ следует:
Вы можете использовать not(), чтобы исключить элементы <input>
, которые имеют более одного предка <td>
:
var firstLevelCells = $("#first").find("input").not("td td input");
Ответ 3
eh, у меня есть лучшая идея..
var badTable = "table.bad"; //the one you want to avoid
var $goodInputs = $("#first").find('input').filter(function() {
return $(this).closest(badTable).length == 0;
});
это может быть или не быть достаточно быстрым для вас. это зависит от вашего DOM, о котором вы не хотите говорить;)
если он медленный, просто напишите код для своего алгоритма вручную. Не существует ярлыка селектора.
Ответ 4
У меня была аналогичная проблема, и мне все еще приходилось делать что-то без цикла расширения или иметь точную структуру DOM. В моем случае у меня уже была ссылка на элемент "#first", который, если вы этого не сделаете, мы могли бы получить его, например, с каждым (даже если это только один объект). Хитрость заключается в том, чтобы вернуться к дереву с родителями и зайти в верхний элемент, чтобы увидеть, есть ли какой-либо промежуточный элемент, удовлетворяющий условию.
Используя сокращенную лямбда-нотацию для функций (как вы можете записать в typescript), это приведет к следующему:
$('#first').each((idx, f) => $(f).find('input').filter((idx2, inp) => $(inp).parentsUntil(f, 'table').length == 0)
Это может быть не самый эффективный способ (поскольку вы сначала выбираете все, чтобы затем выбрасывать элементы, снова создавая DOM-дерево, но он компактен и довольно общий.