简体   繁体   中英

jQuery execute a click function only once on each element?

With my add a box button (#purchase), I add boxes/items to the shopping carts. (this costs 25 of the credits)

When you click the orange div inside, the credits also decrease with an amount of 15 credits, and fades out the top div (so you can see which element has already cost 15 credits. Fading out happens only once, which is good, but while it's fading out, the user can still click the div, which causes the credits to decrease more than they should.

I tried some things with .one() but then it only works on one of the appended elements. Can anyone advise me how I can accomplish this? And why.

JSFiddle

Code Html

<button id="purchase">Add a box </button>
<input id="money">
<div class="container"></div>

JS

var counter = 0;
$("#money").val(250);

$('#purchase').click(function() {

   if ($("#money").val() < 25) {return;}
    var box = $('<div class="box"' + (counter) + '><div class="yellow"' + (counter) + '><div class="buy"' + (counter) + '></div></div></div>').appendTo('.container');
    $("#money").val(Number($("#money").val()) - 25).triggerHandler('change');

});

$('#money').change(function() {
    $('#purchase').prop("disabled", $(this).val() < 25);
});

$('.container').on('click', '.buy', function() {
    if ($("#money").val() < 15) {return;}
    $(this).fadeOut(4000, callbackFunction);
    $("#money").val(Number($("#money").val()) - 15).triggerHandler('change');
});

function callbackFunction() {
 alert('done');   
}

You can use one() to attach an event handler which should be run only once per element. Try this:

$('.container').one('click', '.buy', function() {
    if ($("#money").val() < 15) {return;}
    $(this).fadeOut(4000, callbackFunction);
    $("#money").val(Number($("#money").val()) - 15).triggerHandler('change');
});

API reference: one()

Update

You can also achieve this manually using unbind() :

$('.container').on('click', '.buy', function() {
    $(this).unbind('click');
    if ($("#money").val() < 15) {return;}
    $(this).fadeOut(4000, callbackFunction);
    $("#money").val(Number($("#money").val()) - 15).triggerHandler('change');
});

check the code and implement it for the elements you want the click to be implemented only once

$("purchase").one("click", function() {
if ($("#money").val() < 25) {return;}
var box = $('<div class="box"' + (counter) + '><div class="yellow"' + (counter) + '><div       class="buy"' + (counter) + '></div></div></div>').appendTo('.container');
$("#money").val(Number($("#money").val()) - 25).triggerHandler('change');
});

bind the event when you create element:

var counter = 0;
$("#money").val(250);



$('#purchase').click(function() {


    if ($("#money").val() < 25) {return;} // or alert('not enough money');
    $('<div class="box">').data('counter',counter)
           .append($('<div class="yellow">').data('counter',counter)
           .append($('<div class="buy">').data('counter',counter).one('click',buy_click)
                  )).appendTo('.container');
    $("#money").val(Number($("#money").val()) - 25).triggerHandler('change');

});

$('#money').change(function() {
    $('#purchase').prop("disabled", $(this).val() < 25);
});

var callbackFunction=function() {};

var buy_click=function() {
    if ($("#money").val() < 15) {return;}
    $(this).fadeOut(4000, callbackFunction);
    $("#money").val(Number($("#money").val()) - 15).triggerHandler('change');
};

use data() to keep data, not just numbers as you did

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