1

Each time the user clicks the 'add pizza' button, I would like the page to produce another pizza form and add any costs of the additional pizza. I have been able to add a pizza form, but none of the adding up rules are being applied to the cloned element. Any ideas?

HTML:

    <div id="pizzaForm">
        <fieldset>
            <form class="pure-form">
            <legend>Pizza</legend>
            <label><b>Pizza Type: &nbsp;</b></label>
            <select id="pizza">
                <option name="margarita">Margarita</option>
                <option name="deep-pan">Deep Pan</option>
                <option name="stuffed-crust">Stuffed Crust</option>
            </select>
                <span style="float:right">
                <label><b>Pizza Size: &nbsp;</b></label>
                <select id="pizzaSize">
                    <option name="e-small" id="4.99">Extra Small - £4.99</option>
                    <option name="small" id="5.99">Small - £5.99</option>
                    <option name="medium" id="6.99">Medium - £6.99</option>
                    <option name="large" id="8.99">Large - £8.99</option>
                    <option name="e-large" id="9.99">Extra Large - £9.99</option>
                    <option name="f-size" id="10.99">Family Size - £10.99</option>
                </select>
                </span>
            </form>
        </fieldset>
        <fieldset style = "border-top:0px">
        <form class="pure-form">
            <legend><b>Toppings (99p Each): &nbsp;</b></legend>
            <input type="checkbox" name="onions" id="0.99">Onions</input>
            <input type="checkbox" name="mushrooms" id="0.99">Mushrooms</input>
            <input type="checkbox" name="peppers" id="0.99">Peppers</input>
            <input type="checkbox" name="olives" id="0.99">Olives</input>
            <input type="checkbox" name="garlic" id="0.99">Garlic</input>
            <input type="checkbox" name="peperoni" id="0.99">Peperoni</input>
            <input type="checkbox" name="cheese" id="0.99">Pesto</input>
        </form>
        </fieldset>
        <br>
    </div>
    <div id="extraPizza"></div>
    <center><button id="addPizza"> Add Pizza </button></center>

JavaScript:

var pizzaCost = 0.00;
var toppingCost = 0.00;
var sideCost = 0.00;
var drinkCost= 0.00;
var desertCost = 0.00;
var desertSizeCost = 0.00;
var drinkSizeCost = 0.00;
var sideSizeCost = 0.00;

$("#pizzaSize").prop('disabled', true);

$("#pizza").change(function() {
    $("#pizzaSize").prop('disabled', false);
})

$( "#pizzaSize" ).change(function() {
    $("input[type='checkbox']").prop('disabled', false);
    var selectionPrice = $('option:selected', this).attr('id');
    var selectionInt = parseFloat(selectionPrice, 10);
    pizzaCost = selectionInt;
    calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost);
});

$('input[type=checkbox]').change(function(){
    var checked = $(":checkbox:checked").length;
    toppingCost = 0.99 * checked;
    calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost);
});

function calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, drinkSizeCost, sideSizeCost) {
    var total = pizzaCost + toppingCost + sideCost + drinkCost + desertCost + desertSizeCost + drinkSizeCost + sideSizeCost;
    $("#totalPrice").text(total.toFixed(2));
}

$( "#addPizza" ).click(function() {
  $("#pizzaForm").clone().appendTo("#extraPizza");
});
SamG
  • 303
  • 4
  • 13
  • 1
    Learn about event delegation: https://learn.jquery.com/events/event-delegation/ where you bind the event not to the element itself but delegate it to the document or a container element that always exists on the page. – Victor Levin Dec 17 '15 at 21:33

1 Answers1

5

You should use jQuery on delegation when registering your events so that it will work for the dynamically created and injected form elements.

$(document).on("change","#pizzaSize", function() {
    $("input[type='checkbox']").prop('disabled', false);
    var selectionPrice = $('option:selected', this).attr('id');
    var selectionInt = parseFloat(selectionPrice, 10);
    pizzaCost = selectionInt;
    calculateCost(pizzaCost, toppingCost, sideCost, drinkCost, desertCost, desertSizeCost, 
                                                             drinkSizeCost, sideSizeCost);
});

Also, I see a few issues with your code. First of you should not keep Id's on your form elements because you are making a clone. Also you should not bind your events by using jQuery selection using Id. No more than one element should have the same Id. Keep some css class on the element which you can use to register your click event code. Also do not keep the price in the id property values. What if 2 items has same price ? Same Id ? That is not correct. You should keep the price in HTML 5 data attribute.

You can use closest() method to get to the parent container and then use find to get a reference to the relative size dropdown.

$(document).on("change", ".pizza", function () {
    var _this = $(this);
    _this.closest("fieldset").find(".size").prop('disabled', false);

});

Here is a working sample with the changes i mentioned.

Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thank you for your solution. However the total cost now just changes based off the new cloned input, rather than adding the additional costs. How do I circumvent that issue? – SamG Dec 17 '15 at 21:56
  • @SamG Take a look at my updated answer. Addressed few issues with your current implementation. – Shyju Dec 18 '15 at 02:45