-1

Each card has class names of "card player1card ________" or "card player2card _______" where the blank space is a random class name that is allocated from the cardnames array.

I want the code to check all cards, and for those which are player1card for them to have their class changed to "card player1card" and then an updated class from the cardnames array, and same for player2card.

All variables have been pre-defined.

I get the error "Uncaught TypeError: Cannot set property 'className' of undefined"

var cardsnames = ["recruitbuilder", "allwood", "cabin", "messhall", "mast", "captainsquarters", "schooner", "brig", "frigate", "shipballista", "ram", "crowsnest", "spoondrill", "reinforcements", "recruitgunman", "allgunpowder", "firebarrel", "fireship", "roundshot", "heavyshot", "swivelgun", "chainshot", "mortar", "barrage", "resupply", "smuggler", "blockade", "mutiny", "recruitmerchant", "allgold", "addwood", "addgunpowder", "addgold", "removewood", "removegunpowder", "removegold", "byzantinefire", "slaves", "mercenaries", "ironplating", "coercion", "ascension"];

var w;
var allocatedcard;
var card = document.getElementsByClassName("card");

for (w = 0; w < card.length; w++) {
    if (document.getElementsByClassName("card")[w].className.match('player1card')) {
        this.className = "card player1card";
        var allocatedcard = Math.floor(Math.random() * cardsnames.length);
        this.className += " " + cardsnames[allocatedcard];
        updateimages();             
    } else if (document.getElementsByClassName("card")[w].className.match('player2card')) {
        this.className = "card player2card";
        var allocatedcard = Math.floor(Math.random() * cardsnames.length);
        this.className += " " + cardsnames[allocatedcard];
        updateimages();     
    }
}
evilgenious448
  • 518
  • 2
  • 11
  • Why are you fetching again in loop? just use `card[w].className`. Also I'd suggest `card[w].classList.indexOf('player1card')` – Rajesh Dec 26 '16 at 10:00
  • Sorry Rajesh, I am not the most experienced with Javascript, could you explain this in more detail – evilgenious448 Dec 26 '16 at 10:02
  • `document.getElementsByClassName` returns you a list that is saved in `card`. You want to access an element in it. So ideal way is to access from stored list instead of fetching the list again and again. DOM interactions are very expensive and you should keep it to minimum. Also `classList` will return you a `DOMTokenList`(an array like structure) and you can search in it easily. Its better than string matching (*className.match*) – Rajesh Dec 26 '16 at 10:08
  • What is `this` in this code? Please provide a [mcve]. – Michał Perłakowski Dec 26 '16 at 10:12
  • Gothdo, this refers to `cards[w]` however if I do that, then it updates all of the cards. I need it to update the specific card that is clicked, not all of them. – evilgenious448 Dec 26 '16 at 10:14
  • @evilgenious448 I have updated your code: [JSFiddle](https://jsfiddle.net/RajeshDixit/naz6peys/). Note you should add enough code that explains your problem and do not leave blank/dark areas. Also apologies for initial comment. It was lil rude – Rajesh Dec 26 '16 at 10:16
  • @Rajesh when I use your code I get the error "card[w].classList.indexOf is not a function". I can see what your code does and it seems like it will work, im just not sure how to fix this one part – evilgenious448 Dec 26 '16 at 10:23
  • @evilgenious448 my apologies. Its `.classList.contains('className')` and it returns boolean value. for more reference: https://developer.mozilla.org/en/docs/Web/API/Element/classList – Rajesh Dec 26 '16 at 10:26
  • @Rajesh this line `this.classList.add(className, cardsnames[allocatedcard]);` gives the error: Cannot read property 'classList' of undefined – evilgenious448 Dec 26 '16 at 10:32
  • @Rajesh would it be possible for you to update the JS fiddle with the new code you are proposing so that I can properly test it. Thank you very much in advance – evilgenious448 Dec 26 '16 at 10:37
  • @evilgenious448 you are getting error because your `w` is going out of bound. Also **NO**. You can update that fiddle and play with it. We are here to help not code for you. – Rajesh Dec 26 '16 at 10:41
  • @Rajesh what does out of bound mean? Also I have updated the fiddle to the code that I currently have and am playing with it. My apologies – evilgenious448 Dec 26 '16 at 10:43
  • it means its exceeding the limit. in an array of 10 elements, if you try to access 11th or 12th value, it does not exists and will return `undefined` – Rajesh Dec 26 '16 at 11:03
  • thank you for explaining that to me @Rajesh – evilgenious448 Dec 26 '16 at 11:05
  • what would be the appropriate way to limit it? – evilgenious448 Dec 26 '16 at 11:06

1 Answers1

0

Just for context, the code in the question would have been a function within another function. So instead I did it this way:

var recruitbuilder = document.getElementsByClassName('recruitbuilder');
var f;
var className = "";
var cardsnames = ["recruitbuilder", "allwood", "cabin", "messhall", "mast", "captainsquarters", "schooner", "brig", "frigate", "shipballista", "ram", "crowsnest", "spoondrill", "reinforcements", "recruitgunman", "allgunpowder", "firebarrel", "fireship", "roundshot", "heavyshot", "swivelgun", "chainshot", "mortar", "barrage", "resupply", "smuggler", "blockade", "mutiny", "recruitmerchant", "allgold", "addwood", "addgunpowder", "addgold", "removewood", "removegunpowder", "removegold", "byzantinefire", "slaves", "mercenaries", "ironplating", "coercion", "ascension"];
var allocatedcard = cardsnames[Math.floor(Math.random() * cardsnames.length)];

for (f = 0; f < recruitbuilder.length; f++) {
    recruitbuilder[f].onclick = function() {
        recruitbuilderfunc(p1);
        displayvaluesp1(p1);
        if (this.classList.contains('player1card') == true ) {
            className = "player1card";
        } else if (this.classList.contains('player2card') == true ) {
            className = "player2card";
        }
      //this.className += " " + cardsnames[allocatedcard];

      this.className = "card " + className + " " + allocatedcard;
      updateimages();
    }
}
evilgenious448
  • 518
  • 2
  • 11