Reputation: 1755
I have this nested ul, which are parent -> child -> (grand)child levels.
How can I use jQuery to spot every level adding a class to it so that I can style each level differently?
would be something like:
I couldn't do it with CSS because it needs to work fine at least on IE 7
<ul class="lista-regioes">
<li class="cat-item cat-item-3 i-have-kids">
<a href="http://localhost/poraidemochila/site/?local-destino=brasil" title="Ver todos os posts arquivados em Brasil">Brasil</a>
<ul class="children">
<li class="cat-item cat-item-13">
<a href="#" title="#">Norte</a>
</li>
<li class="cat-item cat-item-4 i-have-kids">
<a href="#" title="#">Sul</a>
<ul class="children">
<li class="cat-item cat-item-5">
<a href="http://localhost/poraidemochila/site/?local-destino=parana" title="Ver todos os posts arquivados em Paraná">Paraná</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
the classes .cat-item
and .cat-item-#
are dynamically generated, so I can't use them in css
the class .i-have-kids
is added by the following js which I found here
$('li.cat-item:has(ul.children)').addClass('i-have-kids');
but it does not really work since it just looks for elements that have children, and do not separate by levels, as you can see in the markup.
Upvotes: 0
Views: 4169
Reputation: 6090
this.addClasses = function(parent, level) {
// add a class to all <li> elements on this level:
parent.children("li").addClass("cat-item-" + level);
// find any child <ul> elements and run this function on them,
// making sure to increment the level counter:
if (parent.children("li").children("ul").length) {
this.addClasses(parent.children("li").children("ul"), level + 1);
}
};
// start off by selecting only the top-level <ul> elements:
this.addClasses($("body > ul"), 1);
Upvotes: 3
Reputation: 14310
Actually you do not need to classes to style your menu, you can access the levels in css with the >
selector. That is the way I would probably do it.
But that is not the question, so I tried it in javascript. What you want is a recursive function.
Something that would work like this:
function addLevelClass($parent, level) {
// add a parent class to the ul
$parent.addClass('parent-'+level);
// fetch all the li's that are direct children of the ul
var $children = $parent.children('li');
// add a child class to the li
$children.addClass('child-'+level);
// loop trough each li
$children.each(function() {
// get the ul that is a direct child of the li
var $sublist = $(this).children('ul');
// if an ul was found
if ($sublist.length > 0) {
// add a class to the current li indicating there is a sub list
$(this).addClass('has-sublist');
// repeat the process for the sublist, but with the level one higher
// = recursive function call
addLevelClass($sublist, level+1);
}
});
}
// call the function to add level classes on the upper most ul
addLevelClass($('.list'), 1);
There are probably more efficient ways to do this (js is not my strongpoint), but as an example I think it should work fine. (Feel free to improve!)
I set up a small example here: http://jsfiddle.net/Pevara/UPN33/
Upvotes: 1
Reputation: 7784
Why not just do something like this: http://jsfiddle.net/Rpg88/
HTML
<ul>
<li><a href="#">link</a></li>
<li>
<a href="#">link</a>
<ul>
<li><a href="#">link</a></li>
<li>
<a href="#">link</a>
<ul>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</li>
<li><a href="#">link</a></li>
</ul>
</li>
<li><a href="#">link</a></li>
</ul>
CSS
ul a { color:red; }
ul ul a {color:orange;}
ul ul ul a {color:lime;}
Upvotes: 0