table.removeRow() stops working when 'resetting' table? - javascript

Suppose you have a html table of the
<form id="myForm">
<table id="myTable">
<tr>
<th>One</th>
<th>Two</th>
<th>Three</th>
</tr>
<tr>
<td>Alpha</td>
<td>Bravo</td>
<td>X</td>
</tr>
<tr>
<td>Charlie</td>
<td>Delta</td>
<td>X</td>
</tr>
<tr>
<td>Echo</td>
<td>Foxtrot</td>
<td>X</td>
</tr>
</table>
</form>
Reset
I have the following javascript
var table = document.getElementById('myTable');
var form = document.getElementById('myForm');
var formSave = form.innerHTML;
function remove(rowID)
{
table.deleteRow(rowID);
}
function reset()
{
form.innerHTML = formSave;
}
For some reason, the remove() function works fine, but after using the reset() function, it no longer works. Can anyone tell me why this is?

As var table is a live 'Element object' it's properties are updated each time you delete a row. By the time you deploy the reset() function var table references less Children than the restored HTML. Opening the console will show you have an indexing error on subsequent uses of the function bound to "X".
You can remedy this by re-acquiring the element in the reset function, like so...
var table = document.getElementById('myTable');
var form = document.getElementById('myForm');
var formSave = form.innerHTML;
function remove(rowID) {
table.deleteRow(rowID);
}
function reset() {
form.innerHTML = formSave;
/* re-acquire 'new' (inserted) table */
table = document.getElementById('myTable');
}
Hope that helped :)

Related

How do i refresh or redraw table rows

Below is the classical issue which I am facing during my app development.
I have an array of JSONObjects in my spring controller that I have to iterate in the jsp;
Also another status attribute called JSONArrayStatus is set that suggests if JSON array is empty or not.
Using jquery if JSONArray is empty I will show noDataImageDiv otherwise will show tableDIV (Binding the data from JSONArray using JSTL)
The problem I am facing is as below.
1. Edit a row in the table and click on Update. At this time I make an Ajax Call say, "UpdatedUser", which will return all the records along with the updated records. I could use refresh however thats not a recommended user experience and hence a no no.
To reflect the updated users in the table, I use jquery as below
clearing table rows table.clear().draw()
Loop the result set as follows.
redraw code
function reDrawExternalContactUsers(externalUsers) {
table.clear().draw();
var row = "";
$.each(externalUsers, function (i, field) {
row = '<tr><td></td><td></td><td class="edit">edit</td></tr>';
$("#tableDIV").append(row);
});
}
afetr this redraw or refresh process
This function is NOT working
$(".edit").click(function(){
});
This function is working
$("#tableDIV .edit").click(function(){
});
Suggest a better way of refreshing table rows, if any.
<div id="tableDIV">
<table id="tableID">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
if data exist
loop{
<tr>
<td></td>
<td></td>
<td class="edit">edit</td>
</tr>
} // loops ends
if close
</tbody>
</table>
</div>
<div id="noDataImageDiv"> No data image</div>
html code :
<div id="tableDIV">
<table id="tableID">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
if data exist
loop{
<tr>
<td class="user-name"></td>
<td></td>
<td class="edit" data-user-id="">edit</td> //set user_id in attr data-user-id
</tr>
} // loops ends
if close
</tbody>
</table>
</div>
<div id="noDataImageDiv"> No data image</div>
jquery code :
you should use click event on document
$(document).on('click', '.edit', function () {
var btn = $(this);
var user_id = btn.attr("data-user-id"); //user_id of user will update
// extra user data
$.ajax({
method: "POST",
url: url,
data: {
'id': id,
// extra data to send
},
success: function (data) {
if (data.status) // successfully user updated
{
var user = data.user;
/* you can set user data like this */
btn.closest('tr').find('.user-name').html(user.name);
}
}
});
});

Multiply td values

I have a html table that looks like this...
<table>
<tr>
<th>Date</th>
<th>Pair</th>
<th>Game</th>
<th>Chance</th>
</tr>
<tr>
<td>2014-2-12</td>
<td>Milan-Udinese</td>
<td>1</td>
<td>1.6</td>
</tr>
<tr>
<td>2014-2-13</td>
<td>Juventus-Inter</td>
<td>x</td>
<td>2.5</td>
</tr>
<tr>
<td>2014-2-13</td>
<td>Arsenal-Liverpul</td>
<td>2</td>
<td>2.5</td>
</tr>
</table>
<p>Total number is:MULTIPLICATION OF ALL CHANCE COLUMN TD</p>
all my rows are added dynamically,how do i multiply all chance column td values(numbers)?Do i have to put certain class on chance tds and then get all tds with that class,and loop through and multiply every value then?I'm kinda a newbie so any help would be appreciated.
You can either do something like this:
var tots = 1;
$('tr td:nth-child(4)').each(function(){
tots *= $(this).text();
});
the nth-child(4) is selecting the fourth td in each row, if you want another, just change that number.
or you can give the cells you want to multiple classes, like you said.
example here
If you're using jQuery, the :last-child selector could be helpful.
<p>Total number is: <span id="result"></span></p>
Javascript:
res = 1;
$("tr td:last-child").each(function() {
res *= parseFloat($(this).html());
});
$("#result").html(res);
Have a look to this JSFiddle.
You don't need jQuery to do this. querySelectorAll supports nth-child selector as well.
var derp = document.querySelectorAll("tr td:nth-child(4)");
var total = 1;
var results = [].reduce.call(derp, function (prev, next) {
return prev * ( + next.textContent );
});
Grab the element, and use native Array prototype methods ([]) to iterate the NodeList and return the parsed value of the element, then return the multiplied total.
Here is a fiddle for you.
$(function () {
var chanceTotals = 1;
$("tr td:nth-child(4)").each(function () {
chanceTotals *= parseFloat($(this).html());
});
$("#totals").html("Total number is: " + chanceTotals);
});
Using jQuery, this executes an anonymous function when the document is ready that will do the calculation for you.
You will need to add the id totals to your p element in order for this to work.
Look at this JSFiddle
You really do not need jquery at all to do this. Interacting with the DOM directly may make you write more (browser support), but it can be more efficient than using jQuery (Unnecessary overhead).
As you can see, I restructured your <table>. I could have just grabbed the <tbody> and looped over its children and skipped the whole if <TD> ? check.
DEMO
$(document).ready(function () {
var table = $('#myTable').get(0);
var multiplier = 1;
var col = 3;
for (var row = 0; row < 4; row++) {
var cell = table.rows[row].cells[col];
if (cell.nodeName == 'TD') {
var text = cell.innerText || cell.textContent;
multiplier *= parseFloat(text);
}
}
$('#multiplier').text(multiplier);
});
<table id="myTable">
<thead>
<tr>
<th>Date</th>
<th>Pair</th>
<th>Game</th>
<th>Chance</th>
</tr>
</thead>
<tbody>
<tr>
<td>2014-2-12</td>
<td>Milan-Udinese</td>
<td>1</td>
<td>1.6</td>
</tr>
<tr>
<td>2014-2-13</td>
<td>Juventus-Inter</td>
<td>x</td>
<td>2.5</td>
</tr>
<tr>
<td>2014-2-13</td>
<td>Arsenal-Liverpul</td>
<td>2</td>
<td>2.5</td>
</tr>
</tbody>
</table>
<p>Total number is:
<span id="multiplier">MULTIPLICATION OF ALL CHANCE COLUMN TD</span>
</p>

Simple show/hide gone wrong in Javascript

I'm trying to create a show/hide function for data within a table populated with data from a mssql database. The function should look for rows with the same value in the "capability" column and onclick, hide all rows with the same value. After this, a row is inserted into the table with the same capability value, but summarizes the data in the hidden rows. This should work in the way that grouping cells together works in excel.
I've managed to get this to work, but it only works for the first click and I receive a "cannot read innerHTML property of NULL" for any of the function's calls after that.
function compactRows(thisrow) {
var totalRows = document.getElementById("DataTable").getElementsByTagName("tr").length;
var summaryVal1= [];
var summaryVal2= [];
for(var i = 1; i < totalRows;i++) {
var trID = "capability" + i;
if(thisrow.innerHTML == document.getElementById(trID).innerHTML) { //The error gets returned on this line
summaryVal1.push(document.getElementById(trID).parentNode.children[5].innerHTML);
summaryVal2.push(document.getElementById(trID).parentNode.children[14].innerHTML);
document.getElementById(trID).parentNode.style.display = 'none';
}
}
createNewRow(thisrow, summaryVal1, summaryVal2);
}
//I took out the logic for the data summarizing in the createNewRow function because I don't think its relevant to the issue I'm having. Also, I didn't want to crowd the area with unrelated code
function createNewRow(row, ibxMobile, overallStatus) {
var table = document.getElementById("DataTable");
var localRow = table.insertRow(row.parentNode.rowIndex);
var cell1 = localRow.insertCell(0);
cell1.setAttribute("id", "entry1");
var cell2 = localRow.insertCell(0);
cell2.setAttribute("id", "Capability");
cell2.innerHTML = row.innerHTML;
var cell3 = localRow.insertCell(0);
cell3.setAttribute("id", "entry3");
}
The function called at the bottom, createNewRow, handles making the row to be entered after all the rows are hidden. It also, handles the logic for summarizing the hidden rows.
All help is greatly appreciated! Thank you
Edit 1: example table set up
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1.1</td>
<td id="Capability1" onclick="compactRows(this)">Lasers</td>
<td>stuff</td>
</tr>
<tr>
<td>1.2</td>
<td id="Capability2" onclick="compactRows(this)">Lasers</td>
<td>things</td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
//The Below table is what it looks like after clicking either of the first two entries
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1</td>
<td id="Capability">Lasers</td>
<td></td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
There is no "Capability1" id for any rows after the "CreateNewRow" is called. Therefore, the second time "CompactRows()" is called a null reference is thrown when accessing "document.getElementById("Capability1").innerHTML". Rework the CreateNewRow to inlcude the increment for the Capability id value or test that "getElementById" actually returns an object before attempting to access the innerHTML method.

Append tr in table in IE

I have a table structure:
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
</tbody>
</table>
I am adding new row with simple Javascript like this:
var itemsContainer = dojo.byId('tbodyId');
itemCount++; //it will give id to tr i.e. trId2
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + itemCount);
newItemNode.innerHTML ='<td>id</td><td>anotherName</td>';
itemsContainer.appendChild(newItemNode);
All works fine in Firefox but row is not appended in IE. New table after it in Firefox becomes:
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
<tr id="trId2">
<td>id</td><td>anotherName</td>
</tr>
</tbody>
</table>
I saw other codes and help. I only want one tbody in this table with simple Javascript no jQuery.
There are special functions for creating table cells ( and rows ) eg - insertRow for rows and insertCell for cells - it works in all browsers
var newItemNode = itemsContainer.insertRow( itemsContainer.rows.length - 1 );
newItemNode.setAttribute("id", 'trId' + itemCount);
var cell = newItemNode.insertCell( 0 );
cell.innerHTML = 'id';
...
PS. I think DOJO Framework have something for inserting rows and cells
First off, this jsfiddle works fine in FF6 & IE8
Make sure that your real html has the proper markup. Your example shows a closing tbody element without the slash
<tr id="trId2">
<td>id</td><td>anotherName</td>
</tr>
<tbody> <!-- This line should be </tbody> -->
IE is inconsistant with its acceptance of bad markup.
In addition, code like this:
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + itemCount);
newItemNode.innerHTML ='<td>id</td><td>anotherName</td>';
Is exactly the sort of code that toolkits like dojo (and its smarter cousin, jQuery) are built to avoid. I suspect the code for creating a new row are different in the version of IE you're testing on.
try this
<html>
<script language = "javascript">
function kk()
{
var itemsContainer = document.getElementById("tbodyId");
var newItemNode = document.createElement('tr');
newItemNode.setAttribute("id", 'trId' + 1);
var newCellItem1 = document.createElement('td');
newCellItem1.innerHTML = "id";
var newCellItem2 = document.createElement('td');
newCellItem2.innerHTML = "anotherName";
newItemNode.appendChild(newCellItem1);
newItemNode.appendChild(newCellItem2);
itemsContainer.appendChild(newItemNode);
}
</script>
<table id="tableId">
<tbody id="tbodyId">
<tr id="trId1">
<td>id</td><td>name</td>
</tr>
</tbody>
</table>
<input type="button" value = "heihei" onclick = "kk();"></input>
</html>

Rearranging table in JavaScript

I want reorder table rows using JavaScript .
for example take the following dummy table:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
<td>D1</td>
</tr>
</table>
I want to do this in JavaScript without using jQuery. I want to show the A1,B1,C1,D1.. row as the first row and then 1,2,3,4 row and then A,B,C,D row.
I know that there will be some wait time on the client side but I need to do it in the client side. Is there some generic solution to do this, for any number of rows?
If I understand correctly, you are asking how to take the last row and make it the first row, pushing down the rest. This should do it:
<table id="mytable">
...
</table>
<script type="text/javascript">
var tbl = document.getElementById('mytable');
var rows = tbl.getElementsByTagName('tr');
var firstRow = rows[0];
var lastRow = rows[rows.length];
firstRow.parentNode.insertBefore(lastRow.parentNode.removeChild(lastRow), firstRow);
</script>
Assuming your table does not have nested tables. At which point this would need to be a little smarter. This also assumes you're not using TBODY and THEAD nodes. But I'm sure you can get the idea and enhance it from there.
Do:
var table = ...; // Get reference to table (by ID or other means)
var lastRow = table.rows[table.rows.length - 1];
lastRow.parent.insertBefore(table.rows[0], lastRow);
The best way to solve this in Javascript is:
Give the Tr.. a unique name. for eg: X_Y,X_Z,A_Y,A_Z
Now add a hidden lable or text Box which gives the sorting order from the server i.e When the page renders I want to sort it All the Tr's that have a ID starting with A should come first and All the Z's should come second.
<asp:label id="lblFirstSortOrder" runat="server" style="display:none;">A,X</label>
<asp:label id="lblSecondSortOrder" runat="server" style="display:none;">Z,Y</label>
When the page renders..the order should be A_Z,A_Y,X_Z,X_Y
Before Rendering this is table that comes from the aspx file:
<table>
<tr id='Tr_Heading'>
<td>A</td>
<td>B</td>
</tr>
<tr id="Tr_X_Y">
<td>GH</td>
<td>GH1</td>
</tr>
<tr id="tr_X_Z">
<td>HU</td>
<td>HU1</td>
</tr>
<tr id="tr_A_Z">
<td>JI</td>
<td>JI1</td>
</tr>
<tr id="tr_A_Y">
<td>JI</td>
<td>JI1</td>
</tr>
Script:
function SortAndArrange()
{
var firstList = document.getElementById('lblFirstSortOrder').value;
var secondList = document.getElementById('lblSecondSortOrder').value;
var firstTypes = new Array();
firstTypes = firstList.split(',');
var secondLists = new Array();
secondLists = secondList.split(',');
var refNode = document.getElementById('Tbl_' + firstTypes[0] + "_" + secondTypes[0]);
for (var i = 0; i<firstTypes.length; i++)
{
for (var j = 0; j< secondTypes.length;j++)
{
var TrName = 'Tbl_'+firstTypes[i]+'_'+secondTypes[j];
var FirstSecondTrs = document.getElementById(TrName);
if (FirstSecondTrs)
{
FirstSecondTrs.parentNode.removeChild(FirstSecondTrs);
insertAfter(refNode,FirstSecondTrs);
refNode = FirstSecondTrs;
}
}
}
}
function insertAfter( referenceNode, newNode )
{
referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );
}
I hope you guys get the idea.. for me the sorting order will always come from the server and not from the user of the page...
Thanks a Lot for all the answers.. Apprecite it. Helped me get to this solution.
Thanks,
Ben

Categories