Opoe
Opoe

Reputation: 1387

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');   
}

Upvotes: 2

Views: 2501

Answers (3)

zb&#39;
zb&#39;

Reputation: 8059

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

Upvotes: 1

Gadde
Gadde

Reputation: 1471

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');
});

Upvotes: 2

Rory McCrossan
Rory McCrossan

Reputation: 337570

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');
});

Upvotes: 4

Related Questions