2015-02-13 04:13:45 +00:00
/ * !
* tablesorter ( FORK ) pager plugin
2015-10-04 14:26:07 +00:00
* updated 10 / 4 / 2015 ( v2 . 23.5 )
2015-02-13 04:13:45 +00:00
* /
2015-10-31 15:08:21 +00:00
/*jshint browser:true, jquery:true, unused:false */
! function ( a ) { "use strict" ; /*jshint supernew:true */
var b = a . tablesorter ; a . extend ( { tablesorterPager : new function ( ) { this . defaults = {
// target the pager markup
container : null ,
// use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}&{filterList:fcol}"
// where {page} is replaced by the page number, {size} is replaced by the number of records to show,
// {sortList:col} adds the sortList to the url into a "col" array, and {filterList:fcol} adds
// the filterList to the url into an "fcol" array.
// So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url
// and a filterList = [[2,Blue],[3,13]] becomes "&fcol[2]=Blue&fcol[3]=13" in the url
ajaxUrl : null ,
// modify the url after all processing has been applied
customAjaxUrl : function ( a , b ) { return b } ,
// ajax error callback from $.tablesorter.showError function
// ajaxError: function( config, xhr, settings, exception ){ return exception; };
// returning false will abort the error message
ajaxError : null ,
// modify the $.ajax object to allow complete control over your ajax requests
ajaxObject : { dataType : "json" } ,
// set this to false if you want to block ajax loading on init
processAjaxOnInit : ! 0 ,
// process ajax so that the following information is returned:
// [ total_rows (number), rows (array of arrays), headers (array; optional) ]
// example:
// [
// 100, // total rows
// [
// [ "row1cell1", "row1cell2", ... "row1cellN" ],
// [ "row2cell1", "row2cell2", ... "row2cellN" ],
// ...
// [ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
// ],
// [ "header1", "header2", ... "headerN" ] // optional
// ]
ajaxProcessing : function ( a ) { return [ 0 , [ ] , null ] } ,
// output default: '{page}/{totalPages}'
// possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
output : "{startRow} to {endRow} of {totalRows} rows" , // '{page}/{totalPages}'
// apply disabled classname to the pager arrows when the rows at either extreme is visible
updateArrows : ! 0 ,
// starting page of the pager (zero based index)
page : 0 ,
// reset pager after filtering; set to desired page #
// set to false to not change page at filter start
pageReset : 0 ,
// Number of visible rows
size : 10 ,
// Number of options to include in the pager number selector
maxOptionSize : 20 ,
// Save pager page & size if the storage script is loaded (requires $.tablesorter.storage in jquery.tablesorter.widgets.js)
savePages : ! 0 ,
// defines custom storage key
storageKey : "tablesorter-pager" ,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight : ! 1 ,
// count child rows towards the set page size? (set true if it is a visible table row within the pager)
// if true, child row(s) may not appear to be attached to its parent row, may be split across pages or
// may distort the table if rowspan or cellspans are included.
countChildRows : ! 1 ,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows : ! 1 , // removing rows in larger tables speeds up the sort
// css class names of pager arrows
cssFirst : ".first" , // go to first page arrow
cssPrev : ".prev" , // previous page arrow
cssNext : ".next" , // next page arrow
cssLast : ".last" , // go to last page arrow
cssGoto : ".gotoPage" , // go to page selector - select dropdown that sets the current page
cssPageDisplay : ".pagedisplay" , // location of where the "output" is displayed
cssPageSize : ".pagesize" , // page size selector - select dropdown that sets the "size" option
cssErrorRow : "tablesorter-errorRow" , // error information row
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled : "disabled" , // Note there is no period "." in front of this class name
// stuff not set by the user
totalRows : 0 , totalPages : 0 , filteredRows : 0 , filteredPages : 0 , ajaxCounter : 0 , currentFilters : [ ] , startRow : 0 , endRow : 0 , $size : null , last : { } } ; var c = "filterInit filterStart filterEnd sortEnd disablePager enablePager destroyPager updateComplete pageSize pageSet pageAndSize pagerUpdate refreshComplete " , d = this ,
// hide arrows at extremes
e = function ( a , b ) { var c = "addClass" , d = "removeClass" , e = a . cssDisabled , f = ! ! b , g = f || 0 === a . page , h = Math . min ( a . totalPages , a . filteredPages ) , i = f || a . page === h - 1 || 0 === h ; a . updateArrows && ( a . $container . find ( a . cssFirst + "," + a . cssPrev ) [ g ? c : d ] ( e ) . attr ( "aria-disabled" , g ) , a . $container . find ( a . cssNext + "," + a . cssLast ) [ i ? c : d ] ( e ) . attr ( "aria-disabled" , i ) ) } , f = function ( a , c ) { var d , e , f , g = a . config , h = g . $table . hasClass ( "hasFilters" ) ; if ( h && ! c . ajaxUrl ) if ( b . isEmptyObject ( g . cache ) )
// delayInit: true so nothing is in the cache
c . filteredRows = c . totalRows = g . $tbodies . eq ( 0 ) . children ( "tr" ) . not ( c . countChildRows ? "" : "." + g . cssChildRow ) . length ; else for ( c . filteredRows = 0 , d = g . cache [ 0 ] . normalized , f = d . length , e = 0 ; f > e ; e ++ ) c . filteredRows += c . regexRows . test ( d [ e ] [ g . columns ] . $row [ 0 ] . className ) ? 0 : 1 ; else h || ( c . filteredRows = c . totalRows ) } , g = function ( c , d , g ) { if ( ! d . initializing ) { var j , k , l , m , n , o , p = c . config , q = p . namespace + "pager" , r = t ( d , d . size , "get" ) ; if ( // don't allow dividing by zero
d . countChildRows && k . push ( p . cssChildRow ) , d . totalPages = Math . ceil ( d . totalRows / r ) , // needed for "pageSize" method
p . totalRows = d . totalRows , u ( d ) , f ( c , d ) , p . filteredRows = d . filteredRows , d . filteredPages = Math . ceil ( d . filteredRows / r ) || 0 , Math . min ( d . totalPages , d . filteredPages ) >= 0 ) { if ( k = d . size * d . page > d . filteredRows && g , d . page = k ? d . pageReset || 0 : d . page , d . startRow = k ? d . size * d . page + 1 : 0 === d . filteredRows ? 0 : d . size * d . page + 1 , d . endRow = Math . min ( d . filteredRows , d . totalRows , d . size * ( d . page + 1 ) ) , l = d . $container . find ( d . cssPageDisplay ) , j = ( d . ajaxData && d . ajaxData . output ? d . ajaxData . output || d . output : d . output ) . replace ( /\{page([\-+]\d+)?\}/gi , function ( a , b ) { return d . totalPages ? d . page + ( b ? parseInt ( b , 10 ) : 1 ) : 0 } ) . replace ( /\{\w+(\s*:\s*\w+)?\}/gi , function ( a ) { var b , c , e = a . replace ( /[{}\s]/g , "" ) , f = e . split ( ":" ) , g = d . ajaxData , h = /(rows?|pages?)$/i . test ( e ) ? 0 : "" ; return /(startRow|page)/ . test ( f [ 0 ] ) && "input" === f [ 1 ] ? ( b = ( "" + ( "page" === f [ 0 ] ? d . totalPages : d . totalRows ) ) . length , c = "page" === f [ 0 ] ? d . page + 1 : d . startRow , '<input type="text" class="ts-' + f [ 0 ] + '" style="max-width:' + b + 'em" value="' + c + '"/>' ) : f . length > 1 && g && g [ f [ 0 ] ] ? g [ f [ 0 ] ] [ f [ 1 ] ] : d [ e ] || ( g ? g [ e ] : h ) || h } ) , d . $goto . length ) { for ( k = "" , o = h ( d ) , n = o . length , m = 0 ; n > m ; m ++ ) k += '<option value="' + o [ m ] + '">' + o [ m ] + "</option>" ;
// innerHTML doesn't work in IE9 - http://support2.microsoft.com/kb/276228
d . $goto . html ( k ) . val ( d . page + 1 ) } l . length && ( l [ "INPUT" === l [ 0 ] . nodeName ? "val" : "html" ] ( j ) ,
// rebind startRow/page inputs
l . find ( ".ts-startRow, .ts-page" ) . unbind ( "change" + q ) . bind ( "change" + q , function ( ) { var b = a ( this ) . val ( ) , c = a ( this ) . hasClass ( "ts-startRow" ) ? Math . floor ( b / d . size ) + 1 : b ; p . $table . trigger ( "pageSet" + q , [ c ] ) } ) ) } e ( d ) , i ( c , d ) , d . initialized && g !== ! 1 && ( p . debug && console . log ( "Pager: Triggering pagerComplete" ) , p . $table . trigger ( "pagerComplete" , d ) ,
// save pager info to storage
d . savePages && b . storage && b . storage ( c , d . storageKey , { page : d . page , size : d . size } ) ) } } , h = function ( b ) {
// Filter the options page number link array if it's larger than 'maxOptionSize'
// as large page set links will slow the browser on large dom inserts
var c , d , e , f , g , h , i = Math . min ( b . totalPages , b . filteredPages ) || 1 ,
// make skip set size multiples of 5
j = 5 * Math . ceil ( i / b . maxOptionSize / 5 ) , k = i > b . maxOptionSize , l = b . page + 1 , m = j , n = i - j , o = [ 1 ] ,
// construct default options pages array
p = k ? j : 1 ; for ( c = p ; i >= c ; ) o . push ( c ) , c += k ? j : 1 ; if ( o . push ( i ) , k ) {
// construct an array to get a focus set around the current page
for ( e = [ ] , d = Math . max ( Math . floor ( b . maxOptionSize / j ) - 1 , 5 ) , m = l - d , 1 > m && ( m = 1 ) , n = l + d , n > i && ( n = i ) , c = m ; n >= c ; c ++ ) e . push ( c ) ;
// keep unique values
o = a . grep ( o , function ( b , c ) { return a . inArray ( b , o ) === c } ) , g = o . length , h = e . length ,
// make sure at all option_pages aren't replaced
g - h > j / 2 && g + h > b . maxOptionSize && ( f = Math . floor ( g / 2 ) - Math . floor ( h / 2 ) , Array . prototype . splice . apply ( o , [ f , h ] ) ) , o = o . concat ( e ) }
// keep unique values again
return o = a . grep ( o , function ( b , c ) { return a . inArray ( b , o ) === c } ) . sort ( function ( a , b ) { return a - b } ) } , i = function ( b , c ) { var d , e , f = b . config , g = f . $tbodies . eq ( 0 ) ; g . find ( "tr.pagerSavedHeightSpacer" ) . remove ( ) , c . fixedHeight && ! c . isDisabled && ( e = a . data ( b , "pagerSavedHeight" ) , e && ( d = e - g . height ( ) , d > 5 && a . data ( b , "pagerLastSize" ) === c . size && g . children ( "tr:visible" ) . length < c . size && g . append ( '<tr class="pagerSavedHeightSpacer ' + f . selectorRemove . slice ( 1 ) + '" style="height:' + d + 'px;"></tr>' ) ) ) } , j = function ( b , c ) { var d , e = b . config , f = e . $tbodies . eq ( 0 ) ; f . find ( "tr.pagerSavedHeightSpacer" ) . remove ( ) , f . children ( "tr:visible" ) . length || f . append ( '<tr class="pagerSavedHeightSpacer ' + e . selectorRemove . slice ( 1 ) + '"><td> </td></tr>' ) , d = f . children ( "tr" ) . eq ( 0 ) . height ( ) * c . size , a . data ( b , "pagerSavedHeight" , d ) , i ( b , c ) , a . data ( b , "pagerLastSize" , c . size ) } , k = function ( a , c ) { if ( ! c . ajaxUrl ) { var d , e = 0 , f = a . config , g = f . $tbodies . eq ( 0 ) . children ( "tr" ) , h = g . length , i = c . page * c . size , j = i + c . size , k = f . widgetOptions && f . widgetOptions . filter _filteredRow || "filtered" , l = 0 , // for cache indexing
m = 0 ; for ( // size counter
c . cacheIndex = [ ] , d = 0 ; h > d ; d ++ ) g [ d ] . className . match ( k ) || ( m === i && g [ d ] . className . match ( f . cssChildRow ) ?
// hide child rows @ start of pager (if already visible)
g [ d ] . style . display = "none" : ( g [ d ] . style . display = m >= i && j > m ? "" : "none" , l !== m && m >= i && j > m && ( c . cacheIndex . push ( d ) , l = m ) , m += g [ d ] . className . match ( f . cssChildRow + "|" + f . selectorRemove . slice ( 1 ) ) && ! c . countChildRows ? 0 : 1 , m === j && "none" !== g [ d ] . style . display && g [ d ] . className . match ( b . css . cssHasChild ) && ( e = d ) ) ) ;
// add any attached child rows to last row of pager. Fixes part of issue #396
if ( e > 0 && g [ e ] . className . match ( b . css . cssHasChild ) ) for ( ; ++ e < h && g [ e ] . className . match ( f . cssChildRow ) ; ) g [ e ] . style . display = "" } } , l = function ( b , c ) { c . size = t ( c , c . $size . val ( ) , "get" ) , c . $size . val ( t ( c , c . size , "set" ) ) , a . data ( b , "pagerLastSize" , c . size ) , e ( c ) , c . removeRows || ( k ( b , c ) , a ( b ) . bind ( "sortEnd filterEnd " . split ( " " ) . join ( b . config . namespace + "pager " ) , function ( ) { k ( b , c ) } ) ) } , m = function ( c , d , e , f , h , i ) {
// process data
if ( "function" == typeof e . ajaxProcessing ) {
// ajaxProcessing result: [ total, rows, headers ]
var j , k , l , m , n , o , p , q , r , s , u , v , w , x , y = d . config , z = y . $table , A = "" , B = e . ajaxProcessing ( c , d , f ) || [ 0 , [ ] ] , C = z . find ( "thead th" ) . length ; if (
// Clean up any previous error.
b . showError ( d ) , i ) y . debug && console . error ( "Pager: >> Ajax Error" , f , h , i ) , b . showError ( d , f , h , i ) , y . $tbodies . eq ( 0 ) . children ( "tr" ) . detach ( ) , e . totalRows = 0 ; else { if (
// process ajax object
a . isArray ( B ) ? ( l = isNaN ( B [ 0 ] ) && ! isNaN ( B [ 1 ] ) , w = B [ l ? 1 : 0 ] , e . totalRows = isNaN ( w ) ? e . totalRows || 0 : w , y . totalRows = y . filteredRows = e . filteredRows = e . totalRows , u = 0 === e . totalRows ? [ ] : B [ l ? 0 : 1 ] || [ ] , s = B [ 2 ] ) : ( e . ajaxData = B , y . totalRows = e . totalRows = B . total , y . filteredRows = e . filteredRows = "undefined" != typeof B . filteredRows ? B . filteredRows : B . total , s = B . headers , u = B . rows || [ ] ) , v = u && u . length , u instanceof jQuery ) e . processAjaxOnInit && (
// append jQuery object
y . $tbodies . eq ( 0 ) . empty ( ) , y . $tbodies . eq ( 0 ) . append ( u ) ) ; else if ( v ) {
// build table from array
for ( j = 0 ; v > j ; j ++ ) { for ( A += "<tr>" , k = 0 ; k < u [ j ] . length ; k ++ )
// build tbody cells; watch for data containing HTML markup - see #434
A += /^\s*<td/ . test ( u [ j ] [ k ] ) ? a . trim ( u [ j ] [ k ] ) : "<td>" + u [ j ] [ k ] + "</td>" ; A += "</tr>" }
// add rows to first tbody
e . processAjaxOnInit && y . $tbodies . eq ( 0 ) . html ( A ) } else
// nothing returned by ajax, empty out the table; see #1032
y . $tbodies . eq ( 0 ) . empty ( ) ;
// only add new header text if the length matches
if ( e . processAjaxOnInit = ! 0 , s && s . length === C ) for ( m = z . hasClass ( "hasStickyHeaders" ) , o = m ? y . widgetOptions . $sticky . children ( "thead:first" ) . children ( "tr" ) . children ( ) : "" , n = z . find ( "tfoot tr:first" ) . children ( ) , p = y . $headers . filter ( "th " ) , x = p . length , k = 0 ; x > k ; k ++ ) q = p . eq ( k ) , q . find ( "." + b . css . icon ) . length ? ( r = q . find ( "." + b . css . icon ) . clone ( ! 0 ) , q . find ( ".tablesorter-header-inner" ) . html ( s [ k ] ) . append ( r ) , m && o . length && ( r = o . eq ( k ) . find ( "." + b . css . icon ) . clone ( ! 0 ) , o . eq ( k ) . find ( ".tablesorter-header-inner" ) . html ( s [ k ] ) . append ( r ) ) ) : ( q . find ( ".tablesorter-header-inner" ) . html ( s [ k ] ) , m && o . length && o . eq ( k ) . find ( ".tablesorter-header-inner" ) . html ( s [ k ] ) ) , n . eq ( k ) . html ( s [ k ] ) } y . showProcessing && b . isProcessing ( d ) ,
// make sure last pager settings are saved, prevents multiple server side calls with
// the same parameters
e . totalPages = Math . ceil ( e . totalRows / t ( e , e . size , "get" ) ) , e . last . totalRows = e . totalRows , e . last . currentFilters = e . currentFilters , e . last . sortList = ( y . sortList || [ ] ) . join ( "," ) , g ( d , e , ! 1 ) ,
// tablesorter core updateCache (not pager)
b . updateCache ( y , function ( ) { e . initialized &&
// apply widgets after table has rendered & after a delay to prevent
// multiple applyWidget blocking code from blocking this trigger
setTimeout ( function ( ) { y . debug && console . log ( "Pager: Triggering pagerChange" ) , z . trigger ( "pagerChange" , e ) , b . applyWidget ( d ) , g ( d , e , ! 0 ) } , 0 ) } ) } e . initialized || ( e . initialized = ! 0 , e . initializing = ! 1 , d . config . debug && console . log ( "Pager: Triggering pagerInitialized" ) , a ( d ) . trigger ( "pagerInitialized" , e ) , b . applyWidget ( d ) , g ( d , e ) ) } , n = function ( c , d ) { var e , f = o ( c , d ) , g = a ( document ) , h = c . config , i = h . namespace + "pager" ; "" !== f && ( h . showProcessing && b . isProcessing ( c , ! 0 ) , g . bind ( "ajaxError" + i , function ( a , b , e , f ) { m ( null , c , d , b , e , f ) , g . unbind ( "ajaxError" + i ) } ) , e = ++ d . ajaxCounter , d . last . ajaxUrl = f , d . ajaxObject . url = f , d . ajaxObject . success = function ( a , b , f ) { e < d . ajaxCounter || ( m ( a , c , d , f ) , g . unbind ( "ajaxError" + i ) , "function" == typeof d . oldAjaxSuccess && d . oldAjaxSuccess ( a ) ) } , h . debug && console . log ( "Pager: Ajax initialized" , d . ajaxObject ) , a . ajax ( d . ajaxObject ) ) } , o = function ( b , c ) { var d , e , f = b . config , g = c . ajaxUrl ? c . ajaxUrl . replace ( /\{page([\-+]\d+)?\}/ , function ( a , b ) { return c . page + ( b ? parseInt ( b , 10 ) : 0 ) } ) . replace ( /\{size\}/g , c . size ) : "" , h = f . sortList , i = c . currentFilters || a ( b ) . data ( "lastSearch" ) || [ ] , j = g . match ( /\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/ ) , k = g . match ( /\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/ ) , l = [ ] ; if ( j ) { for ( j = j [ 1 ] , e = h . length , d = 0 ; e > d ; d ++ ) l . push ( j + "[" + h [ d ] [ 0 ] + "]=" + h [ d ] [ 1 ] ) ;
// if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
g = g . replace ( /\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/g , l . length ? l . join ( "&" ) : j ) , l = [ ] } if ( k ) { for ( k = k [ 1 ] , e = i . length , d = 0 ; e > d ; d ++ ) i [ d ] && l . push ( k + "[" + d + "]=" + encodeURIComponent ( i [ d ] ) ) ;
// if the arry is empty, just add the fcol parameter... "&{filterList:fcol}" becomes "&fcol"
g = g . replace ( /\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g , l . length ? l . join ( "&" ) : k ) , c . currentFilters = i } return "function" == typeof c . customAjaxUrl && ( g = c . customAjaxUrl ( b , g ) ) , f . debug && console . log ( "Pager: Ajax url = " + g ) , g } , p = function ( c , d , e ) { var f , h , i , j , l = a ( c ) , m = c . config , n = m . $table . hasClass ( "hasFilters" ) , o = d && d . length || 0 , // rows may be undefined
p = e . page * e . size , q = e . size ; if ( 1 > o )
// empty table, abort!
return void ( m . debug && console . warn ( "Pager: >> No rows for pager to render" ) ) ; if ( e . page >= e . totalPages &&
// lets not render the table more than once
x ( c , e ) , e . cacheIndex = [ ] , e . isDisabled = ! 1 , // needed because sorting will change the page and re-enable the pager
e . initialized && ( m . debug && console . log ( "Pager: Triggering pagerChange" ) , l . trigger ( "pagerChange" , e ) ) , e . removeRows ) { for ( b . clearTableBody ( c ) , f = b . processTbody ( c , m . $tbodies . eq ( 0 ) , ! 0 ) ,
// not filtered, start from the calculated starting point (s)
// if filtered, start from zero
h = n ? 0 : p , i = n ? 0 : p , j = 0 ; q > j && h < d . length ; ) n && /filtered/ . test ( d [ h ] [ 0 ] . className ) || ( i ++ , i > p && q >= j && ( j ++ , e . cacheIndex . push ( h ) , f . append ( d [ h ] ) ) ) , h ++ ; b . processTbody ( c , f , ! 1 ) } else k ( c , e ) ; g ( c , e ) , c . isUpdating && ( m . debug && console . log ( "Pager: Triggering updateComplete" ) , l . trigger ( "updateComplete" , [ c , ! 0 ] ) ) } , q = function ( c , d ) { var f , g , h ; for ( d . ajax ? e ( d , ! 0 ) : ( a . data ( c , "pagerLastPage" , d . page ) , a . data ( c , "pagerLastSize" , d . size ) , d . page = 0 , d . size = d . totalRows , d . totalPages = 1 , a ( c ) . addClass ( "pagerDisabled" ) . removeAttr ( "aria-describedby" ) . find ( "tr.pagerSavedHeightSpacer" ) . remove ( ) , p ( c , c . config . rowsCopy , d ) , d . isDisabled = ! 0 , b . applyWidget ( c ) , c . config . debug && console . log ( "Pager: Disabled" ) ) , g = d . $size . add ( d . $goto ) . add ( d . $container . find ( ".ts-startRow, .ts-page" ) ) , h = g . length , f = 0 ; h > f ; f ++ ) g . eq ( f ) . attr ( "aria-disabled" , "true" ) . addClass ( d . cssDisabled ) [ 0 ] . disabled = ! 0 } ,
// updateCache if delayInit: true
r = function ( a ) { var c = a . config , d = c . pager ;
// tablesorter core updateCache (not pager)
b . updateCache ( c , function ( ) { var b , e = [ ] , f = a . config . cache [ 0 ] . normalized ; for ( d . totalRows = f . length , b = 0 ; b < d . totalRows ; b ++ ) e . push ( f [ b ] [ c . columns ] . $row ) ; c . rowsCopy = e , s ( a , d , ! 0 ) } ) } , s = function ( c , d , e ) { if ( ! d . isDisabled ) { var g = c . config , h = a ( c ) , i = d . last ;
// abort page move if the table has filters and has not been initialized
// fixes issue where one currentFilter is [] and the other is ['','',''],
// making the next if comparison think the filters are different (joined by commas). Fixes #202.
// don't allow rendering multiple times on the same page/size/totalRows/filters/sorts
// check for ajax url changes see #730
// & ajax url option changes (dynamically add/remove/rename sort & filter parameters)
return e !== ! 1 && d . initialized && b . isEmptyObject ( g . cache ) ? r ( c ) : void ( d . ajax && b . hasWidget ( c , "filter" ) && ! g . widgetOptions . filter _initialized || ( u ( d ) , f ( c , d ) , i . currentFilters = "" === ( i . currentFilters || [ ] ) . join ( "" ) ? [ ] : i . currentFilters , d . currentFilters = "" === ( d . currentFilters || [ ] ) . join ( "" ) ? [ ] : d . currentFilters , ( i . page !== d . page || i . size !== d . size || i . totalRows !== d . totalRows || ( i . currentFilters || [ ] ) . join ( "," ) !== ( d . currentFilters || [ ] ) . join ( "," ) || ( i . ajaxUrl || "" ) !== ( d . ajaxObject . url || "" ) || ( i . optAjaxUrl || "" ) !== ( d . ajaxUrl || "" ) || i . sortList !== ( g . sortList || [ ] ) . join ( "," ) ) && ( g . debug && console . log ( "Pager: Changing to page " + d . page ) , d . last = { page : d . page , size : d . size ,
// fixes #408; modify sortList otherwise it auto-updates
sortList : ( g . sortList || [ ] ) . join ( "," ) , totalRows : d . totalRows , currentFilters : d . currentFilters || [ ] , ajaxUrl : d . ajaxObject . url || "" , optAjaxUrl : d . ajaxUrl || "" } , d . ajax ? n ( c , d ) : d . ajax || p ( c , g . rowsCopy , d ) , a . data ( c , "pagerLastPage" , d . page ) , d . initialized && e !== ! 1 && ( g . debug && console . log ( "Pager: Triggering pageMoved" ) , h . trigger ( "pageMoved" , d ) , b . applyWidget ( c ) , c . isUpdating && ( g . debug && console . log ( "Pager: Triggering updateComplete" ) , h . trigger ( "updateComplete" , [ c , ! 0 ] ) ) ) ) ) ) } } ,
// set to either set or get value
t = function ( a , b , c ) { var d = parseInt ( b , 10 ) || a . size || a . settings . size || 10 ,
// if select does not contain an "all" option, use size
e = a . $size . find ( 'option[value="all"]' ) . length ? "all" : a . totalRows ;
// "get" to set `p.size` or "set" to set `p.$size.val()`
return /all/i . test ( b ) || d === a . totalRows ? "get" === c ? a . totalRows : e : "get" === c ? d : a . size } , u = function ( a ) { var b = Math . min ( a . totalPages , a . filteredPages ) - 1 ; return a . page = parseInt ( a . page , 10 ) , ( a . page < 0 || isNaN ( a . page ) ) && ( a . page = 0 ) , a . page > b && 0 !== a . page && ( a . page = b ) , a . page } , v = function ( b , c , d ) { d . size = t ( d , c , "get" ) , d . $size . val ( t ( d , d . size , "set" ) ) , a . data ( b , "pagerLastPage" , u ( d ) ) , a . data ( b , "pagerLastSize" , d . size ) , d . totalPages = Math . ceil ( d . totalRows / d . size ) , d . filteredPages = Math . ceil ( d . filteredRows / d . size ) , s ( b , d ) } , w = function ( a , b ) { b . page = 0 , s ( a , b ) } , x = function ( a , b ) { b . page = Math . min ( b . totalPages , b . filteredPages ) - 1 , s ( a , b ) } , y = function ( a , b ) { b . page ++ , b . page >= Math . min ( b . totalPages , b . filteredPages ) - 1 && ( b . page = Math . min ( b . totalPages , b . filteredPages ) - 1 ) , s ( a , b ) } , z = function ( a , b ) { b . page -- , b . page <= 0 && ( b . page = 0 ) , s ( a , b ) } , A = function ( a , c ) { var d = a . config , e = d . namespace + "pager" , f = [ c . cssFirst , c . cssPrev , c . cssNext , c . cssLast , c . cssGoto , c . cssPageSize ] . join ( "," ) ; q ( a , c ) , c . $container . hide ( ) . find ( f ) . unbind ( e ) , d . appender = null , // remove pager appender function
d . $table . unbind ( e ) , b . storage && b . storage ( a , c . storageKey , "" ) , delete d . pager , delete d . rowsCopy } , B = function ( c , d , e ) { var f , g , h = c . config ; d . $size . add ( d . $goto ) . add ( d . $container . find ( ".ts-startRow, .ts-page" ) ) . removeClass ( d . cssDisabled ) . removeAttr ( "disabled" ) . attr ( "aria-disabled" , "false" ) , d . isDisabled = ! 1 , d . page = a . data ( c , "pagerLastPage" ) || d . page || 0 , g = d . $size . find ( "option[selected]" ) . val ( ) , d . size = a . data ( c , "pagerLastSize" ) || t ( d , d . size , "get" ) , d . $size . val ( t ( d , d . size , "set" ) ) , d . totalPages = Math . ceil ( Math . min ( d . totalRows , d . filteredRows ) / d . size ) , c . id && ( f = c . id + "_pager_info" , d . $container . find ( d . cssPageDisplay ) . attr ( "id" , f ) , h . $table . attr ( "aria-describedby" , f ) ) , j ( c , d ) , e && ( b . update ( h ) , v ( c , d . size , d ) , l ( c , d ) , h . debug && console . log ( "Pager: Enabled" ) ) } ; d . appender = function ( b , c ) { var d = b . config , e = d . pager ; e . ajax || ( d . rowsCopy = c , e . totalRows = e . countChildRows ? d . $tbodies . eq ( 0 ) . children ( "tr" ) . length : c . length , e . size = a . data ( b , "pagerLastSize" ) || e . size || e . settings . size || 10 , e . totalPages = Math . ceil ( e . totalRows / e . size ) , p ( b , c , e ) ,
// update display here in case all rows are removed
g ( b , e , ! 1 ) ) } , d . construct = function ( e ) { return this . each ( function ( ) {
// check if tablesorter has initialized
if ( this . config && this . hasInitialized ) { var f , h , i , m = this , n = m . config , o = n . widgetOptions , p = n . pager = a . extend ( ! 0 , { } , a . tablesorterPager . defaults , e ) , u = n . $table , C = n . namespace + "pager" ,
// added in case the pager is reinitialized after being destroyed.
D = p . $container = a ( p . container ) . addClass ( "tablesorter-pager" ) . show ( ) ;
// save a copy of the original settings
p . settings = a . extend ( ! 0 , { } , a . tablesorterPager . defaults , e ) , n . debug && console . log ( "Pager: Initializing" ) , p . oldAjaxSuccess = p . oldAjaxSuccess || p . ajaxObject . success , n . appender = d . appender , p . initializing = ! 0 , p . savePages && b . storage && ( f = b . storage ( m , p . storageKey ) || { } , p . page = isNaN ( f . page ) ? p . page : f . page , p . size = ( isNaN ( f . size ) ? p . size : f . size ) || p . settings . size || 10 , a . data ( m , "pagerLastSize" , p . size ) ) ,
// skipped rows
p . regexRows = new RegExp ( "(" + ( o . filter _filteredRow || "filtered" ) + "|" + n . selectorRemove . slice ( 1 ) + "|" + n . cssChildRow + ")" ) , u . unbind ( c . split ( " " ) . join ( C + " " ) . replace ( /\s+/g , " " ) ) . bind ( "filterInit filterStart " . split ( " " ) . join ( C + " " ) , function ( b , c ) { p . currentFilters = a . isArray ( c ) ? c : n . $table . data ( "lastSearch" ) ,
// don't change page if filters are the same (pager updating, etc)
"filterStart" === b . type && p . pageReset !== ! 1 && ( n . lastCombinedFilter || "" ) !== ( p . currentFilters || [ ] ) . join ( "" ) && ( p . page = p . pageReset ) } ) . bind ( "filterEnd sortEnd " . split ( " " ) . join ( C + " " ) , function ( ) { p . currentFilters = n . $table . data ( "lastSearch" ) , ( p . initialized || p . initializing ) && ( n . delayInit && n . rowsCopy && 0 === n . rowsCopy . length &&
// make sure we have a copy of all table rows once the cache has been built
r ( m ) , g ( m , p , ! 1 ) , s ( m , p , ! 1 ) , b . applyWidget ( m ) ) } ) . bind ( "disablePager" + C , function ( a ) { a . stopPropagation ( ) , q ( m , p ) } ) . bind ( "enablePager" + C , function ( a ) { a . stopPropagation ( ) , B ( m , p , ! 0 ) } ) . bind ( "destroyPager" + C , function ( a ) { a . stopPropagation ( ) , A ( m , p ) } ) . bind ( "updateComplete" + C , function ( a , b , c ) {
// table can be unintentionally undefined in tablesorter v2.17.7 and earlier
// don't recalculate total rows/pages if using ajax
if ( a . stopPropagation ( ) , b && ! c && ! p . ajax ) { var d = n . $tbodies . eq ( 0 ) . children ( "tr" ) . not ( n . selectorRemove ) ; p . totalRows = d . length - ( p . countChildRows ? 0 : d . filter ( "." + n . cssChildRow ) . length ) , p . totalPages = Math . ceil ( p . totalRows / p . size ) , d . length && n . rowsCopy && 0 === n . rowsCopy . length &&
// make a copy of all table rows once the cache has been built
r ( b ) , p . page >= p . totalPages && x ( b , p ) , k ( b , p ) , j ( b , p ) , g ( b , p , ! 0 ) } } ) . bind ( "pageSize refreshComplete " . split ( " " ) . join ( C + " " ) , function ( a , b ) { a . stopPropagation ( ) , v ( m , t ( p , b , "get" ) , p ) , k ( m , p ) , g ( m , p , ! 1 ) } ) . bind ( "pageSet pagerUpdate " . split ( " " ) . join ( C + " " ) , function ( a , b ) { a . stopPropagation ( ) , "pagerUpdate" === a . type && ( b = "undefined" == typeof b ? p . page + 1 : b , p . last . page = ! 0 ) , p . page = ( parseInt ( b , 10 ) || 1 ) - 1 , s ( m , p , ! 0 ) , g ( m , p , ! 1 ) } ) . bind ( "pageAndSize" + C , function ( a , b , c ) { a . stopPropagation ( ) , p . page = ( parseInt ( b , 10 ) || 1 ) - 1 , v ( m , t ( p , c , "get" ) , p ) , s ( m , p , ! 0 ) , k ( m , p ) , g ( m , p , ! 1 ) } ) ,
// clicked controls
h = [ p . cssFirst , p . cssPrev , p . cssNext , p . cssLast ] , i = [ w , z , y , x ] , n . debug && ! D . length && console . warn ( "Pager: >> Container not found" ) , D . find ( h . join ( "," ) ) . attr ( "tabindex" , 0 ) . unbind ( "click" + C ) . bind ( "click" + C , function ( b ) { b . stopPropagation ( ) ; var c , d = a ( this ) , e = h . length ; if ( ! d . hasClass ( p . cssDisabled ) ) for ( c = 0 ; e > c ; c ++ ) if ( d . is ( h [ c ] ) ) { i [ c ] ( m , p ) ; break } } ) ,
// goto selector
p . $goto = D . find ( p . cssGoto ) , p . $goto . length ? p . $goto . unbind ( "change" + C ) . bind ( "change" + C , function ( ) { p . page = a ( this ) . val ( ) - 1 , s ( m , p , ! 0 ) , g ( m , p , ! 1 ) } ) : n . debug && console . warn ( "Pager: >> Goto selector not found" ) ,
// page size selector
p . $size = D . find ( p . cssPageSize ) , p . $size . length ? (
// setting an option as selected appears to cause issues with initial page size
p . $size . find ( "option" ) . removeAttr ( "selected" ) , p . $size . unbind ( "change" + C ) . bind ( "change" + C , function ( ) { if ( ! a ( this ) . hasClass ( p . cssDisabled ) ) { var b = a ( this ) . val ( ) ; p . $size . val ( b ) , // in case there are more than one pagers
v ( m , b , p ) , j ( m , p ) } return ! 1 } ) ) : n . debug && console . warn ( "Pager: >> Size selector not found" ) ,
// clear initialized flag
p . initialized = ! 1 ,
// before initialization event
u . trigger ( "pagerBeforeInitialized" , p ) , B ( m , p , ! 1 ) , "string" == typeof p . ajaxUrl ? (
// ajax pager; interact with database
p . ajax = ! 0 ,
// When filtering with ajax, allow only custom filtering function, disable default
// filtering since it will be done server side.
n . widgetOptions . filter _serversideFiltering = ! 0 , n . serverSideSorting = ! 0 , s ( m , p ) ) : ( p . ajax = ! 1 ,
// Regular pager; all rows stored in memory
b . appendCache ( n , ! 0 ) , // true = don't apply widgets
l ( m , p ) ) ,
// pager initialized
p . ajax || p . initialized || ( p . initializing = ! 1 , p . initialized = ! 0 , s ( m , p ) , n . debug && console . log ( "Pager: Triggering pagerInitialized" ) , n . $table . trigger ( "pagerInitialized" , p ) , n . widgetOptions . filter _initialized && b . hasWidget ( m , "filter" ) || g ( m , p , ! 1 ) ) ,
// make the hasWidget function think that the pager widget is being used
n . widgetInit . pager = ! 0 } } ) } } } ) ,
// see #486
b . showError = function ( b , c , d , e ) { var f , g = a ( b ) , h = g [ 0 ] . config , i = h && h . widgetOptions , j = h . pager && h . pager . cssErrorRow || i && i . pager _css && i . pager _css . errorRow || "tablesorter-errorRow" , k = typeof c , l = ! 0 , m = "" , n = function ( ) { h . $table . find ( "thead" ) . find ( "." + j ) . remove ( ) } ; if ( ! g . length ) return void console . error ( "tablesorter showError: no table parameter passed" ) ;
// ajaxError callback for plugin or widget - see #992
if ( "function" == typeof h . pager . ajaxError ) { if ( l = h . pager . ajaxError ( h , c , d , e ) , l === ! 1 ) return n ( ) ; m = l } else if ( "function" == typeof i . pager _ajaxError ) { if ( l = i . pager _ajaxError ( h , c , d , e ) , l === ! 1 ) return n ( ) ; m = l } if ( "" === m ) if ( "object" === k ) m = 0 === c . status ? "Not connected, verify Network" : 404 === c . status ? "Requested page not found [404]" : 500 === c . status ? "Internal Server Error [500]" : "parsererror" === e ? "Requested JSON parse failed" : "timeout" === e ? "Time out error" : "abort" === e ? "Ajax Request aborted" : "Uncaught error: " + c . statusText + " [" + c . status + "]" ; else { if ( "string" !== k )
// remove all error rows
return n ( ) ;
// keep backward compatibility (external usage just passes a message string)
m = c }
// allow message to include entire row HTML!
f = a ( /tr\>/ . test ( m ) ? m : '<tr><td colspan="' + h . columns + '">' + m + "</td></tr>" ) . click ( function ( ) { a ( this ) . remove ( ) } ) . appendTo ( h . $table . find ( "thead:first" ) ) . addClass ( j + " " + h . selectorRemove . slice ( 1 ) ) . attr ( { role : "alert" , "aria-live" : "assertive" } ) } ,
// extend plugin scope
a . fn . extend ( { tablesorterPager : a . tablesorterPager . construct } ) } ( jQuery ) ;