1

Okay this one's starting to freak me out: I have several div containers within the class "tooltipBox", but with different contents. In my little script, I try to store an array of all those divs in a variable, like so:

var agents = $( ".tooltipBox" );

However, when I want to use that array now, it's undefined. When I test the selector on its own (like simply by alert()-ing it), it does work. What's the problem here?

This is where the selector is used:

    $( "#runSimBtn" ).click(function runSimulation() {
        $( "#lContent h2" ).text("Simulation in progress...");

        var agents = $( "div.tooltipBox" );
        var falloutTimes = $( ".rFO" );

        var i, j = 0;

        for(i = 0, j = 0; i < agents.length, j < falloutTimes.length; i++, j++) {
            var ttl = falloutTimes[j].value;

            if((ttl != undefined) && (ttl != 999)) {
                setTimeout(function() {
                    agents[i].animate({ backgroundColor: "#FF0000" }, 500);
                }, ttl*1000);
            } else {
                continue;
            }
        }
    });

Also tried the selector in the browser-console (Firefox) and also there I can select the div, but as soon as I want to store the selection (even of a single div) into a variable, it returns undefined.

Thanks in advance...

10
  • can you show your code? Commented Mar 13, 2014 at 3:32
  • Use console.log(agents); to see the result in browser's console and please show your code how are you using agents Commented Mar 13, 2014 at 3:32
  • Smells like a scope-related issue. agents should be a jQuery object. even for an empty collection. It can't be Commented Mar 13, 2014 at 3:34
  • Could you provide example code that includes the child <div> elements and the selector that works? Commented Mar 13, 2014 at 3:34
  • added the code and what I found using the console, sry Commented Mar 13, 2014 at 3:39

3 Answers 3

2

As I pointed out in the comments, it is a problem with using closure variables in a loop.

Try

$("#runSimBtn").click(function runSimulation() {
    $("#lContent h2").text("Simulation in progress...");

    var agents = $("div.tooltipBox");
    var falloutTimes = $(".rFO");

    var i, j = 0;

    for (i = 0, j = 0; i < agents.length, j < falloutTimes.length; i++, j++) {
        var ttl = falloutTimes[j].value;

        if ((ttl != undefined) && (ttl != 999)) {
            (function (i, ttl) {
                setTimeout(function () {
                    agents[i].animate({
                        backgroundColor: "#FF0000"
                    }, 500);
                }, ttl * 1000);
            })(i, ttl);
        } else {
            continue;
        }
    }
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer - after also reading up here I think I got it now - due to the time the setTimout takes to execute and the rest of the code not waiting for it to finish, the loop runs through before the code within the setTimout() is executed. This is why I need closures, so that I can pass i to my function before its value changes again - did I get this right now? I'm rather new to this concept as you might've already noticed...
@slagjoeyoco yes... it creates a private copy of i for each iteration of the loop so every setTimeout() will gets its own value of i
Alright glad I finally got this now - thank you very much for your help!
0

I think what is going on here is that when the setTimeout calls the function after 1 second, this function where agents is declared has already completed and the agents variable is no longer accessible.

 $( "#runSimBtn" ).click(function runSimulation() {
        $( "#lContent h2" ).text("Simulation in progress...");

        var agents = $( "div.tooltipBox" );
        var falloutTimes = $( ".rFO" );
        var timeoutFunction = function(agent){
            agent.animate({ backgroundColor: "#FF0000" }, 500);
        }

        var i, j = 0;

        for(i = 0, j = 0; i < agents.length, j < falloutTimes.length; i++, j++) {
            var ttl = falloutTimes[j].value;

            if((ttl != undefined) && (ttl != 999)) {
                setTimeout(timeoutFunction(agents[i]), ttl*1000);
            } else {
                continue;
            }
        }
    });

Comments

0

as far as storing div selector in a variable is a concern, it works for me:

<div class="aClass">div 1</div>
<div class="aClass">div 2</div>

and jQuery:

var agents = $("div.aClass");
$(agents).each(function(key, val) {
    alert($(val).text());
});

will alert div 1 and div 2

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.