[javascript] How to tell which row number is clicked in a table?

I have a table like the following:

_x000D_
_x000D_
<table>_x000D_
   <tr>_x000D_
      <td>1</td><td>1</td><td>1</td>_x000D_
   </tr>_x000D_
   <tr>_x000D_
      <td>2</td><td>2</td><td>2</td>_x000D_
   </tr>_x000D_
   <tr>_x000D_
      <td>3</td><td>3</td><td>3</td>_x000D_
   </tr>_x000D_
</table>
_x000D_
_x000D_
_x000D_

When a user clicks on the table, how can I get the index of this row (tr element)?

For example, when I click on the first tr (with 1s in the above table), it should pick it up and return 1.

This question is related to javascript jquery html html-table dom-events

The answer is


You can use object.rowIndex property which has an index starting at 0.

$("table tr").click(function(){
    alert (this.rowIndex);
});

See a working demo


In some cases we could have a couple of tables, and then we need to detect click just for particular table. My solution is this:

<table id="elitable" border="1" cellspacing="0" width="100%">
  <tr>
 <td>100</td><td>AAA</td><td>aaa</td>
  </tr>
  <tr>
<td>200</td><td>BBB</td><td>bbb</td>
   </tr>
   <tr>
<td>300</td><td>CCC</td><td>ccc</td>
  </tr>
</table>


    <script>
    $(function(){
        $("#elitable tr").click(function(){
        alert (this.rowIndex);
        });
    });
    </script>

DEMO


A better approach would be to delegate the event, which means catching it as it bubbles to the parent node.

delegation - overview

This solution is both more robust and efficient.

It allows the event to be handled even if more rows are dynamically added to the table later, and also results in attaching a single event handler to the parent node (table element), instead of one for each child node (tr element).

Assuming that the OP's example is a simplified one, the table's structure can be more complex, for example:

<table id="indexedTable">
    ...
    <tr>
        <td><p>1</p></td>
        <td>2</td>
        <td><p>3</p></td>
    </tr>
</table>

Therefore, a simplistic approach such as getting e.target.parentElement will not work, as clicking the internal <p> and clicking the center <td> will produce different results.

Using delegation normalizes the event handling, only assuming that there are no nested tables.

implementation

Both of the following snippets are equivalent:

$("#indexedTable").delegate("tr", "click", function(e) {
    console.log($(e.currentTarget).index() + 1);
});

$("#indexedTable").on("click", "tr", function(e) {
    console.log($(e.currentTarget).index() + 1);
});

They attach a listener to table element and handle any event that bubbles from the table rows. The current API is the on method and the delegate method is legacy API (and actually calls on behind the scenes).

Note that the order of parameters to both functions is different.

example

A comparison between direct handler attachment and delegation is available below or on jsFiddle:

_x000D_
_x000D_
$("#table-delegate").on("click", "tr", function(e) {_x000D_
  var idx = $(e.currentTarget).index() + 1;_x000D_
  $("#delegation-idx").text(idx);  _x000D_
  console.log('delegated', idx);_x000D_
});_x000D_
_x000D_
$("#table-direct tr").on("click", function(e) {_x000D_
  var idx = $(e.currentTarget).index() + 1;_x000D_
  $("#direct-idx").text(idx);_x000D_
  console.log('direct', idx);_x000D_
});_x000D_
_x000D_
$('[data-action=add-row]').click(function(e) {_x000D_
  var id = e.target.dataset.table;_x000D_
  $('#' + id + ' tbody')_x000D_
    .append($('<tr><td>extra</td><td>extra</td><td>extra</td></tr>')[0])_x000D_
});
_x000D_
tr:hover{_x000D_
    background:#ddd;_x000D_
}_x000D_
_x000D_
button.add-row {_x000D_
    margin-bottom: 5px;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>_x000D_
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>_x000D_
_x000D_
_x000D_
<h1>Event handling test</h1>_x000D_
<p>Add rows to both tables and see the difference in handling.</p>_x000D_
<p>Event delegation attaches a single event listener and events related to newly added children are caught.</p>_x000D_
<p>Direct event handling attaches an event handler to each child, where children added after the inital handler attachment don't have a handler attached to them, and therefore their indices won't be logged to console.</p>_x000D_
<h2>Delegation</h2>_x000D_
<p><span>row index: </span><span id="delegation-idx">unknown</span></p>_x000D_
<button class="add-row" data-action="add-row" data-table="table-delegate">Add row to delegation</button>_x000D_
<table id="table-delegate" class="table">_x000D_
    <tbody>_x000D_
    <tr>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
    </tr>_x000D_
    <tr>_x000D_
        <td><p>nested</p></td>_x000D_
        <td><p>nested</p></td>_x000D_
        <td><p>nested</p></td>_x000D_
    </tr>_x000D_
    <tr>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
        <td><p>nested</p></td>_x000D_
    </tr>_x000D_
_x000D_
</table>_x000D_
_x000D_
<h2>Direct attachment</h2>_x000D_
<p><span>row index: </span><span id="direct-idx">unknown</span></p>_x000D_
<button class="add-row" data-action="add-row" data-table="table-direct">Add row to direct</button>_x000D_
<table id="table-direct" class="table">_x000D_
<tbody>_x000D_
    <tr>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
    </tr>_x000D_
    <tr>_x000D_
        <td><p>nested</p></td>_x000D_
        <td><p>nested</p></td>_x000D_
        <td><p>nested</p></td>_x000D_
    </tr>_x000D_
    <tr>_x000D_
        <td>normal</td>_x000D_
        <td>normal</td>_x000D_
        <td><p>nested</p></td>_x000D_
    </tr>_x000D_
    _x000D_
</tbody>_x000D_
</table>
_x000D_
_x000D_
_x000D_

Here's the demo on jsFiddle.

P.S:

If you do have nested tables (or, in the general case, wish to delegate to elements with specific depth), you can use this suggestion from the jQuery bug report.


A simple and jQuery free solution:

document.querySelector('#elitable').onclick = function(ev) {
   // ev.target <== td element
   // ev.target.parentElement <== tr
   var index = ev.target.parentElement.rowIndex;
}

Bonus: It works even if rows are added/removed dynamically


$('tr').click(function(){
 alert( $('tr').index(this) );
});

For first tr, it alerts 0. If you want to alert 1, you can add 1 to index.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to html-table

Table column sizing DataTables: Cannot read property 'length' of undefined TypeError: a bytes-like object is required, not 'str' in python and CSV How to get the <td> in HTML tables to fit content, and let a specific <td> fill in the rest How to stick table header(thead) on top while scrolling down the table rows with fixed header(navbar) in bootstrap 3? Sorting table rows according to table header column using javascript or jquery How to make background of table cell transparent How to auto adjust table td width from the content bootstrap responsive table content wrapping How to print table using Javascript?

Examples related to dom-events

Detecting real time window size changes in Angular 4 Does Enter key trigger a click event? What are passive event listeners? Stop mouse event propagation React onClick function fires on render How do you Hover in ReactJS? - onMouseLeave not registered during fast hover over iFrame onload JavaScript event addEventListener, "change" and option selection Automatically pass $event with ng-click? JavaScript click event listener on class