最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Iterate over table cells, re-using rowspan values - Stack Overflow

programmeradmin0浏览0评论

I have a simple HTML table, which uses rowspans in some random columns. An example might look like

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

I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.

I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...

I have a simple HTML table, which uses rowspans in some random columns. An example might look like

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

I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.

I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...

Share Improve this question edited Oct 12, 2015 at 11:05 caub 2,7692 gold badges30 silver badges32 bronze badges asked Jul 29, 2013 at 8:28 CodererCoderer 27.3k30 gold badges104 silver badges166 bronze badges 1
  • What I've done so far is to save the left offset of each cell in the first row (since that's guaranteed to have as many TDs as columns in the table), then step through the row paring offsets to see which column the cell "belongs" to. Inspired by this question -- it works OK for now, but would break if I had any colspans and still feels clunky... – Coderer Commented Jul 29, 2013 at 9:36
Add a ment  | 

4 Answers 4

Reset to default 5

without 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>

Try this:

    <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>

Script:

    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

i am not sure about the performance, but it works well.

what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.

I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.

See it running here http://jsfiddle/9PZQj/3/

Here's the plete code:

<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>

Here's the jquery that is used to manipulate the table's data.

   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);

You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

发布评论

评论列表(0)

  1. 暂无评论