如何使用jQuery找到每个表格单元格的“视觉位置”?

11
我有一个包含ROWSPAN和COLSPAN的HTML表格。如何使用jQuery找到每个单元格的“视觉位置”?
例如,这是我的表格的可视化表示,其中每个单元格都填充了“视觉位置”算法应返回的内容:
(注意:我只关心中的单元格,列引用可以是整数而不是字母字符,我只是为了方便突出显示问题)
+--+--+--+--+--+
|  |A |B |C |D |
+--+--+--+--+--+
|1 |A1|B1   |D1|
+--+--+--+--+  +
|2 |A2   |C2|  |
+--+     +--+  +
|3 |     |C3|  |
+--+--+--+--+--+
|4 |A4|B4|C4|D4|
+--+--+--+--+--+
|XYZ           |
+--+--+--+--+--+

我尝试实现第一个链接,但是由于它没有考虑到ROWSPANS,所以C3单元格的引用不准确。第二个链接可能可以合并到第一个解决方案中,但我无法弄清楚如何做到这一点。 我希望将其作为一个名为getCellLocation(cell)的函数使用,它将返回一个关联数组,该数组返回位置,例如:
function getCellLocation(cell)
{
  var row_number = parseInt($(cell).parent().prevAll().length) + 1;
  var col_number = 1;
  $(cell).prevAll('td').each(function() {
      col_number += $(this).attr('colspan') ? parseInt($(this).attr('colspan')) : 1;
  });

  var location = new Array();
  location['row'] = row_number;
  location['col'] = col_number;
  location['index'] = $('td').index(cell) + 1;
  return location;
}

$('table td').each(function(i){
  var cell = getCellLocation($(this));
  $(this).prepend('<span class="ref">R' + cell['row'] + ':C' + cell['col'] + ':D' + cell['index'] + '</span>');
});

以下是示例表格的HTML代码:

这是示例表格的HTML代码:

<table border="1" cellspacing="0">
  <thead>
    <tr>
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>A1</td>
      <td colspan="2">B1</td>
      <td rowspan="3">D1</td>
    </tr>
    <tr>
      <th>2</th>
      <td rowspan="2" colspan="2">A2</td>
      <td>C2</td>
    </tr>
    <tr>
      <th>3</th>
      <td>C3</td>
    </tr>
    <tr>
      <th>4</th>
      <td>A4</td>
      <td>B4</td>
      <td>C4</td>
      <td>D4</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="5">XYZ</td>
    </tr>
  </tfoot>
</table>
<style> span { background-color: #ffc; margin-right: .5em;} </style>
5个回答

10

这是我的解决方案:

function getCellLocation(cell) {

    var cols = cell.closest("tr").children("td").index(cell);
    var rows = cell.closest("tbody").children("tr").index(cell.closest("tr"));
    var coltemp = cols;
    var rowtemp = rows;

    cell.prevAll("td").each(function() {
        cols += ($(this).attr("colspan")) ? parseInt($(this).attr("colspan")) - 1 : 0;
    });

    cell.parent("tr").prevAll("tr").each(function() {
        //get row index for search cells
        var rowindex = cell.closest("tbody").children("tr").index($(this));
        // assign the row to a variable for later use
        var row = $(this);
        row.children("td").each(function() {
            // fetch all cells of this row
            var colindex = row.children("td").index($(this));
            //check if this cell comes before our cell
            if (cell.offset().left > $(this).offset().left) {
                // check if it has both rowspan and colspan, because the single ones are handled before
                var colspn = parseInt($(this).attr("colspan"));
                var rowspn = parseInt($(this).attr("rowspan"));
                if (colspn && rowspn) {
                    if(rowindex + rowspn > rows)
                    cols += colspn;                    
                }
                if(rowspn && rowindex + rowspn > rows) cols +=1;
            }

        });
    });

我正在查找同时具有colspan和rowspan的单元格,因为其他单元格已经被此代码的前五行处理过了。如果单元格同时具有rowspan和colspan,则应该影响不在此单元格下方或旁边的其他单元格,因此我需要搜索每个单元格之前的单元格以查找相互作用。


在某些情况下似乎存在轻微问题或重复计数。请考虑将其应用于此表格时的结果(请参见单元格Col3 Row2):http://jsfiddle.net/tUn54/ - Turgs
如果表格预计更宽,仍然存在一些奇怪的问题。请参见此处:http://jsfiddle.net/tUn54/2/(Row2Col9、Row2Col12、Row5Col9、Row5Col12) - Turgs
@tpaksu,你有更新脚本吗?因为在这种情况下它无法工作。http://jsfiddle.net/TRr6C/8/ - Petah
我更新了我的代码。添加了一行:if(rowspn && rowindex + rowspn > rows) cols +=1;。你可以在这里测试它:http://jsfiddle.net/TRr6C/16/。 - Taha Paksu
我并不仅仅检查跨行单元格,而是那些既有跨行又有跨列的单元格。如果可以的话,我可以解释一下为什么需要这个更新。 - Taha Paksu
显示剩余3条评论

1
your solution        my proposed table design
+--+--+--+--+--+     +--+--+--+--+--+
|  |A |B |C |D |     |  |A |B |C |D |     length 5 vs 5
+--+--+--+--+--+     +--+--+--+--+--+
|1 |A1|B1   |D1|     |1 |A1|B1|//|D1|
+--+--+--+--+  +     +--+--+--+--+--+
|2 |A2   |C2|  |     |2 |A2|//|C2|//|     length 3 vs 5
+--+     +--+  +     +--+--+--+--+--+
|3 |     |C3|  |     |3 |//|//|C3|//|
+--+--+--+--+--+     +--+--+--+--+--+
|4 |A4|B4|C4|D4|     |4 |A4|B4|C4|D4|
+--+--+--+--+--+     +--+--+--+--+--+
|XYZ           |     |XY|//|//|//|//|     length 1 vs 5
+--+--+--+--+--+     +--+--+--+--+--+

// cells labeled '//' above have this class

td.stuffing { display: none; }

我做的事情你看到了吗?

比如说,这是第三行:

<tr>
  <th>2</th>
  <td rowspan="2" colspan="2">A2</td>
  <td class="stuffing"></td>
  <td>C2</td>
  <td class="stuffing"></td>
</tr>

现在,检索正确索引的函数非常简单。
function getCellLocation(cell) {
    return {row:cell.parentNode.rowIndex, cell:cell.cellIndex}
}


这里还有一个额外的好处。如果您访问了一个隐藏的单元格,它将自动遍历到正确的单元格,该单元格跨越了那些隐藏的单元格。

function getSmartCell(table, row, col) {
    var cell = table.rows[row].cells[col];
    if (cell.className.indexOf("stuffing") == -1) return cell;

    // traverse Left
    while ((row>0) && (col>0) && (cell.className.indexOf("stuffing") >= 0)) {
        cell = table.rows[row].cells[--col];
    }

    // roll back one cell if no colSpan is found
    if (cell.colSpan == 1) cell = table.rows[row].cells[++col];

    // traverse Up
    while ((row>0) && (col>0) && (cell.className.indexOf("stuffing") >= 0)) {
        cell = table.rows[--row].cells[col];
    }

    return cell;
}

使用方法:

var tb = document.querySelector("table");
getCellLocation(getSmartCell(tb,3,2)); // {row: 2, cell: 1}

注意 我刚刚检查了 getSmartCell 的代码,如果有两个相邻的行跨度,它将返回错误的结果。我需要修复它。

这里是一个例子 https://jsfiddle.net/goua3m13/


在我的问题中,单元格被“合并”以跨越列和行是有意为之的。对于使用情况来说,它需要这样做,不能使用空单元格并将其隐藏。 - Turgs
1
@Turgs 在使用隐藏单元格的同时,仍然可以使用colspan和rowspan。 - Qwerty

0
这里有一个能够处理复杂表格结构的jQuery解决方案。该解决方案使用开源WxT Table Parser,可在此处获取:https://raw.github.com/wet-boew/wet-boew/master/src/js/dependencies/parserTable.js 你可以在Table Usability Concept Github Repository中找到相关文档。请查看“Table Parser - WET 3.0版本”的API文档。
通过利用HTML表格标记和数据单元格(td)与标题单元格(th)之间的视觉关系,实现表格解析。
// Used to get the reference to the WxT table parser
var _pe = window.pe || {
    fn : {}
};

// For each table elements
$('table').each(function () {

    var $tbl = $(this);

    // Parse the table
    _pe.fn.parsertable.parse($tbl);

    // For each data cell
    $('td', $tbl).each(function () {

        var $td = $(this),
            tblparser;

        // Get the API structure as defined under "Table Parser - WET 3.0 release" (https://github.com/duboisp/Table-Usability-Concept/blob/master/API/td.md#table-parser---wet-30-release)
        tblparser = $td.data().tblparser;

        // Set the cell location (x, y)
        $td.html(tblparser.row.rowpos + ', ' + tblparser.col.start);


    });
});

你可以在这里找到一个可用的示例:http://jsfiddle.net/TVttA/

干杯

:-)


0

对于这种特定的布局(即如果您的第一行没有跨列并且单元格边框更或少相同),您可以这样做:

function getCellLocation(cell)
{
    var row_number = cell.parentNode.rowIndex;
    var col_number = "";
    $(cell).parents('table').find('tr:first th').each( function()
    {
        if (cell.offsetLeft >= this.offsetLeft)
        {
            col_number = $(this).text();
        }
        else return false;
    });
    return col_number + row_number;
}

如果你想要数字列,将其改为

var col_number = 0;
    ...
if (cell.offsetLeft >= this.offsetLeft)
{
    col_number++;
}

0

由于被接受的答案缺少return语句,且仅适用于tbody和td(不适用于thead和th),因此我进行了一些小调整以使其正常工作:

function getCellLocation(cell) {

    var cols = cell.closest("tr").children("th, td").index(cell);
    var rows = cell.closest("thead, tbody").children("tr").index(cell.closest("tr"));

    cell.prevAll("th, td").each(function() {
        cols += ($(this).attr("colspan")) ? parseInt($(this).attr("colspan")) - 1 : 0;
    });

    cell.parent("tr").prevAll("tr").each(function() {
        //get row index for search cells
        var rowindex = cell.closest("thead, tbody").children("tr").index($(this));
        // assign the row to a variable for later use
        var row = $(this);
        row.children("th, td").each(function() {
            //check if this cell comes before our cell
            if (cell.offset().left > $(this).offset().left) {
                // check if it has both rowspan and colspan, because the single ones are handled before
                var colspn = parseInt($(this).attr("colspan"));
                var rowspn = parseInt($(this).attr("rowspan"));
                if (rowspn && rowindex + rowspn > rows) {
                    cols += colspn ? colspn : 1;
                }
            }

        });
    });
    return cols;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接