Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting a table cell by row and column while compensating for rowspan and colspan

I'd like to be able to select a table cell by row and column indices, while compensating for rowspan and colspan. For example, in the following table,

example table

I would expect coloring (1,2) red, (2,3) green, and (3,3) blue, to yield:

expected table

I tried the answer to the question, "Selecting an arbitrary cell in a table by row and column number", but this yielded:

actual table

Here is the jsFiddle: http://jsfiddle.net/acheong87/27HuN/

I understand what is happening, and I even found another question, "Table cellIndex and rowIndex with colspan/rowspan", where an answer was supplied as a plugin, but it just seems unbelievable that there isn't a simpler way! After all, the coloring of the actual result seems understandable, yet unintuitive, while the coloring of the expected result seems far more intuitive and easily graspable.

Can anyone think of a clever and simpler way to implement this?


Update

Here's a new jsFiddle with my (poor) attempt, in case it might inspire a new idea in someone else. Basically, if we assumed the row and col headers weren't spanned (which, of course, isn't a valid assumption), then we could use offsets to "target" the correct cell:

function getCell(table, r, c)
{
    var rowHead = $(table.rows[r].cells[0]);
    var colHead = $(table.rows[0].cells[c]);
    var y = rowHead.offset().top + rowHead.outerHeight(true)/2;
    var x = colHead.offset().left + colHead.outerWidth(true)/2;
    return $(document.elementFromPoint(x, y));
}

While the demo appears to work, there are a number of problems:

  1. Can't assume row and col headers aren't spanned.
  2. Doesn't work if midpoint of row or col is off the viewport; elementFromPoint seems to depend on the viewport.
  3. Doesn't work reliably when scrolling, margins, etc. come into play; flimsy in general; would rather not rely on coordinate-math.
like image 556
slackwing Avatar asked Dec 27 '12 18:12

slackwing


1 Answers

Here's a different approach which does 'pre-processing':

var grid = (function(){

  var table = $("#table")[0], a=[], cell, i, j, k, l, y;

  for (i=0;i<table.rows.length;i++) a[i] = [];

  for (i=0;i<table.rows.length;i++) {
      y = 0;
      for (j=0;j<table.rows[i].cells.length;j++) {
          while (a[i][j + y]) y++;
          cell = $(table.rows[i].cells[j]);
          xspan = parseInt(cell.attr('rowspan') || 1);
          yspan = parseInt(cell.attr('colspan') || 1);
          for (k=0;k<xspan;k++) {
              for (l=0;l<yspan;l++) {
                  if(i + k < table.rows.length) a[i + k][j + y + l] = [i,j];
              }
          }
      }
  }

  return a;

})();

colorCell(1,2,'red');
colorCell(2,3,'green');
colorCell(3,3,'blue');

function colorCell(i,j,s){
    var a = grid[i][j];
    $(table.rows[a[0]].cells[a[1]]).css('background-color', s);
}

jsfiddle

like image 74
ic3b3rg Avatar answered Oct 29 '22 17:10

ic3b3rg