text: /*! Tablesaw - v1.0.4 - 2015-02-19
  * https://github.com/filamentgroup/tablesaw
  * Copyright (c) 2015 Filament Group; Licensed MIT */
  ;(function( $ ) {
  	var div = document.createElement('div'),
  		all = div.getElementsByTagName('i'),
  		$doc = $( document.documentElement );
  
  	div.innerHTML = '<!--[if lte IE 8]><i></i><![endif]-->';
  	if( all[ 0 ] ) {
  		$doc.addClass( 'ie-lte8' );
  	}
  
  	// Cut the mustard
  	if( !( 'querySelector' in document ) ||
  			( window.blackberry && !window.WebKitPoint ) ||
  			window.operamini ) {
  		return;
  	} else {
  		$doc.addClass( 'tablesaw-enhanced' );
  
  		// DOM-ready auto-init of plugins.
  		// Many plugins bind to an "enhance" event to init themselves on dom ready, or when new markup is inserted into the DOM
  		$( function(){
  			$( document ).trigger( "enhance.tablesaw" );
  		});
  	}
  
  })( jQuery );
  /*
  * 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'
  		}
  	};
  }
  if( !Tablesaw.config ) {
  	Tablesaw.config = {};
  }
  
  ;(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 ).eq( 0 ) ).not( this ).children( 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( '.' + 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( '.' + 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.removeAttr( 'data-tablesaw-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',
  		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 ));
  ;(function( $ ) {
  	var pluginName = "tablesawbtn",
  		initSelector = ".btn",
  		methods = {
  			_create: function(){
  				return $( this ).each(function() {
  					$( this )
  						.trigger( "beforecreate." + pluginName )
  						[ pluginName ]( "_init" )
  						.trigger( "create." + pluginName );
  				});
  			},
  			_init: function(){
  				var oEl = $( this ),
  					sel = this.getElementsByTagName( "select" )[ 0 ];
  
  				if( sel ) {
  					$( this )
  						.addClass( "btn-select" )
  						[ pluginName ]( "_select", sel );
  				}
  				return oEl;
  			},
  			_select: function( sel ) {
  				var update = function( oEl, sel ) {
  					var opts = $( sel ).find( "option" ),
  						label, el, children;
  
  					opts.each(function() {
  						var opt = this;
  						if( opt.selected ) {
  							label = document.createTextNode( opt.text );
  						}
  					});
  
  					children = oEl.childNodes;
  					if( opts.length > 0 ){
  						for( var i = 0, l = children.length; i < l; i++ ) {
  							el = children[ i ];
  
  							if( el && el.nodeType === 3 ) {
  								oEl.replaceChild( label, el );
  							}
  						}
  					}
  				};
  
  				update( this, sel );
  				$( this ).bind( "change refresh", function() {
  					update( this, sel );
  				});
  			}
  		};
  
  	// Collection method.
  	$.fn[ pluginName ] = function( arrg, a, b, c ) {
  		return this.each(function() {
  
  		// if it's a method
  		if( arrg && typeof( arrg ) === "string" ){
  			return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
  		}
  
  		// don't re-init
  		if( $( this ).data( pluginName + "active" ) ){
  			return $( this );
  		}
  
  		// otherwise, init
  
  		$( this ).data( pluginName + "active", true );
  			$.fn[ pluginName ].prototype._create.call( this );
  		});
  	};
  
  	// add methods
  	$.extend( $.fn[ pluginName ].prototype, methods );
  
  	$( document ).on( "enhance", function( e ) {
  		$( initSelector, e.target )[ pluginName ]();
  	});
  
  }( jQuery ));
  ;(function( win, $, undefined ){
  
  	var ColumnToggle = function( element ) {
  
  		this.$table = $( element );
  
  		this.classes = {
  			columnToggleTable: 'tablesaw-columntoggle',
  			columnBtnContain: 'tablesaw-columntoggle-btnwrap tablesaw-advance',
  			columnBtn: 'tablesaw-columntoggle-btn tablesaw-nav-btn down',
  			popup: 'tablesaw-columntoggle-popup',
  			priorityPrefix: 'tablesaw-priority-',
  			// TODO duplicate class, also in tables.js
  			toolbar: 'tablesaw-bar'
  		};
  
  		// Expose headers and allHeaders properties on the widget
  		// headers references the THs within the first TR in the table
  		this.headers = this.$table.find( 'tr:first > th' );
  
  		this.$table.data( 'tablesaw-coltoggle', this );
  	};
  
  	ColumnToggle.prototype.init = function() {
  
  		var tableId,
  			id,
  			$menuButton,
  			$popup,
  			$menu,
  			$btnContain,
  			self = this;
  
  		this.$table.addClass( this.classes.columnToggleTable );
  
  		tableId = this.$table.attr( "id" );
  		id = tableId + "-popup";
  		$btnContain = $( "<div class='" + this.classes.columnBtnContain + "'></div>" );
  		$menuButton = $( "<a href='#" + id + "' class='btn btn-micro " + this.classes.columnBtn +"' data-popup-link>" +
  										"<span>" + Tablesaw.i18n.columnBtnText + "</span></a>" );
  		$popup = $( "<div class='dialog-table-coltoggle " + this.classes.popup + "' id='" + id + "'></div>" );
  		$menu = $( "<div class='btn-group'></div>" );
  
  		var hasNonPersistentHeaders = false;
  		$( this.headers ).not( "td" ).each( function() {
  			var $this = $( this ),
  				priority = $this.attr("data-tablesaw-priority"),
  				$cells = $this.add( this.cells );
  
  			if( priority && priority !== "persist" ) {
  				$cells.addClass( self.classes.priorityPrefix + priority );
  
  				$("<label><input type='checkbox' checked>" + $this.text() + "</label>" )
  					.appendTo( $menu )
  					.children( 0 )
  					.data( "cells", $cells );
  
  				hasNonPersistentHeaders = true;
  			}
  		});
  
  		if( !hasNonPersistentHeaders ) {
  			$menu.append( '<label>' + Tablesaw.i18n.columnsDialogError + '</label>' );
  		}
  
  		$menu.appendTo( $popup );
  
  		// bind change event listeners to inputs - TODO: move to a private method?
  		$menu.find( 'input[type="checkbox"]' ).on( "change", function(e) {
  			var checked = e.target.checked;
  
  			$( e.target ).data( "cells" )
  				.toggleClass( "tablesaw-cell-hidden", !checked )
  				.toggleClass( "tablesaw-cell-visible", checked );
  
  			self.$table.trigger( 'tablesawcolumns' );
  		});
  
  		$menuButton.appendTo( $btnContain );
  		$btnContain.appendTo( this.$table.prev( '.' + this.classes.toolbar ) );
  
  		var closeTimeout;
  		function openPopup() {
  			$btnContain.addClass( 'visible' );
  			$menuButton.removeClass( 'down' ).addClass( 'up' );
  
  			$( document ).unbind( 'click.' + tableId, closePopup );
  
  			window.clearTimeout( closeTimeout );
  			closeTimeout = window.setTimeout(function() {
  				$( document ).one( 'click.' + tableId, closePopup );
  			}, 15 );
  		}
  
  		function closePopup( event ) {
  			// Click came from inside the popup, ignore.
  			if( event && $( event.target ).closest( "." + self.classes.popup ).length ) {
  				return;
  			}
  
  			$( document ).unbind( 'click.' + tableId );
  			$menuButton.removeClass( 'up' ).addClass( 'down' );
  			$btnContain.removeClass( 'visible' );
  		}
  
  		$menuButton.on( "click.tablesaw", function( event ) {
  			event.preventDefault();
  
  			if( !$btnContain.is( ".visible" ) ) {
  				openPopup();
  			} else {
  				closePopup();
  			}
  		});
  
  		$popup.appendTo( $btnContain );
  
  		this.$menu = $menu;
  
  		$(window).on( "resize." + tableId, function(){
  			self.refreshToggle();
  		});
  
  		this.refreshToggle();
  	};
  
  	ColumnToggle.prototype.refreshToggle = function() {
  		this.$menu.find( "input" ).each( function() {
  			var $this = $( this );
  
  			this.checked = $this.data( "cells" ).eq( 0 ).css( "display" ) === "table-cell";
  		});
  	};
  
  	ColumnToggle.prototype.refreshPriority = function(){
  		var self = this;
  		$(this.headers).not( "td" ).each( function() {
  			var $this = $( this ),
  				priority = $this.attr("data-tablesaw-priority"),
  				$cells = $this.add( this.cells );
  
  			if( priority && priority !== "persist" ) {
  				$cells.addClass( self.classes.priorityPrefix + priority );
  			}
  		});
  	};
  
  	ColumnToggle.prototype.destroy = function() {
  		// table toolbars, document and window .tableId events
  		// removed in parent tables.js destroy method
  
  		this.$table.removeClass( this.classes.columnToggleTable );
  		this.$table.find( 'th, td' ).each(function() {
  			var $cell = $( this );
  			$cell.removeClass( 'tablesaw-cell-hidden' )
  				.removeClass( 'tablesaw-cell-visible' );
  
  			this.className = this.className.replace( /\bui\-table\-priority\-\d\b/g, '' );
  		});
  	};
  
  	// on tablecreate, init
  	$( document ).on( "tablesawcreate", function( e, Tablesaw ){
  
  		if( Tablesaw.mode === 'columntoggle' ){
  			var table = new ColumnToggle( Tablesaw.table );
  			table.init();
  		}
  
  	} );
  
  	$( document ).on( "tablesawdestroy", function( e, Tablesaw ){
  		if( Tablesaw.mode === 'columntoggle' ){
  			$( Tablesaw.table ).data( 'tablesaw-coltoggle' ).destroy();
  		}
  	} );
  
  }( this, jQuery ));
  ;(function( win, $, undefined ){
  
  	$.extend( Tablesaw.config, {
  		swipe: {
  			horizontalThreshold: 15,
  			verticalThreshold: 30
  		}
  	});
  
  	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 ),
  			hideBtn = 'disabled',
  			persistWidths = 'tablesaw-fix-persist',
  			$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
  			isIE8 = $( 'html' ).is( '.ie-lte8' );
  
  		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( '.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( 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( 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( !isIE8 ) {
  				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( !isIE8 ) {
  					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(){
  				$prevBtn[ canAdvance( getPrev() ) ? "removeClass" : "addClass" ]( hideBtn );
  				$nextBtn[ canAdvance( getNext() ) ? "removeClass" : "addClass" ]( hideBtn );
  			})
  			.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( '.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 ));
  
  ;(function( $ ) {
  	function getSortValue( cell ) {
  		return $.map( cell.childNodes, function( el ) {
  				var $el = $( el );
  				if( $el.is( 'input, select' ) ) {
  					return $el.val();
  				} else if( $el.hasClass( 'tablesaw-cell-label' ) ) {
  					return;
  				}
  				return $.trim( $el.text() );
  			}).join( '' );
  	}
  
  	var pluginName = "tablesaw-sortable",
  		initSelector = "table[data-" + pluginName + "]",
  		sortableSwitchSelector = "[data-" + pluginName + "-switch]",
  		attrs = {
  			defaultCol: "data-tablesaw-sortable-default-col"
  		},
  		classes = {
  			head: pluginName + "-head",
  			ascend: pluginName + "-ascending",
  			descend: pluginName + "-descending",
  			switcher: pluginName + "-switch",
  			tableToolbar: 'tablesaw-toolbar',
  			sortButton: pluginName + "-btn"
  		},
  		methods = {
  			_create: function( o ){
  				return $( this ).each(function() {
  					var init = $( this ).data( "init" + pluginName );
  					if( init ) {
  						return false;
  					}
  					$( this )
  						.data( "init"+ pluginName, true )
  						.trigger( "beforecreate." + pluginName )
  						[ pluginName ]( "_init" , o )
  						.trigger( "create." + pluginName );
  				});
  			},
  			_init: function(){
  				var el = $( this ),
  					heads,
  					$switcher;
  
  				var addClassToTable = function(){
  						el.addClass( pluginName );
  					},
  					addClassToHeads = function( h ){
  						$.each( h , function( i , v ){
  							$( v ).addClass( classes.head );
  						});
  					},
  					makeHeadsActionable = function( h , fn ){
  						$.each( h , function( i , v ){
  							var b = $( "<button class='" + classes.sortButton + "'/>" );
  							b.bind( "click" , { col: v } , fn );
  							$( v ).wrapInner( b );
  						});
  					},
  					clearOthers = function( sibs ){
  						$.each( sibs , function( i , v ){
  							var col = $( v );
  							col.removeAttr( attrs.defaultCol );
  							col.removeClass( classes.ascend );
  							col.removeClass( classes.descend );
  						});
  					},
  					headsOnAction = function( e ){
  						if( $( e.target ).is( 'a[href]' ) ) {
  							return;
  						}
  
  						e.stopPropagation();
  						var head = $( this ).parent(),
  							v = e.data.col,
  							newSortValue = heads.index( head );
  
  						clearOthers( head.siblings() );
  						if( head.hasClass( classes.descend ) ){
  							el[ pluginName ]( "sortBy" , v , true);
  							newSortValue += '_asc';
  						} else {
  							el[ pluginName ]( "sortBy" , v );
  							newSortValue += '_desc';
  						}
  						if( $switcher ) {
  							$switcher.find( 'select' ).val( newSortValue ).trigger( 'refresh' );
  						}
  
  						e.preventDefault();
  					},
  					handleDefault = function( heads ){
  						$.each( heads , function( idx , el ){
  							var $el = $( el );
  							if( $el.is( "[" + attrs.defaultCol + "]" ) ){
  								if( !$el.hasClass( classes.descend ) ) {
  									$el.addClass( classes.ascend );
  								}
  							}
  						});
  					},
  					addSwitcher = function( heads ){
  						$switcher = $( '<div>' ).addClass( classes.switcher ).addClass( classes.tableToolbar ).html(function() {
  							var html = [ '<label>' + Tablesaw.i18n.sort + ':' ];
  
  							html.push( '<span class="btn btn-small">&#160;<select>' );
  							heads.each(function( j ) {
  								var $t = $( this ),
  									isDefaultCol = $t.is( "[" + attrs.defaultCol + "]" ),
  									isDescending = $t.hasClass( classes.descend ),
  									isNumeric = false;
  
  								// Check only the first three rows to see if the column is numbers.
  								$( this.cells ).slice( 0, 3 ).each(function() {
  									if( !isNaN( parseInt( getSortValue( this ), 10 ) ) ) {
  										isNumeric = true;
  										return false;
  									}
  								});
  
  								html.push( '<option' + ( isDefaultCol && !isDescending ? ' selected' : '' ) + ' value="' + j + '_asc">' + $t.text() + ' ' + ( isNumeric ? '↑' : '(A-Z)' ) + '</option>' );
  								html.push( '<option' + ( isDefaultCol && isDescending ? ' selected' : '' ) + ' value="' + j + '_desc">' + $t.text() + ' ' + ( isNumeric ? '↓' : '(Z-A)' ) + '</option>' );
  							});
  							html.push( '</select></span></label>' );
  
  							return html.join('');
  						});
  
  						var $toolbar = el.prev( '.tablesaw-bar' ),
  							$firstChild = $toolbar.children().eq( 0 );
  
  						if( $firstChild.length ) {
  							$switcher.insertBefore( $firstChild );
  						} else {
  							$switcher.appendTo( $toolbar );
  						}
  						$switcher.find( '.btn' ).tablesawbtn();
  						$switcher.find( 'select' ).on( 'change', function() {
  							var val = $( this ).val().split( '_' ),
  								head = heads.eq( val[ 0 ] );
  
  							clearOthers( head.siblings() );
  							el[ pluginName ]( 'sortBy', head.get( 0 ), val[ 1 ] === 'asc' );
  						});
  					};
  
  					addClassToTable();
  					heads = el.find( "thead th[data-" + pluginName + "-col]" );
  					addClassToHeads( heads );
  					makeHeadsActionable( heads , headsOnAction );
  					handleDefault( heads );
  
  					if( el.is( sortableSwitchSelector ) ) {
  						addSwitcher( heads, el.find('tbody tr:nth-child(-n+3)') );
  					}
  			},
  			getColumnNumber: function( col ){
  				return $( col ).prevAll().length;
  			},
  			getTableRows: function(){
  				return $( this ).find( "tbody tr" );
  			},
  			sortRows: function( rows , colNum , ascending, col ){
  				var cells, fn, sorted;
  				var getCells = function( rows ){
  						var cells = [];
  						$.each( rows , function( i , r ){
  							cells.push({
  								cell: getSortValue( $( r ).children().get( colNum ) ),
  								rowNum: i
  							});
  						});
  						return cells;
  					},
  					getSortFxn = function( ascending, forceNumeric ){
  						var fn,
  							regex = /[^\-\+\d\.]/g;
  						if( ascending ){
  							fn = function( a , b ){
  								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
  									return parseFloat( a.cell.replace( regex, '' ) ) - parseFloat( b.cell.replace( regex, '' ) );
  								} else {
  									return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
  								}
  							};
  						} else {
  							fn = function( a , b ){
  								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
  									return parseFloat( b.cell.replace( regex, '' ) ) - parseFloat( a.cell.replace( regex, '' ) );
  								} else {
  									return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
  								}
  							};
  						}
  						return fn;
  					},
  					applyToRows = function( sorted , rows ){
  						var newRows = [], i, l, cur;
  						for( i = 0, l = sorted.length ; i < l ; i++ ){
  							cur = sorted[ i ].rowNum;
  							newRows.push( rows[cur] );
  						}
  						return newRows;
  					};
  
  				cells = getCells( rows );
  				var customFn = $( col ).data( 'tablesaw-sort' );
  				fn = ( customFn && typeof customFn === "function" ? customFn( ascending ) : false ) ||
  					getSortFxn( ascending, $( col ).is( '[data-sortable-numeric]' ) );
  				sorted = cells.sort( fn );
  				rows = applyToRows( sorted , rows );
  				return rows;
  			},
  			replaceTableRows: function( rows ){
  				var el = $( this ),
  					body = el.find( "tbody" );
  				body.html( rows );
  			},
  			makeColDefault: function( col , a ){
  				var c = $( col );
  				c.attr( attrs.defaultCol , "true" );
  				if( a ){
  					c.removeClass( classes.descend );
  					c.addClass( classes.ascend );
  				} else {
  					c.removeClass( classes.ascend );
  					c.addClass( classes.descend );
  				}
  			},
  			sortBy: function( col , ascending ){
  				var el = $( this ), colNum, rows;
  
  				colNum = el[ pluginName ]( "getColumnNumber" , col );
  				rows = el[ pluginName ]( "getTableRows" );
  				rows = el[ pluginName ]( "sortRows" , rows , colNum , ascending, col );
  				el[ pluginName ]( "replaceTableRows" , rows );
  				el[ pluginName ]( "makeColDefault" , col , ascending );
  			}
  		};
  
  	// Collection method.
  	$.fn[ pluginName ] = function( arrg ) {
  		var args = Array.prototype.slice.call( arguments , 1),
  			returnVal;
  
  		// if it's a method
  		if( arrg && typeof( arrg ) === "string" ){
  			returnVal = $.fn[ pluginName ].prototype[ arrg ].apply( this[0], args );
  			return (typeof returnVal !== "undefined")? returnVal:$(this);
  		}
  		// check init
  		if( !$( this ).data( pluginName + "data" ) ){
  			$( this ).data( pluginName + "active", true );
  			$.fn[ pluginName ].prototype._create.call( this , arrg );
  		}
  		return $(this);
  	};
  	// add methods
  	$.extend( $.fn[ pluginName ].prototype, methods );
  
  	$( document ).on( "tablesawcreate", function( e, Tablesaw ) {
  		if( Tablesaw.$table.is( initSelector ) ) {
  			Tablesaw.$table[ pluginName ]();
  		}
  	});
  
  }( jQuery ));
  
  ;(function( win, $, undefined ){
  
  	var MM = {
  		attr: {
  			init: 'data-tablesaw-minimap'
  		}
  	};
  
  	function createMiniMap( $table ){
  
  		var $btns = $( '<div class="tablesaw-advance minimap">' ),
  			$dotNav = $( '<ul class="tablesaw-advance-dots">' ).appendTo( $btns ),
  			hideDot = 'tablesaw-advance-dots-hide',
  			$headerCells = $table.find( 'thead th' );
  
  		// populate dots
  		$headerCells.each(function(){
  			$dotNav.append( '<li><i></i></li>' );
  		});
  
  		$btns.appendTo( $table.prev( '.tablesaw-bar' ) );
  
  		function showMinimap( $table ) {
  			var mq = $table.attr( MM.attr.init );
  			return !mq || win.matchMedia && win.matchMedia( mq ).matches;
  		}
  
  		function showHideNav(){
  			if( !showMinimap( $table ) ) {
  				$btns.hide();
  				return;
  			}
  			$btns.show();
  
  			// show/hide dots
  			var dots = $dotNav.find( "li" ).removeClass( hideDot );
  			$table.find( "thead th" ).each(function(i){
  				if( $( this ).css( "display" ) === "none" ){
  					dots.eq( i ).addClass( hideDot );
  				}
  			});
  		}
  
  		// run on init and resize
  		showHideNav();
  		$( win ).on( "resize", showHideNav );
  
  
  		$table
  			.bind( "tablesawcolumns.minimap", function(){
  				showHideNav();
  			})
  			.bind( "tablesawdestroy.minimap", function(){
  				var $t = $( this );
  
  				$t.prev( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
  				$( win ).off( "resize", showHideNav );
  
  				$t.unbind( ".minimap" );
  			});
  	}
  
  
  
  	// on tablecreate, init
  	$( document ).on( "tablesawcreate", function( e, Tablesaw ){
  
  		if( ( Tablesaw.mode === 'swipe' || Tablesaw.mode === 'columntoggle' ) && Tablesaw.$table.is( '[ ' + MM.attr.init + ']' ) ){
  			createMiniMap( Tablesaw.$table );
  		}
  
  	} );
  
  }( this, jQuery ));
  
  ;(function( win, $ ) {
  
  	var S = {
  		selectors: {
  			init: 'table[data-tablesaw-mode-switch]'
  		},
  		attributes: {
  			excludeMode: 'data-tablesaw-mode-exclude'
  		},
  		classes: {
  			main: 'tablesaw-modeswitch',
  			toolbar: 'tablesaw-toolbar'
  		},
  		modes: [ 'stack', 'swipe', 'columntoggle' ],
  		init: function( table ) {
  			var $table = $( table ),
  				ignoreMode = $table.attr( S.attributes.excludeMode ),
  				$toolbar = $table.prev( '.tablesaw-bar' ),
  				modeVal = '',
  				$switcher = $( '<div>' ).addClass( S.classes.main + ' ' + S.classes.toolbar ).html(function() {
  					var html = [ '<label>' + Tablesaw.i18n.columns + ':' ],
  						dataMode = $table.attr( 'data-tablesaw-mode' ),
  						isSelected;
  
  					html.push( '<span class="btn btn-small">&#160;<select>' );
  					for( var j=0, k = S.modes.length; j<k; j++ ) {
  						if( ignoreMode && ignoreMode.toLowerCase() === S.modes[ j ] ) {
  							continue;
  						}
  
  						isSelected = dataMode === S.modes[ j ];
  
  						if( isSelected ) {
  							modeVal = S.modes[ j ];
  						}
  
  						html.push( '<option' +
  							( isSelected ? ' selected' : '' ) +
  							' value="' + S.modes[ j ] + '">' + Tablesaw.i18n.modes[ j ] + '</option>' );
  					}
  					html.push( '</select></span></label>' );
  
  					return html.join('');
  				});
  
  			var $otherToolbarItems = $toolbar.find( '.tablesaw-advance' ).eq( 0 );
  			if( $otherToolbarItems.length ) {
  				$switcher.insertBefore( $otherToolbarItems );
  			} else {
  				$switcher.appendTo( $toolbar );
  			}
  
  			$switcher.find( '.btn' ).tablesawbtn();
  			$switcher.find( 'select' ).bind( 'change', S.onModeChange );
  		},
  		onModeChange: function() {
  			var $t = $( this ),
  				$switcher = $t.closest( '.' + S.classes.main ),
  				$table = $t.closest( '.tablesaw-bar' ).nextUntil( $table ).eq( 0 ),
  				val = $t.val();
  
  			$switcher.remove();
  			$table.data( 'table' ).destroy();
  
  			$table.attr( 'data-tablesaw-mode', val );
  			$table.table();
  		}
  	};
  
  	$( win.document ).on( "tablesawcreate", function( e, Tablesaw ) {
  		if( Tablesaw.$table.is( S.selectors.init ) ) {
  			S.init( Tablesaw.table );
  		}
  	});
  
  })( this, jQuery );