问题 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>秒。

所以我需要一个jQuery技巧

  • find() 某个元素的所有子元素

  • 将在DOM树中下降n级

  • 但如果某个元素会停止下降(<table>遇到,所以选择器不选择嵌套表的输入(将单独处理)

  • 可以有任意数量的嵌套 <table> 级别,所以无论父母多少,解决方案都应该有效 <table> 或者孩子 <table> 在$(“#first”)范围内遇到 <td> 或任何其他 <td>

我检查了其他jQuery发现直到问题。他们有答案,但似乎他们没有填写最后的标准


6751
2017-11-09 09:41


起源

你觉得你的桌子结构好吗? - Priyank Patel
结构是否使用完成 <table> 或其他一些因素自然与问题无关 - Mikko Ohtamaa
我问是因为你的 input 标签也没有很好地形成 tr 不见了。 - Priyank Patel
@freebird我认为它只是一个匆忙抛出的代码示例 - mkoryak
@freebird:不相关 - Mikko Ohtamaa


答案:


我有类似的问题 这个问题。我最终在与一些人试图想到一个找到选择器来回来之后终于搞清楚了一个插件。

用法: 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;
}

5
2018-06-16 19:00





更新: 让我们再看看。

基本上,你想要匹配所有 <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");

原始答案如下:

您可以使用 不() 排除 <input> 具有多个元素的元素 <td> 祖先:

var firstLevelCells = $("#first").find("input").not("td td input");

3
2017-11-09 10:01



我不明白;这不是必须的 $("#first").find("input").not("td td input")? - lnrbob
你是绝对正确的,我失去了沿途匹配的实际元素。答案相应更新,感谢单挑:) - Frédéric Hamidi


呃,我有一个更好的主意..

var badTable = "table.bad"; //the one you want to avoid
var $goodInputs = $("#first").find('input').filter(function() {
    return $(this).closest(badTable).length == 0;
});

这对你来说可能是也可能不够快。这取决于你不想谈论的DOM;)

如果它很慢,只需手动编写算法代码即可。没有选择器快捷方式。


2
2017-11-09 09:45



正如问题所述,您无法从上下文中识别哪个表“不好”,但它必须适用于任何嵌套级别而没有特殊的类标记 - Mikko Ohtamaa


我有一个类似的问题,仍然面临着没有扩展循环或具有DOM的确切结构的事情的挑战。在我的情况下,我已经引用了元素'#first',如果你不这样做,我们就可以得到它,例如每个(即使它只是一个对象)。诀窍是使用parentsuntil返回树,并停在顶部元素以查看是否有任何满足条件的中间元素。

对函数使用简写lambda表示法(因为你可以在typescript中编写),这将导致:

$('#first').each((idx, f) => $(f).find('input').filter((idx2, inp) => $(inp).parentsUntil(f, 'table').length == 0)

它可能不是最有效的方式(因为你首先选择所有内容然后通过再次安装DOM树来丢弃元素,但它是紧凑的并且相当通用。


1
2017-07-05 09:30