Table row auto-merger
by timmah
HTML
<table>
<tr>
<th>
<p>DATE</p>
</th>
<th>
<p>Col1</p>
</th>
<th>
<p>Col2</p>
</th>
<th>
<p>Col3</p>
</th>
<th>
<p>Col4</p>
</th>
<th>
<p>Col5</p>
</th>
<th>
<p>Col6</p>
</th>
<th>
<p>Col7</p>
</th>
<th>
<p>Col8</p>
</th>
<th>
<p>Col9</p>
</th>
</tr>
<tr>
<td id="row1">
<p>July</p>
</td>
<td>
<p>Row1Col1</p>
</td>
<td>
<p>Row1Col2</p>
</td>
<td>
<p>Row1Col3</p>
</td>
<td></td>
<td></td>
<td>
<p>Row1Col6</p>
</td>
<td></td>
<td></td>
<td>
<p>Row1Col9</p>
</td>
</tr>
<tr>
<td id="row2">
<p>July</p>
</td>
<td></td>
<td></td>
<td></td>
<td>
<p>Row2Col4</p>
</td>
<td></td>
<td></td>
<td>
<p>Row3Col7</p>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td id="row3">
<p>July</p>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<p>Row3Col5</p>
</td>
<td></td>
<td></td>
<td>
<p>Row3Col8</p>
</td>
<td></td>
</tr>
<tr>
<td id="row4">
<p>August</p>
</td>
<td>
<p></p>
</td>
<td>
<p>Row4Col2</p>
</td>
<td>
<p>Row4Col3</p>
</td>
<td>
<p>Row4Col4</p>
</td>
<td>
<p></p>
</td>
<td>
<p></p>
</td>
<td>
...
CSS
table {
max-width: 100%;
padding: 5px;
}
th,
td {
padding: 0.5em;
}
th {
background-color: #ccc;
color: black;
}
td {
border: solid 1px #ddd;
}
JavaScript
/*
* This script allows auto-merging of table rows when:
*
* a) the values of the first cell in 2 sequential rows are identical, and
* b) no cells sitting above one another can both contain text
*
* This is particularly useful for pivot tables (header X + header Y = data Z).
*
* It was built to provide a front-end solution for Drupal's Pivot Tables and
* Views Row Merge modules not playing together well. Delete the script to see
* what I mean...
*
* @TODO:
* - Expand this to handle total rows that must be added together rather than replaced
* - Make the script respectful of wrapper elements (like <p>) inside the cells. Currently it deletes them
*/
console.clear();
// A handy messaging functon to speed up debugging
function msg(i, msg) {
console.log('For $cRowCellsData[' + i + '], ' + msg);
}
function mergeRows() {
var $rows = $('table tr').not(':first'),
$newRow = [];
$rows.each(function() {
var $cRow = $(this),
$nRow = $cRow.next('tr'),
$cRowFCell = $cRow.children('td:first'),
$nRowFCell = $nRow.children('td:first'),
$cRowCells = $cRow.children('td'),
$nRowCells = $nRow.children('td'),
$cRowCellsData = [],
$nRowCellsData = [],
match = false;
// Test if the text in the first cells of sequential rows matches...
if ($cRowFCell.text().trim() === $nRowFCell.text().trim()) {
// Add a target class to delete unnecessary rows later
$cRow.addClass('to-delete');
// Collect the data within each cell for both the Current and Next row
$cRowCells.each(function() {
$cRowCellsData.push($(this).text().trim());
});
$nRowCells.each(function() {
$nRowCellsData.push($(this).text().trim());
});
// Test if the $newRow has already been populated by checking it's length against...