jQuery:find()子项,直到遇到某个阈值元素

时间:2012-11-09 09:42:00

标签: jquery

我有一个像

这样的嵌套表结构
   <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发现直到问题。他们有答案,但似乎他们没有填写最后的标准

4 个答案:

答案 0 :(得分:5)

我在this other question中遇到了类似的问题。我最后在与一些人试图想到找到选择器的情况来回走动时最终找到了一个插件。

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

答案 1 :(得分:3)

  

更新:让我们再考虑一下。

基本上,您希望匹配<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");

答案 2 :(得分:2)

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

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

这可能或者可能不够快。这取决于您不想谈论的DOM;)

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

答案 3 :(得分:1)

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

对函数使用简写的lambda表示法(正如你可以在typescript中编写的那样),这将导致:

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

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