Abhinav Abhinav - 7 months ago 58
Javascript Question

addEventListener not working in Javascript but jQuery Click is working

I am using modular pattern of javascript and trying to do things in Javascript way rather than Jquery

myapp.module1 = (function($){
"use strict";

var _config = {
backgroundImages : document.getElementsByClassName('img_paste'),
}

for(var i = 0;i < _config.backgroundImages.length; i++){
var imageElement = _config.backgroundImages[i];
imageElement.addEventListener('click',myapp.module2.addBackgroundImage(imageElement),false);
}

// $('.img_paste').click(function(){
// var img = this;
// console.log(this);
// console.log($(this));

// myapp.module2.addBackgroundImage(img);
// });


})(jQuery);


In the above code, the Jquery click function works but not the Javacript one.

When I tried to debug, I tried to console out the image in
addBackgroundImage()
function.

var addBackgroundImage = function(imageToBeAdded){
console.log(imageToBeAdded);//
_addImageToCanvas(imageToBeAdded);
}


The function seems to be executing even before
onclick
. Why is that happening?

First, the images elements appear to be empty in the console, then after some some the image elements are displayed in console.

Answer

Take a look at this simple code example:

function describeTheParameter(p) {
    console.log("describeTheParameter invoked. p is of type " + typeof(p));
}

function stringFunction() {
    return "Hello World!";
}

describeTheParameter(stringFunction());
describeTheParameter(stringFunction);

This results in

describeTheParameter invoked. p is of type string

describeTheParameter invoked. p is of type function

In the first call, we are calling stringFunction, and then passing the result to describeTheParameter.

In the second call, we are actually passing the function without invoking it.

When you call addEventListener you must follow the pattern of the second call: pass the function without invoking it:


In the following line of code, you are invoking addBackgroundImage, and then passing the result (which will be undefined) to addEventListener.

imageElement.addEventListener('click',myapp.module2.addBackgroundImage(imageElement),false);

You need to pass a yet-to-be-called function into addEventListener.

The smallest step to make your code work is to employ a currying function:

function addImage(imageElement) {
      return function() {
          myapp.module2.addBackgroundImage(imageElement);
      }
}


for(var i = 0;i < _config.backgroundImages.length; i++){
    var imageElement = _config.backgroundImages[i];
    imageElement.addEventListener('click', addImage(imageElement), false);
}

For much simpler code, make use of the this keyword. In this case, this will point to the element that's firing the event.

function imageClickHandler() {
    var imageElement = this;
    myapp.module2.addBackgroundImage(imageElement);
}

for(var i = 0;i < _config.backgroundImages.length; i++){
   var imageElement = _config.backgroundImages[i];
   imageElement.addEventListener('click', imageClickHandler, false);
}
Comments