jQuery 合并 table 行,但考虑之前的列

jQuery merge table rows, but take previous columns into account

我在 html 中有一个 table。 table 利用通用的 tr 和 td... 并创建一个具有六列和可变行数的动态 table。

如果给定的 table 看起来像这样:

|column 1|column 2|column 3|column 4|column 5|column 6|
-------------------------------------------------------
|  John  |  Green |apples  |February|  cow   |   23   |
-------------------------------------------------------
|  John  |  Red   |Oranges |February|  lion  |   18   |
-------------------------------------------------------
|  John  |  Blue  |apples  |February|  cow   |   45   |
-------------------------------------------------------
|  Mary  |  Blue  |oranges |  April |  cow   |   23   |
-------------------------------------------------------
|  Mary  |  Blue  |apples  |   May  |  dog   |   49   |
-------------------------------------------------------
|  Mary  |  green |apples  |  June  |  cat   |   67   |
-------------------------------------------------------
|  Mary  |  red   |apples  |  June  |  mouse |   32   |
-------------------------------------------------------

当我运行以下javascript:

function MergeCommonRows(table, columnIndexToMerge) {
previous = null;
cellToExtend = null;
table.find("td:nth-child(" + columnIndexToMerge + ")").each(function() {
    jthis = $(this);
    content = jthis.text()
    if (previous == content && content !== "") {
        jthis.remove();
        if (cellToExtend.attr("rowspan") == undefined) {
            cellToExtend.attr("rowspan", 2);
        }
        else {
            currentrowspan = parseInt(cellToExtend.attr("rowspan"));
            cellToExtend.attr("rowspan", currentrowspan + 1);
        }
    }
    else {
        previous = content;
        cellToExtend = jthis;
    }
});
}

做出如下table:

|column 1|column 2|column 3|column 4|column 5|column 6|
-------------------------------------------------------
|        |  Green |apples  |        |  cow   |   23   |
         ------------------         -------------------
|  John  |  Red   |Oranges |February|  lion  |   18   |
         ------------------         -------------------
|        |        |apples  |        |        |   45   |
---------         ------------------         ----------
|        |  Blue  |oranges | April  |  cow   |   23   |
                  ------------------         ----------
|  Mary  |        |        |  May   |        |   49   |
          --------         ----------------------------
|        |  green | apples |  June  |  cat   |   67   |
          --------         ----------------------------
|        |  red   |        |  July  |  mouse |   32   |
-------------------------------------------------------

现在,javascript 的工作原理是我确实需要合并行,如上面 table 所示。第一列合并得很好。列中的其他区域也是如此。我唯一的问题出现在第 2 列和第 5 列等区域。现在重申一下,这些 table 将始终是动态生成的,所以我不能以静态方式处理它。但是...第 2 列中的 "blue" 和第 5 列中的 "cow" 的合并超过了第 1 列中的关联值。相反,我想要这样的 table:

|column 1|column 2|column 3|column 4|column 5|column 6|
-------------------------------------------------------
|        |  Green |apples  |        |  cow   |   23   |
         ------------------         -------------------
|  John  |  Red   |Oranges |February|  lion  |   18   |
         ------------------         -------------------
|        |  Blue  |apples  |        |  cow   |   45   |
-------------------------------------------------------
|        |  Blue  |oranges | April  |  cow   |   23   |
                  ------------------         ----------
|  Mary  |        |        |  May   |        |   49   |
          --------         ----------------------------
|        |  green | apples |  June  |  cat   |   67   |
          --------         ----------------------------
|        |  red   |        |  July  |  mouse |   32   |
-------------------------------------------------------

在上面的 table 中,"blue" 和 "cow" 的合并单元格分开,因为它前面的单元格在那里结束了它们的 rowspan。这无论如何都会发生。如果第二列中的一个单元格碰巧跨越多行,那么任何后续列都不能有 rowspans 延伸超过它。希望我所描述的足够清楚。我在问...如何修改我的 javascript 以达到这种效果?

如果只有第一列应该是其余列的 "divider",那么您可以使用数组来存储第一列行 "breaks"。

此外,您的函数没有工作权限。当元素在循环内 removed 时,删除元素上方的每个元素的索引立即向下移动以填充 DOM 索引间隙(因此在下一次迭代中跳过删除元素之后的元素) .您可以使用 "decremental" 循环或简单地隐藏 td's.

function MergeCommonRows(table) {
    var firstColumnBrakes = [];
    // iterate through the columns instead of passing each column as function parameter:
    for(var i=1; i<=table.find('th').length; i++){
        var previous = null, cellToExtend = null, rowspan = 1;
        table.find("td:nth-child(" + i + ")").each(function(index, e){
            var jthis = $(this), content = jthis.text();
            // check if current row "break" exist in the array. If not, then extend rowspan:
            if (previous == content && content !== "" && $.inArray(index, firstColumnBrakes) === -1) {
                // hide the row instead of remove(), so the DOM index won't "move" inside loop.
                jthis.addClass('hidden');
                cellToExtend.attr("rowspan", (rowspan = rowspan+1));
            }else{
                // store row breaks only for the first column:
                if(i === 1) firstColumnBrakes.push(index);
                rowspan = 1;
                previous = content;
                cellToExtend = jthis;
            }
        });
    }
    // now remove hidden td's (or leave them hidden if you wish):
    $('td.hidden').remove();
}

$('.button').click(function(){
    MergeCommonRows($('#tbl'));
});
table {
    border-collapse: collapse;
}

th, td {
    border: 1px solid black;
    padding:5px;
    text-align: center;
}

.hidden{
    display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table id=tbl>
    <thead>
        <tr>
            <th>column 1</th>
            <th>column 2</th>
            <th>column 3</th>
            <th>column 4</th>
            <th>column 5</th>
            <th>column 6</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>John</td>
            <td>Green</td>
            <td>apples</td>
            <td>February</td>
            <td>cow</td>
            <td>23</td>
        </tr>
        <tr>
            <td>John</td>
            <td>Red</td>
            <td>Oranges</td>
            <td>February</td>
            <td>lion</td>
            <td>18</td>
        </tr>
        <tr>
            <td>John</td>
            <td>Blue</td>
            <td>apples</td>
            <td>February</td>
            <td>cow</td>
            <td>45</td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>Blue</td>
            <td>Oranges</td>
            <td>April</td>
            <td>cow</td>
            <td>23</td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>Blue</td>
            <td>apples</td>
            <td>May</td>
            <td>cow</td>
            <td>49</td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>green</td>
            <td>apples</td>
            <td>June</td>
            <td>cat</td>
            <td>67</td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>red</td>
            <td>apples</td>
            <td>June</td>
            <td>mouse</td>
            <td>32</td>
        </tr>
    </tbody>
</table>

<p><button class=button>Merge Rows</button></p>

观看第一列的简单添加如何,如下所示:

function MergeCommonRows(table, columnIndexToMerge) {
  previous = null;
  cellToExtend = null;
  col1 = null;
  table.find("td:nth-child(" + columnIndexToMerge + ")").each(function() {
      jthis = $(this);
      content1 = jthis.parent('tr').children().first().text();
      if (col1 !== content1) {
          previous = null;
          col1 = content1;
      }
      content = jthis.text()
      if (previous == content && content !== "") {
          jthis.remove();
          if (cellToExtend.attr("rowspan") == undefined) {
              cellToExtend.attr("rowspan", 2);
          }
          else {
              currentrowspan = parseInt(cellToExtend.attr("rowspan"));
              cellToExtend.attr("rowspan", currentrowspan + 1);
          }
      }
      else {
          previous = content;
          cellToExtend = jthis;
      }
  });
  }