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.
If a given table look
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 remove
d 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.
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>
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;
}
});
}