Calculating Table Rows - javascript

So I have a table that i'm able to add a new row. If I manually type in the quantity and the price, the total is calculated using this javascript code.
function addRow() {
addTableRow($('.table tbody'));
}
function removeRow() {
var par = $(this).parent().parent();
var tableSize = $('.table tbody tr').length;
if(tableSize == '1'){
alert('You must have one row');
return false;
}
par.remove();
};
function calculateRow() {
var par = $(this).parent().parent();
var price = $(par).find('.price').val();
var qty = $(par).find('.qty').val();
var total = price*qty;
$(par).find('.total').val(total.toFixed('2'));
}
$('.table tbody').on("click", ".removeRow", removeRow);
$('.table tbody').on("blur", ".qty", calculateRow);
function addTableRow(table) {
$(table).append(
"<tr>" +
"<td><input name='item_number[]' type='text' class='id form-control'></td>" +
"<td><input name='item_name[]' type='text' class='name search form-control'></td>" +
"<td><input name='item_price[]' type='text' class='price form-control price'></td>" +
"<td><input name='item_qty[]' type='text' class='form-control qty'></td>" +
"<td><input name='item_total[]' type='text' class='form-control total'></td>" +
"<td class='text-center' style='vertical-align:middle;'><a href='#' class='text-success removeRow'><i class='fa fa-trash-o'></i></a></td>" +
"</tr>");
auto();
}
Now I've added Jquery UI AutoSuggest to my table and made it so I was able to fill the item number, item name, item quantity, and item price all by choosing a product. Using the javascript below:
function auto() {
var ac_config = {
source: "/admin/items/fetch_items",
select: function(event, ui){
var item = ui.item;
if(item) {
$(".id").val(item.id);
$(".price").val(item.price);
$(".qty").val('1');
var par = $(".qty").parent().parent();
var price = $(par).find('.price').val();
var qty = $(par).find('.qty').val();
var total = price*qty;
$(par).find('.total').val(total.toFixed('2'));
}
},
minLength: 1,
};
$(".search").autocomplete(ac_config);
}
Now as you can see, I am needing to calculate the row total and fill it. As the code sits above, the initial row that is by default made by html is calculated correctly. But once I add a new row and try to autofill it and calculate the total, the first row changes along with the new row I just added.
How do I get the javascript to run on the row I just autofilled with the jQuery UI?

use a class like selected on the active row and add some highlighting css based on that class.
function addRow() {
var $table = $('.table tbody');
addTableRow($table);
$table.find('tr.selected').removeClass('selected').end().find('tr:last').addClass('selected');
}
Now within the autocomplete callback you can target the selected row with your selectors
var ac_config = {
source: "/admin/items/fetch_items",
select: function(event, ui){
var item = ui.item;
if(item) {
var $row = $('tr.selected');
$row.find(".id").val(item.id);
$row.find(".price").val(item.price);
/* ....... etc....*/
}
},
minLength: 1,
};
Then somewhere in your initialization code add a click handler to toggle selected on row click:
$('.table tbody').on('click', 'tr',function(){
$(this).siblings().removeClass('selected');
$(this).addClass('selected');
});

I don't exactly understand your question.
But is this usefull for you?
With jquery you can each tr the and acumulate the values of each row
function total() {
var total=0;
$.each("table tr", function(key,row) {
var tr=$(this);
var qty=parseFloat(tr.find(".qty).val());
var price=parseFloat(tr.find(".price).val());
total+=qty*price;
});
return total;
}
$(".qty, .price").change(function(){
var total=total();
$(".total").html(total);
});

Related

adding row and then deleting causes duplicate rows

So when I add new rows each row is given an id that increments according the number of rows already added. if I add three rows and then delete the second row, then add another row, now the new row has an id the same as the old third row.
is there an easier way to do this or a loop that i can perform to check for an existing number.
$('body').delegate('.remove', 'click', function() {
$(this).parent().parent().remove();
});
function addnewrow() {
var n = ($('.detail tr').length - 0) + 1;
var tr = '<tr>' +
'<td>' + n + '</td>' +
'<td><select id="drop' + n + '" class="select-service" name="prodService[]"> <
option value = "" > -Choose Service - < /option></select > < /td>'+
'<td id="desc' + n + '"></td>' +
'<td>Delete</td>' +
'</tr>';
Try this way...Put counter outside of the function.
$('body').on("click", '.remove', function() {
$(this).closest("tr").remove();
});
var n = 1;
$('body').on('click', '.add-new-row', function() {
var $tr = $("<tr />");
var $td1 = $("<td />").text(n).appendTo($tr);
var $td2 = $("<td />").append("<select id='drop" + n + "' class='select-service' name='prodService[]' />").appendTo($tr);
var $td3 = $("<td id='desc" + n + "' />").appendTo($tr);
var $td4 = $("<td />").append("<a href='#' class='remove'>Delete</a>").appendTo($tr);
$("table").append($tr);
n++;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="add-new-row">Add New Row</button>
<table></table>
Using jQuery is nice because you can avoid writing these giant element strings, so I've gone ahead and rewritten your addnewrow() function to (hopefully) make it slightly cleaner.
As far as determining the IDs, while I believe what talg123 suggested in the comments would be fine - storing a global variable that just increases by 1 each time you add a new row - I personally try to avoid polluting the global scope where I can.
You can use this line to find the last drop id, and remove the "drop" text from it so you're just left with a number.
$("tr select").last().attr("id").replace("drop", "");
Unfortunately, this will break if there are no rows becuase it won't be able to find any select elements. So, first we have to check if they exist:
+$("tr select").length ? (exists) : (does not exist)
If it doesn't exist, we'll just use 1.
Put that all together, and you've got:
//If select exists Get last ID and remove "drop" from it, and add 1 Else, 1
$("tr select").length ? 1 + +$("tr select").last().attr("id").replace("drop", "") : 1;
$('body').on("click", '.remove', function() {
$(this).closest("tr").remove();
});
$('body').on('click', '.add-new-row', function() {
var nextId = $("tr select").length ? 1 + +$("tr select").last().attr("id").replace("drop", "") : 1;
//Create a new select list
var $selectList = $("<select id='drop" + nextId + "' class='select-service' name='prodService[]' />");
$selectList.append("<option> -Select Service- </option"); //Append option 1
$selectList.append("<option> Another example </option"); //Append option 2
var $tr = $("<tr />"); //Create a new table row
var $td1 = $("<td />").text(nextId).appendTo($tr); //Create first cell. Set text to nextId. Add it to the row.
var $td2 = $("<td />").append($selectList).appendTo($tr); //Create second cell. Add our select list to it. Add it to the row.
var $td3 = $("<td id='desc" + nextId + "' />").appendTo($tr); //Create third cell. Set its id to 'desc{nextId}'. Add it to the row.
var $td4 = $("<td />").append("<a href='#' class='remove'>Delete</a>").appendTo($tr); //Create fourth cell. Add link to it. Add it to the row.
$("table").append($tr); //Add the row to the table
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="add-new-row">Add New Row</button>
<table></table>

Having trouble calculating the value of a list of classes in Javascript

I'm trying to add all the values from the class "q-total" But I can't get it to work. Here's the code:
$(document).on("change", ".row-inputs", function(){
var total = 0;
var price = 0;
var multi = 0;
$('.q-quantity', this).each(function(){
multi = $(this).val();
})
$(".q-price", this).each(function(){
price += +$(this).val() * multi;
})
$(".q-total", this).val(price);
for (var i = 0; i < $(".q-total").length; i++) {
// total = 0;
// console.log($(".q-total", this).val() )
total += parseInt($(".q-total", this).val());
}
console.log("Total " + total)
})
Below is the class code I use to add new rows to the html. In case this might help to figure out why the above code is not working.
var counter = 1;
var limit = 10;
function addInput(divName){
if (counter == limit) {
alert("You have reached the limit of adding " + counter + "
inputs");
}
else {
var newdiv = document.createElement('div');
newdiv.className = "row-inputs";
newdiv.innerHTML = "<input type='text' name=''
placeholder='product name' class='q-product-name'> " +
"<input type='number' name='' placeholder='0' class='q-quantity'
value=1> " +
"<input type='text' name='' placeholder='price' class='q-price'> "
+
"<input type='text' name='' placeholder='price' class='q-total'>";
document.getElementById(divName).appendChild(newdiv);
counter++;
}
}
Thank you
Your loop is incorrect:
Change
for (var i = 0; i < $(".q-total").length; i++) {
// total = 0;
// console.log($(".q-total", this).val() )
total += parseInt($(".q-total", this).val());
}
To
$(".q-total").each(function(){
total += +$(this).val();
})
In the original for loop you never iterate over the values, you always take $(this).val(). Not sure why you varied from your .each() approach you've used everywhere else, but that is your fix.
To explain further, using your example of add rows with prices of 3,4,5. The first time through (1st row), you have one element in the jQuery collection, so total=0 becomes total += 3; Second row added and you have two elements, but only look at the value of the current row, so total=0 becomes total += 4 && total += 4 hence total=8; On third row change, there are three elements, to total = 15 ( 3 * 5);

split values are not getting calculated properly

This is related to this thread. I am adding line items with auto calculations according to the selection of price, quantity, discount and tax.
Only for tax I pass values as 1_2, i.e. both id and tax rate. So for the first line item I get a proper value for tax, but from the second onwards, whatever tax I select, it takes the first item's tax value. I don't see what I am doing wrong.
Here is my HTML through which I select the values:
<td>
<select name="tax[]" class="form-control tax" id="tax_1" style="width:80px;">
<option value="">Tax</option>
<?php
$s1 = mysqli_query($con, "select * from taxes");
while($s2 = mysqli_fetch_array($s1)) {
$options .= "<option value='". $s2['tax_id']."_".$s2['rate']."'>"
.$s2['name'].'-'.$s2['rate'] . "</option>";
?>
<option value="<?php echo $s2['tax_id']."_".$s2['rate']; ?>">
<?php echo $s2['name'].'-'.$s2['rate']; ?></option>
<?php
}
?>
</select>
</td>
</tr>
My script:
$(".addmore").on('click', function() {
count = $('table tr').length - 1;
var data = "<tr><td><input type='checkbox' class='case'/></td><td><input class='form-control' type='text' id='productname_" + i + "' name='productname[]'/></td><td><input class='form-control' type='text' id='productcode_" + i + "' name='productcode[]'/></td> <td><textarea class='form-control' id='description_"+ i + "' name='description[]'></textarea></td><td><select class='form-control uom' id='uom_" + i + "' name='uom[]'><option value=''>UOM</option>" + options1 + "</select></td><td><input class='form-control price' type='text' id='price_" + i + "' name='price[]'/></td><td><select class='form-control tax' id='tax_" + i + "' name='tax[]'><option value=''>Tax</option>" + options + "</select></select></td><td><input class='form-control quantity' type='text' id='quantity_" + i + "' name='quantity[]'/></td><td><input class='form-control discount' type='text' id='discount_" + i + "' name='discount[]'/></td><td><input class='form-control amount' type='text' id='amount_" + i + "' name='amount[]'/></td><td><input class='form-control tamount' type='text' id='tamount_" + i + "' name='tamount[]'/></td></tr>";
$('table').append(data);
row = i;
$('#productname_' + i).autocomplete({
source: function(request, response) {
$.ajax({
url: 'ajax.php',
dataType: "json",
method: 'post',
data: {
name_startsWith: request.term,
type: 'items_table',
row_num: row
},
success: function(data) {
response($.map(data, function(item) {
var code = item.split("|");
return {
label: code[0],
value: code[0],
data: item
}
}));
}
});
},
$('body').on('change', '.quantity,.price,.discount,.tax', function() {
var tr = $(this).parent().parent();
var qty = tr.find('.quantity').val();
var price = tr.find('.price').val();
var taxVal= $('.tax').val();
var tax_id=taxVal.split('_')[0];
var rate=taxVal.split('_')[1];
// Here from 2nd line item i am getting 1st line items value for tax.
var dis = tr.find('.discount').val();
var amt = (qty * price) - (qty * price * dis) / 100;
var tax1 = (amt * (rate / 100));
tax1 = Number((tax1).toFixed(2));
tr.find('.tamount').val(tax1);
ttotal();
tr.find('.amount').val(amt);
total();
//tr.find('.ttotal1').val();
});
I see.
This is because you're selecting the .tax selector like so:
var taxVal= $('.tax').val();
You should use $(this) to grab it. Because the way you're doing it, it'll always grab the first one.
Please see this jsfiddle for an example
In short:
$('.tax'); will select any element with the .tax class within the DOM.
When you use any type of binding, this will be the element that triggered the binding (The change event)
So, by grabbing $(this), you'll be grabbing the element that has actually been changed. By grabbing $('.tax'), you'll just grab any .tax element that is in the DOM.
Hope this helps :)
Example html
<select class="tax" id="tax">
<option value="1_2">1_2</option>
<option value="1_3">1_3</option>
<option value="2_2">2_2</option>
</select>
<select class="tax" id="tax">
<option value="3_2">3_2</option>
<option value="3_3">3_3</option>
<option value="3_2">3_2</option>
</select>
Example jQuery
$('.tax').on('change', function() {
var $changedInput = $(this);
var value = $changedInput.val();
var aValues = value.split('_');
var tax_id = aValues[0];
var rate = aValues[1];
alert("tax_id: " + tax_id + " Rate:" + rate );
});
p.s. in your own code, you are already grabbing the parentrow for the other fields in order to find them, so why not do this for .tax also?
tr.find('.tax').val();
"So for the first line item I get a proper value for tax, but from the
second onwards, whatever tax I select, it takes the first item's tax
value."
As Far I See, You are not taking the current object values. You always referring the class name. Since, every inputs having ID ( separated by _ ). You can fetch the ID of that particular Input field and can split to get exact/current ID of it. Using this current ID, you can find other input values too.
Updated Code
$('body').on('change', '.quantity,.price,.discount,.tax', function() {
var tr = $(this).parents('tr');
var id_clicked = $(this).attr('id');
var current_id = id_clicked.split("_")[1];
var qty = tr.find("#quantity_"+current_id).val();
var dis = tr.find("#tax_"+current_id).val();
var price = tr.find("#price_"+current_id).val();
var taxVal= tr.find("#tax"+current_id).val();
var rate = taxVal.split('_')[1];
var amt = (qty * price) - (qty * price * dis) / 100;
var tax1 = (amt * (rate / 100));
tax1 = Number((tax1).toFixed(2));
tr.find('#tamount_'+current_id).val(tax1);
tr.find('#tamount_'+current_id).val(amt);
});

Ordering Child Table data using JQuery

I am creating dynamic data and displayed in child table using DOM object. This is the child table detail.
<table id="stdConTbl" width="135px" height="80px" class = "stdConTbl">
</table>
This is the code to create dynamic tr data.
var tbody = document.getElementById("stdConTbl").tBodies[0];
var tr = document.createElement('tr');
var td = document.createElement('td');
var att = document.createAttribute("width");
att.value = "1%";
td.setAttributeNode(att);
var td1 = document.createElement('td');
td.innerHTML = '<input type = "radio" style = "BACKGROUND-COLOR: #e1e8ee" id = "' + tmpCount + '" name = "' + radioName + '" value = "' + txtValue + '" onclick = "setTblRowId()"/>';
td1.innerHTML = '<label id = '+ tmpCount +"'>" +txtValue + '</label>';
tr.appendChild(td);
tr.appendChild(td1);
//var radioHtml = tr.innerHTML;
tbody.appendChild(tr);
Using this two button I am ordering these table data.
<img src="<%=request.getContextPath()%>/images/procseq/up.png" style="cursor: hand;" class="up" />
<img src="<%=request.getContextPath()%>/images/procseq/down.png" style="cursor: hand;" class="down" />
When i choosing this dynamically created radio button and click on "UP" button, the selected radio button label should be move one step to up and again i click on "UP" button the label should move one more step.
Same thing i follow when i click on "DOWN" button.
But I am not able to get child table row index.
This the code to order data.
$(document).ready(function(){
$(".up,.down").click(function(){
var selectedIndex = 0;
//var row = $(this).parents("tr:first"),$reindex_start;
for(var i = 0; i < document.getElementsByName('stdConRadio').length; i++){
if(document.getElementsByName('stdConRadio')[i].checked){
selectedIndex = document.getElementsByName('stdConRadio')[i].getAttribute("id");
}
}
var row = $(this).parents(".stdConTbl"),$reindex_start;
//var row_index = $(this).closest('tr').index();
if ($(this).is(".up")) {
//row.insertBefore(selectedIndex - 1);
row.insertBefore(row.prev());
$reindex_start=row;
} else {
$reindex_start=row.next();
row.insertAfter(row.next());
}
});
});
Try this : find tr of the the selected radio button and then use insertAfter or insertBefore to move tr.
$(document).ready(function(){
$(".up,.down").click(function(){
//get tr of selected radio button
var $tr = $('#stdConTbl').find('input[name="stdConRadio"]:checked').closest("tr");
//insert
if ($(this).is(".up")) {
$tr.insertBefore($tr.prev("tr"));
} else {
$tr.insertAfter($tr.next("tr"));
}
});
});

How to retain add rows and its value even after page reload

Good day,
I have a table where you can dynamically add/remove rows, on each row you can add an select an item from the list its working perfectly at the moment, what I want to add is for it to retain the added rows and its values even if I page reload my browser?
I have seen on my research that you can attain it by using cookies/localStorage,but would be okay if I store many items on it?
heres my table looks like:
my JS:
function addRow(){
var rowCount = document.getElementById('tblItemList').rows.length - 1 ;
var rowArrayId = rowCount ;
var toBeAdded = document.getElementById('toBeAdded').value;
if (toBeAdded=='')
{ toBeAdded = 2; }
else if(toBeAdded>10)
{
toBeAdded = 10;
}
for (var i = 0; i < toBeAdded; i++) {
var rowToInsert = '';
rowToInsert = "<tr><td><input id='itemName"+rowArrayId+"' required name='product["+rowArrayId+"][name]' class='form-control col-lg-5 itemSearch' type='text' placeholder='select item' />"+
"<input type='hidden' class='rowId' value='"+rowArrayId+"'>"+
"<input type='hidden' name='product[" + rowArrayId + "][itemId]' id='itemId'></td>";
$("#tblItemList tbody").append(
rowToInsert+
"<td><textarea readonly name='product["+rowArrayId+"][description]' class='form-control description' rows='1' ></textarea></td>"+
"<td><input type='number' min='1' max='9999' name='product["+rowArrayId+"][quantity]' class='qty form-control' required />"+
"<input id='poItemId' type='hidden' name='product[" + rowArrayId + "][poContentId]'></td>"+
"<td><input type='number' min='1' step='any' max='9999' name='product["+rowArrayId+"][price]' class='price form-control' required /></td>"+
"<td class='subtotal'><center><h3>0.00</h3></center></td>"+
"<input type='hidden' name='product["+rowArrayId+"][delete]' class='hidden-deleted-id'>"+
"<td class='actions'><a href='#' class='btnRemoveRow btn btn-danger'>x</a></td>"+
"</tr>");
var rowId = "#itemName"+rowArrayId;
$(rowId).select2({
placeholder: 'Select a product',
formatResult: productFormatResult,
formatSelection: productFormatSelection,
dropdownClass: 'bigdrop',
escapeMarkup: function(m) { return m; },
formatNoMatches: function( term ) {
$('.select2-input').on('keyup', function(e) {
if(e.keyCode === 13)
{
$("#modalAdd").modal();
$(".select2-input").unbind( "keyup" );
}
});
return "<li class='select2-no-results'>"+"No results found.<button class='btn btn-success pull-right btn-xs' onClick='modal()'>Add New Item</button></li>";
},
minimumInputLength:1,
ajax: {
url: '/api/productSearch',
dataType: 'json',
data: function(term, page) {
return {
q: term
};
},
results: function(data, page) {
return {results:data};
}
}
});
rowArrayId = rowArrayId + 1;
};
function productFormatResult(product) {
var html = "<table><tr>";
html += "<td>";
html += product.itemName ;
html += "</td></tr></table>";
return html;
}
function productFormatSelection(product) {
var selected = "<input type='hidden' name='itemId' value='"+product.id+"'/>";
return selected + product.itemName;
}
$(".qty, .price").bind("keyup change", calculate);
};
the problem here is whenever Im refreshing the page the Items that I added will also be lost as well as those rows that I've added, any suggestions please? Thanks you very much for your time! Have a nice Day!
Your best bet here would be to cookies to store json data.
Your best bet here would be to cookies to store json data.
function storeRowData() {
var data = [];
$('.TABLE_NAME tr').each(function () {
var $this = $(this),
pname = $this.find(PRODUCT_NAME_INPUT).val(),
desc = $this.find(PRODCUT_DESC_INPUT).val(),
quant = $this.find(PRODUCT_QUANTITY_INPUT).val(),
price = $this.find(PRODUCT_PRICE_INPUT).val();
var temp = { productName: pname, description: desc, quantity: quant, price: price };
data.push(temp);
});
$.cookie('Table_Rows', JSON.stringify(data), {OPTIONS});
}
Now whenever you add or remove rows, you can call this. And when you reload page just read the cookie and parse the string back to JSON and traverse and call addrow for each row.
NOTE: Be sure to read full documentation on jquery.cookie() Here
You can use window.location.reload(true) and $( document ).ready function where you can get current no. of rows.Define row count & column count variable as a global variable.
location.reload(true);
var rowCount,rowArrayId,toBeAdded ;
$(document).ready(function() {
rowCount= document.getElementById('tblItemList').rows.length - 1 ;
rowArrayId = rowCount ;
toBeAdded = document.getElementById('toBeAdded').value;
});

Categories