2

Possible Duplicate:
How to detect which row [ tr ] is clicked?

I have a table like this:

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

In JavaScript (no jQuery please) how do I work out if a user clicks on the table on which row he/she clicked?

Community
  • 1
  • 1
Zo72
  • 14,593
  • 17
  • 71
  • 103
  • 4
    isn't this thread the same issue? http://stackoverflow.com/questions/1824206/how-to-detect-which-row-tr-is-clicked – JMax Sep 27 '11 at 12:43
  • Give your rows an `id` attribute and hook up the onclick event – Anand Shah Sep 27 '11 at 12:44
  • Niiiighhh. Use a library. It doesn't need to be jQuery (and jQuery wouldn't even be my first choice), but use a library. Dealing with this sort of relatively complex event logic has enough variances between browsers to be annoying. Use existing code to solve the problem instead of reinventing the wheel. – Quentin Sep 27 '11 at 12:45
  • 2
    @Quentin: I would hardly call this complex event logic – josh.trow Sep 27 '11 at 12:46
  • Sticking an event handler on the table, figuring out the clicked element (in the two different major event models), then walking up the DOM until you find a table row? It is *sufficiently* complex to justify a library. – Quentin Sep 27 '11 at 12:48
  • 1
    @Quentin: OR, you simply iterate over all the table rows adding a listener to each row. If you can't do iteration, then I'm not sure you need to be dabbling in event-driven programming yet. – josh.trow Sep 27 '11 at 12:51
  • 1
    @Quentin: use a library... reinventing the wheel... Why do some people infer too much from a simple question ? – Zo72 Sep 27 '11 at 12:59

7 Answers7

4

event.target, getElementsByTagName, traditional event method:

var trs = document.getElementsByTagName('tr');

for (var i = 0; i < trs.length; i++) {
     trs[i].onclick = clickHandler;   
}

function clickHandler(event) {
    alert(this.innerText || this.textContent);  // edit: textContent for firefox support
}

jsFiddle

Joe
  • 80,724
  • 18
  • 127
  • 145
  • +1 Simple and easy. You'll just want `alert(this.innerText || this.textContent);` to pick up Firefox support. – user113716 Sep 27 '11 at 13:11
3

If you attach a click event handler to the table, you can get the event target, which will contain the element that was actually clicked:

document.getElementById("yourTable").onclick = function(e) {
    console.log(e.target);   
}

In your example, that's likely to be a td, so you could access the tr like this:

var tr = e.target.parentNode;

You can check the type of element that has been clicked with the tagName property:

var clickedElementType = e.target.tagName; //Returns something like "TD"

Alternatively, you could iterate over all the tr elements in your table and bind a click event handler to each.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • Internet Explorer didn't support the standard event model until recently. Think it was version 9, but might have been a bit earlier. Still, this will break in many places. – Quentin Sep 27 '11 at 12:50
  • 1
    True. I'm not going to go into all the differences though. As you already said, just use a library! (And I'm pretty sure you're right, it was version 9). – James Allardice Sep 27 '11 at 12:52
  • `var tr = (e||window.event)[e?'target':'srcElement'].parentNode` should take care of IE nicely. – user113716 Sep 27 '11 at 13:02
3
function handleEvent(e) {
  // Do stuff with the row
}

var rows = document.getElementsByTagName('tr');
for (var row in rows) {
  row.addEventListener('click', handleEvent); 
  // or attachEvent, depends on browser
}
josh.trow
  • 4,861
  • 20
  • 31
  • Internet Explorer didn't support the standard event model until recently. Think it was version 9, but might have been a bit earlier. Still, this will break in many places. – Quentin Sep 27 '11 at 12:50
  • @Quentin: What? If you mean it doesn't support `addEventListener`, I absolutely agree - that's why I put the comment in there. Otherwise, what did you mean by your comment? – josh.trow Sep 27 '11 at 12:52
  • Ah, missed that. This is going to error when it tries to call `row.length.addEventListener` or `row.item.addEventListener` though. – Quentin Sep 27 '11 at 12:56
  • @Quentin: You have a point there - to correctly do it you would have to call `hasOwnProperty` or do a `for (i ; i < length; i++)` loop - ESPECIALLY if you are using Prototype – josh.trow Sep 27 '11 at 12:58
3
window.onload = function(){
  var table = document.getElementById('myTableID');
  table.addEventListener('click',test,false);
}

function test(e){
  var element = e.srcElement || e.target;
  if(element.nodeName == 'TABLE') return;

  while(element.nodeName != 'TR') element = element.parentNode;
  alert(element.rowIndex);
}
Jan Pfeifer
  • 2,854
  • 25
  • 35
2

I prefer to attach an event to the DOM element vs setting onclick. You'll have to do some checking if you want it to work with IE:

var trs = document.getElementsByTagName('tr');
var len = trs.length

var clickHandler = function(i){
    alert('clicked');
};

for(var i = 0; i < len; i++){
    var theRow = trs[i];

    if(theRow.addEventListener){
        theRow.addEventListener('click',clickHandler);
    }
    else{
        theRow.attachEvent('onclick',clickHandler);
    }
}
bittersweetryan
  • 3,383
  • 5
  • 28
  • 42
1

Add an id to each row and then you can query the node id from the Javascript onclick() handler

Malcolm Box
  • 3,968
  • 1
  • 26
  • 44
1

How about putting an onClick on the <tr>?

CodeCaster
  • 147,647
  • 23
  • 218
  • 272