I have created a table where user can add row. And on specific column, there is an input where user can insert a value and jQuery will sum all the value and insert it to another input
So, to make it clear, here's an example:
example
The problem is, after I add more row, it won't sum all the input. It will only sum the FIRST input of the FIRST row but it won't sum when I insert a value in the second, third, forth and ... input.
Here's the table:
<table id="twe">
<thead>
<tr>
<th valign="middle"><center>Amaun</center></th>
</tr>
</thead>
<tbody>
<tr>
<td><input name="amount[]" type="text" class="amount" id="amount[]" value="" /></td>
</tr>
</tbody>
</table>
<button type="button" onclick="addrow('twe')" title="Add">Add</button>
<br/>
<br/>
Sum: <input type="text" id="sum" />
And here's the script
(function($) {
$.fn.currencyFormat = function() {
this.each( function( i ) {
$(this).change( function( e ){
if( isNaN( parseFloat( this.value ) ) ) return;
this.value = parseFloat(this.value).toFixed(2);
});
});
return this; //for chaining
}
})( jQuery );
$(document).ready(function () {
$('.amount').currencyFormat();
});
$(document).ready(function () {
$(".amount").each(function () {
$(this).keyup(function () {
calculateSum();
});
});
});
function calculateSum() {
var sum = 0;
$(".amount").each(function () {
if (!isNaN(this.value) && this.value.length != 0) {
sum += parseFloat(this.value);
}
});
$("#sum").val(sum.toFixed(2));
}
function addrow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[1].cells.length;
for(var i=0; i<colCount; i++) {
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[1].cells[i].innerHTML;
switch(newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
}
}
}
Same goes with the input currency. It only works on the first input of the first row.
Need help
Thank you
The problem lies in when you are binding the events. In your document.ready function you are looping through the .amount items and binding a keyup, but this doesn't account for FUTURE items that will be created. What you want to do is bind all instances AND future instances to run the calculation.
This can be done using the .on event in jQuery. Your document.ready would be updated as follows:
$(document).ready(function () {
$(document).on("keyup", ".amount", calculateSum);
});
Working Fiddle: http://jsfiddle.net/p2Hbm/
Related
So I'm trying to make a form where the user can dynamically add and remove rows containing cascading dropdowns as a class picker.
So far I've been able to make everything work except for the remove selected classes function.
I've tried a couple different deleteRow functions but can't seem to make it work.
My most recent attempt is by using the checkbox input but I'm open to any other solutions.
Thanks
<!DOCTYPE html>
<html>
<head>
<title>Semesters Planned</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(function() {
$('#selectCategory').change(function() {getSelectedItem(this, null); });
$('#button').click(function()
{addRow('dataTable'); });
var classes = {//can probably use external text files for these later on
"Core": ["UNI101", "ENG101"],
"Major": ["CSC101", "CSC180"],
"Elective": ["ART101", "PSY101"]
};
var keys = Object.keys(classes);
var category_dropdown = document.getElementById("selectCategory");
var getSelectedItem = function(element, row) {
var e = element;
var selectedCategory = e.options[e.selectedIndex].value;
var sub_category_dropdown = (row != null ? row.getElementsByTagName("select")[1] : document.getElementById("selectSubCategory"));
sub_category_dropdown.options.length = 0;
for (var i = 0; i < classes[selectedCategory].length; i++) {
sub_category_dropdown[sub_category_dropdown.length] = new Option(classes[selectedCategory][i], classes[selectedCategory][i]);
}
};
var addRow = function(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;
newcell.childNodes[0].selectedIndex = 0;
}
var selects = row.getElementsByTagName("select");
selects[0].addEventListener('change', function()
{
getSelectedItem(this, row)
}, false);
};
function deleteRow(tableID)
{
for (var rowi= table.rows.length; rowi==0;) {
var row= table.rows[rowi];
var inputs= row.getElementsByTagName('chk');
for (var inputi= inputs.length; inputi0;) {
var input= inputs[inputi];
if (input.type==='checkbox' && input.checked) {
row.parentNode.remove(tableID);
break;
}
}}}
for (var keys in classes) {
category_dropdown[category_dropdown.length] = new Option(keys, keys);
}
});
</script>
</head>
<body>
<INPUT type="button" value="Add Class" id="button" />
<INPUT type="button" value="Remove Selected Classes"/>
<form id="myForm">
<TABLE id="dataTable">
<TR>
<TD>
<select id="selectCategory">
<option>Choose Class Type</option>
</select>
</TD>
<TD>
<select id="selectSubCategory">
<option>Choose Class Type First</option>
</select>
</TD>
<TD><INPUT type="checkbox" name="chk" id="input"/></TD>
</TR>
</TABLE>
</form>
<input type = "Submit" value = "Submit">
</body>
</html>
My first suggestion would be to make sure that the remove button is doing something when you click it - you've attached an event listener to the Add Class button, but the Remove Selected Classes button doesn't look like it's calling that deleteRows function.
Then, make sure that you have a reference to that table in the deleteRows function. You are passing it a table id, but the table variable reference is defined outside of the scope of that function.
Then, work on the for loop and the logic therein. It looks like you are mistaking getElementsByTagName with getElementsByName. The one you are using is concerned with the tag name (input) not the name attribute (chk).
Hope this helps a little bit!
I have prepared this jsfiddle
The problem is that I have many rows containing product qty * price = sub total
This also must dynamically calculate grand total for all sub total amounts. And the biggest problem is the trigger since we may not have change trigger on the qty select fields.. really complicated for me.
I am so far stacked here:
$(document).ready(function() {
var qty=$('.qty').val();
var price = $('.price').val();
var sum = 0;
$('.amount').each(function() {
sum += parseFloat($(this).text());
});
});
Please give me idea for:
Which trigger to use so it can calculate on page load as well and if qty dropdown is changed too.
How to calculate each row first
thank you for your help and time in advance!
You have your answer here: http://jsfiddle.net/kY98p/10/
I changed the html to use the tags thead and tfoot for header and footer
Its just a cycle over the lines where you get the quantity and price and update the amount...
Here is the function that you should call:
function update_amounts()
{
var sum = 0.0;
$('#myTable > tbody > tr').each(function() {
var qty = $(this).find('option:selected').val();
var price = $(this).find('.price').val();
var amount = (qty*price)
sum+=amount;
$(this).find('.amount').text(''+amount);
});
//just update the total to sum
$('.total').text(sum);
}
And the event that you need is:
$('.qty').change(function() {
update_amounts();
});
UPDATE: jsfiddle with total: http://jsfiddle.net/kY98p/11/
Fiddle Demo
$(document).ready(function () {
var amt = $('.amount:gt(0)'), //select element with class greater than one
tot = $('#total'); // cache selectors
function calculator() {
amt.text(function () { // set text of class amount elements
var tr = $(this).closest('tr'); // get tr
var qty = tr.find('.qty').val(); // find it in current tr and get value of element with class qty
var price = tr.find('.price').val(); //get price
return parseFloat(qty) * parseFloat(price); // return product
});
tot.text(function () { //get total
var sum = 0; //set sum = 0
amt.each(function () { //run through all element with class amount
sum += parseFloat($(this).text()); // add text to sum
});
return sum; //set sum to total
});
}
calculator(); //call the above function
$('.qty,.price').change(calculator);// run calculator function when element with class qty or price is changed
});
You can try this one (I changed your html template). Solution work as you want:
1. Calculate each row (find closest input and get data from it)
2. Calculate total and put to span
3. If you will add more selected(with my work class) it will be work
$(".work").on("change", function(){
var total = 0;
$(".work").each(function(){
var val = $(this).closest("tr").find("input[type='text']").val();
total = total + ($(this).val()*val || 0);
});
$(".total").text(total);
});
And html
<table>
<tbody>
<tr>
<th>Product name</th>
<th>Qty</th>
<th>Price</th>
<th align="center"><span id="amount" class="amount">Amount</span></th>
</tr>
<tr>
<td>Product 1</td>
<td>
<select value="" class="qty work" name="qty">
<option value="1">1</option>
<option value="2">2</option>
</select>
</td>
<td><input type="text" value="11.60" class="price"></td>
<td align="center"><span id="amount" class="amount">0</span> eur</td></tr>
<tr>
<td>Product 2</td><td>
<select value="" class="qty work" name="qty">
<option value="1">1</option>
<option value="2">2</option>
</select>
</td>
<td><input type="text" value="15.26" class="price"></td>
<td align="center"><span id="amount" class="amount">0</span> eur</td></tr>
<tr>
<td colspan="2"></td>
<td align="right"><span id="total" class="total">TOTAL</span> </td>
</tr>
</tbody>
</table>
And work demo
Here is a solution that works in with your fiddle (http://jsfiddle.net/kY98p/20/) with one minor DOM update. I put the header of the table in a THEAD so that you can count on the TBODY TR rows to be those with data.
Here we have functions to compute the total of each row and of the whole table.
When you change a row, we recompute that row and then re compute the total.
When we load the page, we recompute everything.
$(document).ready(function () {
function computeRowTotal(row) {
var $row = $(row)
var qty = $row.find('.qty').val();
var price = $row.find('.price').val();
if (qty && price) {
$row.find('.amount').html(qty * price);
}
}
function computeTotal() {
var total = 0.0
$('tbody tr .amount').each(function () {
console.log('T', $(this).text());
total += parseFloat($(this).text());
})
$('tbody tr .total').html("Total: " + total);
}
function updateTable() {
$('tbody tr').each(function (row) {
computeRowTotal(this)
});
computeTotal(this)
};
$('select').bind('change', function () {
computeRowTotal($(this).closest('tr'));
computeTotal();
});
updateTable();
});
Please, give "direction where to go"
Many input rows. For each row is field class="row_changed"
If value in the field is higher than 0, then ajax pass entire row to php. Each row is included in <tr> </tr> For each <tr> id is set <tr id='row'>
At the moment I can do it only with many if
Need something like: if value in any of field field class="row_changed" is more than 0, then pass corresponding row (inside <tr id='row'>) to php.
Here is some information. Is it suitable for the described case?
<tr id='row1'>
<td>
<input type="text" name="row1[]" id="date_day1" class="row_changed1">
</td>
...
<td>
<input type="text" name="row1[]" id="is_row_changed1" size="1">
<script>
$(".row_changed1").on("change", function () {
document.getElementById('is_row_changed1').value = 1;
});
</script>
</td>
<tr>
if ($("#is_row_changed1").val() > 0) {
$.post("_autosave_array.php", $("#row1 :input").serialize(), function (data1) {
$('#load1').html(data1);
$('#is_row_changed1').val(0)
});
var str = $("#row1 :input").serialize();
$("#load1_1").text(str);
}
if ($("#is_row_changed2").val() > 0) {
$.post("_autosave_array.php", $("#row2 :input").serialize(), function (data2) {
$('#load2').html(data2);
$('#is_row_changed2').val(0)
});
var str = $("#row2 :input").serialize();
$("#load2_1").text(str);
}
Something like this should do it:
function doPost(changedRowId,serializeRowId,resultId,serializeResultId){
if ($(changedRowId).val() > 0) {
$.post("_autosave_array.php", $(serializeRowId + ":input").serialize(), function (data2) {
$(resultId).html(data2);
$(changedRowId).val(0)
});
var str = $("#row2 :input").serialize();
$(serializeResultId).text(str);
}
var rowData = [{changedRowId: "#is_row_changed1", serializeRowId: "#row1", resultId: "#load1", serializeResultId: "#load1_1"},
{changedRowId: "#is_row_changed2", serializeRowId: "#row2 ", resultId: "#load2". serializeResultId: "#load2_1"}
];
for(var i = 0; i < rowData.length; ++i){
var data = rowData[i];
doPost(data.changedRowId,data.serializeRowId,data.resultId,data.serializeResultId);
}
I can see that all your input tags have the same name, you can select all of them by name then put your condition/logic inside
sample:
$("input[name='row1[]']").each(function(){
if($(this).val()>0){
$.post("_autosave_array.php", $("#row1 :input").serialize(), function (data1) {
$('#load1').html(data1);
$('#is_row_changed1').val(0)
}
});
I have a table where I can add/delete rows. Thing is when I delete the first one, no rows cant be added anymore. SO, I'd like to prevent deleteion of that first row. How can I do that please?
Thanks
jQuery
$(document).ready(function ($) {
// trigger event when button is clicked
$("button.add").click(function () {
// add new row to table using addTableRow function
addTableRow($("table"));
// prevent button redirecting to new page
return false;
});
// function to add a new row to a table by cloning the last row and
// incrementing the name and id values by 1 to make them unique
function addTableRow(table) {
// clone the last row in the table
var $tr = $(table).find("tbody tr:last").clone();
// get the name attribute for the input and select fields
$tr.find("input,select").attr("name", function () {
// break the field name and it's number into two parts
var parts = this.id.match(/(\D+)(\d+)$/);
// create a unique name for the new field by incrementing
// the number for the previous field by 1
return parts[1] + ++parts[2];
// repeat for id attributes
}).attr("id", function () {
var parts = this.id.match(/(\D+)(\d+)$/);
return parts[1] + ++parts[2];
});
// append the new row to the table
$(table).find("tbody tr:last").after($tr);
$tr.hide().fadeIn('slow');
// row count
rowCount = 0;
$("#table tr td:first-child").text(function () {
return ++rowCount;
});
// remove rows
$(".remove_button").on("click", function () {
$(this).parents("tr").fadeOut('slow', function () {
$(this).remove();
rowCount = 0;
$("#table tr td:first-child").text(function () {
return ++rowCount;
});
});
});
};
});
HTML
<table id="table">
<thead>
<tr>
<th width="8" scope="col"> </th>
<th width="131" scope="col">Roba/Usluga</th>
<th width="144" scope="col">Jmj</th>
<th width="144" scope="col">Qty</th>
<th width="144" scope="col">Price</th>
<th width="144" scope="col">Rabat</th>
<th width="81" scope="col"> </th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>
<select name="sif_roba1" id="sif_roba1">
<option value="">Please select</option>
<option value="1">David Hasselhoff</option>
<option value="2">Michael Jackson</option>
<option value="3">Tina Turner</option>
</select>
</td>
<td>
<select name="idjmj1" id="idjmj1">
<option value="">Please select</option>
<option value="1">David Hasselhoff</option>
<option value="2">Michael Jackson</option>
<option value="3">Tina Turner</option>
</select>
</td>
<td>
<input name="cijena1" id="cijena1">
</td>
<td>
<input name="track1" id="track1">
</td>
<td>
<input name="rabat1" id="rabat1">
</td>
<td>
<button type="button" class="btn remove_button">Remove</button>
</td>
</tr>
</tbody>
</table>
<button type="button" class="add" onClick="clickMe();">Add</button>
DEMO
http://jsfiddle.net/PBZFw/
You can check the length of rows:
$(".remove_button").on("click", function () {
if ( $('#table tbody tr').length === 1 ) return;
// ...
});
http://jsfiddle.net/QLQRT/
The other option is using not method and first-child selector:
$(this).closest("tr").not(':first-child').fadeOut()...
Or hide the first row button using CSS:
#table tbody tr:first-child .remove_button { display: none; }
Here solution, you can optimize that function to your own goal http://jsfiddle.net/PBZFw/
$(document).ready(function ($) {
// trigger event when button is clicked
$("button.add").click(function () {
// add new row to table using addTableRow function
addTableRow($("table"));
// prevent button redirecting to new page
return false;
});
$(document).on("click", ".remove_button", removeTableRow );
// function to add a new row to a table by cloning the last row and
// incrementing the name and id values by 1 to make them unique
var rowCount = null;
function addTableRow(table) {
// clone the last row in the table
var $tr = $(table).find("tbody tr:last").clone();
// get the name attribute for the input and select fields
$tr.find("input,select").attr("name", function () {
// break the field name and it's number into two parts
var parts = this.id.match(/(\D+)(\d+)$/);
// create a unique name for the new field by incrementing
// the number for the previous field by 1
return parts[1] + ++parts[2];
// repeat for id attributes
}).attr("id", function () {
var parts = this.id.match(/(\D+)(\d+)$/);
return parts[1] + ++parts[2];
});
// append the new row to the table
$(table).find("tbody tr:last").after($tr);
$tr.hide().fadeIn('slow');
// row count
rowCount = 0;
$("#table tr td:first-child").text(function () {
return ++rowCount;
});
};
function removeTableRow(){
var $tbody = $(this).parents('tbody'),
$trLen = $tbody.find('tr').length
if ( $trLen === 1 ) return false;
$(this).parents("tr").fadeOut('slow', function () {
$(this).remove();
rowCount = 0;
console.log( rowCount );
$("#table tr td:first-child").text(function () {
return ++rowCount;
});
});
}
});
If i have a table:
<table id="myTable">
<tr>
<td>1</td><td>2</td><td>NoMatch</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>Match</td><td>4</td>
</tr>
</table>
I have been trying:
$(document).ready(function () {
$('input#myInput').keyup(function (val) {
// for each third td of each row, if this value does not contain: this.val() then hide it
});
});
Something like this:
var $cells = $('#myTable tr td:nth-child(3)'),
$hidden = $();
$('#myInput').keyup(function () {
var search = this.value;
var $to_hide = $cells.filter(function() {
return $(this).text() !== search;
}).parent();
$hidden.not($to_hide.get()).show();
$hidden = $to_hide.hide();
});
I assumed that when you say contains, you mean that the text has to be equal to the provided input (otherwise NoMatch and Match would not make sense). But if the content of cell just has to contain the search string as substring, you can use .indexOf() [docs].
DEMO
There are other things you have to consider, like what should happen when the search string is empty, but this is for you to play around ;)
Use "this" in your key up event handler to get the value of the input.
$(document).ready(function () {
$('input#myInput').keyup(function () {
//add if statement
alert($(this).val());
});
});
Not quite sure what you are trying to do with the table. There is not enough information.
Try this:
jsfiddle
HTML
<table id="myTable">
<tr>
<td>1</td><td>2</td><td>NoMatch</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>Match</td><td>4</td>
</tr>
</table>
<input id="myInput"/>
Javascript/Jquery
$('#myInput').keyup(function () {
var me = $(this);
var val = me.val();
$("#myTable tr").each(function() {
var tr = $(this);
var td = tr.find("td:eq(2)");
if(td.text().substring(0, val.length) === val) {
tr.show();
} else {
tr.hide();
}
});
});