Assuming I have the following table:
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td><input type="checkbox"/> A2</td>
<td>A3</td>
</tr>
<tr>
<td>B1</td>
<td><input type="checkbox"/> B2</td>
<td>B3</td>
</tr>
<tr>
<td>C1</td>
<td><input type="checkbox"/> C2</td>
<td>C3</td>
</tr>
</tbody>
</table>
I want to generate JSON from the table only for the rows whose checkbox is checked. What do I put in for "Insert Check Here"?
var myRows = [];
var $headers = $("th");
var $rows = $("tbody tr").each(function(index) {
$cells = $(this).find("td");
myRows[index] = {};
$cells.each(function(cellIndex) {
// Insert Check Here
myRows[index][$($headers[cellIndex]).html()] = $(this).html();
});
});
var myObj = {};
myObj.myrows = myRows;
alert(JSON.stringify(myObj));
I've added an If statement to test if the TD contains a checkbox which is checked or not, see the comment in the code
// Loop through grabbing everything
var myRows = [];
var $headers = $("th");
var $rows = $("tbody tr").each(function(index) {
$cells = $(this).find("td");
myRows[index] = {};
$cells.each(function(cellIndex) {
if($(this).find('checkbox').is(':checked')) //Find the checkbox within the TD and test if it's checked or not
{
myRows[index][$($headers[cellIndex]).html()] = $(this).html();
}
});
});
// Let's put this in the object like you want and convert to JSON (Note: jQuery will also do this for you on the Ajax request)
var myObj = {};
myObj.myrows = myRows;
alert(JSON.stringify(myObj));
Try with:
var selectedRowsHTML = "";
$('table input:checked').each(function() {
selectedRowsHTML += $(this).closest('tr').html();
});
console.log("This is the HTML for selected rows: "+ selectedRowsHTML);
With ":checked" selector you get only inputs that are checked inside your table. Iterate over them, finding the parent row with "closest('tr')". And that's all, you get the HTML for every row (or whatever you want to do with them).
how about thus
$("table input:checked") //filter based on your requirement
.each(function()
{
var td=$(this).parent(); //gets the `td`, do the necessary
});
You can use the checkbox:checked selector and closest to find the nearest element of a specific type.
var selectedRows = [];
$('table input:checkbox:checked').each(function() {
selectedRows.push($(this).closest('tr'))
});
selectedRows contains an array of the selected table rows
Related
I'm trying to use the insertcell method to add a column to my table but either I'm getting the syntax wrong or it isn't working. I wondered if anyone could explain where I am going wrong?
The table body in the html is populated dynamically with some other JavaScript but I don't think this is the problem as I've tested grabbing some content from that table with an alert box and it works (commented out below):
<!DOCTYPE html>
<script type="text/javascript" src="fullstationxyparser.js">
</script>
<html>
<body>
<table border=1>
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
</thead>
<tbody id="stationlist">
</tbody>
</table>
</body>
</html>
function addStationNames() {
var myTable = document.getElementById("stationlist");
var stationListRows = myTable.getElementsByTagName('tr');
for (var i = 1; i < stationListRows.length; i++) {
var cell = stationListRows[i].getElementsByTagName('td');
var stationName = cell[0].innerHTML; //get station id from element Name column
var currentRow = stationListRows[i];
var newCol = currentRow.insertcell(-1);
newCol.innerHTML = stationName;
//alert(stationName);
}
}
In Firefox developer tools, I get TypeError: "currentRow.insertcell is not a function". Perhaps I can't use the insertcell method on a row collection?
In general you can call the insertRow() method on a Table DOM element, followed by calls to the insertCell() method as shown below to dynamically add <td> tags to your table with JavaScript.
Be careful to call insertCell() (with capital C) rather than insertcell() as you are currently doing:
const table = document.querySelector('table');
/* Insert new row */
const row = table.insertRow();
/* Insert cells (td) for row */
const td0 = row.insertCell(0);
const td1 = row.insertCell(1);
const td2 = row.insertCell(2);
const td3 = row.insertCell(3);
/* Populate cells with data */
td0.innerText = 'Foo';
td1.innerText = '3';
td2.innerText = '6';
td3.innerText = 'success';
<table border="1">
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
Specific to your code, some other changes to consider might be as listed in this code snippet:
function addStationNames() {
/* Condense table row access into single query */
const stationRows = document.querySelectorAll("#stationlist tr");
stationRows.forEach((stationRow, i) => {
/* Skip first row */
if(i === 0) { return; }
/* Get station name from text of first cell */
const stationName = stationRow.querySelector('td:first-child').innerText;
/* Insert last cell on row and assign station name */
stationRow.insertCell(-1).innerText = stationName;
});
/*
Old code:
for (let i = 1; i < stationListRows.length; i++) {
var cell = stationListRows[i].getElementsByTagName('td');
var stationName = cell[0].innerHTML;
var currentRow = stationListRows[i];
var newCol = currentRow.insertcell(-1);
newCol.innerHTML = stationName;
}
*/
}
addStationNames();
<!-- set table id to stationlist -->
<table border="1" id="stationlist">
<thead>
<tr>
<td>Element Name</td>
<td>x</td>
<td>y</td>
<td>testCol</td>
</tr>
<tr>
<td>90's pop</td>
<td>232</td>
<td>543</td>
</tr>
</thead>
<tbody>
<!-- Remove id from tbody -->
</tbody>
</table>
An alternative to the answer above (which is totally fine) is this method, which is also a more general method of creating any html element:
const table = document.getElementById('one');
const newRow = document.createElement("tr");
let newCell = document.createElement("td");
newCell.textContent = "first cell";
let newCell2 = document.createElement("td");
newCell2.textContent = "second cell";
newRow.appendChild(newCell);
newRow.appendChild(newCell2);
table.appendChild(newRow);
https://jsfiddle.net/zgaosdbv/
I have a table element defined below as $table. I am trying to run a function on every cell a specific column that is defined by a specific table heading - qc_statusTh. I have found the index of that table heading (qc_statusColumnIndex) and have been able to grab the next table cell in that column - qc_statusCell.
However, I am not able to loop through the table cells and run a function on each table cell in that column.
Here is the JavaScript code I have so far:
$(document).ready(function() {
var $table = $("table.tables.list");
if ($table.length > 0) {
var qc_statusTh = $("th.headersub:contains('qc_status')");
var qc_statusColumnIndex = $(qc_statusTh).index();
var qc_statusCell = $($table).find("td").eq(qc_statusColumnIndex);
// this does not work. this only replaces the first cell
// in the row after qc_statusTh with "TESTING"
$(qc_statusCell).each(function() {
$(this).replaceWith("TESTING");
});
}
});
How can I edit this code to loop through each cell in the table that has an equal index to qc_statusColumnIndex?
If you think about it, you really want to iterate (using each) over the rows of the table, not the cells. If you do that, you can then grab the nth td element from each row and apply your transformation.
$(document).ready(function() {
var $table = $("table.tables.list");
if ($table.length > 0) {
var qc_statusTh = $("th.headersub:contains('qc_status')");
var qc_statusColumnIndex = $(qc_statusTh).index();
var qc_rows = $($table).find('tr');
$(qc_rows).each(function() {
$(this).find('td').eq(qc_statusColumnIndex).replaceWith("TESTING");
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="tables list">
<thead>
<th class="headersub">qc_example</th>
<th class="headersub">qc_status</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Ok</td>
</tr>
<tr>
<td>2</td>
<td>Ok</td>
</tr>
<tr>
<td>3</td>
<td>Error</td>
</tr>
</tbody>
</table>
I have an HTML table and I want to iterate through its rows and create a collection or lets say an "array of objects".
For example:
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
</table>
I want to create a collection as below:
var trArray = [];
$('#tbPermission tr').each(function () {
var tdArray = [];
$(this).find('td').each(function () {
// I want to create the array of objects here …
tdArray.push();
});
// Final array
trArray.push(tdArray);
});
The arrays may be like below:
tdArray : {'UserID' : '1', 'UserName' : 'Test1'};
and:
trArray : [
{'UserID' : '1', 'UserName' : 'Test1'},
{'UserID' : '2', 'UserName' : 'Test2'}
]
Try this code
var trArray = [];
$('#tbPermission tr').each(function () {
var tr =$(this).text(); //get current tr's text
var tdArray = [];
$(this).find('td').each(function () {
var td = $(this).text(); //get current td's text
var items = {}; //create an empty object
items[tr] = td; // add elements to object
tdArray.push(items); //push the object to array
});
});
Here, I just created an empty object, filled object with references of tr and td, the added that object to the final array.
adding a working jsfiddle
This solution relies on adding thead and tbody elements which is a good idea anyways since it indicates to the browser that the table actually is a "data" table and not presentational.
jQuery has a .map() function. map is a basic function where you take an array and then replace the values with a the return value of a callback function - which results in a new array.
$([1,4,9]).map(function(){ return Math.sqrt(this) });
// [1, 2, 3]
.toArray converts the array like jQuery object we get into a "true array".
jQuery(function(){
var $table = $("#tbPermission");
var headers = $table.find('thead th').map(function(){
return $(this).text().replace(' ', '');
});
var rows = $table.find('tbody tr').map(function(){
var result = {};
var values = $(this).find('>td').map(function(){
return $(this).text();
});
// use the headers for keys and td values for values
for (var i = 0; i < headers.length; i++) {
result[headers[i]] = values[i];
}
// If you are using Underscore/Lodash you could replace this with
// return _.object(headers, values);
return result;
}).toArray();
// just for demo purposes
$('#test').text(JSON.stringify(rows));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tbPermission">
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
</tbody>
</table>
<textarea id="test"></textarea>
If you for whatever reason cannot change the HTML you could use the index of the rows to differentiate between headers and rows of data:
var headers = $table.find('tr:eq(0) th').map(function(){
return $(this).text().replace(' ', '');
});
var rows = $table.find('tr:gt(0)').map(function(){
// ...
});
I would suggest changing your html slightly.
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td class="userid">1</td>
<td class="username">Test1</td>
</tr>
</table>
Then in your javascript when you want to get all the elements as an array you could do.
var userIdArray = $('#tbPermission .userid').map(function(userid){ return $(userid).html(); }).toArray();
This will find all elements with a class userid on the table, collect just the values, and .toArray() that result to get a basic javascript array. You can then take that and manipulate it into whatever json structure you want, or you could possibly create your json object inside that map function.
Check the console, you will get an array with the desired objects
var arr = [];
$('#tbPermission tr:not(.header)').each(function() {
var that = $(this);
var id = that.find('td').eq(0).text();
var name = that.find('td').eq(1).text();
var obj = { 'userId': id , 'userName': name };
arr.push(obj);
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="tbPermission">
<tr class="header">
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
<tr>
<td>2</td>
<td>Test2</td>
</tr>
</table>
It's a bit tricky based on the given structure. You may have to modify the HTML a bit to map cells to headers, like below.
var myArray = [];
$("#tbPermission").find("td").each(function() {
var $this = $(this), obj = {};
obj[$this.data("column")] = $this.text();
myArray.push(obj);
});
alert ( JSON.stringify(myArray) );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td data-column="User ID">1</td>
<td data-column="User Name">Test1</td>
</tr>
</table>
Please give in some time to learn about Array.push() and Objects in Javascript. Hope that helps.
I am trying to filter the rows of a table to display the results of entered text in the search bar. The code below does the job but for some reason filters the column headings as well.
$('#search').keyup(function () {
var data = this.value.split(" ");
var rows = $(".Info").find("tr").hide();
if(this.value ==""){
rows.show();
return;
}
rows.hide();
rows.filter(function(i,v){
var t = $(this);
for (var d = 0; d < data.length; d++) {
if (t.is(":Contains('" + data[d] + "')")) {
return true;
}
}
return false;
}).show();
});
HTML
<input type = "search" name = "search" id = "search">
<table style ="width:95%" class = "Info">
<tr>
<th>Select </th>
<th>Name</th>
<th>Number</th>
<th>Date</th>
</tr>
</table>
The user adds rows which is why i haven't written any HTML for it.
Any help would be appreciated. Thanks in advance
http://jsfiddle.net/szjhngwm/
It looks like you need to filter using tbody
<table style ="width:95%" class = "Info">
<thead>
<tr>
<th>Select </th>
<th>Name</th>
<th>Number</th>
<th>Date</th>
</tr>
<thead>
<tbody>
</tbody>
</table>
var rows = $(".Info tbody tr").hide();
Another way to do this would be to use jQuery's :gt() selector.
The only thing that would change is this line:
var rows = $(".Info").find("tr:gt(0)").hide();
Notice the addition of :gt(0) to your tr.
I have a table that is a history of a mysql record.
I want to add a button that will highlight the changes.
<table>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
In this example the 600 would be highlighted as it was 300 and is now 600.
UPDATE: Thanks, I should have said there would be more than 2 rows. could be upto 20 rows
This jsFiddle shows an example that will iterate over a table of any size and highlight the cells that have changed from the previous row.
$(function() {
var $rows = $("tr");
for (oldIndex = 0; oldIndex < $rows.length-1; oldIndex++) {
var newIndex = oldIndex + 1;
var $oldCols = $("td", $rows[oldIndex]);
var $newCols = $("td", $rows[newIndex]);
for (col = 0; col < $oldCols.length; col++) {
var $newCol = $($newCols[col]);
if ($($oldCols[col]).html() != $newCol.html()) {
$newCol.addClass("highlight");
}
}
}
});
Your solution should go along these lines. Assuming set1 and set2 are id's of two trs here is a sample code (not tested).
var s1 = $('tr#set1 td');
var s2 = $('tr#set2 td');
var l = $('tr#set1 td').length;
for(var i =0; i<l i++){
if(s1.eq(i).text() != s2.eq(i)){
$(s2.eq(i)).highlight();
}
}
$('table tr.new td').each(function(i){
//First TR td, Previous Rows
td = $(this);
check = $('table tr.prev td:eq('+i+')');
if(td[0].innerText != check[0].innerText)
{
check.addClass('Changed');
}
})
This should do it but you need to add 2 classes:
<table>
<tr class="new">
<td>150</td>
<td>200</td>
<td>300</td>
</tr>
<tr class="prev">
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
Demo: http://jsfiddle.net/hjXZd/1/
Hope this helps.
I advise you to do an attr for each TD and place the mysql id in there so that you will only compare the rows that are the same in the DB, otherwise if your first list has more items then the second list the results will be corrupt.
Assuming your table has the id results, here is a solution:
var topRow = $('table#results tr:eq(0)');
var bottomRow = $('table#results tr:eq(1)');
topRow.find('td').each(function(index,item){
var shadow = bottomRow.find('td:eq('+index+')');
if($(item).contents().text()!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
Update: this solution compares the top row with all following ones:
$('table#results tr:eq(0) td').each(function(index,item){
var orig = $(item).contents().text();
$('table#results tr:gt(0)').find('td:eq('+index+')').each(function(index2,item2){
var shadow = $(item2);
if(orig!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
});
Using Jquery .live you can handle multiple elements.
See here
http://api.jquery.com/live/
You have to give ids for the changed values.. which can be inside divs.
Hope td also may work
On button click using this .live you can chnage style of div
like highlighting.
Use addClass function os jquery itslef or you can add css using jquery add