1

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.

4
  • 1
    is this called when the dom is ready? Commented Sep 12, 2011 at 12:26
  • It only appears to run once for me: jsfiddle.net/UBVkn Might there there be something external to the provided script that might be calling it twice? Commented Sep 12, 2011 at 12:31
  • I checked it with jQuery 1.6.2, it runs at once 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. Commented Sep 12, 2011 at 13:39

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

ok, your answer didn't answer it directly, but it prompted me to check my code and I had this snippet in a function that was being executed in the callback function of an animate method. That seemed to be causing the issue - not sure why and probably far too complicated to show on here. However, thanks for the fresh eyes on this. I failed to mention the function wrap in my post so it didn't help that I wasn't more descriptive. Thanks once again.
No problem, always remember to track down program flow with the console.log() feature most browser have. You will get a direct insight of how your program is moving.
2

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>

1 Comment

Thanks for your help. You were right in that it was being called twice...a bug on my end. You weren't first so I can't give you the answer but I gave an upvote. Hope that's ok. Thanks again.
0

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 */

});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.