adding row and then deleting causes duplicate rows - javascript

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>

Related

Javascript - Getting removed item name from table?

So I have an table. By click of a button, information will be added there, so each item has also X button, which removes them from the list. I've been trying to do that, if you click that X button, then it will output to console the item name which you deleted. How could I do that?
Here's the function
function sitaSeen(img, name, condition, price) {
$('tbody').append("<tr id='itemCart'><td><img src=" + img + "></td><td>" + name + "</td><td>" + condition + "</td><td>$" + price + "</td><td><span>X</span></td></tr>");
Which is called, when item has to be added.
Here's the X button code
$(document).ready(function() {
$('.sweet-container').on('click', 'tr span', function(){
var removedname = $(this).closest('tr').ignore('span').text();
console.log(removedname);
$(this).closest('tr').remove();
});
});
There's also kind of my try, but ofc it wont work.
There is no ignore() method in jQuery so it will throws error in console. So either clone the tr and remove span from cloned object and then get text or get all td which is not contains span and get text.
$(document).ready(function() {
$('.sweet-container').on('click', 'tr span', function(){
var removedname = $(this).closest('tr').clone().remove('span').text();
// or
// var removedname = $(this).closest('tr').find('td:not(:has(span))').text();
console.log(removedname);
$(this).closest('tr').remove();
});
});
UPDATE : Since you just want the second column you can simply use :nth-child or :eq() selector(or eq()).
$(document).ready(function() {
$('.sweet-container').on('click', 'tr span', function(){
var removedname = $(this).closest('tr').find('td:nth-child(2)').text();
// or
// $(this).closest('tr').find('td:eq(1)').text();
// or
// $(this).closest('tr').children().eq(1).text();
console.log(removedname);
$(this).closest('tr').remove();
});
});
I think it might be better to use:
```
// better way to get to the tr element
var trElem = $(this).parentNode.parentNode;
```
The parentNode attribute is a better way to access the parent of an element.
The item name is the second td so you can use:
var removedname = $(this).closest('tr').find('td:eq(1)').text();
Because the ID have to be unique I added a new parameter to your function.
function sitaSeen(seq, img, name, condition, price) {
$('tbody').append("<tr id='itemCart" + seq + "'>" +
"<td><img src=" + img + "></td>" +
"<td>" + name + seq + "</td>" +
"<td>" + condition + "</td>" +
"<td>$" + price + "</td>" +
"<td><span>X</span></td>" +
"</tr>");
}
$(function () {
$('#addRow').on('click', function(e) {
var seq = +$(this).attr('data-seq');
$(this).attr('data-seq', seq + 1);
sitaSeen(seq, 'img', 'name', 'condition', 'price');
});
$('.sweet-container').on('click', 'tr span', function(){
var removedname = $(this).closest('tr').find('td:eq(1)').text();
console.log(removedname);
$(this).closest('tr').remove();
});
});
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<div class="sweet-container">
<button id="addRow" data-seq="1">Add Row</button>
<table>
<tbody>
</tbody>
</table>
</div>

JavaScript & HTML - Modifying dynamically created subclasses within a dynamically created class

Problem:
I have a dynamically created HTML table, that is used for filling out time sheets. It is created programmatically - there is no formal control. The design is a mix of CSS with text boxes being created through JavaScript. Now each 'row' of this table is in a class called 'divRow', and is separated from the others by having 'r' and the number of the row assigned to it as the class (i.e 'divRow r1', 'divRow r2', etc.).
Within each of these 'divRow's, I have cells in a class called 'divCell cc'. These do not have any identifiers in the class name. At the very last cell, I have a 'Total' column, which ideally calculates the total of the row and then adds it into a dynamically created text box.
What I have at the moment:
// Function to create textboxes on each of the table cells.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
//var getRow = $(this).parent().attr('class'); - this gets the 'divRow r#' that it is currently on.
var arr = document.getElementsByClassName('cc');
var tot = 0;
for(var i = 0; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
$('#t' + c.id).focus();
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});
As you can see, when the user clicks on the 'divCell cc', it creates a text box if one is not present. If the user clicks on the 17th column ('x17'), then it runs the for loop, and assigns the value of the total to the text box.
What I need to happen:
So what happens now is that the last cell sums the total of each cell that has a value. However, they are not row-dependent. I need it to calculate based on the row that it is currently 'on'. So if I'm calculating the 2nd row, I don't want the sum of the first, second and third being entered into the total, I just want the 2nd rows' values summed.
What I've tried:
I've tried looping through and using the 'divRow r#' number to try and get the items in the array that end in that number. (cells are given an id of 'x#y#' and the text boxes assigned to those cells are given an id of 'tx#y#').
I've tried getting elements by the cell class name, and then getting their parent class and sorting by that; didn't get far though, keep running into simple errors.
Let me know if you need more explanation.
Cheers,
Dee.
For anyone else that ever runs into this issue. I got it. I put the elements by the row class into an array, and then using that array, I got the childNodes from the row class. The reason the variable 'i' starts at 2 and not 0 is because I have 2 fields that are not counted in the TimeSheet table (Jobcode and description). It's working great now.
Cheers.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
// Get current row that has focus
var getRow = $(this).parent().attr('class');
// Get the row number for passing through to the next statement
var rowPos = getRow.split('r', 5)[1];
// Get all the elements of the row class and assign them to the rowClass array
var rowClass = document.getElementsByClassName('r' + rowPos)
// Given the rowClass, get the children of the row class and assign them to the new array.
var arr = rowClass.item(0).childNodes
// Initialize the 'total' variable, and give it a value of 0
var tot = 0;
// Begin for loop, give 'i' the value of 2 so it starts from the 3rd index (avoid the Req Code and Description part of the table).
for(var i = 2; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
// Assign focus to the 'Total' cell
$('#t' + c.id).focus();
// Assign the 'total' variable to the textbox that is dynamically created on the click.
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});

How to select multiple columns with JQuery to populate another control on page

I have a page with an HTML table and a select element. I want to use jQuery to extract two columns each row of the able, and add the columns as entries in the select list. For example, if my table is:
1 apple extra
2 banana extra
3 cherry extra
Then when the page loads I would like to add three labels to the select, one for each fruit name, with the corresponding values determined by the first column. I have unsuccessfully attempted to solve this at http://jsfiddle.net/dcodelli/7Ez9d/
My code:
$(document).ready
(
function()
{
var allindexes = $('#Fruits> tbody > tr > td:nthchild(1)').map(function(){
return $(this).text();
}).get();
var allnames = $('#Fruits> tbody > tr > td:nthchild(1)').map(function(){
return $(this).text();
}).get();
for (index = 0; index < a.length; ++index) {
$('#Preset').append('<option value = \"' + allindexes[index] +
'\">"' + allnames[index] + '</option>');
}
}
);
try
$(document).ready
(
$('table#Fruits > tbody > tr').each(function(trIndex) {
console.log ("tr");
var sText;
$(this).find('td').each (function(index, data) {
console.log(data);
if (index == 1) {
sText = $(this).html();
}
});
$('#PreSet').append("<option value='" +trIndex+ "'>" + sText + "</option>");
})
)
Many issues with your jsfiddle including wrong table name, wrong dropdown id.
Using your JSFiddle as a base (see JSFiddle: http://jsfiddle.net/dualspiral/6XdPm/)
$(document).ready(function () {
var allindexes = $('#Fruits > tbody > tr > td:nth-child(1)').map(function () {
return $(this).text();
}).get();
var allnames = $('#Fruits > tbody > tr > td:nth-child(2)').map(function () {
return $(this).text();
}).get();
for (index = 0; index < allindexes.length; ++index) {
$('#PreSet').append('<option value = "' + allindexes[index] + '">' + allnames[index] + '</option>');
}
});
You were using the wrong selector for nth-child (you missed out the hyphen), and in your for loop, you used the wrong variable (a.length instead of allindexes.length). Your JSFiddle also did not have the right ID for the dropdown (PreSet is not the same as Preset).

jqGrid gridComplete:- getRowData - get row cell value from array

Please - need syntax for setting variables from jqGrid getRowData
property
Looping thru rows - just need to pull the ID and Phrase column values into variables
gridComplete: function () {
var allRowsInGrid = $('#list').jqGrid('getRowData');
for (i = 0; i < allRowsInGrid.length; i++) {
pid = allRowsInGrid[i].ID;
vPhrase = allRowsInGrid[i].Phrase;
vHref = "<a href='#' onclick='openForm(" + pid + ", " + vPhrase + ")'>View</a>";
}
},
Was able to get ID easy enough with getDataIDs :-)
Need help with getting specific column values for pid and vPhrase for i
Cheers
Try this:
var ids = jQuery("#list").jqGrid('getDataIDs');
for (var i = 0; i < ids.length; i++)
{
var rowId = ids[i];
var rowData = jQuery('#list').jqGrid ('getRowData', rowId);
console.log(rowData.Phrase);
console.log(rowId);
}
Please Note: If your goal is to add a link to cell which calls a javascript method you can achieve this by using formatter like given below, formatter should be added to colModel like you add other column properties like name,index,width,align etc, so you can avoid the iteration over row data
formatter: function(cellvalue, options, rowObject) {
return "<a href='#' onclick='openForm("
+ rowObject.ID + ", "
+ rowObject.Phrase
+ ")'>View</a>";
}
This is what I use when I want to get Data by RowID for specific Cell.
var selRow = jQuery("#list10").jqGrid('getGridParam','selarrrow'); //get selected rows
for(var i=0;i<selRow.length;i++) //iterate through array of selected rows
{
var ret = jQuery("#list10").jqGrid('getRowData',selRow[i]); //get the selected row
name = ret.NAME; //get the data from selected row by column name
add = ret.ADDRESS;
cno = ret.CONTACTNUMBER
alert(selRow[i] +' : ' + name +' : ' + add +' : ' + cno);
}

Table Navigation and row selection

I have an HTML table which contains about 1000 rows and 26 columns. I am using this jQuery plugin to navigate between rows and make a selection.
My first problem is that the plugin is working fine, but—even using the latest version (0.6.1)—it's very slow when working with 1000 rows.
My second problem is that I want to create a JSON object representing the selected row from the table. I wrote a function that does this, but again it's too slow on such a big table. The following code works, but I want to optimise it:
$(document).bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var td_size = $("tr.selected td").size();
jsonText += "{";
for (i = 0; i < td_size; i++) {
if (i < td_size - 1) {
if (i == 0) {
// Get link URL.
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).find("a").attr("href") + "\",";
} else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\",";
}
}
else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\"";
}
}
jsonText += "}";
$('#content').html('').append(jsonText);
});
Any suggestions please?
One thing you can do is optimize your jQuery selectors to help the Sizzler work faster...
instead of biding on keyup of all document, how about keyup of a specific tr?
$("tr.selected td").size(); // slow
$("table").find(".selected").find("td"); // probably faster
Save the selected tr outside the loop, you're asking the sizzler to find your object 26 times by looping 1000 rows!
$("thead tr th").eq(i) // on every loop element? slow, try saving the information before the keyup event, they are not going anywhere are they?
So probably something like this would be faster:
var $allTrs = $("tr");
var $allHeads = $("thead tr th");
$allTrs.bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var $t = $(this),
$alltds = $t.find("td"),
td_size = $alltds.length();
jsonText += "{";
$.each($alltds, function(i){
jsonText += "\"" + $allHeads.eq(i).text() + "\":\"";
if (i == 0){ // you have a strange condition, will leave it up to u
// append link
jsonText += $(this).find("a").attr("href"); // i remove "" for better readability
}else{
// append text
jsonText += $(this).text();
}
});
jsonText += "}";
$('#content').text(jsonText); // cheaper than html
});
I have not tested this yet.
You can also create a json object directly (wouldn't affect how fast though), like this
var mynewjson = {};
Then inside a loop:
mynewjson[name] = value;

Categories