/*! Tablesaw - v0.1.2 - 2014-05-14
* https://github.com/filamentgroup/tablesaw
* Copyright (c) 2014 Filament Group; Licensed MIT */
;(function( $ ) {
var pluginName = "table",
classes = {
toolbar: "tablesaw-bar"
},
events = {
create: "tablesawcreate",
destroy: "tablesawdestroy"
},
defaultMode = "stack",
initSelector = "table[data-mode],table[data-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-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();
// Add header cells
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 ).eq( 0 ) ).not( this ).children( sel );
coltally++;
});
});
this.$table.trigger( events.create, [ this.mode, colstart ] );
};
Table.prototype.createToolbar = function() {
// Insert the toolbar
// TODO move this into a separate component
var $toolbar = this.$table.prev( '.' + classes.toolbar );
if( !$toolbar.length ) {
$toolbar = $( '
' )
.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( '.' + classes.toolbar ).each(function() {
this.className = this.className.replace( /\bmode\-\w*\b/gi, '' );
});
$( window ).off( 'resize.' + this.$table.attr( 'id' ) );
// other plugins
this.$table.trigger( events.destroy, [ this.mode ] );
this.$table.removeAttr( 'data-mode' );
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 ) {
$( e.target ).find( initSelector )[ pluginName ]();
});
}( jQuery ));
;(function( win, $, undefined ){
var classes = {
stackTable: 'tablesaw-stack',
cellLabels: 'tablesaw-cell-label'
};
var data = {
obj: 'tablesaw-stack'
};
var attrs = {
labelless: 'data-no-labels'
};
var Stack = function( element ) {
this.$table = $( element );
this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
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 );
// create the hide/show toggles
reverseHeaders.each(function(){
var $cells = $( this.cells ),
hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " tablesaw-cell-label-top",
text = $(this).text();
if( text !== "" ){
if( hierarchyClass ){
var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
filter = "";
if( iteration ){
filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
}
$cells.filter( filter ).prepend( "" + text + "" );
} else {
$cells.prepend( "" + text + "" );
}
}
});
};
Stack.prototype.destroy = function() {
this.$table.removeClass( classes.stackTable );
this.$table.find( '.' + classes.cellLabels ).remove();
};
// on tablecreate, init
$( document ).on( "tablesawcreate", "table", function( e, mode, colstart ){
if( mode === 'stack' ){
var table = new Stack( this );
table.init( colstart );
}
} );
$( document ).on( "tablesawdestroy", "table", function( e, mode ){
if( mode === 'stack' ){
$( this ).data( data.obj ).destroy();
}
} );
}( this, jQuery ));