35

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?

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120

12 Answers12

49

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.

SU3
  • 4,323
  • 2
  • 29
  • 55
SolutionYogi
  • 29,539
  • 11
  • 68
  • 77
  • Are you sure? It does work. Check the working demo link in my updated answer. Also, in your code, you started index with 1 instead of 0. You will not attach handler to the first row. – SolutionYogi Jul 30 '09 at 17:22
  • It works but when I saw your solution it was a bit different than it is now... =P I'm really thankful, been banging my head all afternoon! –  Jul 30 '09 at 17:27
  • Yes, I realized it right after I posted my answer (just like redsquare did) and later corrected it. – SolutionYogi Jul 30 '09 at 17:29
  • Why is table.rows[i] required? I tried 'var currentRow = rows[i]' and it worked. – vaichidrewar May 19 '13 at 04:23
  • Been looking for this thanks.. EDIT: I get an error `WHte.js:3 Uncaught TypeError: Cannot read property 'getElementsByTagName' of null` . I assume that is because I load the rows in dynamically? Therefore no "TR". How do I get around that??? – CromeX Sep 12 '16 at 12:52
  • Great found it... call it post update... Great piece of code!! – CromeX Sep 12 '16 at 12:59
7

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());
});
Nick Riggs
  • 1,247
  • 6
  • 7
6

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>
Zolfaghari
  • 1,065
  • 1
  • 14
  • 13
3

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,

Alexander Bell
  • 7,556
  • 2
  • 22
  • 37
1

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);
    }
}
redsquare
  • 75,782
  • 18
  • 147
  • 156
  • Would this work? I posted the same example but I think the 'row' inside the onlcick will always refer to the last row. Isn't it? [JavaScript has only function scoping, no block scoping.] – SolutionYogi Jul 30 '09 at 17:08
  • I know, jQuery makes all these things so easy, when you are left without jQuery, you do all the silly mistakes! :) – SolutionYogi Jul 30 '09 at 17:20
  • indeed it does! give me an each anyday – redsquare Jul 30 '09 at 17:21
1

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>
0

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.

Luke Rinard
  • 313
  • 1
  • 3
  • 7
0

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>
0

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:

<!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> 
Community
  • 1
  • 1
robertocm
  • 104
  • 5
0

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);
  }
}
0
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);  
    };
}

}
0

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

Swiler
  • 27
  • 6