Search code examples
javascriptjqueryshopping-cart

Javascript: Subtracting items from shopping cart result in negative value


I've got this shopping cart script that I'm trying to revise. Trouble is, whenever I try to delete more than one item from the cart, I get a negative value. The cart never goes back to zero when all items are deleted. I can add items fine.

Here is the fiddle.

Below is a code snippet of this feature. The full code is in the fiddle as it is easier to explain by showing you a demo of the problem I am having.

function addToCart(id, container_id, corTitle, corPrice, credit_hrs) {
    var amount = parseFloat(corPrice);
    var hours = parseFloat(credit_hrs);
    var remove = "<button type=\"button\" class=\"remove\"></button>";
    var selected_product = "<div class=\"item \">"
            + "<div class=\"title\">"
            +"<div class=\"remove\"><button type=\"button\" title=\"remove from cart\" class=\"remove-from-cart\" alt=\"Remove Course\" ></button></div>"               
            + corTitle
            + " for $" + corPrice
            + "</div>"              
            + "<input name=\"containerId\" value=\"" + container_id
            + "\" type=\"hidden\">" + "</div>";
    $(selected_product).insertBefore("#subtotals");

    register("add", amount, hours);
    $(".remove-from-cart").click(function() {

        $(this).parents(".item").slideUp("slow");
        console.log(this);
        register("subtract", amount, hours);
        $(toId(id)).removeAttr("disabled").fadeTo("slow", 1);
        $(this).parents(".item").remove();
    });
}   

The problem appears to be that the click handler attached to the remove button is invoked multiple times when a remove button is clicked. The duplicate invocation of register("subtract", amount, hours) causes the total to go negative. How can I fix this?


Solution

  • The problem is that you re-run $(".remove-from-cart").click(...) each time you add an item to the cart, so all existing remove buttons get an extra handler.

    Use jQuery to parse to HTML into a jQuery-wrapped DOM structure, and then use that as a context for your .remove-from-cart selector (as demonstrated in this working fiddle). That way, the .remove-from-cart selector will only apply to your newly-added item.

    var selected_product = "<div class=\"item \">" + ...;
    
    // jQuery-wrapped DOM structure
    var $prod = $(selected_product)
    
    $prod.insertBefore("#subtotals");
    register("add", amount, hours);
    
    // use $prod as jQuery context argument,
    // so `.remove-from-cart` only looks in this DOM tree
    $(".remove-from-cart", $prod).click(function() {    
        ...
    });