Adding an onclick event to a table row - javascript

I'm trying to add an onclick event to a table row through Javascript.
function addRowHandlers() {
var table = document.getElementById("tableId");
var rows = table.getElementsByTagName("tr");
for (i = 1; i < rows.length; i++) {
row = table.rows[i];
row.onclick = function(){
var cell = this.getElementsByTagName("td")[0];
var id = cell.innerHTML;
alert("id:" + id);
};
}
}
This works as expected in Firefox, but in Internet Explorer (IE8) I can't access the table cells. I believe that is somehow related to the fact that "this" in the onclick function is identified as "Window" instead of "Table" (or something like that).
If I could access the the current row I could perform a getElementById in the onclick function by I can't find a way to do that. Any suggestions?

Something like this.
function addRowHandlers() {
var table = document.getElementById("tableId");
var rows = table.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
var currentRow = table.rows[i];
var createClickHandler = function(row) {
return function() {
var cell = row.getElementsByTagName("td")[0];
var id = cell.innerHTML;
alert("id:" + id);
};
};
currentRow.onclick = createClickHandler(currentRow);
}
}
EDIT
Working demo.

Simple way is generating code as bellow:
<!DOCTYPE html>
<html>
<head>
<style>
table, td {
border:1px solid black;
}
</style>
</head>
<body>
<p>Click on each tr element to alert its index position in the table:</p>
<table>
<tr onclick="myFunction(this)">
<td>Click to show rowIndex</td>
</tr>
<tr onclick="myFunction(this)">
<td>Click to show rowIndex</td>
</tr>
<tr onclick="myFunction(this)">
<td>Click to show rowIndex</td>
</tr>
</table>
<script>
function myFunction(x) {
alert("Row index is: " + x.rowIndex);
}
</script>
</body>
</html>

I think for IE you will need to use the srcElement property of the Event object. if jQuery is an option for you, you may want to consider using it - as it abstracts most browser differences for you. Example jQuery:
$("#tableId tr").click(function() {
alert($(this).children("td").html());
});

Here is a compact and a bit cleaner version of the same pure Javascript (not a jQuery) solution as discussed above by #redsquare and #SolutionYogi (re: adding onclick event handlers to all HTML table rows) that works in all major Web Browsers, including the latest IE11:
function addRowHandlers() {
var rows = document.getElementById("tableId").rows;
for (i = 0; i < rows.length; i++) {
rows[i].onclick = function(){ return function(){
var id = this.cells[0].innerHTML;
alert("id:" + id);
};}(rows[i]);
}
}
window.onload = addRowHandlers();
Working DEMO
Note: in order to make it work in IE8 as well, instead of this pointer use the explicit identifier like function(myrow) as suggested by #redsquare.
Best regards,

Head stuck in jq for too long. This will work.
function addRowHandlers() {
var table = document.getElementById("tableId");
var rows = table.getElementsByTagName("tr");
for (i = 1; i < rows.length; i++) {
var row = table.rows[i];
row.onclick = function(myrow){
return function() {
var cell = myrow.getElementsByTagName("td")[0];
var id = cell.innerHTML;
alert("id:" + id);
};
}(row);
}
}

Here is how I do this. I create a table with a thead and tbody tags.
And then add a click event to the tbody element by id.
<script>
document.getElementById("mytbody").click = clickfunc;
function clickfunc(e) {
// to find what td element has the data you are looking for
var tdele = e.target.parentNode.children[x].innerHTML;
// to find the row
var trele = e.target.parentNode;
}
</script>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody id="mytbody">
<tr><td>Data Row</td><td>1</td></tr>
<tr><td>Data Row</td><td>2</td></tr>
<tr><td>Data Row</td><td>3</td></tr>
</tbody>
</table>

I try to figure out how to get a better result with pure JS and i get something this:
DEMO: https://jsfiddle.net/f5r3emjt/1/
const tbody = document.getElementById("tbody");
let rowSelected;
tbody.onclick = (e) => {
for (let i = 0; i < e.path.length; ++i) {
if (e.path[i].tagName == "TR") {
selectRow(e.path[i]);
break;
}
}
};
function selectRow(r) {
if (rowSelected !== undefined) rowSelected.style.backgroundColor = "white";
rowSelected = r;
rowSelected.style.backgroundColor = "dodgerblue";
}
And now you can use the variable rowSelected in other function like you want or call another function after set the style
I like more this implementacion and also compatible with any browser
tbody.onclick = (e) => {
// we need to get the tr element because we always select the td element
const tr = e.srcElement.parentNode;
tr == "TR" && selectRow( tr );
};

Try changing the this.getElementsByTagName("td")[0]) line to read row.getElementsByTagName("td")[0];. That should capture the row reference in a closure, and it should work as expected.
Edit: The above is wrong, since row is a global variable -- as others have said, allocate a new variable and then use THAT in the closure.

My table is in another iframe so i modified SolutionYogi answer to work with that:
<script type="text/javascript">
window.onload = addRowHandlers;
function addRowHandlers() {
var iframe = document.getElementById('myiframe');
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
var table = innerDoc.getElementById("mytable");
var rows = table.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
var currentRow = table.rows[i];
var createClickHandler =
function(row)
{
return function() {
var cell = row.getElementsByTagName("td")[0];
var id = cell.innerHTML;
alert("id:" + id);
};
}
currentRow.onclick = createClickHandler(currentRow);
}
}
</script>

I was trying to select a table row, so that it can be easily copied to the clipboard and then pasted in Excel. Below is a small adaptation of your solution.
References:
Where I took the window.prompt line from (Jarek Milewski):
The user is presented with the prompt box, where the text to be copied is already selected...
For selecting a complete table (Tim Down). Very interesting, but I was not able to adapt for a <tr> element.
<!DOCTYPE html>
<html>
<body>
<div>
<table id="tableId" border=1>
<tbody>
<tr><td>Item <b>A1</b></td><td>Item <b>B1</b></td></tr>
<tr><td>Item <b>A2</b></td><td>Item <b>B2</b></td></tr>
<tr><td>Item <b>A3</b></td><td>Item <b>B3</b></td></tr>
</tbody>
</table>
</div>
<script>
function addRowHandlers() {
var table = document.getElementById("tableId");
var rows = table.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
var currentRow = table.rows[i];
var createClickHandler =
function(row)
{
return function() {
var cell = row.getElementsByTagName("td")[0];
var id = cell.innerHTML;
var cell1 = row.getElementsByTagName("td")[1];
var id2 = cell1.innerHTML;
// alert(id + " - " + id2);
window.prompt("Copy to clipboard: Ctrl+C, Enter", "<table><tr><td>" + id + "</td><td>" + id2 + "</td></tr></table>")
};
};
currentRow.onclick = createClickHandler(currentRow);
}
}
window.onload = addRowHandlers();
</script>
</body>
</html>

While most answers are a copy of SolutionYogi's answer, they all miss an important check to see if 'cell' is not null which will return an error if clicking on the headers.
So, here is the answer with the check included:
function addRowHandlers() {
var table = document.getElementById("tableId");
var rows = table.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
var currentRow = table.rows[i];
var createClickHandler = function(row) {
return function() {
var cell = row.getElementsByTagName("td")[0];
// check if not null
if(!cell) return; // no errors!
var id = cell.innerHTML;
alert("id:" + id);
};
};
currentRow.onclick = createClickHandler(currentRow);
}
}

selectRowToInput();
function selectRowToInput(){
var table = document.getElementById("table");
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++)
{
var currentRow = table.rows[i];
currentRow.onclick = function() {
rows=this.rowIndex;
console.log(rows);
};
}
}

Related

How to get innerHTML of td in dynamically populated table in JavaScript

I created a table and populated values from an array, so I have 5x5 table, where each td will be filled with a word. The word come from array memo and all the code below works fine.
var myTableDiv = document.getElementById("results")
var table = document.createElement('TABLE')
var tableBody = document.createElement('TBODY')
table.border = '1'
table.appendChild(tableBody);
//TABLE ROWS
for (i = 0; i < this.memo.length; i++) {
var tr = document.createElement('TR');
for (j = 0; j < this.memo[i].length; j++) {
var td = document.createElement('TD');
td.onclick = function () {
check();
}
td.appendChild(document.createTextNode(this.memo[i][j]));
tr.appendChild(td)
}
tableBody.appendChild(tr);
}
myTableDiv.appendChild(table);
I have one question : I would like to click on the cell and get the word, which belongs to the cell.
For this purpose I tried onclick as I created td element
td.onclick = function () {
check();
}
The function check should print the innerHTML of the cell, which was clicked
function check() {
var a = td.innerHTML;
console.log(a);
}
But it gives me always wrong text - the last one in the array, which was populated.
How could I solve it?..
You always get the last td in the array because the last value that was set to td was of the last cell. You need to add the a parameter, say event, to onclick's callback function, and then your clicked element will be referenced in event.target. Then you would be able to get it's innerHTML.
Here's why it's always giving you the first element: after the for (j = 0; ... loop is finished, the variable td will hold the value of the last element in the list. Then, when check is called, it accesses that same td variable pointing to the last element.
To solve this, you can add an argument to the function to accept a specific element and log that.
td.onclick = function () {
check(td);
};
// later...
function check(element) {
var html = element.innerHTML;
console.log(html);
}
I would pass the innerHTML in the click itself - please see working example below, with some mock data for memo.
var myTableDiv = document.getElementById("results")
var table = document.createElement('TABLE')
var tableBody = document.createElement('TBODY')
var memo = [
['joe', 'tom', 'pete'],
['sara','lily', 'julia'],
['cody','timmy', 'john']
]
table.border = '1'
table.appendChild(tableBody);
//TABLE ROWS
for (i = 0; i < this.memo.length; i++) {
var tr = document.createElement('TR');
for (j = 0; j < this.memo[i].length; j++) {
var td = document.createElement('TD');
td.onclick = function () {
check(this.innerHTML);
}
td.appendChild(document.createTextNode(this.memo[i][j]));
tr.appendChild(td)
}
tableBody.appendChild(tr);
}
myTableDiv.appendChild(table);
function check(a) {
console.log(a);
}
<div id="results">
</div>
you can try..
td.onclick = function () {
check();
}
to
td.onclick = function (evt) {
var html = evt.target.innerHTML;
console.log(html);
check(html); //to do something..
}

How to insert new rows in some position in table

I have page with table.
In tbody I show data via angularjs. In thead I have same row as in tbody, but its empty, and when I filled input field and click somewhere (focus lost), one row adds to my table (thead). And I need to make some flag on filled row, as like - rowAdded = true, because without that I clicking on input of one row and rows adds. And one more problem is that rows adds to the end of table.
it's all works on this script:
var tbody = $('.table-timesheet thead');
tbody.on('blur', ':text', function () {
var tr = $(this).closest('tr'),
notEmpty = $(':text', tr).filter(function () {
return $.trim($(this).val()) != '';
}).length;
if (notEmpty) {
$('.note-input').css('width', '88%').css('float', 'left');
$('.timesheet-delete-button').css('display', 'block');
//tr.clone(true).appendTo(tbody).find(':text').val('');
insRow();
}
});
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
document.getElementById('table-body').deleteRow(i);
}
function insRow() {
var table = document.getElementById('table-body');
var newRow = table.rows[1].cloneNode(true);
var len = table.rows.length;
newRow.cells[0].innerHTML = len;
var inp1 = newRow.cells[1].getElementsByTagName('input')[0];
inp1.id += len;
inp1.value = '';
var inp2 = newRow.cells[2].getElementsByTagName('input')[0];
inp2.id += len;
inp2.value = '';
table.appendChild(newRow);
}
There is my example in plunker:
http://plnkr.co/edit/rcnwv0Ru8Hmy7Jrf9b1C?p=preview
Is this what you are looking for
function insRow(ind){
var table = document.getElementById('table-body');
var newRow = table.rows[1].cloneNode(true);
var len = table.rows.length;
newRow.cells[0].innerHTML = ind!==undefined ? ind : len;
if(ind!==undefined)
$(table).find('tr:eq('+ind+')').before(newRow);
else table.appendChild(newRow);
}
insRow(2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table-body">
<tbody>
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
</tbody>
</table>

inserting row in the middle of a html table using javascript

I have a table which contains two rows.
<tr id="row1"><td>first row</td></tr>
<tr id="row2"><td>second row</td></tr>
I need to insert few rows between row1 and row2 using java script.
I can achieve this by using java script create element. But I wish to add new rows using string html content.
for example :
"<tr><td>This row is placed between first and second</td></tr>".insertAfter(first row Id);
is there way like this to add rows in between?
var newRow = document.createElement("tr");
newRow.innerHTML = "<td>This row is placed... etc.</td>";
var row2 = document.getElementById("row2");
row2.parentNode.insertBefore(newRow, row2);
Read up on it here: https://developer.mozilla.org/en-US/docs/Web/API/Node.insertBefore
Use jQuery. There is a Function insertAfter();
$("#row1").insertAfter("your html");
http://jquery.com/
var button = document.getElementById('insert');
var table = document.getElementById('table');
button.onclick = function() {
var position=Math.round(table.rows.length / 2);
var row = table.insertRow(position);
row.innerHTML = '<td>This row is placed between '+position+' and '+(parseInt(position)+1)+'</td>';
}
**after that if u can use like that u can increment ur row id also:**
var rowId = '#' + tableId + ' tr';
var k = 0;
$(rowId).each(function () {
var ObjInput = $(this).find('input[type=text],input[type=radio],input[type=checkbox],textarea,select,input[type=img],input[type=hidden],input[type=button],img');
if (ObjInput != null) {
for (var j = 0; j < ObjInput.length; j++) {
var inputId = $(ObjInput[j]).attr('id');
inputId = inputId.replace(/_[0-9]{1,2}/g, '_' + k);
$(ObjInput[j]).attr('id', inputId);
$(ObjInput[j]).attr('name', inputId);
}
k++;
}
});

Delete the row you click on (Javascript dynamic table)

I want to delete a row from a table, I am using Javascript.
I am dynamically creating table rows and in the last cell I have delete button so how to make it delete the row?
var newData4 = document.createElement('td');
var delButton = document.createElement('input');
delButton.setAttribute('type', 'button');
delButton.setAttribute('name', 'deleteButton');
delButton.setAttribute('value', 'Delete');
newData4.appendChild(delButton);
newRow.appendChild(newData4);
this is the function for creating my table rows
function addItem()
{
document.getElementById('add').onclick=function()
{
var myTable = document.getElementById('tbody');
var newRow = document.createElement('tr');
//var element1 = document.createElement("input");
//element1.type = "checkbox";
//newRow.appendChild(element1);
var newData1 = document.createElement('td');
newData1.innerHTML = document.getElementById('desc').value;
var newData2 = document.createElement('td');
newData2.innerHTML = document.getElementById('taskPriority').value;
var newData3 = document.createElement('td');
newData3.innerHTML = document.getElementById('taskDue').value;
myTable.appendChild(newRow);
newRow.appendChild(newData1);
newRow.appendChild(newData2);
newRow.appendChild(newData3);
var newData4 = document.createElement('td');
var delButton = document.createElement('input');
delButton.setAttribute('type', 'button');
delButton.setAttribute('name', 'deleteButton');
delButton.setAttribute('value', 'Delete');
newData4.appendChild(delButton);
newRow.appendChild(newData4);
}
}
function SomeDeleteRowFunction(btndel) {
if (typeof(btndel) == "object") {
$(btndel).closest("tr").remove();
} else {
return false;
}
}
try this code here is fiddle
alternatively try
//delete the table row
$(document).on('click', '#del', function(){
$(this).parents('tr').remove();
});
}); //del is the id of the delete block
one pure javascript approach
function deleteRowUI(btndel) {
var table=document.getElementById('filterTableBody');
if (typeof(btndel) == "object") {
p=btndel.parentNode.parentNode;
p.parentNode.removeChild(p);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (var i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
} else {
return false;
}
}
if you want to temporary hidden it you can do:
this.parentNode.style.display='none';
in mind that the exclusion button is in a td.
But if you want to really delete it from the html and the database:
you need to make the same as above and a extra call to a function of php/plsqlwathever to delete from de db, i recommend using ajax to call it.
http://www.w3schools.com/ajax/default.asp
uses jQuery remove method to do it.
By the id attribute :
$("#id here").remove();
By the class attribute :
$(".class name here").remove();
I hope I've helped a little...

jQuery: How to count table columns?

Using jQuery, how would you figure out how many columns are in a table?
<script>
alert($('table').columnCount());
</script>
<table>
<tr>
<td>spans one column</td>
<td colspan="2">spans two columns</td>
<td colspan="3">spans three columns</td>
<tr>
</table>
The total number of columns in this example is 6. How could I determine this using jQuery?
Here you go:
jsFiddle
$(function() {
var colCount = 0;
$('tr:nth-child(1) td').each(function () {
if ($(this).attr('colspan')) {
colCount += +$(this).attr('colspan');
} else {
colCount++;
}
});
});
$("table").find("tr:first td").length;
I edited as I didn't realize you were counting the colspan's.
If you want to include using colspan try a loop through the td's in the first row:
var cols = $("table").find("tr:first td");
var count = 0;
for(var i = 0; i < cols.length; i++)
{
var colspan = cols.eq(i).attr("colspan");
if( colspan && colspan > 1)
{
count += colspan;
}else{
count++;
}
}
This is the cleanest in my opinion. It handles tables within tables. And is short and simple:
$("table > tbody > tr:first > td").length
In POJS (Plain Old JavaScript):
HTML:
<table id="foo">
<thead></thead>
<tbody>
<tr>
<td>1</td>
<td colspan="2">2</td>
<td colspan="3">3</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
JS:
var foo = document.getElementById("foo"), i = 0, j = 0, row, cell, numCols = 0;
//loop through HTMLTableElement.rows (includes thead, tbody, tfoot)
for(i;i<foo.rows.length;i++)
{
row = foo.rows[i];
//loop through HTMLTableRowElement.cells
for(j = 0;j<row.cells.length;j++)
{
cell = row.cells[j];
numCols += cell.colSpan;
cell = null;
}
row = null;
}
alert(numCols) //6;
HTMLTableElement.rows will collect rows from every HTMLTableSectionElement (THead, TBody, and TFoot). Each section also has its own rows HTMLCollection, so you can filter them if need be.
To be robust..I'd do something like this
alert(numCol("table") + " is the max number of cols");
function numCol(table) {
var maxColNum = 0;
var i=0;
var trs = $(table).find("tr");
for ( i=0; i<trs.length; i++ ) {
maxColNum = Math.max(maxColNum, getColForTr(trs[i]));
}
return maxColNum;
}
function getColForTr(tr) {
var tds = $(tr).find("td");
var numCols = 0;
var i=0;
for ( i=0; i<tds.length; i++ ) {
var span = $(tds[i]).attr("colspan");
if ( span )
numCols += parseInt(span);
else {
numCols++;
}
}
return numCols;
}
Just in case we have some funkiness going on between different rows.
http://jsfiddle.net/WvN9u/
Just paying attention to colspan attr
Pass in a table with something like $('foo#table') or $('table:first')
function getColumnCount(e) { //Expects jQuery table object
var c= 0;
e.find('tbody tr:first td').map(function(i,o) { c += ( $(o).attr('colspan') === undefined ? 1 : parseInt($(o).attr('colspan')) ) } );
return c;
}
To circumvent the td/th issue (and also fix a potential issue where attr('colspan') was giving me strings) I went with this:
var colspan = 0;
$('#table').find('tr:first').children().each(function(){
var cs = $(this).attr('colspan');
if(cs > 0){ colspan += Number(cs); }
else{ colspan++; }
});
/**
* Get number of columns in table.
* #param {string} table jQuery selector
* #param {boolean} [malformed=false] whether to inspect each row of malformed table;
* may take some time for large tables
* #returns {?number} number of columns in table, null if table not found.
*/
function getTableColumnsCount(table, malformed) {
malformed = malformed || false;
var $table = $(table);
if (!$table.length) {
return null;
}
var rows = $table.children('thead, tfoot, tbody').children('tr');
if (!malformed) {
// for correct tables one row is enough
rows = rows.first();
}
var maxCount = 0;
rows.each(function () {
var currentCount = 0;
$(this).children('th, td').each(function () {
currentCount += this.colSpan;
});
maxCount = Math.max(maxCount, currentCount);
});
return maxCount;
}
See in action https://jsfiddle.net/kqv7hdg5.
Takes colspan into account.
Works for nested tables.
Works for <thead>, <tfoot>, <tbody>.
Works for mix of <th> and <td>.
Works for malformed tables.
Slightly modified version for those who would like to pass jQuery object instead of selector https://jsfiddle.net/5jL5kqp5.
You have to set an ID to the header row:
<table>
<tr id="headerRow">
<td>spans one column</td>
<td colspan="2">spans two columns</td>
<td colspan="3">spans three columns</td>
</tr>
</table>
And then you can use the following function:
function getColumnCount(headerRowId) {
var columnCount = 0;
$('#' + headerRowId + ' > td').each(function() {
var colspanValue = $(this).attr('colspan');
if (colspanValue == undefined) {
columnCount++;
} else {
columnCount = columnCount + parseInt(colspanValue);
}
});
return columnCount;
}
I simplified answer of Craig M.
And modified to apply to both td and th tag.
function GetColumnCount($Table)
{
var ColCount = 0;
$Table.find("tr").eq(0).find("th,td").each(function ()
{
ColCount += $(this).attr("colspan") ? parseInt($(this).attr("colspan")) : 1;
});
return ColCount;
}
var foo = document.getElementById("price-test-table")
foo.tBodies["0"].firstElementChild.children.length
Give your table an id name
Assume your rows all have the same amount of columns and you have a table body
Use above code, which I think is the simplest on here, similar to first answer
but provides a little more detail
With jQuery and reduce it could look like this:
$.fn.tableCellCount = function() {
return $(this).find('tr:first td, tr:first th').get().reduce(function(a,b) {
return a + ($(b).attr('colspan') ? parseInt($(b).attr('colspan')) : 1);
},0)
}
$('table').tableCellCount();
Or even simpler:
$.fn.tableCellCount = function() {
return $(this).find('tr:first td, tr:first th').get().reduce(function(a,b) {
return a + (b.colSpan ? parseInt(b.colSpan) : 1);
},0)
}
$('table').tableCellCount();
This is the simple solution I have done:
In case you are using TR change TH for TR.
Using JQUERY:
<script>
$(document).ready(function() {
var number = $("table > tbody > tr:first > th").length;
for(var i=0; i <= number; i++){
$('th:nth-child('+ i +')').hide();
}
});
</script>
One Line:
$('.table-responsive tr th').children().length;
function(){
num_columns = 0;
$("table td]").each(function(){
num_columns = num_columns + ($(this).attr('colspan') == undefined ? 1 : $(this).attr('colspan'));
});
return num_columns;
}

Categories

Resources