Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find nesting depth

Tags:

jquery

php

So, take this html for example:

<ul>
    <li>
        <a href="#">Test</a>

        <ul>
            <li><a href="#">Test</a></li>
            <li><a href="#">Test</a></li>
            <li><a href="#">Test</a></li>
            <li><a href="#">Test</a></li>
        </ul>
    </li>
    <li>
        <a href="#">Test</a>

        <ul>
            <li><a href="#">Test</a></li>
            <li>
                <a href="#">Test</a>

                <ul>
                    <li><a href="#">Test</a></li>
                    <li><a href="#">Test</a></li>
                    <li><a href="#">Test</a></li>
                    <li><a href="#">Test</a></li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

I want to find out the maximum depth of this structure, in this example it would be 3, as the structure goes 3 levels down. But the structure can have an arbitrary depth.

Either a javascript/jquery solution or a PHP based solution using the DOM extension would be fine. I really cant think of any nice way of doing this. Maybe there is an xpath expression that does exactly what I want?

EDIT: To clarify: Depth in this case is the maximum nesting of ul elements, in this case 3.

like image 307
Max Avatar asked Aug 24 '10 11:08

Max


People also ask

What is depth of nesting?

The nesting depth is the number of statement blocks that are nested due to the use of control structures (branches, loops). We will discuss the nesting depth at the level of a procedure (method). Implementations must not occur at other points. The maximum nesting depth is restricted to 256 by ABAP Compiler. Rule.

What is the maximum if nesting possible?

Nested IF limits In Excel 2007 - Excel 365, you can nest up to 64 IF functions. In older versions of Excel 2003 and lower, up to 7 nested IF functions can be used.

What nested parentheses?

Nested parentheses When you want to enclose a set of parentheses inside another set, most style guides recommend using square brackets for the inner element.


3 Answers

If you didn't want to have to specify the lowest selector, this will give you the maximum number of nest levels:

var n = 0

$('ul').each(function(i){ 
    if (($(this).parents('ul').length + 1) > n) { n = $(this).parents('ul').length + 1; }
});

Edit: the variable n contains the number of nest levels, so for the example above, 3.

like image 117
Andy Casey Avatar answered Oct 04 '22 20:10

Andy Casey


Even though you already accepted an answer, I'm going to throw this one out there since I think it will be more efficient.

Try it out: http://jsfiddle.net/3haSq/

Math.max.apply(null, $('ul:not(:has(ul))').map(function() {
    return $(this).parents('ul').length;
}).get()) + 1;
  • $('ul:not(:has(ul))') only concerns itself with <ul> elements that do not have a nested <ul>
  • .map().get() gives you an array of the quantities of their parent <ul> elements
  • The native Math.max() finds the maximum
  • Add +1 at the end to represent the <ul> that was originally selected.

EDIT:

The reason we're doing Math.max.apply() instead of Math.max() is pretty simple.

Normally Math.max() requires several int arguments, like this:

Math.max(12, 23, 34);  // results in `34`

This is fine as long as you know exactly how many arguments there will be beforehand. Not the situation here.

Normally the .apply() method is used to call a function but change the value this for that function call. The first parameter for .apply() is the new value of this. Here we're passing null because we really don't care what the value is.

The important part of .apply() that we care about is the second parameter that takes an Array of arguments that would normally be passed to the function. So taking the example above, we would do this:

Math.max.apply(null, [12,23,34]);  // Converts the Array to a list of arguments

So as you can see, this allows Math.max() to accept one Array of ints instead of several comma separated ints.

(There is a similar method called .call() which takes parameters in the same manner as the original function. As in:)

Math.max.call(null, 12,23,34);   // This version takes several arguments
                                 //     instead of one Array.
like image 37
user113716 Avatar answered Oct 04 '22 22:10

user113716


The "nice" way would be to count the parents of a specific element. Lets say, there was an anchor with the id == foobar, you could do

$('#foobar').parents.length - 1

that would return the number of parent nodes, which also would be the depth.

And the "ugly" way would be a recursive function which crawls through every element in your markup until there are no more child nodes.

like image 37
jAndy Avatar answered Oct 04 '22 21:10

jAndy