tags:

views:

23

answers:

2

I'm a jQuery beginner. I'm adding a bunch of new images into a div. I'd like each of these images to respond to a click.

My initial, and in hindsight foolish code, looked like this:

for (var i = 0; i < 10; i++) {
    $("div#stargrid").append("<img class='clickme' src='http://placehold.it/90x90' alt='90x90 placeholder image' />").click(my_event_handler);
}

Now, I've worked out that that's dumb, because the chaining doesn't work how I thought it did, so (I think) that actually adds the click event handler ten times to my div#stargrid, not once to each img.

I found one solution that seems to work for me, just to separate these operations out and bind the click event to all the images afterward:

for (var i = 0; i < 3; i++) {
    $("div#stargrid").append("<img class='clickme' src='http://placehold.it/90x90' alt='90x90 placeholder image' />");
}
$(".clickme").click(imageclick);

My question is: is that the "right" way to do it?

I realise this may be subjective, but what I'm looking for here is the "standard" way to do this kind of thing in jQuery, preferably with some reasoning as to why it's a good way. I had a look around and couldn't find much in the way of examples of doing what I'm doing here.

Thanks!

+2  A: 

The "right" way (which works, but you should forget about it quickly)

for (var i = 0; i < 10; i++) {
    $("div#stargrid").append($("<img class='clickme' src='http://placehold.it/90x90' alt='90x90 placeholder image' />").click(my_event_handler));
}

As you can see, I just added a new call to the jQuery constructor function $() to create a new DOM node, which then is added to an event handler for click.

But this is kind of ugly, a better approach for this is

$('<img/>', {
   'class':   'clickme',
   'src':     'http://placehold.it/90x90',
   'alt':     '90x90 placeholder image',
   'click':   function(){
       alert('CLICKED');
   }
}).appendTo($("div#stargrid"));

This is cleary less odd, but still not good. If creating multiple elements with the same event handler, you should always consider to use event delegation to just bind one event handler instead of n.

In this case it could look like

$("div#stargrid").delegate('.clickme', 'click', function(e){
    alert('CLICKED');
});

You can use the event object e which is passed into the handler to distinguish which element actually was clicked, for instance, check an id value.

jAndy
The first example still won't work as `click` will be applied to the first selector `div#stargrid`. You can remove the `$()` calls in `append` and `appendTo`, they make no difference. And I would add `.click(imageclick)` to the second example.
Felix Kling
@Felix: wrong, first example works. A new jQuery object is formed before it gets appened to #stargrid. See http://www.jsfiddle.net/9G7Z7/1/
jAndy
Oh sorry, I didn't see where the brackets got closed ;) My bad...
Felix Kling
Thanks, @jAndy, just the kind of answer I was looking for.
Matt Gibson
A: 

Return value of the append function is the receiver, NOT the inserted content, thats why it adds click events to div#stargrid

abespalov
Should be a comment imo.
Felix Kling