Hi there, I am a PHP developer and know little of JS - in my current project I have hit a few probs as I know I need to incoporate some JS. After some help already from this community I have almost completed the JS part of one page that totals without needing a refresh.

I have looked up JS resources that show me how easy it is to take a value and make it and change it to 2 dec places. However, I can not seem to put the relevant code into the function - a very scaled down version of the function is

<script language="JavaScript">
function sumtot()
{
  var unit_price, qty, tot;
 
  unit_price = document.box.unit_price.value;
  qty  = document.box.qty.value;
  tot  = document.box.tot.value;
  document.box.tot.value = (unit_price * qty);
}
</script>

In reality all the the JS is created using PHP dependant upon the items on the page and the unit_price is pulled from a DB Table and the qty is entered for each by the visitor.

What do I need to do to a) format sumtot() to [0.00] to 2.d.p and b) if you have time, the final issue, I would like to ensure that dependant upon the unit[each or kilo] that inputs into the qty field can only accept whole integers and 1 d.p. respectively.

If it helps, I did not want to clog up the start of the post with a load of mark-up, below is an example of the XHTML generated by my PHP/JS - many thanks in advance for any assistance - A

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="http://www.slipstream-organics.co.uk/css.css" />
<meta name="author" content="" />
<meta name="description" content="" />
<meta name="keywords" content="" />	<script language='JavaScript'>function sumtot() {var  unit_price_8, qty_8, unit_price_9, qty_9, unit_price_10, qty_10, unit_price_12, qty_12, tot;unit_price_8=document.box.unit_price_8.value; unit_price_9=document.box.unit_price_9.value; unit_price_10=document.box.unit_price_10.value; unit_price_12=document.box.unit_price_12.value; qty_8 = document.box.qty_8.value; qty_9 = document.box.qty_9.value; qty_10 = document.box.qty_10.value; qty_12 = document.box.qty_12.value; document.box.tot.value =  (unit_price_8 * qty_8) +  (unit_price_9 * qty_9) +  (unit_price_10 * qty_10) +  (unit_price_12 * qty_12) +  0;}</script>
</head>
<body>
<img src="../images/logo.gif" width="400" height="47">



	<table style='width:400px;'>
	 <tr>
		<td colspan='2' style='color:#363;font-weight:bold;text-align:left;line-height:1.5em;font-family:verdana, helvetics, sans-serif;'>Your Details</td>
	 </tr>
	</table>
	<table style='width:400px;background:rgb(230,240,230);'>
	 <tr>
		<td><p class='header'>Name: </p></td><td><p class='header'> PLANT</p></td>
	 </tr>
		<td style='vertical-align:top;'><p class='header'><p class='header'>Address: </p></td>
		<td><p class='header'>2&nbsp;John Daniels Way<br />Churchdown<br />Glos<br />GL3 2QY</p></td>
	 </tr>	 <tr>
		<td><p class='header'>Delivery Round: </p></td><td><p class='header'>Gloucester1</p></td></tr></table><br /><p class='header' style='color:#800;'>THIS ORDER WILL <b>REPLACE</b> YOUR ORDER <b>THIS</b> WEEK</p><p>Some text here to explain what to do, Nick...</p><form method='POST' name='box' action='order.php'><table style='color:#363;font-size:85%;font-family:verdana, helvetica, sans-serif;'>
       <tr>
	  <td><b>Product</b></td>
	  <td style='width:50px;text-align:left;'><b>Unit</b></td>
	  <td style='text-align:right;'><b>Price</b></td>
	  <td><b>Qty</b></td>
	  <td><b>Line Total</b></td>
	 </tr><tr>
				<td>Potatoes</td>
				<td>Kilo</td>
				<td>&pound;0.66</td><input type='hidden' name='unit_price_8' value='0.66' />
				<td><input type='text' size='4' name='qty_8' /><td>
				<td>ln tot</td>
			</tr><tr>
				<td>Carrot</td>
				<td>Kilo</td>
				<td>&pound;0.84</td><input type='hidden' name='unit_price_9' value='0.84' />
				<td><input type='text' size='4' name='qty_9' /><td>
				<td>ln tot</td>
			</tr><tr>
				<td>Onions</td>
				<td>Kilo</td>
				<td>&pound;1.60</td><input type='hidden' name='unit_price_10' value='1.60' />
				<td><input type='text' size='4' name='qty_10' /><td>
				<td>ln tot</td>
			</tr><tr>
				<td>Cauliflower</td>
				<td>Each</td>
				<td>&pound;1.20</td><input type='hidden' name='unit_price_12' value='1.20' />
				<td><input type='text' size='4' name='qty_12' /><td>
				<td>ln tot</td>
			</tr></table><input type='submit' value='Send Order' /><input name='tot' type='text' /><input type='button' value='Calculate' onClick='sumtot()'></form>
 

</body>
</html>

Recommended Answers

All 12 Replies

Aventurine,

First, implement the solution I gave you to your earlier topic. It addresses much of what you are asking.

Airshow

Hi Airshow, I was really hoping that you would not see my latest post! I have tried to understand the logic in your post and as a non-JS guy could not see where all my vars would fit into it.

Adding the value="" to the hidden input makes the script work, felt like a dunce for not noticing the omission, I call it snow-blindness when you look at a page of mark-up for 3 hours and keep missing the same thing.

Are you saying that simply adding your function will solve this or is their more I need to do to adapt?

In the meantime, I will put it and see - thanks for your patience and help

A

Aventurine,

My version of sumtot reads all the necessary data from the DOM, making it unnecessary to dynamically write any javascript.

It's easy to make a working demo of my code.

  • Make a fresh web page with doctype, head, html & body tags (standard stuff).
  • In the head, insert script tags then paste in my javascript
  • In the body, paste my HTML.
  • Save the file as eg. airshow_demo.html and open in your browser.

I would paste my saved version but I'm away from home right now and it's several miles away on my desktop.

To install in your PHP page:

  • Replace all your php-written js with my hard-coded, static js (in the document's head as per the demo).
  • Arrange for your php to build out the (nested) table based on the html in the demo. It is largely the same as your original but with some important mods.

Suggest you backup your page before trying it out.

Airshow

Hi there again, I would very much appreciate it if you would send me the version you have created, I have created an htm page as suggested - see below but get the following error that I think relates to the sumtot()

Line: 82
Char: 1
Error: Object expected
Code: 0

Thanks again - A

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="styles.css" />
<meta name="author" content="" />
<meta name="description" content="" />
<meta name="keywords" content="" />	
<script language='JavaScript'>
onload = function() {	var products = document.getElementById('products'); 	function getPID(id) {//utility function		return id.split('_')[1];//extract n from "pid_n"	} 	function sumtot() {		var tot = 0;		for(var i=0; i<products.rows.length; i++) {			var pid = getPID(products.rows[i].id);			var unit_price = Number(document.box['unit_price_'+pid].value);			var qty = Number(document.box['qty_'+pid].value);			var ln_tot = unit_price * qty;			if(!isNaN(ln_tot)) {				var line_total_cell = document.getElementById('ln_tot_'+pid);				if(line_total_cell) { line_total_cell.innerHTML = "&pound;" + ln_tot.toFixed(2); }				if(tot !== false) { tot += ln_tot; }			}			else {				document.getElementById('ln_tot_'+pid).innerHTML = "error";				tot = false;			}		}		var totPrint = (tot === false) ? 'error' : tot.toFixed(2);		document.box.tot.value = totPrint;// tot		document.getElementById('tot2').innerHTML = totPrint; // tot2	} 	//Here we give eqach of the qty fields an event handler for automatic, spreadsheet-like calculation	for(var i=0; i<products.rows.length; i++) {		var pid = getPID(products.rows[i].id);		var qtyField = document.box['qty_'+pid];		if(qtyField) { qtyField.onkeyup = qtyField.onblur = sumtot; }	}	document.getElementById('calcButton').onclick = sumtot; 	sumtot();//This ensures that initial products and total are shown (eg. zeros all through)};onload = function() {
	var products = document.getElementById('products');
	
	function getPID(id) {//utility function
		return id.split('_')[1];//extract n from "pid_n"
	}

	function sumtot() {
		var tot = 0;
		for(var i=0; i<products.rows.length; i++) {
			var pid = getPID(products.rows[i].id);
			var unit_price = Number(document.box['unit_price_'+pid].value);
			var qty = Number(document.box['qty_'+pid].value);
			var ln_tot = unit_price * qty;
			if(!isNaN(ln_tot)) {
				var line_total_cell = document.getElementById('ln_tot_'+pid);
				if(line_total_cell) { line_total_cell.innerHTML = "&pound;" + ln_tot.toFixed(2); }
				if(tot !== false) { tot += ln_tot; }
			}
			else {
				document.getElementById('ln_tot_'+pid).innerHTML = "error";
				tot = false;
			}
		}
		var totPrint = (tot === false) ? 'error' : tot.toFixed(2);
		document.box.tot.value = totPrint;// tot
		document.getElementById('tot2').innerHTML = totPrint; // tot2
	}
	
	//Here we give eqach of the qty fields an event handler for automatic, spreadsheet-like calculation
	for(var i=0; i<products.rows.length; i++) {
		var pid = getPID(products.rows[i].id);
		var qtyField = document.box['qty_'+pid];
		if(qtyField) { qtyField.onkeyup = qtyField.onblur = sumtot; }
	}
	document.getElementById('calcButton').onclick = sumtot;

	sumtot();//This ensures that initial products and total are shown (eg. zeros all through)
};
</script>
</head>
<body>

<form method='POST' name='box' action='order.php'>
	<table style="color:#363;font-size:85%;font-family:verdana, helvetica, sans-serif;" border> 
	 <tr><th>Product</th><th style="width:50px;text-align:left;">Unit</th><th style="text-align:right;">Price</th><th>Qty</th><th>Line Total</th></tr>
	 <tbody id="products"><!-- This is critical --> 
	 <tr id="pid_8"><!-- Give each row an id reflecting its pid -->
		<td>product_description 8</td>
		<td>unit</td>
		<td>&pound;1.50</td><input type="hidden" name="unit_price_8" value="1.5" />
		<td><input type="text" size="4" name="qty_8" value="0" style="text-align:center;" /></td>
		<td id="ln_tot_8" align="center"></td>
	 </tr> 
	 <tr id="pid_9">
		<td>product_description 9</td>
		<td>unit</td><td>&pound;2.50</td><input type="hidden" name="unit_price_9" value="2.5" />
		<td><input type="text" size="4" name="qty_9" value="0" style="text-align:center;" /></td>
		<td id="ln_tot_9" align="center"></td>
	 </tr> 
	 <tr id="pid_12">
		<td>product_description 12</td>
		<td>unit</td>
		<td>&pound;3.00</td><input type="hidden" name="unit_price_12" value="3.0" />
		<td><input type="text" size="4" name="qty_12" value="0" style="text-align:center;" /></td>
		<td id="ln_tot_12" align="center"></td>
	 </tr> </tbody> 
	</table>
	Total &pound;&nbsp;<input name="tot" type="text" disabled />
	&nbsp;Total &pound;<span id="tot2"></span>
	<br /><br />
	<input id="calcButton" type="button" value="Calculate" onClick="sumtot()" /></form>

</body>
</hmtl>

I'm not too sure why that didn't work.

Try this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Airshow :: product_totals</title>
<script language="JavaScript">
onload = function() {
	var products = document.getElementById('products');
	
	function getPID(id) {//utility function
		return id.split('_')[1];//extract n from "pid_n"
	}

	function sumtot() {
		var tot = 0;
		for(var i=0; i<products.rows.length; i++) {
			var pid = getPID(products.rows[i].id);
			var unit_price = Number(document.box['unit_price_'+pid].value);
			var qty = Number(document.box['qty_'+pid].value);
			var ln_tot = unit_price * qty;
			if(!isNaN(ln_tot)) {
				var line_total_cell = document.getElementById('ln_tot_'+pid);
				if(line_total_cell) { line_total_cell.innerHTML = "&pound;" + ln_tot.toFixed(2); }
				if(tot !== false) { tot += ln_tot; }
			}
			else {
				document.getElementById('ln_tot_'+pid).innerHTML = "error";
				tot = false;
			}
		}
		var totPrint = (tot === false) ? 'error' : tot.toFixed(2);
		document.box.tot.value = totPrint;// tot
		document.getElementById('tot2').innerHTML = totPrint; // tot2
	}
	
	//Here we give eqach of the qty fields an event handler for automatic, spreadsheet-like calculation
	for(var i=0; i<products.rows.length; i++) {
		var pid = getPID(products.rows[i].id);
		var qtyField = document.box['qty_'+pid];
		if(qtyField) { qtyField.onkeyup = qtyField.onblur = sumtot; }
	}
	document.getElementById('calcButton').onclick = sumtot;

	sumtot();//This ensures that initial products and total are shown (eg. zeros all through)
};
</script>  
</head>

<body>
<form method='POST' name='box' action='order.php'>
<table style="color:#363;font-size:85%;font-family:verdana, helvetica, sans-serif;" border>

<tr>
<th>Product</th>
<th style="width:50px;text-align:left;">Unit</th>
<th style="text-align:right;">Price</th>
<th>Qty</th>
<th>Line Total</th>
</tr>

<tbody id="products"><!-- This is critical -->

<tr id="pid_8"><!-- Give each row an id reflecting its pid -->
<td>product_description 8</td>
<td>unit</td>
<td>&pound;1.50</td><input type="hidden" name="unit_price_8" value="1.5" />
<td><input type="text" size="4" name="qty_8" value="0" style="text-align:center;" /></td>
<td id="ln_tot_8" align="center"></td>
</tr>

<tr id="pid_9">
<td>product_description 9</td>
<td>unit</td>
<td>&pound;2.50</td><input type="hidden" name="unit_price_9" value="2.5" />
<td><input type="text" size="4" name="qty_9" value="0" style="text-align:center;" /></td>
<td id="ln_tot_9" align="center"></td>
</tr>

<tr id="pid_12">
<td>product_description 12</td>
<td>unit</td>
<td>&pound;3.00</td><input type="hidden" name="unit_price_12" value="3.0" />
<td><input type="text" size="4" name="qty_12" value="0" style="text-align:center;" /></td>
<td id="ln_tot_12" align="center"></td>
</tr>

</tbody>

</table>
Total &pound;&nbsp;<input name="tot" type="text" disabled />&nbsp;Total &pound;<span id="tot2"></span>
<br /><br />
<input id="calcButton" type="button" value="Calculate" />
</form>
</body>
</html>

I made one minor adjustment but it's something that shouldn't make any difference.

Remember to "allow blocked content" if asked (as I do in IE8 when browsing files locally).

Airshow

Hi Airshow, still not working my friend. You have spent some time on this now, the old, more complicated way works - if I could just get the total to 2dp and within sumtot() create the line totals aswell - here is the error I got with the new markup:

Line: 19
Char: 4
Error: 'document.box[...].value' is null or not an object
Code: 0

Is it my demo that won't work or have you tried to integrate into your PHP?

Either way, the html must be compatible with the javascript, so make sure to browse the whole page exactly as I posted (or adapt as appropriate to build the html with with php).

If you still get the same error, then insert alert(pid) one line above the line that gives the error. What does it give?

What browser are you using? I successfully tested the demo in IE6 & 8, latest FF and latest Opera.

If you can get it going then (a) you will find that it already does line totals and grand total, both to 2dp; (b) you will like it.

Airshow

Hi Airshow, I did not complicate the thing by adding PHP, I simply took your function() and the XHTML mark up as I posted and got the error.

My set up is OS: XP 64 [like the RAM capacity - 16GB so far and much room for expansion] and IE7-version 7.0.5730.13, when MS make a new browser W3C-compliant as MS promised to make IE8 I will start using it. For preference I use FF and have loaded most browsers including SeaMonkey.

Being shouted at by the girlfriend at present, not getting enough attention!

I will do as you say, that said if my OS/browser combo is no good then it is not going to work anyway as it needs to work with all variants.

I thank you for you for your time on this - update to follow.

Respect - A

Hi Airshow, I did not complicate the thing by adding PHP, I simply took your function() and the XHTML mark up as I posted and got the error.

Aha, that's probably it. My function() will only work with my XHTML, which has some minor but important chages from your original. In particular, there's a <tbody id="products"> and each product tr is of the format <tr id="pid_n">. . The javascript uses the value n as it goes round its loop to address the various html elements.

There's nothing in the javascript that should be browser/version sensitive.

Wives/girlfriends - who needs 'em.

Airshow

Airshow, that's amazing, I have just changed my DOCTYPE to 4.01 Transitional and it works perfectly!

I have no problem having a 4.01 page in this small site. Thankyou for all your assistance.

RESPECT! A

Whew! I knew you'd like it. :cool:

Doctype, who'd of thought. If it works, I guess XHTML Transitional would be better.

Airshow

Thanks again, I have in the meantime made the page dynamic and all works as expected, I have been singing your praises to my client, who is also a friend of mine. I also included another script to ensure that if the unit was 'Each' rather than 'Kilo', no dp can be entered.

Not only have you helped me out here, I now have complex function that I can learn from.

I am in your debt, most of this work is to help this organcic food delivery service allow online orders for Christmas, one of their busiest times, back on schedule, thanks to you.

Regards A

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.