user2208533
user2208533

Reputation: 37

finding the class of .click function

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

Answers (2)

Paul Butcher
Paul Butcher

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. currentTargetshould be the div in question.

Upvotes: 1

Anthony Grist
Anthony Grist

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

Related Questions