• This widget will only work in tablesorter version 2.8+ and jQuery version 1.7+.
  • Please do not use this widget in very large tables (it might be really slow) or when your table includes multiple tbodies.
  • In New v2.15.6, added group_saveGroups & group_saveReset options. More details are included in the "Options" section.
  • In New v2.14, added group_dateString option. More details are included in the "Options" section.
  • In v2.13, added group_separator option & group-separator-# header class name. To see this in action, check out the file type parser demo.
  • In v2.12, added group_callback & group_complete options. See options section below for details.
  • In v2.11:
    • The grouping widget now works across multiple tbodies.
    • Added group-false header option which disables the grouping widget for a specific column.
    • Added the group_collapsed option - get more details in the options block below.
    • You can now toggle all group rows by holding down the Shift key while clicking on a group header.
    • This widget now works properly with the pager addon (pager addon updated).
  • Clicking on any of the sortable header cells will cause the column below it to sort and add a group header.

Demo

Numeric column:
"group-number-10" (includes subtotals)
Animals column:
"group-letter-1"
Date column:
"group-date"

Quality (number)
Numeric (every 10)
Priority (letter)
Animals (first letter)
Natural Sort (first word)
Inputs (second word)
Date (full)
Quality Numeric Priority Animals Natural Sort Inputs Date
110Koalaabc 1231/13/2013 12:01 AM
329Kangarooabc 11/15/2013
210Antabc 91/13/2013
381Beezyx 241/11/2013
321Aardwolfzyx 551/13/2013 03:30 AM
13Bearabc 111/15/2013
412Armadillozyx 21/15/2013 12:30 PM
256Aardvarkabc 21/22/2013
155Lionabc 92/15/2013
487AnteaterABC 101/3/2013
298Lemurzyx 11/11/2013
120Llamazyx 1212/13/2012

Page Header

<!-- Tablesorter: required -->
<link href="../css/theme.blue.css" rel="stylesheet">
<script src="../js/jquery.tablesorter.js"></script>
<script src="../js/jquery.tablesorter.widgets.js"></script>

<!-- Grouping widget -->
<script src="../js/parsers/parser-input-select.js"></script>
<script src="../js/widgets/widget-grouping.js"></script>

Script

$(function(){

$("#groups").tablesorter({
theme : "blue",
headers: {
0: { sorter: "checkbox" },
3: { sorter: "select" },
6: { sorter: "inputs" }
},
widgets: [ "group", "columns", "zebra" ],
widgetOptions: {
group_collapsible : true, // make the group header clickable and collapse the rows below it.
group_collapsed : false, // start with all groups collapsed (if true)
group_saveGroups : true, // remember collapsed groups
group_saveReset : '.group_reset', // element to clear saved collapsed groups
group_count : " ({num})", // if not false, the "{num}" string is replaced with the number of rows in the group

// change these default date names based on your language preferences
group_months : [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
group_week : [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
group_time : [ "AM", "PM" ],

// this function is used when "group-date" is set to create the date string
// you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString()
// reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter
group_dateString : function(date) {
return date.toLocaleString();
},

group_formatter : function(txt, col, table, c, wo) {
// txt = current text; col = current column
// table = current table (DOM); c = table.config; wo = table.config.widgetOptions
if (col === 7 && txt.indexOf("GMT") > 0) {
// remove "GMT-0000 (Xxxx Standard Time)" from the end of the full date
txt = txt.substring(0, txt.indexOf("GMT"));
}
// If there are empty cells, name the group "Empty"
return txt === "" ? "Empty" : txt;
},

group_callback : function($cell, $rows, column, table){
// callback allowing modification of the group header labels
// $cell = current table cell (containing group header cells ".group-name" & ".group-count"
// $rows = all of the table rows for the current group; table = current table (DOM)
// column = current column being sorted/grouped
if (column === 2) {
var subtotal = 0;
$rows.each(function(){
subtotal += parseFloat( $(this).find("td").eq(column).text() );
});
$cell.find(".group-count").append("; subtotal: " + subtotal );
}
},
// event triggered on the table when the grouping widget has finished work
group_complete : "groupingComplete"
}
});

});

CSS

tr.group-header td {
background: #eee;
}
.group-name {
text-transform: uppercase;
font-weight: bold;
}
.group-count {
color: #999;
}
.group-hidden {
display: none;
}
.group-header, .group-header td {
user-select: none;
-moz-user-select: none;
}
/* collapsed arrow */
tr.group-header td i {
display: inline-block;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid #888;
border-right: 4px solid #888;
border-left: 4px solid transparent;
margin-right: 7px;
user-select: none;
-moz-user-select: none;
}
tr.group-header.collapsed td i {
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid #888;
border-right: 0;
margin-right: 10px;
}

HTML

<table id="groups">
<thead>
<tr>
<th class="group-word"></th> <!-- checkbox status -->
<th class="group-number">Quality (number)</th> <!-- notice this uses the same class name as the Numeric column, it's just left at 1 -->
<th class="group-number-10">Numeric (every <span>10</span>)</th>
<th class="group-letter-1">Priority (letter)</th>
<th class="group-letter-1">Animals (first <span>letter</span>)</th>
<th class="group-word-1">Natural Sort (first word)</th>
<th class="group-word-2">Inputs (second word)</th>
<!-- try "group-date", "group-date-year", "group-date-month", "group-date-day", "group-date-week" or "group-date-time" -->
<th class="group-date">Date (<span>Full</span>)</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Quality</th>
<th>Numeric</th>
<th>Priority</th>
<th>Animals</th>
<th>Natural Sort</th>
<th>Inputs</th>
<th>Date</th>
</tr>
</tfoot>
<tbody>
<tr><td><input type="checkbox" checked=""></td><td>1</td><td>10</td><td><select><option selected="">A</option><option>B</option><option>C</option></select></td><td>Koala</td><td>abc 123</td><td><input type="text" value="item: truck"></td><td>1/13/2013 12:01 AM</td></tr>
<tr><td><input type="checkbox"></td><td>3</td><td>29</td><td><select><option>A</option><option>B</option><option selected="">C</option></select></td><td>Kangaroo</td><td>abc 1</td><td><input type="text" value="item: car"></td><td>1/15/2013</td></tr>
<tr><td><input type="checkbox"></td><td>2</td><td>10</td><td><select><option>A</option><option>B</option><option selected="">C</option></select></td><td>Ant</td><td>abc 9</td><td><input type="text" value="item: motorcycle"></td><td>1/13/2013</td></tr>
<tr><td><input type="checkbox"></td><td>3</td><td>81</td><td><select><option>A</option><option selected="">B</option><option>C</option></select></td><td>Bee</td><td>zyx 24</td><td><input type="text" value="item: golf cart"></td><td>1/11/2013</td></tr>
<tr><td><input type="checkbox" checked=""></td><td>3</td><td>21</td><td><select><option>A</option><option selected="">B</option><option>C</option></select></td><td>Aardwolf</td><td>zyx 55</td><td><input type="text" value="item: scooter"></td><td>1/13/2013 03:30 AM</td></tr>
<tr><td><input type="checkbox"></td><td>1</td><td>3</td><td><select><option selected="">A</option><option>B</option><option>C</option></select></td><td>Bear</td><td>abc 11</td><td><input type="text"></td><td>1/15/2013</td></tr>
<tr><td><input type="checkbox"></td><td>4</td><td>12</td><td><select><option>A</option><option selected="">B</option><option>C</option></select></td><td>Armadillo</td><td>zyx 2</td><td><input type="text"></td><td>1/15/2013 12:30 PM</td></tr>
<tr><td><input type="checkbox" checked=""></td><td>2</td><td>56</td><td><select><option selected="">A</option><option>B</option><option>C</option></select></td><td>Aardvark</td><td>abc 2</td><td><input type="text" value="item: skateboard"></td><td>1/22/2013</td></tr>
<tr><td><input type="checkbox"></td><td>1</td><td>55</td><td><select><option selected="">A</option><option>B</option><option>C</option></select></td><td>Lion</td><td>abc 9</td><td><input type="text"></td><td>2/15/2013</td></tr>
<tr><td><input type="checkbox" checked=""></td><td>4</td><td>87</td><td><select><option>A</option><option selected="">B</option><option>C</option></select></td><td>Anteater</td><td>ABC 10</td><td><input type="text" value="item: skates"></td><td>1/3/2013</td></tr>
<tr><td><input type="checkbox" checked=""></td><td>2</td><td>98</td><td><select><option>A</option><option>B</option><option selected="">C</option></select></td><td>Lemur</td><td>zyx 1</td><td><input type="text"></td><td>1/11/2013</td></tr>
<tr><td><input type="checkbox"></td><td>1</td><td>20</td><td><select><option>A</option><option>B</option><option selected="">C</option></select></td><td>Llama</td><td>zyx 12</td><td><input type="text"></td><td>12/13/2012</td></tr>
</tbody>
</table>