Designing forms is very much about human behavior. If there's a way to screw up something it will happen. When you want accurate data you can't count on a user to enter only certain numbers, or only positive numbers, etc. Yes, you can script against it, but it's much easier just to use a <select> input tag. That way you're assured the number entered will fit your parameters.
Secondly, if you write to an <input type="text"> tag, you're leaving that tag open to "adjustment" by the user, making the data unusable to you.
Third, I always like to give the user "instant results". And I like "pretty printing" in case the user really wants to print the page.
With all that in mind, here's a rebuild of your page. I've commented things so hopefully you'll see what's going on.
<!DOCTYPE html>
<!-- EX02.html-->
<html lang = "en">
<head>
<meta charset="utf-8">
<title> Basic Computer Store </title>
<script src="calculate.js"></script>
</head>
<body onload="total()"> <!-- runs the total for the first time and displays it in the Grand Total -->
<h2> Welcome to the Basic Computer Store </h2>
<h3> choose your Basic Upgrades for a basic price </h3>
<img class = "Left" src = "download.png" alt = "Picture of computer"/>
<table>
<tr>
<th colspan="3" style="text-align:right;"> Base Price </th>
<th style="text-align:right;"> $<span name="total">999.99</span> </th>
</tr>
<tr>
<th> Add-on </th>
<th> quantity </th>
<th> Add-on Price </th>
<th> Add-on Total </th>
</tr>
<tr>
<td> 1.21 Jiggawatt Powersupply </td>
<td> <select id="ps" name="ps" onchange="calc(this,pscost,pstot)"> <!--Each time this changes pass the id's to the calc function and run it-->
<option value=""></option>
<option value="1">1</option> <!--Add or remove options/numbers as needed-->
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select> </td>
<td> $<span id="pscost">1985</span> </td>
<td style="text-align:right;"> $<span id="pstot" name="total"></span> </td>
</tr>
<tr>
<td> Brainpower™ Memory Upgrade </td>
<td> <select id="mem" name="mem" onchange="calc(this,memcost,memtot)">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select> </td>
<td> $<span id="memcost">1337</span> </td>
<td style="text-align:right;"> $<span id="memtot" name="total"></span> </td>
</tr>
<tr>
<td> Mouse </td>
<td> <select id="mouse" name="mouse" onchange="calc(this,mousecost,mousetot)">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select> </td>
<td> $<span id="mousecost">1</span> </td>
<td style="text-align:right;"> $<span id="mousetot" name="total"></span> </td>
</tr>
<tr>
<td colspan="3" style="text-align:right;"> Grand Total </td>
<td style="text-align:right;"> $<span id="total" name="gtotal"></span> </td>
</tr>
</table>
<p><a href = "http://www.hpu.edu/"> <input type="button" value="exit" onClick=""> </a></p>
</body>
</html>
Save this as calculate.js in the same folder as your page:
function calc(el,cost,tot){ // create variables from the id's passed from the page, allowing this function to be reused
var x = el.value, // # selected
y = cost.innerHTML, // cost per item.
t = x*y; // multiply # x cost
tot.innerHTML = t; // display subtotal on page
total(); // go to "function total()" below to add all the subtotals to the base price, this retotals everything when any number is changed by the user.
}
function total(){ // this function runs on pageload to drop an initial grand total (the base price) on the page.
var sub = document.getElementsByName("total"), // get all elements with the name="total" attribute
t = document.getElementById("total").innerHTML; // get the current amount of the grand total and create the variable
t=0; // zero the grand total so new numbers don't get added to old totals if someone changes a 2 to a 1 e.g.
for(var i = 0; i < sub.length; i++){ // iterate through all the subtotals
var a = sub[i].innerHTML, // on each iteration, get the number, add it to the grand total, and create a new grand total
b = 1*a+1*t,
b2 = b.toFixed(2); // forces grand total to 2 decimal places -- with large numbers it was going beyond that
t = b2;
document.getElementById("total").innerHTML = t; // display the grand total on the page
}
}
Lastly, you didn't indicate that the data would be submitted online. If so, it's fairly trivial to copy the data into hidden inputs for form handling purposes.