skip to Main Content

I have an unknown, complex DOM structure and searching for the max number of nested elements with a given class (.bar).

I need a (recursive) method which returns the max levels of nested elements. In this example it should be 3

<div class="root">
    <div class="foo"></div>
    <div class="foo">
        <div class="bar"> <!-- #1 -->
            <div class="foo"></div>
            <div class="foo"></div>
        </div>
    </div>
    <div class="foo"></div>
    <div class="foo">
        <div class="bar"> <!-- #1 -->
            <div class="foo"></div>
            <div class="foo"></div>
            <div class="foo">
                <div class="bar"> <!-- #2 -->
                    <div class="foo"></div>
                    <div class="foo"></div>
                    <div class="foo">
                        <div class="bar"> <!-- #3 --> <!-- << this is the "most nested element" -->
                            <div class="foo"></div>
                            <div class="foo"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="foo"></div>
    <div class="foo">
        <div class="bar"> <!-- #1 -->
            <div class="foo"></div>
            <div class="foo"></div>
            <div class="foo"></div>
        </div>
    </div>
    <div class="bar"> <!-- #1 -->
        <div class="foo"></div>
        <div class="foo"></div>
        <div class="foo">
            <div class="bar"> <!-- #2 -->
                <div class="foo"></div>
                <div class="foo"></div>
                <div class="foo"></div>
            </div>
        </div>
    </div>
</div>

So my approach would be to use querySelectorAll( '.bar' ):

let d = 0;

function my_counter(root, depth = 0) {
    //get all items
    let items = root.querySelectorAll('.bar');

    d = Math.max(d, depth);

    //for each item check
    items.forEach((item) => {
        my_counter(item, depth + 1);
    });

    return d;
}

This approach looks dirty and resource intensive to me so I look for a better. Also if the count change as elements can get removed Math.max doesn’t respect that.

2

Answers


  1. you can directly return and update the depth value in your recursive function. Additionally, since you’re only interested in the maximum depth of .bar elements, you don’t need to use querySelectorAll(‘.bar’) multiple times. Here’s a cleaner version of your code:

    function findMaxNestedDepth(root, depth = 0) {
        let maxDepth = depth;
    
        // Get all .bar elements within the current root
        const barElements = root.querySelectorAll('.bar');
    
        // Iterate through each .bar element and recursively check their nested depth
        barElements.forEach((barElement) => {
            const nestedDepth = findMaxNestedDepth(barElement, depth + 1);
            maxDepth = Math.max(maxDepth, nestedDepth);
        });
    
        return maxDepth;
    }
    
    const rootElement = document.querySelector('.root');
    const maxDepth = findMaxNestedDepth(rootElement);
    console.log('Max Nested Depth:', maxDepth);
    
    Login or Signup to reply.
  2. Here is a recursive function that reduces the queried child elements by a specified selector.

    const findMaxDepth = (root, selector, depth = 0) =>
      [...root.querySelectorAll(selector)].reduce((maxDepth, children) =>
        Math.max(maxDepth, findMaxDepth(children, selector, depth + 1)), depth);
    
    const root = document.querySelector('.root');
    
    console.log("Max depth of '.bar':", findMaxDepth(root, '.bar')); // 3
    console.log("Max depth of '.foo':", findMaxDepth(root, '.foo')); // 4
    <div class="root">
      <div class="foo"></div>
      <div class="foo">
        <div class="bar">
          <!-- #1 -->
          <div class="foo"></div>
          <div class="foo"></div>
        </div>
      </div>
      <div class="foo"></div>
      <div class="foo">
        <div class="bar">
          <!-- #1 -->
          <div class="foo"></div>
          <div class="foo"></div>
          <div class="foo">
            <div class="bar">
              <!-- #2 -->
              <div class="foo"></div>
              <div class="foo"></div>
              <div class="foo">
                <div class="bar">
                  <!-- #3 -->
                  <!-- << this is the "most nested element" -->
                  <div class="foo"></div>
                  <div class="foo"></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="foo"></div>
      <div class="foo">
        <div class="bar">
          <!-- #1 -->
          <div class="foo"></div>
          <div class="foo"></div>
          <div class="foo"></div>
        </div>
      </div>
      <div class="bar">
        <!-- #1 -->
        <div class="foo"></div>
        <div class="foo"></div>
        <div class="foo">
          <div class="bar">
            <!-- #2 -->
            <div class="foo"></div>
            <div class="foo"></div>
            <div class="foo"></div>
          </div>
        </div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search