1

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.

0

2 Answers 2

3

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 to describeTheParameter.

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);
}
Sign up to request clarification or add additional context in comments.

4 Comments

This worked..thank you so much, but I am still not able to comprehend your solution, I load all my images first and at the bottom have placed the scripts, why doesnt it work for what I tried?
Hi Andrew..I am in a learning stage so pls bear with me, I tried out both of your solutions, why is it necessary to return the function in your first solution cos in your second solution you are just executing the function... I tried to execute function instead of returning it in your first solution, but it wont work! Whats the difference?
@Abhinav In that first one addImage is not what is being assigned as the click handler, it is actually executing immediately and returning an anonymous function, which is what is actually assigned as the click handler. That new function will have access to the value of the imageElement that was passed into addImage via closure.
@Abhinav - I've written an open paragraph. I think this should explain the underlying concept.
2

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

Look at the statement you wrote:

myapp.module2.addBackgroundImage(imageElement)

You are calling the function and then passing its return value as the function argument.

You want something more along the lines of:

myapp.module2.addBackgroundImage.bind(myapp.module2, imageElement)

(or the function expression that you used in the commented out code)

3 Comments

Where should I specify the click event here? cudn get you
@Abhinav — In the same place. You just change the bit of code I was talking about.
imageElement.addEventListener('click', myapp.module2.addBackgroundImage.bind(myapp.module2, imageElement), false);. What this is doing is similar to what is happening in the first solution @Andrew Shepherd purposed. This is using bind to create a new function that when called, calls myapp.module2.addBackgroundImage with the value of imageElement (at the time bind was called) as its argument.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.