I have an html code with multiple rows containing two values.Using javascript,I am able to compare the two values for only one row.How can I do the same for dynamically generated rows.
HTML:
<tbody id="appendrow" class="appendrow">
<input type="text"
data-field="quantity"
required
class="form-control"
name="units_ordered[]"
id="units_ordered0"
value=""/>
<input type="text"
data-field="inventory"
class="form-control"
name="inventory"
id="inventory0"
value="" />
</tbody>
Javascript:
var counter = 1;
$(window).load(function () {
$(function () {
$('#addRow').click(function () {
var row = $(' <tbody id=\'appendrow\' class=\'appendrow\'><tr><td> <input type=\'text\' required class=\'form-control\' name=\'sku[]\' onclick=\'filtersku(this,' + counter + ');\'> <input type=\'hidden\' id=\'product_id' + counter + '\' name=\'product_id[]\'/></td> <td> <input type=\'text\' readonly data-field=\'vendorsku\' id=\'vendor_sku' + counter + '\' name=\'vendorsku[]\'class=\'form-control\'></td> <td><input class=\'form-control\' data-field=\'quantity\' type=\'text\' required id=units_ordered' + counter + '\' name=\'units_ordered[]\' /></td> <td><input class=\'form-control\' type=\'text\' data-field=\'price\' required name=\'vendor_unit_price[]\' id=\'vendor_price' + counter + '\'></td> <td><input name=\'discount_percent[]\' data-field=\'discount\' class=\'form-control\' ><input type=\'hidden\' data-field=\'discountnumber\' class=\'form-control\' id=\'discountnumber\' ></td><td><input type=\'text\' readonly data-field=\'tax\' id=\'tax_id' + counter + '\' class=\'form-control\' name=\'tax_id[]\' /></td><td> Rs. <span data-field=\'taxPrice\' id=\'taxPrice' + counter + '\' >0</span><input type=\'hidden\' data-field=\'taxPriceInput\' id=\'taxPriceInput' + counter + '\' class=\'taxPrice\' value = \'0\'/> </td> <td><input type=\'text\' class=\'form-control\'data-field=\'total\' name=\'subtotal[]\'/><input type=\'hidden\' data-field=\'totalbeforetax\' class=\'form-control\' id=\'subtotalbeforetax\' /></td><td><button type=\'button\' class=\'btn btn-danger\' name=\'delete[]\' onclick=\'javascript:deletefun(this);\'><i class=\'fa fa-trash\' aria-hidden=\'true\'></i></button></td></tr></tbody>');
$('#example').append(row);
counter++;
});
});
});
function validation() {
var ordered = parseInt(document.getElementById('units_ordered0').value);
var inventory = parseInt(document.getElementById('inventory0').value);
if (inventory == -1) {
return true;
}
else {
if (ordered <= inventory) {
return true;
}
else {
document.getElementById('error').innerHTML = ('Ordered units of a product cannot be greater than the number of products present in inventory whose value is ' + inventory).fontcolor('red');
return false;
}
}
}
Please note the correct structure of the HTML5 Table. Here is a clean HTML5 Table structure:
<table>
<caption>Table Caption</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>Header Row 1</th>
<th>Header Row 2</th>
<th>Header Row 3</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Footer Row 1</td>
<td>Footer Row 2</td>
<td>Footer Row 3</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Body Row 1</td>
<td>Body Row 2</td>
<td>Body Row 3</td>
</tr>
</tbody>
</table>
And about your question:
var counter = 1;
document.getElementById( 'addRow' ).addEventListener( 'click', function ( e ) {
var table = document.getElementById( 'myTable' ),
row = table.insertRow( counter ),
cell1 = row.insertCell( 0 ),
cell2 = row.insertCell( 1 );
cell1.innerHTML = '<input type="text" data-field="quantity" class="form-control" name="units_ordered[]" id="units_ordered' + counter + '" required/>';
cell2.innerHTML = '<input type="text" data-field="inventory" class="form-control" name="inventory" id="inventory' + counter + '"/>';
counter++;
e.preventDefault()
} )
document.getElementById( 'validate' ).addEventListener( 'click', function ( e ) {
validation();
e.preventDefault()
} )
function validation() {
var ordered = document.querySelectorAll( 'input[id^="units_ordered"]' ),
inventory = document.querySelectorAll( 'input[id^="inventory"]' );
document.getElementById( 'error' ).innerHTML = ''
ordered.forEach( function ( item, index ) {
var ordered_val = Number( item.value ) || 0,
inventory_val = Number( inventory[ index ].value ) || 0
if ( inventory_val == -1 ) {
return true
} else {
if ( ordered_val <= inventory_val ) {
return true
} else {
document.getElementById( 'error' ).innerHTML += 'Row ' + +( index + 1 ) + ': Ordered units of a product cannot be greater than the number of products present in inventory whose value is ' + inventory_val + '<br/>';
return false
}
}
} )
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 300px
}
td, th {
border: 1px solid #86af49;
text-align: left;
padding: 0
}
th {
padding: 5px;
color: #fff;
background-color: #86af49
}
input[type="text"] {
box-sizing: border-box;
width: 100%;
border: 0;
outline: none
}
#error {
color: red;
font-size: .75em
}
<p>
<button type="button" id="addRow">Add Row</button>
<button type="button" id="validate">Validation</button>
</p>
<table id="myTable">
<thead>
<tr>
<th>Ordered</th>
<th>Inventory</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" data-field="quantity" class="form-control" name="units_ordered[]" id="units_ordered0" required/>
</td>
<td>
<input type="text" data-field="inventory" class="form-control" name="inventory" id="inventory0"/>
</td>
</tr>
</tbody>
</table>
<p id="error"></p>
Related
I can't figure out why my horizontal borders are not showing up with my output section. See code and screenshot below:
I would like to have horizontal borders and if possible keep the date fields from
wrapping into the next row below itself.
I would like to have horizontal borders and if possible keep the date fields from wrapping into the next row below itself.
<td align="center"><input type="button" value="Submit" name="submit" id="submit" onClick="display()" /></button></td>
</tr>
</table>
<table width="400px" align="center" colspan="40" table border="5">
<tr style="background-color:#8FBC8F;">
<td align="center"><b>Name</b></td>
<td align="center"><b>Company</b></td>
<td align="center"><b>Time In</b></td>
<td align="center"><b>Time Out</b></td>
<td align="center"><b>Description of Work</b></td>
</tr>
<tr>
<td align="center"><div id="displayarea"></div></td>
<td align="center"><div id="displayarea1"></div></td>
<td align="center"><div id="displayarea2"></div></td>
<td align="center"><div id="displayarea3"></div></td>
<td align="center"><div id="displayarea4"></div></td>
</tr>
I would like to have horizontal borders and if possible keep the date fields from wrapping into the next row below itself.
function getValue() {
var Items = "";
var td1 = document.getElementById("displayarea").innerHTML.split("<br>");
var td2 = document.getElementById("displayarea1").innerHTML.split("<br>");
var td3 = document.getElementById("displayarea2").innerHTML.split("<br>");
var td4 = document.getElementById("displayarea3").innerHTML.split("<br>");
var td5 = document.getElementById("displayarea4").innerHTML.split("<br>");
for (var i = 0; i < td1.length; i++) {
if (td1[i])
Items += td1[i] + " ,";
if (td2[i])
Items += td2[i] + " ,";
if (td2[i])
Items += td2[i] + " ,";
if (td3[i])
Items += td3[i] + " ,";
if (td4[i])
Items += td4[i] + " ";
Items += "\n";
}
console.log(Items);
return Items;
}
function display() {
document.getElementById("displayarea").innerHTML += document.getElementById("fname").value + "<br />";
document.getElementById("fname").value = "";
document.getElementById("displayarea1").innerHTML += document.getElementById("lname").value + "<br />";
document.getElementById("lname").value = "";
document.getElementById("displayarea2").innerHTML += document.getElementById("sname").value + "<br />";
document.getElementById("sname").value = "";
document.getElementById("displayarea3").innerHTML += document.getElementById("pname").value + "<br />";
document.getElementById("pname").value = "";
document.getElementById("displayarea4").innerHTML += document.getElementById("jname").value + "<br />";
document.getElementById("jname").value = "";
}
I highly suggest you start separating your data from your presentation of that data.
So, split your display function into two: createRow and renderRows. Likewise, getValues can just be getRows.
Note that this required a different way of doing things in your code, so I also refactored your HTML and CSS to bring it more in line with modern methods.
function getRows(data) {
return data.map(datum => Object.values(datum).join(',')).join('\n');
}
function createRow(data) {
const datum = {
fname: document.getElementById("fname").value,
lname: document.getElementById("lname").value,
sname: new Date(document.getElementById("sname").valueAsNumber).toLocaleString(),
pname: new Date(document.getElementById("pname").valueAsNumber).toLocaleString(),
jname: document.getElementById("jname").value
};
data.push(datum);
document.getElementById("dataForm").reset();
renderRows(data);
}
function renderRows(data) {
const body = document.getElementById("renderedData");
body.innerHTML = "";
for (let datum of data) {
let tr = document.createElement('tr');
let tdFName = document.createElement('td');
tdFName.appendChild(document.createTextNode(datum.fname));
tr.appendChild(tdFName);
let tdLName = document.createElement('td');
tdLName.appendChild(document.createTextNode(datum.lname));
tr.appendChild(tdLName);
let tdSName = document.createElement('td');
tdSName.appendChild(document.createTextNode(datum.sname));
tr.appendChild(tdSName);
let tdPName = document.createElement('td');
tdPName.appendChild(document.createTextNode(datum.pname));
tr.appendChild(tdPName);
let tdJName = document.createElement('td');
tdJName.appendChild(document.createTextNode(datum.jname));
tr.appendChild(tdJName);
body.appendChild(tr);
}
}
window.addEventListener('load', () => {
const data = [];
document.getElementById('add').addEventListener('click', function(e) {
createRow(data);
});
document.getElementById('getData').addEventListener('click', function(e) {
console.log(getRows(data));
});
});
form {
width: max-content;
margin: 0 auto 1rem;
}
.control-group {
display: flex;
justify-content: space-between;
}
fieldset {
display: flex;
flex-flow: column nowrap;
}
fieldset button {
align-self: flex-end;
}
<form id="dataForm">
<fieldset>
<legend>Enter Data</legend>
<div class="control-group">
<label for="fname">Name:</label>
<input id="fname" type="text">
</div>
<div class="control-group">
<label for="lname">Company:</label>
<input id="lname" type="text">
</div>
<div class="control-group">
<label for="sname">Time In:</label>
<input id="sname" type="datetime-local">
</div>
<div class="control-group">
<label for="pname">Time Out:</label>
<input id="pname" type="datetime-local">
</div>
<div class="control-group">
<label for="jname">Description of Work:</label>
<textarea id="jname"></textarea>
</div>
<button type="button" id="add">Add</button>
</fieldset>
</form>
<table width="400px" align="center" colspan="40" table border="5">
<thead>
<tr style="background-color:#8FBC8F;" id='header'>
<td align="center"><b>Name</b></td>
<td align="center"><b>Company</b></td>
<td align="center"><b>Time In</b></td>
<td align="center"><b>Time Out</b></td>
<td align="center"><b>Description of Work</b></td>
</tr>
</thead>
<tbody id="renderedData">
</tbody>
</table>
<button type="button" id="getData">Get Data</button>
To get borders for all cells, add this at the top of your html code (inside the head):
<style>
table {
border-collapse: collapse;
}
td {
border: 1px solid #555;
}
</style>
Adjust the border thickness, style and color as you like (in the border setting of td)
Here's an easy way to add a row with each addition using the element - available in all good browsers (not so fast Internet Explorer, I wasn't talking to you)
I've also changed how to read the values
note, using class instead of id in the cells in the rows - to make it easy to get them all with minimal change to your code
Although, personally I'd get the row data data differently (shown in alternativeGetValues)
function getValue() {
var Items = "";
var td1 = [...document.querySelectorAll(".displayarea")].map(e => e.innerHTML);
var td2 = [...document.querySelectorAll(".displayarea1")].map(e => e.innerHTML);
var td3 = [...document.querySelectorAll(".displayarea2")].map(e => e.innerHTML);
var td4 = [...document.querySelectorAll(".displayarea3")].map(e => e.innerHTML);
var td5 = [...document.querySelectorAll(".displayarea4")].map(e => e.innerHTML);
for (var i = 0; i < td1.length; i++) {
if (td1[i])
Items += td1[i] + " ,";
if (td2[i])
Items += td2[i] + " ,";
if (td3[i])
Items += td3[i] + " ,";
if (td4[i])
Items += td4[i] + " ,";
if (td5[i])
Items += td5[i] + " ";
Items += "\n";
}
console.log(Items);
return Items;
}
function display() {
const template = document.getElementById("row");
const clone = template.content.cloneNode(true);
const additem = (dest, src) => {
const s = document.querySelector(src);
clone.querySelector(dest).innerHTML = s.value;
s.value = "";
};
additem(".displayarea", "#fname");
additem(".displayarea1", "#lname");
additem(".displayarea2", "#sname");
additem(".displayarea3", "#pname");
additem(".displayarea4", "#jname");
template.insertAdjacentElement('beforebegin', clone.firstElementChild);
}
// IMHO this is better
function alternateGetValue() {
const Items = [...document.querySelectorAll('.data')]
.map(row => [...row.querySelectorAll('td>div')]
.map(d => d.textContent).join(',')
).join('\n');
console.log(Items);
return Items;
}
.wide {
min-width:12em;
}
F: <input id="fname"> <br>
L: <input id="lname"> <br>
S: <input id="sname"> <br>
P: <input id="pname"> <br>
J: <input id="jname"> <br>
<input type="button" value="add" onclick="display()"/>
<input type="button" value="show" onclick="getValue()"/>
<input type="button" value="Better" onclick="alternateGetValue()"/>
<table width="400px" align="center" colspan="40" table border="5">
<thead>
<tr style="background-color:#8FBC8F;" id='header'>
<td align="center"><b>Name</b></td>
<td align="center"><b>Company</b></td>
<td align="center" class="wide"><b>Time In</b></td>
<td align="center" class="wide"><b>Time Out</b></td>
<td align="center"><b>Description of Work</b></td>
</tr>
</thead>
<tbody>
<template id="row">
<tr style="background-color:#8F8FBC;" class="data">
<td align="center"><div class="displayarea"></div></td>
<td align="center"><div class="displayarea1"></div></td>
<td align="center"><div class="displayarea2"></div></td>
<td align="center"><div class="displayarea3"></div></td>
<td align="center"><div class="displayarea4"></div></td>
</tr>
</template>
</tbody>
</table>
I am trying to give a dynamic row number while clicking add and delete button, but in between I delete any row it is not giving proper row_number.
My td in table(dataTable) is:
echo "<td> 1 <input type='hidden' name='task_number[]' value='1'> </td>";
ADD and delete btn :
echo "<input type='button' value='Add Task' onClick=addRow('dataTable') /> ";
echo "<INPUT type='button' value='Delete Task' onclick=deleteRow('dataTable') />";
in javascript:
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length -1;
var inps = document.getElementsByName('task_number[]');
var inp=inps[rowCount-1].value; // array start from 0
inp = ++inp;
var cell2 = row.insertCell(1);
cell2.innerHTML = inp;
}
Output
use this function
function setRowNumber()
{
$('#tablename tbody tr').each(function (idx) {
$(this).children("td:eq(1)").html(idx + 1);
});
}
I also put a dynamic table code. If the checkbox is checked, that row can be deleted.
orderTable();
function addRow()
{
var rowCount = $('#example tr').length;
if(rowCount == 1)
{
var tr = "<tbody><tr id='tr'><td><input type='checkbox' id='chk' name='chk' value='chk'></td>" + "<td></td><td>Task Designer</td></tr></tbody>";
$('#example thead:last').after(tr);
}
else
{
var tr = "<tr id='tr'><td><input type='checkbox' id='chk' name='chk' value='chk'></td>" + "<td></td><td>Task Designer</td></tr>";
$('#example tr:last').after(tr);
}
orderTable();
}
function deleteRow()
{
var i = 0;
$('#example input[type=checkbox]').each(function(){
if($(this).is(":checked"))
{
$('#tr' + (i + 1)).remove();
}
i = i + 1;
});
$('#example input[type=checkbox]').each(function(){
$(this).prop('checked', false);
});
orderTable();
}
function orderTable()
{
var rowCount = $('#example tbody tr').length;
if(rowCount > 0)
{
$('#example tbody tr').each(function (idx) {
var num = idx + 1;
$(this).children("td:eq(1)").html(num);
$(this).children("td:eq(2)").html('Task Designer' + num);
$(this).attr('id','tr' + num);
//set input names
$(this).children("td:eq(0)").children().attr('id','chk' + num);
$(this).children("td:eq(0)").children().attr('name','chk' + num);
$(this).children("td:eq(0)").children().attr('value','chk' + num);
});
}
}
#example
{
border:1px solid #ddd;
border-collapse: collapse;
}
th
{
background:#333;
color:white;
font-weight:bold;
height:40px;
}
td
{
text-align: center;
vertical-align: middle;
border:1px solid #ddd;
height:40px;
}
<input type='button' id="btnAdd" value='Add Task' onclick="addRow()" />
<input type='button' id="btnRemove" value='Delete Task' onclick="deleteRow()" />
<table id="example" class="display" cellspacing="0" width="100%" border="0">
<thead>
<tr>
<th>Select</th>
<th>Task Number</th>
<th>Task Description</th>
</tr>
</thead>
<tbody>
<tr id="tr">
<td><input type="checkbox" id="chk" name="chk" value="chk"></td>
<td>11</td>
<td>Task Designer</td>
</tr>
<tr id="tr">
<td><input type="checkbox" id="chk" name="chk" value="chk"></td>
<td>2</td>
<td>Task Designer</td>
</tr>
<tr id="tr">
<td><input type="checkbox" id="chk" name="chk" value="chk"></td>
<td>3</td>
<td>Task Designer</td>
</tr>
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Below code should get me the value of the column next to the checked box in the table, but, once the button is clicked, I am getting:
Cannot read property childNodes of null
Note: database from firebase which where the values from the table come from
Table image :
rootRefReAgents.on("child_added", snap => {
var AgentName = snap.child("Name").val();
$("#table_body_Test").append("<tr><td>" + AgentName + "</td><td><INPUT TYPE=\"Checkbox\"> </Input></td></tr>");
});
}
function ActionData(){
let agents = [];
let table = document.getElementById("table_body_Test");
let childNodes = Array.from(table.childNodes);
// let childNodes = table.childNodes;
for (let child of childNodes.values()) {
console.log(`child: ${child}`);
if (child.constructor.name !== "HTMLTableRowElement") {
continue;
}
let agent = child.childNodes.item(1).innerHTML;
console.log(`agent: ${agent}`);
let checkbox = child.childNodes.item(3).childNodes.item(1);
console.log(`checkbox: ${checkbox}`);
console.log(checkbox.checked);
if (checkbox.checked) {
agents.push(agent);
}
}
console.log(`agents: ${agents}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="testTable" align="center">
<thead>
<tr style="color: #D2002E; background: #FFCC01; height:32px;">
<td>Agents</td>
<td>Select</td>
</tr>
</thead>
<tbody id="table_body_Test">
</tbody>
</table>
<button id="submitBtn" onclick="ActionData()">Next</button>
ES6 brought new methods that simplify the code and its reading
const tableBody = document.querySelector('#testTable tbody' );
document.querySelector('#submitBtn').onclick=()=>
{
let agents = [];
console.clear();
for (let rowX of tableBody.rows )
{
let
agent = rowX.cells[0].textContent,
checkbox = rowX.cells[1].querySelector('input[type=checkbox]')
;
console.log( 'agent:', agent, 'checked:', checkbox.checked);
if (checkbox.checked) { agents.push(agent); }
}
console.log( 'agents (array):', agents.join(' / '));
}
/// bonus info :
/*
rootRefReAgents.on("child_added", snap=>{
let
newRow = tableBody.insertRow(-1);
newRow.insertCell(0).textContent = snap.child("Name").val();
newRow.insertCell(1).innerHTML = '<input type="Checkbox">';
});
*/
#testTable { margin: auto; border-collapse: collapse }
#testTable thead tr {
color: #D2002E;
background: #FFCC01;
height:32px;
font-weight: bold;
}
#testTable tr:nth-child(even) {background-color: lightgrey }
#testTable td { border:1px solid grey; padding: 0 20px; }
#testTable td:nth-child(2) { text-align: center }
<table id="testTable">
<thead>
<tr> <td>Agents</td> <td>Select</td> </tr>
</thead>
<tbody>
<tr> <td>AMC</td> <td> <input type="checkbox" > </td> </tr>
<tr> <td>Mygulfex</td> <td> <input type="checkbox" > </td> </tr>
<tr> <td>topStar</td> <td> <input type="checkbox" > </td> </tr>
<tr> <td>WMC</td> <td> <input type="checkbox" > </td> </tr>
</tbody>
</table>
<button id="submitBtn" >see Selects in console</button>
I would like to make a function which counts how many attributes I have with Attribute name&value I entered in html.
I don't know how to count by Attribute name&value!
like when i put "type" and "text" in this html then show 2!
I am very new to javascript! if you help me it would be very thankful! thanks
function javascript_click() {
if (document.getElementById("value3").value && document.getElementById("value4").value ) {
var attName=document.getElementById("value3").value;
var attValue=document.getElementById("value4").value;
if((attName && attValue) !==''){
var val3 = document.getElementById("value3");}
else {
document.getElementById("cnt").innerHTML +=
"wrong value of ID <br>";
}
}
}
<form action="">
<table class="tg" id="tg">
<tr>
<td>Attribute name</td>
<td><input type="text" id="value3"></td>
</tr>
<tr>
<td>attribute value</td>
<td><input type="text" id="value4"></td>
</tr>
</table>
<div id="cnt"></div>
</form>
<div class="button">
<button id='btn_javascript' onclick="javascript_click();">javascript</button>
</div>
Every time the user is entering a pair of attributes I'm pushing the attributes in an array attRy.
attRy.length will give you the number of attributes pairs.
let attRy = []
function javascript_click() {
if (value3.value && value4.value ) {
var attName = value3.value;
var attValue = value4.value;
if(attName !=='' && attValue !==''){
attRy.push(attName + ": " +attValue);
cnt.innerHTML = attRy.length +" attributes:<br>";
attRy.forEach((a) =>{
cnt.innerHTML += a + "<br>"
})
}
else {
cnt.innerHTML +=
"wrong value of ID <br>";
}
}
}
<form action="">
<table class="tg" id="tg">
<tr>
<td>Attribute name</td>
<td><input type="text" id="value3"></td>
</tr>
<tr>
<td>attribute value</td>
<td><input type="text" id="value4"></td>
</tr>
</table>
<div id="cnt"></div>
</form>
<div class="button">
<button id='btn_javascript' onclick="javascript_click();">javascript</button>
</div>
I hope I understand you right
function javascript_click() {
if (document.getElementById("value3").value && document.getElementById("value4").value) {
var attName = document.getElementById("value3").value;
var attValue = document.getElementById("value4").value;
var value = "[" + attName + "=" + attValue + "]";
var num2 = document.querySelectorAll(value).length;
document.getElementById("cnt").innerHTML += "선택하신 노드는 " + num2 + "개 입니다. By javascript<br>";
} else {
document.getElementById("cnt").innerHTML += "wrong value of ID <br>";
}
}
<form action="">
<table class="tg" id="tg">
<tr>
<td>Attribute name</td>
<td><input type="text" id="value3"></td>
</tr>
<tr>
<td>attribute value</td>
<td><input type="text" id="value4"></td>
</tr>
</table>
<div id="cnt"></div>
</form>
<div class="button">
<button id='btn_javascript' onclick="javascript_click();">javascript</button>
</div>
I am currently working on a dynamic invoice system for myself. But I can't seem to completely get it working correctly.
I have a invoice table like this in HTML:
Product name -- Quantity -- Tax -- Price (without tax) -- total price
My HTML looks like this:
<td><input type="text" placeholder="Item name" class="form-control" /></td>
<td class="text-center"><input type="number" min="1" id="target" placeholder="Quantity" class="form-control quantity" /></td>
<td class="text-center"><input type="text" placeholder="TAX" class="form-control tax" /></td>
<td class="text-right"><input type="text" placeholder="Price" class="form-control" /></td>
<td class="text-right"><input type="text" disabled placeholder="0,00" class="form-control price" /></td>
I can add rows with this Javascript code:
<script>
function addItem(){
var itemRow =
'<tr>' +
'<td><input type="text" class="form-control" placeholder="Item name" /></td>' +
'<td><input type="text" class="form-control" placeholder="Quantity" /></td>' +
'<td><input type="text" class="form-control tax" placeholder="Tax" /></td>' +
'<td><input type="text" class="form-control" placeholder="Price" /></td>' +
'<td><input type="text" class="form-control price" disabled placeholder="0,00" /></td>' +
'</tr>';
$("#items_table tr:last").after(itemRow);
}
</script>
And I calculate it with this jQuery code:
<script>
var total = 0;
var taxTotal = 0;
(function() {
$('#items_table').on('change', 'input', function() {
if( !$(this).hasClass('tax')) {
totalPrice = 0;
var row = $(this).closest('tr');
// ## Get quantity
var qty = parseFloat(row.find('input:eq(1)').val());
if (qty < 0) {
row.addClass('danger');
return;
} else {
row.removeClass('danger');
}
// ## Get the entered price
var price = parseFloat(row.find('input:eq(3)').val());
if (price < 0) {
row.addClass('danger');
return;
} else {
row.removeClass('danger');
}
// ## Calculate total price
var total = qty * price;
// ## Set total price at the end
row.find('input:eq(4)').val(isNaN(total) ? '' : total);
tax = parseFloat(row.find('input:eq(2)').val());
var salesTax = total * (tax / 100);
if (!isNaN(salesTax)) {
$('#tax-' + row.find('input:eq(2)').val()).html(salesTax.toFixed(2));
$('#tax_percentage').html(tax + '%');
$('#tax_total').html('€ ' + salesTax.toFixed(2));
$('.price').each(function (i, obj) {
// ## Add all the prices again
totalPrice = totalPrice += parseFloat($(this).val()) + salesTax;
});
}
$('#total_price').html('€ ' + totalPrice.toFixed(2));
}else{
// ## Remove all the taxes
$('[id^=tax-tr-]').remove();
if($('#tax-'+ $(this).val()).length > 0 ){
console.log('it already exists');
}else{
$('.tax').each(function (i, obj) {
var itemRow =
'<tr id="tax-tr-' + $(this).val() + '">' +
'<td colspan="4" class="font-w600 text-right">BTW ' + $(this).val() + '%</td>' +
'<td style="width: 20%;" class="text-right">€ <span id="tax-' + $(this).val() + '">0</span></td>' +
'</tr>';
$("#subtotal_table tr").eq(-2).after(itemRow);
});
}
}
});
})();
</script>
Although, its not exactly doing what I want. I want the total price to be at the end of the table row (total price disabled row)
And I want the tax to be added below the invoice (a new table), like this:
Sub total: (Total price without tax)
TAX 10%: (The tax ammount according to the 10%)
TAX 15%: (The tax ammount according to the 15%)
Total: (Sub total price + the tax prices)
But the problem I get is once I have 2 items in the table, and I change the first row's TAX, it gets all messed up.
I am currently out of idea's how to correctly do this. So I all I need is once I filled 1 item row, the tax gets in the total table added, and once I change that tax in that row, it changes below aswell, and the price has to be changed aswell.
Can someone get me back on the right track?
It's not exactly clear what you want to display in the second table,however, I believe the below will suite your needs.
Here is a jsFiddle as well
$('#addRow').click(function () {
addItem();
});
$('#items_table').on('keyup', '.update', function () {
var key = event.keyCode || event.charCode; // if the user hit del or backspace, dont do anything
if( key == 8 || key == 46 ) return false;
calculateTotals();
});
$('#taxPercentage').change(function () {
calculateTotals(); // user changed tax percentage, recalculate everything
});
function calculateTotals(){
// get all of the various input typs from the rows
// each will be any array of elements
var nameElements = $('.row-name');
var quantityElements = $('.row-quantity');
var taxElements = $('.row-tax');
var priceElements = $('.row-price');
var totalElements = $('.row-total');
// get the bottom table elements
var taxPercentageElement =$('#taxPercentage');
var subTotalElement =$('#subTotal');
var totalTaxElement =$('#totalTax');
var grandTotalElement =$('#grandTotal');
var subTotal=0;
var taxTotal=0;
var grandTotal=0;
$(quantityElements).each(function(i,e){
// get all the elements for the current row
var nameElement = $('.row-name:eq(' + i + ')');
var quantityElement = $('.row-quantity:eq(' + i + ')');
var taxElement = $('.row-tax:eq(' + i + ')');
var priceElement = $('.row-price:eq(' + i + ')');
var totalElement = $('.row-total:eq(' + i + ')');
// get the needed values from this row
var qty = quantityElement.val().trim().replace(/[^0-9$.,]/g, ''); // filter out non digits like letters
qty = qty == '' ? 0 : qty; // if blank default to 0
quantityElement.val(qty); // set the value back, in case we had to remove soemthing
var price = priceElement.val().trim().replace(/[^0-9$.,]/g, '');
price = price == '' ? 0 : price; // if blank default to 0
priceElement.val(price); // set the value back, in case we had to remove soemthing
// get/set row tax and total
// also add to our totals for later
var rowPrice = (price * 1000) * qty
subTotal = subTotal + rowPrice;
var tax = taxPercentageElement.val() * rowPrice;
taxElement.val((tax / 1000).toFixed(2));
taxTotal = taxTotal + tax;
var total = rowPrice + tax
totalElement.val((total / 1000).toFixed(2));
grandTotal = grandTotal + total;
});
// set the bottom table values
subTotalElement.val((subTotal / 1000).toFixed(2));
totalTaxElement.val((taxTotal / 1000).toFixed(2));
grandTotalElement.val((grandTotal / 1000).toFixed(2));
}
function addItem() {
var itemRow =
'<tr>' +
'<td><input type="text" class="form-control row-name" placeholder="Item name" /></td>' +
'<td><input type="text" class="form-control update row-quantity" placeholder="Quantity" /></td>' +
'<td><input type="text" class="form-control update row-tax" placeholder="Tax" /></td>' +
'<td><input type="text" class="form-control update row-price" placeholder="Price" /></td>' +
'<td><input type="text" class="form-control row-total" disabled placeholder="0,00" /></td>' +
'</tr>';
$("#items_table").append(itemRow);
}
addItem(); //call function on load to add the first item
button{
font-size:18px;
}
.myTable {
background-color:#ffaa56;
}
.myTable {
border-collapse: collapse;
border-spacing: 0;
width:100%;
height:100%;
margin:0px;
padding:0px;
}
.myTable tr:last-child td:last-child {
-moz-border-radius-bottomright:0px;
-webkit-border-bottom-right-radius:0px;
border-bottom-right-radius:0px;
}
.myTable tr:first-child td:first-child {
-moz-border-radius-topleft:0px;
-webkit-border-top-left-radius:0px;
border-top-left-radius:0px;
}
.myTable tr:first-child td:last-child {
-moz-border-radius-topright:0px;
-webkit-border-top-right-radius:0px;
border-top-right-radius:0px;
}
.myTable tr:last-child td:first-child {
-moz-border-radius-bottomleft:0px;
-webkit-border-bottom-left-radius:0px;
border-bottom-left-radius:0px;
}
.myTable tr:hover td {
}
#items_table tr:nth-child(odd) {
background-color:#ffffff;
}
#items_table tr:nth-child(even) {
background-color:#ffd0a3;
}
.myTable td {
vertical-align:middle;
border:1px solid #000000;
border-width:0px 1px 1px 0px;
text-align:left;
padding:7px;
font-size:10px;
font-family:Arial;
font-weight:normal;
color:#000000;
}
.myTable tr:last-child td {
border-width:0px 1px 0px 0px;
}
.myTable tr td:last-child {
border-width:0px 0px 1px 0px;
}
.myTable tr:last-child td:last-child {
border-width:0px 0px 0px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button id="addRow">Add a row</button><br><br>
<table class="myTable">
<thead>
<tr>
<th>Item Name</th>
<th>Quantity</th>
<th>Tax</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody id="items_table"></tbody>
<tfoot>
<tr>
<th>Item Name</th>
<th>Quantity</th>
<th>Tax</th>
<th>Price</th>
<th>Total</th>
</tr>
</tfoot>
</table>
<br>
<br>
<table class="myTable" style="width:70%">
<thead>
<tr>
<th>Tax Percentage</th>
<th>Sub Total</th>
<th>Total Tax</th>
<th>Grand Total</th>
</tr>
</thead>
<tbody id="items_table">
<tr>
<td>
<select name="" id="taxPercentage" class="form-control">
<option value=".10">10%</option>
<option value=".15">15%</option>
</select>
<td><input type="text" class="form-control" id="subTotal" disabled placeholder="0,00" /></td>
<td><input type="text" class="form-control" id="totalTax" disabled placeholder="0,00" /></td>
<td><input type="text" class="form-control" id="grandTotal" disabled placeholder="0,00" /></td>
</tr>
</tbody>
<tfoot>
</tfoot>
</table>
<p>Add rows and give them values for quantity and price, the script will do the rest.</p>
<p>Select a diferent tax amount to recalculate everything</p>