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)

}
d_wesseling
  • 141
  • 1
  • 11

2 Answers2

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?

Community
  • 1
  • 1
modal_dialog
  • 733
  • 5
  • 12
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()});
Citrullin
  • 2,269
  • 14
  • 29
  • 1
    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: https://en.wikipedia.org/wiki/Closure_(computer_programming) – modal_dialog Feb 28 '16 at 01:45