开发者

Get the value of a variable in a loop

I have a loop that when it is called, creates a div with some form elements in them. Each div is based on a variable, "i" to give unique names to the fields and divs. Is there a way I can store what the variable was at the point of creating the div?

For example, div1 is created and everything in it has 1 (the variable) attached to the name. The form elements rely on each other and are called by ID. Problem is, when I create a new div and the variable (i) is changed to 2, the first set of form elements try to use 2 instead of 1.

Make sense?

Edit: Here's some code. It's pretty messy so I apologize in advance.

    var i = 0;

    $('a#add-product').click(function(event){
        i++;
        $('<div />').addClass('product').attr('id', 'product'+i)
            .append($('<h2><img src="<?php echo base_url();?>img/product.png" alt="" />Product '+i+'</h2>'))
            .append($('<div class="info-line"><label>Division</label><p><select id="selection-'+i+'" class="selection"><option value="">- Select a Division -</option><option value="abrasives">Abrasives</option><option value="tapes">Bonding, Surface Protection &amp; Tapes</option><option value="packaging">Packaging</option></select></p></div>'))
            .append($('<div class="info-line"><label>Category</label><p><select id="selectionresult-'+i+'" name="selectionresult-'+i+'" class="selectionresult"></select><span id="res开发者_高级运维ult-'+i+'" class="result">&nbsp;</span></p></div>'))
            .append($('<div class="info-line"><label>Product</label><p><select id="selectionresult2-'+i+'" name="selectionresult2-'+i+'" class="selectionresult2"></select><span id="result2-'+i+'" class="result2">&nbsp;</span></p></div>'))
            .append($('<a class="remove" href="#add-product" id="remove-product'+i+'"><img src="<?php echo base_url();?>img/remove-product.jpg" alt="" />Remove Product</a>'))
            .appendTo("#products");

            // START OF ADDITIONAL PRODUCT DROP DOWNS

                    $("#selectionresult-"+i).hide();
                    $("#selectionresult2-"+i).hide();

                    $("#selection-"+i).change( function() {

                        $(this).next(".selectionresult").hide();
                        $(this).next(".selectionresult2").hide();
                        $("#result-"+i).html('Retrieving ...');
                        $.ajax({
                            type: "POST",
                            data: "data=" + $(this).val(),
                            url: "<?php echo base_url();?>dropdown.php",
                            success: function(msg){
                                if (msg != ''){
                                    $("#selectionresult-"+i).html(msg).show();
                                    $("#result-"+i).html('');
                                }
                                else{
                                    $("#result-"+i).html('<em>No item result</em>');
                                }
                            }
                        });

                    });
                    $("#selectionresult-"+i).change( function() {
                        $(this).next(".selectionresult2").hide();
                        $("#result2-"+i).html('Retrieving ...');
                        $.ajax({
                            type: "POST",
                            data: "data=" + $(this).val(),
                            url: "<?php echo base_url();?>dropdown.php",
                            success: function(msg){
                                if (msg != ''){
                                    $("#selectionresult2-"+i).html(msg).show();
                                    $("#result2-"+i).html('');
                                }
                                else{
                                    $("#result2-"+i).html('<em>No item result</em>');
                                }
                            }
                        });
                    });
    });


You can place the code that needs to reference the correct version of i in a closure like this:

var i = 0;

$('a#add-product').click(function(event){
    i++;

    // Begin closure. When called (at the end of the closure) it receives
    //    the current value of "i". This value of "i" will be referenced
    //    throughout the closure as a local variable containing the value
    //    you expect, instead of the "shared" "i" variable outside the 
    //    closure.
    (function( i ) {

        // So basically we've created a new "scope" inside here. Now "i"
        //    is a separate local variable than the "i" variable ouside
        //    the closure. You could change the variable name by changing
        //    the parameter above. Like (function( my_i ) {...
        // If you did that, you would need to change the "i" in your .change()
        //    handlers to "my_i". The rest of them could stay the same, or you
        //    could change them. Either way would work.
        // This is because the .change() handlers are executed at a later time
        //    (and so are the AJAX callbacks) so they need to use the variable
        //    that is local to this closure.
        // The rest of the code, like $("#selectionresult-" + i) is executing
        //    immediately, so it could reference the "i" variable that is
        //    outside the closure, and still work properly.

        $('<div />').addClass('product').attr('id', 'product'+i)
            .append($('<h2><img src="<?php echo base_url();?>img/product.png" alt="" />Product '+i+'</h2>'))
            .append($('<div class="info-line"><label>Division</label><p><select id="selection-'+i+'" class="selection"><option value="">- Select a Division -</option><option value="abrasives">Abrasives</option><option value="tapes">Bonding, Surface Protection &amp; Tapes</option><option value="packaging">Packaging</option></select></p></div>'))
            .append($('<div class="info-line"><label>Category</label><p><select id="selectionresult-'+i+'" name="selectionresult-'+i+'" class="selectionresult"></select><span id="result-'+i+'" class="result">&nbsp;</span></p></div>'))
            .append($('<div class="info-line"><label>Product</label><p><select id="selectionresult2-'+i+'" name="selectionresult2-'+i+'" class="selectionresult2"></select><span id="result2-'+i+'" class="result2">&nbsp;</span></p></div>'))
            .append($('<a class="remove" href="#add-product" id="remove-product'+i+'"><img src="<?php echo base_url();?>img/remove-product.jpg" alt="" />Remove Product</a>'))
            .appendTo("#products");

        // START OF ADDITIONAL PRODUCT DROP DOWNS
        $("#selectionresult-" + i).hide();
        $("#selectionresult2-" + i).hide();

        $("#selection-" + i).change(function () {

            $(this).next(".selectionresult").hide();
            $(this).next(".selectionresult2").hide();
            $("#result-" + i).html('Retrieving ...');
            $.ajax({
                type: "POST",
                data: "data=" + $(this).val(),
                url: "<?php echo base_url();?>dropdown.php",
                success: function (msg) {
                    if (msg != '') {
                        $("#selectionresult-" + i).html(msg).show();
                        $("#result-" + i).html('');
                    }
                    else {
                        $("#result-" + i).html('<em>No item result</em>');
                    }
                }
            });

        });
        $("#selectionresult-" + i).change(function () {
            $(this).next(".selectionresult2").hide();
            $("#result2-" + i).html('Retrieving ...');
            $.ajax({
                type: "POST",
                data: "data=" + $(this).val(),
                url: "<?php echo base_url();?>dropdown.php",
                success: function (msg) {
                    if (msg != '') {
                        $("#selectionresult2-" + i).html(msg).show();
                        $("#result2-" + i).html('');
                    }
                    else {
                        $("#result2-" + i).html('<em>No item result</em>');
                    }
                }
            });
        });

     // End closure. Executes the closure function, passing in the
     //   current value of "i"
    })( i );
});

EDIT:

To explain what is happening, in javascript, variables passed to (or created in) a function body are local to that function, and they persist.

All I'm doing above is creating a function that accepts one parameter. Here I'll change the name of the parameter to perhaps make it more clear:

function( inner_i ) {
    // create your element with the new local variable "inner_i"
}

...but I'm also calling that function as soon as I create it:

(function( inner_i ) {
    // create your element with the new local variable "inner_i"
})( i )
//  ^------- call the function, passing in the "i" from your loop.

The syntax looks a little strange, but it is simply a way to call a function that you've just created.

It would be the same as doing:

function myNewFunction( inner_i ) {
    // creates your element with the new local variable "inner_i"
}

myNewFunction( i );  // Call the function we just created above, 
                     //   and pass the "i" from the loop into it


From what I can understand the elements in div1 refer to each other but not to the elements in div2. The question is, HOW do they refer to each other? If it is by events, for example a textbox's onchange event, then you can do the following:

var MAX = 10;
for (var i = 0; i < MAX; i++) {
    // Create textbox
    $("<input type='text'>").attr("name", "slave" + i);
    // Create a second textbox that, when changed, takes it's value,
    // makes it uppercase, and copies it to the first one
    $("<input type='text'>").attr("name", "master" + i)
    .change(
        (function(i) {
            function() {
                $("input[name=slave" + i + "]").text($(this).text());
            }
        })(i)
    );
}

What it does is creates a temporary scope that captures the value of i within itself:

        (function(i) {
            function() {
                // the value of i is frozen in time within here
            }
        })(i)


Actually, a simpler answer would be to store the integer as a value to each element you're creating. Saves you from messing with closures and is a lot more maintainable. Within your loop just do:

newElement.data("myIndex", i);

And to retrieve the index again:

newElement.data("myIndex");

Or, if within an event handler:

$(this).data("myIndex");


Use a separate variable to store the index in, using the loop to add to it.

Roughly speaking, the function with the loop (whether or not it calls another function with the index number or not is irrelevant) but this way you get the index value stored, and use your loops so there are no duplicates.

var uniqueIndex = 0;

function functionWithLoop(x)
{
    for (i=0; i<x; i++)
    {
        uniqueIndex++;
        createNewDivFunction(uniqueIndex);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜