Reputation: 14774
I have a loop that runs through first level LI items of a menu. I want to detect the end of the loop, however, the print out I get seems to run twice.
Here's my JS:
var numNavItems = $("#navigation > li").size() - 1;
$("#navigation > li").each(function(i) {
$(this).delay( i * 300 ).animate({ opacity: 1 }, 300);
// This runs twice
$("#content").append("<p>Loop number: " + i + " out of " + numNavItems + "</p>");
if( i == numNavItems) {
//$("#navigation li").css({ "opacity" : 1 });
//alert("End! Number of items = " + numNavItems + ". Last item = " + i );
}
});
So, my logic fires twice. Not sure why, could it be my nested list?
Here's the HTML...
<ul id="navigation">
<li class="selected"><a href="./">Home</a></li>
<li><a href="./portfolio/">Portfolio</a>
<ul>
<li><a href="#">Cosmos</a></li>
<li><a href="#">Remora</a></li>
<li><a href="#">Caspian</a></li>
<li><a href="#">Megaway</a></li>
</ul>
</li>
<li><a href="./philosophy/">Philosophy</a></li>
<li><a href="./about/">About</a></li>
<li><a href="./contact/">Contact</a></li>
</ul>
I used the ">" to find only the first level LI's.
It prints:
Loop number: 0 out of 4
Loop number: 1 out of 4
Loop number: 2 out of 4
Loop number: 3 out of 4
Loop number: 4 out of 4
Loop number: 0 out of 4
Loop number: 1 out of 4
Loop number: 2 out of 4
Loop number: 3 out of 4
Loop number: 4 out of 4
Many thanks for your help. Michael.
Upvotes: 1
Views: 10517
Reputation: 71
I solved this problem by using the :visible
pseudo class of the element, because apparently .each
loops over every element regardless of whether it is hidden or visible.
$('li:visible').each(function(){
/* it will loop on the elements which are visible */
});
Upvotes: 0
Reputation: 12302
Check this fiddle. It works ok on every browser.
Probably you are calling it twice somewhere, or you have duplicated code.
Note that it's not a matter of calling it on DOM ready or page load, it won't change anything. It's also not a problem of having two elements with the same ID "content" (the output would be 0 of 4, 0 of 4, 1 of 4, 1 of 4 ...), and anyway it simply ignore the second div.
Either check for duplicated HTML or JS code, or a function called two times.
You should put your loop in a function and add console.log('menu loop function');
at the beginning of your function. See how many times it's being called.
Upvotes: 3
Reputation: 21279
I simply suspect that your code is called twice possibly because of a double binding on a button or something similar. I just tried to reproduce your issue and I got only 5 lines. It "may" be possible that appending code directly to your current page would double the results. I would suggest to replace $("#content").append(…) by console.log(…) (under a webkit browser) or alert(…) and see if you still get your double results. (if this is the case then "appending" mess your "each" loop, else you are just calling twice your function). Here is my dummy test snippet:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
var numNavItems = $("#navigation > li").size() - 1;
$("#navigation > li").each(function(i) {
$(this).delay( i * 300 ).animate({ opacity: 1 }, 300);
// This runs twice
console.log("<p>Loop number: " + i + " out of " + numNavItems + "</p>");
if( i == numNavItems) {
//$("#navigation li").css({ "opacity" : 1 });
// alert("End! Number of items = " + numNavItems + ". Last item = " + i );
}
});
});
</script>
</head>
<body>
<ul id="navigation">
<li class="selected"><a href="./">Home</a></li>
<li><a href="./portfolio/">Portfolio</a>
<ul>
<li><a href="#">Cosmos</a></li>
<li><a href="#">Remora</a></li>
<li><a href="#">Caspian</a></li>
<li><a href="#">Megaway</a></li>
</ul>
</li>
<li><a href="./philosophy/">Philosophy</a></li>
<li><a href="./about/">About</a></li>
<li><a href="./contact/">Contact</a></li>
</ul>
</body>
</html>
Upvotes: 2