Merge branch 'master' into gh-pages

This commit is contained in:
Rob Garrison 2017-12-13 15:19:59 -06:00
commit 7b4496d4d6
28 changed files with 566 additions and 229 deletions

View File

@ -77,5 +77,11 @@ Simen Flatby <simenflatby@users.noreply.github.com>
Ruchir Patel <ruchir.patel19@gmail.com> Ruchir Patel <ruchir.patel19@gmail.com>
Andy Sleigh <adsleigh@hotmail.com> Andy Sleigh <adsleigh@hotmail.com>
Micah <micahedumont@gmail.com> Micah <micahedumont@gmail.com>
LaurentBarbareau <lbarbareau@gmail.com>
ced-b <cedric@cos.flag.org>
Federico-G <federicogasior@hotmail.com>
Lars <lars.bodtke@live.de>
Alex Weissman <alex@alexanderweissman.com>
Andrew Murphy <aavmurphy@users.noreply.github.com>
# Generated by tools/authors.sh # Generated by tools/authors.sh

View File

@ -104,6 +104,28 @@ If you would like to contribute, please...
View the [complete change log here](https://github.com/Mottie/tablesorter/wiki/Changes). View the [complete change log here](https://github.com/Mottie/tablesorter/wiki/Changes).
#### <a name="v2.29.1">Version 2.29.1</a> (12/13/2017)
* Core:
* Fix non-typical use of selectorHeaders. See [issue #1459](https://github.com/Mottie/tablesorter/issues/1459).
* Update external header icons on sort. Fixes [issue #1483](https://github.com/Mottie/tablesorter/issues/1483).
* Remove an empty block.
* Filter:
* Select exact matches ignore "and" and "or" keywords. Fixes [issue #1486](https://github.com/Mottie/tablesorter/issues/1486).
* Resizable:
* `addLastColumn` stops adding handles to hidden columns. Fixes [issue #1485](https://github.com/Mottie/tablesorter/issues/1485).
* Scroller:
* Adjust columns on `filterInit`. See [issue #1468](https://github.com/Mottie/tablesorter/issues/1468).
* Vertical Group:
* New widget added. See [demo](https://mottie.github.io/tablesorter/docs/example-widget-vertical-group.html).
* Thanks to [aavmurphy](https://github.com/aavmurphy) for sharing the code. See [issue #1469](https://github.com/Mottie/tablesorter/issues/1469) and [PR #1470](https://github.com/Mottie/tablesorter/pull/1470).
* Docs:
* Fix pager example.
* List all contained IP parsers. Fixes [issue #1484](https://github.com/Mottie/tablesorter/issues/1484).
* Fix Bootstrap v2 demo; restored gyphs images.
* Meta:
* Update authors.
#### <a name="v2.29.0">Version 2.29.0</a> (9/27/2017) #### <a name="v2.29.0">Version 2.29.0</a> (9/27/2017)
* Core: * Core:
@ -164,15 +186,3 @@ View the [complete change log here](https://github.com/Mottie/tablesorter/wiki/C
* Use src files in filter formatter demo for testing. * Use src files in filter formatter demo for testing.
* Meta: * Meta:
* Include `js` & `css` folders with bower installs. * Include `js` & `css` folders with bower installs.
#### <a name="v2.28.14">Version 2.28.14</a> (6/8/2017)
* Core:
* Show console error for mismatched column count. See [issue #1415](https://github.com/Mottie/tablesorter/issues/1415).
* Pager:
* (addon) Ensure ajax is called after filter widget init. Fixes [issue #1389](https://github.com/Mottie/tablesorter/issues/1389).
* (addon) Fix height issues for certain browsers (border-spacing). See [pull #1418](https://github.com/Mottie/tablesorter/pull/1418); thanks [@DoctorWhite](https://github.com/DoctorWhite)
* (widget) Apply height adjustment code to pager widget.
* Use selectorRemove to remove error rows. Removes error rows with dynamically changed class names.
* Meta:
* Added [AUTHORS](https://github.com/Mottie/tablesorter/blob/master/AUTHORS) file.

View File

@ -1,4 +1,4 @@
/*! tablesorter (FORK) - updated 09-27-2017 (v2.29.0)*/ /*! tablesorter (FORK) - updated 12-13-2017 (v2.29.1)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -10,7 +10,7 @@
} }
}(function(jQuery) { }(function(jQuery) {
/*! TableSorter (FORK) v2.29.0 *//* /*! TableSorter (FORK) v2.29.1 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -34,7 +34,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.29.0', version : '2.29.1',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -526,8 +526,7 @@
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) { if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
ts.buildCache( c ); ts.buildCache( c );
} }
// jQuery v1.2.6 doesn't have closest() $cell = ts.getClosest( $( this ), '.' + ts.css.header );
$cell = ts.getHeaderCell( $( this ) );
// reference original table headers and find the same cell // reference original table headers and find the same cell
// don't use $headers or IE8 throws an error - see #987 // don't use $headers or IE8 throws an error - see #987
temp = $headers.index( $cell ); temp = $headers.index( $cell );
@ -567,10 +566,15 @@
''; '';
// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) { c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {
var configHeaders, header, column, template, tmp, $th, var configHeaders, header, column, template, tmp,
$elem = $( elem ); $elem = $( elem );
// ignore cell (don't add it to c.$headers) if row has ignoreRow class // ignore cell (don't add it to c.$headers) if row has ignoreRow class
if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; }
// transfer data-column to element if not th/td - #1459
if ( !/(th|td)/i.test( elem.nodeName ) ) {
tmp = ts.getClosest( $elem, 'th, td' );
$elem.attr( 'data-column', tmp.attr( 'data-column' ) );
}
// make sure to get header cell & not column indexed cell // make sure to get header cell & not column indexed cell
configHeaders = ts.getColumnData( c.table, c.headers, index, true ); configHeaders = ts.getColumnData( c.table, c.headers, index, true );
// save original header content // save original header content
@ -593,9 +597,7 @@
if ( c.onRenderHeader ) { if ( c.onRenderHeader ) {
c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); c.onRenderHeader.apply( $elem, [ index, c, c.$table ] );
} }
// data-column stored on th or td only column = parseInt( $elem.attr( 'data-column' ), 10 );
$th = ts.getHeaderCell( $elem );
column = parseInt( $th.attr( 'data-column' ), 10 );
elem.column = column; elem.column = column;
tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder ); tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );
// this may get updated numerous times if there are multiple rows // this may get updated numerous times if there are multiple rows
@ -631,6 +633,7 @@
if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) { if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {
c.sortVars[ indx ] = {}; c.sortVars[ indx ] = {};
} }
// Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td
$temp = c.$headers.filter( '[data-column="' + indx + '"]' ); $temp = c.$headers.filter( '[data-column="' + indx + '"]' );
// target sortable column cells, unless there are none, then use non-sortable cells // target sortable column cells, unless there are none, then use non-sortable cells
// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
@ -1094,6 +1097,15 @@
css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = [ 'ascending', 'descending' ], aria = [ 'ascending', 'descending' ],
updateColumnSort = function($el, index) {
$el
.removeClass( none )
.addClass( css[ index ] )
.attr( 'aria-sort', aria[ index ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ index ] );
},
// find the footer // find the footer
$extras = c.$table $extras = c.$table
.find( 'tfoot tr' ) .find( 'tfoot tr' )
@ -1132,7 +1144,7 @@
var include = true, var include = true,
$el = c.$headers.eq( i ), $el = c.$headers.eq( i ),
col = parseInt( $el.attr( 'data-column' ), 10 ), col = parseInt( $el.attr( 'data-column' ), 10 ),
end = col + c.$headers[ i ].colSpan; end = col + ts.getClosest( $el, 'th, td' )[0].colSpan;
for ( ; col < end; col++ ) { for ( ; col < end; col++ ) {
include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false; include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;
} }
@ -1146,23 +1158,13 @@
if ( $sorted.length ) { if ( $sorted.length ) {
for ( column = 0; column < $sorted.length; column++ ) { for ( column = 0; column < $sorted.length; column++ ) {
if ( !$sorted[ column ].sortDisabled ) { if ( !$sorted[ column ].sortDisabled ) {
$sorted updateColumnSort( $sorted.eq( column ) , list[ indx ][ 1 ] );
.eq( column )
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] )
.attr( 'aria-sort', aria[ list[ indx ][ 1 ] ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ list[ indx ][ 1 ] ] );
} }
} }
// add sorted class to footer & extra headers, if they exist }
if ( $extras.length ) { // add sorted class to footer & extra headers, if they exist
$extras if ( $extras.length ) {
.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ) updateColumnSort( $extras.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ), list[ indx ][ 1 ] );
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] );
}
} }
} }
} }
@ -1173,29 +1175,20 @@
} }
}, },
// This function does NOT return closest if the $el matches the selector
getClosest : function( $el, selector ) { getClosest : function( $el, selector ) {
return $.fn.closest ?
$el.closest( selector ) :
$el.parents( selector ).filter( ':first' );
},
getHeaderCell : function( $el ) {
// jQuery v1.2.6 doesn't have closest() // jQuery v1.2.6 doesn't have closest()
if ( $.fn.closest ) { if ( $.fn.closest ) {
return $el.closest( 'th, td' ); return $el.closest( selector );
} }
return /TH|TD/.test( $el[0].nodeName ) ? return $el.is( selector ) ?
$el : $el :
$el.parents( 'th, td' ).filter( ':first' ); $el.parents( selector ).filter( ':first' );
}, },
// nextSort (optional), lets you disable next sort text // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) { setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) { if ( $header.length ) {
var $th = ts.getHeaderCell( $header ), var column = parseInt( $header.attr( 'data-column' ), 10 ),
// data-column always stored on the th/td
column = parseInt( $th.attr( 'data-column' ), 10 ),
vars = c.sortVars[ column ], vars = c.sortVars[ column ],
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
@ -1563,10 +1556,10 @@
notMultiSort = !event[ c.sortMultiSortKey ], notMultiSort = !event[ c.sortMultiSortKey ],
table = c.table, table = c.table,
len = c.$headers.length, len = c.$headers.length,
// get current column index; *always* stored on th/td th = ts.getClosest( $( cell ), 'th, td' ),
$th = ts.getHeaderCell( $( cell ) ), col = parseInt( th.attr( 'data-column' ), 10 ),
col = parseInt( $th.attr( 'data-column' ), 10 ),
order = c.sortVars[ col ].order; order = c.sortVars[ col ].order;
th = th[0];
// Only call sortStart if sorting is enabled // Only call sortStart if sorting is enabled
c.$table.triggerHandler( 'sortStart', table ); c.$table.triggerHandler( 'sortStart', table );
// get current column sort order // get current column sort order
@ -1601,8 +1594,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -1634,8 +1627,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -2404,7 +2397,7 @@
$cells = ( $headers || c.$headers ), $cells = ( $headers || c.$headers ),
// c.$headerIndexed is not defined initially // c.$headerIndexed is not defined initially
$cell = c.$headerIndexed && c.$headerIndexed[ indx ] || $cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||
$cells.filter( '[data-column="' + indx + '"]:last' ); $cells.find( '[data-column="' + indx + '"]:last' );
if ( typeof obj[ indx ] !== 'undefined' ) { if ( typeof obj[ indx ] !== 'undefined' ) {
return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ]; return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];
} }
@ -4406,6 +4399,7 @@
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) { if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
matches = tsf.types[ffxn]( c, data, vars ); matches = tsf.types[ffxn]( c, data, vars );
if ( matches !== null ) { if ( matches !== null ) {
data.matchedOn = ffxn;
filterMatched = matches; filterMatched = matches;
} }
} }
@ -4453,6 +4447,7 @@
tsf.multipleColumns( c, wo.filter_$anyMatch ) : tsf.multipleColumns( c, wo.filter_$anyMatch ) :
[]; [];
data.$cells = data.$row.children(); data.$cells = data.$row.children();
data.matchedOn = null;
if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) { if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {
data.anyMatch = true; data.anyMatch = true;
data.isMatch = true; data.isMatch = true;
@ -4554,7 +4549,9 @@
// cycle through the different filters // cycle through the different filters
// filters return a boolean or null if nothing matches // filters return a boolean or null if nothing matches
filterMatched = tsf.processTypes( c, data, vars ); filterMatched = tsf.processTypes( c, data, vars );
if ( filterMatched !== null ) { // select with exact match; ignore "and" or "or" within the text; fixes #1486
txt = fxn === true && (data.matchedOn === 'and' || data.matchedOn === 'or');
if ( filterMatched !== null && !txt) {
result = filterMatched; result = filterMatched;
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
@ -5713,7 +5710,10 @@
columns = c.columns - 1, columns = c.columns - 1,
$header = $this.data( 'header' ); $header = $this.data( 'header' );
if ( !$header ) { return; } // see #859 if ( !$header ) { return; } // see #859
if ( !$header.is(':visible') ) { if (
!$header.is(':visible') ||
( !wo.resizable_addLastColumn && ts.resizable.checkVisibleColumns(c, column) )
) {
$this.hide(); $this.hide();
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
$this.css({ $this.css({
@ -5725,6 +5725,16 @@
}); });
}, },
// Fixes #1485
checkVisibleColumns: function( c, column ) {
var i,
len = 0;
for ( i = column + 1; i < c.columns; i++ ) {
len += c.$headerIndexed[i].is( ':visible' ) ? 1 : 0;
}
return len === 0;
},
// prevent text selection while dragging resize bar // prevent text selection while dragging resize bar
toggleTextSelection : function( c, wo, toggle ) { toggleTextSelection : function( c, wo, toggle ) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,7 @@
} }
}(function(jQuery) { }(function(jQuery) {
/*! TableSorter (FORK) v2.29.0 *//* /*! TableSorter (FORK) v2.29.1 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -32,7 +32,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.29.0', version : '2.29.1',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -524,8 +524,7 @@
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) { if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
ts.buildCache( c ); ts.buildCache( c );
} }
// jQuery v1.2.6 doesn't have closest() $cell = ts.getClosest( $( this ), '.' + ts.css.header );
$cell = ts.getHeaderCell( $( this ) );
// reference original table headers and find the same cell // reference original table headers and find the same cell
// don't use $headers or IE8 throws an error - see #987 // don't use $headers or IE8 throws an error - see #987
temp = $headers.index( $cell ); temp = $headers.index( $cell );
@ -565,10 +564,15 @@
''; '';
// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) { c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {
var configHeaders, header, column, template, tmp, $th, var configHeaders, header, column, template, tmp,
$elem = $( elem ); $elem = $( elem );
// ignore cell (don't add it to c.$headers) if row has ignoreRow class // ignore cell (don't add it to c.$headers) if row has ignoreRow class
if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; }
// transfer data-column to element if not th/td - #1459
if ( !/(th|td)/i.test( elem.nodeName ) ) {
tmp = ts.getClosest( $elem, 'th, td' );
$elem.attr( 'data-column', tmp.attr( 'data-column' ) );
}
// make sure to get header cell & not column indexed cell // make sure to get header cell & not column indexed cell
configHeaders = ts.getColumnData( c.table, c.headers, index, true ); configHeaders = ts.getColumnData( c.table, c.headers, index, true );
// save original header content // save original header content
@ -591,9 +595,7 @@
if ( c.onRenderHeader ) { if ( c.onRenderHeader ) {
c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); c.onRenderHeader.apply( $elem, [ index, c, c.$table ] );
} }
// data-column stored on th or td only column = parseInt( $elem.attr( 'data-column' ), 10 );
$th = ts.getHeaderCell( $elem );
column = parseInt( $th.attr( 'data-column' ), 10 );
elem.column = column; elem.column = column;
tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder ); tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );
// this may get updated numerous times if there are multiple rows // this may get updated numerous times if there are multiple rows
@ -629,6 +631,7 @@
if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) { if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {
c.sortVars[ indx ] = {}; c.sortVars[ indx ] = {};
} }
// Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td
$temp = c.$headers.filter( '[data-column="' + indx + '"]' ); $temp = c.$headers.filter( '[data-column="' + indx + '"]' );
// target sortable column cells, unless there are none, then use non-sortable cells // target sortable column cells, unless there are none, then use non-sortable cells
// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
@ -1092,6 +1095,15 @@
css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = [ 'ascending', 'descending' ], aria = [ 'ascending', 'descending' ],
updateColumnSort = function($el, index) {
$el
.removeClass( none )
.addClass( css[ index ] )
.attr( 'aria-sort', aria[ index ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ index ] );
},
// find the footer // find the footer
$extras = c.$table $extras = c.$table
.find( 'tfoot tr' ) .find( 'tfoot tr' )
@ -1130,7 +1142,7 @@
var include = true, var include = true,
$el = c.$headers.eq( i ), $el = c.$headers.eq( i ),
col = parseInt( $el.attr( 'data-column' ), 10 ), col = parseInt( $el.attr( 'data-column' ), 10 ),
end = col + c.$headers[ i ].colSpan; end = col + ts.getClosest( $el, 'th, td' )[0].colSpan;
for ( ; col < end; col++ ) { for ( ; col < end; col++ ) {
include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false; include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;
} }
@ -1144,23 +1156,13 @@
if ( $sorted.length ) { if ( $sorted.length ) {
for ( column = 0; column < $sorted.length; column++ ) { for ( column = 0; column < $sorted.length; column++ ) {
if ( !$sorted[ column ].sortDisabled ) { if ( !$sorted[ column ].sortDisabled ) {
$sorted updateColumnSort( $sorted.eq( column ) , list[ indx ][ 1 ] );
.eq( column )
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] )
.attr( 'aria-sort', aria[ list[ indx ][ 1 ] ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ list[ indx ][ 1 ] ] );
} }
} }
// add sorted class to footer & extra headers, if they exist }
if ( $extras.length ) { // add sorted class to footer & extra headers, if they exist
$extras if ( $extras.length ) {
.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ) updateColumnSort( $extras.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ), list[ indx ][ 1 ] );
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] );
}
} }
} }
} }
@ -1171,29 +1173,20 @@
} }
}, },
// This function does NOT return closest if the $el matches the selector
getClosest : function( $el, selector ) { getClosest : function( $el, selector ) {
return $.fn.closest ?
$el.closest( selector ) :
$el.parents( selector ).filter( ':first' );
},
getHeaderCell : function( $el ) {
// jQuery v1.2.6 doesn't have closest() // jQuery v1.2.6 doesn't have closest()
if ( $.fn.closest ) { if ( $.fn.closest ) {
return $el.closest( 'th, td' ); return $el.closest( selector );
} }
return /TH|TD/.test( $el[0].nodeName ) ? return $el.is( selector ) ?
$el : $el :
$el.parents( 'th, td' ).filter( ':first' ); $el.parents( selector ).filter( ':first' );
}, },
// nextSort (optional), lets you disable next sort text // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) { setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) { if ( $header.length ) {
var $th = ts.getHeaderCell( $header ), var column = parseInt( $header.attr( 'data-column' ), 10 ),
// data-column always stored on the th/td
column = parseInt( $th.attr( 'data-column' ), 10 ),
vars = c.sortVars[ column ], vars = c.sortVars[ column ],
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
@ -1561,10 +1554,10 @@
notMultiSort = !event[ c.sortMultiSortKey ], notMultiSort = !event[ c.sortMultiSortKey ],
table = c.table, table = c.table,
len = c.$headers.length, len = c.$headers.length,
// get current column index; *always* stored on th/td th = ts.getClosest( $( cell ), 'th, td' ),
$th = ts.getHeaderCell( $( cell ) ), col = parseInt( th.attr( 'data-column' ), 10 ),
col = parseInt( $th.attr( 'data-column' ), 10 ),
order = c.sortVars[ col ].order; order = c.sortVars[ col ].order;
th = th[0];
// Only call sortStart if sorting is enabled // Only call sortStart if sorting is enabled
c.$table.triggerHandler( 'sortStart', table ); c.$table.triggerHandler( 'sortStart', table );
// get current column sort order // get current column sort order
@ -1599,8 +1592,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -1632,8 +1625,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -2402,7 +2395,7 @@
$cells = ( $headers || c.$headers ), $cells = ( $headers || c.$headers ),
// c.$headerIndexed is not defined initially // c.$headerIndexed is not defined initially
$cell = c.$headerIndexed && c.$headerIndexed[ indx ] || $cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||
$cells.filter( '[data-column="' + indx + '"]:last' ); $cells.find( '[data-column="' + indx + '"]:last' );
if ( typeof obj[ indx ] !== 'undefined' ) { if ( typeof obj[ indx ] !== 'undefined' ) {
return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ]; return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];
} }

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
/*! tablesorter (FORK) - updated 09-27-2017 (v2.29.0)*/ /*! tablesorter (FORK) - updated 12-13-2017 (v2.29.1)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -1519,6 +1519,7 @@
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) { if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
matches = tsf.types[ffxn]( c, data, vars ); matches = tsf.types[ffxn]( c, data, vars );
if ( matches !== null ) { if ( matches !== null ) {
data.matchedOn = ffxn;
filterMatched = matches; filterMatched = matches;
} }
} }
@ -1566,6 +1567,7 @@
tsf.multipleColumns( c, wo.filter_$anyMatch ) : tsf.multipleColumns( c, wo.filter_$anyMatch ) :
[]; [];
data.$cells = data.$row.children(); data.$cells = data.$row.children();
data.matchedOn = null;
if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) { if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {
data.anyMatch = true; data.anyMatch = true;
data.isMatch = true; data.isMatch = true;
@ -1667,7 +1669,9 @@
// cycle through the different filters // cycle through the different filters
// filters return a boolean or null if nothing matches // filters return a boolean or null if nothing matches
filterMatched = tsf.processTypes( c, data, vars ); filterMatched = tsf.processTypes( c, data, vars );
if ( filterMatched !== null ) { // select with exact match; ignore "and" or "or" within the text; fixes #1486
txt = fxn === true && (data.matchedOn === 'and' || data.matchedOn === 'or');
if ( filterMatched !== null && !txt) {
result = filterMatched; result = filterMatched;
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
@ -2826,7 +2830,10 @@
columns = c.columns - 1, columns = c.columns - 1,
$header = $this.data( 'header' ); $header = $this.data( 'header' );
if ( !$header ) { return; } // see #859 if ( !$header ) { return; } // see #859
if ( !$header.is(':visible') ) { if (
!$header.is(':visible') ||
( !wo.resizable_addLastColumn && ts.resizable.checkVisibleColumns(c, column) )
) {
$this.hide(); $this.hide();
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
$this.css({ $this.css({
@ -2838,6 +2845,16 @@
}); });
}, },
// Fixes #1485
checkVisibleColumns: function( c, column ) {
var i,
len = 0;
for ( i = column + 1; i < c.columns; i++ ) {
len += c.$headerIndexed[i].is( ':visible' ) ? 1 : 0;
}
return len === 0;
},
// prevent text selection while dragging resize bar // prevent text selection while dragging resize bar
toggleTextSelection : function( c, wo, toggle ) { toggleTextSelection : function( c, wo, toggle ) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
/*! Widget: vertical-group (BETA) - updated 12/13/2017 (v2.29.1) */
!function(r){"use strict";function e(r){r.removeClass(i.verticalGroupHide+" "+i.verticalGroupShow)}function a(r,e,a){e.parent().removeClass(r.zebra[(a+1)%2]).addClass(r.zebra[a%2])}function o(o,l,s,c){var u=-1,v=o.tBodies[0].rows,d=(o.tHead.rows,t.hasWidget(o,"zebra")),p=[],n=[];if(!s.vertical_group_lock){if(s.vertical_group_lock=!0,""===(p=r.map(l.$headerIndexed,function(r){return r.hasClass(i.verticalGroupHeader)?1:""})).join(""))return e(r(v).find("."+i.verticalGroupHide+",."+i.verticalGroupShow)),void(s.vertical_group_lock=!1);for(var h=0;h<v.length;h++)for(var G=!1,f=0;f<l.columns;f++)if(p[f]&&v[h].cells[f]){var g=r(v[h].cells[f]),C=t.isValueInArray(f,l.sortList),w=g.html();C<0?e(g):G||w!==n[f]?0===C&&(G=!0,g.hasClass(i.verticalGroupShow)||g.addClass(i.verticalGroupShow),g.removeClass(i.verticalGroupHide),d&&a(s,g,C?u:++u)):(g.hasClass(i.verticalGroupHide)||g.addClass(i.verticalGroupHide),d&&a(s,g,u),g.removeClass(i.verticalGroupShow)),n[f]=w}else u++;s.vertical_group_lock=!1}}var t=r.tablesorter,i=t.css;r.extend(t.css,{verticalGroupHeader:"tablesorter-vertical-group",verticalGroupHide:"tablesorter-vertical-group-hide",verticalGroupShow:"tablesorter-vertical-group-show"}),t.addWidget({id:"vertical-group",priority:99,init:o,format:o})}(jQuery);

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -268,7 +268,7 @@
<h2>Page Header</h2> <h2>Page Header</h2>
<div> <div>
<pre class="prettyprint lang-html">&lt;!-- Bootstrap stylesheet --&gt; <pre class="prettyprint lang-html">&lt;!-- Bootstrap stylesheet --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/bootstrap-v3.min.css&quot;&gt; &lt;link rel=&quot;stylesheet&quot; href=&quot;css/bootstrap-v2.min.css&quot;&gt;
&lt;!-- bootstrap widget theme --&gt; &lt;!-- bootstrap widget theme --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/theme.bootstrap_2.css&quot;&gt; &lt;link rel=&quot;stylesheet&quot; href=&quot;css/theme.bootstrap_2.css&quot;&gt;

View File

@ -105,7 +105,7 @@ $('table').tablesorter({
&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/theme.blue.css&quot;&gt; &lt;link rel=&quot;stylesheet&quot; href=&quot;../css/theme.blue.css&quot;&gt;
&lt;script src=&quot;../js/jquery.tablesorter.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;../js/jquery.tablesorter.js&quot;&gt;&lt;/script&gt;
&lt;!-- load ipv6 parser --&gt; &lt;!-- load mac, ipv4 and ipv6 parsers --&gt;
&lt;script src=&quot;../js/parsers/parser-network.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;../js/parsers/parser-network.js&quot;&gt;&lt;/script&gt;
&lt;script&gt; &lt;script&gt;
$(function() { $(function() {
@ -116,8 +116,8 @@ $(function() {
sortList: [[1, 0]], sortList: [[1, 0]],
headers: { headers: {
1: { sorter: 'MAC' }, 1: { sorter: 'MAC' },
// 2: { sorter: 'ipAddress' }, this parser is auto-detected // 2: { sorter: 'ipAddress' }, this parser is auto-detected (alias for 'ipv4Address')
3: { sorter: 'ipv6Address' } 3: { sorter: 'ipv6Address' } // this parser is also auto-detected
} }
}); });

View File

@ -100,6 +100,7 @@ $(function() {
<h3><a href="#">Notes</a></h3> <h3><a href="#">Notes</a></h3>
<div> <div>
<ul> <ul>
<li>In <span class="version">v2.29.1</span>, a <code>data.matchedOn</code> value was added. See the <a class="intlink" href="#how_to_add_custom_filter_types">How to add Custom filter types</a> section below.</li>
<li>In <span class="version">v2.22.0</span>, additional values were added to the <code>data</code> parameter as it is now provided as a parameter to all <a href="index.html#widget-filter-functions"><code>filter_functions</code></a>. See the "How to add Custom filter types" section below to review the new additions.</li> <li>In <span class="version">v2.22.0</span>, additional values were added to the <code>data</code> parameter as it is now provided as a parameter to all <a href="index.html#widget-filter-functions"><code>filter_functions</code></a>. See the "How to add Custom filter types" section below to review the new additions.</li>
<li><span class="label warning">Notice!</span> In version <span class="version">v2.17.8</span>, some drastic changes were made to the way variables are passed to the filters. Please check out the "How to add Custom Filter types" section below.</li> <li><span class="label warning">Notice!</span> In version <span class="version">v2.17.8</span>, some drastic changes were made to the way variables are passed to the filters. Please check out the "How to add Custom Filter types" section below.</li>
<li>This demo was added in <span class="version">v2.17.5</span>, but modification using these instructions works for v2.13.3+; when the filter widget was restructured to allow the adding of custom filter search types.</li> <li>This demo was added in <span class="version">v2.17.5</span>, but modification using these instructions works for v2.13.3+; when the filter widget was restructured to allow the adding of custom filter search types.</li>
@ -174,8 +175,9 @@ $(function() {
<li><code>data.cacheArray</code> - An array of parsed content from each table cell in the row being processed.</li> <li><code>data.cacheArray</code> - An array of parsed content from each table cell in the row being processed.</li>
<li><code>data.childRowText</code> - contains <em>all</em> text from any associated child rows.</li> <li><code>data.childRowText</code> - contains <em>all</em> text from any associated child rows.</li>
<li><code>data.parsed</code> - An array of boolean flags that indicate if the column data should be obtained from parsed values, or not; obtained from <code>filter_useParsedData</code> setting or <code>filter-parsed</code> classes on the header cells. <li><code>data.parsed</code> - An array of boolean flags that indicate if the column data should be obtained from parsed values, or not; obtained from <code>filter_useParsedData</code> setting or <code>filter-parsed</code> classes on the header cells.<br><br>
</li> </li>
<li><code>data.matchedOn</code> - The name of the filter type function (see the <a class="intlink" href="#builtin_filters">Built-in Filters</a> section above for a list) that returned a match, either <code>true</code> or <code>false</code>. If no type was matched, it will contain a <code>null</code> value; added <span class="version">v2.29.1</span>.</li>
</ul> </ul>
<br> <br>
</li> </li>

View File

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery tablesorter 2.0 - Vertical Group Widget</title>
<!-- jQuery -->
<script src="js/jquery-latest.min.js"></script>
<!-- Demo stuff -->
<link rel="stylesheet" href="css/jq.css">
<link href="css/prettify.css" rel="stylesheet">
<script src="js/prettify.js"></script>
<script src="js/docs.js"></script>
<!-- Tablesorter: required -->
<link rel="stylesheet" href="../css/theme.blue.css">
<script src="../js/jquery.tablesorter.js"></script>
<script src="../js/parsers/parser-date-weekday.js"></script>
<script src="../js/widgets/widget-vertical-group.js"></script>
<style id="css">/* Required additional CSS to make this widget work */
table.tablesorter tr:not(:last-of-type) th,
table.tablesorter tr:not(:last-of-type) td {
/* all current themes style the bottom border; we'll switch to use the top */
border-width: 1px 1px 0 0;
}
.tablesorter td.tablesorter-vertical-group-hide {
text-indent: -9999em;
border-top-color: transparent;
}
/* class added to the cell in the first row of the group */
.tablesorter td.tablesorter-vertical-group-show {}</style>
<script id="js">$(function() {
// call the tablesorter plugin
$("table").tablesorter({
theme: 'blue',
widgets: ["vertical-group", "zebra"]
});
});</script>
</head>
<body>
<div id="banner">
<h1>table<em>sorter</em></h1>
<h2>Vertical Group Widget</h2>
<h3>Flexible client-side table sorting</h3>
<a href="index.html">Back to documentation</a>
</div>
<div id="main">
<p class="tip">
<em>NOTE!</em>
</p>
<ul>
<li>Widget added in <span class="version">v2.29.1</span>. Thanks to <a href="https://github.com/aavmurphy">aavmurphy</a> for sharing the code!
<ul>
<li>This widget works by enabling it in the <code>widgets</code> option <em>and</em> adding a <code>tablesorter-vertical-group</code> class name to the header column.</li>
<li>Make sure to include the additional CSS shown on this page.</li>
<li>Click to sort a column. Any sorted columns with duplicate cell entries will be grouped together and the zebra striping will be adjusted.</li>
<li>Sorting multiple columns will again adjust the duplicates and zebra striping.</li>
</ul>
</li>
</ul>
<h1>Demo</h1>
<div id="demo"><table class="tablesorter">
<thead>
<tr>
<th class="tablesorter-vertical-group sorter-weekday">Day</th>
<th class="tablesorter-vertical-group">First Name</th>
<th class="tablesorter-vertical-group">Last Name</th></tr>
</thead>
<tbody>
<tr><td>Tuesday</td><td>Peter</td><td>Jones</td></tr>
<tr><td>Thursday</td><td>Peter</td><td>Smith</td></tr>
<tr><td>Thursday</td><td>Fred</td><td>Smith</td></tr>
<tr><td>Friday</td><td>Fred</td><td>Jones</td></tr>
<tr><td>Tuesday</td><td>Mike</td><td>Snow</td></tr>
<tr><td>Monday</td><td>Mike</td><td>Jones</td></tr>
<tr><td>Wednesday</td><td>Mike</td><td>Smith</td></tr>
<tr><td>Friday</td><td>Fred</td><td>Snow</td></tr>
<tr><td>Tuesday</td><td>Fred</td><td>Smith</td></tr>
<tr><td>Thursday</td><td>Peter</td><td>Snow</td></tr>
<tr><td>Friday</td><td>Mike</td><td>Smith</td></tr>
<tr><td>Monday</td><td>Fred</td><td>Jones</td></tr>
<tr><td>Tuesday</td><td>Peter</td><td>Snow</td></tr>
<tr><td>Friday</td><td>Mike</td><td>Jones</td></tr>
<tr><td>Wednesday</td><td>Peter</td><td>Smith</td></tr>
</tbody>
</table></div>
<h1>Page Header</h1>
<div>
<pre class="prettyprint lang-html">
&lt;link rel="stylesheet" href="css/blue/style.css"&gt;
&lt;script src="js/jquery-latest.min.js"&gt;&lt;/script&gt;
&lt;script src="js/jquery.tablesorter.min.js"&gt;&lt;/script&gt;
&lt;script src="js/widgets/widget-vertical-group.min.js">&lt;/script&gt;</pre>
</div>
<h1>CSS</h1>
<div id="css">
<pre class="prettyprint lang-css"></pre>
</div>
<h1>Javascript</h1>
<div id="javascript">
<pre class="prettyprint lang-javascript"></pre>
</div>
<h1>HTML</h1>
<div id="html">
<pre class="prettyprint lang-html"></pre>
</div>
</div>
</body>
</html>

View File

@ -527,6 +527,7 @@
<li><a href="example-option-theme-bootstrap-v4.html">Bootstrap v4.x</a> (<span class="version updated">v2.29.0</span>) <span class="label warning">NOTE</span> <strong>does not</strong> require the uitheme widget!</li> <li><a href="example-option-theme-bootstrap-v4.html">Bootstrap v4.x</a> (<span class="version updated">v2.29.0</span>) <span class="label warning">NOTE</span> <strong>does not</strong> require the uitheme widget!</li>
</ul> </ul>
</li> </li>
<li><span class="label label-info">Beta</span> <a href="example-widget-vertical-group.html">Vertical Group Widget</a> (<span class="version">v2.29.1</span>).</li>
<li><span class="label label-info">Beta</span> <a href="example-widget-view.html">View Widget</a> (<span class="version">v2.24.0</span>; <span class="version updated">v2.26.6</span>).</li> <li><span class="label label-info">Beta</span> <a href="example-widget-view.html">View Widget</a> (<span class="version">v2.24.0</span>; <span class="version updated">v2.26.6</span>).</li>
<li><span class="results">&Dagger;</span> <a href="example-widget-zebra.html">Zebra stripe widget</a>.</li> <li><span class="results">&Dagger;</span> <a href="example-widget-zebra.html">Zebra stripe widget</a>.</li>
</ul> </ul>
@ -2903,7 +2904,7 @@ filter_cellFilter : [ '', 'hidden', '', 'hidden' ]</pre>
Filter widget: Customize the filter widget by adding a select dropdown with content, custom options or custom filter functions (v2.3.6; <span class="version updated">v2.17.0</span>). Filter widget: Customize the filter widget by adding a select dropdown with content, custom options or custom filter functions (v2.3.6; <span class="version updated">v2.17.0</span>).
<div class="collapsible"> <div class="collapsible">
<br> <br>
In <span class="version updated">v2.22.0</span>, a <code>data</code> parameter was added to that long list of parameters.<p></p> In <span class="version updated">v2.22.0</span>, a <a href="example-widget-filter-custom-search.html#how_to_add_custom_filter_types"><code>data</code></a> parameter was added to that long list of parameters.<p></p>
<span class="label alert">*WARNING*</span> In a future update, the filter function parameters will be cleaned up and changed as follows! <span class="label alert">*WARNING*</span> In a future update, the filter function parameters will be cleaned up and changed as follows!
<pre class="prettyprint lang-js">filter_functions : { <pre class="prettyprint lang-js">filter_functions : {
// function(e, n, f, i, $r, c, data) {} &lt;- current parameters // function(e, n, f, i, $r, c, data) {} &lt;- current parameters
@ -6114,7 +6115,7 @@ $.tablesorter.storage( $('#myTable'), 'tablesorter-filters', '' );</pre>
.bind('pagerChange pagerComplete', function(event, options){ .bind('pagerChange pagerComplete', function(event, options){
// options = table.config.pager (pager addon) // options = table.config.pager (pager addon)
// options = table.config (pager widget) - so use options.pager.page below // options = table.config (pager widget) - so use options.pager.page below
// c.totalPages contains the total number of pages // this.totalPages contains the total number of pages (this = table)
$('#display').html( event.type + " event triggered, now on page " + (options.page + 1) ); $('#display').html( event.type + " event triggered, now on page " + (options.page + 1) );
}); });

View File

@ -4,7 +4,7 @@
*/ */
/*! tablesorter (FORK) - updated 09-27-2017 (v2.29.0)*/ /*! tablesorter (FORK) - updated 12-13-2017 (v2.29.1)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -16,7 +16,7 @@
} }
}(function(jQuery) { }(function(jQuery) {
/*! TableSorter (FORK) v2.29.0 *//* /*! TableSorter (FORK) v2.29.1 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -40,7 +40,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.29.0', version : '2.29.1',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -532,8 +532,7 @@
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) { if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
ts.buildCache( c ); ts.buildCache( c );
} }
// jQuery v1.2.6 doesn't have closest() $cell = ts.getClosest( $( this ), '.' + ts.css.header );
$cell = ts.getHeaderCell( $( this ) );
// reference original table headers and find the same cell // reference original table headers and find the same cell
// don't use $headers or IE8 throws an error - see #987 // don't use $headers or IE8 throws an error - see #987
temp = $headers.index( $cell ); temp = $headers.index( $cell );
@ -573,10 +572,15 @@
''; '';
// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) { c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {
var configHeaders, header, column, template, tmp, $th, var configHeaders, header, column, template, tmp,
$elem = $( elem ); $elem = $( elem );
// ignore cell (don't add it to c.$headers) if row has ignoreRow class // ignore cell (don't add it to c.$headers) if row has ignoreRow class
if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; }
// transfer data-column to element if not th/td - #1459
if ( !/(th|td)/i.test( elem.nodeName ) ) {
tmp = ts.getClosest( $elem, 'th, td' );
$elem.attr( 'data-column', tmp.attr( 'data-column' ) );
}
// make sure to get header cell & not column indexed cell // make sure to get header cell & not column indexed cell
configHeaders = ts.getColumnData( c.table, c.headers, index, true ); configHeaders = ts.getColumnData( c.table, c.headers, index, true );
// save original header content // save original header content
@ -599,9 +603,7 @@
if ( c.onRenderHeader ) { if ( c.onRenderHeader ) {
c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); c.onRenderHeader.apply( $elem, [ index, c, c.$table ] );
} }
// data-column stored on th or td only column = parseInt( $elem.attr( 'data-column' ), 10 );
$th = ts.getHeaderCell( $elem );
column = parseInt( $th.attr( 'data-column' ), 10 );
elem.column = column; elem.column = column;
tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder ); tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );
// this may get updated numerous times if there are multiple rows // this may get updated numerous times if there are multiple rows
@ -637,6 +639,7 @@
if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) { if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {
c.sortVars[ indx ] = {}; c.sortVars[ indx ] = {};
} }
// Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td
$temp = c.$headers.filter( '[data-column="' + indx + '"]' ); $temp = c.$headers.filter( '[data-column="' + indx + '"]' );
// target sortable column cells, unless there are none, then use non-sortable cells // target sortable column cells, unless there are none, then use non-sortable cells
// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
@ -1100,6 +1103,15 @@
css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = [ 'ascending', 'descending' ], aria = [ 'ascending', 'descending' ],
updateColumnSort = function($el, index) {
$el
.removeClass( none )
.addClass( css[ index ] )
.attr( 'aria-sort', aria[ index ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ index ] );
},
// find the footer // find the footer
$extras = c.$table $extras = c.$table
.find( 'tfoot tr' ) .find( 'tfoot tr' )
@ -1138,7 +1150,7 @@
var include = true, var include = true,
$el = c.$headers.eq( i ), $el = c.$headers.eq( i ),
col = parseInt( $el.attr( 'data-column' ), 10 ), col = parseInt( $el.attr( 'data-column' ), 10 ),
end = col + c.$headers[ i ].colSpan; end = col + ts.getClosest( $el, 'th, td' )[0].colSpan;
for ( ; col < end; col++ ) { for ( ; col < end; col++ ) {
include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false; include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;
} }
@ -1152,23 +1164,13 @@
if ( $sorted.length ) { if ( $sorted.length ) {
for ( column = 0; column < $sorted.length; column++ ) { for ( column = 0; column < $sorted.length; column++ ) {
if ( !$sorted[ column ].sortDisabled ) { if ( !$sorted[ column ].sortDisabled ) {
$sorted updateColumnSort( $sorted.eq( column ) , list[ indx ][ 1 ] );
.eq( column )
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] )
.attr( 'aria-sort', aria[ list[ indx ][ 1 ] ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ list[ indx ][ 1 ] ] );
} }
} }
// add sorted class to footer & extra headers, if they exist }
if ( $extras.length ) { // add sorted class to footer & extra headers, if they exist
$extras if ( $extras.length ) {
.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ) updateColumnSort( $extras.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ), list[ indx ][ 1 ] );
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] );
}
} }
} }
} }
@ -1179,29 +1181,20 @@
} }
}, },
// This function does NOT return closest if the $el matches the selector
getClosest : function( $el, selector ) { getClosest : function( $el, selector ) {
return $.fn.closest ?
$el.closest( selector ) :
$el.parents( selector ).filter( ':first' );
},
getHeaderCell : function( $el ) {
// jQuery v1.2.6 doesn't have closest() // jQuery v1.2.6 doesn't have closest()
if ( $.fn.closest ) { if ( $.fn.closest ) {
return $el.closest( 'th, td' ); return $el.closest( selector );
} }
return /TH|TD/.test( $el[0].nodeName ) ? return $el.is( selector ) ?
$el : $el :
$el.parents( 'th, td' ).filter( ':first' ); $el.parents( selector ).filter( ':first' );
}, },
// nextSort (optional), lets you disable next sort text // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) { setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) { if ( $header.length ) {
var $th = ts.getHeaderCell( $header ), var column = parseInt( $header.attr( 'data-column' ), 10 ),
// data-column always stored on the th/td
column = parseInt( $th.attr( 'data-column' ), 10 ),
vars = c.sortVars[ column ], vars = c.sortVars[ column ],
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
@ -1569,10 +1562,10 @@
notMultiSort = !event[ c.sortMultiSortKey ], notMultiSort = !event[ c.sortMultiSortKey ],
table = c.table, table = c.table,
len = c.$headers.length, len = c.$headers.length,
// get current column index; *always* stored on th/td th = ts.getClosest( $( cell ), 'th, td' ),
$th = ts.getHeaderCell( $( cell ) ), col = parseInt( th.attr( 'data-column' ), 10 ),
col = parseInt( $th.attr( 'data-column' ), 10 ),
order = c.sortVars[ col ].order; order = c.sortVars[ col ].order;
th = th[0];
// Only call sortStart if sorting is enabled // Only call sortStart if sorting is enabled
c.$table.triggerHandler( 'sortStart', table ); c.$table.triggerHandler( 'sortStart', table );
// get current column sort order // get current column sort order
@ -1607,8 +1600,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -1640,8 +1633,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -2410,7 +2403,7 @@
$cells = ( $headers || c.$headers ), $cells = ( $headers || c.$headers ),
// c.$headerIndexed is not defined initially // c.$headerIndexed is not defined initially
$cell = c.$headerIndexed && c.$headerIndexed[ indx ] || $cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||
$cells.filter( '[data-column="' + indx + '"]:last' ); $cells.find( '[data-column="' + indx + '"]:last' );
if ( typeof obj[ indx ] !== 'undefined' ) { if ( typeof obj[ indx ] !== 'undefined' ) {
return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ]; return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];
} }
@ -4412,6 +4405,7 @@
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) { if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
matches = tsf.types[ffxn]( c, data, vars ); matches = tsf.types[ffxn]( c, data, vars );
if ( matches !== null ) { if ( matches !== null ) {
data.matchedOn = ffxn;
filterMatched = matches; filterMatched = matches;
} }
} }
@ -4459,6 +4453,7 @@
tsf.multipleColumns( c, wo.filter_$anyMatch ) : tsf.multipleColumns( c, wo.filter_$anyMatch ) :
[]; [];
data.$cells = data.$row.children(); data.$cells = data.$row.children();
data.matchedOn = null;
if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) { if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {
data.anyMatch = true; data.anyMatch = true;
data.isMatch = true; data.isMatch = true;
@ -4560,7 +4555,9 @@
// cycle through the different filters // cycle through the different filters
// filters return a boolean or null if nothing matches // filters return a boolean or null if nothing matches
filterMatched = tsf.processTypes( c, data, vars ); filterMatched = tsf.processTypes( c, data, vars );
if ( filterMatched !== null ) { // select with exact match; ignore "and" or "or" within the text; fixes #1486
txt = fxn === true && (data.matchedOn === 'and' || data.matchedOn === 'or');
if ( filterMatched !== null && !txt) {
result = filterMatched; result = filterMatched;
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
@ -5719,7 +5716,10 @@
columns = c.columns - 1, columns = c.columns - 1,
$header = $this.data( 'header' ); $header = $this.data( 'header' );
if ( !$header ) { return; } // see #859 if ( !$header ) { return; } // see #859
if ( !$header.is(':visible') ) { if (
!$header.is(':visible') ||
( !wo.resizable_addLastColumn && ts.resizable.checkVisibleColumns(c, column) )
) {
$this.hide(); $this.hide();
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
$this.css({ $this.css({
@ -5731,6 +5731,16 @@
}); });
}, },
// Fixes #1485
checkVisibleColumns: function( c, column ) {
var i,
len = 0;
for ( i = column + 1; i < c.columns; i++ ) {
len += c.$headerIndexed[i].is( ':visible' ) ? 1 : 0;
}
return len === 0;
},
// prevent text selection while dragging resize bar // prevent text selection while dragging resize bar
toggleTextSelection : function( c, wo, toggle ) { toggleTextSelection : function( c, wo, toggle ) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';

View File

@ -1,4 +1,4 @@
/*! TableSorter (FORK) v2.29.0 *//* /*! TableSorter (FORK) v2.29.1 *//*
* Client-side table sorting with ease! * Client-side table sorting with ease!
* @requires jQuery v1.2.6+ * @requires jQuery v1.2.6+
* *
@ -22,7 +22,7 @@
'use strict'; 'use strict';
var ts = $.tablesorter = { var ts = $.tablesorter = {
version : '2.29.0', version : '2.29.1',
parsers : [], parsers : [],
widgets : [], widgets : [],
@ -514,8 +514,7 @@
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) { if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
ts.buildCache( c ); ts.buildCache( c );
} }
// jQuery v1.2.6 doesn't have closest() $cell = ts.getClosest( $( this ), '.' + ts.css.header );
$cell = ts.getHeaderCell( $( this ) );
// reference original table headers and find the same cell // reference original table headers and find the same cell
// don't use $headers or IE8 throws an error - see #987 // don't use $headers or IE8 throws an error - see #987
temp = $headers.index( $cell ); temp = $headers.index( $cell );
@ -555,10 +554,15 @@
''; '';
// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) { c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {
var configHeaders, header, column, template, tmp, $th, var configHeaders, header, column, template, tmp,
$elem = $( elem ); $elem = $( elem );
// ignore cell (don't add it to c.$headers) if row has ignoreRow class // ignore cell (don't add it to c.$headers) if row has ignoreRow class
if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; }
// transfer data-column to element if not th/td - #1459
if ( !/(th|td)/i.test( elem.nodeName ) ) {
tmp = ts.getClosest( $elem, 'th, td' );
$elem.attr( 'data-column', tmp.attr( 'data-column' ) );
}
// make sure to get header cell & not column indexed cell // make sure to get header cell & not column indexed cell
configHeaders = ts.getColumnData( c.table, c.headers, index, true ); configHeaders = ts.getColumnData( c.table, c.headers, index, true );
// save original header content // save original header content
@ -581,9 +585,7 @@
if ( c.onRenderHeader ) { if ( c.onRenderHeader ) {
c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); c.onRenderHeader.apply( $elem, [ index, c, c.$table ] );
} }
// data-column stored on th or td only column = parseInt( $elem.attr( 'data-column' ), 10 );
$th = ts.getHeaderCell( $elem );
column = parseInt( $th.attr( 'data-column' ), 10 );
elem.column = column; elem.column = column;
tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder ); tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );
// this may get updated numerous times if there are multiple rows // this may get updated numerous times if there are multiple rows
@ -619,6 +621,7 @@
if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) { if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {
c.sortVars[ indx ] = {}; c.sortVars[ indx ] = {};
} }
// Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td
$temp = c.$headers.filter( '[data-column="' + indx + '"]' ); $temp = c.$headers.filter( '[data-column="' + indx + '"]' );
// target sortable column cells, unless there are none, then use non-sortable cells // target sortable column cells, unless there are none, then use non-sortable cells
// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
@ -1082,6 +1085,15 @@
css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = [ 'ascending', 'descending' ], aria = [ 'ascending', 'descending' ],
updateColumnSort = function($el, index) {
$el
.removeClass( none )
.addClass( css[ index ] )
.attr( 'aria-sort', aria[ index ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ index ] );
},
// find the footer // find the footer
$extras = c.$table $extras = c.$table
.find( 'tfoot tr' ) .find( 'tfoot tr' )
@ -1120,7 +1132,7 @@
var include = true, var include = true,
$el = c.$headers.eq( i ), $el = c.$headers.eq( i ),
col = parseInt( $el.attr( 'data-column' ), 10 ), col = parseInt( $el.attr( 'data-column' ), 10 ),
end = col + c.$headers[ i ].colSpan; end = col + ts.getClosest( $el, 'th, td' )[0].colSpan;
for ( ; col < end; col++ ) { for ( ; col < end; col++ ) {
include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false; include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;
} }
@ -1134,23 +1146,13 @@
if ( $sorted.length ) { if ( $sorted.length ) {
for ( column = 0; column < $sorted.length; column++ ) { for ( column = 0; column < $sorted.length; column++ ) {
if ( !$sorted[ column ].sortDisabled ) { if ( !$sorted[ column ].sortDisabled ) {
$sorted updateColumnSort( $sorted.eq( column ) , list[ indx ][ 1 ] );
.eq( column )
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] )
.attr( 'aria-sort', aria[ list[ indx ][ 1 ] ] )
.find( '.' + ts.css.icon )
.removeClass( cssIcon[ 2 ] )
.addClass( cssIcon[ list[ indx ][ 1 ] ] );
} }
} }
// add sorted class to footer & extra headers, if they exist }
if ( $extras.length ) { // add sorted class to footer & extra headers, if they exist
$extras if ( $extras.length ) {
.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ) updateColumnSort( $extras.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ), list[ indx ][ 1 ] );
.removeClass( none )
.addClass( css[ list[ indx ][ 1 ] ] );
}
} }
} }
} }
@ -1161,29 +1163,20 @@
} }
}, },
// This function does NOT return closest if the $el matches the selector
getClosest : function( $el, selector ) { getClosest : function( $el, selector ) {
return $.fn.closest ?
$el.closest( selector ) :
$el.parents( selector ).filter( ':first' );
},
getHeaderCell : function( $el ) {
// jQuery v1.2.6 doesn't have closest() // jQuery v1.2.6 doesn't have closest()
if ( $.fn.closest ) { if ( $.fn.closest ) {
return $el.closest( 'th, td' ); return $el.closest( selector );
} }
return /TH|TD/.test( $el[0].nodeName ) ? return $el.is( selector ) ?
$el : $el :
$el.parents( 'th, td' ).filter( ':first' ); $el.parents( selector ).filter( ':first' );
}, },
// nextSort (optional), lets you disable next sort text // nextSort (optional), lets you disable next sort text
setColumnAriaLabel : function( c, $header, nextSort ) { setColumnAriaLabel : function( c, $header, nextSort ) {
if ( $header.length ) { if ( $header.length ) {
var $th = ts.getHeaderCell( $header ), var column = parseInt( $header.attr( 'data-column' ), 10 ),
// data-column always stored on the th/td
column = parseInt( $th.attr( 'data-column' ), 10 ),
vars = c.sortVars[ column ], vars = c.sortVars[ column ],
tmp = $header.hasClass( ts.css.sortAsc ) ? tmp = $header.hasClass( ts.css.sortAsc ) ?
'sortAsc' : 'sortAsc' :
@ -1551,10 +1544,10 @@
notMultiSort = !event[ c.sortMultiSortKey ], notMultiSort = !event[ c.sortMultiSortKey ],
table = c.table, table = c.table,
len = c.$headers.length, len = c.$headers.length,
// get current column index; *always* stored on th/td th = ts.getClosest( $( cell ), 'th, td' ),
$th = ts.getHeaderCell( $( cell ) ), col = parseInt( th.attr( 'data-column' ), 10 ),
col = parseInt( $th.attr( 'data-column' ), 10 ),
order = c.sortVars[ col ].order; order = c.sortVars[ col ].order;
th = th[0];
// Only call sortStart if sorting is enabled // Only call sortStart if sorting is enabled
c.$table.triggerHandler( 'sortStart', table ); c.$table.triggerHandler( 'sortStart', table );
// get current column sort order // get current column sort order
@ -1589,8 +1582,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -1622,8 +1615,8 @@
if ( dir < 2 ) { if ( dir < 2 ) {
c.sortList[ c.sortList.length ] = [ col, dir ]; c.sortList[ c.sortList.length ] = [ col, dir ];
// add other columns if header spans across multiple // add other columns if header spans across multiple
if ( cell.colSpan > 1 ) { if ( th.colSpan > 1 ) {
for ( indx = 1; indx < cell.colSpan; indx++ ) { for ( indx = 1; indx < th.colSpan; indx++ ) {
c.sortList[ c.sortList.length ] = [ col + indx, dir ]; c.sortList[ c.sortList.length ] = [ col + indx, dir ];
// update count on columns in colSpan // update count on columns in colSpan
c.sortVars[ col + indx ].count = $.inArray( dir, order ); c.sortVars[ col + indx ].count = $.inArray( dir, order );
@ -2392,7 +2385,7 @@
$cells = ( $headers || c.$headers ), $cells = ( $headers || c.$headers ),
// c.$headerIndexed is not defined initially // c.$headerIndexed is not defined initially
$cell = c.$headerIndexed && c.$headerIndexed[ indx ] || $cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||
$cells.filter( '[data-column="' + indx + '"]:last' ); $cells.find( '[data-column="' + indx + '"]:last' );
if ( typeof obj[ indx ] !== 'undefined' ) { if ( typeof obj[ indx ] !== 'undefined' ) {
return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ]; return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];
} }

View File

@ -4,7 +4,7 @@
*/ */
/*! tablesorter (FORK) - updated 09-27-2017 (v2.29.0)*/ /*! tablesorter (FORK) - updated 12-13-2017 (v2.29.1)*/
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */ /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
(function(factory) { (function(factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -1525,6 +1525,7 @@
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) { if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
matches = tsf.types[ffxn]( c, data, vars ); matches = tsf.types[ffxn]( c, data, vars );
if ( matches !== null ) { if ( matches !== null ) {
data.matchedOn = ffxn;
filterMatched = matches; filterMatched = matches;
} }
} }
@ -1572,6 +1573,7 @@
tsf.multipleColumns( c, wo.filter_$anyMatch ) : tsf.multipleColumns( c, wo.filter_$anyMatch ) :
[]; [];
data.$cells = data.$row.children(); data.$cells = data.$row.children();
data.matchedOn = null;
if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) { if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {
data.anyMatch = true; data.anyMatch = true;
data.isMatch = true; data.isMatch = true;
@ -1673,7 +1675,9 @@
// cycle through the different filters // cycle through the different filters
// filters return a boolean or null if nothing matches // filters return a boolean or null if nothing matches
filterMatched = tsf.processTypes( c, data, vars ); filterMatched = tsf.processTypes( c, data, vars );
if ( filterMatched !== null ) { // select with exact match; ignore "and" or "or" within the text; fixes #1486
txt = fxn === true && (data.matchedOn === 'and' || data.matchedOn === 'or');
if ( filterMatched !== null && !txt) {
result = filterMatched; result = filterMatched;
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {
@ -2832,7 +2836,10 @@
columns = c.columns - 1, columns = c.columns - 1,
$header = $this.data( 'header' ); $header = $this.data( 'header' );
if ( !$header ) { return; } // see #859 if ( !$header ) { return; } // see #859
if ( !$header.is(':visible') ) { if (
!$header.is(':visible') ||
( !wo.resizable_addLastColumn && ts.resizable.checkVisibleColumns(c, column) )
) {
$this.hide(); $this.hide();
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
$this.css({ $this.css({
@ -2844,6 +2851,16 @@
}); });
}, },
// Fixes #1485
checkVisibleColumns: function( c, column ) {
var i,
len = 0;
for ( i = column + 1; i < c.columns; i++ ) {
len += c.$headerIndexed[i].is( ':visible' ) ? 1 : 0;
}
return len === 0;
},
// prevent text selection while dragging resize bar // prevent text selection while dragging resize bar
toggleTextSelection : function( c, wo, toggle ) { toggleTextSelection : function( c, wo, toggle ) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';

View File

@ -1115,6 +1115,7 @@
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) { if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
matches = tsf.types[ffxn]( c, data, vars ); matches = tsf.types[ffxn]( c, data, vars );
if ( matches !== null ) { if ( matches !== null ) {
data.matchedOn = ffxn;
filterMatched = matches; filterMatched = matches;
} }
} }
@ -1162,6 +1163,7 @@
tsf.multipleColumns( c, wo.filter_$anyMatch ) : tsf.multipleColumns( c, wo.filter_$anyMatch ) :
[]; [];
data.$cells = data.$row.children(); data.$cells = data.$row.children();
data.matchedOn = null;
if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) { if ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {
data.anyMatch = true; data.anyMatch = true;
data.isMatch = true; data.isMatch = true;
@ -1263,7 +1265,9 @@
// cycle through the different filters // cycle through the different filters
// filters return a boolean or null if nothing matches // filters return a boolean or null if nothing matches
filterMatched = tsf.processTypes( c, data, vars ); filterMatched = tsf.processTypes( c, data, vars );
if ( filterMatched !== null ) { // select with exact match; ignore "and" or "or" within the text; fixes #1486
txt = fxn === true && (data.matchedOn === 'and' || data.matchedOn === 'or');
if ( filterMatched !== null && !txt) {
result = filterMatched; result = filterMatched;
// Look for match, and add child row data for matching // Look for match, and add child row data for matching
} else { } else {

View File

@ -175,7 +175,10 @@
columns = c.columns - 1, columns = c.columns - 1,
$header = $this.data( 'header' ); $header = $this.data( 'header' );
if ( !$header ) { return; } // see #859 if ( !$header ) { return; } // see #859
if ( !$header.is(':visible') ) { if (
!$header.is(':visible') ||
( !wo.resizable_addLastColumn && ts.resizable.checkVisibleColumns(c, column) )
) {
$this.hide(); $this.hide();
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
$this.css({ $this.css({
@ -187,6 +190,16 @@
}); });
}, },
// Fixes #1485
checkVisibleColumns: function( c, column ) {
var i,
len = 0;
for ( i = column + 1; i < c.columns; i++ ) {
len += c.$headerIndexed[i].is( ':visible' ) ? 1 : 0;
}
return len === 0;
},
// prevent text selection while dragging resize bar // prevent text selection while dragging resize bar
toggleTextSelection : function( c, wo, toggle ) { toggleTextSelection : function( c, wo, toggle ) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';

View File

@ -289,8 +289,10 @@
}); });
// resize/update events - filterEnd fires after "tablesorter-initialized" and "updateComplete" // resize/update events - filterEnd fires after "tablesorter-initialized" and "updateComplete"
events = ( ( ts.hasWidget( c.table, 'filter' ) ? 'filterEnd' : 'tablesorter-initialized updateComplete' ) + tmp = ts.hasWidget( c.table, 'filter' ) ?
' sortEnd pagerComplete columnUpdate ' ).split( ' ' ).join( namespace + ' ' ); 'filterEnd filterInit' :
'tablesorter-initialized updateComplete';
events = ( tmp + ' sortEnd pagerComplete columnUpdate ' ).split( ' ' ).join( namespace + ' ' );
$table $table
.off( namespace ) .off( namespace )

View File

@ -0,0 +1,137 @@
/*! Widget: vertical-group (BETA) - updated 12/13/2017 (v2.29.1) */
/* Requires tablesorter and jQuery
* Originally by @aavmurphy (Andrew Murphy)
* Adapted for tablesorter by Rob Garrison - see #1469 & #1470
*
* This widget is licensed under the same terms at mottie/tablesorter itself, i.e. free to use
*/
/* jshint browser:true, jquery:true, unused:false */
/* global jQuery:false */
;(function($){
'use strict';
var ts = $.tablesorter,
tscss = ts.css;
$.extend( ts.css, {
verticalGroupHeader: 'tablesorter-vertical-group',
verticalGroupHide: 'tablesorter-vertical-group-hide',
verticalGroupShow: 'tablesorter-vertical-group-show'
});
ts.addWidget({
id: 'vertical-group',
priority: 99,
init: verticalGroup,
format: verticalGroup
});
function cleanUp( el ) {
el.removeClass(tscss.verticalGroupHide + ' ' + tscss.verticalGroupShow);
}
function setZebra( wo, $cell, indx ) {
var $row = $cell.parent();
$row
.removeClass( wo.zebra[ (indx + 1) % 2 ] )
.addClass( wo.zebra[ indx % 2] );
}
function verticalGroup( table, c, wo, init ) {
// -------------------------------------------------------------------------
// loop thru the header row,
// - look for .vertical-group
//
// loop thru the rows
//
// set ALWAYS_SHOW = FALSE
// loop thru the 1st 4 columns
// if this cell does not exist, skip to next row
// if ALWAYS_SHOW, then this cell is SHOW
// else if this column does not have '.vertical-group', then this cell is SHOW
// else if this cell is NOT the same as the cell-above, then this cell is SHOW
// else this cell is HIDE
// if this cell is SHOW, set ALWAYS_SHOW
// if this cell is SHOW,
// then
// set the cell class to .vertical_group_show
// else
// set the cell class to vertical_group_show
//
// TO DO add/remove classes so as not to clobber other existing classes
// TO DO add classes
//
// .vertical-group-show { background-color: white !important; }
// .vertical-group-hide { visibility: hidden; border-top: white !important;background-color: white !important; }
//
// this is all because of stripped tables
// - background-colour show be the table's background colour (or the first row's)
// - the border-color needs to be the same
//
// ------------------------------------------------------------------------------------------------
var tmp,
zebra_index = -1, // increments at start of loop
rows = table.tBodies[0].rows,
header = table.tHead.rows,
has_zebra = ts.hasWidget( table, 'zebra'),
is_vertical_group_col = [],
last_row = [];
if ( wo.vertical_group_lock ) {
return;
}
wo.vertical_group_lock = true;
is_vertical_group_col = $.map( c.$headerIndexed, function( el ) {
return el.hasClass( tscss.verticalGroupHeader ) ? 1 : '';
});
if ( is_vertical_group_col.join('') === '' ) {
cleanUp( $(rows).find( '.' + tscss.verticalGroupHide + ',.' + tscss.verticalGroupShow ) );
wo.vertical_group_lock = false;
return;
}
for (var i = 0; i < rows.length; i++) {
var always_show_cell = false;
for (var j = 0; j < c.columns; j++ ) {
if ( !is_vertical_group_col[ j ] || !rows[ i ].cells[ j ] ) {
zebra_index++;
continue;
}
var $cell = $( rows[ i ].cells[ j ] ),
// only group if column is sorted
isSorted = ts.isValueInArray( j, c.sortList ), // returns equivalent of an indexOf value
cell_data = $cell.html();
if ( isSorted < 0 ) {
cleanUp( $cell );
} else if ( !always_show_cell && cell_data === last_row[j] ) {
if ( !$cell.hasClass(tscss.verticalGroupHide) ) {
$cell.addClass( tscss.verticalGroupHide );
}
if ( has_zebra ) {
setZebra( wo, $cell, zebra_index );
}
$cell.removeClass( tscss.verticalGroupShow );
} else if (isSorted === 0) {
// only show cells from the first sorted column
always_show_cell = true; // show
if ( !$cell.hasClass( tscss.verticalGroupShow ) ) {
$cell.addClass( tscss.verticalGroupShow );
}
$cell.removeClass( tscss.verticalGroupHide );
if ( has_zebra ) {
// only adjust striping based on the first sorted column
setZebra( wo, $cell, isSorted ? zebra_index : ++zebra_index );
}
}
last_row[j] = cell_data;
}
}
wo.vertical_group_lock = false;
}
})(jQuery);

View File

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

View File

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