added filter_onlyAvail option; fixes #292

This commit is contained in:
Mottie 2013-05-12 17:32:39 -05:00
parent 8910283581
commit fc9a64e693
4 changed files with 88 additions and 42 deletions

View File

@ -165,24 +165,25 @@
</ul>
</div>
<h3><a href="#"><strong>Default Select</strong> ("First Name" column)</a></h3>
<h3><a href="#"><strong>Default Select</strong> (&quot;First Name&quot; column)</a></h3>
<div>
<ul>
<li>To enable this type of select, set the <code>filter_functions</code> option for the column to <code>true</code>,<pre class="prettyprint lang-javascript">filter_functions : {
// Add select menu to this column
// set the column value to true, and/or add "filter-select" class name to header
// set the column value to true, and/or add &quot;filter-select&quot; class name to header
0 : true
}</pre>or add a "filter-select" class to the column header cell (see code below).</li>
<li>The default option text, "Select a name", 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>
<li>Add a "filter-match" class to only match instead of exactly match the selected value. Click on the "Match" button below to see the difference.<pre class="prettyprint lang-html">&lt;th class=&quot;filter-select filter-match&quot; data-placeholder=&quot;Select a name&quot;&gt;First Name&lt;/th&gt;</pre></li>
<li>The select is populated by the column text contents with repeated content combined (i.e. There are three "Aaron"'s in the first column, but only one in the dropdown.</li>
}</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>
<li>Add a &quot;filter-match&quot; class to only match instead of exactly match the selected value. Click on the &quot;Match&quot; button below to see the difference.<pre class="prettyprint lang-html">&lt;th class=&quot;filter-select filter-match&quot; data-placeholder=&quot;Select a name&quot;&gt;First Name&lt;/th&gt;</pre></li>
<li>The select is populated by the column text contents with repeated content combined (i.e. There are three &quot;Aaron&quot;'s in the first column, but only one in the dropdown.</li>
<li>Select options are automatically alphanumerically (new in v2.4) sorted.</li>
<li>Please check out what the &quot;filter-onlyAvail&quot; class name does by reviewing the details below (in the &quot;Discount&quot; column) (<span class="version">v2.10.1</span>).</li>
</ul>
</div>
<h3><a href="#"><strong>Custom Filter Function</strong> ("Last Name" column)</a></h3>
<h3><a href="#"><strong>Custom Filter Function</strong> (&quot;Last Name&quot; column)</a></h3>
<div>
<ul>
<li>To enable this type of filter, add your custom function to the <code>filter_functions</code> option following this example:<pre class="prettyprint lang-javascript">filter_functions : {
@ -194,27 +195,27 @@
}</pre></li>
<li>The example shows you how to show only exact matches. The problem with this is that you can't see the matches while typing unless you set the <code>filter_searchDelay</code> option to be a bit longer.</li>
<li>Also, the example only checks for an exact match (<code>===</code>) meaning the <code>filter_ignoreCase</code> option is ignored, but other comparisons can be made using regex and the insensitive "i" flag.</li>
<li>Also, the example only checks for an exact match (<code>===</code>) meaning the <code>filter_ignoreCase</code> option is ignored, but other comparisons can be made using regex and the insensitive &quot;i&quot; flag.</li>
<li>See the filter function information below.</li>
</ul>
</div>
<h3><a href="#"><strong>Custom Select</strong> ("City" or "Total" column)</a></h3>
<h3><a href="#"><strong>Custom Select</strong> (&quot;City&quot; or &quot;Total&quot; column)</a></h3>
<div>
<ul>
<li>To enable this type of select, add your custom options within the <code>filter_functions</code> option.</li>
<li>Each option is set as a "key:value" pair where the "key" is the actual text of the option and the "value" is the function associated with the option.</li>
<li>Each option is set as a &quot;key:value&quot; pair where the &quot;key&quot; is the actual text of the option and the &quot;value&quot; is the function associated with the option.</li>
<li>Here is an example using alphabetical comparisons (using regular expressions):<pre class="prettyprint lang-javascript">filter_functions : {
// Add these options to the select dropdown (regex example)
2 : {
"A - D" : function(e, n, f, i) { return /^[A-D]/.test(e); },
"E - H" : function(e, n, f, i) { return /^[E-H]/.test(e); },
"I - L" : function(e, n, f, i) { return /^[I-L]/.test(e); },
"M - P" : function(e, n, f, i) { return /^[M-P]/.test(e); },
"Q - T" : function(e, n, f, i) { return /^[Q-T]/.test(e); },
"U - X" : function(e, n, f, i) { return /^[U-X]/.test(e); },
"Y - Z" : function(e, n, f, i) { return /^[Y-Z]/.test(e); }
&quot;A - D&quot; : function(e, n, f, i) { return /^[A-D]/.test(e); },
&quot;E - H&quot; : function(e, n, f, i) { return /^[E-H]/.test(e); },
&quot;I - L&quot; : function(e, n, f, i) { return /^[I-L]/.test(e); },
&quot;M - P&quot; : function(e, n, f, i) { return /^[M-P]/.test(e); },
&quot;Q - T&quot; : function(e, n, f, i) { return /^[Q-T]/.test(e); },
&quot;U - X&quot; : function(e, n, f, i) { return /^[U-X]/.test(e); },
&quot;Y - Z&quot; : function(e, n, f, i) { return /^[Y-Z]/.test(e); }
}
}</pre></li>
@ -223,12 +224,29 @@
// Note that only the normalized (n) value will contain numerical data
// If you use the exact text, you'll need to parse it (parseFloat or parseInt)
4 : {
"< $10" : function(e, n, f, i) { return n < 10; },
"$10 - $100" : function(e, n, f, i) { return n >= 10 && n <=100; },
"> $100" : function(e, n, f, i) { return n > 100; }
&quot;< $10&quot; : function(e, n, f, i) { return n < 10; },
&quot;$10 - $100&quot; : function(e, n, f, i) { return n >= 10 && n <=100; },
&quot;> $100&quot; : function(e, n, f, i) { return n > 100; }
}
}</pre></li>
<li>See the "Filter function information" section below.</li>
<li>See the &quot;Filter function information&quot; section below.</li>
</ul>
</div>
<h3><a href="#"><strong>Default Select showing only available options (&quot;Discount&quot; column)</strong></a></h3>
<div>
<ul>
<li>This column uses the same method as the &quot;First Name&quot; column with one exception, it also includes the &quot;filter-onlyAvail&quot; class name in the header
cell:<pre class="prettyprint lang-html">&lt;th class=&quot;filter-select filter-onlyAvail&quot;&gt;Discount&lt;/th&gt;</pre></li>
<li>To see how this works, do the following:
<ul>
<li>First, filter the &quot;First Name&quot; column by selecting the name &quot;Clark&quot;</li>
<li>Now use the &quot;Discount&quot; filter select box, you'll notice that only the values associated with the first name of Clark are showing as options.</li>
</ul>
</li>
<li>Conversely, if you reset the filters, select &quot;44%&quot; in the &quot;Discount&quot; column, then look at the &quot;First Name&quot; filter selector, you'll notice that it still contains all of the original options; because the &quot;filter-onlyAvail&quot; class name is not included in that column's header cell.</li>
<li>Sorry, this only functionalirt only works for default select filters.</li>
<li>This funcitonality was added in <span class="version">v2.10.1</span>.</li>
</ul>
</div>
@ -253,7 +271,7 @@
</div>
<h1>Demo</h1>
<button class="match" data-filter-column="0" data-filter-text="Denni">Match</button> <span id="mode">false</span> (toggle "filter-match" class on First Name column)<br>
<button class="match" data-filter-column="0" data-filter-text="Denni">Match</button> <span id="mode">false</span> (toggle &quot;filter-match&quot; class on First Name column)<br>
<button class="reset">Reset Search</button>
<div id="demo"><table class="tablesorter">
@ -266,7 +284,7 @@
<th data-placeholder="Choose a city">City</th>
<th>Age</th>
<th data-placeholder="Select a filter">Total</th>
<th>Discount</th>
<th class="filter-select filter-onlyAvail">Discount</th>
<th>Date</th>
</tr>
</thead>

View File

@ -182,16 +182,16 @@ $(function(){
<table class="tablesorter-blue">
<thead><tr><th>Type <small class="bright">(1)</small></th><td>Description</th><th>Example</th></tr></thead>
<tbody>
<tr><td class="center">text</td><td>Any text entered in the filter will <strong>match</strong> text found within the column</td><td><code>abc</code> (finds "abc", "abcd", "abcde", etc)</td></tr>
<tr><td class="center"><code>"</code></td><td>To exactly match the search query, add a quote, apostrophe or equal sign to the beginning and/or end of the query</td><td><code>abc"</code> or <code>abc=</code> (exactly match "abc")</td></tr>
<tr><td class="center"><code>?</code></td><td>Wildcard for a single, non-space character.</td><td><code>J?n</code> (finds "Jan" and "Jun", but not "Joan")</td></tr>
<tr><td class="center"><code>*</code></td><td>Wildcard for zero or more non-space characters.</td><td><code>B*k</code> (matches "Black" and "Book")</td></tr>
<tr><td class="center"><code>/\d/</code></td><td>Add any regex to the query to use in the query</td><td><code>/b[aeiou]g/i</code> (finds "bag", "beg", "BIG", "Bug", etc)</td></tr>
<tr><td class="center">text</td><td>Any text entered in the filter will <strong>match</strong> text found within the column</td><td><code>abc</code> (finds &quot;abc&quot;, &quot;abcd&quot;, &quot;abcde&quot;, etc)</td></tr>
<tr><td class="center"><code>&quot;</code></td><td>To exactly match the search query, add a quote, apostrophe or equal sign to the beginning and/or end of the query</td><td><code>abc&quot;</code> or <code>abc=</code> (exactly match &quot;abc&quot;)</td></tr>
<tr><td class="center"><code>?</code></td><td>Wildcard for a single, non-space character.</td><td><code>J?n</code> (finds &quot;Jan&quot; and &quot;Jun&quot;, but not &quot;Joan&quot;)</td></tr>
<tr><td class="center"><code>*</code></td><td>Wildcard for zero or more non-space characters.</td><td><code>B*k</code> (matches &quot;Black&quot; and &quot;Book&quot;)</td></tr>
<tr><td class="center"><code>/\d/</code></td><td>Add any regex to the query to use in the query</td><td><code>/b[aeiou]g/i</code> (finds &quot;bag&quot;, &quot;beg&quot;, &quot;BIG&quot;, &quot;Bug&quot;, etc)</td></tr>
<tr><td class="center"><code>&lt; &lt;= &gt;= &gt;</code></td><td>Find alphabetical or numerical values less than or greater than or equal to the filtered query <small class="bright">(2)</small></td><td><code>&gt;= 10</code> (find values greater than or equal to 10)</td></tr>
<tr><td class="center"><code>!</code></td><td>Not operator. Filter the column with content that <strong>do not</strong> match the query.</td><td><code>!fe</code> (hide rows with "female" in that column, but shows rows with "male")</td></tr>
<tr><td class="center"><code>&nbsp;&&&nbsp;</code> or <code>&nbsp;AND&nbsp;</code></td><td>Logical "and". Filter the column for content that matches text from either side of the operator.</td><td><code>box && bat</code> (matches a column cell that contains both "box" and "bat")</td></tr>
<tr><td class="center"><code>|</code> or <code>&nbsp;OR&nbsp;</code></td><td>Logical "or" (Vertical bar). Filter the column for content that matches text from either side of the bar.</td><td><code>box|bat</code> (matches a column cell with either "box" or "bat")</td></tr>
<tr><td class="center"><code>&nbsp;-&nbsp;</code> or <code>&nbsp;to&nbsp;</code></td><td>Find a range of values. Make sure there is a space before and after the dash (or the word "to") <small class="bright">(2)</small>.</td><td><code>10 - 30</code> or <code>10 to 30</code> (match values between 10 and 30)</td></tr>
<tr><td class="center"><code>!</code></td><td>Not operator. Filter the column with content that <strong>do not</strong> match the query.</td><td><code>!fe</code> (hide rows with &quot;female&quot; in that column, but shows rows with &quot;male&quot;)</td></tr>
<tr><td class="center"><code>&nbsp;&&&nbsp;</code> or <code>&nbsp;AND&nbsp;</code></td><td>Logical &quot;and&quot;. Filter the column for content that matches text from either side of the operator.</td><td><code>box && bat</code> (matches a column cell that contains both &quot;box&quot; and &quot;bat&quot;)</td></tr>
<tr><td class="center"><code>|</code> or <code>&nbsp;OR&nbsp;</code></td><td>Logical &quot;or&quot; (Vertical bar). Filter the column for content that matches text from either side of the bar.</td><td><code>box|bat</code> (matches a column cell with either &quot;box&quot; or &quot;bat&quot;)</td></tr>
<tr><td class="center"><code>&nbsp;-&nbsp;</code> or <code>&nbsp;to&nbsp;</code></td><td>Find a range of values. Make sure there is a space before and after the dash (or the word &quot;to&quot;) <small class="bright">(2)</small>.</td><td><code>10 - 30</code> or <code>10 to 30</code> (match values between 10 and 30)</td></tr>
</tbody>
</table>
<span class="bright">(1)</span> You cannot combine these operators with each other (except for the wildcards).<br>
@ -213,9 +213,10 @@ $(function(){
<li><code>filter_hideFilters : false</code> - if true, filters are hidden initially, but can be revealed by clicking on the filter icon.</li>
<li><code>filter_ignoreCase : true</code> - if true, make all searches case-insensitive.</li>
<li><code>filter_liveSearch : true</code> - if true, search column content while the user types (with a delay). If false, the user must press enter to start the search. If set to a number, when the length of the input text reaches this minimum length, a search will initiate.</li>
<li><code>filter_onlyAvail : 'filter-onlyAvail'</code> - a header with a select dropdown &amp; this class name will only show available (visible) options within that drop down.</li>
<li><code>filter_reset : null</code> - jQuery selector string of an element used to reset the filters.</li>
<li><code>filter_searchDelay : 300</code> - typing delay in milliseconds before starting a search.</li>
<li><code>filter_serversideFiltering : false</code> - if true, filter will be done server-side. The client-side filtering will be disabled, but the ui and events will still be used..</li>
<li><code>filter_serversideFiltering : false</code> - if true, filter will be done server-side. The client-side filtering will be disabled, but the ui and events will still be used.</li>
<li><code>filter_startsWith : false</code> - if true, filter start from the beginning of the cell contents.</li>
<li><code>filter_useParsedData : false</code> - filter all data using parsed content.</li>
</ul>
@ -227,8 +228,9 @@ $(function(){
<ul>
<li><code>filter-false</code> - disable the filter for a specific header column.</li>
<li><code>filter-select</code> - build a default select box for a column (shows unique column content). See the <a href="example-widget-filter-custom.html">custom filter widget</a> demo for an example.</li>
<li><code>filter-match</code> - only applies to "filter-select" columns. Makes the select match the column contents instead of exactly matching.</li>
<li><code>filter-match</code> - only applies to &quot;filter-select&quot; columns. Makes the select match the column contents instead of exactly matching.</li>
<li><code>filter-parsed</code> - set a column to filter through parsed data instead of the actual table cell content.</li>
<li><code>filter-onlyAvail</code> - show only available (visible) options within a default select box. See the <a href="example-widget-filter-custom.html">custom filter widget</a> demo &quot;Discount&quot; column for an example.</li>
</ul>
</div>
@ -243,7 +245,7 @@ $(function(){
<h3>search</h3>
<blockquote>
With this method, you can pass an array of filter values:
<pre class="prettyprint lang-javascript">// apply "2?%" filter to the fifth column (zero-based index)
<pre class="prettyprint lang-javascript">// apply &quot;2?%&quot; filter to the fifth column (zero-based index)
var columns = [];
columns[5] = '2?%';
// or define the array this way var columns = [ '', '', '', '', '', '2?%' ]
@ -293,7 +295,7 @@ $.tablesorter.setFilters( $('table'), [ '', '', '', '', '', '2?%' ], true );</pr
<hr>
<div id="demo">
<button class="search" data-filter-column="5" data-filter-text="2?%">Saved Search</button> (search the Discount column for "2?%")<br>
<button class="search" data-filter-column="5" data-filter-text="2?%">Saved Search</button> (search the Discount column for &quot;2?%&quot;)<br>
<button class="reset">Reset Search</button> <!-- targetted by the "filter_reset" option -->
<table class="tablesorter">

View File

@ -1307,6 +1307,8 @@ $(function(){
filter_ignoreCase : true,
// if true, search column content while the user types (with a delay)
filter_liveSearch : true,
// a selector in a header with this class name will only show selected options in the drop down
filter_onlyAvail : 'filter-onlyAvail',
// jQuery selector string of an element used to reset the filters.
filter_reset : null,
// typing delay in milliseconds before starting a search.
@ -1837,6 +1839,20 @@ $(function(){
<td></td>
</tr>
<tr id="widget-filter-onlyAvail">
<td><a href="#" class="toggle2">filter_onlyAvail</a></td>
<td>String</td>
<td>'filter-onlyAvail'</td>
<td>
Filter widget: If a header contains a select dropdown and this class name, only the available (visible) options in the column will show (<span class="version">v2.10.1</span>).
<div class="collapsible">
<br>
This option is useful after one or more columns have been filtered, then the column select filter with this class applied will only show the contents of the column within the dropdown that are currently visible. See the <a href="example-widget-filter-custom.html">custom filter widget</a> demo &quot;Discount&quot; column for an example (sort the &quot;First Name&quot; column first).
</div>
</td>
<td><a href="example-widget-filter-custom.html">Example</a></td>
</tr>
<tr id="widget-filter-reset">
<td><a href="#" class="toggle2">filter_reset</a></td>
<td>String</td>

View File

@ -332,6 +332,7 @@ ts.addWidget({
filter_hideFilters : false, // collapse filter row when mouse leaves the area
filter_ignoreCase : true, // if true, make all searches case-insensitive
filter_liveSearch : true, // if true, search column content while the user types (with a delay)
filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available (visible) options within the drop down
filter_reset : null, // jQuery selector string of an element used to reset the filters
filter_searchDelay : 300, // typing delay in milliseconds before starting a search
filter_startsWith : false, // if true, filter start from the beginning of the cell contents
@ -522,14 +523,16 @@ ts.addWidget({
$t.trigger('applyWidgets'); // make sure zebra widget is applied
$t.trigger('filterEnd');
},
buildSelect = function(i, updating){
var o, arry = [];
buildSelect = function(i, updating, onlyavail){
var o, t, arry = [], currentVal;
i = parseInt(i, 10);
o = '<option value="">' + ($ths.filter('[data-column="' + i + '"]:last').attr('data-placeholder') || '') + '</option>';
for (k = 0; k < b.length; k++ ){
l = c.cache[k].row.length;
// loop through the rows
for (j = 0; j < l; j++){
// check if has class filtered
if (onlyavail && c.cache[k].row[j][0].className.match(wo.filter_filteredRow)) { continue; }
// get non-normalized cell content
if (wo.filter_useParsedData){
arry.push( '' + c.cache[k].normalized[j][i] );
@ -550,10 +553,14 @@ ts.addWidget({
});
arry = (ts.sortText) ? arry.sort(function(a, b){ return ts.sortText(table, a, b, i); }) : arry.sort(true);
// Get curent filter value
currentVal = $t.find('thead').find('select.' + css + '[data-column="' + i + '"]').val();
// build option list
for (k = 0; k < arry.length; k++){
t = arry[k].replace(/\"/g, "&quot;");
// replace quotes - fixes #242 & ignore empty strings - see http://stackoverflow.com/q/14990971/145346
o += arry[k] !== '' ? '<option value="' + arry[k].replace(/\"/g, "&quot;") + '">' + arry[k] + '</option>' : '';
o += arry[k] !== '' ? '<option value="' + t + '"' + (currentVal === t ? ' selected="selected"' : '') +'>' + arry[k] + '</option>' : '';
}
$t.find('thead').find('select.' + css + '[data-column="' + i + '"]')[ updating ? 'html' : 'append' ](o);
},
@ -565,7 +572,7 @@ ts.addWidget({
if ((t.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[i] === true) && !t.hasClass('filter-false')){
if (!wo.filter_functions) { wo.filter_functions = {}; }
wo.filter_functions[i] = true; // make sure this select gets processed by filter_functions
buildSelect(i, updating);
buildSelect(i, updating, t.hasClass(wo.filter_onlyAvail));
}
}
};
@ -622,8 +629,8 @@ ts.addWidget({
}
}
$t
.bind('addRows updateCell update updateRows updateComplete appendCache filterReset search '.split(' ').join('.tsfilter '), function(e, filter){
if (!/(search|filterReset)/.test(e.type)){
.bind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join('.tsfilter '), function(e, filter){
if (!/(search|filterReset|filterEnd)/.test(e.type)){
e.stopPropagation();
buildDefault(true);
}
@ -633,6 +640,9 @@ ts.addWidget({
// send false argument to force a new search; otherwise if the filter hasn't changed, it will return
filter = e.type === 'search' ? filter : e.type === 'updateComplete' ? $t.data('lastSearch') : '';
checkFilters(filter);
if (e.type === 'filterEnd') {
buildDefault(true);
}
return false;
})
.find('input.' + css).bind('keyup search', function(e, filter){