I have a html table like this:
<table>
<tr id='first'>
<td>text</td>
</tr>
<tr>
<td>text</td>
</tr>
<tr>
<td>text</td>
</tr>
</table>
I want to remove 2 tr elements at once something like this:
<script>
var tr = document.getElementById('first'),
table = document.getElementsByTagName('table')[0],
i=0;
do {
tr = table.tbody.removeChild(tr);
} while ((tr = tr.nextSibling(tr)) && i++<2);
</script>
But after first iteration table.removeChild(tr) returns null, so I can't get tr.nextSibling(tr).
Please help me.
You should temporary save a reference to the next row, as shwn below. Also, to select the tbody, you have to use tBodies[0].
var nextrow = document.getElementById('first'),
table = document.getElementsByTagName('table')[0],
i=0, tr;
while (nextrow && i++<2) {
tr = nextrow;
nextrow = tr.nextSibling;
table.tbodies[0].removeChild(tr);
}
An alternative, universal solution:
var nextrow = document.getElementById('first'),
i=0, tr;
while (nextrow && i++<2) {
tr = nextrow;
nextrow = tr.nextSibling;
tr.parentNode.removeChild(tr);
}
Maybe you should define the next tr to remove before removing the current tr.
this works as well:
var trs = document.getElementsByTagName("tr");
for(var i = 1; i < trs.length; i++){
trs[i].parentNode.removeChild(trs[i]);
i--;
}
Related
I have this table, and I can't seem to find out how to unselect marked field, if it's clicked again? So a double-click on id 2 would select->unselect.
function highlight_row() {
var table = document.getElementById('testresultsTable');
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function () {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
rowsNotSelected[row].style.backgroundColor = "";
rowsNotSelected[row].classList.remove('selected');
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
rowSelected.style.backgroundColor = "yellow";
rowSelected.className += " selected";
}
}
} //end of function
window.onload = highlight_row;
<table id="testresultsTable">
<thead>
<th>ID</th>
<th>Tests</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>TESTRUN1</td>
</tr>
<tr>
<td>2</td>
<td>TESTRUN2</td>
</tr>
<tr>
<td>3</td>
<td>TESTRUN3</td>
</tr>
</tbody>
</table>
I thought about making some kind of count on the rowID, so if it's clicked more than once after each other, then it would toggle between select/unselect?
You can solve it by doing something similar to this, this will first check the selected row for the selected class and remove it if it is found, otherwise, it'll add it to the row you clicked. After that is done, this function will loop through all other rows, check if they aren't the clicked row and remove the selected state accordingly.
So now once you click, your code will look for selected on the row you clicked, if it is found, it'll remove that class to reset the styling, if it isn't found, it'll add the selected class. After this, the code will check all rows to see if they're not the selected row and style them accordingly.
function highlight_row() {
var table = document.getElementById('testresultsTable');
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function() {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
if(row !== rowId) {
rowsNotSelected[row].style.backgroundColor = "";
rowsNotSelected[row].classList.remove('selected');
}
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
if (rowSelected.classList.contains('selected')) {
rowSelected.style.backgroundColor = "";
rowSelected.classList.remove('selected');
} else {
rowSelected.style.backgroundColor = "yellow";
rowSelected.classList.add("selected");
}
}
}
} //end of function
window.onload = highlight_row;
<table id="testresultsTable">
<thead>
<th>ID</th>
<th>Tests</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>TESTRUN1</td>
</tr>
<tr>
<td>2</td>
<td>TESTRUN2</td>
</tr>
<tr>
<td>3</td>
<td>TESTRUN3</td>
</tr>
</tbody>
</table>
Hope this helps!
function highlight_row() {
var table = document.getElementById('testresultsTable');
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function () {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
if(row!==rowId){
rowsNotSelected[row].style.backgroundColor = "white";
rowsNotSelected[row].classList.remove('selected');
}
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
if(rowSelected.classList.contains("selected")) {
rowSelected.style.backgroundColor = "";
rowSelected.classList.remove("selected");
}
else{
rowSelected.style.backgroundColor = "yellow";
rowSelected.classList.add("selected");
}
}
}
} //end of function
window.onload = highlight_row;
<table id="testresultsTable">
<thead>
<th>ID</th>
<th>Tests</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>TESTRUN1</td>
</tr>
<tr>
<td>2</td>
<td>TESTRUN2</td>
</tr>
<tr>
<td>3</td>
<td>TESTRUN3</td>
</tr>
</tbody>
</table>
I'd do it like this
var selected;
(function () {
var rows = document.querySelectorAll('#testresultsTable > tbody > tr');
rows.forEach(tr => tr.addEventListener('click', () => {
if(selected === tr){
selected.classList.remove('selected');
selected = undefined;
}
else {
if(selected) selected.classList.remove('selected');
selected = tr;
tr.classList.add('selected');
}
}));
})();
tbody > tr {
cursor: pointer;
user-select: none;
}
tr.selected {
background-color: yellow;
}
<table id="testresultsTable">
<thead><th>ID</th><th>Tests</th></thead>
<tbody>
<tr><td>1</td><td>TESTRUN1</td></tr>
<tr><td>2</td><td>TESTRUN2</td></tr>
<tr><td>3</td><td>TESTRUN3</td></tr>
</tbody>
</table>
I have an html table that I want to read from and create a new table underneath it from reading the first table. The first table looks like this:
ID | Value
100 | 3
200 | 2
400 | 7
100 | 4
and should output this
ID | Total
100 | 7
200 | 2
400 | 7
I'm having trouble creating the new rows after the first row and adding them based on ID, heres what I have so far
var id = document.getElementByID("total");
var td = document.createElement('td');
var eleName = document.getElementsByName('initValue');
var total = 0;
for (var i = 1; i < eleName.length; i++) {
total += parseInt(eleName[i].value);
}
td.textContent = total;
id.appendChild(td);
Right now its just adding all the values
The ID can only increase by 100 and can have more than just 100-400 and more entries. The inital table is made with php
original table html
<table>
<tr><th>ID</th><th>Value</th></tr>
<tr><td name="itin" id="itin">100</td><td id="initValue" name="initValue">3</td></tr>
<tr><td name="itin" id="itin">200</td><td id="initValue" name="initValue">2</td></tr>
<tr><td name="itin" id="itin">400</td><td id="initValue"name="initValue">7</td></tr>
<tr><td name="itin" id="itin">100</td><td id="initValue" name="initValue">4</td></tr>
</table>
As a few people have said in the comments an element's ID, <el id="something">, must be unique and there cannot be any duplicates of it on the page. If you want to "group" similar elements use a class.
For solving your problem, since the value of your ID is is a direct sibling we only need one selector to get the ID and Value:
const itin = document.querySelectorAll('[name="itin"]');
With this we can loop over every ID element, name="itin", and get the value with el.nextElementSibling.textContent. We're going to be keeping track of our IDs and Values in an object since javascript doesn't have key/value pair arrays: let values = {}.
We use .nextElementSibling to ignore white spaces and only get the next element.
We check if values already has a record of our ID with hasOwnProperty, if it does, we add the values together, if not we create a property in values with our ID and give it a value:
if (values.hasOwnProperty(inner)) {
values[inner] = values[inner] += parseInt(next);
} else {
values[inner] = parseInt(next);
}
Next we create a second loop to iterate over all properties in values and build our new table with that and the rest is pretty straight forward.
The two loops could likely be combined into one with a bit more logic to search for matching IDs.
const itin = document.querySelectorAll('[name="itin"]');
let values = {};
itin.forEach(item => {
const inner = item.textContent;
let next = null;
/* For direct sibling use this */
//const next = item.nextElementSibling.textContent;
/* For an unknown sibling use this */
for ( let a = 0; a < item.parentElement.children.length; a++ ) {
const n = item.parentElement.children[a];
if ( n.getAttribute('name') === 'initValue') {
next = n;
}
}
next = next.textContent;
/****/
if (values.hasOwnProperty(inner)) {
values[inner] = values[inner] += parseInt(next);
} else {
values[inner] = parseInt(next);
}
});
const table_two = document.querySelector('.table-two tbody');
for (let prop in values) {
const val = values[prop];
let tr = document.createElement('tr');
let td1 = document.createElement('td');
let td2 = document.createElement('td');
td1.innerHTML = prop;
td2.innerHTML = val;
tr.appendChild(td1);
tr.appendChild(td2);
table_two.appendChild(tr);
}
<table>
<tr>
<th>ID</th>
<th>Value</th>
</tr>
<tr>
<td name="itin">100</td>
<td name="initValue">3</td>
</tr>
<tr>
<td name="itin">200</td>
<td name="initValue">2</td>
</tr>
<tr>
<td name="itin">400</td>
<td name="initValue">7</td>
</tr>
<tr>
<td name="itin">100</td>
<td name="initValue">4</td>
</tr>
</table>
<table class="table-two">
<thead>
<tr>
<th>ID</th>
<th>Value</th>
</tr>
</thead>
<tbody></tbody>
</table>
An entirely javascript solution based on what you have provided is available on this jsfiddle
var tds = document.getElementsByName("itin");
var tdDict = {};
var keys = [];
for(var i=0;i<tds.length;i++){
var tdId = tds[i];
var tdVal = tds[i].nextSibling;
if(tdId.textContent in tdDict){
var curTotal = tdDict[tdId.textContent];
var newTotal = curTotal + parseInt(tdVal.textContent);
tdDict[tdId.textContent] = newTotal;
}
else{
tdDict[tdId.textContent] = parseInt(tdVal.textContent);
keys.push(tdId.textContent);
}
}
var totalDiv = document.getElementById("totals");
var totalTable = document.createElement("table");
totalDiv.append(totalTable);
var hrow = document.createElement("tr");
var idHeader = document.createElement("th");
idHeader.textContent = "ID";
var totalHeader = document.createElement("th");
totalHeader.textContent = "Total";
totalTable.append(hrow);
hrow.append(idHeader);
hrow.append(totalHeader);
for(var i=0;i<keys.length; i++){
var newRow = document.createElement("tr");
var idVal = keys[i];
var valVal = tdDict[idVal];
var idValTd = document.createElement("td");
idValTd.textContent = idVal;
var valValTd = document.createElement("td");
valValTd.textContent = valVal;
newRow.appendChild(idValTd);
newRow.appendChild(valValTd);
totalTable.appendChild(newRow);
}
<table>
<tr><th>ID</th><th>Value</th></tr>
<tr><td name="itin" id="itin">100</td><td id="initValue" name="initValue">3</td></tr>
<tr><td name="itin" id="itin">200</td><td id="initValue" name="initValue">2</td></tr>
<tr><td name="itin" id="itin">400</td><td id="initValue"name="initValue">7</td></tr>
<tr><td name="itin" id="itin">100</td><td id="initValue" name="initValue">4</td></tr>
</table>
<div id="totals">
</div>
I have a table where each row has its unique id. Say there are rows with id='id25' and id='id26'. I need to insert a new row after row with id='id25'. I am using Vanilla JS without jQuery.
I have tried this:
var refElement = document.getElementById('id'+id);
var newrow = document.createElement("tr");
if (refElement) {
refElement.insertBefore(newrow, refElement.nextSibling);
}
but it throws me an error saying
Failed to execute 'insertBefore' on 'Node'
The node before which the new node is to be inserted is not a child of this node.
I know how to insert rows into top or bottom of the table but now I have an id as a reference to a particular row.
Any suggestions would be welcome
You want to insert into the refElement's parent, not refElement itself:
refElement.parentNode.insertBefore(newrow, refElement.nextSibling);
// -------^^^^^^^^^^^
var id = 1;
var refElement = document.getElementById('id' + id);
var newrow = document.createElement("tr");
newrow.innerHTML = "<td>new row</td>";
if (refElement) {
refElement.parentNode.insertBefore(newrow, refElement.nextSibling);
}
<table>
<tbody>
<tr id="id1"><td>refElement</td></tr>
<tr><td>original next sibling</td></tr>
</tbody>
</table>
(And yes, for anyone wondering, it'll work even if the refElement is the last row in the table.)
Inserting five rows per comment:
var id = 1;
var refElement = document.getElementById('id' + id);
var n, newrow;
if (refElement) {
for (n = 0; n < 5; ++n) {
newrow = document.createElement("tr");
newrow.innerHTML = "<td>new row #" + n + "</td>";
refElement.parentNode.insertBefore(newrow, refElement.nextSibling);
}
}
<table>
<tbody>
<tr id="id1">
<td>refElement</td>
</tr>
<tr>
<td>original next sibling</td>
</tr>
</tbody>
</table>
Note the order in which those appeared. If you want them in 0 - 4 order instead:
var id = 1;
var refElement = document.getElementById('id' + id);
var n, newrow;
if (refElement) {
for (n = 0; n < 5; ++n) {
newrow = document.createElement("tr");
newrow.innerHTML = "<td>new row #" + n + "</td>";
refElement.parentNode.insertBefore(newrow, refElement.nextSibling);
refElement = refElement.nextSibling; // *** This is the change
}
}
<table>
<tbody>
<tr id="id1">
<td>refElement</td>
</tr>
<tr>
<td>original next sibling</td>
</tr>
</tbody>
</table>
function addRowAfter(rowId){
var refElement = document.getElementById('id'+id);
var newrow= document.createElement('tr');
refElement.parentNode.insertBefore(newrow, refElement.nextSibling );
return newRow;
}
Check this.
I am looking to create an array using jQuery from a table with a <thead> and a <tbody>
The result I am looking for is
[[20th Jan, 33], [21st Jan, 44], [22nd Jan, 5],[23rd Jan, 17]]
My Table is as follows
<table class="" id="bookedTable" border="1">
<thead>
<tr>
<th>Date</th>
<th>20th jan</th>
<th>21st jan</th>
<th>22nd jan</th>
<th>23rd Jan</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>33</td>
<td>44</td>
<td>5</td>
<td>17</td>
</tr>
</tbody>
My JS is as follows
$(function() {
var $table = $("#bookedTable"),
$headerCells = $table.find("thead th"),
$rowCells = $table.find("tbody tr td");
var headers = [],
rows = [];
$headerCells.each(function(k,v) {
headers[headers.length] = $(this).text();
});
$rowCells.each(function(k,v) {
rows[rows.length] = $(this).text();
});
console.log(headers);
console.log(rows);
});
I can only figure out how to console log the header and rows sepeartely and not combine them in 1 array per my desired result above. Looking for some help to resolve.
MY DEMO HERE
var combined = [];
for(var i = 1; i < $headerCells.length; i++) {
combined.push([$($headerCells[i]).text(), $($rowCells[i]).text()]);
}
See it here:
http://jsfiddle.net/kp7zK/2/
var arr = $.map($('#bookedTable th:not(:first)'), function(el,i) {
return [[$(el).text(), $('#bookedTable td:eq('+i+')').text()]];
});
FIDDLE
You don't have to separately pick the headers (this replaces the whole code) :
var $table = $("#bookedTable"), l = [];
$table.find('thead th').each(function(i){
l.push([$(this).text(), $('table tbody td').eq(i).text()])
});
l = l.slice(1);
Demonstration
var myArr = [];
$("table thead tr th").each(function(i){
if(i != 0){
var colValue = $("table tbody tr td").eq(i).text();
myArr.push([this.innerHTML, colValue]);
}
});
JS Fiddle: http://jsfiddle.net/FtK4b/1/
Try this
$(function() {
var rows = [];
$('tbody tr td').each(function(k,v) {
if(k>0)
rows.push([ $('thead th:eq('+k+')').text(),$(this).text()]);
});
alert(rows.toSource());
});
Here is the working Fiddle
I've a GridView with three rows like this
<tr>
<th>SlNo</th>
</tr>
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
I've the following code to traverse through the rows
var GridViewRow=GridView.getElementsByTagName('tr')
Here the row length is 3.
I travese through the GridViewRow using for loop .Here how will i get the tag name of the current element ie (th or td).
If the tagname is "TH" it should return and if it is "TD" it should take the value of TD.
How about this
var table = document.getElementById("mytab1");
for (var i = 0, cell; cell = table.cells[i]; i++) {
//iterate through cells
//cells would be accessed using the "cell" variable assigned in the for loop
}
you can also try out
var tbl = document.getElementById('yourTableId');
var rows = tbl.getElementsByTagName('tr');
for (var i = 0; i < rows.length; i++)
{
if(rows[i].getElementsByTagName('td').length > 0)
{
//code to execute
}
else
{
continue;
}
}
var GridViewRow = GridView.getElementsByTagName('tr');
$(GridViewRow).each(function() {
var $this = $(this), td = $this.find('td');
if (td.length === 1) {
console.log(td.text());
}
});
this works for <tr> in which you have exactly one <td> if you use jquery, otherwise in plain javascript try this:
var GridViewRow = GridView.getElementsByTagName('tr'),
len = GridViewRow.length,
td;
while (--len) {
td = GridViewRow[len].getElementsByTagName('td');
if (td.length === 1) {
console.log(td[0].innerHTML);
}
}
});
You can check the tag name with jQuery :
$(this).attr("tag");
Later edit:
For raw javascript, use tagName:
element.tagName