Coder Perfect

Click events from jQuery are fired several times.

Problem

I’m trying to learn the basics of Javascript by writing a video poker game, and I’ve run into a situation where the jQuery click event handlers are triggering several times.

They’re attached to bet buttons, and they operate perfectly for putting bets on the first hand of a game (firing only once); but, while betting on the second hand, the click event fires twice each time a bet or place bet button is hit (so twice the correct amount is bet for each press). Overall, the number of times the click event is fired when pressing the bet button once—where the ith term of the sequence is for betting the ith hand from the start of the game: 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, which appears to be n(n+1)/2 + 1 for whatever that’s worth—follows this pattern, and I wasn’t smart enough to figure it out.

Here’s the function with the faulty click event handlers; hopefully it’s clear (please let me know if it’s not; I’d like to improve in this area as well):

/** The following function keeps track of bet buttons that are pressed, until place button is pressed to place bet. **/
function pushingBetButtons() {
    $("#money").text("Money left: $" + player.money); // displays money player has left

    $(".bet").click(function() {
        var amount = 0; // holds the amount of money the player bet on this click
        if($(this).attr("id") == "bet1") { // the player just bet $1
            amount = 1;
        } else if($(this).attr("id") == "bet5") { // etc.
            amount = 5;
        } else if($(this).attr("id") == "bet25") {
            amount = 25;
        } else if($(this).attr("id") == "bet100") {
            amount = 100;
        } else if($(this).attr("id") == "bet500") {
            amount = 500;
        } else if($(this).attr("id") == "bet1000") {
            amount = 1000;
        }
        if(player.money >= amount) { // check whether the player has this much to bet
            player.bet += amount; // add what was just bet by clicking that button to the total bet on this hand
            player.money -= amount; // and, of course, subtract it from player's current pot
            $("#money").text("Money left: $" + player.money); // then redisplay what the player has left
        } else {
            alert("You don't have $" + amount + " to bet.");
        }
    });

    $("#place").click(function() {
        if(player.bet == 0) { // player didn't bet anything on this hand
            alert("Please place a bet first.");
        } else {
            $("#card_para").css("display", "block"); // now show the cards
            $(".card").bind("click", cardClicked); // and set up the event handler for the cards
            $("#bet_buttons_para").css("display", "none"); // hide the bet buttons and place bet button
            $("#redraw").css("display", "block"); // and reshow the button for redrawing the hand
            player.bet = 0; // reset the bet for betting on the next hand
            drawNewHand(); // draw the cards
        }
    });
}

Please let me know if you have any thoughts or suggestions, or if the solution to my problem is comparable to a solution to another problem on here (I’ve looked at a lot of posts with similar titles but haven’t seen anything that could work for me).

Asked by Gregory Fowler

Solution #1

Use this to ensure that a click only does one action:

$(".bet").unbind().click(function() {
    //Stuff
});

Answered by Rob

Solution #2

You should use the.off() method instead of.unbind() because it is deprecated. Simply call.off() before calling.on() ().

All event handlers will be removed as a result of this:

$(element).off().on('click', function() {
    // function body
});

To only remove ‘click’ event handlers that have been registered:

$(element).off('click').on('click', function() {
    // function body
});

Answered by mtl

Solution #3

.one() is a superior alternative:

$(".bet").one('click',function() {
    //Your function
});

If there are numerous classes, each of which must be clicked once,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});

Answered by Shaunak D

Solution #4

If.off(),.unbind(), or.stopPropagation() don’t solve your problem, try.stopImmediatePropagation() () It’s ideal for cases where you only want your event to happen without any bubbling and without interfering with other events. Something along these lines:

$(".bet").click(function(event) {
  event.stopImmediatePropagation();
  //Do Stuff
});

does the trick!

Answered by Alfonse Pinto

Solution #5

If you call that function for each “click,” each call will result in the addition of a new pair of handlers.

Adding handlers with jQuery isn’t the same as changing the “onclick” attribute’s value. You can have as many handlers as you want.

Answered by Pointy

Post is based on https://stackoverflow.com/questions/14969960/jquery-click-events-firing-multiple-times