views:

305

answers:

6

I'm writing a script which manages a very large table. When a user clicks a table cell, I would like to know which cell they clicked. e.g

--------------
|     |      |
|     | Click|
--------------

should give me a cell reference of (1, 1).

Any way I could do this with javascript. The page it's running on uses jquery for other purposes, so any jquery based solutions are good aswell.

EDIT: To clarify, the top left cell is (0, 0). For performance reasons, the event needs to bound to the table, not the tds.

+1  A: 

Walk the DOM hierarchy...

You should be able to do this by obtaining a reference to the DOM node for the clicked TD, then walking the previousSibling chain backwards until you reach the first column, counting as you go.

One you're at the start of that sibling chain (i.e., the first TD in the row), the parentNode should be the TR node, and with that you can perform a similar walk through previousSibling TRs to count up the number of rows.

..or tag each cell with additional attributes

Alternatively, when you create the table, add some fake rowidx="??" and colidx="??" attributes to each cell and retrieve these with getAttribute. If you want to use a legal attribute, you could put the row and column index in an axis="??,??" attribute.

Paul Dixon
this is *unhelpful*?
Paul Dixon
+1, I got your back :) Someone came through and downvoted everyone.
Paolo Bergantino
+2  A: 

This is done very easily using the target property of the event object:

$('#mytable').click(function(e) {
    var tr = $(e.target).parent('tr');
    var x = $('tr', this).index(tr);
    var y = tr.children('td').index($(e.target));
    alert(x + ',' + y);
});

This approach allows you to only bind 1 event handler to the entire table and then figure out which table cell was clicked. This is known as event delegation and can be much more efficient in the right situation, and this one fits the bill. Using this you avoid binding an event to each <td>, and it does not require hard-coding coordinates. So, if your table looks like this:

<table id='mytable'>
    <tr>
      <td>hi</td>
      <td>heya</td>
    </tr>
    <tr>
      <td>boo</td>
      <td>weee</td>
    </tr>
</table>

It will alert the coordinates on click. You can do whatever with that. :)

If you find performance to be too slow (depending on just how large your table is) you would then have to resort to hardcoding or a combination of the two, maybe only hard coding the <tr> index, as that would be the slowest to get, and then getting the <td> index dynamically. Finally, if all this coordinate business is completely unnecessary and what you really just wanted was a reference to the clicked <td>, you would just do this:

$('#mytable').click(function(e) {
    var td = $(e.target);
    // go crazy
});
Paolo Bergantino
A: 

Edit: don't look at mine, look at kkyy's. His should work, mine is swapped.

$("#tableId td").click( function () {
     var x = $(this).index($(this).siblings().andSelf());
     var y = $(this).parent().index($(this).parent().siblings().andSelf());
     alert(x + ", " + y);
});
cobbal
+2  A: 
$('td').click(function(event) {
  var row = $(this).parent('tr');
  var horizontal = $(this).siblings().andSelf().index(this);
  var vertical = row.siblings().andSelf().index(row);
  alert(horizontal+','+vertical);
});
kkyy
This is going to bind an event handler to each td. He says he has a large table. It would be best to bind to the table itself and figure it out then.
Paolo Bergantino
Probably so, I just threw the td in there for simplicity's sake. Imho the purpose of these answers is to present the general idea to the question asker, not to provide a ready-made-all-things-considered-just-plug-and-play -solution :)
kkyy
The original attempt, used event handlers on tds. Performance was scarily bad.
Macha
A: 

You mentioned a very large table - it would be unwise to bind the click to every td. A better approach is to use the .live method, if your still on jquery 1.2.6 you can just bind a click event to the table and use event delegation. if you need code for this ask.

$("#tableId td").live('click', function () {
     var $this = $(this);
     var x = $this.prevAll().length;
     var y = $this.parent().prevAll.length;
     console.log(x + ", " + y);
});
redsquare
A: 

assuming your 1st row, 1st column to be 0,0

var row = 0;
    $('#tblImages > tbody > tr').each( function(){
               var col = 0;

               $(this).children('td').each( function(){

                   $(this).attr("currentRow", row).attr("currentCol", col);
                   col++;
               });
               row++;
        }
        );
    $('#tblImages > tbody > tr > td').click(function(){
        alert( $(this).attr("currentRow") + "   " + $(this).attr("currentCol"));

This can certainly be improved more..but its working

James_Smith