Using jQuery is there a way to find the farthest (deepest, or most nested) child element?

后端 未结 5 738
南笙
南笙 2020-12-11 11:25

If I have a set of elements:

Text 1
相关标签:
5条回答
  • 2020-12-11 11:57

    I think this will work for you.

    var deepestLevel = 0;
    var deepestLevelText = "";
    
    function findDeepNested(element, currentLevel) {
        if ((element.children().length == 0) && (deepestLevel < currentLevel)) {
            // No children and current level is deeper than previous most nested level
            deepestLevelText="<li>" + element.text() + "</li>";
        }
        else { // there are children, keep diving
            element.children().each( function () {
                findDeepNested($(this), currentLevel + 1);
            });
        }
    }
    
    $(".start").each( function () {
        deepestLevel = 0;
        deepestLevelText = "";
        findDeepNested($(this), 0);
        $("#results").append(deepestLevelText);
    });
    

    Fiddle

    0 讨论(0)
  • 2020-12-11 11:59

    Another method(possibly not so fast) with minimal lines of code could be as follows:

    var all_matched_elements = $(":contains('" + text_to_search + "')");
    var all_parent_elements = $(all_matched_elements).parents();
    var all_deepest_matches = $(all_matched_elements).not(all_parent_elements);
    

    This method is especially useful if your text is inside an element that also has other children elements as follows:

    <div class="start">
        <div>
            <div>Text 1<span>Alpha Beta Gamma</span></div>
        </div>
    </div>
    

    However, the above code would not work for a DOM that looks like following:

    <div class="start">
            <div>
                <div id="zzz">search-text
                    <div id="aaa">search-text</div>
                </div>  
            </div>
     </div>
    

    In above case, it would only select inner-most with id "#aaa". It would drop id "#zzz". If one wants to also choose with id "#zzz" then code at the start has to be modified to drop elements from "all_parent_elements" whose direct text also matches search text.

    0 讨论(0)
  • 2020-12-11 12:02

    You need to use the :last filter

    $('.start').find(':last');
    

    Working fiddle: http://jsfiddle.net/BmEzd/1/

    0 讨论(0)
  • 2020-12-11 12:03

    Here's an implementation that uses a treeWalk function I had written earlier and then wraps it in a jquery method that finds the deepest descendant of each item in the passed in jQuery object and returns a new jQuery object containing those nodes.

    A solution with recursion and lots of jQuery can be done with lots less code, but it will likely be slower. This is based on a generic native JS tree walk function that walks a tree.

    Working demo with more complicated HTML test case than the OP's HTML: http://jsfiddle.net/jfriend00/8tC3a/

    $.fn.findDeepest = function() {
        var results = [];
        this.each(function() {
            var deepLevel = 0;
            var deepNode = this;
            treeWalkFast(this, function(node, level) {
                if (level > deepLevel) {
                    deepLevel = level;
                    deepNode = node;
                }
            });
            results.push(deepNode);
        });
        return this.pushStack(results);
    };
    
    var treeWalkFast = (function() {
        // create closure for constants
        var skipTags = {"SCRIPT": true, "IFRAME": true, "OBJECT": true, "EMBED": true};
        return function(parent, fn, allNodes) {
            var node = parent.firstChild, nextNode;
            var level = 1;
            while (node && node != parent) {
                if (allNodes || node.nodeType === 1) {
                    if (fn(node, level) === false) {
                        return(false);
                    }
                }
                // if it's an element &&
                //    has children &&
                //    has a tagname && is not in the skipTags list
                //  then, we can enumerate children
                if (node.nodeType === 1 && node.firstChild && !(node.tagName && skipTags[node.tagName])) {                
                    node = node.firstChild;
                    ++level;
                } else if (node.nextSibling) {
                    node = node.nextSibling;
                } else {
                    // no child and no nextsibling
                    // find parent that has a nextSibling
                    --level;
                    while ((node = node.parentNode) != parent) {
                        if (node.nextSibling) {
                            node = node.nextSibling;
                            break;
                        }
                        --level;
                    }
                }
            }
        }
    })();
    
    var deeps = $(".start").findDeepest();
    
    deeps.each(function(i,v){
        $("#results").append(
            $("<li>").html($(v).prop("tagName") + " " + $(v).html())
        );
    });
    
    0 讨论(0)
  • 2020-12-11 12:13
    <script type="text/javascript">
        function findFarthestNode(node)
        {
            if(node.parent().length && node.parent().prop("tagName") != "BODY")
                return findFarthestNode(node.parent());
            return node;
        }
        jQuery(document).ready(function() {
            node = jQuery("span");
            farthest = findFarthestNode(node);
            console.log(farthest);
        });
    </script>
    
    0 讨论(0)
提交回复
热议问题