<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
* { box-sizing: border-box;
}
table { border-spacing: 0;
border-collapse: collapse;
}
th { padding: 10px;
}
td { padding:8px;
border:1px solid #ddd;
}
input { padding: 6px;
}
input[type=number] { text-align: right;
}
.text { line-height: 1.8;
}
.subtotal, .total, .base, .iva { text-align: right;
min-width: 100px;
}
.bold { font-weight: bold;
}
</style>
</head>
<body>
<table>
<thead>
<th>Producto</th>
<th>Cantidad</th>
<th>Importe</th>
<th>Total</th>
</thead>
<tr>
<td><input type="text"></td>
<td><input type="number"></td>
<td><input type="number"></td>
<td class="subtotal">0.00</td>
</tr>
<tr>
<td></td>
<td></td>
<td class='text'>Base Imponible<br>IVA 21%<br><span class="bold">Total</span></td>
<td class='text'><div class="base">0.00</div><div class="iva">0.00</div><div class="total bold">0.00</div></td>
</tr>
</table>
</body>
</html>
<script>
/**
* Funcion que crea los eventos necesarios
*/
const setEvents = () => { document.querySelectorAll("input").forEach(el => { el.removeEventListener("keyup", calcularFila); el.addEventListener("keyup", calcularFila); });
};
setEvents();
/**
* Funcion para calcular el subtotal de la fila
* Se ejecuta cada vez que se modifica un input
*/
function calcularFila() { const tr=this.closest("tr") const num=tr.querySelectorAll("input[type=number]"); tr.querySelector(".subtotal").innerText=(parseFloat(num[0].value)*parseFloat(num[1].value) || 0).toFixed(2);
calcularTotal();
agregarFila();
}
/**
* Funcion que calcula el total
*/
function calcularTotal() { const suma=[...document.querySelectorAll(".subtotal")].reduce((acum, el) => acum+parseFloat(el.innerText), 0); document.querySelector(".base").innerText=suma.toFixed(2); document.querySelector(".iva").innerText=(suma*.21).toFixed(2); document.querySelector(".total").innerText=((suma*.21)+suma).toFixed(2);}
/**
* Funcion para revisar si hay que añadir una nueva fila
* Unicamente se añade una nueva fila, si la ultima fila no
* esta vacia
*/
function agregarFila() { // revisamos si la ultima fila esta vacia.
const tr=document.querySelectorAll("tr"); // la ultima fila contiene el total, y nosotros queremos al anterior a la del total
const ultimaFila=tr[tr.length-2];
// comprovamos si la ultima fila esta vacia
const vacio=[...ultimaFila.querySelectorAll("input")].every(el => el.value==""); if (vacio==false) { ultimaFila.insertAdjacentElement('afterend', createTr()); setEvents();
}
}
/**
* Funcion que crea una nueva fila
*
* @return {object} tr */
function createTr() { // creamos una nueva fila
const td1=document.createElement("td"); const input1=document.createElement("input"); input1.type="text";
td1.appendChild(input1);
const td2=document.createElement("td"); const input2=document.createElement("input"); input2.type="number";
td2.appendChild(input2);
const td3=document.createElement("td"); const input3=document.createElement("input"); input3.type="number";
td3.appendChild(input3);
const td4=document.createElement("td"); td4.classList.add("subtotal"); td4.innerText="0.00";
const tr=document.createElement("tr"); tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
return tr;
}
</script>
Comentarios sobre la versión: 1 (0)
No hay comentarios