2

I'm currently working on an invoice project.

So far I have a dynamic form where you can add and remove rows (see snippet below).

However I have a problem with my javascript, I was wondering if someone could help me out with it.

Basically, when you input the values into the form on the first row, it calculates it all perfectly. However, if you add a new row and try to fill it in with some data, the javascript doesn't seem to perform any calculation for that row. It only works for the first row and it's really frustrating me! I can't seem to figure out why.

Any help is much appreciated. The snippet of code is below and you can run it and add some data to some rows to see for yourself. I need any advice I can get on this.

Thanks in advance guys.

Snelly

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
	<script type="text/javascript">
    function calculate() {
		var QTY = document.getElementById("Qty").value;
        var LINEPRICENET = document.getElementById("LinePriceNet").value;
		var LINEPRICEDISCOUNT = document.getElementById("LinePriceDiscountInput").value;
		var TAXRATE = document.getElementById("TaxRate").value;
		// Lineprice with discount
		LINEPRICEWITHDISCOUNT =  (QTY*(LINEPRICENET - (LINEPRICENET * (LINEPRICEDISCOUNT))));		   
        document.getElementById('LinePriceWithDiscount').value = LINEPRICEWITHDISCOUNT.toFixed(2);
		//Line Price discount Amount
		LINEPRICEDISCOUNTAMOUNT =  (QTY*(LINEPRICENET) - (QTY*(LINEPRICENET - (LINEPRICENET * (LINEPRICEDISCOUNT)))));		   
        document.getElementById("LinePriceDiscountAmount").value = LINEPRICEDISCOUNTAMOUNT.toFixed(2);
		//Tax calculation
		TAXAMOUNT = (LINEPRICEWITHDISCOUNT * TAXRATE);
		document.getElementById("TaxAmount").value = TAXAMOUNT.toFixed(2);
		//Calc Gross
		LINEPRICEGROSSAMOUNT = (LINEPRICEWITHDISCOUNT + TAXAMOUNT);
		document.getElementById("GrossOutput").value = LINEPRICEGROSSAMOUNT.toFixed(2);		
    }
	
function addRow(tableID) {
	var table = document.getElementById(tableID);
	var rowCount = table.rows.length;
		var row = table.insertRow(rowCount);
		var colCount = table.rows[0].cells.length;
		for(var i=0; i<colCount; i++) {
			var newcell = row.insertCell(i);
			newcell.innerHTML = table.rows[0].cells[i].innerHTML;
		}

}

function deleteRow(tableID) {
	var table = document.getElementById(tableID);
	var rowCount = table.rows.length;
	for(var i=0; i<rowCount; i++) {
		var row = table.rows[i];
		var chkbox = row.cells[0].childNodes[0];
		if(null != chkbox && true == chkbox.checked) {
			if(rowCount <= 1) { 						// limit the user from removing all the fields
				alert("Cannot Remove all of the items!.");
				break;
			}
			table.deleteRow(i);
			rowCount--;
			i--;
		}
	}
}	
</script>
</head>
<body>
    <form  name="CalculationTesting" >
		<p>
			<input type="button" value="Add Item" onClick="addRow('dataTable')" /> 
			<input type="button" value="Remove Selected Item" onClick="deleteRow('dataTable')"  /> 
		</p>
		        <thead>
            <tr>
                <th>Qty</th>			
                <th>Line Price Net</th>
                 <th>Line Price Discount%</th>
				 <th>Line Price Discount Amount</th>
				 <th>Line Price With Discount</th>
				 <th>VAT Rate Amount</th>
				 <th>VAT Amount</th>
				 <th>Line Price Gross-OUTPUT</th>    
            </tr>
        </thead>
        <table id="dataTable" border="1"  width="600" height="50" cellpadding="10" cellspacing="3">
            <tr>
			               
                    <td><input type="checkbox" required="required" name="chk[]" checked="checked" /></td>
                </td>
                <td>
                    <input type="number" name="Qty" id="Qty" onchange="calculate();"/>
                </td>			
                <td>
                    <input type="number" name="LinePriceNet" id="LinePriceNet" onchange="calculate();"/>
                </td>
			 <td>
                    <select type="number" name="LinePriceDiscount" id="LinePriceDiscountInput" onchange="calculate();"/>
						<option value="0.00">None</option>
						<option value="0.01">1%</option>
						<option value="0.02">2%</option>
						<option value="0.03">3%</option>
						<option value="0.04">4%</option>
						<option value="0.05">5%</option>
						<option value="0.06">6%</option>
						<option value="0.07">7%</option>
						<option value="0.08">8%</option>
						<option value="0.09">9%</option>
						<option value="0.10">10%</option>
					</select>
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="LinePriceDiscountAmount" id="LinePriceDiscountAmount">
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="LinePriceWithDiscount" id="LinePriceWithDiscount">
                </td>
				<td>
                    <select type="number" name="TaxRate" id="TaxRate" onchange="calculate();"/>
						<option value="0.00">Zero Rate</option>
						<option value="0.20">Standard(20%)</option>
						<option value="0.00">Exempt</option>
						<option value="0.05">Reduced Rate</option>
						<option value="0.00">Outside The Scope</option>
					</select>
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="TaxAmount" id="TaxAmount">
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="GrossOutput" id="GrossOutput">
                </td>
            </tr>
        </table>
		
    </form>


</body>
</html>

1 Answer 1

2

I was able to fix it using following code. There might be cleaner version possible.

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
	<script type="text/javascript">
    function calculate(object) {
		var QTY = object.parentNode.parentNode.querySelector('#Qty').value;
        var LINEPRICENET = object.parentNode.parentNode.querySelector("#LinePriceNet").value;
		var LINEPRICEDISCOUNT = object.parentNode.parentNode.querySelector("#LinePriceDiscountInput").value;
		var TAXRATE = object.parentNode.parentNode.querySelector("#TaxRate").value;
		// Lineprice with discount
		LINEPRICEWITHDISCOUNT =  (QTY*(LINEPRICENET - (LINEPRICENET * (LINEPRICEDISCOUNT))));		   
        object.parentNode.parentNode.querySelector('#LinePriceWithDiscount').value = LINEPRICEWITHDISCOUNT.toFixed(2);
		//Line Price discount Amount
		LINEPRICEDISCOUNTAMOUNT =  (QTY*(LINEPRICENET) - (QTY*(LINEPRICENET - (LINEPRICENET * (LINEPRICEDISCOUNT)))));		   
        object.parentNode.parentNode.querySelector("#LinePriceDiscountAmount").value = LINEPRICEDISCOUNTAMOUNT.toFixed(2);
		//Tax calculation
		TAXAMOUNT = (LINEPRICEWITHDISCOUNT * TAXRATE);
		object.parentNode.parentNode.querySelector("#TaxAmount").value = TAXAMOUNT.toFixed(2);
		//Calc Gross
		LINEPRICEGROSSAMOUNT = (LINEPRICEWITHDISCOUNT + TAXAMOUNT);
		object.parentNode.parentNode.querySelector("#GrossOutput").value = LINEPRICEGROSSAMOUNT.toFixed(2);
    }
	
function addRow(tableID) {
	var table = document.getElementById(tableID);
	var rowCount = table.rows.length;
		var row = table.insertRow(rowCount);
		var colCount = table.rows[0].cells.length;
		for(var i=0; i<colCount; i++) {
			var newcell = row.insertCell(i);
			newcell.innerHTML = table.rows[0].cells[i].innerHTML;
		}

}

function deleteRow(tableID) {
	var table = document.getElementById(tableID);
	var rowCount = table.rows.length;
	for(var i=0; i<rowCount; i++) {
		var row = table.rows[i];
		var chkbox = row.cells[0].childNodes[0];
		if(null != chkbox && true == chkbox.checked) {
			if(rowCount <= 1) { 						// limit the user from removing all the fields
				alert("Cannot Remove all of the items!.");
				break;
			}
			table.deleteRow(i);
			rowCount--;
			i--;
		}
	}
}	
</script>
</head>
<body>
    <form  name="CalculationTesting" >
		<p>
			<input type="button" value="Add Item" onClick="addRow('dataTable')" /> 
			<input type="button" value="Remove Selected Item" onClick="deleteRow('dataTable')"  /> 
		</p>
		        <thead>
            <tr>
                <th>Qty</th>			
                <th>Line Price Net</th>
                 <th>Line Price Discount%</th>
				 <th>Line Price Discount Amount</th>
				 <th>Line Price With Discount</th>
				 <th>VAT Rate Amount</th>
				 <th>VAT Amount</th>
				 <th>Line Price Gross-OUTPUT</th>    
            </tr>
        </thead>
        <table id="dataTable" border="1"  width="600" height="50" cellpadding="10" cellspacing="3">
            <tr>
			               
                    <td><input type="checkbox" required="required" name="chk[]" checked="checked" /></td>
                </td>
                <td>
                    <input type="number" name="Qty" id="Qty" onblur="this.value = parseFloat(Math.round(this.value * 100) / 100).toFixed(2);" onchange="calculate(this);"/>
                </td>			
                <td>
                    <input type="number" name="LinePriceNet" id="LinePriceNet" onblur="this.value = parseFloat(Math.round(this.value * 100) / 100).toFixed(2);" onchange="calculate(this);"/>
                </td>
			 <td>
                    <select type="number" name="LinePriceDiscount" id="LinePriceDiscountInput" onchange="calculate(this);"/>
						<option value="0.00">None</option>
						<option value="0.01">1%</option>
						<option value="0.02">2%</option>
						<option value="0.03">3%</option>
						<option value="0.04">4%</option>
						<option value="0.05">5%</option>
						<option value="0.06">6%</option>
						<option value="0.07">7%</option>
						<option value="0.08">8%</option>
						<option value="0.09">9%</option>
						<option value="0.10">10%</option>
					</select>
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="LinePriceDiscountAmount" id="LinePriceDiscountAmount">
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="LinePriceWithDiscount" id="LinePriceWithDiscount">
                </td>
				<td>
                    <select type="number" name="TaxRate" id="TaxRate" onchange="calculate(this);"/>
						<option value="0.00">Zero Rate</option>
						<option value="0.20">Standard(20%)</option>
						<option value="0.00">Exempt</option>
						<option value="0.05">Reduced Rate</option>
						<option value="0.00">Outside The Scope</option>
					</select>
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="TaxAmount" id="TaxAmount">
                </td>
				<td>
                    <input readonly="readonly"  type="number" name="GrossOutput" id="GrossOutput">
                </td>
            </tr>
        </table>
		
    </form>


</body>
</html>

The issue was, whenever you were hitting calculate function, it was taking values from first row only as there was no different ids for each rows. Here I used this to differentiate each row.

I had to use parentNode twice. If you find a cleaner version, please do share.

Also, using jQuery will make things easier.

Sign up to request clarification or add additional context in comments.

2 Comments

Ahhh of course! It had no way of differentiating each unique row. But these ID's make that possible. Thank you so much sphinx. I'm actually quite the beginner at JS. I don't suppose you know how to format the output and input strings to always show 2 decimal places? Example... InputValue = 100 Browser outputs it as 100.00 That's perhaps going to have to be a totally seperate question ^_^
Oh, no issues! Refer to the edit. I have added some code to fix it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.