T. Evans
T. Evans

Reputation: 1001

this.setAttribute is not a function

I am trying to get cards to flip over from back to front in a matching game and I am having trouble I am getting a console error and I am not sure why this is happening: at checkForMatch (main.js:27) at HTMLImageElement.flipCard (main.js:37)

Please look over my code and let me know what you see. P.S. this is a pre course assignment for school that I am doing so I am not 100% familiar with some terms, but usually can understand what people are trying to say. Thanks

var cards = [
{
    rank: "queen",
    suit: "hearts",
    cardImage: "images/queen-of-hearts.png"
},
{
    rank: "queen",
    suit: "diamonds",
    cardImage: "images/queen-of-diamonds.png"
},
{
    rank: "king",
    suit: "hearts",
    cardImage: "images/king-of-hearts.png"
},
{
    rank: "king",
    suit: "diamonds",
    cardImage: "images/king-of-diamonds.png"
}
];

var cardsInPlay = [];

var checkForMatch = function() {
    this.setAttribute('src', (cards.cardImage));
if (cardsInPlay.length === 2 && cardsInPlay[0] === cardsInPlay[1]){
    alert("You found a match!");
} else {
        alert("Sorry, try again");
    }
}

var flipCard = function(){
    var cardId = this.getAttribute('data-id');
    checkForMatch();
    console.log("User flipped " + cards.rank);
    cardsInPlay.push(cards.rank);
    console.log(cards.cardImage);
    console.log(cards.suit);
}

var createBoard = function(){
    for (var i = 0; i < cards.length; i++) {
        var cardElement = document.createElement('img');
        cardElement.setAttribute('src', "images/back.png");
        cardElement.setAttribute('data-id', i);
        cardElement.addEventListener('click', flipCard);
        document.getElementById('game-board').appendChild(cardElement);
    }
}

createBoard();

Upvotes: 1

Views: 6209

Answers (2)

Nope
Nope

Reputation: 22339

To fix the context issue you can replace Update checkForMatch() with checkForMatch.bind(this)(); but you also seem to have another issue in your code inside checkForMath, line ► this.setAttribute('src', (cards.cardImage)); doesn't specify the index of the array you want the image from.

My guess is you wanted to pass the cardId, similar to this ► checkForMatch.bind(this)(cardId);

It seems your console logs are also not specifying an index and propably should be using the cardId as well ► console.log(cards[cardId].cardImage); and console.log(cards[cardId].suit);

I made all the changes below in a working example. As the images are random for demonstration purpose and to sow actual images, use the corrected console output for to see everything working correctly.

document.addEventListener("DOMContentLoaded", function(event) {


  var cards = [{
    rank: "queen",
    suit: "hearts",
    cardImage: "http://lorempixel.com/25/25/animals/"
  }, {
    rank: "queen",
    suit: "diamonds",
    cardImage: "http://lorempixel.com/25/25/animals/"
  }, {
    rank: "king",
    suit: "hearts",
    cardImage: "http://lorempixel.com/25/25/animals/"
  }, {
    rank: "king",
    suit: "diamonds",
    cardImage: "http://lorempixel.com/25/25/animals/"
  }];

  var cardsInPlay = [];

  var checkForMatch = function(cardId) {
    this.setAttribute('src', cards[cardId].cardImage);
    if (cardsInPlay.length === 2 && cardsInPlay[0] === cardsInPlay[1]) {
      alert("You found a match!");
    } else {
      alert("Sorry, try again");
    }
  }

  var flipCard = function() {
    var cardId = this.getAttribute('data-id');
    checkForMatch.bind(this)(cardId);
    console.log("User flipped " + cards[cardId].rank);
    cardsInPlay.push(cards.rank);
    console.log(cards[cardId].cardImage);
    console.log(cards[cardId].suit);
  }

  var createBoard = function() {
    for (var i = 0; i < cards.length; i++) {
      var cardElement = document.createElement('img');
      cardElement.setAttribute('src', "http://lorempixel.com/25/25/animals/");
      cardElement.setAttribute('data-id', i);
      cardElement.addEventListener('click', flipCard);
      document.getElementById('game-board').appendChild(cardElement);
    }
  }

  createBoard();
});
img{
padding: 2px;
}
<div id="game-board"></div>

Upvotes: 1

Peter Kota
Peter Kota

Reputation: 8340

You need to pass the this parameter to the function. Try this:

var checkForMatch = function(elem) {
    elem.setAttribute('src', (cards.cardImage));
    if (cardsInPlay.length === 2 && cardsInPlay[0] === cardsInPlay[1]){
        alert("You found a match!");
    } else {
        alert("Sorry, try again");
    }
}

var flipCard = function(elem){
    var cardId = elem.getAttribute('data-id');
    checkForMatch(elem);
    console.log("User flipped " + cards.rank);
    cardsInPlay.push(cards.rank);
    console.log(cards.cardImage);
    console.log(cards.suit);
}

var createBoard = function(){
    for (var i = 0; i < cards.length; i++) {
        var cardElement = document.createElement('img');
        cardElement.setAttribute('src', "images/back.png");
        cardElement.setAttribute('data-id', i);
        cardElement.addEventListener('click', function() {
            flipCard(this);
        });
        document.getElementById('game-board').appendChild(cardElement);
    }
}

createBoard();

Upvotes: 0

Related Questions