Table row auto-merger
by timmah
HTML
<table>
<tr>
<th>
<p>DATE</p>
</th>
<th>
<p>Loc1</p>
</th>
<th>
<p>Loc2</p>
</th>
<th>
<p>Loc3</p>
</th>
<th>
<p>Loc4</p>
</th>
<th>
<p>Loc5</p>
</th>
<th>
<p>Loc6</p>
</th>
<th>
<p>Loc7</p>
</th>
<th>
<p>Loc8</p>
</th>
<th>
<p>Loc9</p>
</th>
</tr>
<tr>
<td id="row1">
<p>July</p>
</td>
<td>
<p>Row1Loc1</p>
</td>
<td>
<p>Row1Loc2</p>
</td>
<td>
<p>Row1Loc3</p>
</td>
<td></td>
<td></td>
<td>
<p>Row1Loc6</p>
</td>
<td></td>
<td></td>
<td>
<p>Row1Loc9</p>
</td>
</tr>
<tr>
<td id="row2">
<p>July</p>
</td>
<td></td>
<td></td>
<td></td>
<td>
<p>Row2Loc4</p>
</td>
<td></td>
<td></td>
<td>
<p>Row3Loc7</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>Row3Loc5</p>
</td>
<td></td>
<td></td>
<td>
<p>Row3Loc8</p>
</td>
<td></td>
</tr>
<tr>
<td id="row4">
<p>August</p>
</td>
<td>
<p></p>
</td>
<td>
<p>Row4Loc2</p>
</td>
<td>
<p>Row4Loc3</p>
</td>
<td>
<p>Row4Loc4</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()) {
match = true;
} else {
console.log('No match');
}
// If it's a match...
if (match === true) {
console.log('ROW: ' + $cRowFCell.attr('id'));
// 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());
});
...