1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery tablesorter 2.0 - Custom Filter Widget Functions</title>
<!-- jQuery -->
<script src="js/jquery-latest.min.js"></script>
<!-- Demo stuff -->
<link class="ui-theme" rel="stylesheet" href="css/jquery-ui.min.css">
<script src="js/jquery-ui.min.js"></script>
<link rel="stylesheet" href="css/jq.css">
<link href="css/prettify.css" rel="stylesheet">
<script src="js/prettify.js"></script>
<script src="js/docs.js"></script>
<!-- Tablesorter: required -->
<link rel="stylesheet" href="../css/theme.blue.css">
<script src="../js/jquery.tablesorter.js"></script>
<script src="../js/widgets/widget-storage.js"></script>
<script src="../js/widgets/widget-filter.js"></script>
<script>
$(function() {
// External search
// buttons set up like this:
// <button type="button" class="search" data-filter-column="4" data-filter-text="2?%">Saved Search</button>
$('button.match').click(function() {
// toggle "filter-match" class on first column
var first = $('table').find('th:first').toggleClass('filter-match');
$('#mode').html( '' + first.hasClass('filter-match') );
/*** first method *** data-filter-column="1" data-filter-text="!son"
add search value to Discount column (zero based index) input */
var filters = $('table').find('.tablesorter-filter'),
col = $(this).data('filter-column'), // zero-based index
txt = $(this).data('filter-text'); // text to add to filter
filters.val(''); // clear all filters
filters.eq(col).val(txt).trigger('search', false);
return false;
});
$('.accordion button[data-filter-column]').click(function() {
var filters = [],
$t = $(this),
col = $t.data('filter-column'), // zero-based index
txt = $t.data('filter-text') || $t.text(); // text to add to filter
filters[col] = txt;
$.tablesorter.setFilters( $('#demo table'), filters, true );
return false;
});
$('button.search-type').click(function() {
var c = $('#demo table')[0].config,
wo = c.widgetOptions,
search = wo.filter_searchFiltered = !wo.filter_searchFiltered;
$('#search-type').html( '' + search );
$.tablesorter.setFilters( c.$table, [ '', 'Evan' ], true );
});
});
</script>
<script id="js">$(function() {
// call the tablesorter plugin
$("table").tablesorter({
theme: 'blue',
// hidden filter input/selects will resize the columns, so try to minimize the change
widthFixed : true,
// initialize zebra striping and filter widgets
widgets: ["zebra", "filter"],
// headers: { 5: { sorter: false, filter: false } },
widgetOptions : {
// extra css class applied to the table row containing the filters & the inputs within that row
filter_cssFilter : '',
// If there are child rows in the table (rows with class name from "cssChildRow" option)
// and this option is true and a match is found anywhere in the child row, then it will make that row
// visible; default is false
filter_childRows : false,
// if true, filters are collapsed initially, but can be revealed by hovering over the grey bar immediately
// below the header row. Additionally, tabbing through the document will open the filter row when an input gets focus
filter_hideFilters : false,
// Set this option to false to make the searches case sensitive
filter_ignoreCase : true,
// jQuery selector string of an element used to reset the filters
filter_reset : '.reset',
// Use the $.tablesorter.storage utility to save the most recent filters
filter_saveFilters : true,
// Delay in milliseconds before the filter widget starts searching; This option prevents searching for
// every character while typing and should make searching large tables faster.
filter_searchDelay : 300,
// Set this option to true to use the filter to find text from the start of the column
// So typing in "a" will find "albert" but not "frank", both have a's; default is false
filter_startsWith : false,
// Add select box to 4th column (zero-based index)
// each option has an associated function that returns a boolean
// function variables:
// e = exact text from cell
// n = normalized value returned by the column parser
// f = search filter input value
// i = column index
filter_functions : {
// Add select menu to this column
// set the column value to true, and/or add "filter-select" class name to header
// '.first-name' : true,
// Exact match only
1 : function(e, n, f, i, $r, c, data) {
return e === f;
},
// Add these options to the select dropdown (regex example)
2 : {
"A - D" : function(e, n, f, i, $r, c, data) { return /^[A-D]/.test(e); },
"E - H" : function(e, n, f, i, $r, c, data) { return /^[E-H]/.test(e); },
"I - L" : function(e, n, f, i, $r, c, data) { return /^[I-L]/.test(e); },
"M - P" : function(e, n, f, i, $r, c, data) { return /^[M-P]/.test(e); },
"Q - T" : function(e, n, f, i, $r, c, data) { return /^[Q-T]/.test(e); },
"U - X" : function(e, n, f, i, $r, c, data) { return /^[U-X]/.test(e); },
"Y - Z" : function(e, n, f, i, $r, c, data) { return /^[Y-Z]/.test(e); }
},
// Add these options to the select dropdown (numerical comparison example)
// 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, $r, c, data) { return n < 10; },
"$10 - $100" : function(e, n, f, i, $r, c, data) { return n >= 10 && n <=100; },
"> $100" : function(e, n, f, i, $r, c, data) { return n > 100; }
}
}
}
});
});</script>
</head>
<body>
<div id="banner">
<h1>table<em>sorter</em></h1>
<h2>Custom Filter Widget Functions</h2>
<h3>Flexible client-side table sorting</h3>
<a href="index.html">Back to documentation</a>
</div>
<div id="main">
<p></p>
<br>
<div class="accordion">
<h3><a href="#">Notes</a></h3>
<div>
<ul>
<li>In <span class="version">v2.22.0</span>,
<ul>
<li>An additional <code>data</code> parameter was added to the filter functions. It is an object which contains all data provided to the filter type functions (see <a href="example-widget-filter-custom-search.html#how_to_add_custom_filter_types">all the data values here</a>).</li>
<li><span class="label warning">*WARNING*</span> In a future update, the filter function parameters will change to clean up the code (I know, it's messy)!
<pre class="prettyprint lang-js">filter_functions : {
// function(e, n, f, i, $r, c, data) {} <- current parameters
0 : function(c, data) {} // planned change (version undetermined)
}</pre>The <code>e</code> (exact table cell text), <code>n</code> (normalized table cell text), <code>f</code> (filter input value), <code>i</code> (column index) and <code>$r</code> (current row; jQuery object) are all already included in the <code>data</code> object.<p></p></li>
</ul>
</li>
<li>In <span class="version">v2.21.0</span>, the filter functions provide an additional parameter <code>c</code> which is the <code>table.config</code>.</li>
<li>In <span class="version updated">v2.17.0</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>
<li>Adding a class of <code>"filter-select-nosort"</code> will now leave the select options unsorted.</li>
</ul>
</li>
<li>In <span class="version">v2.14</span>, the <code>filter_saveFilters</code> option was added (default set to <code>false</code>); this demo has it set to <code>true</code> to provide an example.</li>
<li>In <span class="version">v2.11</span>, the filter functions provide an additional parameter <code>$r</code> providing a jQuery object of the current row being searched by the filter.</li>
<li>For <span class="version">v2.10.8</span>, the Age column includes the new <code>data-value</code> set to <code><30</code> which sets the default (starting) filter value (see <a href="index.html#widget-filter-defaultattrib">filter_defaultAttrib</a> for more details).</li>
<li>As of tablesorter <span class="version">v2.9</span>, this widget can no longer be applied to versions of tablesorter prior to version 2.8.</li>
<li>Custom filter widget option <code>filter_functions</code> was added in version 2.3.6.</li>
<li>jQuery v1.4.3+ required.</li>
</ul>
</div>
<h3><a href="#"><strong>Default Select</strong></a> <span class="xsmall">("First Name" column)</span></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
'.first-name' : 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"><th class="filter-select" data-placeholder="Select a name">First Name</th></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"><th class="filter-select filter-match" data-placeholder="Select a name">First Name</th></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>
<li>Select options are automatically <del>alphanumerically</del> (new in v2.4) sorted. Changed in <span class="version updated">v2.16.3</span>:
<ul>
<li>The select contents are now parsed from the assigned parser, then sorted using the <a href="index.html#textsorter"><code>textSorter</code></a> option</li>
<li>Add a class name of <code>"filter-select-nosort"</code> to prevent sorting the select options (<span class="version">v2.16.3</span>).</li>
</ul>
</li>
<li>Please check out what the "filter-onlyAvail" class name does by reviewing the details below (in the "Discount" column) (<span class="version">v2.10.1</span>).</li>
</ul>
</div>
<h3><a href="#"><strong>Custom Filter Function</strong></a> <span class="xsmall">("Last Name" column)</span></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 : {
// Exact match only
1 : function(e, n, f, i, $r, c, data) {
return e === f;
}
}</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><span class="label warning">*NOTE*</span> If using an exact match function like this, consider setting the <a href="index.html#widget-filter-searchfiltered"><code>filter_searchFiltered</code></a> option to false. If it were set to <code>true</code>, the filter widget wouldn't know to search through the entire contents of the column if the content were only slightly different. To see this problem, search for <button type="button" data-filter-column="1">Evan</button> in the "Last Name" column, then add an "s" to the end to find "Evans". No results will show up, unless the search filtered option is <code>false</code>.</li>
<li>See the filter function information below for more details about the function parameters.</li>
</ul>
</div>
<h3><a href="#"><strong>Custom Select</strong></a> <span class="xsmall">("City" or "Total" column)</span></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>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, $r, c, data) { return /^[A-D]/.test(e); },
"E - H" : function(e, n, f, i, $r, c, data) { return /^[E-H]/.test(e); },
"I - L" : function(e, n, f, i, $r, c, data) { return /^[I-L]/.test(e); },
"M - P" : function(e, n, f, i, $r, c, data) { return /^[M-P]/.test(e); },
"Q - T" : function(e, n, f, i, $r, c, data) { return /^[Q-T]/.test(e); },
"U - X" : function(e, n, f, i, $r, c, data) { return /^[U-X]/.test(e); },
"Y - Z" : function(e, n, f, i, $r, c, data) { return /^[Y-Z]/.test(e); }
}
}</pre></li>
<li>Here is an example using numerical comparisons:<pre class="prettyprint lang-javascript">filter_functions : {
// Add these options to the select dropdown (numerical comparison example)
// 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, $r, c, data) { return n < 10; },
"$10 - $100" : function(e, n, f, i, $r, c, data) { return n >= 10 && n <=100; },
"> $100" : function(e, n, f, i, $r, c, data) { return n > 100; }
}
}</pre></li>
<li>See the "Filter function information" section below for more details about the function parameters.</li>
</ul>
</div>
<h3><a href="#"><strong>Default Select with only available options</strong></a> <span class="xsmall">("Discount" column)</span></h3>
<div>
<ul>
<li>This column uses the same method as the "First Name" column with one exception, it also includes the "filter-onlyAvail" class name in the header
cell:<pre class="prettyprint lang-html"><th class="filter-select filter-onlyAvail">Discount</th></pre></li>
<li>To see how this works, do the following:
<ul>
<li>First, filter the "First Name" column by selecting the name "Clark"</li>
<li>Now use the "Discount" 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 "44%" in the "Discount" column, then look at the "First Name" filter selector, you'll notice that it still contains all of the original options; because the "filter-onlyAvail" class name is not included in that column's header cell.</li>
<li>Sorry, this functionality only works for default select filters.</li>
<li>This funcitonality was added in <span class="version">v2.10.1</span>.</li>
</ul>
</div>
<h3><a href="#"><strong>Filter function information</strong></a></h3>
<div>
<ul>
<li>The custom function must return a boolean value. If <code>true</code> is returned, the row will be shown if all other filters match; and if <code>false</code> is returned, the row will be hidden.
<pre class="prettyprint lang-javascript">function(e, n, f, i, $r, c, data) { return test; /* test should be a Boolean (true or false) */ }</pre>
</li>
<li>The <strong>exact text (e)</strong> of the table cell is a variable passed to the function. Note that numbers will need to be parsed to make comparisons.</li>
<li><strong>Normalized table cell data (n)</strong> is the next varibale passed to the function.
<ul>
<li>This data has been parsed by the assigned column parser, so make sure the same type of data is being compared as parsed data may not be what you expect.</li>
<li>Normalized numerical values within the table will be of numeric type and not of string type, as the sorter needs to use mathematical comparisons while sorting.</li>
<li>The data will be in lower-case if the <code>filter_ignoreCase</code> option is <code>true</code>.</li>
<li>Dates like in the last column of the table below will store the time in seconds since 1970 (using javascript's .getTime() function).</li>
<li>The percentage column will only store the number and not percentage sign.</li>
</ul>
</li>
<li>The <strong>filter input value (f)</strong> is the exact text entered by the user. If numerical, it will need to be parsed using parseFloat() or parseInt() to allow for making comparisons.</li>
<li>The <strong>column index (i)</strong> might be useful for obtaining more information from header, or something.</li>
<li>The <strong>row ($r)</strong> is the current table row (jQuery object) being searched (or filtered).
<ul>
<li>This allows access to any extra information within. To access the current cell, just use <code>$r.children().eq(i)</code>.</li>
<li><span class="label alert">* NOTE *</span> The row object provided is <em>not</em> attached to the table, so using something like <code>.parent()</code> or <code>.closest()</code> will not work!</li>
<li>For this reason, the next parameter (<code>c</code>) was added.</li>
</ul>
</li>
<li>The <strong>config (c)</strong> is the <code>table.config</code> (added <span class="version">v2.21.0</span>).</li>
<li>The <strong>data</strong> parameter is the same data passed to the filter types (see <a href="example-widget-filter-custom-search.html#how_to_add_custom_filter_types">all the data values here</a>; added <span class="version">v2.22.0</span>).</li>
</ul>
</div>
</div>
<h1>Demo</h1>
<button type="button" class="match" data-filter-column="0" data-filter-text="Denni">Toggle</button> <span id="mode" class="bright">false</span> "filter-match" class name on the "First Name" column<br>
<button type="button" class="search-type">Toggle</button> filter_searchFiltered : <span id="search-type" class="bright">true</span> (if true, the search is performed on already filtered rows, with some exceptions)<br>
<button type="button" class="reset">Reset Search</button>
<div id="demo"><table class="tablesorter">
<thead>
<tr>
<!-- 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="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>
<th data-placeholder="Select a filter">Total</th>
<th class="filter-select filter-onlyAvail">Discount</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>Aaron</td>
<td>Johnson Sr</td>
<td>Atlanta</td>
<td>35</td>
<td>$5.95</td>
<td>22%</td>
<td>Jun 26, 2004 7:22 AM</td>
</tr>
<tr>
<td>Aaron</td>
<td>Johnson</td>
<td>Yuma</td>
<td>12</td>
<td>$2.99</td>
<td>5%</td>
<td>Aug 21, 2009 12:21 PM</td>
</tr>
<tr>
<td>Clark</td>
<td>Henry Jr</td>
<td>Tampa</td>
<td>51</td>
<td>$42.29</td>
<td>18%</td>
<td>Oct 13, 2000 1:15 PM</td>
</tr>
<tr>
<td>Denni</td>
<td>Henry</td>
<td>New York</td>
<td>28</td>
<td>$9.99</td>
<td>20%</td>
<td>Jul 6, 2006 8:14 AM</td>
</tr>
<tr>
<td>John</td>
<td>Hood</td>
<td>Boston</td>
<td>33</td>
<td>$19.99</td>
<td>25%</td>
<td>Dec 10, 2002 5:14 AM</td>
</tr>
<tr>
<td>Clark</td>
<td>Kent Sr</td>
<td>Los Angeles</td>
<td>18</td>
<td>$15.89</td>
<td>44%</td>
<td>Jan 12, 2003 11:14 AM</td>
</tr>
<tr>
<td>Peter</td>
<td>Kent Esq</td>
<td>Seattle</td>
<td>45</td>
<td>$153.19</td>
<td>44%</td>
<td>Jan 18, 2021 9:12 AM</td>
</tr>
<tr>
<td>Peter</td>
<td>Johns</td>
<td>Milwaukee</td>
<td>13</td>
<td>$5.29</td>
<td>4%</td>
<td>Jan 8, 2012 5:11 PM</td>
</tr>
<tr>
<td>Aaron</td>
<td>Evan</td>
<td>Chicago</td>
<td>24</td>
<td>$14.19</td>
<td>14%</td>
<td>Jan 14, 2004 11:23 AM</td>
</tr>
<tr>
<td>Bruce</td>
<td>Evans</td>
<td>Upland</td>
<td>22</td>
<td>$13.19</td>
<td>11%</td>
<td>Jan 18, 2007 9:12 AM</td>
</tr>
<tr>
<td>Clark</td>
<td>McMasters</td>
<td>Pheonix</td>
<td>18</td>
<td>$55.20</td>
<td>15%</td>
<td>Feb 12, 2010 7:23 PM</td>
</tr>
<tr>
<td>Dennis</td>
<td>Masters</td>
<td>Indianapolis</td>
<td>65</td>
<td>$123.00</td>
<td>32%</td>
<td>Jan 20, 2001 1:12 PM</td>
</tr>
<tr>
<td>John</td>
<td>Hood</td>
<td>Fort Worth</td>
<td>25</td>
<td>$22.09</td>
<td>17%</td>
<td>Jun 11, 2011 10:55 AM</td>
</tr>
</tbody>
</table></div>
<h1>Javascript</h1>
<div id="javascript">
<pre class="prettyprint lang-javascript"></pre>
</div>
<h1>HTML</h1>
<div id="html">
<pre class="prettyprint lang-html"></pre>
</div>
<div class="next-up">
<hr />
Next up: <a href="example-widget-filter-custom-search.html">Custom Filter Widget Search Types ››</a>
</div>
</div>
</body>
</html>
|