3

Possible Duplicate:
Javascript closure inside loops - simple practical example

I'm creating a table of statuses for a "dashboard" web page. Each status is in a state of "On" or "Off".

I'm trying to use the jQuery button/buttonset to have switch/toggle controls to allow the user to toggle the value of a status. I create the table and buttons dynamically as the result of an ajax database query.

I'm basically trying to fire off an ajax query when the user clicks on one of the buttons, but I'm struggling to assign the click event properly.

My first go-round had the final list value fire no matter what button was clicked.

Therefore, Aha! It's a standard "JavaScript closure" issue. (So I thought...)

Further playing around with it has yielded nothing, and I don't really understand the closure issue well enough to figure out why my technique is wrong.

Here's the code I want to call:

function SetStatus(item, status) {
    var params = '{itemName: "' + item + '", status: "' + status + '"}';
    $.ajax({
        type: "POST",
        url: "WebServices/Dashboard.asmx/SetItemStatus",
        data: params,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: StatusSet,
        error: ShowError
    });
}

Here's the current version of code I'm trying:

$(itemOnButton).click(
    function (_item) {
        SetStatus(_item, 'On');
    } (itemName)
);

The result is that immediately upon getting the results from the database (before they're even displayed), SetStatus fires for the last item with status == 'On'.

I know this is simple, and I'm still convinced it's a basic closure issue, but I'm banging my head against the wall! Thanks for any help!

Community
  • 1
  • 1
mbm29414
  • 11,558
  • 6
  • 56
  • 87

1 Answers1

6
$(itemOnButton).click(
    function (_item) {
        SetStatus(_item, 'On');
    } (itemName)
);

Currently you are fireing your 'closure' function when assinging it to click. Try

$(itemOnButton).click(
    function (ev) { 
        // this is the clicked element
        // ev is the event object

        // how do you get the name?
        // var itemName = $(this).attr("name");

        SetStatus(itemName, 'On');
    }
);

You could also do

$(itemOnButton).click(
    function (_item) {
        return function (ev) {
            SetStatus(_item, 'On');
        };
    } (itemName)
);

Now it fires like you did, but it doesn't execute immediate, instead it returns the event handling function for click.

The returned event handling function is now the closure for _item. The anonymous function is the scope for _item, set to itemName by argument.

metadings
  • 3,798
  • 2
  • 28
  • 37
  • Your first example got rid of the automatic clicking, but still had only the last item passed in, no matter the button. The second example is what got the page working. Thanks! – mbm29414 Nov 09 '12 at 17:03
  • You're welcome. Read also [this very good answer](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) on stackoverflow. – metadings Nov 09 '12 at 17:05