jQuery click events firing multiple times

2018-12-31 18:42发布

I'm attempting to write a video poker game in Javascript as a way of getting the basics of it down, and I've run into a problem where the jQuery click event handlers are firing multiple times.

They're attached to buttons for placing a bet, and it works fine for placing a bet on the first hand during a game (firing only once); but in betting for the second hand, it fires the click event twice each time a bet or place bet button is pressed (so twice the correct amount is bet for each press). Overall, it follows this pattern for number of times the click event is fired when pressing a bet button once--where the ith term of the sequence is for the betting of the ith hand from the beginning 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--and I wasn't smart enough to figure that out, I used OEIS. :)

Here's the function with the click event handlers that are acting up; hopefully it's easy to understand (let me know if not, I want to get better at that 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 ideas or suggestions, or if the solution to my problem is similar to a solution to another problem on here (I've looked at many similarly titled threads and had no luck in finding a solution that could work for me).

20条回答
浮光初槿花落
2楼-- · 2018-12-31 19:16

.unbind() is deprecated and you should use the .off() method instead. Simply call .off() right before you call .on().

This will remove all event handlers:

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

To only remove registered 'click' event handlers:

$(element).off('click').on('click', function() {
    // function body
});
查看更多
只靠听说
3楼-- · 2018-12-31 19:18

To make sure a click only actions once use this:

$(".bet").unbind().click(function() {
    //Stuff
});
查看更多
怪性笑人.
4楼-- · 2018-12-31 19:19

.one()

A better option would be .one() :

The handler is executed at most once per element per event type.

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

In case of multiple classes and each class needs to be clicked once,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
查看更多
皆成旧梦
5楼-- · 2018-12-31 19:19

If you find that .off() .unbind() or .stopPropagation() still doesn't fix your specific issue, try using .stopImmediatePropagation() Works great in situations when you just want your event to be handled without any bubbling and without effecting any other events already being handled. Something like:

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

does the trick!

查看更多
怪性笑人.
6楼-- · 2018-12-31 19:20

All the stuff about .on() and .one() is great, and jquery is great.

But sometimes, you want it to be a little more obvious that the user isn't allowed to click, and in those cases you could do something like this:

function funName(){
    $("#orderButton").prop("disabled", true);
    //  do a bunch of stuff
    // and now that you're all done
    setTimeout(function(){
        $("#orderButton").prop("disabled",false);
        $("#orderButton").blur();
    }, 3000);
}

and your button would look like:

<button onclick='funName()'>Click here</button>
查看更多
刘海飞了
7楼-- · 2018-12-31 19:23

It happens due to the particular event is bound multiple times to the same element.

The solution which worked for me is:

Kill all the events attached using .die() method.

And then attach your method listener.

Thus,

$('.arrow').click(function() {
// FUNCTION BODY HERE
}

should be:

$('.arrow').die("click")
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
查看更多
登录 后发表回答