| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*
- * tablesaw: A set of plugins for responsive tables
- * Swipe Toggle: swipe gesture (or buttons) to navigate which columns are shown.
- * Copyright (c) 2013 Filament Group, Inc.
- * MIT License
- */
- ;(function( win, $, undefined ){
- $.extend( Tablesaw.config, {
- swipe: {
- horizontalThreshold: 15,
- verticalThreshold: 30
- }
- });
- function isIE8() {
- var div = document.createElement('div'),
- all = div.getElementsByTagName('i');
- div.innerHTML = '<!--[if lte IE 8]><i></i><![endif]-->';
- return !!all.length;
- }
- var classes = {
- // TODO duplicate class, also in tables.js
- toolbar: "tablesaw-bar",
- hideBtn: "disabled",
- persistWidths: "tablesaw-fix-persist",
- allColumnsVisible: 'tablesaw-all-cols-visible'
- };
- function createSwipeTable( $table ){
- var $btns = $( "<div class='tablesaw-advance'></div>" ),
- $prevBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro left' title='Previous Column'></a>" ).appendTo( $btns ),
- $nextBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro right' title='Next Column'></a>" ).appendTo( $btns ),
- $headerCells = $table.find( "thead th" ),
- $headerCellsNoPersist = $headerCells.not( '[data-tablesaw-priority="persist"]' ),
- headerWidths = [],
- $head = $( document.head || 'head' ),
- tableId = $table.attr( 'id' ),
- // TODO switch this to an nth-child feature test
- supportsNthChild = !isIE8();
- if( !$headerCells.length ) {
- throw new Error( "tablesaw swipe: no header cells found. Are you using <th> inside of <thead>?" );
- }
- // Calculate initial widths
- $table.css('width', 'auto');
- $headerCells.each(function() {
- headerWidths.push( $( this ).outerWidth() );
- });
- $table.css( 'width', '' );
- $btns.appendTo( $table.prev().filter( '.tablesaw-bar' ) );
- $table.addClass( "tablesaw-swipe" );
- if( !tableId ) {
- tableId = 'tableswipe-' + Math.round( Math.random() * 10000 );
- $table.attr( 'id', tableId );
- }
- function $getCells( headerCell ) {
- return $( headerCell.cells ).add( headerCell );
- }
- function showColumn( headerCell ) {
- $getCells( headerCell ).removeClass( 'tablesaw-cell-hidden' );
- }
- function hideColumn( headerCell ) {
- $getCells( headerCell ).addClass( 'tablesaw-cell-hidden' );
- }
- function persistColumn( headerCell ) {
- $getCells( headerCell ).addClass( 'tablesaw-cell-persist' );
- }
- function isPersistent( headerCell ) {
- return $( headerCell ).is( '[data-tablesaw-priority="persist"]' );
- }
- function unmaintainWidths() {
- $table.removeClass( classes.persistWidths );
- $( '#' + tableId + '-persist' ).remove();
- }
- function maintainWidths() {
- var prefix = '#' + tableId + '.tablesaw-swipe ',
- styles = [],
- tableWidth = $table.width(),
- hash = [],
- newHash;
- $headerCells.each(function( index ) {
- var width;
- if( isPersistent( this ) ) {
- width = $( this ).outerWidth();
- // Only save width on non-greedy columns (take up less than 75% of table width)
- if( width < tableWidth * 0.75 ) {
- hash.push( index + '-' + width );
- styles.push( prefix + ' .tablesaw-cell-persist:nth-child(' + ( index + 1 ) + ') { width: ' + width + 'px; }' );
- }
- }
- });
- newHash = hash.join( '_' );
- $table.addClass( classes.persistWidths );
- var $style = $( '#' + tableId + '-persist' );
- // If style element not yet added OR if the widths have changed
- if( !$style.length || $style.data( 'hash' ) !== newHash ) {
- // Remove existing
- $style.remove();
- if( styles.length ) {
- $( '<style>' + styles.join( "\n" ) + '</style>' )
- .attr( 'id', tableId + '-persist' )
- .data( 'hash', newHash )
- .appendTo( $head );
- }
- }
- }
- function getNext(){
- var next = [],
- checkFound;
- $headerCellsNoPersist.each(function( i ) {
- var $t = $( this ),
- isHidden = $t.css( "display" ) === "none" || $t.is( ".tablesaw-cell-hidden" );
- if( !isHidden && !checkFound ) {
- checkFound = true;
- next[ 0 ] = i;
- } else if( isHidden && checkFound ) {
- next[ 1 ] = i;
- return false;
- }
- });
- return next;
- }
- function getPrev(){
- var next = getNext();
- return [ next[ 1 ] - 1 , next[ 0 ] - 1 ];
- }
- function nextpair( fwd ){
- return fwd ? getNext() : getPrev();
- }
- function canAdvance( pair ){
- return pair[ 1 ] > -1 && pair[ 1 ] < $headerCellsNoPersist.length;
- }
- function matchesMedia() {
- var matchMedia = $table.attr( "data-tablesaw-swipe-media" );
- return !matchMedia || ( "matchMedia" in win ) && win.matchMedia( matchMedia ).matches;
- }
- function fakeBreakpoints() {
- if( !matchesMedia() ) {
- return;
- }
- var extraPaddingPixels = 20,
- containerWidth = $table.parent().width(),
- persist = [],
- sum = 0,
- sums = [],
- visibleNonPersistantCount = $headerCells.length;
- $headerCells.each(function( index ) {
- var $t = $( this ),
- isPersist = $t.is( '[data-tablesaw-priority="persist"]' );
- persist.push( isPersist );
- sum += headerWidths[ index ] + ( isPersist ? 0 : extraPaddingPixels );
- sums.push( sum );
- // is persistent or is hidden
- if( isPersist || sum > containerWidth ) {
- visibleNonPersistantCount--;
- }
- });
- var needsNonPersistentColumn = visibleNonPersistantCount === 0;
- $headerCells.each(function( index ) {
- if( persist[ index ] ) {
- // for visual box-shadow
- persistColumn( this );
- return;
- }
- if( sums[ index ] <= containerWidth || needsNonPersistentColumn ) {
- needsNonPersistentColumn = false;
- showColumn( this );
- } else {
- hideColumn( this );
- }
- });
- if( supportsNthChild ) {
- unmaintainWidths();
- }
- $table.trigger( 'tablesawcolumns' );
- }
- function advance( fwd ){
- var pair = nextpair( fwd );
- if( canAdvance( pair ) ){
- if( isNaN( pair[ 0 ] ) ){
- if( fwd ){
- pair[0] = 0;
- }
- else {
- pair[0] = $headerCellsNoPersist.length - 1;
- }
- }
- if( supportsNthChild ) {
- maintainWidths();
- }
- hideColumn( $headerCellsNoPersist.get( pair[ 0 ] ) );
- showColumn( $headerCellsNoPersist.get( pair[ 1 ] ) );
- $table.trigger( 'tablesawcolumns' );
- }
- }
- $prevBtn.add( $nextBtn ).click(function( e ){
- advance( !!$( e.target ).closest( $nextBtn ).length );
- e.preventDefault();
- });
- function getCoord( event, key ) {
- return ( event.touches || event.originalEvent.touches )[ 0 ][ key ];
- }
- $table
- .bind( "touchstart.swipetoggle", function( e ){
- var originX = getCoord( e, 'pageX' ),
- originY = getCoord( e, 'pageY' ),
- x,
- y;
- $( win ).off( "resize", fakeBreakpoints );
- $( this )
- .bind( "touchmove", function( e ){
- x = getCoord( e, 'pageX' );
- y = getCoord( e, 'pageY' );
- var cfg = Tablesaw.config.swipe;
- if( Math.abs( x - originX ) > cfg.horizontalThreshold && Math.abs( y - originY ) < cfg.verticalThreshold ) {
- e.preventDefault();
- }
- })
- .bind( "touchend.swipetoggle", function(){
- var cfg = Tablesaw.config.swipe;
- if( Math.abs( y - originY ) < cfg.verticalThreshold ) {
- if( x - originX < -1 * cfg.horizontalThreshold ){
- advance( true );
- }
- if( x - originX > cfg.horizontalThreshold ){
- advance( false );
- }
- }
- window.setTimeout(function() {
- $( win ).on( "resize", fakeBreakpoints );
- }, 300);
- $( this ).unbind( "touchmove touchend" );
- });
- })
- .bind( "tablesawcolumns.swipetoggle", function(){
- var canGoPrev = canAdvance( getPrev() );
- var canGoNext = canAdvance( getNext() );
- $prevBtn[ canGoPrev ? "removeClass" : "addClass" ]( classes.hideBtn );
- $nextBtn[ canGoNext ? "removeClass" : "addClass" ]( classes.hideBtn );
- $prevBtn.closest( "." + classes.toolbar )[ !canGoPrev && !canGoNext ? 'addClass' : 'removeClass' ]( classes.allColumnsVisible );
- })
- .bind( "tablesawnext.swipetoggle", function(){
- advance( true );
- } )
- .bind( "tablesawprev.swipetoggle", function(){
- advance( false );
- } )
- .bind( "tablesawdestroy.swipetoggle", function(){
- var $t = $( this );
- $t.removeClass( 'tablesaw-swipe' );
- $t.prev().filter( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
- $( win ).off( "resize", fakeBreakpoints );
- $t.unbind( ".swipetoggle" );
- });
- fakeBreakpoints();
- $( win ).on( "resize", fakeBreakpoints );
- }
- // on tablecreate, init
- $( document ).on( "tablesawcreate", function( e, Tablesaw ){
- if( Tablesaw.mode === 'swipe' ){
- createSwipeTable( Tablesaw.$table );
- }
- } );
- }( this, jQuery ));
|