Reputation: 37
i have a string objects of books which i have got from a JSON objects. This Book object has three Key value pairs, Title,Author and URL. I use a for loop to read each object and just put the title of the object as a button on the html page. But when the button is clicked i want the URL of the book to be alerted. As i read the objects i make Books objects and push it into an array for later use. but i am not able to Use .Click() method the URL is not right. Please see the code for better understanding. :-)
for (i = 0; i < 6; i++) //I know that there is only 65 Books..jsonString.books.lenght is not working.
{
var title = jsonString.books[i].title;
var classname = title.replace(/\s/g, "");
var author = jsonString.books[i].author;
var URL = jsonString.books[i].url;
var htmlString = '<div class="' + classname + '"><input type="button" value="' + title + '"></div>';
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
OneBook = new Book(author, title, URL);
arr.push(OneBook);
}
attachpoint is a reference in the html file that i got from
var attachpoint=document.querySelector('.buttonAttachPoint');
So in the above code the URL that i get on clicking is always the last object in the jsonString. this is happening coz of the for loop. So is there a way i can get to class name of the Div that has onclick or the title of the button so that i can get the URL from the array of objects i created? Or is there an easier way. Also could any one point out why "jsonString.books.lenght" is not working? Thanks in advance.:-) all the help much appreciated. :-)
Upvotes: 0
Views: 82
Reputation: 6956
In ECMAScript, variables are scoped to their function, rather than any block.
The functions you are binding to click
have a closure over URL
in the context of the loop as a whole, not over URL
in the context of the loop iteration.
This means that whenever any of the functions are invoked, URL
will have the last value that the loop sets it to.
You need to freeze the value of URL
for each loop. One way to do this is to have a function elsewhere that takes URL
as an argument, and returns a function that closes over it, thus:
function getBookLoader(url) {
return function (){
loadBook(url);
};
}
You can then replace your ... .click
line with the following:
$(htmlString).appendTo(attachPoint).click(getBookLoader(URL))
To answer the question in the title, the target
property of an event contains the object to which the event was dispatched, and the currentTarget
property contains the object whose listeners are currently being evaluated. currentTarget
should be the div
in question.
Upvotes: 1
Reputation: 38345
Creating a closure using an immediately invoked function expression should do the trick. Just replace this:
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
with this:
(function(URL) {
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
})(URL);
URL
inside the scope of that anonymous function will have the value passed to it, which will be the correct value for that iteration of the for
loop.
Upvotes: 2