Jquery multiple click binding not working correctly
I seem to have a problem making copies of the template and binding the .click () method to them. 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 () { alert(x); });
if (list == undefined)
list = temp;
else
list = list.append(temp.contents());
}
$("#test_div2").append(list);
}
The problem I see with is that no matter what element the user clicks on, it always fires an alert (2), even when you click on the first few elements.
How can I get this to work?
Edit: I made a very simple example that should make the problem much clearer. No matter which item you click on, it always displays an alert box with the number 2 on it.
a source to share
Correct me if I'm wrong, .valueOf()
in JS it returns a primitive boolean object value .....
it won't happen ShowObject(5,'T');
...ShowObject(objectVal.valueOf(), 'T');
Why not use it objects[x].Value
directly?ShowObject(objects[x].Value, 'T');
WOOOOOSSSHHHH!
after deep searching ... I found a solution ...
because it's a closure, it won't actually work ...
here's the solution,
temp.find('a').bind('click', {testVal: x},function (e) {
alert(e.data.testVal);
return false;
});
for a better explanation, read this ... in the middle of the page where it says Passing event data a
quick demo of the above code
a source to share
I think your question comes from a misunderstanding of scopes in JavaScript. (My apologies if I am wrong.)
function () {
for (...) {
var foo = ...;
$('<div>').click(function () { alert(foo); }).appendTo(...);
}
}
In JavaScript, functions only create a new scope (usually called a closure ).
So every loop of the loop for
will know the same foo
as its scope is that function
and not for
. This also applies to defined events. At the end of the cycle, everyone click
will know the same ones foo
and know that this is the last value it was assigned.
To work around this, either create an inner closure with an instantly executable 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 problem, I would go with the latter (note the changes objects[x]
on 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());
});
a source to share