version bump

This commit is contained in:
Rob Garrison 2015-11-10 15:27:30 -06:00
parent ea13f6d256
commit a203ac5f52
32 changed files with 781 additions and 741 deletions

134
README.md
View File

@ -92,6 +92,39 @@ If you would like to contribute, please...
View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes). View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes).
#### <a name="v2.24.4">Version 2.24.4</a> (11/10/2015)
* Core
* `sortRestart` works again with multi-row headers. Fixes [issue #1074](https://github.com/Mottie/tablesorter/issues/1074).
* Add `sortDisabled` language setting; used in aria-labels.
* Docs
* Update `group_formatter` docs. See [issue #1077](https://github.com/Mottie/tablesorter/issues/1077).
* Add clarification & missing possible values. See [issue #1070](https://github.com/Mottie/tablesorter/issues/1070).
* Fixed mixed content issue, broken links (beta-testing demos) & other stuff.
* Add [filter + jQuery UI Selectmenu demo](http://mottie.github.io/tablesorter/docs/example-widget-filter-selectmenu.html). See [issue #1060](https://github.com/Mottie/tablesorter/issues/1060)
* Misc updates.
* Filter
* Convert filters to strings using conventional methods.
* Prevent "OR" filter type from splitting up regex string. See [issue #1070]https://github.com/Mottie/tablesorter/issues/1070).
* `filter_selectSource` option now accepts an array of objects ([demo](http://mottie.github.io/tablesorter/docs/example-widget-filter-selectmenu.html)).
* Group
* Include group & row data parameters in `group_formatter`. Fixes [issue #1077](https://github.com/Mottie/tablesorter/issues/1077).
* HeaderTitles
* Update aria-label usage.
* Math
* Avoid nested table math cells. See [Stackoverflow](http://stackoverflow.com/q/33631298/145346).
* Pager
* Clear `tbody` prior to calling `ajaxProcessing`. This again allows the developer to add the HTML to the table instead of needing to return it.
* Sort2Hash
* Make widget functions accessible.
* Add 2 utility functions to simplify hash processing.
* Toggle
* Add new widget to enable/disable sort & filter. See [issue #1075](https://github.com/Mottie/tablesorter/issues/1075).
* Parser
* Add "file-extension" parser.
* Misc
* Grunt: Fix uglify comment removal & update dist folder.
#### <a name="v2.24.3">Version 2.24.3</a> (11/4/2015) #### <a name="v2.24.3">Version 2.24.3</a> (11/4/2015)
* Core * Core
@ -109,104 +142,3 @@ View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes
* Misc * Misc
* Restory empty bower.json ignore setting... bower is installing an empty dist folder. * Restory empty bower.json ignore setting... bower is installing an empty dist folder.
#### <a name="v2.24.1">Version 2.24.1</a> (11/2/2015)
* Core
* Cache "shortDate" parser & time parser now extracts the time.
* Group
* Add optimizations from [pull #830](https://github.com/Mottie/tablesorter/pull/830); thanks to [VorontsovIE](https://github.com/VorontsovIE)!
* Update [demo](http://mottie.github.io/tablesorter/docs/example-widget-grouping.html) to use new "weekday-index" parser when "group-date-week" is set, and updated "time" parser when "group-date-time" is set.
* Print
* Rows option now accepts custom css selectors.
* Sort2Hash
* Remove history push state as it ignored other tables on the page.
* Parsers
* Globalization parser now caches the `Globalize` object in a same named option.
* Convert month & weekday parsers to utilize globalization data.
* Add "weekday-index" parser - this parser ignores the actual date but saves the weekday from a date object
* Misc
* Revert bower.json changes in [pull #1063](https://github.com/Mottie/tablesorter/pull/1063); Fixes [issue #1068](https://github.com/Mottie/tablesorter/issues/1068).
#### <a name="v2.24.0">Version 2.24.0</a> (10/31/2015)
* Docs
* Fix mixed content using GitHub buttons on main page. See [pull #1029](https://github.com/Mottie/tablesorter/pull/1029); thanks [OmgImAlexis](https://github.com/OmgImAlexis)!
* Clarify use of pager `ajaxUrl` option.
* Add theme class to tables to prevent FOUC.
* Fix left menu push. The body no longer squeezes the content.
* Update stickyHeaders after menu close.
* Include horizontal scroll while jumping to search result.
* Add some examples (`filter_cssFilter`).
* Global
* Call internal functions directly; stop using triggered events.
* Core
* Use plain javascript to set index attribute & remove unused variable. See [issue #1048](https://github.com/Mottie/tablesorter/issues/1048).
* Add "entire column `colspan`" support. See issues [#485](https://github.com/Mottie/tablesorter/issues/485), [#746](https://github.com/Mottie/tablesorter/issues/746) & [#1047](https://github.com/Mottie/tablesorter/issues/1047).
* Fix parser detect & sortVars on columns that don't exist due to colspan. See issues [#485](https://github.com/Mottie/tablesorter/issues/485), [#746](https://github.com/Mottie/tablesorter/issues/746) & [#1047](https://github.com/Mottie/tablesorter/issues/1047).
* Reformat structure & expand variable names.
* Add `rowFilter` parameter to `getColumnText` function.
* Fix multisort indicators. Fixes [issue #1005](https://github.com/Mottie/tablesorter/issues/1005), again.
* `sortAppend` now accepts an object of column references; see [Stackoverflow](http://stackoverflow.com/q/33177910/145346).
* Internalize sort counter & fix spanned sorts.
* Add `"tablesorter-ready"` event.
* Add widget from class before adding widget options.
* Maintaining support for IE7-8 until 1/12/16.
* Chart
* Fix `chart_layout` column indexing.
* ColumnSelector
* Add `mediaqueryHidden` option. Resolves [issue #964](https://github.com/Mottie/tablesorter/issues/964).
* Extra rows & colspans now supported in `thead` & `tfoot`. Fixes [issue #501](https://github.com/Mottie/tablesorter/issues/501).
* Fix jscs reported issues.
* Filter
* Encode/decode filters in case they end up in cookies. See [issue #1026](https://github.com/Mottie/tablesorter/issues/1026).
* Add "entire column `colspan`" support. See issues [#485](https://github.com/Mottie/tablesorter/issues/485), [#746](https://github.com/Mottie/tablesorter/issues/746) & [#1047](https://github.com/Mottie/tablesorter/issues/1047).
* `hideFilters` applies to stickyHeaders again. Fixes [issue #1050](https://github.com/Mottie/tablesorter/issues/1050).
* Prevent error in `formatterUpdated`. Fixes [issue #1056](https://github.com/Mottie/tablesorter/issues/1056).
* Grouping
* Prevent error if `group_forceColumn` is improperly defined. See [issue #1030](https://github.com/Mottie/tablesorter/issues/1030).
* Improve compatibility with [jQuery Globalize](https://github.com/jquery/globalize); Find [more details here](http://mottie.github.io/tablesorter/docs/example-widget-grouping.html#globalization).
* Update header in pager with `removeRows:true`. Fixes [issue #1035](https://github.com/Mottie/tablesorter/issues/1035).
* HeaderTitles
* Switch to use internalized sort counter.
* Lazyload
* Add new widget. [Demo](http://mottie.github.io/tablesorter/docs/example-widget-lazyload.html)
* Math
* Created new calculation type "below". It works just like "above" except in other direction starting from top to bottom. See [pull #1027](https://github.com/Mottie/tablesorter/pull/1027); thanks [LvLynx](https://github.com/LvLynx)!
* Tweak changes & more tweaks for better compression.
* Detach table prior to indexing all cells. See [issue #1048](https://github.com/Mottie/tablesorter/issues/1048).
* Add `math_none` option.
* Include `config` parameter in math equations - needed for `math_none` option.
* Output
* Correct `formatContent` function comment (missing widgetOptions variable)
* Do not include nested table headers with parent. Fixes [issue #1040](https://github.com/Mottie/tablesorter/issues/1040).
* Pager
* Clear tbody if no data returned by ajax. See [issue #1032](https://github.com/Mottie/tablesorter/issues/1032).
* Add "all" setting for page size methods; includes select option & all methods. See [issue #1055](https://github.com/Mottie/tablesorter/issues/1055).
* Fix pager widget demo destroy method.
* destroyPager again reveals all rows. Fixes [issue #1055](https://github.com/Mottie/tablesorter/issues/1055).
* Parse page numbers to prevent user seeing `NaN`.
* Parse page size updates.
* Print
* Internal variable tweaks.
* Include css to hide filter rows. Fixes [issue #1046](https://github.com/Mottie/tablesorter/issues/1046).
* Add print delay; allows browsers to render print preview.
* Scroller
* Fix `scroller_barWidth` issue in iOS. See [pull #1062](https://github.com/Mottie/tablesorter/pull/1062); thanks [fire-wally](https://github.com/fire-wally)!
* Sort2Hash
* Update to include pager (page & size) and filter parameters.
* SortTbodies
* Moved config string defaults to `$.tablesorter.strings` to match core reformatting.
* StickyHeaders
* `hideFilters` applies to stickyHeaders again. Fixes [issue #1050](https://github.com/Mottie/tablesorter/issues/1050).
* View
* Add new widget. [Demo](http://mottie.github.io/tablesorter/docs/example-widget-view.html).
* Fix jscs reported issues.
* Parsers
* Globalize parser now allows a different language per column.
* Fix jscs reported issues.
* Misc
* Bower: use correct theme name. Fixes [issue #1028](https://github.com/Mottie/tablesorter/issues/1028).
* Readme: Add link to [UserFrosting](https://github.com/alexweissman/UserFrosting) by [alexweissman](https://github.com/alexweissman)
* Updated build dependencies x2.
* Added development files & directories to bower ignore. See [pull #1063](https://github.com/Mottie/tablesorter/pull/1063); thanks [jdufresne](https://github.com/jdufresne)!

View File

@ -1,6 +1,6 @@
/*! /*!
* tablesorter (FORK) pager plugin * tablesorter (FORK) pager plugin
* updated 10/31/2015 (v2.24.0) * updated 11/10/2015 (v2.24.4)
*/ */
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
;(function($) { ;(function($) {

1
dist/css/theme.blue.nested.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
/*! tablesorter (FORK) - updated 11-06-2015 (v2.24.3)*/ /*! tablesorter (FORK) - updated 11-10-2015 (v2.24.4)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -10,7 +10,7 @@
} }
}(function($) { }(function($) {
/*! TableSorter (FORK) v2.24.3 *//* /*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -33,7 +33,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.24.3', version : '2.24.4',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -151,12 +151,13 @@
// labels applied to sortable headers for accessibility (aria) support // labels applied to sortable headers for accessibility (aria) support
language : { language : {
sortAsc : 'Ascending sort applied, ', sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ', sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ', sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort', sortDisabled : 'sorting is disabled',
nextDesc : 'activate to apply a descending sort', nextAsc : 'activate to apply an ascending sort',
nextNone : 'activate to remove the sort' nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
}, },
regex : { regex : {
@ -1005,7 +1006,7 @@
*/ */
setHeadersCss : function( c ) { setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp, var $sorted, indx, column,
list = c.sortList, list = c.sortList,
len = list.length, len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone, none = ts.css.sortNone + ' ' + c.cssNone,
@ -1073,50 +1074,62 @@
} }
// add verbose aria labels // add verbose aria labels
len = c.$headers.length; len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
$header = $headers.eq( indx ); ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
if ( $header.length ) { }
header = $headers[ indx ]; },
column = parseInt( $header.attr( 'data-column' ), 10 );
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ]; // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) {
var column = parseInt( $header.attr( 'data-column' ), 10 ),
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone'; $header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
ts.language[ tmp ] + if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ]; txt += ts.language.sortDisabled;
$header.attr( 'aria-label', txt ); } else {
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ];
// if nextSort
txt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
} }
$header.attr( 'aria-label', txt );
} }
}, },
updateHeader : function( c ) { updateHeader : function( c ) {
var index, isDisabled, $th, col, var index, isDisabled, $header, col,
table = c.table, table = c.table,
len = c.$headers.length; len = c.$headers.length;
for ( index = 0; index < len; index++ ) { for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index ); $header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true ); col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set // add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false'; isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled; ts.setColumnSort( c, $header, isDisabled );
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled ); }
// disable tab index on disabled cells },
if ( c.tabIndex ) {
if ( isDisabled ) { setColumnSort : function( c, $header, isDisabled ) {
$th.removeAttr( 'tabindex' ); var id = c.table.id;
} else { $header[ 0 ].sortDisabled = isDisabled;
$th.attr( 'tabindex', '0' ); $header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )
} .attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$header.removeAttr( 'tabindex' );
} else {
$header.attr( 'tabindex', '0' );
} }
// aria-controls - requires table ID }
if ( table.id ) { // aria-controls - requires table ID
if ( isDisabled ) { if ( id ) {
$th.removeAttr( 'aria-controls' ); if ( isDisabled ) {
} else { $header.removeAttr( 'aria-controls' );
$th.attr( 'aria-controls', table.id ); } else {
} $header.attr( 'aria-controls', id );
} }
} }
}, },
@ -2178,14 +2191,14 @@
// *** Process table *** // *** Process table ***
// add processing indicator // add processing indicator
isProcessing : function( $table, toggle, $ths ) { isProcessing : function( $table, toggle, $headers ) {
$table = $( $table ); $table = $( $table );
var c = $table[ 0 ].config, var c = $table[ 0 ].config,
// default to all headers // default to all headers
$header = $ths || $table.find( '.' + ts.css.header ); $header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) { if ( toggle ) {
// don't use sortList if custom $ths used // don't use sortList if custom $headers used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) { if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList // get headers from the sortList
$header = $header.filter( function() { $header = $header.filter( function() {
// get data-column from attr to keep compatibility with jQuery 1.2.6 // get data-column from attr to keep compatibility with jQuery 1.2.6
@ -2977,13 +2990,13 @@
})(jQuery); })(jQuery);
/*! Widget: filter - updated 11/4/2015 (v2.24.3) *//* /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */
;( function ( $ ) { ;( function ( $ ) {
'use strict'; 'use strict';
var tsf, var tsf, tsfRegex,
ts = $.tablesorter || {}, ts = $.tablesorter || {},
tscss = ts.css; tscss = ts.css;
@ -3089,20 +3102,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class ) // data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: { types: {
or : function( c, data, vars ) { or : function( c, data, vars ) {
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) { // look for "|", but not if it is inside of a regular expression
if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
// this test for regex has potential to slow down the overall search
!tsfRegex.regex.test( data.filter ) ) {
var indx, filterMatched, query, regex, var indx, filterMatched, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.orSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.orSplit ),
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')'; query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try { try {
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search, // use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group // e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
@ -3124,22 +3138,20 @@
}, },
// Look for an AND or && operator ( logical and ) // Look for an AND or && operator ( logical and )
and : function( c, data, vars ) { and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) { if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex, var indx, filterMatched, result, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.andSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.andSplit ),
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' ) query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// replace wild cards since /(a*)/i will match anything // replace wild cards since /(a*)/i will match anything
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ); .replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
try { try {
// use try/catch just in case RegExp is invalid // use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' ); regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -3161,10 +3173,10 @@
}, },
// Look for regex // Look for regex
regex: function( c, data ) { regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) { if ( tsfRegex.regex.test( data.filter ) ) {
var matches, var matches,
// cache regex per column for optimal speed // cache regex per column for optimal speed
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ), regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
isRegex = regex instanceof RegExp; isRegex = regex instanceof RegExp;
try { try {
if ( !isRegex ) { if ( !isRegex ) {
@ -3183,18 +3195,17 @@
// Look for operators >, >=, < or <= // Look for operators >, >=, < or <=
operators: function( c, data ) { operators: function( c, data ) {
// ignore empty strings... because '' < 10 is true // ignore empty strings... because '' < 10 is true
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) { if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
var cachedValue, result, txt, var cachedValue, result, txt,
table = c.table, table = c.table,
index = data.index, parsed = data.parsed[ data.index ],
parsed = data.parsed[index], query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ), parser = c.parsers[ data.index ],
parser = c.parsers[index],
savedSearch = query; savedSearch = query;
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) { if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) ); txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true ); result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query; query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
} }
// iExact may be numeric - see issue #149; // iExact may be numeric - see issue #149;
@ -3206,10 +3217,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact; txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table ); cachedValue = ts.formatFloat( txt, table );
} }
if ( tsf.regex.gtTest.test( data.iFilter ) ) { if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query; result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) { } else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query; result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
} }
// keep showing all rows if nothing follows the operator // keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) { if ( !result && savedSearch === '' ) {
@ -3221,13 +3232,13 @@
}, },
// Look for a not match // Look for a not match
notMatch: function( c, data ) { notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) { if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx, var indx,
txt = data.iFilter.replace( '!', '' ), txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsf.regex.exact.test( filter ) ) { if ( tsfRegex.exact.test( filter ) ) {
// look for exact not matches - see #628 // look for exact not matches - see #628
filter = filter.replace( tsf.regex.exact, '' ); filter = filter.replace( tsfRegex.exact, '' );
return filter === '' ? true : $.trim( filter ) !== data.iExact; return filter === '' ? true : $.trim( filter ) !== data.iExact;
} else { } else {
indx = data.iExact.search( $.trim( filter ) ); indx = data.iExact.search( $.trim( filter ) );
@ -3239,29 +3250,29 @@
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric // Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
exact: function( c, data ) { exact: function( c, data ) {
/*jshint eqeqeq:false */ /*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) { if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ), var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact; return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
} }
return null; return null;
}, },
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu! // Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) { range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) { if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2, var result, tmp, range1, range2,
table = c.table, table = c.table,
index = data.index, index = data.index,
parsed = data.parsed[index], parsed = data.parsed[index],
// make sure the dash is for a range and not indicating a negative number // make sure the dash is for a range and not indicating a negative number
query = data.iFilter.split( tsf.regex.toSplit ); query = data.iFilter.split( tsfRegex.toSplit );
tmp = query[0].replace( ts.regex.nondigit, '' ) || ''; tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
tmp = query[1].replace( ts.regex.nondigit, '' ) || ''; tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || c.parsers[index].type === 'numeric' ) { if ( parsed || c.parsers[ index ].type === 'numeric' ) {
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1; range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
@ -3282,18 +3293,16 @@
}, },
// Look for wild card: ? = single, * = multiple, or | = logical OR // Look for wild card: ? = single, * = multiple, or | = logical OR
wild : function( c, data ) { wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) { if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var index = data.index, var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
// look for an exact match with the 'or' unless the 'filter-match' class is found // look for an exact match with the 'or' unless the 'filter-match' class is found
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) { if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
query = data.isMatch ? query : '^(' + query + ')$'; query = data.isMatch ? query : '^(' + query + ')$';
} }
// parsing the filter may not work properly when using wildcards =/ // parsing the filter may not work properly when using wildcards =/
try { try {
return new RegExp( return new RegExp(
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ), query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
c.widgetOptions.filter_ignoreCase ? 'i' : '' c.widgetOptions.filter_ignoreCase ? 'i' : ''
) )
.test( data.exact ); .test( data.exact );
@ -3305,21 +3314,18 @@
}, },
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license ) // fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) { fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) { if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx, var indx,
patternIndx = 0, patternIndx = 0,
len = data.iExact.length, len = data.iExact.length,
txt = data.iFilter.slice( 1 ), txt = data.iFilter.slice( 1 ),
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; pattern = tsf.parseFilter( c, txt, data ) || '';
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) { if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1; patternIndx += 1;
} }
} }
if ( patternIndx === pattern.length ) { return patternIndx === pattern.length;
return true;
}
return false;
} }
return null; return null;
} }
@ -3332,8 +3338,7 @@
and : 'and' and : 'and'
}, ts.language ); }, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect, var options, string, txt, $header, column, filters, val, fxn, noSelect;
regex = tsf.regex;
c.$table.addClass( 'hasFilters' ); c.$table.addClass( 'hasFilters' );
// define timers so using clearTimeout won't cause an undefined error // define timers so using clearTimeout won't cause an undefined error
@ -3344,8 +3349,8 @@
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]'; wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]'; wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}'; val = '\\{' + tsfRegex.query + '\\}';
$.extend( regex, { $.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ), child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ), filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ), alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -3623,8 +3628,10 @@
c.$table.data( 'lastSearch', filters ); c.$table.data( 'lastSearch', filters );
return filters; return filters;
}, },
parseFilter: function( c, filter, column, parsed ) { parseFilter: function( c, filter, data, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter; return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
}, },
buildRow: function( table, c, wo ) { buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp, var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -3876,8 +3883,8 @@
}, },
defaultFilter: function( filter, mask ) { defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; } if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery, var regex = tsfRegex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length, maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ], query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1, len = query.length - 1,
indx = 0, indx = 0,
@ -3974,9 +3981,8 @@
return filterMatched; return filterMatched;
}, },
processRow: function( c, data, vars ) { processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched, var result, filterMatched,
fxn, ffxn, txt, fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions, wo = c.widgetOptions,
showRow = true, showRow = true,
@ -4055,7 +4061,7 @@
result = data.rawArray[ columnIndex ] || ''; result = data.rawArray[ columnIndex ] || '';
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405 data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
} }
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ? data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
data.exact.toLowerCase() : data.exact; data.exact.toLowerCase() : data.exact;
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' ); data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -4073,21 +4079,13 @@
data.filter = ts.replaceAccents( data.filter ); data.filter = ts.replaceAccents( data.filter );
} }
val = true;
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
// val is used to indicate that a filter select is using a default filter;
// so we override the exact & partial matches
val = false;
}
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ), // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
// data.filter = case sensitive // data.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter; data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ]; fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null; filterMatched = null;
if ( fxn || ( hasSelect && val ) ) { if ( fxn ) {
if ( fxn === true || hasSelect ) { if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found // default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ? filterMatched = data.isMatch ?
// data.iExact may be a number // data.iExact may be a number
@ -4113,7 +4111,7 @@
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
txt = ( data.iExact + data.childRowText ) txt = ( data.iExact + data.childRowText )
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) ); .indexOf( tsf.parseFilter( c, data.iFilter, data ) );
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) ); result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
} }
} else { } else {
@ -4133,7 +4131,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx, isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt, notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ), storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters // data object passed to filters; anyMatch is a flag for the filters
@ -4215,7 +4212,7 @@
); );
if ( wo.filter_columnAnyMatch ) { if ( wo.filter_columnAnyMatch ) {
// specific columns search // specific columns search
query = data.anyMatchFilter.split( regex.andSplit ); query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false; injected = false;
for ( indx = 0; indx < query.length; indx++ ) { for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' ); res = query[ indx ].split( ':' );
@ -4250,12 +4247,12 @@
// there are no changes from beginning of filter // there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 && val.indexOf( lastSearch[indx] || '' ) === 0 &&
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string // if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
!regex.alreadyFiltered.test( val ) && !tsfRegex.alreadyFiltered.test( val ) &&
// if we are not doing exact matches, using '|' ( logical or ) or not '!' // if we are not doing exact matches, using '|' ( logical or ) or not '!'
!regex.exactTest.test( val ) && !tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative // don't search only filtered if the value is negative
// ( '> -10' => '> -100' will ignore hidden rows ) // ( '> -10' => '> -100' will ignore hidden rows )
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) && !( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593 // if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length && !( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) ); !c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -4273,7 +4270,7 @@
// replace accents // replace accents
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter ); data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
} }
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) { if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter ); data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
// clear search filtered flag because default filters are not saved to the last search // clear search filtered flag because default filters are not saved to the last search
searchFiltered = false; searchFiltered = false;
@ -4290,9 +4287,9 @@
txt = $rows[ rowIndex ].className; txt = $rows[ rowIndex ].className;
// the first row can never be a child row // the first row can never be a child row
isChild = rowIndex && regex.child.test( txt ); isChild = rowIndex && tsfRegex.child.test( txt );
// skip child rows & already filtered rows // skip child rows & already filtered rows
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) { if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue; continue;
} }
@ -4402,7 +4399,6 @@
// custom select source function for a SPECIFIC COLUMN // custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail ); arry = fxn( table, column, onlyAvail );
} }
if ( arry === false ) { if ( arry === false ) {
// fall back to original method // fall back to original method
arry = tsf.getOptions( table, column, onlyAvail ); arry = tsf.getOptions( table, column, onlyAvail );
@ -4416,18 +4412,19 @@
return false; return false;
} }
table = $( table )[0]; table = $( table )[0];
var cts, txt, indx, len, var cts, txt, indx, len, parsedTxt, str,
c = table.config, c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns, validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = []; parsed = [];
// get unique elements and sort the list // get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ), // if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort // then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) { arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx; return $.inArray( value, arry ) === indx;
}); });
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) { if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options // unsorted select options
return arry; return arry;
@ -4436,22 +4433,30 @@
// parse select option values // parse select option values
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
txt = arry[ indx ]; txt = arry[ indx ];
// check for object
str = txt.text ? txt.text : txt;
// sortNatural breaks if you don't pass it strings
parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( str, table, [], column ) || str ).toString();
parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
// parse array data using set column parser; this DOES NOT pass the original // parse array data using set column parser; this DOES NOT pass the original
// table cell to the parser format function // table cell to the parser format function
parsed.push({ if ( txt.text ) {
t : txt, txt.parsed = parsedTxt;
// check parser length - fixes #934 parsed.push( txt );
p : validColumn && c.parsers && c.parsers.length && } else {
c.parsers[ column ].format( txt, table, [], column ) || txt parsed.push({
}); text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
} }
// sort parsed select options // sort parsed select options
cts = c.textSorter || ''; cts = c.textSorter || '';
parsed.sort( function( a, b ) { parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings var x = a.parsed,
var x = a.p.toString(), y = b.parsed;
y = b.p.toString();
if ( validColumn && typeof cts === 'function' ) { if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter // custom OVERALL text sorter
return cts( x, y, true, column, table ); return cts( x, y, true, column, table );
@ -4469,7 +4474,7 @@
arry = []; arry = [];
len = parsed.length; len = parsed.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t ); arry.push( parsed[indx] );
} }
return arry; return arry;
} }
@ -4529,7 +4534,7 @@
return; return;
} }
var indx, val, txt, t, $filters, $filter, var indx, val, txt, t, $filters, $filter, option,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
node = c.$headerIndexed[ column ], node = c.$headerIndexed[ column ],
@ -4554,23 +4559,45 @@
if ( $.isArray( arry ) ) { if ( $.isArray( arry ) ) {
// build option list // build option list
for ( indx = 0; indx < arry.length; indx++ ) { for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '&quot;' ); option = arry[ indx ];
val = txt; if ( option.text ) {
// allow including a symbol in the selectSource array // OBJECT!! add data-function-name in case the value is set in filter_functions
// 'a-z|A through Z' so that 'a-z' becomes the option value option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) { // support jQuery < v1.8, otherwise the below code could be shortened to
t = txt.split( wo.filter_selectSourceSeparator ); // options += $( '<option>', option )[ 0 ].outerHTML;
val = t[0]; options += '<option';
txt = t[1]; for ( val in option ) {
if ( option.hasOwnProperty( val ) && val !== 'text' ) {
options += ' ' + val + '="' + option[ val ] + '"';
}
}
if ( !option.value ) {
options += ' value="' + option.text + '"';
}
options += '>' + option.text + '</option>';
// above code is needed in jQuery < v1.8
// make sure we don't turn an object into a string (objects without a "text" property)
} else if ( '' + option !== '[object Object]' ) {
txt = option = ( '' + option ).replace( tsfRegex.quote, '&quot;' );
val = txt;
// allow including a symbol in the selectSource array
// 'a-z|A through Z' so that 'a-z' becomes the option value
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
t = txt.split( wo.filter_selectSourceSeparator );
val = t[0];
txt = t[1];
}
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += option !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + option + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += arry[indx] !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// clear arry so it doesn't get appended twice // clear arry so it doesn't get appended twice
arry = []; arry = [];
@ -4616,6 +4643,9 @@
} }
}; };
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) { ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols, var i, $filters, $column, cols,
filters = false, filters = false,

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,7 @@
} }
}(function($) { }(function($) {
/*! TableSorter (FORK) v2.24.3 *//* /*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -31,7 +31,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.24.3', version : '2.24.4',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -149,12 +149,13 @@
// labels applied to sortable headers for accessibility (aria) support // labels applied to sortable headers for accessibility (aria) support
language : { language : {
sortAsc : 'Ascending sort applied, ', sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ', sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ', sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort', sortDisabled : 'sorting is disabled',
nextDesc : 'activate to apply a descending sort', nextAsc : 'activate to apply an ascending sort',
nextNone : 'activate to remove the sort' nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
}, },
regex : { regex : {
@ -1003,7 +1004,7 @@
*/ */
setHeadersCss : function( c ) { setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp, var $sorted, indx, column,
list = c.sortList, list = c.sortList,
len = list.length, len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone, none = ts.css.sortNone + ' ' + c.cssNone,
@ -1071,50 +1072,62 @@
} }
// add verbose aria labels // add verbose aria labels
len = c.$headers.length; len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
$header = $headers.eq( indx ); ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
if ( $header.length ) { }
header = $headers[ indx ]; },
column = parseInt( $header.attr( 'data-column' ), 10 );
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ]; // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) {
var column = parseInt( $header.attr( 'data-column' ), 10 ),
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone'; $header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
ts.language[ tmp ] + if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ]; txt += ts.language.sortDisabled;
$header.attr( 'aria-label', txt ); } else {
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ];
// if nextSort
txt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
} }
$header.attr( 'aria-label', txt );
} }
}, },
updateHeader : function( c ) { updateHeader : function( c ) {
var index, isDisabled, $th, col, var index, isDisabled, $header, col,
table = c.table, table = c.table,
len = c.$headers.length; len = c.$headers.length;
for ( index = 0; index < len; index++ ) { for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index ); $header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true ); col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set // add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false'; isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled; ts.setColumnSort( c, $header, isDisabled );
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled ); }
// disable tab index on disabled cells },
if ( c.tabIndex ) {
if ( isDisabled ) { setColumnSort : function( c, $header, isDisabled ) {
$th.removeAttr( 'tabindex' ); var id = c.table.id;
} else { $header[ 0 ].sortDisabled = isDisabled;
$th.attr( 'tabindex', '0' ); $header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )
} .attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$header.removeAttr( 'tabindex' );
} else {
$header.attr( 'tabindex', '0' );
} }
// aria-controls - requires table ID }
if ( table.id ) { // aria-controls - requires table ID
if ( isDisabled ) { if ( id ) {
$th.removeAttr( 'aria-controls' ); if ( isDisabled ) {
} else { $header.removeAttr( 'aria-controls' );
$th.attr( 'aria-controls', table.id ); } else {
} $header.attr( 'aria-controls', id );
} }
} }
}, },
@ -2176,14 +2189,14 @@
// *** Process table *** // *** Process table ***
// add processing indicator // add processing indicator
isProcessing : function( $table, toggle, $ths ) { isProcessing : function( $table, toggle, $headers ) {
$table = $( $table ); $table = $( $table );
var c = $table[ 0 ].config, var c = $table[ 0 ].config,
// default to all headers // default to all headers
$header = $ths || $table.find( '.' + ts.css.header ); $header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) { if ( toggle ) {
// don't use sortList if custom $ths used // don't use sortList if custom $headers used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) { if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList // get headers from the sortList
$header = $header.filter( function() { $header = $header.filter( function() {
// get data-column from attr to keep compatibility with jQuery 1.2.6 // get data-column from attr to keep compatibility with jQuery 1.2.6

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
/*! tablesorter (FORK) - updated 11-06-2015 (v2.24.3)*/ /*! tablesorter (FORK) - updated 11-10-2015 (v2.24.4)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -366,13 +366,13 @@
})(jQuery); })(jQuery);
/*! Widget: filter - updated 11/4/2015 (v2.24.3) *//* /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */
;( function ( $ ) { ;( function ( $ ) {
'use strict'; 'use strict';
var tsf, var tsf, tsfRegex,
ts = $.tablesorter || {}, ts = $.tablesorter || {},
tscss = ts.css; tscss = ts.css;
@ -478,20 +478,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class ) // data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: { types: {
or : function( c, data, vars ) { or : function( c, data, vars ) {
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) { // look for "|", but not if it is inside of a regular expression
if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
// this test for regex has potential to slow down the overall search
!tsfRegex.regex.test( data.filter ) ) {
var indx, filterMatched, query, regex, var indx, filterMatched, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.orSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.orSplit ),
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')'; query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try { try {
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search, // use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group // e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
@ -513,22 +514,20 @@
}, },
// Look for an AND or && operator ( logical and ) // Look for an AND or && operator ( logical and )
and : function( c, data, vars ) { and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) { if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex, var indx, filterMatched, result, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.andSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.andSplit ),
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' ) query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// replace wild cards since /(a*)/i will match anything // replace wild cards since /(a*)/i will match anything
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ); .replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
try { try {
// use try/catch just in case RegExp is invalid // use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' ); regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -550,10 +549,10 @@
}, },
// Look for regex // Look for regex
regex: function( c, data ) { regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) { if ( tsfRegex.regex.test( data.filter ) ) {
var matches, var matches,
// cache regex per column for optimal speed // cache regex per column for optimal speed
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ), regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
isRegex = regex instanceof RegExp; isRegex = regex instanceof RegExp;
try { try {
if ( !isRegex ) { if ( !isRegex ) {
@ -572,18 +571,17 @@
// Look for operators >, >=, < or <= // Look for operators >, >=, < or <=
operators: function( c, data ) { operators: function( c, data ) {
// ignore empty strings... because '' < 10 is true // ignore empty strings... because '' < 10 is true
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) { if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
var cachedValue, result, txt, var cachedValue, result, txt,
table = c.table, table = c.table,
index = data.index, parsed = data.parsed[ data.index ],
parsed = data.parsed[index], query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ), parser = c.parsers[ data.index ],
parser = c.parsers[index],
savedSearch = query; savedSearch = query;
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) { if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) ); txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true ); result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query; query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
} }
// iExact may be numeric - see issue #149; // iExact may be numeric - see issue #149;
@ -595,10 +593,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact; txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table ); cachedValue = ts.formatFloat( txt, table );
} }
if ( tsf.regex.gtTest.test( data.iFilter ) ) { if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query; result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) { } else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query; result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
} }
// keep showing all rows if nothing follows the operator // keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) { if ( !result && savedSearch === '' ) {
@ -610,13 +608,13 @@
}, },
// Look for a not match // Look for a not match
notMatch: function( c, data ) { notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) { if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx, var indx,
txt = data.iFilter.replace( '!', '' ), txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsf.regex.exact.test( filter ) ) { if ( tsfRegex.exact.test( filter ) ) {
// look for exact not matches - see #628 // look for exact not matches - see #628
filter = filter.replace( tsf.regex.exact, '' ); filter = filter.replace( tsfRegex.exact, '' );
return filter === '' ? true : $.trim( filter ) !== data.iExact; return filter === '' ? true : $.trim( filter ) !== data.iExact;
} else { } else {
indx = data.iExact.search( $.trim( filter ) ); indx = data.iExact.search( $.trim( filter ) );
@ -628,29 +626,29 @@
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric // Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
exact: function( c, data ) { exact: function( c, data ) {
/*jshint eqeqeq:false */ /*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) { if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ), var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact; return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
} }
return null; return null;
}, },
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu! // Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) { range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) { if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2, var result, tmp, range1, range2,
table = c.table, table = c.table,
index = data.index, index = data.index,
parsed = data.parsed[index], parsed = data.parsed[index],
// make sure the dash is for a range and not indicating a negative number // make sure the dash is for a range and not indicating a negative number
query = data.iFilter.split( tsf.regex.toSplit ); query = data.iFilter.split( tsfRegex.toSplit );
tmp = query[0].replace( ts.regex.nondigit, '' ) || ''; tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
tmp = query[1].replace( ts.regex.nondigit, '' ) || ''; tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || c.parsers[index].type === 'numeric' ) { if ( parsed || c.parsers[ index ].type === 'numeric' ) {
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1; range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
@ -671,18 +669,16 @@
}, },
// Look for wild card: ? = single, * = multiple, or | = logical OR // Look for wild card: ? = single, * = multiple, or | = logical OR
wild : function( c, data ) { wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) { if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var index = data.index, var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
// look for an exact match with the 'or' unless the 'filter-match' class is found // look for an exact match with the 'or' unless the 'filter-match' class is found
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) { if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
query = data.isMatch ? query : '^(' + query + ')$'; query = data.isMatch ? query : '^(' + query + ')$';
} }
// parsing the filter may not work properly when using wildcards =/ // parsing the filter may not work properly when using wildcards =/
try { try {
return new RegExp( return new RegExp(
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ), query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
c.widgetOptions.filter_ignoreCase ? 'i' : '' c.widgetOptions.filter_ignoreCase ? 'i' : ''
) )
.test( data.exact ); .test( data.exact );
@ -694,21 +690,18 @@
}, },
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license ) // fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) { fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) { if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx, var indx,
patternIndx = 0, patternIndx = 0,
len = data.iExact.length, len = data.iExact.length,
txt = data.iFilter.slice( 1 ), txt = data.iFilter.slice( 1 ),
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; pattern = tsf.parseFilter( c, txt, data ) || '';
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) { if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1; patternIndx += 1;
} }
} }
if ( patternIndx === pattern.length ) { return patternIndx === pattern.length;
return true;
}
return false;
} }
return null; return null;
} }
@ -721,8 +714,7 @@
and : 'and' and : 'and'
}, ts.language ); }, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect, var options, string, txt, $header, column, filters, val, fxn, noSelect;
regex = tsf.regex;
c.$table.addClass( 'hasFilters' ); c.$table.addClass( 'hasFilters' );
// define timers so using clearTimeout won't cause an undefined error // define timers so using clearTimeout won't cause an undefined error
@ -733,8 +725,8 @@
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]'; wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]'; wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}'; val = '\\{' + tsfRegex.query + '\\}';
$.extend( regex, { $.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ), child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ), filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ), alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -1012,8 +1004,10 @@
c.$table.data( 'lastSearch', filters ); c.$table.data( 'lastSearch', filters );
return filters; return filters;
}, },
parseFilter: function( c, filter, column, parsed ) { parseFilter: function( c, filter, data, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter; return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
}, },
buildRow: function( table, c, wo ) { buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp, var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -1265,8 +1259,8 @@
}, },
defaultFilter: function( filter, mask ) { defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; } if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery, var regex = tsfRegex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length, maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ], query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1, len = query.length - 1,
indx = 0, indx = 0,
@ -1363,9 +1357,8 @@
return filterMatched; return filterMatched;
}, },
processRow: function( c, data, vars ) { processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched, var result, filterMatched,
fxn, ffxn, txt, fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions, wo = c.widgetOptions,
showRow = true, showRow = true,
@ -1444,7 +1437,7 @@
result = data.rawArray[ columnIndex ] || ''; result = data.rawArray[ columnIndex ] || '';
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405 data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
} }
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ? data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
data.exact.toLowerCase() : data.exact; data.exact.toLowerCase() : data.exact;
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' ); data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -1462,21 +1455,13 @@
data.filter = ts.replaceAccents( data.filter ); data.filter = ts.replaceAccents( data.filter );
} }
val = true;
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
// val is used to indicate that a filter select is using a default filter;
// so we override the exact & partial matches
val = false;
}
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ), // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
// data.filter = case sensitive // data.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter; data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ]; fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null; filterMatched = null;
if ( fxn || ( hasSelect && val ) ) { if ( fxn ) {
if ( fxn === true || hasSelect ) { if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found // default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ? filterMatched = data.isMatch ?
// data.iExact may be a number // data.iExact may be a number
@ -1502,7 +1487,7 @@
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
txt = ( data.iExact + data.childRowText ) txt = ( data.iExact + data.childRowText )
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) ); .indexOf( tsf.parseFilter( c, data.iFilter, data ) );
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) ); result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
} }
} else { } else {
@ -1522,7 +1507,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx, isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt, notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ), storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters // data object passed to filters; anyMatch is a flag for the filters
@ -1604,7 +1588,7 @@
); );
if ( wo.filter_columnAnyMatch ) { if ( wo.filter_columnAnyMatch ) {
// specific columns search // specific columns search
query = data.anyMatchFilter.split( regex.andSplit ); query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false; injected = false;
for ( indx = 0; indx < query.length; indx++ ) { for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' ); res = query[ indx ].split( ':' );
@ -1639,12 +1623,12 @@
// there are no changes from beginning of filter // there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 && val.indexOf( lastSearch[indx] || '' ) === 0 &&
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string // if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
!regex.alreadyFiltered.test( val ) && !tsfRegex.alreadyFiltered.test( val ) &&
// if we are not doing exact matches, using '|' ( logical or ) or not '!' // if we are not doing exact matches, using '|' ( logical or ) or not '!'
!regex.exactTest.test( val ) && !tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative // don't search only filtered if the value is negative
// ( '> -10' => '> -100' will ignore hidden rows ) // ( '> -10' => '> -100' will ignore hidden rows )
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) && !( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593 // if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length && !( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) ); !c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -1662,7 +1646,7 @@
// replace accents // replace accents
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter ); data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
} }
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) { if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter ); data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
// clear search filtered flag because default filters are not saved to the last search // clear search filtered flag because default filters are not saved to the last search
searchFiltered = false; searchFiltered = false;
@ -1679,9 +1663,9 @@
txt = $rows[ rowIndex ].className; txt = $rows[ rowIndex ].className;
// the first row can never be a child row // the first row can never be a child row
isChild = rowIndex && regex.child.test( txt ); isChild = rowIndex && tsfRegex.child.test( txt );
// skip child rows & already filtered rows // skip child rows & already filtered rows
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) { if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue; continue;
} }
@ -1791,7 +1775,6 @@
// custom select source function for a SPECIFIC COLUMN // custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail ); arry = fxn( table, column, onlyAvail );
} }
if ( arry === false ) { if ( arry === false ) {
// fall back to original method // fall back to original method
arry = tsf.getOptions( table, column, onlyAvail ); arry = tsf.getOptions( table, column, onlyAvail );
@ -1805,18 +1788,19 @@
return false; return false;
} }
table = $( table )[0]; table = $( table )[0];
var cts, txt, indx, len, var cts, txt, indx, len, parsedTxt, str,
c = table.config, c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns, validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = []; parsed = [];
// get unique elements and sort the list // get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ), // if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort // then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) { arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx; return $.inArray( value, arry ) === indx;
}); });
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) { if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options // unsorted select options
return arry; return arry;
@ -1825,22 +1809,30 @@
// parse select option values // parse select option values
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
txt = arry[ indx ]; txt = arry[ indx ];
// check for object
str = txt.text ? txt.text : txt;
// sortNatural breaks if you don't pass it strings
parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( str, table, [], column ) || str ).toString();
parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
// parse array data using set column parser; this DOES NOT pass the original // parse array data using set column parser; this DOES NOT pass the original
// table cell to the parser format function // table cell to the parser format function
parsed.push({ if ( txt.text ) {
t : txt, txt.parsed = parsedTxt;
// check parser length - fixes #934 parsed.push( txt );
p : validColumn && c.parsers && c.parsers.length && } else {
c.parsers[ column ].format( txt, table, [], column ) || txt parsed.push({
}); text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
} }
// sort parsed select options // sort parsed select options
cts = c.textSorter || ''; cts = c.textSorter || '';
parsed.sort( function( a, b ) { parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings var x = a.parsed,
var x = a.p.toString(), y = b.parsed;
y = b.p.toString();
if ( validColumn && typeof cts === 'function' ) { if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter // custom OVERALL text sorter
return cts( x, y, true, column, table ); return cts( x, y, true, column, table );
@ -1858,7 +1850,7 @@
arry = []; arry = [];
len = parsed.length; len = parsed.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t ); arry.push( parsed[indx] );
} }
return arry; return arry;
} }
@ -1918,7 +1910,7 @@
return; return;
} }
var indx, val, txt, t, $filters, $filter, var indx, val, txt, t, $filters, $filter, option,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
node = c.$headerIndexed[ column ], node = c.$headerIndexed[ column ],
@ -1943,23 +1935,45 @@
if ( $.isArray( arry ) ) { if ( $.isArray( arry ) ) {
// build option list // build option list
for ( indx = 0; indx < arry.length; indx++ ) { for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '&quot;' ); option = arry[ indx ];
val = txt; if ( option.text ) {
// allow including a symbol in the selectSource array // OBJECT!! add data-function-name in case the value is set in filter_functions
// 'a-z|A through Z' so that 'a-z' becomes the option value option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) { // support jQuery < v1.8, otherwise the below code could be shortened to
t = txt.split( wo.filter_selectSourceSeparator ); // options += $( '<option>', option )[ 0 ].outerHTML;
val = t[0]; options += '<option';
txt = t[1]; for ( val in option ) {
if ( option.hasOwnProperty( val ) && val !== 'text' ) {
options += ' ' + val + '="' + option[ val ] + '"';
}
}
if ( !option.value ) {
options += ' value="' + option.text + '"';
}
options += '>' + option.text + '</option>';
// above code is needed in jQuery < v1.8
// make sure we don't turn an object into a string (objects without a "text" property)
} else if ( '' + option !== '[object Object]' ) {
txt = option = ( '' + option ).replace( tsfRegex.quote, '&quot;' );
val = txt;
// allow including a symbol in the selectSource array
// 'a-z|A through Z' so that 'a-z' becomes the option value
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
t = txt.split( wo.filter_selectSourceSeparator );
val = t[0];
txt = t[1];
}
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += option !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + option + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += arry[indx] !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// clear arry so it doesn't get appended twice // clear arry so it doesn't get appended twice
arry = []; arry = [];
@ -2005,6 +2019,9 @@
} }
}; };
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) { ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols, var i, $filters, $column, cols,
filters = false, filters = false,

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! Parser: filetype */ /*! Parser: filetype - updated 11/10/2015 (v2.24.4) */
!function(a){"use strict";a.tablesorter.fileTypes={separator:"|",equivalents:{"3D Image":"3dm|3ds|dwg|max|obj",Audio:"aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma",Compressed:"7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo",Database:"csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml",Development:"asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb",Document:"doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri",Executable:"apk|app|com|exe|gadget|lnk|msi",Fonts:"eot|fnt|fon|otf|ttf|woff",Icons:"ani|cur|icns|ico",Images:"bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp",Presentation:"pps|ppt",Published:"chp|epub|lit|pub|ppp|fm|mobi",Script:"as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf",Styles:"css|less|sass",Text:"info|log|md|markdown|nfo|tex|text|txt",Vectors:"awg|ai|eps|cdr|ps|svg",Video:"asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv",Web:"asp|aspx|cer|cfm|htm|html|php|url|xhtml"}},a.tablesorter.addParser({id:"filetype",is:function(){return!1},format:function(b,c){var d,e=c.config,f=e.widgetOptions,g=f.group_separator||"-",h=b.lastIndexOf("."),i=a.tablesorter.fileTypes.separator,j=a.tablesorter.fileTypes.matching,k=a.tablesorter.fileTypes.equivalents;if(j||(d=[],a.each(k,function(a,b){d.push(b)}),j=a.tablesorter.fileTypes.matching=i+d.join(i)+i),h>=0&&(d=i+b.substring(h+1,b.length)+i,j.indexOf(d)>=0))for(h in k)if((i+k[h]+i).indexOf(d)>=0)return h+("/"!==g.toString().charAt(0)?f.group_separator:"-")+b;return b},type:"text"}),a.tablesorter.addParser({id:"file-extension",is:function(){return!1},format:function(a){var b,c=a.split(".");return c.length?(b=c.pop(),c.unshift(b),c.join(".")):a},type:"text"})}(jQuery); !function(a){"use strict";a.tablesorter.fileTypes={separator:"|",equivalents:{"3D Image":"3dm|3ds|dwg|max|obj",Audio:"aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma",Compressed:"7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo",Database:"csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml",Development:"asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb",Document:"doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri",Executable:"apk|app|com|exe|gadget|lnk|msi",Fonts:"eot|fnt|fon|otf|ttf|woff",Icons:"ani|cur|icns|ico",Images:"bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp",Presentation:"pps|ppt",Published:"chp|epub|lit|pub|ppp|fm|mobi",Script:"as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf",Styles:"css|less|sass",Text:"info|log|md|markdown|nfo|tex|text|txt",Vectors:"awg|ai|eps|cdr|ps|svg",Video:"asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv",Web:"asp|aspx|cer|cfm|htm|html|php|url|xhtml"}},a.tablesorter.addParser({id:"filetype",is:function(){return!1},format:function(b,c){var d,e=c.config,f=e.widgetOptions,g=f.group_separator||"-",h=b.lastIndexOf("."),i=a.tablesorter.fileTypes.separator,j=a.tablesorter.fileTypes.matching,k=a.tablesorter.fileTypes.equivalents;if(j||(d=[],a.each(k,function(a,b){d.push(b)}),j=a.tablesorter.fileTypes.matching=i+d.join(i)+i),h>=0&&(d=i+b.substring(h+1,b.length)+i,j.indexOf(d)>=0))for(h in k)if((i+k[h]+i).indexOf(d)>=0)return h+("/"!==g.toString().charAt(0)?f.group_separator:"-")+b;return b},type:"text"}),a.tablesorter.addParser({id:"file-extension",is:function(){return!1},format:function(a){var b,c=a.split(".");return c.length?(b=c.pop(),c.unshift(b),c.join(".")):a},type:"text"})}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! Widget: headerTitles - updated 11/8/2015 (v2.24.4) */ /*! Widget: headerTitles - updated 11/10/2015 (v2.24.4) */
!function(a){"use strict";var b=a.tablesorter;b.addWidget({id:"headerTitles",options:{headerTitle_useAria:!1,headerTitle_tooltip:"",headerTitle_cur_text:[" sort: A - Z"," sort: Z - A","ly unsorted"],headerTitle_cur_numeric:[" sort: 0 - 9"," sort: 9 - 0","ly unsorted"],headerTitle_nxt_text:[" sort: A - Z"," sort: Z - A","remove sort"],headerTitle_nxt_numeric:[" sort: 0 - 9"," sort: 9 - 0","remove sort"],headerTitle_output_sorted:"current{current}; activate to {next}",headerTitle_output_unsorted:"current{current}; activate to {next} ",headerTitle_output_nosort:"No sort available",headerTitle_type:[],headerTitle_callback:null},init:function(b,c,d,e){d.$table.on("refreshHeaderTitle",function(){c.format(b,d,e)}),a.isArray(e.headerTitle_tooltip)?d.$headers.each(function(){a(this).addClass(e.headerTitle_tooltip[this.column]||"")}):""!==e.headerTitle_tooltip&&d.$headers.addClass(e.headerTitle_tooltip)},format:function(c,d,e){var f;d.$headers.each(function(){var c=a(this),g=parseInt(c.attr("data-column"),10),h=e.headerTitle_type[g]||d.parsers[g].type||"text",i=c.hasClass(b.css.sortAsc)?0:c.hasClass(b.css.sortDesc)?1:2,j=d.sortVars[g].order[(d.sortVars[g].count+1)%(d.sortReset?3:2)];e.headerTitle_useAria?f=c.attr("aria-label")||e.headerTitle_output_nosort||"":(f=(e.headerTitle_prefix||"")+(c.hasClass("sorter-false")?e.headerTitle_output_nosort:b.isValueInArray(g,d.sortList)>=0?e.headerTitle_output_sorted:e.headerTitle_output_unsorted),f=f.replace(/\{(current|next|name)\}/gi,function(a){return{"{name}":c.text(),"{current}":e["headerTitle_cur_"+h][i]||"","{next}":e["headerTitle_nxt_"+h][j]||""}[a.toLowerCase()]})),c.attr("title",a.isFunction(e.headerTitle_callback)?e.headerTitle_callback(c,f):f)})},remove:function(b,c,d){c.$headers.attr("title",""),c.$table.off("refreshHeaderTitle"),a.isArray(d.headerTitle_tooltip)?c.$headers.each(function(){a(this).removeClass(d.headerTitle_tooltip[this.column]||"")}):""!==d.headerTitle_tooltip&&c.$headers.removeClass(d.headerTitle_tooltip)}})}(jQuery); !function(a){"use strict";var b=a.tablesorter;b.addWidget({id:"headerTitles",options:{headerTitle_useAria:!1,headerTitle_tooltip:"",headerTitle_cur_text:[" sort: A - Z"," sort: Z - A","ly unsorted"],headerTitle_cur_numeric:[" sort: 0 - 9"," sort: 9 - 0","ly unsorted"],headerTitle_nxt_text:[" sort: A - Z"," sort: Z - A","remove sort"],headerTitle_nxt_numeric:[" sort: 0 - 9"," sort: 9 - 0","remove sort"],headerTitle_output_sorted:"current{current}; activate to {next}",headerTitle_output_unsorted:"current{current}; activate to {next} ",headerTitle_output_nosort:"No sort available",headerTitle_type:[],headerTitle_callback:null},init:function(b,c,d,e){d.$table.on("refreshHeaderTitle",function(){c.format(b,d,e)}),a.isArray(e.headerTitle_tooltip)?d.$headers.each(function(){a(this).addClass(e.headerTitle_tooltip[this.column]||"")}):""!==e.headerTitle_tooltip&&d.$headers.addClass(e.headerTitle_tooltip)},format:function(c,d,e){var f;d.$headers.each(function(){var c=a(this),g=parseInt(c.attr("data-column"),10),h=e.headerTitle_type[g]||d.parsers[g].type||"text",i=c.hasClass(b.css.sortAsc)?0:c.hasClass(b.css.sortDesc)?1:2,j=d.sortVars[g].order[(d.sortVars[g].count+1)%(d.sortReset?3:2)];e.headerTitle_useAria?f=c.attr("aria-label")||e.headerTitle_output_nosort||"":(f=(e.headerTitle_prefix||"")+(c.hasClass("sorter-false")?e.headerTitle_output_nosort:b.isValueInArray(g,d.sortList)>=0?e.headerTitle_output_sorted:e.headerTitle_output_unsorted),f=f.replace(/\{(current|next|name)\}/gi,function(a){return{"{name}":c.text(),"{current}":e["headerTitle_cur_"+h][i]||"","{next}":e["headerTitle_nxt_"+h][j]||""}[a.toLowerCase()]})),c.attr("title",a.isFunction(e.headerTitle_callback)?e.headerTitle_callback(c,f):f)})},remove:function(b,c,d){c.$headers.attr("title",""),c.$table.off("refreshHeaderTitle"),a.isArray(d.headerTitle_tooltip)?c.$headers.each(function(){a(this).removeClass(d.headerTitle_tooltip[this.column]||"")}):""!==d.headerTitle_tooltip&&c.$headers.removeClass(d.headerTitle_tooltip)}})}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! Widget: sort2Hash (BETA) - updated 11/8/2015 (v2.24.4) */ /*! Widget: sort2Hash (BETA) - updated 11/10/2015 (v2.24.4) */
!function(a){"use strict";var b=a.tablesorter||{},c=b.sort2Hash={init:function(d,e){var f,g,h,i,j=d.table,k=d.pager,l=b.hasWidget(j,"saveSort"),m=c.decodeHash(d,e,"sort");(m&&!l||m&&l&&e.sort2Hash_overrideSaveSort)&&c.convertString2Sort(d,e,m),b.hasWidget(d.table,"pager")&&(g=parseInt(c.decodeHash(d,e,"page"),10),h=k.page=0>g?0:g>k.totalPages?k.totalPages-1:g,i=k.size=parseInt(c.decodeHash(d,e,"size"),10)),b.hasWidget(j,"filter")&&(f=c.decodeHash(d,e,"filter"),f&&(f=f.split(e.sort2Hash_separator),d.$table.one("tablesorter-ready",function(){setTimeout(function(){d.$table.one("filterEnd",function(){a(this).trigger("pageAndSize",[h,i])}),a.tablesorter.setFilters(j,f,!0)},100)}))),f||d.$table.one("tablesorter-ready",function(){d.$table.trigger("pageAndSize",[h,i])}),d.$table.on("sortEnd.sort2hash filterEnd.sort2hash pagerComplete.sort2Hash",function(){this.hasInitialized&&c.setHash(this.config,this.config.widgetOptions)})},getTableId:function(b,c){return c.sort2Hash_tableId||b.table.id||"table"+a("table").index(b.$table)},regexEscape:function(a){return a.replace(/([\.\^\$\*\+\-\?\(\)\[\]\{\}\\\|])/g,"\\$1")},convertString2Sort:function(a,b,d){for(var e,f,g,h,i,j,k=d.split(b.sort2Hash_separator),l=0,m=k.length,n=[];m>l;){if(f=k[l++],h=parseInt(f,10),isNaN(h)||h>a.columns)for(e=new RegExp("("+c.regexEscape(f)+")","i"),i=0;i<a.columns;i++)j=a.$headerIndexed[i],e.test(j.attr(b.sort2Hash_headerTextAttr))&&(f=i,i=a.columns);g=k[l++],"undefined"!=typeof f&&"undefined"!=typeof g&&(isNaN(g)&&(g=g.indexOf(b.sort2Hash_directionText[1])>-1?1:0),n.push([f,g]))}n.length&&(a.sortList=n)},convertSort2String:function(b,c){var d,e,f,g,h=[],i=b.sortList||[],j=i.length;for(d=0;j>d;d++)f=i[d][0],e=a.trim(b.$headerIndexed[f].attr(c.sort2Hash_headerTextAttr)),h.push(""!==e?encodeURIComponent(e):f),g=c.sort2Hash_directionText[i[d][1]],h.push(g);return h.join(c.sort2Hash_separator)},convertFilter2String:function(b,c){var d,e,f,g,h=[],i=b.sortList||[],j=i.length;for(d=0;j>d;d++)f=i[d][0],e=a.trim(b.$headerIndexed[f].attr(c.sort2Hash_headerTextAttr)),f="undefined"!=typeof e?encodeURIComponent(e):f,h.push(f),g=c.sort2Hash_directionText[i[d][1]],h.push(g);return h.join(c.sort2Hash_separator)},getParam:function(a,b,d){b||(b=window.location.hash);var e=new RegExp("[\\?&]"+c.regexEscape(a)+"=([^&#]*)"),f=e.exec(b);return d?e:null===f?"":decodeURIComponent(f[1])},removeParam:function(a,b){b||(b=window.location.hash);var d,e=c.getParam(a,b,!0),f=[],g=b.split("&"),h=g.length;for(d=0;h>d;d++)e.test("&"+g[d])||f.push(g[d]);return f.length?f.join("&"):""},encodeHash:function(a,b,d,e,f){var g=!1,h=c.getTableId(a,b);return"function"==typeof b.sort2Hash_encodeHash&&(g=b.sort2Hash_encodeHash(a,h,d,e,f||e)),g===!1&&(g="&"+d+"["+h+"]="+e),g},decodeHash:function(a,b,d){var e=!1,f=c.getTableId(a,b);return"function"==typeof b.sort2Hash_decodeHash&&(e=b.sort2Hash_decodeHash(a,f,d)),e===!1&&(e=c.getParam(d+"["+f+"]")),e||""},cleanHash:function(a,b,d,e){var f=!1,g=c.getTableId(a,b);return"function"==typeof b.sort2Hash_cleanHash&&(f=b.sort2Hash_cleanHash(a,g,d,e)),f===!1&&(f=c.removeParam(d+"["+g+"]",e)),f||""},setHash:function(d,e){var f="",g=window.location.hash,h=b.hasWidget(d.table,"pager"),i=b.hasWidget(d.table,"filter"),j=c.convertSort2String(d,e),k=i&&""!==d.lastSearch.join("")?d.lastSearch:[],l=encodeURIComponent(k.join(d.widgetOptions.sort2Hash_separator)),m={sort:j?c.encodeHash(d,e,"sort",j,d.sortList):"",page:h?c.encodeHash(d,e,"page",d.pager.page+1):"",size:h?c.encodeHash(d,e,"size",d.pager.size):"",filter:l?c.encodeHash(d,e,"filter",l,k):""};a.each(m,function(a,b){g=c.cleanHash(d,e,a,g),f+=b}),window.location.hash=((window.location.hash||"").replace("#","").length?g:e.sort2Hash_hash)+f}};b.addWidget({id:"sort2Hash",priority:60,options:{sort2Hash_hash:"#",sort2Hash_separator:"-",sort2Hash_headerTextAttr:"data-header",sort2Hash_directionText:[0,1],sort2Hash_overrideSaveSort:!1},init:function(a,b,d,e){c.init(d,e)},remove:function(a,b){b.$table.off(".sort2hash")}})}(jQuery); !function(a){"use strict";var b=a.tablesorter||{},c=b.sort2Hash={init:function(d,e){var f,g,h,i,j=d.table,k=d.pager,l=b.hasWidget(j,"saveSort"),m=c.decodeHash(d,e,"sort");(m&&!l||m&&l&&e.sort2Hash_overrideSaveSort)&&c.convertString2Sort(d,e,m),b.hasWidget(d.table,"pager")&&(g=parseInt(c.decodeHash(d,e,"page"),10),h=k.page=0>g?0:g>k.totalPages?k.totalPages-1:g,i=k.size=parseInt(c.decodeHash(d,e,"size"),10)),b.hasWidget(j,"filter")&&(f=c.decodeHash(d,e,"filter"),f&&(f=f.split(e.sort2Hash_separator),d.$table.one("tablesorter-ready",function(){setTimeout(function(){d.$table.one("filterEnd",function(){a(this).trigger("pageAndSize",[h,i])}),a.tablesorter.setFilters(j,f,!0)},100)}))),f||d.$table.one("tablesorter-ready",function(){d.$table.trigger("pageAndSize",[h,i])}),d.$table.on("sortEnd.sort2hash filterEnd.sort2hash pagerComplete.sort2Hash",function(){this.hasInitialized&&c.setHash(this.config,this.config.widgetOptions)})},getTableId:function(b,c){return c.sort2Hash_tableId||b.table.id||"table"+a("table").index(b.$table)},regexEscape:function(a){return a.replace(/([\.\^\$\*\+\-\?\(\)\[\]\{\}\\\|])/g,"\\$1")},convertString2Sort:function(a,b,d){for(var e,f,g,h,i,j,k=d.split(b.sort2Hash_separator),l=0,m=k.length,n=[];m>l;){if(f=k[l++],h=parseInt(f,10),isNaN(h)||h>a.columns)for(e=new RegExp("("+c.regexEscape(f)+")","i"),i=0;i<a.columns;i++)j=a.$headerIndexed[i],e.test(j.attr(b.sort2Hash_headerTextAttr))&&(f=i,i=a.columns);g=k[l++],"undefined"!=typeof f&&"undefined"!=typeof g&&(isNaN(g)&&(g=g.indexOf(b.sort2Hash_directionText[1])>-1?1:0),n.push([f,g]))}n.length&&(a.sortList=n)},convertSort2String:function(b,c){var d,e,f,g,h=[],i=b.sortList||[],j=i.length;for(d=0;j>d;d++)f=i[d][0],e=a.trim(b.$headerIndexed[f].attr(c.sort2Hash_headerTextAttr)),h.push(""!==e?encodeURIComponent(e):f),g=c.sort2Hash_directionText[i[d][1]],h.push(g);return h.join(c.sort2Hash_separator)},convertFilter2String:function(b,c){var d,e,f,g,h=[],i=b.sortList||[],j=i.length;for(d=0;j>d;d++)f=i[d][0],e=a.trim(b.$headerIndexed[f].attr(c.sort2Hash_headerTextAttr)),f="undefined"!=typeof e?encodeURIComponent(e):f,h.push(f),g=c.sort2Hash_directionText[i[d][1]],h.push(g);return h.join(c.sort2Hash_separator)},getParam:function(a,b,d){b||(b=window.location.hash);var e=new RegExp("[\\?&]"+c.regexEscape(a)+"=([^&#]*)"),f=e.exec(b);return d?e:null===f?"":decodeURIComponent(f[1])},removeParam:function(a,b){b||(b=window.location.hash);var d,e=c.getParam(a,b,!0),f=[],g=b.split("&"),h=g.length;for(d=0;h>d;d++)e.test("&"+g[d])||f.push(g[d]);return f.length?f.join("&"):""},encodeHash:function(a,b,d,e,f){var g=!1,h=c.getTableId(a,b);return"function"==typeof b.sort2Hash_encodeHash&&(g=b.sort2Hash_encodeHash(a,h,d,e,f||e)),g===!1&&(g="&"+d+"["+h+"]="+e),g},decodeHash:function(a,b,d){var e=!1,f=c.getTableId(a,b);return"function"==typeof b.sort2Hash_decodeHash&&(e=b.sort2Hash_decodeHash(a,f,d)),e===!1&&(e=c.getParam(d+"["+f+"]")),e||""},cleanHash:function(a,b,d,e){var f=!1,g=c.getTableId(a,b);return"function"==typeof b.sort2Hash_cleanHash&&(f=b.sort2Hash_cleanHash(a,g,d,e)),f===!1&&(f=c.removeParam(d+"["+g+"]",e)),f||""},setHash:function(d,e){var f="",g=window.location.hash,h=b.hasWidget(d.table,"pager"),i=b.hasWidget(d.table,"filter"),j=c.convertSort2String(d,e),k=i&&""!==d.lastSearch.join("")?d.lastSearch:[],l=encodeURIComponent(k.join(d.widgetOptions.sort2Hash_separator)),m={sort:j?c.encodeHash(d,e,"sort",j,d.sortList):"",page:h?c.encodeHash(d,e,"page",d.pager.page+1):"",size:h?c.encodeHash(d,e,"size",d.pager.size):"",filter:l?c.encodeHash(d,e,"filter",l,k):""};a.each(m,function(a,b){g=c.cleanHash(d,e,a,g),f+=b}),window.location.hash=((window.location.hash||"").replace("#","").length?g:e.sort2Hash_hash)+f}};b.addWidget({id:"sort2Hash",priority:60,options:{sort2Hash_hash:"#",sort2Hash_separator:"-",sort2Hash_headerTextAttr:"data-header",sort2Hash_directionText:[0,1],sort2Hash_overrideSaveSort:!1},init:function(a,b,d,e){c.init(d,e)},remove:function(a,b){b.$table.off(".sort2hash")}})}(jQuery);

View File

@ -1,4 +1,4 @@
/*! tablesorter enable/disable sort & filter (BETA) - 11/8/2015 (v2.24.4) /*! tablesorter enable/disable sort & filter (BETA) - 11/10/2015 (v2.24.4)
* Requires tablesorter v2.24.4+ & jQuery 1.7+ * Requires tablesorter v2.24.4+ & jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -457,7 +457,7 @@
<li><a href="example-widget-column-selector.html">Column selector widget</a> (<span class="version">v2.15</span>; <span class="version updated">v2.24.0</span>).</li> <li><a href="example-widget-column-selector.html">Column selector widget</a> (<span class="version">v2.15</span>; <span class="version updated">v2.24.0</span>).</li>
<li><a href="example-widget-editable.html">Content editable widget</a> (v2.9; <span class="version updated">v2.24.0</span>).</li> <li><a href="example-widget-editable.html">Content editable widget</a> (v2.9; <span class="version updated">v2.24.0</span>).</li>
<li><span class="label label-info">Beta</span> <a href="example-dragtable.html">Dragtable mod</a> - (jQuery UI widget for column reordering [<a href="http://stackoverflow.com/a/27770224/145346">ref</a>]; <span class="version">v2.24.0</span>).</li> <li><span class="label label-info">Beta</span> <a href="example-dragtable.html">Dragtable mod</a> - (jQuery UI widget for column reordering [<a href="http://stackoverflow.com/a/27770224/145346">ref</a>]; <span class="version">v2.24.0</span>).</li>
<li><span class="results">&dagger;</span> Filter widget (<span class="version updated">v2.24.3</span>): <li><span class="results">&dagger;</span> Filter widget (<span class="version updated">v2.24.4</span>):
<ul> <ul>
<li><a href="example-widget-filter.html">basic</a> (v2.0.18; <span class="version updated">v2.23.5</span>).</li> <li><a href="example-widget-filter.html">basic</a> (v2.0.18; <span class="version updated">v2.23.5</span>).</li>
<li><a href="example-widget-filter-any-match.html">external option (match any column)</a> (<span class="version">v2.13.3</span>; <span class="version updated">v2.22.0</span>).</li> <li><a href="example-widget-filter-any-match.html">external option (match any column)</a> (<span class="version">v2.13.3</span>; <span class="version updated">v2.22.0</span>).</li>
@ -474,13 +474,13 @@
<li><span class="label label-info">Beta</span> <a href="example-widget-formatter.html">Formatter widget</a> (<span class="version">v2.19.1</span>).</li> <li><span class="label label-info">Beta</span> <a href="example-widget-formatter.html">Formatter widget</a> (<span class="version">v2.19.1</span>).</li>
<li>Grouping rows widget: <li>Grouping rows widget:
<ul> <ul>
<li><a href="example-widget-grouping.html">basic</a> (v2.8; <span class="version updated">v2.24.1</span>).</li> <li><a href="example-widget-grouping.html">basic</a> (v2.8; <span class="version updated">v2.24.4</span>).</li>
<li><a href="example-widget-grouping-filter-childrows.html">Grouping + filter + child rows</a> (<span class="updated version">v2.15.12</span>).</li> <li><a href="example-widget-grouping-filter-childrows.html">Grouping + filter + child rows</a> (<span class="updated version">v2.15.12</span>).</li>
</ul> </ul>
</li> </li>
<li><a href="example-widget-header-titles.html">Header titles widget</a> (v2.15.6; <span class="version updated">v2.24.4</span>).</li> <li><a href="example-widget-header-titles.html">Header titles widget</a> (v2.15.6; <span class="version updated">v2.24.4</span>).</li>
<li><span class="label label-info">Beta</span> <a href="example-widget-lazyload.html">Lazyload widget</a> (<span class="version">v2.24.0</span>).</li> <li><span class="label label-info">Beta</span> <a href="example-widget-lazyload.html">Lazyload widget</a> (<span class="version">v2.24.0</span>).</li>
<li><a href="example-widget-math.html">Math widget</a> (<span class="version">v2.16</span>; <span class="version updated">v2.24.0</span>).</li> <li><a href="example-widget-math.html">Math widget</a> (<span class="version">v2.16</span>; <span class="version updated">v2.24.4</span>).</li>
<li> <li>
<a href="example-widget-output.html">Output widget</a> (<span class="version">v2.16</span>; <span class="version updated">v2.24.0</span>). <a href="example-widget-output.html">Output widget</a> (<span class="version">v2.16</span>; <span class="version updated">v2.24.0</span>).
<br><br> <br><br>

View File

@ -4,7 +4,7 @@
*/ */
/*! tablesorter (FORK) - updated 11-06-2015 (v2.24.3)*/ /*! tablesorter (FORK) - updated 11-10-2015 (v2.24.4)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -16,7 +16,7 @@
} }
}(function($) { }(function($) {
/*! TableSorter (FORK) v2.24.3 *//* /*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -39,7 +39,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.24.3', version : '2.24.4',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -157,12 +157,13 @@
// labels applied to sortable headers for accessibility (aria) support // labels applied to sortable headers for accessibility (aria) support
language : { language : {
sortAsc : 'Ascending sort applied, ', sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ', sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ', sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort', sortDisabled : 'sorting is disabled',
nextDesc : 'activate to apply a descending sort', nextAsc : 'activate to apply an ascending sort',
nextNone : 'activate to remove the sort' nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
}, },
regex : { regex : {
@ -1011,7 +1012,7 @@
*/ */
setHeadersCss : function( c ) { setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp, var $sorted, indx, column,
list = c.sortList, list = c.sortList,
len = list.length, len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone, none = ts.css.sortNone + ' ' + c.cssNone,
@ -1079,50 +1080,62 @@
} }
// add verbose aria labels // add verbose aria labels
len = c.$headers.length; len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
$header = $headers.eq( indx ); ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
if ( $header.length ) { }
header = $headers[ indx ]; },
column = parseInt( $header.attr( 'data-column' ), 10 );
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ]; // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) {
var column = parseInt( $header.attr( 'data-column' ), 10 ),
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone'; $header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
ts.language[ tmp ] + if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ]; txt += ts.language.sortDisabled;
$header.attr( 'aria-label', txt ); } else {
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ];
// if nextSort
txt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
} }
$header.attr( 'aria-label', txt );
} }
}, },
updateHeader : function( c ) { updateHeader : function( c ) {
var index, isDisabled, $th, col, var index, isDisabled, $header, col,
table = c.table, table = c.table,
len = c.$headers.length; len = c.$headers.length;
for ( index = 0; index < len; index++ ) { for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index ); $header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true ); col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set // add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false'; isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled; ts.setColumnSort( c, $header, isDisabled );
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled ); }
// disable tab index on disabled cells },
if ( c.tabIndex ) {
if ( isDisabled ) { setColumnSort : function( c, $header, isDisabled ) {
$th.removeAttr( 'tabindex' ); var id = c.table.id;
} else { $header[ 0 ].sortDisabled = isDisabled;
$th.attr( 'tabindex', '0' ); $header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )
} .attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$header.removeAttr( 'tabindex' );
} else {
$header.attr( 'tabindex', '0' );
} }
// aria-controls - requires table ID }
if ( table.id ) { // aria-controls - requires table ID
if ( isDisabled ) { if ( id ) {
$th.removeAttr( 'aria-controls' ); if ( isDisabled ) {
} else { $header.removeAttr( 'aria-controls' );
$th.attr( 'aria-controls', table.id ); } else {
} $header.attr( 'aria-controls', id );
} }
} }
}, },
@ -2184,14 +2197,14 @@
// *** Process table *** // *** Process table ***
// add processing indicator // add processing indicator
isProcessing : function( $table, toggle, $ths ) { isProcessing : function( $table, toggle, $headers ) {
$table = $( $table ); $table = $( $table );
var c = $table[ 0 ].config, var c = $table[ 0 ].config,
// default to all headers // default to all headers
$header = $ths || $table.find( '.' + ts.css.header ); $header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) { if ( toggle ) {
// don't use sortList if custom $ths used // don't use sortList if custom $headers used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) { if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList // get headers from the sortList
$header = $header.filter( function() { $header = $header.filter( function() {
// get data-column from attr to keep compatibility with jQuery 1.2.6 // get data-column from attr to keep compatibility with jQuery 1.2.6
@ -2983,13 +2996,13 @@
})(jQuery); })(jQuery);
/*! Widget: filter - updated 11/4/2015 (v2.24.3) *//* /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */
;( function ( $ ) { ;( function ( $ ) {
'use strict'; 'use strict';
var tsf, var tsf, tsfRegex,
ts = $.tablesorter || {}, ts = $.tablesorter || {},
tscss = ts.css; tscss = ts.css;
@ -3095,20 +3108,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class ) // data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: { types: {
or : function( c, data, vars ) { or : function( c, data, vars ) {
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) { // look for "|", but not if it is inside of a regular expression
if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
// this test for regex has potential to slow down the overall search
!tsfRegex.regex.test( data.filter ) ) {
var indx, filterMatched, query, regex, var indx, filterMatched, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.orSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.orSplit ),
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')'; query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try { try {
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search, // use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group // e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
@ -3130,22 +3144,20 @@
}, },
// Look for an AND or && operator ( logical and ) // Look for an AND or && operator ( logical and )
and : function( c, data, vars ) { and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) { if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex, var indx, filterMatched, result, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.andSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.andSplit ),
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' ) query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// replace wild cards since /(a*)/i will match anything // replace wild cards since /(a*)/i will match anything
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ); .replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
try { try {
// use try/catch just in case RegExp is invalid // use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' ); regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -3167,10 +3179,10 @@
}, },
// Look for regex // Look for regex
regex: function( c, data ) { regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) { if ( tsfRegex.regex.test( data.filter ) ) {
var matches, var matches,
// cache regex per column for optimal speed // cache regex per column for optimal speed
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ), regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
isRegex = regex instanceof RegExp; isRegex = regex instanceof RegExp;
try { try {
if ( !isRegex ) { if ( !isRegex ) {
@ -3189,18 +3201,17 @@
// Look for operators >, >=, < or <= // Look for operators >, >=, < or <=
operators: function( c, data ) { operators: function( c, data ) {
// ignore empty strings... because '' < 10 is true // ignore empty strings... because '' < 10 is true
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) { if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
var cachedValue, result, txt, var cachedValue, result, txt,
table = c.table, table = c.table,
index = data.index, parsed = data.parsed[ data.index ],
parsed = data.parsed[index], query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ), parser = c.parsers[ data.index ],
parser = c.parsers[index],
savedSearch = query; savedSearch = query;
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) { if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) ); txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true ); result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query; query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
} }
// iExact may be numeric - see issue #149; // iExact may be numeric - see issue #149;
@ -3212,10 +3223,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact; txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table ); cachedValue = ts.formatFloat( txt, table );
} }
if ( tsf.regex.gtTest.test( data.iFilter ) ) { if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query; result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) { } else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query; result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
} }
// keep showing all rows if nothing follows the operator // keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) { if ( !result && savedSearch === '' ) {
@ -3227,13 +3238,13 @@
}, },
// Look for a not match // Look for a not match
notMatch: function( c, data ) { notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) { if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx, var indx,
txt = data.iFilter.replace( '!', '' ), txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsf.regex.exact.test( filter ) ) { if ( tsfRegex.exact.test( filter ) ) {
// look for exact not matches - see #628 // look for exact not matches - see #628
filter = filter.replace( tsf.regex.exact, '' ); filter = filter.replace( tsfRegex.exact, '' );
return filter === '' ? true : $.trim( filter ) !== data.iExact; return filter === '' ? true : $.trim( filter ) !== data.iExact;
} else { } else {
indx = data.iExact.search( $.trim( filter ) ); indx = data.iExact.search( $.trim( filter ) );
@ -3245,29 +3256,29 @@
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric // Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
exact: function( c, data ) { exact: function( c, data ) {
/*jshint eqeqeq:false */ /*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) { if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ), var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact; return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
} }
return null; return null;
}, },
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu! // Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) { range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) { if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2, var result, tmp, range1, range2,
table = c.table, table = c.table,
index = data.index, index = data.index,
parsed = data.parsed[index], parsed = data.parsed[index],
// make sure the dash is for a range and not indicating a negative number // make sure the dash is for a range and not indicating a negative number
query = data.iFilter.split( tsf.regex.toSplit ); query = data.iFilter.split( tsfRegex.toSplit );
tmp = query[0].replace( ts.regex.nondigit, '' ) || ''; tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
tmp = query[1].replace( ts.regex.nondigit, '' ) || ''; tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || c.parsers[index].type === 'numeric' ) { if ( parsed || c.parsers[ index ].type === 'numeric' ) {
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1; range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
@ -3288,18 +3299,16 @@
}, },
// Look for wild card: ? = single, * = multiple, or | = logical OR // Look for wild card: ? = single, * = multiple, or | = logical OR
wild : function( c, data ) { wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) { if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var index = data.index, var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
// look for an exact match with the 'or' unless the 'filter-match' class is found // look for an exact match with the 'or' unless the 'filter-match' class is found
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) { if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
query = data.isMatch ? query : '^(' + query + ')$'; query = data.isMatch ? query : '^(' + query + ')$';
} }
// parsing the filter may not work properly when using wildcards =/ // parsing the filter may not work properly when using wildcards =/
try { try {
return new RegExp( return new RegExp(
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ), query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
c.widgetOptions.filter_ignoreCase ? 'i' : '' c.widgetOptions.filter_ignoreCase ? 'i' : ''
) )
.test( data.exact ); .test( data.exact );
@ -3311,21 +3320,18 @@
}, },
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license ) // fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) { fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) { if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx, var indx,
patternIndx = 0, patternIndx = 0,
len = data.iExact.length, len = data.iExact.length,
txt = data.iFilter.slice( 1 ), txt = data.iFilter.slice( 1 ),
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; pattern = tsf.parseFilter( c, txt, data ) || '';
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) { if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1; patternIndx += 1;
} }
} }
if ( patternIndx === pattern.length ) { return patternIndx === pattern.length;
return true;
}
return false;
} }
return null; return null;
} }
@ -3338,8 +3344,7 @@
and : 'and' and : 'and'
}, ts.language ); }, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect, var options, string, txt, $header, column, filters, val, fxn, noSelect;
regex = tsf.regex;
c.$table.addClass( 'hasFilters' ); c.$table.addClass( 'hasFilters' );
// define timers so using clearTimeout won't cause an undefined error // define timers so using clearTimeout won't cause an undefined error
@ -3350,8 +3355,8 @@
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]'; wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]'; wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}'; val = '\\{' + tsfRegex.query + '\\}';
$.extend( regex, { $.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ), child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ), filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ), alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -3629,8 +3634,10 @@
c.$table.data( 'lastSearch', filters ); c.$table.data( 'lastSearch', filters );
return filters; return filters;
}, },
parseFilter: function( c, filter, column, parsed ) { parseFilter: function( c, filter, data, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter; return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
}, },
buildRow: function( table, c, wo ) { buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp, var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -3882,8 +3889,8 @@
}, },
defaultFilter: function( filter, mask ) { defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; } if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery, var regex = tsfRegex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length, maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ], query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1, len = query.length - 1,
indx = 0, indx = 0,
@ -3980,9 +3987,8 @@
return filterMatched; return filterMatched;
}, },
processRow: function( c, data, vars ) { processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched, var result, filterMatched,
fxn, ffxn, txt, fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions, wo = c.widgetOptions,
showRow = true, showRow = true,
@ -4061,7 +4067,7 @@
result = data.rawArray[ columnIndex ] || ''; result = data.rawArray[ columnIndex ] || '';
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405 data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
} }
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ? data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
data.exact.toLowerCase() : data.exact; data.exact.toLowerCase() : data.exact;
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' ); data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -4079,21 +4085,13 @@
data.filter = ts.replaceAccents( data.filter ); data.filter = ts.replaceAccents( data.filter );
} }
val = true;
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
// val is used to indicate that a filter select is using a default filter;
// so we override the exact & partial matches
val = false;
}
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ), // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
// data.filter = case sensitive // data.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter; data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ]; fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null; filterMatched = null;
if ( fxn || ( hasSelect && val ) ) { if ( fxn ) {
if ( fxn === true || hasSelect ) { if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found // default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ? filterMatched = data.isMatch ?
// data.iExact may be a number // data.iExact may be a number
@ -4119,7 +4117,7 @@
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
txt = ( data.iExact + data.childRowText ) txt = ( data.iExact + data.childRowText )
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) ); .indexOf( tsf.parseFilter( c, data.iFilter, data ) );
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) ); result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
} }
} else { } else {
@ -4139,7 +4137,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx, isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt, notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ), storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters // data object passed to filters; anyMatch is a flag for the filters
@ -4221,7 +4218,7 @@
); );
if ( wo.filter_columnAnyMatch ) { if ( wo.filter_columnAnyMatch ) {
// specific columns search // specific columns search
query = data.anyMatchFilter.split( regex.andSplit ); query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false; injected = false;
for ( indx = 0; indx < query.length; indx++ ) { for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' ); res = query[ indx ].split( ':' );
@ -4256,12 +4253,12 @@
// there are no changes from beginning of filter // there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 && val.indexOf( lastSearch[indx] || '' ) === 0 &&
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string // if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
!regex.alreadyFiltered.test( val ) && !tsfRegex.alreadyFiltered.test( val ) &&
// if we are not doing exact matches, using '|' ( logical or ) or not '!' // if we are not doing exact matches, using '|' ( logical or ) or not '!'
!regex.exactTest.test( val ) && !tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative // don't search only filtered if the value is negative
// ( '> -10' => '> -100' will ignore hidden rows ) // ( '> -10' => '> -100' will ignore hidden rows )
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) && !( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593 // if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length && !( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) ); !c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -4279,7 +4276,7 @@
// replace accents // replace accents
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter ); data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
} }
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) { if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter ); data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
// clear search filtered flag because default filters are not saved to the last search // clear search filtered flag because default filters are not saved to the last search
searchFiltered = false; searchFiltered = false;
@ -4296,9 +4293,9 @@
txt = $rows[ rowIndex ].className; txt = $rows[ rowIndex ].className;
// the first row can never be a child row // the first row can never be a child row
isChild = rowIndex && regex.child.test( txt ); isChild = rowIndex && tsfRegex.child.test( txt );
// skip child rows & already filtered rows // skip child rows & already filtered rows
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) { if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue; continue;
} }
@ -4408,7 +4405,6 @@
// custom select source function for a SPECIFIC COLUMN // custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail ); arry = fxn( table, column, onlyAvail );
} }
if ( arry === false ) { if ( arry === false ) {
// fall back to original method // fall back to original method
arry = tsf.getOptions( table, column, onlyAvail ); arry = tsf.getOptions( table, column, onlyAvail );
@ -4422,18 +4418,19 @@
return false; return false;
} }
table = $( table )[0]; table = $( table )[0];
var cts, txt, indx, len, var cts, txt, indx, len, parsedTxt, str,
c = table.config, c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns, validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = []; parsed = [];
// get unique elements and sort the list // get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ), // if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort // then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) { arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx; return $.inArray( value, arry ) === indx;
}); });
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) { if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options // unsorted select options
return arry; return arry;
@ -4442,22 +4439,30 @@
// parse select option values // parse select option values
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
txt = arry[ indx ]; txt = arry[ indx ];
// check for object
str = txt.text ? txt.text : txt;
// sortNatural breaks if you don't pass it strings
parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( str, table, [], column ) || str ).toString();
parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
// parse array data using set column parser; this DOES NOT pass the original // parse array data using set column parser; this DOES NOT pass the original
// table cell to the parser format function // table cell to the parser format function
parsed.push({ if ( txt.text ) {
t : txt, txt.parsed = parsedTxt;
// check parser length - fixes #934 parsed.push( txt );
p : validColumn && c.parsers && c.parsers.length && } else {
c.parsers[ column ].format( txt, table, [], column ) || txt parsed.push({
}); text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
} }
// sort parsed select options // sort parsed select options
cts = c.textSorter || ''; cts = c.textSorter || '';
parsed.sort( function( a, b ) { parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings var x = a.parsed,
var x = a.p.toString(), y = b.parsed;
y = b.p.toString();
if ( validColumn && typeof cts === 'function' ) { if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter // custom OVERALL text sorter
return cts( x, y, true, column, table ); return cts( x, y, true, column, table );
@ -4475,7 +4480,7 @@
arry = []; arry = [];
len = parsed.length; len = parsed.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t ); arry.push( parsed[indx] );
} }
return arry; return arry;
} }
@ -4535,7 +4540,7 @@
return; return;
} }
var indx, val, txt, t, $filters, $filter, var indx, val, txt, t, $filters, $filter, option,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
node = c.$headerIndexed[ column ], node = c.$headerIndexed[ column ],
@ -4560,23 +4565,45 @@
if ( $.isArray( arry ) ) { if ( $.isArray( arry ) ) {
// build option list // build option list
for ( indx = 0; indx < arry.length; indx++ ) { for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '&quot;' ); option = arry[ indx ];
val = txt; if ( option.text ) {
// allow including a symbol in the selectSource array // OBJECT!! add data-function-name in case the value is set in filter_functions
// 'a-z|A through Z' so that 'a-z' becomes the option value option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) { // support jQuery < v1.8, otherwise the below code could be shortened to
t = txt.split( wo.filter_selectSourceSeparator ); // options += $( '<option>', option )[ 0 ].outerHTML;
val = t[0]; options += '<option';
txt = t[1]; for ( val in option ) {
if ( option.hasOwnProperty( val ) && val !== 'text' ) {
options += ' ' + val + '="' + option[ val ] + '"';
}
}
if ( !option.value ) {
options += ' value="' + option.text + '"';
}
options += '>' + option.text + '</option>';
// above code is needed in jQuery < v1.8
// make sure we don't turn an object into a string (objects without a "text" property)
} else if ( '' + option !== '[object Object]' ) {
txt = option = ( '' + option ).replace( tsfRegex.quote, '&quot;' );
val = txt;
// allow including a symbol in the selectSource array
// 'a-z|A through Z' so that 'a-z' becomes the option value
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
t = txt.split( wo.filter_selectSourceSeparator );
val = t[0];
txt = t[1];
}
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += option !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + option + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += arry[indx] !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// clear arry so it doesn't get appended twice // clear arry so it doesn't get appended twice
arry = []; arry = [];
@ -4622,6 +4649,9 @@
} }
}; };
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) { ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols, var i, $filters, $column, cols,
filters = false, filters = false,

View File

@ -1,4 +1,4 @@
/*! TableSorter (FORK) v2.24.3 *//* /*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -21,7 +21,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.24.3', version : '2.24.4',
parsers : [], parsers : [],
widgets : [], widgets : [],

View File

@ -4,7 +4,7 @@
*/ */
/*! tablesorter (FORK) - updated 11-06-2015 (v2.24.3)*/ /*! tablesorter (FORK) - updated 11-10-2015 (v2.24.4)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -372,13 +372,13 @@
})(jQuery); })(jQuery);
/*! Widget: filter - updated 11/4/2015 (v2.24.3) *//* /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */
;( function ( $ ) { ;( function ( $ ) {
'use strict'; 'use strict';
var tsf, var tsf, tsfRegex,
ts = $.tablesorter || {}, ts = $.tablesorter || {},
tscss = ts.css; tscss = ts.css;
@ -484,20 +484,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class ) // data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: { types: {
or : function( c, data, vars ) { or : function( c, data, vars ) {
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) { // look for "|", but not if it is inside of a regular expression
if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
// this test for regex has potential to slow down the overall search
!tsfRegex.regex.test( data.filter ) ) {
var indx, filterMatched, query, regex, var indx, filterMatched, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.orSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.orSplit ),
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')'; query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try { try {
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search, // use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group // e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
@ -519,22 +520,20 @@
}, },
// Look for an AND or && operator ( logical and ) // Look for an AND or && operator ( logical and )
and : function( c, data, vars ) { and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) { if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex, var indx, filterMatched, result, query, regex,
// duplicate data but split filter // duplicate data but split filter
data2 = $.extend( {}, data ), data2 = $.extend( {}, data ),
index = data.index, filter = data.filter.split( tsfRegex.andSplit ),
parsed = data.parsed[ index ], iFilter = data.iFilter.split( tsfRegex.andSplit ),
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
len = filter.length; len = filter.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true; data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' ); data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' ); data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' ) query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// replace wild cards since /(a*)/i will match anything // replace wild cards since /(a*)/i will match anything
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ); .replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
try { try {
// use try/catch just in case RegExp is invalid // use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' ); regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -556,10 +555,10 @@
}, },
// Look for regex // Look for regex
regex: function( c, data ) { regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) { if ( tsfRegex.regex.test( data.filter ) ) {
var matches, var matches,
// cache regex per column for optimal speed // cache regex per column for optimal speed
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ), regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
isRegex = regex instanceof RegExp; isRegex = regex instanceof RegExp;
try { try {
if ( !isRegex ) { if ( !isRegex ) {
@ -578,18 +577,17 @@
// Look for operators >, >=, < or <= // Look for operators >, >=, < or <=
operators: function( c, data ) { operators: function( c, data ) {
// ignore empty strings... because '' < 10 is true // ignore empty strings... because '' < 10 is true
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) { if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
var cachedValue, result, txt, var cachedValue, result, txt,
table = c.table, table = c.table,
index = data.index, parsed = data.parsed[ data.index ],
parsed = data.parsed[index], query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ), parser = c.parsers[ data.index ],
parser = c.parsers[index],
savedSearch = query; savedSearch = query;
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) { if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) ); txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true ); result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query; query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
} }
// iExact may be numeric - see issue #149; // iExact may be numeric - see issue #149;
@ -601,10 +599,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact; txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table ); cachedValue = ts.formatFloat( txt, table );
} }
if ( tsf.regex.gtTest.test( data.iFilter ) ) { if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query; result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) { } else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query; result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
} }
// keep showing all rows if nothing follows the operator // keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) { if ( !result && savedSearch === '' ) {
@ -616,13 +614,13 @@
}, },
// Look for a not match // Look for a not match
notMatch: function( c, data ) { notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) { if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx, var indx,
txt = data.iFilter.replace( '!', '' ), txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsf.regex.exact.test( filter ) ) { if ( tsfRegex.exact.test( filter ) ) {
// look for exact not matches - see #628 // look for exact not matches - see #628
filter = filter.replace( tsf.regex.exact, '' ); filter = filter.replace( tsfRegex.exact, '' );
return filter === '' ? true : $.trim( filter ) !== data.iExact; return filter === '' ? true : $.trim( filter ) !== data.iExact;
} else { } else {
indx = data.iExact.search( $.trim( filter ) ); indx = data.iExact.search( $.trim( filter ) );
@ -634,29 +632,29 @@
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric // Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
exact: function( c, data ) { exact: function( c, data ) {
/*jshint eqeqeq:false */ /*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) { if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ), var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact; return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
} }
return null; return null;
}, },
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu! // Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) { range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) { if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2, var result, tmp, range1, range2,
table = c.table, table = c.table,
index = data.index, index = data.index,
parsed = data.parsed[index], parsed = data.parsed[index],
// make sure the dash is for a range and not indicating a negative number // make sure the dash is for a range and not indicating a negative number
query = data.iFilter.split( tsf.regex.toSplit ); query = data.iFilter.split( tsfRegex.toSplit );
tmp = query[0].replace( ts.regex.nondigit, '' ) || ''; tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
tmp = query[1].replace( ts.regex.nondigit, '' ) || ''; tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table ); range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
// parse filter value in case we're comparing numbers ( dates ) // parse filter value in case we're comparing numbers ( dates )
if ( parsed || c.parsers[index].type === 'numeric' ) { if ( parsed || c.parsers[ index ].type === 'numeric' ) {
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1; range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index ); result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
@ -677,18 +675,16 @@
}, },
// Look for wild card: ? = single, * = multiple, or | = logical OR // Look for wild card: ? = single, * = multiple, or | = logical OR
wild : function( c, data ) { wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) { if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var index = data.index, var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
// look for an exact match with the 'or' unless the 'filter-match' class is found // look for an exact match with the 'or' unless the 'filter-match' class is found
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) { if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
query = data.isMatch ? query : '^(' + query + ')$'; query = data.isMatch ? query : '^(' + query + ')$';
} }
// parsing the filter may not work properly when using wildcards =/ // parsing the filter may not work properly when using wildcards =/
try { try {
return new RegExp( return new RegExp(
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ), query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
c.widgetOptions.filter_ignoreCase ? 'i' : '' c.widgetOptions.filter_ignoreCase ? 'i' : ''
) )
.test( data.exact ); .test( data.exact );
@ -700,21 +696,18 @@
}, },
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license ) // fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) { fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) { if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx, var indx,
patternIndx = 0, patternIndx = 0,
len = data.iExact.length, len = data.iExact.length,
txt = data.iFilter.slice( 1 ), txt = data.iFilter.slice( 1 ),
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || ''; pattern = tsf.parseFilter( c, txt, data ) || '';
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) { if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1; patternIndx += 1;
} }
} }
if ( patternIndx === pattern.length ) { return patternIndx === pattern.length;
return true;
}
return false;
} }
return null; return null;
} }
@ -727,8 +720,7 @@
and : 'and' and : 'and'
}, ts.language ); }, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect, var options, string, txt, $header, column, filters, val, fxn, noSelect;
regex = tsf.regex;
c.$table.addClass( 'hasFilters' ); c.$table.addClass( 'hasFilters' );
// define timers so using clearTimeout won't cause an undefined error // define timers so using clearTimeout won't cause an undefined error
@ -739,8 +731,8 @@
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]'; wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]'; wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}'; val = '\\{' + tsfRegex.query + '\\}';
$.extend( regex, { $.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ), child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ), filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ), alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -1018,8 +1010,10 @@
c.$table.data( 'lastSearch', filters ); c.$table.data( 'lastSearch', filters );
return filters; return filters;
}, },
parseFilter: function( c, filter, column, parsed ) { parseFilter: function( c, filter, data, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter; return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
}, },
buildRow: function( table, c, wo ) { buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp, var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -1271,8 +1265,8 @@
}, },
defaultFilter: function( filter, mask ) { defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; } if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery, var regex = tsfRegex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length, maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ], query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1, len = query.length - 1,
indx = 0, indx = 0,
@ -1369,9 +1363,8 @@
return filterMatched; return filterMatched;
}, },
processRow: function( c, data, vars ) { processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched, var result, filterMatched,
fxn, ffxn, txt, fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions, wo = c.widgetOptions,
showRow = true, showRow = true,
@ -1450,7 +1443,7 @@
result = data.rawArray[ columnIndex ] || ''; result = data.rawArray[ columnIndex ] || '';
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405 data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
} }
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ? data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
data.exact.toLowerCase() : data.exact; data.exact.toLowerCase() : data.exact;
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' ); data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -1468,21 +1461,13 @@
data.filter = ts.replaceAccents( data.filter ); data.filter = ts.replaceAccents( data.filter );
} }
val = true;
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
// val is used to indicate that a filter select is using a default filter;
// so we override the exact & partial matches
val = false;
}
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ), // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
// data.filter = case sensitive // data.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter; data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ]; fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null; filterMatched = null;
if ( fxn || ( hasSelect && val ) ) { if ( fxn ) {
if ( fxn === true || hasSelect ) { if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found // default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ? filterMatched = data.isMatch ?
// data.iExact may be a number // data.iExact may be a number
@ -1508,7 +1493,7 @@
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
txt = ( data.iExact + data.childRowText ) txt = ( data.iExact + data.childRowText )
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) ); .indexOf( tsf.parseFilter( c, data.iFilter, data ) );
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) ); result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
} }
} else { } else {
@ -1528,7 +1513,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx, isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt, notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ), storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters // data object passed to filters; anyMatch is a flag for the filters
@ -1610,7 +1594,7 @@
); );
if ( wo.filter_columnAnyMatch ) { if ( wo.filter_columnAnyMatch ) {
// specific columns search // specific columns search
query = data.anyMatchFilter.split( regex.andSplit ); query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false; injected = false;
for ( indx = 0; indx < query.length; indx++ ) { for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' ); res = query[ indx ].split( ':' );
@ -1645,12 +1629,12 @@
// there are no changes from beginning of filter // there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 && val.indexOf( lastSearch[indx] || '' ) === 0 &&
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string // if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
!regex.alreadyFiltered.test( val ) && !tsfRegex.alreadyFiltered.test( val ) &&
// if we are not doing exact matches, using '|' ( logical or ) or not '!' // if we are not doing exact matches, using '|' ( logical or ) or not '!'
!regex.exactTest.test( val ) && !tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative // don't search only filtered if the value is negative
// ( '> -10' => '> -100' will ignore hidden rows ) // ( '> -10' => '> -100' will ignore hidden rows )
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) && !( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593 // if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length && !( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) ); !c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -1668,7 +1652,7 @@
// replace accents // replace accents
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter ); data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
} }
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) { if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter ); data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
// clear search filtered flag because default filters are not saved to the last search // clear search filtered flag because default filters are not saved to the last search
searchFiltered = false; searchFiltered = false;
@ -1685,9 +1669,9 @@
txt = $rows[ rowIndex ].className; txt = $rows[ rowIndex ].className;
// the first row can never be a child row // the first row can never be a child row
isChild = rowIndex && regex.child.test( txt ); isChild = rowIndex && tsfRegex.child.test( txt );
// skip child rows & already filtered rows // skip child rows & already filtered rows
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) { if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue; continue;
} }
@ -1797,7 +1781,6 @@
// custom select source function for a SPECIFIC COLUMN // custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail ); arry = fxn( table, column, onlyAvail );
} }
if ( arry === false ) { if ( arry === false ) {
// fall back to original method // fall back to original method
arry = tsf.getOptions( table, column, onlyAvail ); arry = tsf.getOptions( table, column, onlyAvail );
@ -1811,18 +1794,19 @@
return false; return false;
} }
table = $( table )[0]; table = $( table )[0];
var cts, txt, indx, len, var cts, txt, indx, len, parsedTxt, str,
c = table.config, c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns, validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = []; parsed = [];
// get unique elements and sort the list // get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ), // if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort // then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) { arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx; return $.inArray( value, arry ) === indx;
}); });
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) { if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options // unsorted select options
return arry; return arry;
@ -1831,22 +1815,30 @@
// parse select option values // parse select option values
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
txt = arry[ indx ]; txt = arry[ indx ];
// check for object
str = txt.text ? txt.text : txt;
// sortNatural breaks if you don't pass it strings
parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( str, table, [], column ) || str ).toString();
parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
// parse array data using set column parser; this DOES NOT pass the original // parse array data using set column parser; this DOES NOT pass the original
// table cell to the parser format function // table cell to the parser format function
parsed.push({ if ( txt.text ) {
t : txt, txt.parsed = parsedTxt;
// check parser length - fixes #934 parsed.push( txt );
p : validColumn && c.parsers && c.parsers.length && } else {
c.parsers[ column ].format( txt, table, [], column ) || txt parsed.push({
}); text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
} }
// sort parsed select options // sort parsed select options
cts = c.textSorter || ''; cts = c.textSorter || '';
parsed.sort( function( a, b ) { parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings var x = a.parsed,
var x = a.p.toString(), y = b.parsed;
y = b.p.toString();
if ( validColumn && typeof cts === 'function' ) { if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter // custom OVERALL text sorter
return cts( x, y, true, column, table ); return cts( x, y, true, column, table );
@ -1864,7 +1856,7 @@
arry = []; arry = [];
len = parsed.length; len = parsed.length;
for ( indx = 0; indx < len; indx++ ) { for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t ); arry.push( parsed[indx] );
} }
return arry; return arry;
} }
@ -1924,7 +1916,7 @@
return; return;
} }
var indx, val, txt, t, $filters, $filter, var indx, val, txt, t, $filters, $filter, option,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
node = c.$headerIndexed[ column ], node = c.$headerIndexed[ column ],
@ -1949,23 +1941,45 @@
if ( $.isArray( arry ) ) { if ( $.isArray( arry ) ) {
// build option list // build option list
for ( indx = 0; indx < arry.length; indx++ ) { for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '&quot;' ); option = arry[ indx ];
val = txt; if ( option.text ) {
// allow including a symbol in the selectSource array // OBJECT!! add data-function-name in case the value is set in filter_functions
// 'a-z|A through Z' so that 'a-z' becomes the option value option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) { // support jQuery < v1.8, otherwise the below code could be shortened to
t = txt.split( wo.filter_selectSourceSeparator ); // options += $( '<option>', option )[ 0 ].outerHTML;
val = t[0]; options += '<option';
txt = t[1]; for ( val in option ) {
if ( option.hasOwnProperty( val ) && val !== 'text' ) {
options += ' ' + val + '="' + option[ val ] + '"';
}
}
if ( !option.value ) {
options += ' value="' + option.text + '"';
}
options += '>' + option.text + '</option>';
// above code is needed in jQuery < v1.8
// make sure we don't turn an object into a string (objects without a "text" property)
} else if ( '' + option !== '[object Object]' ) {
txt = option = ( '' + option ).replace( tsfRegex.quote, '&quot;' );
val = txt;
// allow including a symbol in the selectSource array
// 'a-z|A through Z' so that 'a-z' becomes the option value
// and 'A through Z' becomes the option text
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
t = txt.split( wo.filter_selectSourceSeparator );
val = t[0];
txt = t[1];
}
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += option !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + option + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// replace quotes - fixes #242 & ignore empty strings
// see http://stackoverflow.com/q/14990971/145346
options += arry[indx] !== '' ?
'<option ' +
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
'value="' + val + '">' + txt +
'</option>' : '';
} }
// clear arry so it doesn't get appended twice // clear arry so it doesn't get appended twice
arry = []; arry = [];
@ -2011,6 +2025,9 @@
} }
}; };
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) { ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols, var i, $filters, $column, cols,
filters = false, filters = false,

View File

@ -1,4 +1,4 @@
/*! Parser: filetype *//* /*! Parser: filetype - updated 11/10/2015 (v2.24.4) *//*
* When a file type extension is found, the equivalent name is * When a file type extension is found, the equivalent name is
* prefixed into the parsed data, so sorting occurs in groups * prefixed into the parsed data, so sorting occurs in groups
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: filter - updated 11/4/2015 (v2.24.3) *//* /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: grouping - updated 11/2/2015 (v2.24.1) *//* /*! Widget: grouping - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: headerTitles - updated 11/8/2015 (v2.24.4) *//* /*! Widget: headerTitles - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.8+ and jQuery 1.7+ * Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: math - updated 10/31/2015 (v2.24.0) *//* /*! Widget: math - updated 11/10/2015 (v2.24.4) *//*
* Requires tablesorter v2.16+ and jQuery 1.7+ * Requires tablesorter v2.16+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: Pager - updated 10/31/2015 (v2.24.0) */ /*! Widget: Pager - updated 11/10/2015 (v2.24.4) */
/* Requires tablesorter v2.8+ and jQuery 1.7+ /* Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! Widget: sort2Hash (BETA) - updated 11/8/2015 (v2.24.4) */ /*! Widget: sort2Hash (BETA) - updated 11/10/2015 (v2.24.4) */
/* Requires tablesorter v2.8+ and jQuery 1.7+ /* Requires tablesorter v2.8+ and jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,4 +1,4 @@
/*! tablesorter enable/disable sort & filter (BETA) - 11/8/2015 (v2.24.4) /*! tablesorter enable/disable sort & filter (BETA) - 11/10/2015 (v2.24.4)
* Requires tablesorter v2.24.4+ & jQuery 1.7+ * Requires tablesorter v2.24.4+ & jQuery 1.7+
* by Rob Garrison * by Rob Garrison
*/ */

View File

@ -1,7 +1,7 @@
{ {
"name": "tablesorter", "name": "tablesorter",
"title": "tablesorter", "title": "tablesorter",
"version": "2.24.3", "version": "2.24.4",
"description": "tablesorter (FORK) is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.", "description": "tablesorter (FORK) is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.",
"author": { "author": {
"name": "Christian Bach", "name": "Christian Bach",

View File

@ -1,7 +1,7 @@
{ {
"name": "tablesorter", "name": "tablesorter",
"title": "tablesorter", "title": "tablesorter",
"version": "2.24.3", "version": "2.24.4",
"description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.", "description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.",
"author": { "author": {
"name": "Christian Bach", "name": "Christian Bach",