Q:

jQuery: Events being bound to wrong elements in loop

I have the strangest thing going on here which I'm sure there's a perfectly rational answer to. I'm using jQuery which frankly I haven't used to any substantial extent, so I'm guessing this is my own newbie-ism at work.
I am sending a settings-object to a function. This settings-object contains a struct by the name of "functions". This "functions"-object is a struct where the jQuery identifiers are keys, and the values are the callback functions.
Then, in the target function (to which the settings-object gets sent), I iterate through the settings.functions object to bind each function to each respective target.
However, the $button.click() event always sets every control to the last of the settings.functions functions.
So, if I have 2 buttons, "Delete" and "Edit", and I configure the settings object so that each will get their own, respective function... then for reasons that I'm trying to find, both buttons will receive the "Edit" function. Testing has shown that both buttons always get the last function in the settings.functions struct, no matter the key.
See "this.init = function..." code for the centre of weirdness. (snippet in middle)
The reason I'm trying to do it this way, is because in the call-back functions (configured in settings.functions), I need access to the $resource element from within $resources.each() clause. So in other words, from within the library function, I need to send the $resource object back to the callbacks, wherever they be defined.
Here's the portion which calls the function:

$(document).ready(function() {

    var settings = {
        functions: {
            ".but-act-delete": function($row) {
                if (confirm("Are you sure you want to delete this resource? This action cannot be undone!")) {
                    /* Nevermind this
                    $page_action.val("resource-delete");
                    $resource_id.val($row.attr("resource_id"));
                    $page_form.submit();
                    */
                }
            },
            ".but-act-edit": function($row) {
                window.location = "admin-resource-edit.php?resource_id=" + $row.attr("resource_id");
            }
        }
    };

    var supertable = new SuperTable();
    supertable.init(settings);
});

Here's the library function:

this.init = function(settings)
{
    var $resources = $("td.act");
    $resources.each(function(index, resource)
    {
        var $resource = $(resource);

        var button_class;
        for (button_class in settings.functions)
        {
            var $button = $resource.find(button_class);

            // This accurately shows ".but-act-edit" or ".but-act-delete"
            alert(button_class);

            $button.click(function()
            {
                // This ALWAYS shows ".but-act-edit"
                alert(button_class);

                // Find the proper callback.
                var func = settings.functions[button_class];

                // Call the call-back with the required element $resource.
                func($resource);
            });
        }
    });
}

Here is the HTML in question.

<td class="act" resource_id="<?php print $resource_id; ?>">
    <input type="button" class="but-act-edit" />
    <input type="button" class="but-act-delete" />
</td>

It appears that $button.click() assigns the event handler to all buttons every time, not just the one that it finds with $resource.find(button_class), which returns only one input each time (as it should).
Any help deeply appreciated. Especially if there's a way to make what I'm doing unnecessary.
Thanks in advance.

A:

This is the classic "using an outer loop variable in a callback" problem.
Your button_class variable changes in the loop, but isn't bound correctly in the callback, so its final value will always be used.
The simplest fix in this case is to use:
$.each(settings.functions, function(button_class, func) {
})

instead of:
for (button_class in settings.functions)

this will ensure that your button_class variable is correctly bound for each possible value.

