Changes

  • In v2.17.5, the need to modify the server's content disposition no longer exists.
  • In v2.17.0,
    • Added the output_ignoreColumns option & modified the output_callback parameters.
    • Added output_duplicateSpans option to duplicate (when true) colspan & rowspan content across cells.
  • In v2.16.4, added the output_encoding option.

Requirements

  • This widget will only work in tablesorter version 2.8+ and jQuery version 1.7+.
  • To download a file with the set filename and extension, the server's Content-disposition needs to be set
  • This widget now uses a method available in modern browsers (IE10+) to download files without the need for server side modifications
  • Support in older browsers (IE9 and older) have not been throughly tested.

Features & Usage

  • This widget can output the table data to:
    • JSON
    • Array of arrays
    • Text with any separator (comma, tab, etc).
  • Rowspan and colspan are supported by this widget. Please take note of additional information in the "Rowspan and colspan" section below.
  • This demo uses Bootstrap to create the download button dropdown for each table allowing the user to choose the settings
    • Using Bootstrap was kind of a pain in the butt... any click inside would close the dropdown.
    • I am sure there are better alternatives as the download button and popup are all completely customizable.
    • The download dropdown code is probably overly complicated because it is set up for two tables & allows modifying almost all of the options.
    • The only thing needed to output the table code (download or open a popup) is to trigger the following event after all of your widget options are set as desired:
      $table.trigger('outputTable');

Credit

Demo


Search in the Discount column

Table showing filter & pager support

1 - 5 / 13 (13)
Rank
First Name
Last Name
Age
Total
Discount
Date
1Philip Aaron WongJohnson Sr Esq25$5.9522%Jun 26, 2004 7:22 AM
11Aaron"doc" Hibert12$2.995%Aug 21, 2009 12:21 PM
12Brandon ClarkHenry Jr51$42.2918%Oct 13, 2000 1:15 PM
111PeterParker28$9.9920%Jul 6, 2006 8:14 AM
21John "Robin"
Hood
33$19.9925%Dec 10, 2002 5:14 AM

Table showing output widget rowspan & colspan support

line
values
value1
value2
value3
1 1.1 1.2 1.3
1.4 1.5
2 2.1 2.2 2.3
2.4 2.5
3 3.1 3.2 3.3
3.4 3.5
4 4.1 4.2
4.3

Script

$(function() {

// set up demo for two table groups
var demos = ['.group1', '.group2'];

$.each(demos, function(groupIndex){
var $this = $(demos[groupIndex]);

// call the tablesorter plugin
$this.find("table").tablesorter({
theme: 'bootstrap',
widthFixed : true,
headerTemplate : '{content} {icon}',
widgets: ["zebra", "filter", "uitheme", "output"],
widgetOptions : {
filter_filteredRow : 'filtered',
filter_reset : demos[groupIndex] + ' .reset',
output_separator : ',', // ',' 'json', 'array' or separator (e.g. ',')
output_ignoreColumns : [], // columns to ignore [0, 1,... ] (zero-based index)
output_dataAttrib : 'data-name', // data-attribute containing alternate cell text
output_headerRows : true, // output all header rows (multiple rows)
output_delivery : 'p', // (p)opup, (d)ownload
output_saveRows : 'f', // (a)ll, (f)iltered or (v)isible
output_duplicateSpans: true, // duplicate output data in tbody colspan/rowspan
output_replaceQuote : '\u201c;', // change quote to left double quote
output_includeHTML : true, // output includes all cell HTML (except the header cells)
output_trimSpaces : false, // remove extra white-space characters from beginning & end
output_wrapQuotes : false, // wrap every cell output in quotes
output_popupStyle : 'width=580,height=310',
output_saveFileName : 'mytable.csv',
// callbackJSON used when outputting JSON & any header cells has a colspan - unique names required
output_callbackJSON : function($cell, txt, cellIndex) { return txt + '(' + cellIndex + ')'; },
// callback executed when processing completes
// return true to continue download/output
// return false to stop delivery & do something else with the data
output_callback : function(config, data) { return true; },

// the need to modify this for Excel no longer exists
output_encoding : 'data:application/octet-stream;charset=utf8,'

}
});

// add pager to first table
if (groupIndex === 0) {
$this.find("table").tablesorterPager({
container: $(".ts-pager"),
output: '{startRow} - {endRow} / {filteredRows} ({totalRows})',
size: 5
});
}

$this.find('.dropdown-toggle').click(function(e){
// this is needed because clicking inside the dropdown will close
// the menu with only bootstrap controlling it.
$this.find('.dropdown-menu').toggle();
return false;
});
// make separator & replace quotes buttons update the value
$this.find('.output-separator').click(function(){
$this.find('.output-separator').removeClass('active');
var txt = $(this).addClass('active').html()
$this.find('.output-separator-input').val( txt );
$this.find('.output-filename').val(function(i, v){
// change filename extension based on separator
var filetype = (txt === 'json' || txt === 'array') ? 'js' :
txt === ',' ? 'csv' : 'txt';
return v.replace(/\.\w+$/, '.' + filetype);
});
return false;
});
$this.find('.output-quotes').click(function(){
$this.find('.output-quotes').removeClass('active');
$this.find('.output-replacequotes').val( $(this).addClass('active').text() );
return false;
});

// clicking the download button; all you really need is to
// trigger an "output" event on the table
$this.find('.download').click(function(){
var typ,
$table = $this.find('table'),
wo = $table[0].config.widgetOptions,
saved = $this.find('.output-filter-all :checked').attr('class');
wo.output_separator = $this.find('.output-separator-input').val();
wo.output_delivery = $this.find('.output-download-popup :checked').attr('class') === "output-download" ? 'd' : 'p';
wo.output_saveRows = saved === "output-filter" ? 'f' : saved === 'output-visible' ? 'v' : 'a';
wo.output_replaceQuote = $this.find('.output-replacequotes').val();
wo.output_trimSpaces = $this.find('.output-trim').is(':checked');
wo.output_includeHTML = $this.find('.output-html').is(':checked');
wo.output_wrapQuotes = $this.find('.output-wrap').is(':checked');
wo.output_headerRows = $this.find('.output-headers').is(':checked');
wo.output_saveFileName = $this.find('.output-filename').val();
$table.trigger('outputTable');
return false;
});

// add tooltip
$this.find('.dropdown-menu [title]').tipsy({ gravity: 's' });

});

});

HTML

<div class="group1">
<h4>Table showing filter & pager support</h4>
<div class="btn-group">
<button type="button" class="btn btn-default reset">Reset</button> <!-- targeted by the "filter_reset" option -->

<!-- Split button -->
<div class="btn-group">
<button type="button" class="btn btn-default download">Download</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><h5><strong>Output options</strong></h5></li>
<li>
<label>Separator: <input class="output-separator-input" type="text" size="2" value=","></label>
<button type="button" class="output-separator btn btn-default btn-xs active" title="comma">,</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="semi-colon">;</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="tab"> </button>
<button type="button" class="output-separator btn btn-default btn-xs" title="space"> </button>
<button type="button" class="output-separator btn btn-default btn-xs" title="output JSON">json</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="output Array (see note)">array</button>
</li>
<li>
<div class="btn-group output-download-popup" data-toggle="buttons" title="Download file or open in Popup window">
<label class="btn btn-default btn-sm active">
<input type="radio" name="delivery1" class="output-popup" checked=""> Popup
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="delivery1" class="output-download"> Download
</label>
</div>
</li>
<li>
<div class="btn-group output-filter-all" data-toggle="buttons" title="Output only filtered, visible or all rows">
<label class="btn btn-default btn-sm active">
<input type="radio" name="getrows1" class="output-filter" checked="checked"> Filtered
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="getrows1" class="output-visible"> Visible
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="getrows1" class="output-all"> All
</label>
</div>
</li>
<li class="divider"></li>
<li>
<label>Replace quotes: <input class="output-replacequotes" type="text" size="2" value="'"></label>
<button type="button" class="output-quotes btn btn-default btn-xs active" title="single quote">'</button>
<button type="button" class="output-quotes btn btn-default btn-xs" title="left double quote"></button>
<button type="button" class="output-quotes btn btn-default btn-xs" title="escaped quote">\"</button>
</li>
<li><label title="Remove extra white space from each cell">Trim spaces: <input class="output-trim" type="checkbox" checked=""></label></li>
<li><label title="Include HTML from cells in output">Include HTML: <input class="output-html" type="checkbox"></label></li>
<li><label title="Wrap all values in quotes">Wrap in Quotes: <input class="output-wrap" type="checkbox"></label></li>
<li><label title="Choose a download filename">Filename: <input class="output-filename" type="text" size="15" value="mytable.csv"></label></li>
</ul>
</div>
</div>

<div class="ts-pager form-horizontal">
<button type="button" class="btn btn-default btn-sm first"><i class="icon-step-backward glyphicon glyphicon-step-backward"></i></button>
<button type="button" class="btn btn-default btn-sm prev"><i class="icon-arrow-left glyphicon glyphicon-backward"></i></button>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<button type="button" class="btn btn-default btn-sm next"><i class="icon-arrow-right glyphicon glyphicon-forward"></i></button>
<button type="button" class="btn btn-default btn-sm last"><i class="icon-step-forward glyphicon glyphicon-step-forward"></i></button>
<select class="pagesize form-control btn-sm" title="Select page size">
<option selected="selected" value="5">5</option>
<option value="10">10</option>
</select>
<select class="gotoPage form-control btn-sm" title="Select page number"></select>
</div>

<table id="table" class="tablesorter">
<thead>
<tr>
<th>Rank</th>
<th data-name="First">First Name</th>
<th data-name="Last">Last Name</th>
<th>Age</th>
<th>Total</th>
<th>Discount</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>Philip Aaron Wong</td><td>Johnson Sr Esq</td><td>25</td><td>$5.95</td><td>22%</td><td>Jun 26, 2004 7:22 AM</td></tr>
<tr><td>11</td><td>Aaron</td><td>"doc" Hibert</td><td>12</td><td>$2.99</td><td>5%</td><td>Aug 21, 2009 12:21 PM</td></tr>
<tr><td>12</td><td>Brandon Clark</td><td>Henry Jr</td><td>51</td><td>$42.29</td><td>18%</td><td>Oct 13, 2000 1:15 PM</td></tr>
<tr><td>111</td><td>Peter</td><td>Parker</td><td>28</td><td>$9.99</td><td>20%</td><td>Jul 6, 2006 8:14 AM</td></tr>
<tr><td>21</td><td><span class="red">John</span></td><td> "Robin"<br> Hood </td><td>33</td><td>$19.99</td><td>25%</td><td>Dec 10, 2002 5:14 AM</td></tr>
<tr><td>013</td><td>Clark</td><td>"Old man" Kent Sr.</td><td>18</td><td>$15.89</td><td>44%</td><td>Jan 12, 2003 11:14 AM</td></tr>
<tr><td>005</td><td>Bruce</td><td>Almighty <span class="red">Esq</span></td><td>45</td><td>$153.19</td><td>44%</td><td>Jan 18, 2021 9:12 AM</td></tr>
<tr><td>10</td><td>Alex</td><td>Dumass</td><td>13</td><td>$5.29</td><td>4%</td><td>Jan 8, 2012 5:11 PM</td></tr>
<tr><td>16</td><td>Jim</td><td>"Jimmy" Franco</td><td>24</td><td><span class="red">-$14.19</span></td><td>24%</td><td>Jan 14, 2004 11:23 AM</td></tr>
<tr><td>166</td><td>Bruce Lee</td><td>Evans</td><td>22</td><td>$13.19</td><td>11%</td><td>Jan 18, 2007 9:12 AM</td></tr>
<tr><td>100</td><td>Brenda Dexter</td><td>McMasters</td><td>18</td><td>$55.20</td><td>15%</td><td>Feb 12, 2010 7:23 PM</td></tr>
<tr><td>55</td><td>Dennis</td><td><span class="red">"Charley"</span> Bronson</td><td>65</td><td>$123.00</td><td>32%</td><td>Jan 20, 2001 1:12 PM</td></tr>
<tr><td>9</td><td>Martha</td><td>delFuego</td><td>25</td><td>$22.09</td><td>12%</td><td>Jun 11, 2011 10:55 AM</td></tr>
</tbody>
</table>
</div>

<div class="group2">
<h4>Table showing output widget rowspan & colspan support</h4>
<div class="btn-group">
<button type="button" class="btn btn-default reset">Reset</button> <!-- targeted by the "filter_reset" option -->

<!-- Split button -->
<div class="btn-group">
<button type="button" class="btn btn-default download">Download</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><h5><strong>Output options</strong></h5></li>
<li>
<label>Separator: <input class="output-separator-input" type="text" size="2" value=","></label>
<button type="button" class="output-separator btn btn-default btn-xs active" title="comma">,</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="semi-colon">;</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="tab"> </button>
<button type="button" class="output-separator btn btn-default btn-xs" title="space"> </button>
<button type="button" class="output-separator btn btn-default btn-xs" title="output JSON">json</button>
<button type="button" class="output-separator btn btn-default btn-xs" title="output Array (see note)">array</button>
</li>
<li>
<div class="btn-group output-download-popup" data-toggle="buttons" title="Download file or open in Popup window">
<label class="btn btn-default btn-sm active">
<input type="radio" name="delivery2" class="output-popup" checked=""> Popup
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="delivery2" class="output-download"> Download
</label>
</div>
</li>
<li>
<div class="btn-group output-filter-all" data-toggle="buttons" title="Output only filtered, visible or all rows">
<label class="btn btn-default btn-sm active">
<input type="radio" name="getrows2" class="output-filter" checked=""> Filtered
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="getrows2" class="output-visible"> Visible
</label>
<label class="btn btn-default btn-sm">
<input type="radio" name="getrows2" class="output-all"> All
</label>
</div>
</li>
<li class="divider"></li>
<li>
<label>Replace quotes: <input class="output-replacequotes" type="text" size="2" value="'"></label>
<button type="button" class="output-quotes btn btn-default btn-xs active" title="single quote">'</button>
<button type="button" class="output-quotes btn btn-default btn-xs" title="left double quote"></button>
<button type="button" class="output-quotes btn btn-default btn-xs" title="escaped quote">\"</button>
</li>
<li><label title="Remove extra white space from each cell">Trim spaces: <input class="output-trim" type="checkbox" checked=""></label></li>
<li><label title="Include HTML from cells in output">Include HTML: <input class="output-html" type="checkbox"></label></li>
<li><label title="Wrap all values in quotes">Wrap in Quotes: <input class="output-wrap" type="checkbox"></label></li>
<li><label title="Include both header rows in output">Include both header rows: <input class="output-headers" type="checkbox" checked=""></label></li>
<li><label title="Choose a download filename">Filename: <input class="output-filename" type="text" size="15" value="mytable.csv"></label></li>
</ul>
</div>

</div>

<table id="table2">
<thead>
<tr>
<th rowspan="2">line</th>
<th colspan="3">values</th>
</tr>
<tr>
<th>value1</th>
<th>value2</th>
<th>value3</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>1.1</td>
<td>1.2</td>
<td><span class="red">1.3</span></td>
</tr>
<tr class="tablesorter-childRow">
<td>1.4</td>
<td colspan="2">1.5</td>
</tr>
<tr>
<td rowspan="2">2</td>
<td>2.1</td>
<td><span class="red">2.2</span></td>
<td>2.3</td>
</tr>
<tr class="tablesorter-childRow">
<td>2.4</td>
<td colspan="2">2.5</td>
</tr>
<tr>
<td rowspan="2">3</td>
<td>3.1</td>
<td>3.2</td>
<td>3.3</td>
</tr>
<tr class="tablesorter-childRow">
<td>3.4</td>
<td colspan="2"><span class="red">3.5</span></td>
</tr>
<tr>
<td rowspan="2">4</td>
<td rowspan="2" colspan="2"><span class="red">4.1</span></td>
<td>4.2</td>
</tr>
<tr class="tablesorter-childRow">
<td>4.3</td>
</tr>
</tbody>
</table>
</div>