javascript jQuery 合并表格行,但考虑前一列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28492279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:04:02  来源:igfitidea点击:

jQuery merge table rows, but take previous columns into account

javascriptjqueryhtmlmerge

提问by newuser

I have a table in html. The table utilizes generic tr's and td's... and makes a dynamic table with six columns and a variable number of rows.

我有一个 html 表格。该表使用通用的 tr 和 td ......并制作一个具有六列和可变行数的动态表。

If a given table looks something like this:

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

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

When I run the following javascript:

当我运行以下 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;
    }
});
}

The following table is made:

制作了下表:

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

Now, the javascript works in the sense that I do need the rows to merge as seen in the above table. The first column merges nicely. And other areas in the columns do so as well. My only issues arises in areas like columns 2 and five. Now to reiterate, these tables will always be dynamically generated so I can't approach this in a static fashion. But... the merging for "blue" in column 2 and "cow" in column 5 goes past the associated values in column 1. Instead, I would want a table like this:

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

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

In the above table, the merged cells for "blue" and "cow" separate because the cells preceding it end their rowspan there. This would occur in any case. If a cell in the second column happened to span multiple rows, then any subsequent columns could not have rowspans extending past it. Hopefully what I have described is clear enough. I am asking... how do I revise my javascript to achieve this effect?

在上表中,“blue”和“cow”的合并单元格是分开的,因为它前面的单元格在那里结束了它们的行跨度。这在任何情况下都会发生。如果第二列中的一个单元格恰好跨越多行,则任何后续列都不能有行跨度超过它。希望我所描述的足够清楚。我在问...我如何修改我的 javascript 以达到这种效果?

回答by Artur Filipiak

If only the first column is supposed to be a "divider" for the rest of the columns, then you could use an array to store first column rows "breaks".

如果只有第一列应该是其余列的“分隔符”,那么您可以使用数组来存储第一列行“中断”。

Also, your function doesn't have the right to work. When element is removed inside loop, The index of each element above the removed one is shifted down immediately to fill the DOM index gap (so the element right after the removed one is skipped in next iteration). You could use "decremental" loop or simply hide td's.

此外,您的功能无权工作。当元素remove在循环中时,被删除元素之上的每个元素的索引立即向下移动以填充 DOM 索引间隙(因此在下一次迭代中跳过被删除元素之后的元素)。您可以使用“递减”循环或简单地隐藏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>

回答by newuser

How about a simple addition to watch the first column, like so:

观看第一列的简单添加怎么样,像这样:

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