259 lines
6.6 KiB
JavaScript
259 lines
6.6 KiB
JavaScript
/*! Tablesaw - v2.0.3 - 2016-05-02
|
||
* https://github.com/filamentgroup/tablesaw
|
||
* Copyright (c) 2016 Filament Group; Licensed MIT */
|
||
/*
|
||
* tablesaw: A set of plugins for responsive tables
|
||
* Stack and Column Toggle tables
|
||
* Copyright (c) 2013 Filament Group, Inc.
|
||
* MIT License
|
||
*/
|
||
|
||
if( typeof Tablesaw === "undefined" ) {
|
||
Tablesaw = {
|
||
i18n: {
|
||
modes: [ 'Stack', 'Swipe', 'Toggle' ],
|
||
columns: 'Col<span class=\"a11y-sm\">umn</span>s',
|
||
columnBtnText: 'Columns',
|
||
columnsDialogError: 'No eligible columns.',
|
||
sort: 'Sort'
|
||
},
|
||
// cut the mustard
|
||
mustard: 'querySelector' in document &&
|
||
( !window.blackberry || window.WebKitPoint ) &&
|
||
!window.operamini
|
||
};
|
||
}
|
||
if( !Tablesaw.config ) {
|
||
Tablesaw.config = {};
|
||
}
|
||
if( Tablesaw.mustard ) {
|
||
jQuery( document.documentElement ).addClass( 'tablesaw-enhanced' );
|
||
}
|
||
|
||
;(function( $ ) {
|
||
var pluginName = "table",
|
||
classes = {
|
||
toolbar: "tablesaw-bar"
|
||
},
|
||
events = {
|
||
create: "tablesawcreate",
|
||
destroy: "tablesawdestroy",
|
||
refresh: "tablesawrefresh"
|
||
},
|
||
defaultMode = "stack",
|
||
initSelector = "table[data-tablesaw-mode],table[data-tablesaw-sortable]";
|
||
|
||
var Table = function( element ) {
|
||
if( !element ) {
|
||
throw new Error( "Tablesaw requires an element." );
|
||
}
|
||
|
||
this.table = element;
|
||
this.$table = $( element );
|
||
|
||
this.mode = this.$table.attr( "data-tablesaw-mode" ) || defaultMode;
|
||
|
||
this.init();
|
||
};
|
||
|
||
Table.prototype.init = function() {
|
||
// assign an id if there is none
|
||
if ( !this.$table.attr( "id" ) ) {
|
||
this.$table.attr( "id", pluginName + "-" + Math.round( Math.random() * 10000 ) );
|
||
}
|
||
|
||
this.createToolbar();
|
||
|
||
var colstart = this._initCells();
|
||
|
||
this.$table.trigger( events.create, [ this, colstart ] );
|
||
};
|
||
|
||
Table.prototype._initCells = function() {
|
||
var colstart,
|
||
thrs = this.table.querySelectorAll( "thead tr" ),
|
||
self = this;
|
||
|
||
$( thrs ).each( function(){
|
||
var coltally = 0;
|
||
|
||
$( this ).children().each( function(){
|
||
var span = parseInt( this.getAttribute( "colspan" ), 10 ),
|
||
sel = ":nth-child(" + ( coltally + 1 ) + ")";
|
||
|
||
colstart = coltally + 1;
|
||
|
||
if( span ){
|
||
for( var k = 0; k < span - 1; k++ ){
|
||
coltally++;
|
||
sel += ", :nth-child(" + ( coltally + 1 ) + ")";
|
||
}
|
||
}
|
||
|
||
// Store "cells" data on header as a reference to all cells in the same column as this TH
|
||
this.cells = self.$table.find("tr").not( thrs[0] ).not( this ).children().filter( sel );
|
||
coltally++;
|
||
});
|
||
});
|
||
|
||
return colstart;
|
||
};
|
||
|
||
Table.prototype.refresh = function() {
|
||
this._initCells();
|
||
|
||
this.$table.trigger( events.refresh );
|
||
};
|
||
|
||
Table.prototype.createToolbar = function() {
|
||
// Insert the toolbar
|
||
// TODO move this into a separate component
|
||
var $toolbar = this.$table.prev().filter( '.' + classes.toolbar );
|
||
if( !$toolbar.length ) {
|
||
$toolbar = $( '<div>' )
|
||
.addClass( classes.toolbar )
|
||
.insertBefore( this.$table );
|
||
}
|
||
this.$toolbar = $toolbar;
|
||
|
||
if( this.mode ) {
|
||
this.$toolbar.addClass( 'mode-' + this.mode );
|
||
}
|
||
};
|
||
|
||
Table.prototype.destroy = function() {
|
||
// Don’t remove the toolbar. Some of the table features are not yet destroy-friendly.
|
||
this.$table.prev().filter( '.' + classes.toolbar ).each(function() {
|
||
this.className = this.className.replace( /\bmode\-\w*\b/gi, '' );
|
||
});
|
||
|
||
var tableId = this.$table.attr( 'id' );
|
||
$( document ).unbind( "." + tableId );
|
||
$( window ).unbind( "." + tableId );
|
||
|
||
// other plugins
|
||
this.$table.trigger( events.destroy, [ this ] );
|
||
|
||
this.$table.removeData( pluginName );
|
||
};
|
||
|
||
// Collection method.
|
||
$.fn[ pluginName ] = function() {
|
||
return this.each( function() {
|
||
var $t = $( this );
|
||
|
||
if( $t.data( pluginName ) ){
|
||
return;
|
||
}
|
||
|
||
var table = new Table( this );
|
||
$t.data( pluginName, table );
|
||
});
|
||
};
|
||
|
||
$( document ).on( "enhance.tablesaw", function( e ) {
|
||
// Cut the mustard
|
||
if( Tablesaw.mustard ) {
|
||
$( e.target ).find( initSelector )[ pluginName ]();
|
||
}
|
||
});
|
||
|
||
}( jQuery ));
|
||
|
||
;(function( win, $, undefined ){
|
||
|
||
var classes = {
|
||
stackTable: 'tablesaw-stack',
|
||
cellLabels: 'tablesaw-cell-label',
|
||
cellContentLabels: 'tablesaw-cell-content'
|
||
};
|
||
|
||
var data = {
|
||
obj: 'tablesaw-stack'
|
||
};
|
||
|
||
var attrs = {
|
||
labelless: 'data-tablesaw-no-labels',
|
||
hideempty: 'data-tablesaw-hide-empty'
|
||
};
|
||
|
||
var Stack = function( element ) {
|
||
|
||
this.$table = $( element );
|
||
|
||
this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
|
||
this.hideempty = this.$table.is( '[' + attrs.hideempty + ']' );
|
||
|
||
if( !this.labelless ) {
|
||
// allHeaders references headers, plus all THs in the thead, which may include several rows, or not
|
||
this.allHeaders = this.$table.find( "th" );
|
||
}
|
||
|
||
this.$table.data( data.obj, this );
|
||
};
|
||
|
||
Stack.prototype.init = function( colstart ) {
|
||
this.$table.addClass( classes.stackTable );
|
||
|
||
if( this.labelless ) {
|
||
return;
|
||
}
|
||
|
||
// get headers in reverse order so that top-level headers are appended last
|
||
var reverseHeaders = $( this.allHeaders );
|
||
var hideempty = this.hideempty;
|
||
|
||
// create the hide/show toggles
|
||
reverseHeaders.each(function(){
|
||
var $t = $( this ),
|
||
$cells = $( this.cells ).filter(function() {
|
||
return !$( this ).parent().is( "[" + attrs.labelless + "]" ) && ( !hideempty || !$( this ).is( ":empty" ) );
|
||
}),
|
||
hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " tablesaw-cell-label-top",
|
||
// TODO reduce coupling with sortable
|
||
$sortableButton = $t.find( ".tablesaw-sortable-btn" ),
|
||
html = $sortableButton.length ? $sortableButton.html() : $t.html();
|
||
|
||
if( html !== "" ){
|
||
if( hierarchyClass ){
|
||
var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
|
||
filter = "";
|
||
|
||
if( iteration ){
|
||
filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
|
||
}
|
||
$cells.filter( filter ).prepend( "<b class='" + classes.cellLabels + hierarchyClass + "'>" + html + "</b>" );
|
||
} else {
|
||
$cells.wrapInner( "<span class='" + classes.cellContentLabels + "'></span>" );
|
||
$cells.prepend( "<b class='" + classes.cellLabels + "'>" + html + "</b>" );
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
Stack.prototype.destroy = function() {
|
||
this.$table.removeClass( classes.stackTable );
|
||
this.$table.find( '.' + classes.cellLabels ).remove();
|
||
this.$table.find( '.' + classes.cellContentLabels ).each(function() {
|
||
$( this ).replaceWith( this.childNodes );
|
||
});
|
||
};
|
||
|
||
// on tablecreate, init
|
||
$( document ).on( "tablesawcreate", function( e, Tablesaw, colstart ){
|
||
if( Tablesaw.mode === 'stack' ){
|
||
var table = new Stack( Tablesaw.table );
|
||
table.init( colstart );
|
||
}
|
||
|
||
} );
|
||
|
||
$( document ).on( "tablesawdestroy", function( e, Tablesaw ){
|
||
|
||
if( Tablesaw.mode === 'stack' ){
|
||
$( Tablesaw.table ).data( data.obj ).destroy();
|
||
}
|
||
|
||
} );
|
||
|
||
}( this, jQuery )); |