Error adding N elements with Javascript

1

I have a problem adding all the totals, it manages to add the totals of each product and a final total but when editing a price or quantity it is added to the final total and it is not edited correctly.

Code:

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Prueba de concepto de agregado y cálculo dinámico.</title>
<link rel="stylesheet" type="text/css" media="all" href="css/base.css" />
<style type="text/css">
#contenedor {
	width: 90%;
	margin: auto;
}
#tabla {
	width: 100%;
	margin: auto;
	border: 1px solid #a1a1a1;
}
#tabla thead tr {
	background-color: #afafaf;
}
#tabla thead tr th, #tabla tbody tr td {
	border: 1px solid #a1a1a1;
	padding: 3px;
}
#tabla tbody tr td input {
	padding: 3px;
	border: 1px solid #717171;
}
#total {
	font-size: 1.1em;
	font-weight: bold;
}
</style>
<script type="text/javascript">
function AddItem() {
	var tbody = null;
	var tabla = document.getElementById("tabla");
	var nodes = tabla.childNodes;
	for (var x = 0; x<nodes.length;x++) {
		if (nodes[x].nodeName == 'TBODY') {
			tbody = nodes[x];
			break;
		}
	}
	if (tbody != null) {
		var tr = document.createElement('tr');
		tr.innerHTML = '<td><input type="text" name="item[]"/></td><td><input type="text" name="cantidad[]" onChange="Calcular(this);" value="1" /></td><td><input type="text" name="precunit[]" onChange="Calcular(this);" value="0"/></td><td><input type="text" name="totalitem[]" readonly /></td>';
		tbody.appendChild(tr);
	}
}

function Calcular(ele) {
	var cantidad = 0, precunit = 0, totalitem = 0;
	var tr = ele.parentNode.parentNode;
	var nodes = tr.childNodes;
	for (var x = 0; x<nodes.length;x++) {
		if (nodes[x].firstChild.name == 'cantidad[]') {
			cantidad = parseFloat(nodes[x].firstChild.value,10);
		}
		if (nodes[x].firstChild.name == 'precunit[]') {
			precunit = parseFloat(nodes[x].firstChild.value,10);
		}
		if (nodes[x].firstChild.name == 'totalitem[]') {
			totalitem = parseFloat((precunit*cantidad),10);
			nodes[x].firstChild.value = totalitem;
		}
	}
	var total = document.getElementById("total");
	if (total.innerHTML == 'NaN') {
		total.innerHTML = 0;
	}
	total.innerHTML = parseFloat(total.innerHTML)+totalitem;
}
</script>
</head>
<body>
<form name="frmitems" id="frmitems" action="recibe221.php" method="POST">
	<div id="contenedor">
		<table id="tabla">
			<thead>
				<tr>
					<th>Item</th>
					<th>Cantidad</th>
					<th>Precio Unitario</th>
					<th>Total</th>
				</tr>
			</thead>
			<tbody>
				
			</tbody>
			<tfoot>
				<tr>
					<td>Total</td>
					<td>&nbsp;</td>
					<td>&nbsp;</td>
					<td><span id="total">0</span></td>
				</tr>
			</tfoot>
		</table>
		<button type="button" onClick="AddItem();">Agregar item.</button>
	</div>
	<input type="submit" value="Enviar" />
</form>
</body>
</html>
    
asked by Marcial Cahuaya Tarqui 28.03.2017 в 17:50
source

1 answer

5

The detail you have when calling the function Calcular ; the value before the modification is not being subtracted from Total (at the end of the table) you are only adding the new value (of the modification).

I suggest you perform the calculation of all existing elements (practically go through all the elements and get the totalitem and add it, or add a new parameter to 'Calculate' in which you pass the value that you had before its modification for subtract it to end up doing something like:

total.innerHTML = parseFloat(total.innerHTML)+totalitem-valorAntesModificar;

Do the following to add to your code:

Modification to function AddItem :

function AddItem() {
    var tbody = null;
    var tabla = document.getElementById("tabla");
    var nodes = tabla.childNodes;
    for (var x = 0; x<nodes.length;x++) {
        if (nodes[x].nodeName == 'TBODY') {
            tbody = nodes[x];
            break;
        }
    }
    if (tbody != null) {
        var tr = document.createElement('tr');
        tr.innerHTML = '<td><input type="text" name="item[]"/></td><td><input type="text" name="cantidad[]" onChange="Calcular(this);" value="1" /></td><td><input type="text" name="precunit[]" onChange="Calcular(this);" value="0"/></td><td><input type="text" name="totalitem[]" readonly /></td>';
        /// agrege la siguiente (por la estructura que usaste; aquí guardo el valor anterior
        tr.innerHTML+='<td style="display:none"><input type="text" name="totalitemold[]" value="0" /></td>';
        tbody.appendChild(tr);
    }
}

Make changes to Calcular :

  function Calcular(ele) {
    var cantidad = 0, precunit = 0, totalitem = 0;
    var tr = ele.parentNode.parentNode;
    var nodes = tr.childNodes;
    // Inicio: Lo tenias casi al final
    var total = document.getElementById("total");
      if (total.innerHTML == 'NaN') {
          total.innerHTML = 0;
      }
    // Fin: Lo tenias casi al final

    for (var x = 0; x<nodes.length;x++) {
        if (nodes[x].firstChild.name == 'cantidad[]') {
            cantidad = parseFloat(nodes[x].firstChild.value,10);
        }
        if (nodes[x].firstChild.name == 'precunit[]') {
            precunit = parseFloat(nodes[x].firstChild.value,10);
        }
        if (nodes[x].firstChild.name == 'totalitem[]') {
            totalitem = parseFloat((precunit*cantidad),10);
            nodes[x].firstChild.value = totalitem;
        }
        if (nodes[x].firstChild.name == 'totalitemold[]') {
            total.innerHTML = parseFloat(total.innerHTML)-parseFloat(nodes[x].firstChild.value,10); // Restamos lo anterior
            nodes[x].firstChild.value=totalitem; //  Asumiendo no hay falla se coloca el nuevo valor de "if (nodes[x].firstChild.name == 'totalitem[]')", el cual será el "valor antes de modificar"
        }
    }

    total.innerHTML = parseFloat(total.innerHTML)+totalitem;
}

Notes:

  • For the structure you handle, add a TD which I put it hidden; verify does not affect when presented; In case you do add in <thead> a <td style="display:none"></td> after <th>Total</th> and place it.
  • answered by 28.03.2017 / 18:23
    source