Skip to content

Commit

Permalink
Core: refer filter_functions & filter_selectSource by header class/id…
Browse files Browse the repository at this point in the history
…. See #237.
  • Loading branch information
Mottie committed May 22, 2014
1 parent acbf44d commit e006571
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 78 deletions.
9 changes: 5 additions & 4 deletions docs/example-widget-filter-custom.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

// Add select menu to this column
// set the column value to true, and/or add "filter-select" class name to header
// 0 : true,
// '.first-name' : true,

// Exact match only
1 : function(e, n, f, i, $r) {
Expand Down Expand Up @@ -158,6 +158,7 @@ <h3>Flexible client-side table sorting</h3>
<h3><a href="#">Notes</a></h3>
<div>
<ul>
<li>In <span class="version updated">v2.16.5</span>, the <code>filter_functions</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).</li>
<li>In <span class="version">v2.16.3</span>,
<ul>
<li>When a default filter select is added to a column, it is now parsed from the assigned parser, then sorted using the <code>textSorter</code> setting, and falls back to an alphanumeric sort.</li>
Expand All @@ -180,7 +181,7 @@ <h3><a href="#"><strong>Default Select</strong></a> <span class="xsmall">(&quot;

// Add select menu to this column
// set the column value to true, and/or add &quot;filter-select&quot; class name to header
0 : true
'.first-name' : true

}</pre>or add a &quot;filter-select&quot; class to the column header cell (see code below).</li>
<li>The default option text, &quot;Select a name&quot;, is obtained from the header <code>data-placeholder</code> attribute of the column header cell. And when active, it will show all table rows.<pre class="prettyprint lang-html">&lt;th class=&quot;filter-select&quot; data-placeholder=&quot;Select a name&quot;&gt;First Name&lt;/th&gt;</pre></li>
Expand Down Expand Up @@ -291,9 +292,9 @@ <h1>Demo</h1>
<div id="demo"><table class="tablesorter">
<thead>
<tr>
<!-- add "filter-select" class or filter_functions : { 0: true } -->
<!-- add "filter-select" class or filter_functions : { '.first-name' : true } -->
<!-- add "filter-match" class to just match the content, so selecting "Denni" will also show "Dennis" -->
<th class="filter-select" data-placeholder="Select a name">First Name</th>
<th class="first-name filter-select" data-placeholder="Select a name">First Name</th>
<th data-placeholder="Exact matches only">Last Name</th>
<th data-placeholder="Choose a city">City</th>
<th data-value="<30">Age</th>
Expand Down
23 changes: 12 additions & 11 deletions docs/example-widget-filter-formatter-1.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@
// add custom selector elements to the filter row
filter_formatter : {

// Rank
0 : function($cell, indx){
// Rank (jQuery selector added v2.16.5)
'th:contains("Rank")' : function($cell, indx){
return $.tablesorter.filterFormatter.uiSlider( $cell, indx, {
delayed : true,
valueToHeader : false,
Expand Down Expand Up @@ -104,8 +104,8 @@
});
},

// Total
2 : function($cell, indx){
// Total (jQuery selector added v2.16.5)
'.total' : function($cell, indx){
return $.tablesorter.filterFormatter.uiRange( $cell, indx, {
delayed : false,
valueToHeader : false,
Expand Down Expand Up @@ -184,8 +184,9 @@ <h3>Flexible client-side table sorting</h3>
<h3><a href="#">Notes</a></h3>
<div>
<ul>
<li>In version <span class="version">v2.16.0</span>, the <code>filter_placeholder</code> option was added. See the jQuery UI Datepicker Range Selector section for more details.</li>
<li>In version <span class="version">v2.15.0</span>, the following changes were made:
<li>In <span class="version updated">v2.16.5</span>, the <code>filter_formatter</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).</li>
<li>In <span class="version">v2.16.0</span>, the <code>filter_placeholder</code> option was added. See the jQuery UI Datepicker Range Selector section for more details.</li>
<li>In <span class="version">v2.15.0</span>, the following changes were made:
<ul>
<li>These updated filter widget functions are not completely backward compatible with older versions of the filter widget. Please update both!</li>
<li>Added <code>compare</code> &amp; <code>selected</code> options:
Expand Down Expand Up @@ -259,8 +260,8 @@ <h3><a href="#"><strong>jQuery UI Single Slider</strong></a> <span class="xsmall
// add custom selector elements to the filter row
filter_formatter : {

// Rank
0 : function($cell, indx){
// Rank (jQuery selector added v2.16.5)
'th:contains("Rank")' : function($cell, indx){
return $.tablesorter.filterFormatter.uiSlider( $cell, indx, {
// filterFormatter options
cellText : 'Rank:',
Expand Down Expand Up @@ -327,8 +328,8 @@ <h3><a href="#"><strong>jQuery UI Range Slider</strong></a> <span class="xsmall"
// add custom selector elements to the filter row
filter_formatter : {

// Total column
2 : function($cell, indx){
// Total column (jQuery selector added v2.16.5)
'.total' : function($cell, indx){
return $.tablesorter.filterFormatter.uiRange( $cell, indx, {
delayed: true, // delay search (set by filter_searchDelay)
valueToHeader: false, // add current slider value to the header cell
Expand Down Expand Up @@ -566,7 +567,7 @@ <h1>Demo</h1>
<tr>
<th>Rank</th>
<th>Age</th>
<th>Total (range)</th>
<th class="total">Total (range)</th>
<th>Discount</th>
<th data-placeholder="Try 1/18/2013">Date (one input)</th>
<th>Date (two inputs; range)</th>
Expand Down
1 change: 1 addition & 0 deletions docs/example-widget-filter-formatter-2.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ <h3>Flexible client-side table sorting</h3>
<h3><a href="#">Notes</a></h3>
<div>
<ul>
<li>In <span class="version updated">v2.16.5</span>, the <code>filter_formatter</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).</li>
<li>As of tablesorter version 2.9+, this widget can no longer be applied to versions of tablesorter prior to version 2.8.</li>
<li>At this time, these widgets do not work with the sticky header widget.</li>
<li>This page shows you how to add a few default <strong>HTML5 elements</strong> to interact with the filter widget.</li>
Expand Down
16 changes: 12 additions & 4 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2012,9 +2012,11 @@ <h1>Widget &amp; Pager Options</h1>
<td>Object</td>
<td>null</td>
<td>
Filter widget: This option allows you to add custom controls within the filter widget row (v2.7.7).<br>
Filter widget: This option allows you to add custom controls within the filter widget row (v2.7.7; <span class="version updated">v2.16.5</span>).<br>
<div class="collapsible">
<br>
In <span class="version updated">v2.16.5</span>, the <code>filter_formatter</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).<br>
<br>
A new file has been included named "jquery.tablesorter.widgets-filter-formatter.js". It includes code to add jQuery UI and HTML5 controls via the <a href="#widget-filter-formatter"><code>filter_formatter</code></a> option.<br>
<br>
Most of the formatter functions have an option named <code>valueToHeader</code> which, when <code>true</code> adds a span to the header cell above the filter row and updates it with the current control's value (see <a href="example-widget-filter-formatter-2.html">example 2</a>). If the option exists and is set to <code>false</code>, then the current value is added to the control's handle and css can be used to create a popup to show the current value (see <a href="example-widget-filter-formatter-1.html">example 1</a>).<br>
Expand All @@ -2030,8 +2032,9 @@ <h1>Widget &amp; Pager Options</h1>
widgets: ["filter"],
widgetOptions : {
filter_formatter : {
// column index `0` or use a jQuery selector `"th:contains('Discount')"`
0 : function($cell, indx){
return $.tablesorter.filterFormatter.<strong>uiSpinner</strong>( $cell, indx, {
return $.tablesorter.filterFormatter.uiSpinner( $cell, indx, {
value : 0, // starting value
min : 0, // minimum value
max : 50, // maximum value
Expand Down Expand Up @@ -2064,8 +2067,11 @@ <h1>Widget &amp; Pager Options</h1>
<td>Object</td>
<td>null</td>
<td>
Filter widget: Customize the filter widget by adding a select dropdown with content, custom options or custom filter functions (v2.3.6).
Filter widget: Customize the filter widget by adding a select dropdown with content, custom options or custom filter functions (v2.3.6; <span class="version updated">v2.16.5</span>).
<div class="collapsible">
<br>
In <span class="version updated">v2.16.5</span>, the <code>filter_functions</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).<br>
<br>
Use the <a href="#widget-filter-functions"><code>&quot;filter_functions&quot;</code></a> option in three different ways:
<br>
<ul>
Expand Down Expand Up @@ -2376,9 +2382,11 @@ <h4>Comparison example</h4>
<td>Function</td>
<td>null</td>
<td>
Filter widget: Include a function to return an array of values to be added to the column filter select (<span class="version">v2.16.0</span>).
Filter widget: Include a function to return an array of values to be added to the column filter select (<span class="version">v2.16.0</span>; <span class="version updated">v2.16.5</span>).
<div class="collapsible">
<br>
In <span class="version updated">v2.16.5</span>, the <code>filter_selectSource</code> column can also be referenced by using a jQuery selector (e.g. class name or ID).<br>
<br>
A column will have a filter select dropdown when a "filter-select" class name is added to the header cell, or if the <a href="#widget-filter-functions"><code>filter_functions</code></a> column value is set to <code>true</code><br>
<br>
This option allows using an alternate source, or customizing options of the filter select dropdown. This option can be set as follows:
Expand Down
70 changes: 33 additions & 37 deletions js/jquery.tablesorter.widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ ts.filter = {
and : 'and'
}, ts.language);

var options, string, $header, column, filters, time,
var options, string, $header, column, filters, time, fxn,
regex = ts.filter.regex;
if (c.debug) {
time = new Date();
Expand Down Expand Up @@ -622,16 +622,16 @@ ts.filter = {
}
}
if (wo.filter_functions) {
// column = column # (string)
for (column in wo.filter_functions) {
if (wo.filter_functions.hasOwnProperty(column) && typeof column === 'string') {
for (column = 0; column < c.columns; column++) {
fxn = ts.getColumnData( table, wo.filter_functions, column );
if (fxn) {
$header = c.$headers.filter('[data-column="' + column + '"]:last');
options = '';
if (wo.filter_functions[column] === true && !$header.hasClass('filter-false')) {
if (fxn === true && !$header.hasClass('filter-false')) {
ts.filter.buildSelect(table, column);
} else if (typeof column === 'string' && !$header.hasClass('filter-false')) {
} else if (typeof fxn === 'object' && !$header.hasClass('filter-false')) {
// add custom drop down list
for (string in wo.filter_functions[column]) {
for (string in fxn) {
if (typeof string === 'string') {
options += options === '' ?
'<option value="">' + ($header.data('placeholder') || $header.attr('data-placeholder') || wo.filter_placeholder.select || '') + '</option>' : '';
Expand Down Expand Up @@ -703,7 +703,7 @@ ts.filter = {
return filters;
},
buildRow: function(table, c, wo) {
var column, $header, buildSelect, disabled, name,
var column, $header, buildSelect, disabled, name, ffxn,
// c.columns defined in computeThIndexes()
columns = c.columns,
buildFilter = '<tr class="' + ts.css.filterRow + '">';
Expand All @@ -716,21 +716,18 @@ ts.filter = {
disabled = false;
// assuming last cell of a column is the main column
$header = c.$headers.filter('[data-column="' + column + '"]:last');
buildSelect = (wo.filter_functions && wo.filter_functions[column] && typeof wo.filter_functions[column] !== 'function') ||
ffxn = ts.getColumnData( table, wo.filter_functions, column );
buildSelect = (wo.filter_functions && ffxn && typeof ffxn !== "function" ) ||
$header.hasClass('filter-select');
if (ts.getData) {
// get data from jQuery data, metadata, headers option or header class name
disabled = ts.getData($header[0], ts.getColumnData( table, column ), 'filter') === 'false';
} else {
// only class names and header options - keep this for compatibility with tablesorter v2.0.5
disabled = (c.headers[column] && c.headers[column].hasOwnProperty('filter') && c.headers[column].filter === false) ||
$header.hasClass('filter-false');
}
// get data from jQuery data, metadata, headers option or header class name
disabled = ts.getData($header[0], ts.getColumnData( table, c.headers, column ), 'filter') === 'false';

if (buildSelect) {
buildFilter = $('<select>').appendTo( c.$filters.eq(column) );
} else {
if (wo.filter_formatter && $.isFunction(wo.filter_formatter[column])) {
buildFilter = wo.filter_formatter[column]( c.$filters.eq(column), column );
ffxn = ts.getColumnData( table, wo.filter_formatter, column );
if (ffxn) {
buildFilter = ffxn( c.$filters.eq(column), column );
// no element returned, so lets go find it
if (buildFilter && buildFilter.length === 0) {
buildFilter = c.$filters.eq(column).children('input');
Expand Down Expand Up @@ -793,8 +790,8 @@ ts.filter = {
( event.which >= 37 && event.which <= 40 ) || (event.which !== 13 && wo.filter_liveSearch === false) ) ) ) {
return;
}
// true flag tells getFilters to skip newest timed input
ts.filter.searching( table, true, true );
// change event = no delay; last true flag tells getFilters to skip newest timed input
ts.filter.searching( table, event.type !== 'change', true );
})
.bind('keypress.' + c.namespace + 'filter', function(event){
if (event.which === 13) {
Expand Down Expand Up @@ -885,7 +882,7 @@ ts.filter = {
var cached, len, $rows, rowIndex, tbodyIndex, $tbody, $cells, columnIndex,
childRow, childRowText, exact, iExact, iFilter, lastSearch, matches, result,
notFiltered, searchFiltered, filterMatched, showRow, time, val, indx,
anyMatch, iAnyMatch, rowArray, rowText, iRowText, rowCache,
anyMatch, iAnyMatch, rowArray, rowText, iRowText, rowCache, fxn,
regex = ts.filter.regex,
c = table.config,
wo = c.widgetOptions,
Expand Down Expand Up @@ -931,7 +928,7 @@ ts.filter = {
// don't search only filtered if the value is negative ('> -10' => '> -100' will ignore hidden rows)
!(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
// if filtering using a select without a "filter-match" class (exact match) - fixes #593
!( val !== '' && wo.filter_functions && wo.filter_functions[indx] === true && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
!( val !== '' && c.$filters.eq(indx).find('select').length && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
}
notFiltered = $rows.not('.' + wo.filter_filteredRow).length;
// can't search when all rows are hidden - this happens when looking for exact matches
Expand Down Expand Up @@ -1014,17 +1011,18 @@ ts.filter = {
filters[columnIndex] = c.sortLocaleCompare ? ts.replaceAccents(filters[columnIndex]) : filters[columnIndex];
// val = case insensitive, filters[columnIndex] = case sensitive
iFilter = wo.filter_ignoreCase ? (filters[columnIndex] || '').toLocaleLowerCase() : filters[columnIndex];
if (wo.filter_functions && wo.filter_functions[columnIndex]) {
if (wo.filter_functions[columnIndex] === true) {
fxn = ts.getColumnData( table, wo.filter_functions, columnIndex );
if (fxn) {
if (fxn === true) {
// default selector; no "filter-select" class
result = (c.$headers.filter('[data-column="' + columnIndex + '"]:last').hasClass('filter-match')) ?
iExact.search(iFilter) >= 0 : filters[columnIndex] === exact;
} else if (typeof wo.filter_functions[columnIndex] === 'function') {
} else if (typeof fxn === 'function') {
// filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object )
result = wo.filter_functions[columnIndex](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
} else if (typeof wo.filter_functions[columnIndex][filters[columnIndex]] === 'function') {
result = fxn(exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
} else if (typeof fxn[filters[columnIndex]] === 'function') {
// selector option function
result = wo.filter_functions[columnIndex][filters[columnIndex]](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
result = fxn[filters[columnIndex]](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
}
} else {
filterMatched = null;
Expand Down Expand Up @@ -1078,15 +1076,16 @@ ts.filter = {
wo = c.widgetOptions,
parsed = [],
arry = false,
source = wo.filter_selectSource;
source = wo.filter_selectSource,
fxn = $.isFunction(source) ? true : ts.getColumnData( table, source, column );

// filter select source option
if ($.isFunction(source)) {
if (fxn === true) {
// OVERALL source
arry = source(table, column, onlyAvail);
} else if ($.type(source) === 'object' && source.hasOwnProperty(column)) {
} else if ($.type(source) === 'object' && fxn) {
// custom select source function for a SPECIFIC COLUMN
arry = source[column](table, column, onlyAvail);
arry = fxn(table, column, onlyAvail);
}
if (arry === false) {
// fall back to original method
Expand Down Expand Up @@ -1203,10 +1202,7 @@ ts.filter = {
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
$header = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
// look for the filter-select class; build/update it if found
if (($header.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[columnIndex] === true) &&
!$header.hasClass('filter-false')) {
if (!wo.filter_functions) { wo.filter_functions = {}; }
wo.filter_functions[columnIndex] = true; // make sure this select gets processed by filter_functions
if (($header.hasClass('filter-select') || ts.getColumnData( table, wo.filter_functions, columnIndex ) === true) && !$header.hasClass('filter-false')) {
ts.filter.buildSelect(table, columnIndex, updating, $header.hasClass(wo.filter_onlyAvail));
}
}
Expand Down
Loading

0 comments on commit e006571

Please sign in to comment.