2015-10-31 16:06:09 +00:00
/* Widget: columnSelector (responsive table widget) - updated 10/31/2015 (v2.24.0) */
2015-10-31 15:08:21 +00:00
/ *
* Requires tablesorter v2 . 8 + and jQuery 1.7 +
* by Justin Hallett & Rob Garrison
* /
/*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */
! function ( a ) { "use strict" ; var b = a . tablesorter , c = ".tscolsel" , d = b . columnSelector = { queryAll : "@media only all { [columns] { display: none; } } " , queryBreak : "@media all and (min-width: [size]) { [columns] { display: table-cell; } } " , init : function ( b , e , f ) { var g , h ;
// abort if no input is contained within the layout
// unique table class name
// build column selector/state array
return g = a ( f . columnSelector _layout ) , g . find ( "input" ) . add ( g . filter ( "input" ) ) . length ? ( e . $table . addClass ( e . namespace . slice ( 1 ) + "columnselector" ) , h = e . selector = { $container : a ( f . columnSelector _container || "<div>" ) } , h . $style = a ( "<style></style>" ) . prop ( "disabled" , ! 0 ) . appendTo ( "head" ) , h . $breakpoints = a ( "<style></style>" ) . prop ( "disabled" , ! 0 ) . appendTo ( "head" ) , h . isInitializing = ! 0 , d . setUpColspan ( e , f ) , d . setupSelector ( e , f ) , f . columnSelector _mediaquery && d . setupBreakpoints ( e , f ) , h . isInitializing = ! 1 , h . $container . length ? d . updateCols ( e , f ) : e . debug && console . warn ( "ColumnSelector: >> container not found" ) , void e . $table . off ( "refreshColumnSelector" + c ) . on ( "refreshColumnSelector" + c , function ( a , b , c ) { d . refreshColumns ( this . config , b , c ) } ) ) : void ( e . debug && console . error ( "ColumnSelector: >> ERROR: Column Selector aborting, no input found in the layout! ***" ) ) } , refreshColumns : function ( b , c , e ) { var f , g , h = a . isArray ( e || c ) , i = b . widgetOptions ;
// see #798
if ( "undefined" != typeof c && b . selector . $container . length ) {
// pass an array of column zero-based indexes to turn off auto mode & toggle selected columns
if (
// pass "selectors" to update the all of the container contents
"selectors" === c && ( b . selector . $container . empty ( ) , d . setupSelector ( b , i ) , d . setupBreakpoints ( b , i ) ,
// if optState is undefined, maintain the current "auto" state
"undefined" == typeof e && ( e = b . selector . auto ) ) , h ) for ( g = e || c , a . each ( g , function ( a , b ) { g [ a ] = parseInt ( b , 10 ) } ) , f = 0 ; f < b . columns ; f ++ ) b . selector . $container . find ( "input[data-column=" + f + "]" ) . prop ( "checked" , a . inArray ( f , g ) >= 0 ) ;
// if passing an array, set auto to false to allow manual column selection & update columns
// refreshColumns( c, 'auto', true ) === refreshColumns( c, true );
d . updateAuto ( b , i , b . selector . $container . find ( 'input[data-column="auto"]' ) . prop ( "checked" , e === ! 0 || c === ! 0 || "auto" === c && e !== ! 1 ) ) } else d . updateBreakpoints ( b , i ) , d . updateCols ( b , i ) ; d . adjustColspans ( b , i ) } , setupSelector : function ( c , e ) { var f , g , h , i , j , k , l = c . selector , m = l . $container , n = e . columnSelector _saveColumns && b . storage ,
// get stored column states
o = n ? b . storage ( c . table , "tablesorter-columnSelector" ) : [ ] , p = n ? b . storage ( c . table , "tablesorter-columnSelector-auto" ) : { } ;
// populate the selector container
for (
// initial states
l . auto = a . isEmptyObject ( p ) || "boolean" !== a . type ( p . auto ) ? e . columnSelector _mediaqueryState : p . auto , l . states = [ ] , l . $column = [ ] , l . $wrapper = [ ] , l . $checkbox = [ ] , f = 0 ; f < c . columns ; f ++ ) h = c . $headerIndexed [ f ] , i = h . attr ( e . columnSelector _priority ) || 1 , k = h . attr ( "data-column" ) , j = b . getColumnData ( c . table , c . headers , k ) , p = b . getData ( h , j , "columnSelector" ) , isNaN ( i ) && i . length > 0 || "disable" === p || e . columnSelector _columns [ k ] && "disable" === e . columnSelector _columns [ k ] || ( l . states [ k ] = o && "undefined" != typeof o [ k ] ? o [ k ] : "undefined" != typeof e . columnSelector _columns [ k ] ? e . columnSelector _columns [ k ] : "true" === p || "false" !== p , l . $column [ k ] = a ( this ) , g = h . attr ( e . columnSelector _name ) || h . text ( ) , m . length && ( l . $wrapper [ k ] = a ( e . columnSelector _layout . replace ( /\{name\}/g , g ) ) . appendTo ( m ) , l . $checkbox [ k ] = l . $wrapper [ k ] . find ( "input" ) . add ( l . $wrapper [ k ] . filter ( "input" ) ) . attr ( "data-column" , k ) . toggleClass ( e . columnSelector _cssChecked , l . states [ k ] ) . prop ( "checked" , l . states [ k ] ) . on ( "change" , function ( ) { var b = a ( this ) . attr ( "data-column" ) ; c . selector . states [ b ] = this . checked , d . updateCols ( c , e ) } ) . change ( ) ) ) } , setupBreakpoints : function ( b , e ) { var f = b . selector ;
// add responsive breakpoints
e . columnSelector _mediaquery && (
// used by window resize function
f . lastIndex = - 1 , d . updateBreakpoints ( b , e ) , b . $table . off ( "updateAll" + c ) . on ( "updateAll" + c , function ( ) { d . updateBreakpoints ( b , e ) , d . updateCols ( b , e ) } ) ) , f . $container . length && (
// Add media queries toggle
e . columnSelector _mediaquery && ( f . $auto = a ( e . columnSelector _layout . replace ( /\{name\}/g , e . columnSelector _mediaqueryName ) ) . prependTo ( f . $container ) , f . $auto . find ( "input" ) . add ( f . $auto . filter ( "input" ) ) . attr ( "data-column" , "auto" ) . prop ( "checked" , f . auto ) . toggleClass ( e . columnSelector _cssChecked , f . auto ) . on ( "change" , function ( ) { d . updateAuto ( b , e , a ( this ) ) } ) . change ( ) ) ,
// Add a bind on update to re-run col setup
b . $table . off ( "update" + c ) . on ( "update" + c , function ( ) { d . updateCols ( b , e ) } ) ) } , updateAuto : function ( c , e , f ) { var g = c . selector ; g . auto = f . prop ( "checked" ) || ! 1 , a . each ( g . $checkbox , function ( a , b ) { b && ( b [ 0 ] . disabled = g . auto , g . $wrapper [ a ] . toggleClass ( "disabled" , g . auto ) ) } ) , e . columnSelector _mediaquery && d . updateBreakpoints ( c , e ) , d . updateCols ( c , e ) ,
// copy the column selector to a popup/tooltip
c . selector . $popup && c . selector . $popup . find ( ".tablesorter-column-selector" ) . html ( g . $container . html ( ) ) . find ( "input" ) . each ( function ( ) { var b = a ( this ) . attr ( "data-column" ) ; a ( this ) . prop ( "checked" , "auto" === b ? g . auto : g . states [ b ] ) } ) , e . columnSelector _saveColumns && b . storage && b . storage ( c . $table [ 0 ] , "tablesorter-columnSelector-auto" , { auto : g . auto } ) , d . adjustColspans ( c , e ) ,
// trigger columnUpdate if auto is true (it gets skipped in updateCols()
g . auto && c . $table . trigger ( e . columnSelector _updated ) } , addSelectors : function ( a , b ) { var c = [ ] , d = " col:nth-child(" + b + ")" ; return c . push ( a + d + "," + a + "_extra_table" + d ) , d = " tr th:nth-child(" + b + ")" , c . push ( a + d + "," + a + "_extra_table" + d ) , d = " tr td:nth-child(" + b + ")" , c . push ( a + d + "," + a + "_extra_table" + d ) , c } , updateBreakpoints : function ( c , e ) { var f , g , h , i , j = [ ] , k = c . selector , l = c . namespace + "columnselector" , m = [ ] , n = "" ; if ( e . columnSelector _mediaquery && ! k . auto ) return k . $breakpoints . prop ( "disabled" , ! 0 ) , void k . $style . prop ( "disabled" , ! 1 ) ; if ( e . columnSelector _mediaqueryHidden )
// add columns to be hidden; even when "auto" is set - see #964
for ( h = 0 ; h < c . columns ; h ++ ) g = b . getColumnData ( c . table , c . headers , h ) , j [ h + 1 ] = "false" === b . getData ( c . $headerIndexed [ h ] , g , "columnSelector" ) , j [ h + 1 ] && ( m = m . concat ( d . addSelectors ( l , h + 1 ) ) ) ;
// only 6 breakpoints (same as jQuery Mobile)
for ( f = 0 ; 6 > f ; f ++ ) i = [ ] , c . $headers . filter ( "[" + e . columnSelector _priority + "=" + ( f + 1 ) + "]" ) . each ( function ( ) { h = parseInt ( a ( this ) . attr ( "data-column" ) , 10 ) + 1 , j [ h ] || ( i = i . concat ( d . addSelectors ( l , h ) ) ) } ) , i . length && ( m = m . concat ( i ) , n += d . queryBreak . replace ( /\[size\]/g , e . columnSelector _breakpoints [ f ] ) . replace ( /\[columns\]/g , i . join ( "," ) ) ) ; k . $style && k . $style . prop ( "disabled" , ! 0 ) , m . length && k . $breakpoints . prop ( "disabled" , ! 1 ) . html ( d . queryAll . replace ( /\[columns\]/g , m . join ( "," ) ) + n ) } , updateCols : function ( c , e ) { if ( ! ( e . columnSelector _mediaquery && c . selector . auto || c . selector . isInitializing ) ) { var f , g = c . selector , h = [ ] , i = c . namespace + "columnselector" ; g . $container . find ( "input[data-column]" ) . filter ( '[data-column!="auto"]' ) . each ( function ( ) { this . checked || ( f = parseInt ( a ( this ) . attr ( "data-column" ) , 10 ) + 1 , h = h . concat ( d . addSelectors ( i , f ) ) ) , a ( this ) . toggleClass ( e . columnSelector _cssChecked , this . checked ) } ) , e . columnSelector _mediaquery && g . $breakpoints . prop ( "disabled" , ! 0 ) , g . $style && g . $style . prop ( "disabled" , ! 1 ) . html ( h . length ? h . join ( "," ) + " { display: none; }" : "" ) , e . columnSelector _saveColumns && b . storage && b . storage ( c . $table [ 0 ] , "tablesorter-columnSelector" , g . states ) , d . adjustColspans ( c , e ) , c . $table . trigger ( e . columnSelector _updated ) } } , setUpColspan : function ( c , e ) { var f , g , h , i = a ( window ) , j = ! 1 , k = c . $table . add ( a ( c . namespace + "_extra_table" ) ) . children ( "thead, tfoot" ) . children ( "tr" ) . children ( "th, td" ) , l = k . length ; for ( f = 0 ; l > f ; f ++ ) g = k [ f ] . colSpan , g > 1 && ( j = ! 0 , k . eq ( f ) . addClass ( c . namespace . slice ( 1 ) + "columnselectorHasSpan" ) . attr ( "data-col-span" , g ) ) ;
// only add resize end if using media queries
j && e . columnSelector _mediaquery && ( h = c . namespace . slice ( 1 ) + "columnselector" , i . off ( h ) . on ( "resize" + h , b . window _resize ) . on ( "resizeEnd" + h , function ( ) { i . off ( "resize" + h , b . window _resize ) , d . adjustColspans ( c , e ) , i . on ( "resize" + h , b . window _resize ) } ) ) } , adjustColspans : function ( b , c ) { var d , e , f , g , h , i = b . selector , j = i . auto , k = a ( b . namespace + "columnselectorHasSpan" ) , l = k . length ; if ( l ) for ( d = 0 ; l > d ; d ++ ) { for ( f = parseInt ( k . eq ( d ) . attr ( "data-column" ) , 10 ) , g = parseInt ( k . eq ( d ) . attr ( "data-col-span" ) , 10 ) , h = f + g , e = f ; h > e ; e ++ ) ( ! j && i . states [ e ] === ! 1 || j && b . $headerIndexed [ e ] && ! b . $headerIndexed [ e ] . is ( ":visible" ) ) && g -- ; g ? k . eq ( d ) . show ( ) [ 0 ] . colSpan = g : k . eq ( d ) . hide ( ) } } , attachTo : function ( b , c ) { b = a ( b ) [ 0 ] ; var d , e , f , g = b . config , h = a ( c ) ; h . length && g && ( h . find ( ".tablesorter-column-selector" ) . length ||
// add a wrapper to add the selector into, in case the popup has other content
h . append ( '<span class="tablesorter-column-selector"></span>' ) , d = g . selector , e = g . widgetOptions , h . find ( ".tablesorter-column-selector" ) . html ( d . $container . html ( ) ) . find ( "input" ) . each ( function ( ) { var b = a ( this ) . attr ( "data-column" ) , c = "auto" === b ? d . auto : d . states [ b ] ; a ( this ) . toggleClass ( e . columnSelector _cssChecked , c ) . prop ( "checked" , c ) } ) , d . $popup = h . on ( "change" , "input" , function ( ) { f = a ( this ) . toggleClass ( e . columnSelector _cssChecked , this . checked ) . attr ( "data-column" ) , d . $container . find ( 'input[data-column="' + f + '"]' ) . prop ( "checked" , this . checked ) . trigger ( "change" ) } ) ) } } ; /* Add window resizeEnd event (also used by scroller widget) */
b . window _resize = function ( ) { b . timer _resize && clearTimeout ( b . timer _resize ) , b . timer _resize = setTimeout ( function ( ) { a ( window ) . trigger ( "resizeEnd" ) } , 250 ) } , b . addWidget ( { id : "columnSelector" , priority : 10 , options : {
// target the column selector markup
columnSelector _container : null ,
// column status, true = display, false = hide
// disable = do not display on list
columnSelector _columns : { } ,
// remember selected columns
columnSelector _saveColumns : ! 0 ,
// container layout
columnSelector _layout : '<label><input type="checkbox">{name}</label>' ,
// data attribute containing column name to use in the selector container
columnSelector _name : "data-selector-name" , /* Responsive Media Query settings */
// enable/disable mediaquery breakpoints
columnSelector _mediaquery : ! 0 ,
// toggle checkbox name
columnSelector _mediaqueryName : "Auto: " ,
// breakpoints checkbox initial setting
columnSelector _mediaqueryState : ! 0 ,
// hide columnSelector false columns while in auto mode
columnSelector _mediaqueryHidden : ! 1 ,
// responsive table hides columns with priority 1-6 at these breakpoints
// see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint
// *** set to false to disable ***
columnSelector _breakpoints : [ "20em" , "30em" , "40em" , "50em" , "60em" , "70em" ] ,
// data attribute containing column priority
// duplicates how jQuery mobile uses priorities:
// http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/
columnSelector _priority : "data-priority" ,
// class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome
// applied icons; use this class name (input.checked) instead of input:checked
columnSelector _cssChecked : "checked" ,
// event triggered when columnSelector completes
columnSelector _updated : "columnUpdate" } , init : function ( a , b , c , e ) { d . init ( a , c , e ) } , remove : function ( a , b , d , e ) { if ( ! e ) { var f = b . selector ; f . $container . empty ( ) , f . $popup && f . $popup . empty ( ) , f . $style . remove ( ) , f . $breakpoints . remove ( ) , b . $table . off ( "updateAll" + c + " update" + c ) } } } ) } ( jQuery ) ;