1

I have an array of objects and I am building a page with those objecs The objects have an image, image will be clickable and I want to count the clicks per image. I am trying to assign the value for clicks from each object to "tclicks" and than hand "tclicks" over to the onclick function to count the clicks separately. I am not sure if that works.

My current problem is that the value appears as NaN when the onclick function gets executed. I am aware that I need to assign a starting value to clicks. I tried it in various places. In the object, in the function outside of the function. Either the value was not counting up, or I got an error as the element was set to 0 Where can I assign the starting value?

This is the array

var things = 
[
{img : "cat.jpg",
tclicks: "cleo_clicks",
id : "cleo"
},

{img : "shimi.png",
tclicks: "shimi_clicks",
id : "shimi" 
}
]

This is how I am building the page for ( var i= 0; i < things.length; i++){

var x = document.createElement("IMG");
x.setAttribute("src", things[i].img);
x.setAttribute(tclicks, things[i].clicks);
x.setAttribute("onclick", "countClicks(tclicks)");

document.body.appendChild(x);


}

And this is my onclick functions

function countClicks(clicks){

clicks ++;
console.log(clicks)

}

2 Answers 2

1

There's no reason you can't assign clicks=0 where you define the array of objects like this:

var things = [
  {
    img: "cat.jpg",
    tclicks: "cleo_clicks",
    id: "cleo",
    clicks: 0
  },
  {
    img: "shimi.png",
    tclicks: "shimi_clicks",
    id: "shimi",
    clicks: 0 
  }
];

...but that's only half the problem.

In your click-increment function:

function countClicks(clicks) {
  clicks++;
  console.log(clicks);
}

...you will never affect a change on any object's click property because Javascript passes function parameters by value (https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value).

You need to pass in the entire object to the function and allow it to modify the property value instead:

function countClicks(someObject) {
  someObject.clicks++;
  console.log(someObject.clicks);
}

...which means you need to change how the function is called, something like:

x.setAttribute("onclick", "countClicks(things[i])");

Note: above assumes things array is global, otherwise you'll need to further refactor.

Final note, calling JS pass-by-value is simplifying a little. You ca dive into the issue more here: Is JavaScript a pass-by-reference or pass-by-value language?

Sign up to request clarification or add additional context in comments.

Comments

1

Yep. Use an object and don't write it hard as onClick. It's too dangerous. You could override it. Use an eventListener instead.

function CountClicks(config){
    var img     = config.img;
    var tclicks = config.tclicks;
    var id      = config.id;
        var clicks  = 0;
    return{
        countUp: function(){
            clicks++;           
        },
        countDown: function(){
            clicks--;           
        },
        getCount: function(){
            return clicks;
        }
    }
}


x.counter = new CountClicks(things[i]);
x.addEventListener('click', function(){this.counter.countUp()});

1 Comment

I was trying to answer in a way that would require only incremental changes to the code, but this provides a nicer overall solution. However, in order to fully understand, you'll need to grasp closures: en.wikipedia.org/wiki/Closure_(computer_programming)

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.