0

I have two images, image_0 and image_1, and when each is clicked, I want it to display an alert saying the id of that image. To do this, I have created an array to store these functions (this was necessary because of my previous issue: https://stackoverflow.com/questions/41003122/looping-in-jquery-only-remembers-last-iteration?noredirect=1#comment69215730_41003122).

The code below shows my attempt. However, nothing happens when I click either image. Why?

HTML:

<img id="image_0" src="http://placehold.it/350x150" width="300">
<img id="image_1" src="http://placehold.it/350x150" width="300">

Javascript:

$(document).ready(function()
{
    // The number of images shown
    num_images = 2

    // List of functions for each thumbnail click.
    var image_click_functions = new Array(num_images);

    // Define the function for when the thumbnail is clicked
    function CreateImageClickFunction(image_id)
    {
        return function() { alert(image_id) };
    }

    // Loop through all images, and define the click functions
    for (i = 0; i < num_images; i++)
    {
        image_click_functions[i] = CreateImageClickFunction(i);
        image_id = "#image_" + i;
        $(image_id).click(function()
        {
            image_click_functions[i];
        });
    }
});
Community
  • 1
  • 1
Karnivaurus
  • 22,823
  • 57
  • 147
  • 247

5 Answers5

5

Add a common class, create one handler, and use an instance of this

<img class="image" id="image_0" src="http://placehold.it/350x150" width="300">
<img class="image" id="image_1" src="http://placehold.it/350x150" width="300">

JS:

$(".image").click(function() { alert(this.id) });
tymeJV
  • 103,943
  • 14
  • 161
  • 157
4

Why do you need to write it so complex?

you could very easily do:

$('img').click(function(){
   alert($(this).attr('id'));
}

(this actually creates a different listener for each one)

or you could use on like this:

$(document).on('click','img',function(){
   alert($(this).attr('id'));
})

that has the advantages of:

a. using only one event listener

b. works on dynamically created content (if you add more images using ajax for example, this event listener will still work on the new images)

Jameson the dog
  • 1,796
  • 1
  • 11
  • 12
1

As CreateImageClickFunction(image_id) is returning a function, You just need to pass the function as event handler.

$(image_id).click(image_click_functions[i]);

Alternatively. as per existing HTML you can use Attribute Starts With Selector [name^=”value”] to bind event

$('[id^image_]').click(function(){
    //Extract number from ID
    var idNum = this.id.match(/\d+$/)[0];
})

If you need to store some arbitrary data I would recommend you to use data-* prefixed custom attribute, which can be fetched using $.fn.data() method or HTMLElement.dataset property

<img class="image" data-id="0" src="http://placehold.it/350x150" width="300">
<img class="image" data-id="1" src="http://placehold.it/350x150" width="300">

Script

$(parentContainerSelector).on('click','.image',function(){
   console.log(this.dataset.id);
})
Satpal
  • 132,252
  • 13
  • 159
  • 168
  • 3
    But still a really bad way to do it... single handler and identify item by attributes etc is the way to go – iCollect.it Ltd Dec 07 '16 at 13:49
  • Using the `id` and the `attribute starts with selector` is a very obscure way of organizing JS. As a fellow developer, it'd be _much more clear_ to use a dedicated class (e.g. `.js-img-click`). – sweeds Dec 07 '16 at 14:03
1

I think you over-complicate this. Have a look on this example: html:

    $("#container").on("click", "img", function(e){
      console.log($(this).attr("id"));
    })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"> 
      <img id="image_0" src="http://placehold.it/350x150" width="300">
      <img id="image_1" src="http://placehold.it/350x150" width="300">
    </div>

example: http://codepen.io/xszaboj/pen/PbeypX?editors=1010

prasanth
  • 22,145
  • 4
  • 29
  • 53
xszaboj
  • 1,035
  • 7
  • 21
0

I think you've overcomplicated by not understanding Closures in your original question. This is a more advanced "feature" in JS, but worth taking time to research and understand.

However, a much simpler way to do this in jQuery, is to use the images as a selector, and iterate over them that way. Then you can access this as the image. Here's example code.

Community
  • 1
  • 1
sweeds
  • 539
  • 6
  • 18