【问题标题】:Iterate over table cells, re-using rowspan values迭代表格单元格,重新使用行跨度值
【发布时间】:2017-10-17 16:28:29
【问题描述】:

我有一个简单的 HTML 表,它在一些随机列中使用行跨度。一个例子可能看起来像

 A | B |
---|---| C
 D |   |
---| E |---
 F |   | G

我想遍历行,以便我看到行为A,B,CD,E,C,然后是F,E,G

我想我可能可以使用cell.index() 拼凑一些非常复杂的东西来检查后面行中的“遗漏”列,但我想要一些更优雅的东西......

【问题讨论】:

  • 到目前为止我所做的是保存第一行中每个单元格的左偏移量(因为这保证了TDs 与表中的列一样多),然后逐步执行比较偏移量的行以查看单元格“属于”哪一列。受到this question 的启发——它现在工作正常,但如果我有任何colspans 并且仍然感觉笨重,它就会崩溃......

标签: javascript html html-table


【解决方案1】:

没有 jquery:

function tableToMatrix(table) {
  var M = [];
  for (var i = 0; i < table.rows.length; i++) {
    var tr = table.rows[i];
    M[i] = [];
    for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
      var c = (M[i-1]||[])[j];
      // first check if there's a continuing cell above with rowSpan
      if (c && c.parentNode.rowIndex + c.rowSpan > i) {
        M[i].push(...Array.from({length: c.colSpan}, () => c))
        j += c.colSpan;
      } else if (tr.cells[k]) {
        var td = tr.cells[k++];
        M[i].push(...Array.from({length: td.colSpan}, () => td));
        j += td.colSpan;
      }
    }
  }
  return M;
}

var M = tableToMatrix(document.querySelector('table'));

console.table(M.map(r => r.map(c => c.innerText)));

var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
  border: 1px solid rgba(0,0,0,.3);
}
<table>
  <tr>
    <td colspan=2>A</td>

    <td rowspan=2>B</td>
  </tr>
  <tr>
    <td>C</td>
    <td rowspan=3>D</td>
  </tr>
  <tr>
    <td rowspan=2>E</td>
    <td rowspan=4>F</td>
  </tr>
  <tr></tr>
  <tr>
    <td rowspan=2 colspan=2>G</td>
  </tr>
  <tr></tr>
  <tr>
    <td rowspan=3 colspan=3>H</td>
  </tr>
  <tr></tr>
  <tr></tr>
  <tr>
    <td colspan=3>I</td>
  </tr>
</table>

【讨论】:

    【解决方案2】:

    试试这个:

        <table id="tbl">
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td colspan="2" rowspan="2">A</td>
            <td rowspan="2">C</td>
        </tr>
        <tr>
            <td rowspan="2">E</td>
        </tr>
        <tr>
            <td>F</td>
            <td>G</td>
        </tr>
        </table>
    

    脚本:

        var finalResult = '';
        var totalTds = $('#tbl TR')[0].length;
        var trArray = [];
        var trArrayValue = [];
        var trIndex = 1;
        $('#tbl TR').each(function(){
        var currentTr = $(this);
        var tdIndex = 1;
        trArray[trIndex] = [];
        trArrayValue[trIndex] = [];
        var tdActuallyTraversed = 0;
        var colspanCount = 1;
        $('#tbl TR').first().children().each(function(){
            if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
            { 
                trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
                trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
                finalResult = finalResult + trArrayValue[trIndex][tdIndex];
            }
            else
            {                        
                if(colspanCount <= 1)
                {
                    colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
                }
                if(colspanCount > 1 && tdIndex > 1)
                {
                    trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
                    trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
                    colspanCount--;
                }
                else
                {
                    trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
                    trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
                    tdActuallyTraversed++;
                }
                finalResult = finalResult + trArrayValue[trIndex][tdIndex];
    
            }
    
            tdIndex++;
        });
        trIndex++;
    });
    
    alert(finalResult);
    

    Fiddle

    我不确定性能,但效果很好。

    【讨论】:

    • 更新解决方案,现在它也涵盖了 colspan
    【解决方案3】:

    我对您的问题的理解是:您想用相同的值拆分合并的单元格,然后简单地逐行迭代表格。

    我创建了一个 JSFiddle,它将使用相同的值拆分合并的单元格。然后,您将拥有一个可以简单地按行迭代的表,以获得您指定的所需输出。

    在这里运行http://jsfiddle.net/9PZQj/3/

    这是完整的代码:

    <table id="tbl" border = "1">
        <tr>
            <td>A</td>
            <td>B</td>
            <td rowspan="2">C</td>
        </tr>
        <tr>
            <td>D</td>
            <td rowspan="2">E</td>
        </tr>
        <tr>
            <td>F</td>
            <td>G</td>
        </tr>
    </table>
    <br>
    <div id="test"> </div>
    

    这是用于操作表数据的 jquery。

       var tempTable = $('#tbl').clone(true);
        var tableBody = $(tempTable).children();
        $(tableBody).children().each(function(index , item){
            var currentRow = item;
            $(currentRow).children().each(function(index1, item1){
                if($(item1).attr("rowspan"))
                {
                    // copy the cell
                    var item2 = $(item1).clone(true);
                    // Remove rowspan
                    $(item1).removeAttr("rowspan");
                    $(item2).removeAttr("rowspan");
                    // last item's index in next row
                    var indexOfLastElement = $(currentRow).next().last().index();
                    if(indexOfLastElement <= index1)
                    {
                         $(currentRow).next().append(item2)
                    }
                    else
                    {
                      // intermediate cell insertion at right position
                      $(item2).insertBefore($(currentRow).next().children().eq(index1))
                    }
                }
            });
    
            console.log(currentRow)
        });
    
       $('#test').append(tempTable);
    

    【讨论】:

    • 这可行,但我确实想更改表格的显示方式——我只想在“逻辑行”中工作,当然应该包括表中每一列的值,如图所示。
    • 您的原始表格没有改变。在此解决方案中,我正在创建表的副本并对其进行调整,以便您可以使用新的更新表来处理相同的元素但合并行跨度。
    【解决方案4】:

    您可以使用this Gist。它支持 W3C 的所有要求,甚至“rowspan=0”(似乎只有 Firefox 支持)。

    【讨论】:

    • 请在您的答案中发布相关的、最少的代码 - 如果删除要点,这对未来的搜索者来说用处不大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2022-10-23
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    相关资源
    最近更新 更多