Bhuvan Rikka 웃 Bhuvan Rikka 웃 - 4 months ago 14
Javascript Question

Count of nested ul-li children over multiple levels doesn't always work

I was trying to show the count of all children elements over multiple nested levels beside all li elements which are dynamically generated.

Eg:

Z(8)
A(4)
B
C(2)
D
E
F(2)
G
H


What i am getting now:
Image

Code I used:
Sample HTML:

<li class="li-item">
<a href="#">B R(None)<span class="count-item" data-cnt="2">[2]</span></a>
<ul class="sub-parent-ul 237">
<li class="li-item">
<a href="#">B R(None)<span class="count-item" data-cnt="3">[3]</span></a>
<ul class="sub-parent-ul 246">
<li class="li-item">
<a href="#">Bhu Rik(None)<span class="count-item" data-cnt="3">[3]</span></a>
<ul class="sub-parent-ul 258">
<li class="li-item"><a href="#">Kai Hiwatari(None)<span class="count-item"></span></a></li>
<li class="li-item">
<a href="#">B R(None)<span class="count-item" data-cnt="2">[2]</span></a>
<ul class="sub-parent-ul 263">
<li class="li-item">
<a href="#">Bhu Rik(None)<span class="count-item" data-cnt="1">[1]</span></a>
<ul class="sub-parent-ul 264">
<li class="li-item"><a href="#">B R(None)<span class="count-item"></span></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>


JQuery:

$(".sub-parent-ul").each(function() {
// reusabilty
var context = $(this);

// count and populate
var count = context.children().length;

context.prev("a").children().text('['+count+']');
context.prev("a").children().attr('data-cnt',count);

});

$(".sub-parent-ul").each(function() {
var context2 = $(this);

// count and populate
var child_count = context2.children().length;
//check for inner ul
var sub_count = 0;
context2.children('li').each(function () {
var context3 = $(this);
if(context3.children('a').children('span').attr('data-cnt') !== undefined){
sub_count += +context3.children('a').children('span').attr('data-cnt');
}
if(context2.hasClass('G52436')){
console.log(context3.children('a').children('span').attr('data-cnt'));
console.log(context3.children('a').children('span').html());
console.log(context3.children('a').children('span'));
}
});
// final count and populate

var tot_count = child_count+sub_count;

context2.prev("a").children().text('['+tot_count+']');
context2.prev("a").children().attr('data-cnt',tot_count);
});


It works for some levels but not everywhere. I am not sure where i am wrong. What's weird is, I have kept some console logs in the calculation logic which will get the complete count of child count. The js object shows the perfect count which i need, but when i select the attr from the object, it shows different value and that is driving me nuts.

console log
As you can see in the screenshot, the object shows the count as 2 but the value of attribute returns 1. It looks like it is ignoring the data-cnt of immediate child and getting the next child's data-cnt in some cases.

Can someone please identify the issue?

Answer

The code doesn't seem to be using recursion, but rather tries to enumerate a set depth (context,context2,context3). One solution would be to use recursion within the function itself, the other is to use find instead of children to search multiple levels for all the children:

$(".sub-parent-ul").each(function() {
        var context = $(this),
            children = context.find('li'),
            count = children.length,
            a = context.prev("a").children();
        a.text('['+count+']');
        a.data('cnt', count);
});

Not entirely sure it's exactly according to your goal, but the outcome for the example html can be seen in this fiddle

Comments