I am making what I call a PM (Preventive Maintenance) Kit list. My users will use this list to generate a printable sheet to tell me what they used out of there kit. The list includes pricing per part and I would like the list to calculate the costing as they enter each item. So a total per line and an overall total cost.

I have included a snap shot of the page and below is the code.
I can do this sort of thing on a small scale with just adding two lines but I am not sure how to modify it to handle this scale. You can see the script towards the bottom of the page. That is my lame attempt to make the per line costing happen but NOTHING happens.

<?php
	require "../config/bpts_config.php";
	// Start the session
	//session_start();
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
	<title>PM Kit Listing - Edit</title>
    <?php include("../includes/pm_kit_css_js_includes.php"); ?>
</head>

<body>
	<div id="container">
        <div id="header_container">
			<?php include("../includes/header.php"); ?>
        </div>
		
        <div id="upper_container">
        	<div id="upper_2col_left"></div>
			<div id="upper_2col_right"> <a href='index.php'>Back To Listing</a> </div>
        </div>
        
        <div id="body_container">
            <div id="body_content">
            	<?php
				$pm_kit_type_ID = (int) $_GET['pm_kit_type_ID'];
				// Select all the pm kit items, ordered by Part Name:
				$pm_kit_parts_SQL = mysql_query("SELECT * from pm_kit_parts JOIN sage_part_listing
										WHERE pm_kit_type_ID = $pm_kit_type_ID 
										AND pm_kit_parts.SKICPart = sage_part_listing.SKICPart 
										AND 'status' = 0 
										ORDER BY `sage_part_listing`.`ID` ASC") or die(mysql_error());
				?>
				<table>
					<tr>
                    	<th>Qty</th>
						<th>Part Number</th>
						<th>Description</th>
                        <th>Cost Each</th>
						<th width="60px">Qty Used</th>
                        <th width="60px">Total</th>
                        <th width="60px">Spares</th>
                        <th width="60px">Total</th>
					</tr>
                    <?php
					while($info = mysql_fetch_array($pm_kit_parts_SQL)) {
					?>
					<tr>
                        <? $parts_ID = $info['pm_kit_parts_ID']; ?>
                        <td align="center"><? echo $info['quantity']; ?></td>
						<td><? echo $info['ID']; ?></td>
						<td><? echo $info['Description1'] . $info['extended_description']; ?></td>
                        <td align="right"><? echo "$" . number_format($info['PartCost'],2, '.', ','); ?></td>
                        
						<td><input style="text-align:center" name="qty_used" type="text" size="8" onclick="calculateTotal<? echo $parts_ID; ?>(this.form)"></td>
                        <td><input style="text-align:right" name="qty_used_total" type="text" size="8"></td>
                        <td><input style="text-align:center" name="spares_left" type="text" size="8"></td>
                        <td><input style="text-align:right" name="spares_left_total" type="text" size="8"></td>
					</tr>
                    <script language="javascript" type="text/javascript">
						function calculateTotal<? echo $parts_ID; ?>(myForm) {
							var item1 = Number(myForm.qty_used.value);
							var qty_total;
							
							if (myForm.item1.value==true) { qty_total = item1 * <? $info['PartCost']; ?>; }
							else if myForm.item1.value==false) { order_total = 0.00; }
							
							myForm.qty_used_total.value = order_total.toFixed(2);
						}
					</script>
					<?php } ?>
				</table>
			</div>
		</div>

</body>
</html>

Ken

Dani AI

Generated

Nice progress, . Your per-row math works, but generating one JS function per row and summing by nth-child makes maintenance brittle (column order changes = broken). A simpler pattern is to mark each row with its unit cost and use one delegated handler to recalc the row and the grand totals. With jQuery 1.5.1, use .delegate (not .on). This also keeps currency formatting out of inputs so you do not have to strip the $ later. Thanks for jumping in.

Drop this at the bottom of the page (assumes your table id is data, each data row has class line, and you render unit price onto the row with data-cost="<price>"; also add three total placeholders: #total_used_cost, #total_spares_cost, and #grand_total).

$(function () {
  function calcRow($tr) {
    var cost   = Number($tr.data("cost")) || 0;
    var used   = Number($tr.find("input.qty-used").val()) || 0;
    var spares = Number($tr.find("input.spares-left").val()) || 0;

    var usedTotal   = used * cost;
    var sparesTotal = spares * cost;

    $tr.find(".row-total").text("$" + usedTotal.toFixed(2));
    $tr.find(".spares-total").text("$" + sparesTotal.toFixed(2));
    return { usedTotal: usedTotal, sparesTotal: sparesTotal };
  }

  function calcGrand() {
    var sumUsed = 0, sumSpares = 0;
    $("#data tr.line").each(function () {
      var t = calcRow($(this));
      sumUsed  += t.usedTotal;
      sumSpares+= t.sparesTotal;
    });
    $("#total_used_cost").text("$" + sumUsed.toFixed(2));
    $("#total_spares_cost").text("$" + sumSpares.toFixed(2));
    $("#grand_total").text("$" + (sumUsed + sumSpares).toFixed(2));
  }

  $("#data").delegate("input.qty-used, input.spares-left", "keyup change", function () {
    calcRow($(this).closest("tr.line"));
    calcGrand();
  });

  calcGrand(); // initial paint
});

Markup example per row (server renders cost once):

  • <tr class="line" data-cost="5.00"> ... <td><input class="qty-used"></td><td class="row-total">$0.00</td> ... <td><input class="spares-left"></td><td class="spares-total">$0.00</td> ... </tr>

Tips: keep totals as text (not inputs), default empty inputs to 0 with Number(...)||0, and if you ever add rows dynamically, .delegate will still catch the events.

Recommended Answers

All 4 Replies

Okay I figured out how to calculate per row using javascript within the php. Now how do I sum the totaled column? Here is the code.

<?php
	require "../config/bpts_config.php";
	// Start the session
	//session_start();
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
	<title>PM Kit Listing - Edit</title>
    <?php include("../includes/pm_kit_css_js_includes.php"); ?>
    <script src="../js/jquery-1.5.1.min.js" type="text/javascript" charset="utf-8"></script>
    
</head>

<body>
	<div id="container">
        <div id="header_container">
			<?php include("../includes/header.php"); ?>
        </div>
		
        <div id="upper_container">
        	<div id="upper_2col_left"></div>
			<div id="upper_2col_right"> <a href='index.php'>Back To Listing</a> </div>
        </div>
        
        <div id="body_container">
            <div id="body_content">
            	<?php
				$pm_kit_type_ID = (int) $_GET['pm_kit_type_ID'];
				// Select all the pm kit items, ordered by Part Name:
				$pm_kit_parts_SQL = mysql_query("SELECT * from pm_kit_parts JOIN sage_part_listing
										WHERE pm_kit_type_ID = $pm_kit_type_ID 
										AND pm_kit_parts.SKICPart = sage_part_listing.SKICPart 
										AND 'status' = 0 
										ORDER BY `sage_part_listing`.`ID` ASC") or die(mysql_error());
				?>
				<table>
					<tr>
                    	<th>Qty</th>
						<th>Part Number</th>
						<th>Description</th>
                        <th>Cost Each</th>
						<th width="60px">Qty Used</th>
                        <th width="60px">Total</th>
                        <th width="60px">Spares</th>
                        <th width="60px">Total</th>
					</tr>
                    <form>
                    <?php
					while($info = mysql_fetch_array($pm_kit_parts_SQL)) {
					?>
					<tr>
                        <? $parts_ID = $info['pm_kit_parts_ID']; ?>
                        <td align="center"><? echo $info['quantity']; ?></td>
						<td><? echo $info['ID']; ?></td>
						<td><? echo $info['Description1'] . $info['extended_description']; ?></td>
                        <td align="right"><? echo "$" . number_format($info['PartCost'],2, '.', ','); ?></td>
                        
						<td><input style="text-align:center" name="qty_used<? echo $parts_ID; ?>" type="text" size="8" onKeyUp="calculateTotal<? echo $parts_ID; ?>(this.form)"></td>
                        <td><input style="text-align:right" name="qty_used_total<? echo $parts_ID; ?>" type="text" size="8" value="$0.00" readonly></td>
                        <td><input style="text-align:center" name="spares_left" type="text" size="8"></td>
                        <td><input style="text-align:right" name="spares_left_total<? echo $parts_ID; ?>" type="text" size="8" value="$0.00" readonly></td>
					</tr>
                    
					<script language="javascript" type="text/javascript">
                        function calculateTotal<? echo $parts_ID; ?>(myForm) {
                            var item1 = (myForm.qty_used<? echo $parts_ID; ?>.value);
							var partsID = ( <? echo $parts_ID; ?> );
							var PartCost = ( <? echo $info['PartCost']; ?> );
							var qtyTotal = item1 * PartCost;
                    
                            myForm.qty_used_total<? echo $parts_ID; ?>.value = "$"+qtyTotal.toFixed(2);
						}
					</script>
                    
					<?php } ?>
                    </form>
				</table>
			</div>
		</div>
	</div>
</body>
</html>

Thank you for looking urtrivedi but that does not help in my case. In that link all of the info is already in the database and only php code is needed. My problem requires users to enter the qty needed so javascript is required.
Thank you for trying.
Ken

I figured out how to do it.
Here is how I did it.

This is the javascript placed inside of the php while loop that generates the table.
This scripts calculates the extended total of each row in the table
So Part x is $5 dollars. User enters 10 and it puts $50 in the total column.

<script language="javascript" type="text/javascript">
	function calculateTotal<? echo $parts_ID; ?>(myForm) {
		var item1 = (myForm.qty_used<? echo $parts_ID; ?>.value);
		var partsID = ( <? echo $parts_ID; ?> );
		var PartCost = ( <? echo $info['PartCost']; ?> );
		var qtyTotal = item1 * PartCost;

		myForm.qty_used_total<? echo $parts_ID; ?>.value = "$" + qtyTotal.toFixed(2);
		sumOfColumns("data",6,true,"total_used_cost");
		sumOfColumns("data",8,true,"total_spares_cost");
		
	}
</script>

The last two lines call the column total script.

<script type="text/javascript">
	function sumOfColumns(tableID, columnIndex, hasHeader, displayWhereID) {
	  var total_cost = 0;
	  $("#" + tableID + " tr" + (hasHeader ? ":gt(0)" : ""))
	  .children("td:nth-child(" + columnIndex + ")")
	  .each(function() {
		total_cost += parseFloat($(this).find("input").val().replace('$',''));

	  });
	  $("#" + displayWhereID ).html("$" + total_cost);
	}
</script>

This was hard to figure out for a beginner like me. The script is used to total all of the column totals.
Most of it came from
I had to change it to look inside a text box rather than inside the td of the table.
I also added the replace to remove the "$" sign.
Ken

commented: Good work +11
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.