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).
#### <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)
* Core
@ -109,104 +142,3 @@ View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes
* Misc
* 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
* updated 10/31/2015 (v2.24.0)
* updated 11/10/2015 (v2.24.4)
*/
/*jshint browser:true, jquery:true, unused:false */
;(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 ) */
(function(factory) {
if (typeof define === 'function' && define.amd) {
@ -10,7 +10,7 @@
}
}(function($) {
/*! TableSorter (FORK) v2.24.3 *//*
/*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease!
* @requires jQuery v1.2.6+
*
@ -33,7 +33,7 @@
'use strict';
var ts = $.tablesorter = {
version : '2.24.3',
version : '2.24.4',
parsers : [],
widgets : [],
@ -151,12 +151,13 @@
// labels applied to sortable headers for accessibility (aria) support
language : {
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
sortDisabled : 'sorting is disabled',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
},
regex : {
@ -1005,7 +1006,7 @@
*/
setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp,
var $sorted, indx, column,
list = c.sortList,
len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone,
@ -1073,50 +1074,62 @@
}
// add verbose aria labels
len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) {
$header = $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 ) ];
ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
}
},
// 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 ) ?
'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone';
txt = $.trim( $header.text() ) + ': ' +
ts.language[ tmp ] +
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
$header.attr( 'aria-label', txt );
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
txt += ts.language.sortDisabled;
} 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 ) {
var index, isDisabled, $th, col,
var index, isDisabled, $header, col,
table = c.table,
len = c.$headers.length;
for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index );
$header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled;
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$th.removeAttr( 'tabindex' );
} else {
$th.attr( 'tabindex', '0' );
}
isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
ts.setColumnSort( c, $header, isDisabled );
}
},
setColumnSort : function( c, $header, isDisabled ) {
var id = c.table.id;
$header[ 0 ].sortDisabled = isDisabled;
$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 ) {
if ( isDisabled ) {
$th.removeAttr( 'aria-controls' );
} else {
$th.attr( 'aria-controls', table.id );
}
}
// aria-controls - requires table ID
if ( id ) {
if ( isDisabled ) {
$header.removeAttr( 'aria-controls' );
} else {
$header.attr( 'aria-controls', id );
}
}
},
@ -2178,14 +2191,14 @@
// *** Process table ***
// add processing indicator
isProcessing : function( $table, toggle, $ths ) {
isProcessing : function( $table, toggle, $headers ) {
$table = $( $table );
var c = $table[ 0 ].config,
// default to all headers
$header = $ths || $table.find( '.' + ts.css.header );
$header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) {
// don't use sortList if custom $ths used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) {
// don't use sortList if custom $headers used
if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList
$header = $header.filter( function() {
// get data-column from attr to keep compatibility with jQuery 1.2.6
@ -2977,13 +2990,13 @@
})(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+
* by Rob Garrison
*/
;( function ( $ ) {
'use strict';
var tsf,
var tsf, tsfRegex,
ts = $.tablesorter || {},
tscss = ts.css;
@ -3089,20 +3102,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: {
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,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
filter = data.filter.split( tsfRegex.orSplit ),
iFilter = data.iFilter.split( tsfRegex.orSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try {
// 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
@ -3124,22 +3138,20 @@
},
// Look for an AND or && operator ( logical and )
and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) {
if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
filter = data.filter.split( tsfRegex.andSplit ),
iFilter = data.iFilter.split( tsfRegex.andSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// 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 {
// use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -3161,10 +3173,10 @@
},
// Look for regex
regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) {
if ( tsfRegex.regex.test( data.filter ) ) {
var matches,
// 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;
try {
if ( !isRegex ) {
@ -3183,18 +3195,17 @@
// Look for operators >, >=, < or <=
operators: function( c, data ) {
// 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,
table = c.table,
index = data.index,
parsed = data.parsed[index],
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
parser = c.parsers[index],
parsed = data.parsed[ data.index ],
query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
parser = c.parsers[ data.index ],
savedSearch = query;
// parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true );
txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
}
// iExact may be numeric - see issue #149;
@ -3206,10 +3217,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table );
}
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
}
// keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) {
@ -3221,13 +3232,13 @@
},
// Look for a not match
notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) {
if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx,
txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsf.regex.exact.test( filter ) ) {
filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsfRegex.exact.test( filter ) ) {
// 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;
} else {
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
exact: function( c, data ) {
/*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
}
return null;
},
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) {
if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2,
table = c.table,
index = data.index,
parsed = data.parsed[index],
// 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, '' ) || '';
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, '' ) || '';
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 )
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 );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
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
wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
var index = data.index,
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
// 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 + ')$';
}
// parsing the filter may not work properly when using wildcards =/
try {
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' : ''
)
.test( data.exact );
@ -3305,21 +3314,18 @@
},
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx,
patternIndx = 0,
len = data.iExact.length,
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++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1;
}
}
if ( patternIndx === pattern.length ) {
return true;
}
return false;
return patternIndx === pattern.length;
}
return null;
}
@ -3332,8 +3338,7 @@
and : 'and'
}, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect,
regex = tsf.regex;
var options, string, txt, $header, column, filters, val, fxn, noSelect;
c.$table.addClass( 'hasFilters' );
// 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_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}';
$.extend( regex, {
val = '\\{' + tsfRegex.query + '\\}';
$.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -3623,8 +3628,10 @@
c.$table.data( 'lastSearch', filters );
return filters;
},
parseFilter: function( c, filter, column, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter;
parseFilter: function( c, filter, data, parsed ) {
return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
},
buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -3876,8 +3883,8 @@
},
defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length,
var regex = tsfRegex.iQuery,
maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1,
indx = 0,
@ -3974,9 +3981,8 @@
return filterMatched;
},
processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched,
var result, filterMatched,
fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions,
showRow = true,
@ -4055,7 +4061,7 @@
result = data.rawArray[ columnIndex ] || '';
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.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -4073,21 +4079,13 @@
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.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null;
if ( fxn || ( hasSelect && val ) ) {
if ( fxn === true || hasSelect ) {
if ( fxn ) {
if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ?
// data.iExact may be a number
@ -4113,7 +4111,7 @@
// Look for match, and add child row data for matching
} else {
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 ) );
}
} else {
@ -4133,7 +4131,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config,
wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters
@ -4215,7 +4212,7 @@
);
if ( wo.filter_columnAnyMatch ) {
// specific columns search
query = data.anyMatchFilter.split( regex.andSplit );
query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false;
for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' );
@ -4250,12 +4247,12 @@
// there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 &&
// 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 '!'
!regex.exactTest.test( val ) &&
!tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative
// ( '> -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
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -4273,7 +4270,7 @@
// replace accents
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 );
// clear search filtered flag because default filters are not saved to the last search
searchFiltered = false;
@ -4290,9 +4287,9 @@
txt = $rows[ rowIndex ].className;
// 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
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) {
if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue;
}
@ -4402,7 +4399,6 @@
// custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail );
}
if ( arry === false ) {
// fall back to original method
arry = tsf.getOptions( table, column, onlyAvail );
@ -4416,18 +4412,19 @@
return false;
}
table = $( table )[0];
var cts, txt, indx, len,
var cts, txt, indx, len, parsedTxt, str,
c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = [];
// get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx;
});
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options
return arry;
@ -4436,22 +4433,30 @@
// parse select option values
for ( indx = 0; indx < len; 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
// table cell to the parser format function
parsed.push({
t : txt,
// check parser length - fixes #934
p : validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( txt, table, [], column ) || txt
});
if ( txt.text ) {
txt.parsed = parsedTxt;
parsed.push( txt );
} else {
parsed.push({
text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
}
// sort parsed select options
cts = c.textSorter || '';
parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings
var x = a.p.toString(),
y = b.p.toString();
var x = a.parsed,
y = b.parsed;
if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter
return cts( x, y, true, column, table );
@ -4469,7 +4474,7 @@
arry = [];
len = parsed.length;
for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t );
arry.push( parsed[indx] );
}
return arry;
}
@ -4529,7 +4534,7 @@
return;
}
var indx, val, txt, t, $filters, $filter,
var indx, val, txt, t, $filters, $filter, option,
c = table.config,
wo = c.widgetOptions,
node = c.$headerIndexed[ column ],
@ -4554,23 +4559,45 @@
if ( $.isArray( arry ) ) {
// build option list
for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.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];
option = arry[ indx ];
if ( option.text ) {
// OBJECT!! add data-function-name in case the value is set in filter_functions
option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// support jQuery < v1.8, otherwise the below code could be shortened to
// options += $( '<option>', option )[ 0 ].outerHTML;
options += '<option';
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
arry = [];
@ -4616,6 +4643,9 @@
}
};
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols,
filters = false,

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,7 @@
}
}(function($) {
/*! TableSorter (FORK) v2.24.3 *//*
/*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease!
* @requires jQuery v1.2.6+
*
@ -31,7 +31,7 @@
'use strict';
var ts = $.tablesorter = {
version : '2.24.3',
version : '2.24.4',
parsers : [],
widgets : [],
@ -149,12 +149,13 @@
// labels applied to sortable headers for accessibility (aria) support
language : {
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
sortDisabled : 'sorting is disabled',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
},
regex : {
@ -1003,7 +1004,7 @@
*/
setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp,
var $sorted, indx, column,
list = c.sortList,
len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone,
@ -1071,50 +1072,62 @@
}
// add verbose aria labels
len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) {
$header = $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 ) ];
ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
}
},
// 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 ) ?
'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone';
txt = $.trim( $header.text() ) + ': ' +
ts.language[ tmp ] +
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
$header.attr( 'aria-label', txt );
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
txt += ts.language.sortDisabled;
} 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 ) {
var index, isDisabled, $th, col,
var index, isDisabled, $header, col,
table = c.table,
len = c.$headers.length;
for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index );
$header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled;
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$th.removeAttr( 'tabindex' );
} else {
$th.attr( 'tabindex', '0' );
}
isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
ts.setColumnSort( c, $header, isDisabled );
}
},
setColumnSort : function( c, $header, isDisabled ) {
var id = c.table.id;
$header[ 0 ].sortDisabled = isDisabled;
$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 ) {
if ( isDisabled ) {
$th.removeAttr( 'aria-controls' );
} else {
$th.attr( 'aria-controls', table.id );
}
}
// aria-controls - requires table ID
if ( id ) {
if ( isDisabled ) {
$header.removeAttr( 'aria-controls' );
} else {
$header.attr( 'aria-controls', id );
}
}
},
@ -2176,14 +2189,14 @@
// *** Process table ***
// add processing indicator
isProcessing : function( $table, toggle, $ths ) {
isProcessing : function( $table, toggle, $headers ) {
$table = $( $table );
var c = $table[ 0 ].config,
// default to all headers
$header = $ths || $table.find( '.' + ts.css.header );
$header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) {
// don't use sortList if custom $ths used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) {
// don't use sortList if custom $headers used
if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList
$header = $header.filter( function() {
// 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 ) */
(function(factory) {
if (typeof define === 'function' && define.amd) {
@ -366,13 +366,13 @@
})(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+
* by Rob Garrison
*/
;( function ( $ ) {
'use strict';
var tsf,
var tsf, tsfRegex,
ts = $.tablesorter || {},
tscss = ts.css;
@ -478,20 +478,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: {
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,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
filter = data.filter.split( tsfRegex.orSplit ),
iFilter = data.iFilter.split( tsfRegex.orSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try {
// 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
@ -513,22 +514,20 @@
},
// Look for an AND or && operator ( logical and )
and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) {
if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
filter = data.filter.split( tsfRegex.andSplit ),
iFilter = data.iFilter.split( tsfRegex.andSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// 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 {
// use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -550,10 +549,10 @@
},
// Look for regex
regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) {
if ( tsfRegex.regex.test( data.filter ) ) {
var matches,
// 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;
try {
if ( !isRegex ) {
@ -572,18 +571,17 @@
// Look for operators >, >=, < or <=
operators: function( c, data ) {
// 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,
table = c.table,
index = data.index,
parsed = data.parsed[index],
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
parser = c.parsers[index],
parsed = data.parsed[ data.index ],
query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
parser = c.parsers[ data.index ],
savedSearch = query;
// parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true );
txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
}
// iExact may be numeric - see issue #149;
@ -595,10 +593,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table );
}
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
}
// keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) {
@ -610,13 +608,13 @@
},
// Look for a not match
notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) {
if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx,
txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsf.regex.exact.test( filter ) ) {
filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsfRegex.exact.test( filter ) ) {
// 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;
} else {
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
exact: function( c, data ) {
/*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
}
return null;
},
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) {
if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2,
table = c.table,
index = data.index,
parsed = data.parsed[index],
// 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, '' ) || '';
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, '' ) || '';
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 )
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 );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
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
wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
var index = data.index,
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
// 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 + ')$';
}
// parsing the filter may not work properly when using wildcards =/
try {
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' : ''
)
.test( data.exact );
@ -694,21 +690,18 @@
},
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx,
patternIndx = 0,
len = data.iExact.length,
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++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1;
}
}
if ( patternIndx === pattern.length ) {
return true;
}
return false;
return patternIndx === pattern.length;
}
return null;
}
@ -721,8 +714,7 @@
and : 'and'
}, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect,
regex = tsf.regex;
var options, string, txt, $header, column, filters, val, fxn, noSelect;
c.$table.addClass( 'hasFilters' );
// 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_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}';
$.extend( regex, {
val = '\\{' + tsfRegex.query + '\\}';
$.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -1012,8 +1004,10 @@
c.$table.data( 'lastSearch', filters );
return filters;
},
parseFilter: function( c, filter, column, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter;
parseFilter: function( c, filter, data, parsed ) {
return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
},
buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -1265,8 +1259,8 @@
},
defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length,
var regex = tsfRegex.iQuery,
maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1,
indx = 0,
@ -1363,9 +1357,8 @@
return filterMatched;
},
processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched,
var result, filterMatched,
fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions,
showRow = true,
@ -1444,7 +1437,7 @@
result = data.rawArray[ columnIndex ] || '';
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.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -1462,21 +1455,13 @@
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.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null;
if ( fxn || ( hasSelect && val ) ) {
if ( fxn === true || hasSelect ) {
if ( fxn ) {
if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ?
// data.iExact may be a number
@ -1502,7 +1487,7 @@
// Look for match, and add child row data for matching
} else {
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 ) );
}
} else {
@ -1522,7 +1507,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config,
wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters
@ -1604,7 +1588,7 @@
);
if ( wo.filter_columnAnyMatch ) {
// specific columns search
query = data.anyMatchFilter.split( regex.andSplit );
query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false;
for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' );
@ -1639,12 +1623,12 @@
// there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 &&
// 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 '!'
!regex.exactTest.test( val ) &&
!tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative
// ( '> -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
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -1662,7 +1646,7 @@
// replace accents
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 );
// clear search filtered flag because default filters are not saved to the last search
searchFiltered = false;
@ -1679,9 +1663,9 @@
txt = $rows[ rowIndex ].className;
// 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
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) {
if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue;
}
@ -1791,7 +1775,6 @@
// custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail );
}
if ( arry === false ) {
// fall back to original method
arry = tsf.getOptions( table, column, onlyAvail );
@ -1805,18 +1788,19 @@
return false;
}
table = $( table )[0];
var cts, txt, indx, len,
var cts, txt, indx, len, parsedTxt, str,
c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = [];
// get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx;
});
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options
return arry;
@ -1825,22 +1809,30 @@
// parse select option values
for ( indx = 0; indx < len; 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
// table cell to the parser format function
parsed.push({
t : txt,
// check parser length - fixes #934
p : validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( txt, table, [], column ) || txt
});
if ( txt.text ) {
txt.parsed = parsedTxt;
parsed.push( txt );
} else {
parsed.push({
text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
}
// sort parsed select options
cts = c.textSorter || '';
parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings
var x = a.p.toString(),
y = b.p.toString();
var x = a.parsed,
y = b.parsed;
if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter
return cts( x, y, true, column, table );
@ -1858,7 +1850,7 @@
arry = [];
len = parsed.length;
for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t );
arry.push( parsed[indx] );
}
return arry;
}
@ -1918,7 +1910,7 @@
return;
}
var indx, val, txt, t, $filters, $filter,
var indx, val, txt, t, $filters, $filter, option,
c = table.config,
wo = c.widgetOptions,
node = c.$headerIndexed[ column ],
@ -1943,23 +1935,45 @@
if ( $.isArray( arry ) ) {
// build option list
for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.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];
option = arry[ indx ];
if ( option.text ) {
// OBJECT!! add data-function-name in case the value is set in filter_functions
option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// support jQuery < v1.8, otherwise the below code could be shortened to
// options += $( '<option>', option )[ 0 ].outerHTML;
options += '<option';
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
arry = [];
@ -2005,6 +2019,9 @@
}
};
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols,
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);

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);

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);

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+
* 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-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="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>
<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>
@ -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>Grouping rows widget:
<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>
</ul>
</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><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>
<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>

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 ) */
(function(factory) {
if (typeof define === 'function' && define.amd) {
@ -16,7 +16,7 @@
}
}(function($) {
/*! TableSorter (FORK) v2.24.3 *//*
/*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease!
* @requires jQuery v1.2.6+
*
@ -39,7 +39,7 @@
'use strict';
var ts = $.tablesorter = {
version : '2.24.3',
version : '2.24.4',
parsers : [],
widgets : [],
@ -157,12 +157,13 @@
// labels applied to sortable headers for accessibility (aria) support
language : {
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
sortAsc : 'Ascending sort applied, ',
sortDesc : 'Descending sort applied, ',
sortNone : 'No sort applied, ',
sortDisabled : 'sorting is disabled',
nextAsc : 'activate to apply an ascending sort',
nextDesc : 'activate to apply a descending sort',
nextNone : 'activate to remove the sort'
},
regex : {
@ -1011,7 +1012,7 @@
*/
setHeadersCss : function( c ) {
var $sorted, header, indx, column, $header, nextSort, txt, tmp,
var $sorted, indx, column,
list = c.sortList,
len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone,
@ -1079,50 +1080,62 @@
}
// add verbose aria labels
len = c.$headers.length;
$headers = c.$headers.not( '.sorter-false' );
for ( indx = 0; indx < len; indx++ ) {
$header = $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 ) ];
ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
}
},
// 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 ) ?
'sortAsc' :
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone';
txt = $.trim( $header.text() ) + ': ' +
ts.language[ tmp ] +
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
$header.attr( 'aria-label', txt );
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
txt += ts.language.sortDisabled;
} 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 ) {
var index, isDisabled, $th, col,
var index, isDisabled, $header, col,
table = c.table,
len = c.$headers.length;
for ( index = 0; index < len; index++ ) {
$th = c.$headers.eq( index );
$header = c.$headers.eq( index );
col = ts.getColumnData( table, c.headers, index, true );
// add 'sorter-false' class if 'parser-false' is set
isDisabled = ts.getData( $th, col, 'sorter' ) === 'false' || ts.getData( $th, col, 'parser' ) === 'false';
$th[ 0 ].sortDisabled = isDisabled;
$th[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' ).attr( 'aria-disabled', '' + isDisabled );
// disable tab index on disabled cells
if ( c.tabIndex ) {
if ( isDisabled ) {
$th.removeAttr( 'tabindex' );
} else {
$th.attr( 'tabindex', '0' );
}
isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
ts.setColumnSort( c, $header, isDisabled );
}
},
setColumnSort : function( c, $header, isDisabled ) {
var id = c.table.id;
$header[ 0 ].sortDisabled = isDisabled;
$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 ) {
if ( isDisabled ) {
$th.removeAttr( 'aria-controls' );
} else {
$th.attr( 'aria-controls', table.id );
}
}
// aria-controls - requires table ID
if ( id ) {
if ( isDisabled ) {
$header.removeAttr( 'aria-controls' );
} else {
$header.attr( 'aria-controls', id );
}
}
},
@ -2184,14 +2197,14 @@
// *** Process table ***
// add processing indicator
isProcessing : function( $table, toggle, $ths ) {
isProcessing : function( $table, toggle, $headers ) {
$table = $( $table );
var c = $table[ 0 ].config,
// default to all headers
$header = $ths || $table.find( '.' + ts.css.header );
$header = $headers || $table.find( '.' + ts.css.header );
if ( toggle ) {
// don't use sortList if custom $ths used
if ( typeof $ths !== 'undefined' && c.sortList.length > 0 ) {
// don't use sortList if custom $headers used
if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
// get headers from the sortList
$header = $header.filter( function() {
// get data-column from attr to keep compatibility with jQuery 1.2.6
@ -2983,13 +2996,13 @@
})(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+
* by Rob Garrison
*/
;( function ( $ ) {
'use strict';
var tsf,
var tsf, tsfRegex,
ts = $.tablesorter || {},
tscss = ts.css;
@ -3095,20 +3108,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: {
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,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
filter = data.filter.split( tsfRegex.orSplit ),
iFilter = data.iFilter.split( tsfRegex.orSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try {
// 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
@ -3130,22 +3144,20 @@
},
// Look for an AND or && operator ( logical and )
and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) {
if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
filter = data.filter.split( tsfRegex.andSplit ),
iFilter = data.iFilter.split( tsfRegex.andSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// 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 {
// use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -3167,10 +3179,10 @@
},
// Look for regex
regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) {
if ( tsfRegex.regex.test( data.filter ) ) {
var matches,
// 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;
try {
if ( !isRegex ) {
@ -3189,18 +3201,17 @@
// Look for operators >, >=, < or <=
operators: function( c, data ) {
// 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,
table = c.table,
index = data.index,
parsed = data.parsed[index],
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
parser = c.parsers[index],
parsed = data.parsed[ data.index ],
query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
parser = c.parsers[ data.index ],
savedSearch = query;
// parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true );
txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
}
// iExact may be numeric - see issue #149;
@ -3212,10 +3223,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table );
}
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
}
// keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) {
@ -3227,13 +3238,13 @@
},
// Look for a not match
notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) {
if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx,
txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsf.regex.exact.test( filter ) ) {
filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsfRegex.exact.test( filter ) ) {
// 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;
} else {
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
exact: function( c, data ) {
/*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
}
return null;
},
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) {
if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2,
table = c.table,
index = data.index,
parsed = data.parsed[index],
// 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, '' ) || '';
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, '' ) || '';
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 )
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 );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
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
wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
var index = data.index,
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
// 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 + ')$';
}
// parsing the filter may not work properly when using wildcards =/
try {
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' : ''
)
.test( data.exact );
@ -3311,21 +3320,18 @@
},
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx,
patternIndx = 0,
len = data.iExact.length,
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++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1;
}
}
if ( patternIndx === pattern.length ) {
return true;
}
return false;
return patternIndx === pattern.length;
}
return null;
}
@ -3338,8 +3344,7 @@
and : 'and'
}, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect,
regex = tsf.regex;
var options, string, txt, $header, column, filters, val, fxn, noSelect;
c.$table.addClass( 'hasFilters' );
// 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_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}';
$.extend( regex, {
val = '\\{' + tsfRegex.query + '\\}';
$.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -3629,8 +3634,10 @@
c.$table.data( 'lastSearch', filters );
return filters;
},
parseFilter: function( c, filter, column, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter;
parseFilter: function( c, filter, data, parsed ) {
return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
},
buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -3882,8 +3889,8 @@
},
defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length,
var regex = tsfRegex.iQuery,
maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1,
indx = 0,
@ -3980,9 +3987,8 @@
return filterMatched;
},
processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched,
var result, filterMatched,
fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions,
showRow = true,
@ -4061,7 +4067,7 @@
result = data.rawArray[ columnIndex ] || '';
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.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -4079,21 +4085,13 @@
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.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null;
if ( fxn || ( hasSelect && val ) ) {
if ( fxn === true || hasSelect ) {
if ( fxn ) {
if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ?
// data.iExact may be a number
@ -4119,7 +4117,7 @@
// Look for match, and add child row data for matching
} else {
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 ) );
}
} else {
@ -4139,7 +4137,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config,
wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters
@ -4221,7 +4218,7 @@
);
if ( wo.filter_columnAnyMatch ) {
// specific columns search
query = data.anyMatchFilter.split( regex.andSplit );
query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false;
for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' );
@ -4256,12 +4253,12 @@
// there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 &&
// 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 '!'
!regex.exactTest.test( val ) &&
!tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative
// ( '> -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
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -4279,7 +4276,7 @@
// replace accents
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 );
// clear search filtered flag because default filters are not saved to the last search
searchFiltered = false;
@ -4296,9 +4293,9 @@
txt = $rows[ rowIndex ].className;
// 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
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) {
if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue;
}
@ -4408,7 +4405,6 @@
// custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail );
}
if ( arry === false ) {
// fall back to original method
arry = tsf.getOptions( table, column, onlyAvail );
@ -4422,18 +4418,19 @@
return false;
}
table = $( table )[0];
var cts, txt, indx, len,
var cts, txt, indx, len, parsedTxt, str,
c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = [];
// get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx;
});
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options
return arry;
@ -4442,22 +4439,30 @@
// parse select option values
for ( indx = 0; indx < len; 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
// table cell to the parser format function
parsed.push({
t : txt,
// check parser length - fixes #934
p : validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( txt, table, [], column ) || txt
});
if ( txt.text ) {
txt.parsed = parsedTxt;
parsed.push( txt );
} else {
parsed.push({
text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
}
// sort parsed select options
cts = c.textSorter || '';
parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings
var x = a.p.toString(),
y = b.p.toString();
var x = a.parsed,
y = b.parsed;
if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter
return cts( x, y, true, column, table );
@ -4475,7 +4480,7 @@
arry = [];
len = parsed.length;
for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t );
arry.push( parsed[indx] );
}
return arry;
}
@ -4535,7 +4540,7 @@
return;
}
var indx, val, txt, t, $filters, $filter,
var indx, val, txt, t, $filters, $filter, option,
c = table.config,
wo = c.widgetOptions,
node = c.$headerIndexed[ column ],
@ -4560,23 +4565,45 @@
if ( $.isArray( arry ) ) {
// build option list
for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.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];
option = arry[ indx ];
if ( option.text ) {
// OBJECT!! add data-function-name in case the value is set in filter_functions
option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// support jQuery < v1.8, otherwise the below code could be shortened to
// options += $( '<option>', option )[ 0 ].outerHTML;
options += '<option';
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
arry = [];
@ -4622,6 +4649,9 @@
}
};
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols,
filters = false,

View File

@ -1,4 +1,4 @@
/*! TableSorter (FORK) v2.24.3 *//*
/*! TableSorter (FORK) v2.24.4 *//*
* Client-side table sorting with ease!
* @requires jQuery v1.2.6+
*
@ -21,7 +21,7 @@
'use strict';
var ts = $.tablesorter = {
version : '2.24.3',
version : '2.24.4',
parsers : [],
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 ) */
(function(factory) {
if (typeof define === 'function' && define.amd) {
@ -372,13 +372,13 @@
})(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+
* by Rob Garrison
*/
;( function ( $ ) {
'use strict';
var tsf,
var tsf, tsfRegex,
ts = $.tablesorter || {},
tscss = ts.css;
@ -484,20 +484,21 @@
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
types: {
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,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.orSplit ),
iFilter = data.iFilter.split( tsf.regex.orSplit ),
filter = data.filter.split( tsfRegex.orSplit ),
iFilter = data.iFilter.split( tsfRegex.orSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
try {
// 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
@ -519,22 +520,20 @@
},
// Look for an AND or && operator ( logical and )
and : function( c, data, vars ) {
if ( tsf.regex.andTest.test( data.filter ) ) {
if ( tsfRegex.andTest.test( data.filter ) ) {
var indx, filterMatched, result, query, regex,
// duplicate data but split filter
data2 = $.extend( {}, data ),
index = data.index,
parsed = data.parsed[ index ],
filter = data.filter.split( tsf.regex.andSplit ),
iFilter = data.iFilter.split( tsf.regex.andSplit ),
filter = data.filter.split( tsfRegex.andSplit ),
iFilter = data.iFilter.split( tsfRegex.andSplit ),
len = filter.length;
for ( indx = 0; indx < len; indx++ ) {
data2.nestedFilters = true;
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
// 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 {
// use try/catch just in case RegExp is invalid
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
@ -556,10 +555,10 @@
},
// Look for regex
regex: function( c, data ) {
if ( tsf.regex.regex.test( data.filter ) ) {
if ( tsfRegex.regex.test( data.filter ) ) {
var matches,
// 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;
try {
if ( !isRegex ) {
@ -578,18 +577,17 @@
// Look for operators >, >=, < or <=
operators: function( c, data ) {
// 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,
table = c.table,
index = data.index,
parsed = data.parsed[index],
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
parser = c.parsers[index],
parsed = data.parsed[ data.index ],
query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
parser = c.parsers[ data.index ],
savedSearch = query;
// parse filter value in case we're comparing numbers ( dates )
if ( parsed || parser.type === 'numeric' ) {
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
result = tsf.parseFilter( c, txt, index, true );
txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
result = tsf.parseFilter( c, txt, data, true );
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
}
// iExact may be numeric - see issue #149;
@ -601,10 +599,10 @@
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
cachedValue = ts.formatFloat( txt, table );
}
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
if ( tsfRegex.gtTest.test( data.iFilter ) ) {
result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
}
// keep showing all rows if nothing follows the operator
if ( !result && savedSearch === '' ) {
@ -616,13 +614,13 @@
},
// Look for a not match
notMatch: function( c, data ) {
if ( tsf.regex.notTest.test( data.iFilter ) ) {
if ( tsfRegex.notTest.test( data.iFilter ) ) {
var indx,
txt = data.iFilter.replace( '!', '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsf.regex.exact.test( filter ) ) {
filter = tsf.parseFilter( c, txt, data ) || '';
if ( tsfRegex.exact.test( filter ) ) {
// 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;
} else {
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
exact: function( c, data ) {
/*jshint eqeqeq:false */
if ( tsf.regex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
if ( tsfRegex.exact.test( data.iFilter ) ) {
var txt = data.iFilter.replace( tsfRegex.exact, '' ),
filter = tsf.parseFilter( c, txt, data ) || '';
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
}
return null;
},
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
range : function( c, data ) {
if ( tsf.regex.toTest.test( data.iFilter ) ) {
if ( tsfRegex.toTest.test( data.iFilter ) ) {
var result, tmp, range1, range2,
table = c.table,
index = data.index,
parsed = data.parsed[index],
// 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, '' ) || '';
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, '' ) || '';
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 )
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 );
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
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
wild : function( c, data ) {
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
var index = data.index,
parsed = data.parsed[ index ],
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
// 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 + ')$';
}
// parsing the filter may not work properly when using wildcards =/
try {
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' : ''
)
.test( data.exact );
@ -700,21 +696,18 @@
},
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
fuzzy: function( c, data ) {
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
var indx,
patternIndx = 0,
len = data.iExact.length,
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++ ) {
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
patternIndx += 1;
}
}
if ( patternIndx === pattern.length ) {
return true;
}
return false;
return patternIndx === pattern.length;
}
return null;
}
@ -727,8 +720,7 @@
and : 'and'
}, ts.language );
var options, string, txt, $header, column, filters, val, fxn, noSelect,
regex = tsf.regex;
var options, string, txt, $header, column, filters, val, fxn, noSelect;
c.$table.addClass( 'hasFilters' );
// 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_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
val = '\\{' + tsf.regex.query + '\\}';
$.extend( regex, {
val = '\\{' + tsfRegex.query + '\\}';
$.extend( tsfRegex, {
child : new RegExp( c.cssChildRow ),
filtered : new RegExp( wo.filter_filteredRow ),
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
@ -1018,8 +1010,10 @@
c.$table.data( 'lastSearch', filters );
return filters;
},
parseFilter: function( c, filter, column, parsed ) {
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter;
parseFilter: function( c, filter, data, parsed ) {
return parsed || data.parsed[ data.index ] ?
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
filter;
},
buildRow: function( table, c, wo ) {
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
@ -1271,8 +1265,8 @@
},
defaultFilter: function( filter, mask ) {
if ( filter === '' ) { return filter; }
var regex = tsf.regex.iQuery,
maskLen = mask.match( tsf.regex.igQuery ).length,
var regex = tsfRegex.iQuery,
maskLen = mask.match( tsfRegex.igQuery ).length,
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
len = query.length - 1,
indx = 0,
@ -1369,9 +1363,8 @@
return filterMatched;
},
processRow: function( c, data, vars ) {
var hasSelect, result, val, filterMatched,
var result, filterMatched,
fxn, ffxn, txt,
regex = tsf.regex,
wo = c.widgetOptions,
showRow = true,
@ -1450,7 +1443,7 @@
result = data.rawArray[ columnIndex ] || '';
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.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
@ -1468,21 +1461,13 @@
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.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
fxn = vars.functions[ columnIndex ];
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
filterMatched = null;
if ( fxn || ( hasSelect && val ) ) {
if ( fxn === true || hasSelect ) {
if ( fxn ) {
if ( fxn === true ) {
// default selector uses exact match unless 'filter-match' class is found
filterMatched = data.isMatch ?
// data.iExact may be a number
@ -1508,7 +1493,7 @@
// Look for match, and add child row data for matching
} else {
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 ) );
}
} else {
@ -1528,7 +1513,6 @@
isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
notFiltered, searchFiltered, query, injected, res, id, txt,
storedFilters = $.extend( [], filters ),
regex = tsf.regex,
c = table.config,
wo = c.widgetOptions,
// data object passed to filters; anyMatch is a flag for the filters
@ -1610,7 +1594,7 @@
);
if ( wo.filter_columnAnyMatch ) {
// specific columns search
query = data.anyMatchFilter.split( regex.andSplit );
query = data.anyMatchFilter.split( tsfRegex.andSplit );
injected = false;
for ( indx = 0; indx < query.length; indx++ ) {
res = query[ indx ].split( ':' );
@ -1645,12 +1629,12 @@
// there are no changes from beginning of filter
val.indexOf( lastSearch[indx] || '' ) === 0 &&
// 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 '!'
!regex.exactTest.test( val ) &&
!tsfRegex.exactTest.test( val ) &&
// don't search only filtered if the value is negative
// ( '> -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
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
@ -1668,7 +1652,7 @@
// replace accents
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 );
// clear search filtered flag because default filters are not saved to the last search
searchFiltered = false;
@ -1685,9 +1669,9 @@
txt = $rows[ rowIndex ].className;
// 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
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) {
if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
continue;
}
@ -1797,7 +1781,6 @@
// custom select source function for a SPECIFIC COLUMN
arry = fxn( table, column, onlyAvail );
}
if ( arry === false ) {
// fall back to original method
arry = tsf.getOptions( table, column, onlyAvail );
@ -1811,18 +1794,19 @@
return false;
}
table = $( table )[0];
var cts, txt, indx, len,
var cts, txt, indx, len, parsedTxt, str,
c = table.config,
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
parsed = [];
// get unique elements and sort the list
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
// then natural sort the list otherwise use a basic sort
arry = $.grep( arry, function( value, indx ) {
if ( value.text ) {
return true;
}
return $.inArray( value, arry ) === indx;
});
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
// unsorted select options
return arry;
@ -1831,22 +1815,30 @@
// parse select option values
for ( indx = 0; indx < len; 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
// table cell to the parser format function
parsed.push({
t : txt,
// check parser length - fixes #934
p : validColumn && c.parsers && c.parsers.length &&
c.parsers[ column ].format( txt, table, [], column ) || txt
});
if ( txt.text ) {
txt.parsed = parsedTxt;
parsed.push( txt );
} else {
parsed.push({
text : txt,
// check parser length - fixes #934
parsed : parsedTxt
});
}
}
// sort parsed select options
cts = c.textSorter || '';
parsed.sort( function( a, b ) {
// sortNatural breaks if you don't pass it strings
var x = a.p.toString(),
y = b.p.toString();
var x = a.parsed,
y = b.parsed;
if ( validColumn && typeof cts === 'function' ) {
// custom OVERALL text sorter
return cts( x, y, true, column, table );
@ -1864,7 +1856,7 @@
arry = [];
len = parsed.length;
for ( indx = 0; indx < len; indx++ ) {
arry.push( parsed[indx].t );
arry.push( parsed[indx] );
}
return arry;
}
@ -1924,7 +1916,7 @@
return;
}
var indx, val, txt, t, $filters, $filter,
var indx, val, txt, t, $filters, $filter, option,
c = table.config,
wo = c.widgetOptions,
node = c.$headerIndexed[ column ],
@ -1949,23 +1941,45 @@
if ( $.isArray( arry ) ) {
// build option list
for ( indx = 0; indx < arry.length; indx++ ) {
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.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];
option = arry[ indx ];
if ( option.text ) {
// OBJECT!! add data-function-name in case the value is set in filter_functions
option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
// support jQuery < v1.8, otherwise the below code could be shortened to
// options += $( '<option>', option )[ 0 ].outerHTML;
options += '<option';
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
arry = [];
@ -2011,6 +2025,9 @@
}
};
// filter regex variable
tsfRegex = tsf.regex;
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
var i, $filters, $column, cols,
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
* 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+
* 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+
* 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+
* 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+
* 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+
* 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+
* 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+
* by Rob Garrison
*/

View File

@ -1,7 +1,7 @@
{
"name": "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.",
"author": {
"name": "Christian Bach",

View File

@ -1,7 +1,7 @@
{
"name": "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.",
"author": {
"name": "Christian Bach",