jQuery: find() children until a certain threshold element is encountered

前端 未结 4 1245
不思量自难忘°
不思量自难忘° 2021-02-19 17:59

I have a nested table structure like

   
相关标签:
4条回答
  • 2021-02-19 18:34

    I had a similar issue in this other question. I ended up finally figuring out a plugin on my own after going back and forth with some people trying to think of a find selector.

    USAGE : 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;
    }
    

    (Condensed Version):

    $.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;
    }
    
    0 讨论(0)
  • 2021-02-19 18:36

    Update: Let's have another take at this.

    Basically, you want to match all the <input> elements that are descendants of #first and that are not children of <td> elements nested more than one level deep under #first.

    (I'm not sure about that last under #first part, but implementing it allows us to support <td> elements above #first in the ancestor chain.)

    Technically, the following selector alone should fulfill your requirements:

    var inputs = $("#first td:not(#first td td) > input");
    

    If this does not work in your browser (Sizzle should be up to the task I think, but complex selectors like :not() are always tricky), you can delegate the processing to jQuery methods:

    var inputs = $("#first td").not("#first td td").children("input");
    

    Original answer follows:

    You can use not() to exclude <input> elements that have more than one <td> ancestor:

    var firstLevelCells = $("#first").find("input").not("td td input");
    
    0 讨论(0)
  • 2021-02-19 18:38

    I had a similar issue and was still challenged to do something without an extension loop or having the exact structure of the DOM. In my case I had already a reference to the element '#first' which if you don't we could get it for example with an each (even if it is only one object). The trick is to go back up the tree with parentsuntil and stop at your top element to see if there is any intermediate element satisfying the conditionn.

    Using the shorthand lambda notation for the functions (as you can write in typescript) this would lead to this:

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

    It might not be the most efficient way (as you first select everything to then throw away elements by mounting up the DOM-tree again, but it is compact and fairly generic.

    0 讨论(0)
  • 2021-02-19 18:43

    eh, i have a better idea..

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

    this may or may not be fast enough for you. it depends on your DOM which you do not want to talk about ;)

    if its slow, just write the code for your algorithm by hand. There isnt a selector shortcut.

    0 讨论(0)
提交回复
热议问题