0

I have a list of cats. Each cat object has a property cat.clicks that record the number of times the cat image has been clicked. The cat image's onclick calls the method cat.clickCat.

But of course 'this' in the clickCat method refers to the image element and not the cat object which contains the property 'clicks'.

How do I display and update the number of clicks on the image?

function Cat(src, name) {
  this.src = src;
  this.name = name;
  this.clicks = 0; //property recording no. of clicks
}

Cat.prototype.createCatItem = function() {
  let catDisplay = document.createElement("div");
  catDisplay.id = "catDisplay"
    let catName = document.createElement("h2");
    let catImg = document.createElement("img");
    let catCounter = document.createElement("div");
    catCounter.id = "clicker";
    catName.innerHTML = this.name;
    catImg.src = this.src;
    catImg.onclick = this.clickCat; //call the clickCat method
  catDisplay.appendChild(catName);
  catDisplay.appendChild(catImg);
  catDisplay.appendChild(catCounter);
  return catDisplay;
}

Cat.prototype.clickCat = function() {
  this.clicks += 1; //how to access the object property clicks from this method?
  let clickerDiv = document.getElementById("clicker")
  clickerDiv.innerHTML = ''
  clickerDiv.innerHTML = 'clicks = ' + this.clicks;
}

function App() {
  this.cats = [];
}

App.prototype.add = function(cat) {
  this.cats.push(cat)
}

App.prototype.listCats = function() {
  let container = document.getElementById("container");
  let ul = document.createElement("ul");
  for (let i=0; i<this.cats.length; i++){
    let li = document.createElement("li");
    li.innerHTML = this.cats[i].name;
    li.onclick = this.displayCat;
    ul.appendChild(li);
  }
  container.appendChild(ul);
}

App.prototype.displayCat = function() {
  let container = document.getElementById("container");
  let catDisplay = document.getElementById("catDisplay")
  let cats = app.cats;
  let chosenCat = cats.filter(cat => cat.name === this.innerHTML);
  let chosenCatItem = chosenCat[0].createCatItem();
  container.removeChild(catDisplay);
  container.appendChild(chosenCatItem);
  console.log(chosenCat);
}

App.prototype.showFirstCat = function() {
  let container = document.getElementById("container");
  let catDisplay = document.getElementById("catDisplay")
  let firstCat = app.cats[0].createCatItem();
  container.appendChild(firstCat);
}

let app = new App;

let tea = new Cat("http://placehold.it/350x150", "tea");
let snowball = new Cat("http://placehold.it/350x200", "snowball");
let triksy = new Cat("http://placehold.it/350x300", "triksy");
let vera = new Cat("http://placehold.it/350x350", "vera");
let jon = new Cat("http://placehold.it/350x400", "jon");


app.add(tea)
app.add(snowball)
app.add(triksy)
app.add(vera)
app.add(jon)

app.listCats();
app.showFirstCat();
<div id="container">
    <h1>My Cat Clicker</h1>
</div>
OctaviaLo
  • 1,268
  • 2
  • 21
  • 46
  • 1
    Possible duplicate of [How to access the correct \`this\` inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Andreas Mar 13 '17 at 10:31

1 Answers1

1

First of all .. beware of using this ... this always refer the object currently responsible to execute the scripts in browser ... so in your case the image is responsible for executing the click event and it has no property called clicks .. and that's why clicks is NaN

A good practice is preserve this into a variable to avoid the system replacement when executing (that=this)

    Cat.prototype.createCatItem = function() {
        let that=this; //preserving this value

        let catDisplay = document.createElement("div");
        catDisplay.id = "catDisplay"
        let catName = document.createElement("h2");
        let catImg = document.createElement("img");
        let catCounter = document.createElement("div");
        catCounter.id = "clicker";
        catName.innerHTML = this.name;
        catImg.src = this.src;
        catImg.onclick = function() {
            //alert(this);
            that.clicks += 1; //how to access the object property clicks from this method?
            let clickerDiv = document.getElementById("clicker")
            clickerDiv.innerHTML = ''
            clickerDiv.innerHTML = 'clicks = ' + that.clicks;
        }
        catDisplay.appendChild(catName);
        catDisplay.appendChild(catImg);
        catDisplay.appendChild(catCounter);
        return catDisplay;
    }

    //Cat.prototype.clickCat = function() {
    //    this.clicks += 1; //how to access the object property clicks from this method?
    //    let clickerDiv = document.getElementById("clicker")
    //    clickerDiv.innerHTML = ''
    //    clickerDiv.innerHTML = 'clicks = ' + this.clicks;
    //}
Moumit
  • 8,314
  • 9
  • 55
  • 59