ziggy
ziggy

Reputation: 35

Utilizing .each() with an array

I am creating a Matching Card game using jQuery. Currently, I am running into an issue where the playerChoices array in my code does not update the 'matched' cards with the 'matched' class.

var playerChoices = [];

function showCard(){

    $(this).addClass('selected'); //mark the selection with the selected class

    playerChoices.push($(this)); //push the players choice onto the playerChoices array
    console.log(playerChoices);

    moves++;
    console.log(moves);

    $('#buttons').show();
    matchCards(playerChoices);

}

Here is the function in question where the issues lie:

function matchCards(array){

    if(playerChoices.length === 3){
        //when the player finds the first match
        if(playerChoices[0].attr('class') === playerChoices[1].attr('class')){  //if both playerChoices have the class 
            console.log("match found at index 0 and 1 of playerchoice!");
            **$(playerChoices).each(playerChoices, function(index, element){
                $(this).addClass('matched');**
            })
        }

        //Deselect the two choices that were made
        else{ 
            $(playerChoices).each(function(index, element){
                $(this).removeClass('selected');
            })
            playerChoices = [];
        }
    }

    else if(playerChoices.length === 4){

        //when the player gets the second match
        if(playerChoices[2].attr('class') === playerChoices[3].attr('class')){
            console.log("match found at index 2 and 3 of playerchoice!");
            **$(playerChoices).each(playerChoices, function(index, element){
                $(this).addClass('matched');**
            })
            **showGameOverMessage();**
        }

        //Deselect the last two choices that were made
        else{
            $(playerChoices).each(function(index, element){
                $(this).removeClass('selected');
            })
        }
    }
}

The primary issue here are the area's that I have 'asterisks' around in my code. I set up break points in the console, and I found that the code was never reaching the $(this).addClass('matched') lines. I've never used .each before and have looked at the examples api.jquery.com but I still was not able to overcome this issue of applying the matched class to my 'matched' cards.

FYI: I tried to get my code to work in JSFiddle but I kept getting errors with the images of my cards. My code works outside of that, I am just not able to get the matching class to apply appropriately.

https://jsfiddle.net/2sharkp/54s47vzb/ Works now

Any help is greatly appreciated!

Upvotes: 2

Views: 78

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074355

Your updated question makes the problem clear: You're pushing jQuery instances into playerChoices:

playerChoices.push($(this));

...then later using $(playerChoices).each(...) to try to loop over them. While $() accepts arrays of HTML elements in the $() function, it doesn't correctly understand it if you pass it an array of jQuery instances — you end up with a jQuery instance wrapped around that set of jQuery instances, which isn't useful — you may as well just use the array (or use a single jQuery instance as I describe later).

You can use $.each (the one on the jQuery function itself):

$.each(playerChoices, function() {
    // ...`this` (not `$(this)`) here will be a jQuery instance:
    this.addClass('matched');
});

Updated Fiddle

But you really dont need $.each, just use the array's built-in forEach:

playerChoices.forEach(function(entry) {
    // ...`entry` here will be a jQuery instance
    entry.addClass('matched');
});

Updated Fiddle

...or there are lots of other ways to loop through arrays outlined in my answer here.

That said, you might consider making playerChoices a (single) jQuery instance. jQuery is set-based, so a single jQuery instance can contain multiple HTML elements that you can then act on with just a single method call. For instance, if you made playerChoices a jQuery instance, instead of:

playerChoices.forEach(function(entry) {
    entry.addClass('matched');
});

You could do this:

playerChoices.addClass('matched');

To do that, start with:

playerChoices = $();

...and add elements via add:

playerChoices.add(this);

Upvotes: 3

guest271314
guest271314

Reputation: 1

Try removing playerChoices before callback

$(playerChoices).each(function(index, element){
  $(this).addClass('matched');
})

jsfiddle https://jsfiddle.net/xowkyh6p/1/

Upvotes: 1

Related Questions