开发者

Jquery click bindings are not working correctly when binding multiple copies

I seem to have an issue when creating copies of a template and tying the .click() method to them properly. Take the following javascript for example:

function TestMethod() {
    var test = Array();
    test[0] = 0;
    test[1] = 1;
    test[2] = 2;

    // Insert link into the page
    $("#test_div").html("<a href=\"#\"></a><br>");
    var list;
    for (x = 0; x < test.length; x++) {
        var temp = $("#test_div").clone();
        temp.find('a').html("Item #" + test[x]);
        temp.click(function () { a开发者_如何学JAVAlert(x); });

        if (list == undefined)
            list = temp;
        else
            list = list.append(temp.contents());
    }
    $("#test_div2").append(list);
 }

The problem I am seeing with this is that no matter which item the user clicks on, it always runs alert(2), even when you click on the first few items.

How can I get this to work?

Edit: I have made a very simple example that should show the problem much clearer. No matter what item you click on, it always shows an alert box with the number 2 on it.


Correct me if I'm wrong, .valueOf() in JS returns the primitive value of a Boolean object.....

this would not happen ShowObject(5,'T');... ShowObject(objectVal.valueOf(), 'T');

why not use objects[x].Value directly? ShowObject(objects[x].Value, 'T');

WOOOOOSSSHHHH!

after searching deeply... I found a solution...

because it's a closure, it won't really work that way...
here's a solution,

temp.find('a').bind('click', {testVal: x},function (e) { 
   alert(e.data.testVal);
   return false;
});

for best explanation, please read this... in the middle part of the page where it says Passing Event Data
a quick demo of above code


I think your issue arises from a misunderstanding of scopes in JavaScript. (My apologies if I'm wrong.)

function () {
    for (...) {
        var foo = ...;

        $('<div>').click(function () { alert(foo); }).appendTo(...);
    }
}

In JavaScript, only functions create a new scope (commonly referred to as a closure).

So, every round of the for loop will know the same foo, since its scope is the function, not the for. This also applies to the events being defined. By the end of looping, every click will know the same foo and know it to be the last value it was assigned.

To get around this, either create an inner closure with an immediately-executing, anonymous function:

function () {
    for (...) {
        (function (foo) {
            $('<div>').click(function () { alert(foo); }).appendTo(...);
        })(...);
    }
}

Or, using a callback-based function, such as jQuery.each:

function () {
    $.each(..., function (i, foo) {
        $('<div>').click(function () { alert(foo); }).appendTo(...);
    });
}

For your issue, I'd go with the latter (note the changes of objects[x] to just object):

var list;
jQuery.each(data.objects, function (x, object) {

    // Clone the object list item template
    var item = $("#object_item_list_template").clone();

    // Setup the click action and inner text for the link tag in the template
    var objectVal = object.Value;
    item.find('a').click(function () { ShowObject(objectVal.valueOf(), 'T'); }).html(object.Text);

    // add the html to the list
    if (list == undefined)
        list = item;
    else
        list.append(item.contents());
});
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜