Afunakwa
Afunakwa

Reputation: 437

Javascript event listener confuses me

I'm confused. I want to construct a gallery wherein you can click on any image and you have the full-scale image superimposed on the document (kinda like with facebook galleries).

The gallery's thumbnails are displayed with some PHP. It looks like this:

$i = 0;

while($img_dir = mysqli_fetch_assoc($gallery_q))
{
    $i++;

    echo
    '
        <div class="entry"><div class="image" id="' . $img_dir['dir'] . '">
<img id="img' . $i . '" src="' . $img_dir['thumb_dir'] . '" /></div></div>
    ';

}

I then fetch the number of images with json_encode and produce a bunch of event listener with a loop, like so:

for(var i = 1; i <= nbImg; i++)
{ 
    document.getElementById("img" + i).addEventListener("click", display(i));
}

The display function being the following:

function display(i)
{
document.getElementById("body").insertAdjacentHTML("afterBegin",
'<div id="display"><div><img src="' + document.getElementById("img" + i).parentNode.getAttribute("id") + '"></div>');

style.insertAdjacentHTML("beforeend",
"#display{z-index: 20; position: fixed; width: 1000px; height: 1000px; left: 50%; top: 10%; margin-left: -600px;");

}

And well, it works.. except display() is called without any regards for whether I click on the image or not. But when I restrain this behavior to only one image (that is, the event listener isn't in a loop and no argument is passed to the function; it just displays a preset image) then all is fine. The event is triggered when I click.

It's actually not the first time I encounter this phenomenon of the listening function being triggered not matter what event I ask the event listener to be on the lookout for. It happens most often with alert and I honestly can't figure out why. Can someone help me?

Upvotes: 0

Views: 75

Answers (2)

Da Rod
Da Rod

Reputation: 731

the reason display is being called has to do with this code. you're invoking the display function as opposed to referencing it. replace the display function with a closure.

for (var i = 1; i <= nbImg; i++) {
  document.getElementById("img" + i).addEventListener("click", function() {
    display(i)
  });
}

Upvotes: 3

tymeJV
tymeJV

Reputation: 104775

You can't assign the function like that. Adding the () immediately invokes the function (to pass the function, omit the () - but you'll also lose the ability to pass i in, event would instead be passed in since it's the first param that the function passed to addEventListener has):

document.getElementById("img" + i).addEventListener("click", function() {
    display(i);
});

You'll probably notice that i is always the last iterated loop var, so you want to wrap this in a closure:

for(var i = 1; i <= nbImg; i++) { 
    (function(i) {
        document.getElementById("img" + i).addEventListener("click", function() {
            display(i)
        });
    })(i);
}

Upvotes: 4

Related Questions