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;
});
});
}
});
Related
I'm fairly new to coding. I have a jQuery datatable, and when I select a row, the tds of that row fill out html textboxes above the table. I'm trying to make it so whatever is entered into those textboxes (and upon pressing the save button), is then saved into the row.
Currently I have it so it saves 1 field/td. If I press on column 0, fill out the Name textbox and press save, it saves. But it works on any column. It should only be editing the correct td. Plus I want to edit the entire row, not just one td. I'm not sure how to accomplish this. Thanks for any help!
JSFiddle
Javascript:
var table = $('#example').DataTable();
(function () {
var table = document.querySelector('#example');
var name = document.querySelector('#nameinput');
var format = document.querySelector('#formatinput');
var address = document.querySelector('#addressinput');
var report = document.querySelector('#reportinput');
var alarm = document.querySelector('#alarminput');
table.addEventListener('click', onTableClick);
function onTableClick (e) {
var tr = e.target.parentElement;
var data = [];
for (var td of tr.children) {
data.push(td.innerHTML);
}
name.value = data[0];
address.value = data[1];
format.value = data[2];
report.value = data[3];
alarm.value = data[4];
console.log(alarm.value);
}
$("#saverow").click(function() {
var table1 = $('#data-table').DataTable();
var data = [];
data[0] = name.value;
data[4] = alarm.value;
console.log(name.value);
console.log(alarm.value);
table1.draw(true);
});
})();`
I've updated my code with what I've tried so far. Currently, what I type in the textboxes, correctly is displayed in the console (upon hitting the saverow button), now I cant figure out how to save that into the table.
i think it is mor responsive to edit data right in the table.
HTML:
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Format</th>
<th>Report Time</th>
<th>Alarms</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>Tiger#gmail.com</td>
<td>email</td>
<td>1PM</td>
<td>Master</td>
<td class="td-button"></td>
</tr>
<tr>
<td>Bill Gates</td>
<td>111-111-1111</td>
<td>sms</td>
<td></td>
<td>Master</td>
<td class="td-button"></td>
</tr>
</tbody>
</table>
JS:
var table = $('#example').DataTable();
$("#example tbody tr").click(function(){
if (! $(this).find("button").length)
{
$(this).find("td").each(function(){
if (!$(this).hasClass("td-button"))
{
var text = $(this).text();
$(this).html ('<input type="text" value="' + text + '">')
} else
$(this).html ('<button class="button-save">Save</button>')
})
}
})
$(document).on("click", ".button-save",function(){
var tr = $(this).parent().parent();
tr.find("td").each(function(){
if (!$(this).hasClass("td-button"))
{
var text = $(this).find("input").val();
$(this).text(text)
} else
$(this).html('');
})
})
https://jsfiddle.net/91wvw619/
I have a page that is essentially a table which has its rows duplicated when the button is pushed. Each additional row has a unique id/name.
I now have this problem. I essentially have a similar table on a different page. Main difference is that it may have additional inputs. At the moment, it looks something like this:
JavaScript
var cloned;
$(function() {
initDatepickersAndSelect();
$('#add_row').on('click', function(evt) {
addRow();
});
$('#delete_row').on('click', function(evt) {
deleteRow();
});
$('#add_row2').on('click', function(evt) {
addRow(x);
});
$('#delete_row2').on('click', function(evt) {
deleteRow(x);
});
});
function initDatepickersAndSelect() {
cloned = $("table tr#actionRow0").eq(0).clone();
$(".dateControl").datepicker({
dateFormat: "dd-mm-yy"
});
$(".responsibility").select2({
tags: true
});
$(".campaignType").select2({
tags: true
});
}
function addRow() {
var $tr = cloned.clone();
var newRowIdx = $("table#actionTable tr").length - 1;
$tr.attr('id', 'actionRow' + newRowIdx);
$tr.find("input, select").each(function(i_idx, i_elem) {
var $input = $(i_elem);
if ($input.is("input")) {
$input.val("");
}
$input.attr({
'id': function(_, id) {
return id + newRowIdx;
},
'name': function(_, name) {
return name.replace('[0]', '[' + newRowIdx + ']');
},
'value': ''
});
});
$tr.appendTo("table#actionTable");
$(".dateControl", $tr).datepicker({
dateFormat: "dd-mm-yy"
});
$(".responsibility", $tr).select2({
tags: true
});
$(".campaignType", $tr).select2({
tags: true
});
}
function deleteRow() {
var curRowIdx = $("table#actionTable tr").length;
if (curRowIdx > 2) {
$("#actionRow" + (curRowIdx - 2)).remove();
curRowIdx--;
}
}
HTML
<div class="col-md-12 noPadding">
<table class="table table-bordered table-hover additionalMargin" id="reportTable">
<thead>
<tr>
<th class="text-center">Something</th>
<th class="text-center">Something else</th>
</tr>
</thead>
<tbody>
<tr id='actionRow0'>
<td>
<select class="campType" name='reportInput[0][campType]' id="reportInput">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</td>
<td>
<input type="text" name='reportInput[0][campDelivery]' id="dateInput" class="form-control" />
</td>
</tr>
</tbody>
</table>
<a id="add_row" class="btn btn-default pull-right">Add Row</a>
<a id='delete_row' class="pull-right btn btn-default">Delete Row</a>
</div>
The last thing I want to do is duplicate all of my JavaScript and rename things to match the above.
What I am wondering, is there anyway I could reuse the JavaScript?
Any advice appreciated.
Thanks
(code also available as JSFiddle)
Based on my understanding of the question, I think you could do something like this. Assuming a function called addRow as seen in your fiddle, the first step is to include that JS on all pages where you want that functionality. You then mentioned that other pages might have additional controls. For this, I'd override the function...
On the page with normal controls
function addRow() {
// Row adding code...
}
On the page with extra controls
var oldAddRow = addRow;
var addRow = function(){
$('.some_other_control').click(ctrlHandler);
$('.some .input').val('');
oldAddRow();
}
I suggest to have an invisible "template row" in your table, which you can copy to add new rows.
Something like this:
<style>
tr.template { display: none; }
</style>
<table id="table1">
<tr class="template"><td><input id="blah">/td><td><input id="foo"></td></tr>
</table>
<button id="add">Add Row</button>
<script>
function add_row($table) {
var count = $table.find('tr').length - 1;
var tr_id = ""+(count+1);
var $template = $table.find('tr.template');
var $tr = $template.clone().removeClass('template').prop('id', tr_id);
$tr.find(':input').each(function() {
var input_id = $(this).prop('id');
input_id = tr_id + '_' + input_id;
$(this).prop('id', input_id);
});
$table.find('tbody').append($tr);
}
$('#add').on('click', function() { add_row($('#table1')); });
</script>
I think it will be easier to make the code generic in this way. If you don't want the inputs in the template to be submitted, you can disable them or remove them somehow.
Demo: http://sam.nipl.net/table-demo.html
You may just clone a row and reset attibutes within with something like:
function addRow(id) {
var c = $("table#"+id+" tr").last();
$("table#"+id+" tbody").append(c.clone().attr({id: "addedrow" + Math.random()*10+1}));
}
function deleteRow(id,index) {
var curRowIdx = $("table#"+id+" tr").length;
if (curRowIdx > 2) {
if(index != void 0) {
$("table#"+id+" tr")[index].remove();
}else{
$("table#"+id+" tr").last().remove();
}
}
}
Call it with
$('#add_row').on('click', function(evt){addRow("reportTable");});
$('#delete_row').on('click', function(evt){deleteRow("reportTable",1);});
Maybe you'll prepare new rows for your table with something like
var emptyRow[id] = $("table#"+id+" tr").last();
and change
$("table#"+id+" tbody").append(c.clone().attr({id: "addedrow" + Math.random()*10+1}));
to
$("table#"+id+" tbody").append(emptyRow[id].clone().attr({id: "addedrow" + Math.random()*10+1}));
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/
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();
});
I have a table within a form that I want to append new rows as the user enters input in the last row of the table.
$('table.form-table').on('input', function() {
var tableID = '#' + $(this).closest('table').attr('id');
if(jQuery(this).closest('tr').is(':last-child')) {
var currTR = $(this).closest('tr');
var currTRhtml = '<tr>' + currTR.html() + '</tr>';
var nextRow = jQuery(currTRhtml);
var checkBox = jQuery('<td class="border-right checks"><input type="checkbox" name="del_000" value="000"></td>');
jQuery(tableID).append(nextRow);
checkBox.appendTo(currTR);
}
});
And the html code if needed (simplified/trimmed):
<table class="form-table" id="XXX" border="1" cellspacing="0" cellpadding="3">
<thead>
<tr class="main"><th nowrap colspan="3" align="left"
class="border-left border-top border-right">
<h3>XXX</h3></th>
</tr>
<tr>
<th>header</th>
</tr>
</thead>
<tbody>
<tr>
<input type="hidden" name="isnew" value="">
<td >
<input type="text"
name="new_text"
value="">
</td>
</tr>
</tbody>
</table>
The problem is that this works only once and does not continue appending new rows. It's as if the last-child filtering does not get reset...
Any thoughts?
The problem is that you need to use the event's target, rather than "this". Right now "this" refers to the current table, but you need to refer to the current input box and then use closest() to find its parent tr (and :first-child to make sure it's the last one). So your code needs to look more like this:
$('table.form-table').on('input', function(e) {
var tableID = '#' + $(this).closest('table').attr('id');
if ($(e.target).closest('tr').is(':last-child')) {
var currTR = $(e.target).closest('tr');
var currTRhtml = '<tr>' + currTR.html() + '</tr>';
var nextRow = $(currTRhtml);
var checkBox = $('<td class="border-right checks"><input type="checkbox" name="del_000" value="000"></td>');
$(tableID).append(nextRow);
checkBox.appendTo(currTR);
}
});
Notice I'm passing the event as "e" and then referencing the current input box with $(e.target).
Here's a working JS fiddle.
I suspect the problem is that you need to delegate the input event as the appended rows do not exist on $(document).ready(). Try doing something like this to delegate the handler:
$(document).ready(function () {
$('table.form-table tbody').on('input', 'tr', function () {
var self = $(this),
tableID = '#' + self.closest('table').attr('id'),
currTR = self.closest('tr'),
currTRhtml = '<tr>' + currTR.html() + '</tr>',
nextRow = $(currTRhtml),
checkBox = $('<td class="border-right checks"><input type="checkbox" name="del_000" value="000"></td>');
if (currTR.is(':last-child')) {
$(tableID).append(nextRow);
checkBox.appendTo(currTR);
}
});
});
Fiddle: http://jsfiddle.net/KW7ET/