简体   繁体   中英

jQuery unbinding event after second click

I am creating a Memory Game for a class at school, and I am using Bootstrap and jQuery. See Github . For testing use this jsfiddle , as the github code will change, I've included it if you would like to fork it for your own purposes.

I've constructed the code on the following logic:

  1. Pick with how many cards you want to play.
  2. Cards get loaded and randomized. Each pair have the same class(card* and glyphicon*).
  3. You click on one card, then on another, and if they match they get discarded, else you pick again.

The problem that I'm currently having is with the third step, namely when you click on the third card it shows the previous two, meaning I need to include something to escape the first click events. At least that was my first suggestion for the problem. If you have other suggestions to completely restructure the third step, please don't shy to elaborate why.

// check if picked cards' classes match     
jQuery("[class^=card]").click(function() { //picking the first card
    jQuery(this).css('color', '#000');
    var firstCard = $(this);
    var firstCardClass = $(this).find('[class*=glyphicon]').attr('class').split(' ')[1];
    jQuery("[class^=card]").click(function() { //picking the second card
        var secondCard = $(this);
        var secondCardClass = $(this).find('[class*=glyphicon]').attr('class').split(' ')[1];
        console.log(firstCardClass);
        console.log(secondCardClass);
        if (firstCardClass == secondCardClass) {
            console.log("yes")
            $(firstCard).css('color', '#005d00'); //make them green
            $(secondCard).css('color', '#005d00');

            setTimeout(function() {
                $(firstCard).css('display', 'none'); //discard
                $(secondCard).css('display', 'none');
            }, 1000);
        } 
        else {
            console.log("no");
            $(firstCard).css('color', '#cc0000'); //make them red
            $(secondCard).css('color', '#cc0000');

            setTimeout(function() {
                $(firstCard).css('color', '#fff'); //hide again
                $(secondCard).css('color', '#fff');
            }, 1000);
        }
    });
});

Note that the icons should be white as the cards, made them grey to see witch ones match without the need of firebug. If you click on more then two cards you will see what the problem is (if I failed to explain it well). I tried with including click unbind events in the end of each statement, but couldn't make it work.

Try your best! Thanks!

EDITED:

Seems I misunderstood the question so here's how I would go about having such game.

First I'll have my cards to have a structure like this:

<span class="card" data-card-type="one">One</span>

I'll use data-card-type to compare whether two cards are of the same type

I'll have a global variable firstCard which is originally null, if null I assign the clicked card to it and if not I compare the clicked card with it and then whether it's a match or not, I assign null to it meaning another pairing has begun.

I'll do all the logic in one onclick, looks weird to have a click listener inside another makes it to somehow look over-complicated.

var firstCard = null;

$('.card').on('click', function() {
    $(this).addClass('selected');
    if(!firstCard)
        firstCard = $(this);
    else if(firstCard[0] != $(this)[0]) {
        if(firstCard.data('card-type') == $(this).data('card-type')) {
            firstCard.remove();
            $(this).remove();
            firstCard = null;
            //$('.card.selected').removeClass('selected');
        }
        else {
            firstCard = null;
            $('.card.selected').removeClass('selected');
        }
    }
});

jsfiddle DEMO

when a card is clicked, you can add a class to that particular card (eg classname clickedcard ). Whenever you click another card you can test if there are 2 cards having this clickedcard class. If so, you can take action, for example remove all the clickedcard classes and add one again to the newly clicked one.

In pseudo code I would do it something like this:

jQuery("[class^=card]").click(function() { 
    if (jQuery('.clickedcard').length == 2) {
       // two cards where clicked already... 
       // take the actions you want to do for 2 clicked cards

       // you can use jQuery('.clickedcard')[0] and jQuery('.clickedcard')[1]
       // to address both clicked cards

       jQuery('.clickedcard').removeClass('clickedcard');
    } else {
       // no card or only one card is clicked
       // do actions on the clicked card and add classname
       jQuery(this).addClass('clickedcard');
    }
});

You could use `one' (to bind an event once):

$("[class^=card]").one(`click', firstCard);

function firstCard() { //picking the first card
  $(this).css('color', '#000');
  var firstCard = $(this);
  var firstCardClass = $(this).find('[class*=glyphicon]').attr('class').split(' ')[1];
  $("[class^=card]").one('click', secondCard);

 function secondCard() { //picking the second card
    var secondCard = $(this);
    var secondCardClass = $(this).find('[class*=glyphicon]').attr('class').split(' ')[1];
    console.log(firstCardClass);
    console.log(secondCardClass);
    if (firstCardClass == secondCardClass) {
        console.log("yes")
        $(firstCard).css('color', '#005d00'); //make them green
        $(secondCard).css('color', '#005d00');

        setTimeout(function() {
            $(firstCard).css('display', 'none'); //discard
            $(secondCard).css('display', 'none');
        }, 1000);
    } 
    else {
        console.log("no");
        $(firstCard).css('color', '#cc0000'); //make them red
        $(secondCard).css('color', '#cc0000');

        setTimeout(function() {
            $(firstCard).css('color', '#fff'); //hide again
            $(secondCard).css('color', '#fff');
        }, 1000);
    }
    $("[class^=card]").one(`click', firstCard);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM