JavaScript to calculate shopping cart

This is my first shot at writing a JavaScript to calculate a shopping cart. Naturally, it doesn’t work. I was hoping someone out there would be able to offer some suggestions as to how to fix it.

Thanks in advance for your help!!

/* I built this script based on the guidance and examples I found

here:

http://www.javascript-coder.com/javascript-form/javascript-calcul

ator-script.phtml
*/



<script>
var theForm = document.forms["order"];

var bakery_prices= new Array();
bakery_prices["None"]=0;
bakery_prices["sourdough"]=5;
bakery_prices["bread"]=3;

var mns_prices= new Array();
mns_prices["None"]=0;
mns_prices["filet"]=5;
mns_prices["fish"]=5;

var produce_prices= new Array();
produce_prices{["None"]=0;
produce_prices["asparagus"]=3;
produce_prices["pineapple"]=2;

var cnd_prices= new Array();
cnd_prices["None"]=0;
cnd_prices["cheddar"]=3;
cnd_prices["milk"]=4;

var wine_prices= new Array();
wine_prices["None"]=0;
wine_prices["chardonnay"]=25;
wine_prices["merlot"]=20;


function getbakeryPrice()
{
    var bakeryPrice=0;
    var theForm = document.forms["order"];
    var selectedbakery = theForm.elements["bakery"];
    bakeryPrice = bakery_prices[selectedbakery.value];

    return bakeryPrice;
}
function getmnsPrice()
{
    var mnsPrice=0;
    var theForm = document.forms["order"];
    var selectedmns = theForm.elements["mns"];
    mnsPrice = mns_prices[selectedmns.value];

    return mnsPrice;
}
function getproducePrice()
{
    var producePrice=0;
    var theForm = document.forms["order"];
    var selectedproduce = theForm.elements["produce"];
    mnsPrice = produce_prices[selectedproduce.value];

    return producePrice;
}
function getcndPrice()
{
    var cndPrice=0;
    var theForm = document.forms["order"];
    var selectedcnd = theForm.elements["cnd"];
    mnsPrice = cnd_prices[selectedcnd.value];

    return cndPrice;
}
function getwinePrice()
{
    var winePrice=0;
    var theForm = document.forms["order"];
    var selectedwine = theForm.elements["wine"];
    mnsPrice = wine_prices[selectedwine.value];

    return winePrice;
}

function calculateTotal()
{
    var totalPrice = getbakeryPrice() + getmnsPrice() +

getproducePrice() + getcndPrice() + getwinePrice();

var divobj = document.getElementById('totalPrice');
divobj.style.display="block";
divobj.innerHTML = "Your Order Total is $"+totalPrice;
}

function hideTotal()
{
    var divobj = document.getElementById('totalPrice');
    divobj.style.display='none';
}

</script>

Here’s an update to the code, where the arrays or prices have been removed and had the prices put in to the select field.
I’ve also refactored the functions so that they all perform very simple tasks, and as such they become much easier to modify and maintain.

You’ll also find that there’s a demo page with this code up at http://jsfiddle.net/pmw57/NcLuG/3/


function getPrice(itemField) {
    return itemField.value || 0;
}

function getQuantity(quantityField) {
    return parseInt(quantityField.value, 10) || 0;
}

function updateItemQuantity(itemField, quantityField) {
    var quantity = getQuantity(quantityField);
    if (quantity < 1) {
        quantity = 1;
    }
    
    if (getPrice(itemField)) {
        quantityField.value = quantity;
    } else {
        quantityField.value = quantityField.defaultValue;
    }
}

function getItemTotal(itemField, quantityField) {
    return getPrice(itemField) * getQuantity(quantityField);
}

function hide(el) {
    el.className = 'hidden';
}

function show(el) {
    el.className = '';
}

function updateTotal(el, amount) {
    hide(el);
    if (amount > 0) {
        show(el);
        el.innerHTML = "Your Order Total is $" + amount;
    }
}
    
function forEachFormItem(form, items, func) {
    var i,
        item,
        itemField,
        quantityField,
        result = 0;
    for (i = 0; i < items.length; i += 1) {
        item = items[i];
        itemField = form.elements[item],
        quantityField = form.elements[item + 'quantity'],
        result += func(itemField, quantityField);
    }
    return result;
}

function calculateTotal() {
    var form = this,
        items = ['bakery', 'mns', 'produce', 'cnd', 'wine'],
        total = 0,
        priceField = form.priceField;
    
    forEachFormItem(form, items, updateItemQuantity);
    total = forEachFormItem(form, items, getItemTotal);

    updateTotal(priceField, total);
}

var theForm = document.getElementById('order');
theForm.priceField = document.getElementById('totalPrice');
theForm.onchange = calculateTotal;
&#8203;

Paul - Thanks so much for all your help!! As I said earlier, it was my first attempt to write a shopping cart script. Obviously still a lot of practice required. :slight_smile:

One of the updates that I made is to set the quantity field to 1 when someone chooses an item.

Because we don’t want functions that get values (such as to get the item totals) to also set the quantity as a side effect, it’s better to set the quantity first, and then to get the item totals. That would normally mean though creating two early identical loops in separate functions, one to set the quantity, and another function to get the item totals.

So instead, there is one single function that loops through the items, and passes those item and quantity fields on to whichever function is given.


function forEachFormItem(form, items, func) {
    var i,
        item,
        itemField,
        quantityField,
        result = 0;
    for (i = 0; i < items.length; i += 1) {
        item = items[i];
        itemField = form.elements[item],
        quantityField = form.elements[item + 'quantity'],
        result += func(itemField, quantityField);
    }
    return result;
}

Which allows us to update the quantity fields of the form with:


forEachFormItem(form, items, updateItemQuantity);

Or to get the item totals with:


total = forEachFormItem(form, items, getItemTotal);

If we want to push things further than that, we can rewrite the forEachFormItem function using more modern JavaScript, so that it is:


function forEachFormItem(form, items, func) {
    var result = 0;
    items.forEach(function (item) {
        var itemField = form.elements[item],
            quantityField = form.elements[item + 'quantity'];
        result += func(itemField, quantityField);
    });
    return result;
}

Or, we can make the function even smaller still by using the reduce method, but at the cost of understanding what’s going on:


function forEachFormItem(form, items, func) {
    return items.reduce(function (result, item) {
        return result + func(form.elements[item], form.elements[item + 'quantity']);
    }, 0);
}

So that’s getting the the point of being too compact to easily understand, which makes the previous function or the code from earlier ends up being a better choice, due to how much easier it is to understand what they’re doing.