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.
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.
Share Improve this question asked Sep 12, 2011 at 12:23 Michael Giovanni PumoMichael Giovanni Pumo 14.8k18 gold badges99 silver badges145 bronze badges 4- 1 is this called when the dom is ready? – Daniel A. White Commented Sep 12, 2011 at 12:26
- It only appears to run once for me: jsfiddle/UBVkn Might there there be something external to the provided script that might be calling it twice? – Paul Butcher Commented Sep 12, 2011 at 12:31
- I checked it with jQuery 1.6.2, it runs at once – Anatoly Commented Sep 12, 2011 at 12:31
- Thanks guys - I was mistakenly calling it twice via a dodgy callback function - my fault. Thanks for taking a look anyhow. – Michael Giovanni Pumo Commented Sep 12, 2011 at 13:39
3 Answers
Reset to default 3Check 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.
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./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>
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 */
});