PageSourceSearch

https://www.muecke-motorsport.de/templates/content/listetermine/js/tablesaw.jquery.js?639262042549631961

js muecke-motorsport.de collected 2026-10-02 18:32:18 UTC 49,531 bytes, 1,718 lines download raw bytes

vendor: 5,670 bytes, lines 1-194
1/*! Tablesaw - v3.0.1-beta.13 - 2017-03-21
2* https://github.com/filamentgroup/tablesaw
3* Copyright (c) 2017 Filament Group; Licensed MIT */
4// UMD module definition
5// From: https://github.com/umdjs/umd/blob/master/templates/jqueryPlugin.js
6
7(function (factory) {
8	if (typeof define === 'function' && define.amd) {
9			// AMD. Register as an anonymous module.
10			define(['jquery'], factory);
11	} else if (typeof module === 'object' && module.exports) {
12		// Node/CommonJS
13		module.exports = function( root, jQuery ) {
14			if ( jQuery === undefined ) {
15				// require('jQuery') returns a factory that requires window to
16				// build a jQuery instance, we normalize how we use modules
17				// that require this pattern but the window provided is a noop
18				// if it's defined (how jquery works)
19				if ( typeof window !== 'undefined' ) {
20					jQuery = require('jquery');
21				} else {
22					jQuery = require('jquery')(root);
23				}
24			}
25			factory(jQuery);
26			return jQuery;
27		};
28	} else {
29		// Browser globals
30		factory(jQuery);
31	}
32}(function ($) {
33	"use strict";
34
35	var win = typeof window !== "undefined" ? window : this;
36
37var Tablesaw = {
38	i18n: {
39		modes: [ 'Stack', 'Swipe', 'Toggle' ],
40		columns: 'Col<span class=\"a11y-sm\">umn</span>s',
41		columnBtnText: 'Columns',
42		columnsDialogError: 'No eligible columns.',
43		sort: 'Sort'
44	},
45	// cut the mustard
46	mustard: ( 'head' in document ) && // IE9+, Firefox 4+, Safari 5.1+, Mobile Safari 4.1+, Opera 11.5+, Android 2.3+
47		( !window.blackberry || window.WebKitPoint ) && // only WebKit Blackberry (OS 6+)
48		!window.operamini
49};
50
51if( Tablesaw.mustard ) {
52	$( document.documentElement ).addClass( 'tablesaw-enhanced' );
53}
54
55(function() {
56	var pluginName = "tablesaw";
57	var classes = {
58		toolbar: "tablesaw-bar"
59	};
60	var events = {
61		create: "tablesawcreate",
62		destroy: "tablesawdestroy",
63		refresh: "tablesawrefresh",
64		resize: "tablesawresize"
65	};
66	var defaultMode = "stack";
67	var initSelector = "table";
68	var initFilterSelector = "[data-tablesaw],[data-tablesaw-mode],[data-tablesaw-sortable]";
69	var defaultConfig = {};
70
71	Tablesaw.events = events;
72
73	var Table = function( element ) {
74		if( !element ) {
75			throw new Error( "Tablesaw requires an element." );
76		}
77
78		this.table = element;
79		this.$table = $( element );
80
81		// only one <thead> and <tfoot> are allowed, per the specification
82		this.$thead = this.$table.children().filter( "thead" ).eq( 0 );
83
84		// multiple <tbody> are allowed, per the specification
85		this.$tbody = this.$table.children().filter( "tbody" );
86
87		this.mode = this.$table.attr( "data-tablesaw-mode" ) || defaultMode;
88
89		this.init();
90	};
91
92	Table.prototype.init = function() {
93		// assign an id if there is none
94		if ( !this.$table.attr( "id" ) ) {
95			this.$table.attr( "id", pluginName + "-" + Math.round( Math.random() * 10000 ) );
96		}
97
98		this.createToolbar();
99
100		this._initCells();
101
102		this.$table.data( pluginName, this );
103
104		this.$table.trigger( events.create, [ this ] );
105	};
106
107	Table.prototype.getConfig = function( pluginSpecificConfig ) {
108		// shoestring extend doesn’t support arbitrary args
109		var configs = $.extend( defaultConfig, pluginSpecificConfig || {} );
110		return $.extend( configs, typeof TablesawConfig !== "undefined" ? TablesawConfig : {} );
111	};
112
113	Table.prototype._getPrimaryHeaderRow = function() {
114		return this._getHeaderRows().eq( 0 );
115	};
116
117	Table.prototype._getHeaderRows = function() {
118		return this.$thead.children().filter( "tr" ).filter(function() {
119			return !$( this ).is( "[data-tablesaw-ignorerow]" );
120		});
121	};
122
123	Table.prototype._getRowIndex = function( $row ) {
124		return $row.prevAll().length;
125	};
126
127	Table.prototype._getHeaderRowIndeces = function() {
128		var self = this;
129		var indeces = [];
130		this._getHeaderRows().each(function() {
131			indeces.push( self._getRowIndex( $( this ) ) );
132		});
133		return indeces;
134	};
135
136	Table.prototype._getPrimaryHeaderCells = function( $row ) {
137		return ( $row || this._getPrimaryHeaderRow() ).find( "th" );
138	};
139
140	Table.prototype._findPrimaryHeadersForCell = function( cell ) {
141		var $headerRow = this._getPrimaryHeaderRow();
142		var $headers = this._getPrimaryHeaderCells( $headerRow );
143		var headerRowIndex = this._getRowIndex( $headerRow );
144		var results = [];
145
146		for( var rowNumber = 0; rowNumber < this.headerMapping.length; rowNumber++ ) {
147			if( rowNumber === headerRowIndex ) {
148				continue;
149			}
150			for( var colNumber = 0; colNumber < this.headerMapping[ rowNumber ].length; colNumber++ ) {
151				if( this.headerMapping[ rowNumber ][ colNumber ] === cell ) {
152					results.push( $headers[ colNumber ] );
153				}
154			}
155		}
156		return results;
157	};
158
159	// used by init cells
160	Table.prototype.getRows = function() {
161		var self = this;
162		return this.$table.find( "tr" ).filter(function() {
163			return $( this ).closest( "table" ).is( self.$table );
164		});
165	};
166
167	// used by sortable
168	Table.prototype.getBodyRows = function( tbody ) {
169		return ( tbody ? $( tbody ) : this.$tbody ).children().filter( "tr" );
170	};
171
172	Table.prototype.getHeaderCellIndex = function( cell ) {
173		var lookup = this.headerMapping[ 0 ];
174		for( var colIndex = 0; colIndex < lookup.length; colIndex++ ) {
175			if( lookup[ colIndex ] === cell ) {
176				return colIndex;
177			}
178		}
179
180		return -1;
181	};
182
183	Table.prototype._initCells = function() {
184		var $rows = this.getRows();
185		var columnLookup = [];
186
187		$rows.each(function( rowNumber ) {
188			columnLookup[ rowNumber ] = [];
189		});
190
191		$rows.each(function( rowNumber ) {
192			var coltally = 0;
193			var $t = $( this );
194			var children = $t.children();
vendor: 6,717 bytes, lines 195-430
195
196			children.each(function() {
197				var colspan = parseInt( this.getAttribute( "colspan" ), 10 );
198				var rowspan = parseInt( this.getAttribute( "rowspan" ), 10 );
199
200				// set in a previous rowspan
201				while( columnLookup[ rowNumber ][ coltally ] ) {
202					coltally++;
203				}
204
205				columnLookup[ rowNumber ][ coltally ] = this;
206
207				// TODO? both colspan and rowspan
208				if( colspan ) {
209					for( var k = 0; k < colspan - 1; k++ ){
210						coltally++;
211						columnLookup[ rowNumber ][ coltally ] = this;
212					}
213				}
214				if( rowspan ) {
215					for( var j = 1; j < rowspan; j++ ){
216						columnLookup[ rowNumber + j ][ coltally ] = this;
217					}
218				}
219
220				coltally++;
221			});
222		});
223
224		var headerRowIndeces = this._getHeaderRowIndeces();
225		for( var colNumber = 0; colNumber < columnLookup[ 0 ].length; colNumber++ ) {
226			for( var headerIndex = 0, k = headerRowIndeces.length; headerIndex < k; headerIndex++ ) {
227				var headerCol = columnLookup[ headerRowIndeces[ headerIndex ] ][ colNumber ];
228
229				var rowNumber = headerRowIndeces[ headerIndex ];
230				var rowCell;
231
232				if( !headerCol.cells ) {
233					headerCol.cells = [];
234				}
235
236				while( rowNumber < columnLookup.length ) {
237					rowCell = columnLookup[ rowNumber ][ colNumber ];
238
239					if( headerCol !== rowCell ) {
240						headerCol.cells.push( rowCell );
241					}
242
243					rowNumber++;
244				}
245			}
246		}
247
248		this.headerMapping = columnLookup;
249	};
250
251	Table.prototype.refresh = function() {
252		this._initCells();
253
254		this.$table.trigger( events.refresh, [ this ] );
255	};
256
257	Table.prototype.createToolbar = function() {
258		// Insert the toolbar
259		// TODO move this into a separate component
260		var $toolbar = this.$table.prev().filter( '.' + classes.toolbar );
261		if( !$toolbar.length ) {
262			$toolbar = $( '<div>' )
263				.addClass( classes.toolbar )
264				.insertBefore( this.$table );
265		}
266		this.$toolbar = $toolbar;
267
268		if( this.mode ) {
269			this.$toolbar.addClass( 'tablesaw-mode-' + this.mode );
270		}
271	};
272
273	Table.prototype.destroy = function() {
274		// Don’t remove the toolbar. Some of the table features are not yet destroy-friendly.
275		this.$table.prev().filter( '.' + classes.toolbar ).each(function() {
276			this.className = this.className.replace( /\btablesaw-mode\-\w*\b/gi, '' );
277		});
278
279		var tableId = this.$table.attr( 'id' );
280		$( document ).off( "." + tableId );
281		$( window ).off( "." + tableId );
282
283		// other plugins
284		this.$table.trigger( events.destroy, [ this ] );
285
286		this.$table.removeData( pluginName );
287	};
288
289	// Collection method.
290	$.fn[ pluginName ] = function() {
291		return this.each( function() {
292			var $t = $( this );
293
294			if( $t.data( pluginName ) ){
295				return;
296			}
297
298			new Table( this );
299		});
300	};
301
302	var $doc = $( win.document );
303	$doc.on( "enhance.tablesaw", function( e ) {
304		// Cut the mustard
305		if( Tablesaw.mustard ) {
306			$( e.target ).find( initSelector ).filter( initFilterSelector )[ pluginName ]();
307		}
308	});
309
310	// Avoid a resize during scroll:
311	// Some Mobile devices trigger a resize during scroll (sometimes when
312	// doing elastic stretch at the end of the document or from the 
313	// location bar hide)
314	var isScrolling = false;
315	var scrollTimeout;
316	$doc.on( "scroll.tablesaw", function() {
317		isScrolling = true;
318
319		win.clearTimeout( scrollTimeout );
320		scrollTimeout = win.setTimeout(function() {
321			isScrolling = false;
322		}, 300 ); // must be greater than the resize timeout below
323	});
324
325	var resizeTimeout;
326	$( win ).on( "resize", function() {
327		if( !isScrolling ) {
328			win.clearTimeout( resizeTimeout );
329			resizeTimeout = win.setTimeout(function() {
330				$doc.trigger( events.resize );
331			}, 150 ); // must be less than the scrolling timeout above.
332		}
333	});
334
335}());
336
337(function(){
338
339	var classes = {
340		stackTable: 'tablesaw-stack',
341		cellLabels: 'tablesaw-cell-label',
342		cellContentLabels: 'tablesaw-cell-content'
343	};
344
345	var data = {
346		key: 'tablesaw-stack'
347	};
348
349	var attrs = {
350		labelless: 'data-tablesaw-no-labels',
351		hideempty: 'data-tablesaw-hide-empty'
352	};
353
354	var Stack = function( element, tablesaw ) {
355
356		this.tablesaw = tablesaw;
357		this.$table = $( element );
358
359		this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
360		this.hideempty = this.$table.is( '[' + attrs.hideempty + ']' );
361
362		this.$table.data( data.key, this );
363	};
364
365	Stack.prototype.init = function() {
366		this.$table.addClass( classes.stackTable );
367
368		if( this.labelless ) {
369			return;
370		}
371
372		var self = this;
373
374		this.$table.find( "th, td" ).filter(function() {
375			return !$( this ).closest( "thead" ).length;
376		}).filter(function() {
377			return !$( this ).closest( "tr" ).is( "[" + attrs.labelless + "]" ) &&
378				( !self.hideempty || !!$( this ).html() );
379		}).each(function() {
380			var $newHeader = $( document.createElement( "b" ) ).addClass( classes.cellLabels );
381			var $cell = $( this );
382
383			$( self.tablesaw._findPrimaryHeadersForCell( this ) ).each(function( index ) {
384				var $header = $( this.cloneNode( true ) );
385				// TODO decouple from sortable better
386				// Changed from .text() in https://github.com/filamentgroup/tablesaw/commit/b9c12a8f893ec192830ec3ba2d75f062642f935b
387				// to preserve structural html in headers, like <a>
388				var $sortableButton = $header.find( ".tablesaw-sortable-btn" );
389				$header.find( ".tablesaw-sortable-arrow" ).remove();
390
391				// TODO decouple from checkall better
392				var $checkall = $header.find( "[data-tablesaw-checkall]" );
393				$checkall.closest( "label" ).remove();
394				if( $checkall.length ) {
395					$newHeader = $([]);
396					return;
397				}
398
399				if( index > 0 ) {
400					$newHeader.append( document.createTextNode( ", " ) );
401				}
402				$newHeader.append( $sortableButton.length ? $sortableButton[ 0 ].childNodes : $header[ 0 ].childNodes );
403			});
404
405			if( $newHeader.length && !$cell.find( "." + classes.cellContentLabels ).length ) {
406				$cell.wrapInner( "<span class='" + classes.cellContentLabels + "'></span>" );
407			}
408
409			// Update if already exists.
410			var $label = $cell.find( "." + classes.cellLabels );
411			if( !$label.length ) {
412				$cell.prepend( $newHeader );
413			} else { // only if changed
414				$label.replaceWith( $newHeader );
415			}
416		});
417	};
418
419	Stack.prototype.destroy = function() {
420		this.$table.removeClass( classes.stackTable );
421		this.$table.find( '.' + classes.cellLabels ).remove();
422		this.$table.find( '.' + classes.cellContentLabels ).each(function() {
423			$( this ).replaceWith( this.childNodes );
424		});
425	};
426
427	// on tablecreate, init
428	$( document ).on( Tablesaw.events.create, function( e, tablesaw ){
429		if( tablesaw.mode === 'stack' ){
430			var table = new Stack( tablesaw.table, tablesaw );
431			table.init();
432		}
433	}).on( Tablesaw.events.refresh, function( e, tablesaw ){
434		if( tablesaw.mode === 'stack' ){
435			$( tablesaw.table ).data( data.key ).init();
436		}
437	}).on( Tablesaw.events.destroy, function( e, tablesaw ){
438		if( tablesaw.mode === 'stack' ){
439			$( tablesaw.table ).data( data.key ).destroy();
440		}
441	});
442
443}());
444(function() {
445	var pluginName = "tablesawbtn",
446		methods = {
447			_create: function(){
448				return $( this ).each(function() {
449					$( this )
450						.trigger( "beforecreate." + pluginName )[ pluginName ]( "_init" )
451						.trigger( "create." + pluginName );
452				});
453			},
454			_init: function(){
455				var oEl = $( this ),
456					sel = this.getElementsByTagName( "select" )[ 0 ];
457
458				if( sel ) {
459					// TODO next major version: remove .btn-select
460					$( this )
461						.addClass( "btn-select tablesaw-btn-select" )[ pluginName ]( "_select", sel );
462				}
463				return oEl;
464			},
465			_select: function( sel ) {
466				var update = function( oEl, sel ) {
467					var opts = $( sel ).find( "option" );
468					var label = document.createElement( "span" );
469					var el;
470					var children;
471					var found = false;
472
473					label.setAttribute( "aria-hidden", "true" );
474					label.innerHTML = "&#160;";
475
476					opts.each(function() {
477						var opt = this;
478						if( opt.selected ) {
479							label.innerHTML = opt.text;
480						}
481					});
482
483					children = oEl.childNodes;
484					if( opts.length > 0 ){
485						for( var i = 0, l = children.length; i < l; i++ ) {
486							el = children[ i ];
487
488							if( el && el.nodeName.toUpperCase() === "SPAN" ) {
489								oEl.replaceChild( label, el );
490								found = true;
491							}
492						}
493
494						if( !found ) {
495							oEl.insertBefore( label, oEl.firstChild );
496						}
497					}
498				};
499
500				update( this, sel );
501				$( this ).on( "change refresh", function() {
502					update( this, sel );
503				});
504			}
505		};
506
507	// Collection method.
508	$.fn[ pluginName ] = function( arrg, a, b, c ) {
509		return this.each(function() {
510
511			// if it's a method
512			if( arrg && typeof( arrg ) === "string" ){
513				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
514			}
515
516			// don't re-init
517			if( $( this ).data( pluginName + "active" ) ){
518				return $( this );
519			}
520
521			$( this ).data( pluginName + "active", true );
522
523			$.fn[ pluginName ].prototype._create.call( this );
524		});
525	};
526
527	// add methods
528	$.extend( $.fn[ pluginName ].prototype, methods );
529
530}());
531(function(){
532
533	var data = {
534		key: "tablesaw-coltoggle"
535	};
536
537	var ColumnToggle = function( element ) {
538
539		this.$table = $( element );
540
541		if( !this.$table.length ) {
542			return;
543		}
544
545		this.tablesaw = this.$table.data( "tablesaw" );
546
547		this.attributes = {
548			subrow: "data-tablesaw-subrow",
549			ignorerow: "data-tablesaw-ignorerow",
550			btnTarget: 'data-tablesaw-columntoggle-btn-target',
551		};
552
553		this.classes = {
554			columnToggleTable: 'tablesaw-columntoggle',
555			columnBtnContain: 'tablesaw-columntoggle-btnwrap tablesaw-advance',
556			columnBtn: 'tablesaw-columntoggle-btn tablesaw-nav-btn down',
557			popup: 'tablesaw-columntoggle-popup',
558			priorityPrefix: 'tablesaw-priority-',
559			// TODO duplicate class, also in tables.js
560			toolbar: 'tablesaw-bar'
561		};
562
563		this.$headers = this.tablesaw._getPrimaryHeaderCells();
564
565		this.$table.data( data.key, this );
566	};
567
568	ColumnToggle.prototype.init = function() {
569
570		if( !this.$table.length ) {
571			return;
572		}
573
574		var tableId,
575			id,
576			$menuButton,
577			$popup,
578			$menu,
579			$btnContain,
580			self = this;
581
582		this.$table.addClass( this.classes.columnToggleTable );
583
584		tableId = this.$table.attr( "id" );
585		id = tableId + "-popup";
586		$btnContain = $( "<div class='" + this.classes.columnBtnContain + "'></div>" );
587		// TODO next major version: remove .btn
588		$menuButton = $( "<a href='#" + id + "' class='btn tablesaw-btn btn-micro " + this.classes.columnBtn +"' data-popup-link>" +
589										"<span>" + Tablesaw.i18n.columnBtnText + "</span></a>" );
590		$popup = $( "<div class='dialog-table-coltoggle " + this.classes.popup + "' id='" + id + "'></div>" );
591		$menu = $( "<div class='btn-group'></div>" );
592
593		var hasNonPersistentHeaders = false;
594		this.$headers.each( function() {
595			var $this = $( this ),
596				priority = $this.attr("data-tablesaw-priority"),
597				$cells = self.$getCells( this );
598
599			if( priority && priority !== "persist" ) {
600				$cells.addClass( self.classes.priorityPrefix + priority );
601
602				$("<label><input type='checkbox' checked>" + $this.text() + "</label>" )
603					.appendTo( $menu )
604					.children()
605					.first()
606					.data( "tablesaw-header", this );
607
608				hasNonPersistentHeaders = true;
609			}
610		});
611
612		if( !hasNonPersistentHeaders ) {
613			$menu.append( '<label>' + Tablesaw.i18n.columnsDialogError + '</label>' );
614		}
615
616		$menu.appendTo( $popup );
617
618		// bind change event listeners to inputs - TODO: move to a private method?
619		$menu.find( 'input[type="checkbox"]' ).on( "change", function(e) {
620			var checked = e.target.checked;
621
622			var header = self.getHeaderFromCheckbox( e.target );
623			var $cells = self.$getCells( header );
624
625			$cells[ !checked ? "addClass" : "removeClass" ]( "tablesaw-cell-hidden" );
626			$cells[ checked ? "addClass" : "removeClass" ]( "tablesaw-cell-visible" );
627
628			self.updateColspanIgnoredRows( checked, $( header ).add( header.cells ) );
629
630			self.$table.trigger( 'tablesawcolumns' );
631		});
632
633		$menuButton.appendTo( $btnContain );
634
635		var $btnTarget = $( this.$table.attr( this.attributes.btnTarget ) );
636		$btnContain.appendTo( $btnTarget.length ? $btnTarget : this.$table.prev().filter( '.' + this.classes.toolbar ) );
637
638		function closePopup( event ) {
639			// Click came from inside the popup, ignore.
640			if( event && $( event.target ).closest( "." + self.classes.popup ).length ) {
641				return;
642			}
643
644			$( document ).off( 'click.' + tableId );
645			$menuButton.removeClass( 'up' ).addClass( 'down' );
646			$btnContain.removeClass( 'visible' );
647		}
648
649		var closeTimeout;
650		function openPopup() {
651			$btnContain.addClass( 'visible' );
652			$menuButton.removeClass( 'down' ).addClass( 'up' );
653
654			$( document ).off( 'click.' + tableId, closePopup );
655
656			window.clearTimeout( closeTimeout );
657			closeTimeout = window.setTimeout(function() {
658				$( document ).on( 'click.' + tableId, closePopup );
659			}, 15 );
660		}
661
662		$menuButton.on( "click.tablesaw", function( event ) {
663			event.preventDefault();
664
665			if( !$btnContain.is( ".visible" ) ) {
666				openPopup();
667			} else {
668				closePopup();
669			}
670		});
671
672		$popup.appendTo( $btnContain );
673
674		this.$menu = $menu;
675
676		$(window).on( Tablesaw.events.resize + "." + tableId, function(){
677			self.refreshToggle();
678		});
679
680		this.refreshToggle();
681	};
682
683	ColumnToggle.prototype.updateColspanIgnoredRows = function( invisibleColumnCount, $cells ) {
684		this.$table.find( "[" + this.attributes.subrow + "],[" + this.attributes.ignorerow + "]" ).each(function() {
685			var $t = $( this );
686			var $td = $t.find( "td[colspan]" ).eq( 0 );
687			var excludedInvisibleColumns;
688
689			var colspan;
690			var originalColspan;
691			var modifier;
692
693			// increment or decrementing only (from a user triggered column show/hide)
694			if( invisibleColumnCount === true || invisibleColumnCount === false ) {
695				// unless the column being hidden is not included in the colspan
696				modifier = $cells.filter(function() {
697					return this === $td[ 0 ];
698				}).length ? ( invisibleColumnCount ? 1 : -1 ) : 0;
699
700				colspan = parseInt( $td.attr( "colspan" ), 10 ) + modifier;
701			} else {
702				// triggered from a resize or init
703				originalColspan = $td.data( "original-colspan" );
704
705				if( originalColspan ) {
706					colspan = originalColspan;
707				} else {
708					colspan = parseInt( $td.attr( "colspan" ), 10 );
709					$td.data( "original-colspan", colspan );
710				}
711
712				excludedInvisibleColumns = $t.find( "td" ).filter(function() {
713					return this !== $td[ 0 ] && $( this ).css( "display" ) === "none";
714				}).length;
715
716				colspan -= ( invisibleColumnCount - excludedInvisibleColumns );
717			}
718
719			// TODO add a colstart param so that this more appropriately selects colspan elements based on the column being hidden.
720			$td.attr( "colspan", colspan );
721		});
722	};
723
724	ColumnToggle.prototype.$getCells = function( th ) {
725		var self = this;
726		return $( th ).add( th.cells ).filter(function() {
727			var $t = $( this );
728			var $row = $t.parent();
729			var hasColspan = $t.is( "[colspan]" );
730			// no subrows or ignored rows (keep cells in ignored rows that do not have a colspan)
731			return !$row.is( "[" + self.attributes.subrow + "]" ) &&
732				( !$row.is( "[" + self.attributes.ignorerow + "]" ) || !hasColspan );
733		});
734	};
735
736	ColumnToggle.prototype.getHeaderFromCheckbox = function( checkbox ) {
737		return $( checkbox ).data( "tablesaw-header" );
738	};
739
740	ColumnToggle.prototype.refreshToggle = function() {
741		var self = this;
742		var invisibleColumns = 0;
743		this.$menu.find( "input" ).each( function() {
744			var header = self.getHeaderFromCheckbox( this );
745			var isVisible = self.$getCells( header ).eq( 0 ).css( "display" ) === "table-cell";
746			this.checked = isVisible;
747
748			if( !isVisible ) {
749				invisibleColumns++;
750			}
751		});
752
vendor: 9,119 bytes, lines 753-1048
753		this.updateColspanIgnoredRows( invisibleColumns );
754	};
755
756	ColumnToggle.prototype.destroy = function() {
757		this.$table.removeClass( this.classes.columnToggleTable );
758		this.$table.find( 'th, td' ).each(function() {
759			var $cell = $( this );
760			$cell.removeClass( 'tablesaw-cell-hidden' )
761				.removeClass( 'tablesaw-cell-visible' );
762
763			this.className = this.className.replace( /\bui\-table\-priority\-\d\b/g, '' );
764		});
765	};
766
767	// on tablecreate, init
768	$( document ).on( Tablesaw.events.create, function( e, tablesaw ){
769
770		if( tablesaw.mode === 'columntoggle' ){
771			var table = new ColumnToggle( tablesaw.table );
772			table.init();
773		}
774
775	} );
776
777	$( document ).on( Tablesaw.events.destroy, function( e, tablesaw ){
778		if( tablesaw.mode === 'columntoggle' ){
779			$( tablesaw.table ).data( data.key ).destroy();
780		}
781	} );
782
783}());
784;(function() {
785	function getSortValue( cell ) {
786		var text = [];
787		$( cell.childNodes ).each(function() {
788			var $el = $( this );
789			if( $el.is( 'input, select' ) ) {
790				text.push( $el.val() );
791			} else if( $el.is( '.tablesaw-cell-label' ) ) {
792			} else {
793				text.push( ( $el.text() || '' ).replace(/^\s+|\s+$/g, '') );
794			}
795		});
796
797		return text.join( '' );
798	}
799
800	var pluginName = "tablesaw-sortable",
801		initSelector = "table[data-" + pluginName + "]",
802		sortableSwitchSelector = "[data-" + pluginName + "-switch]",
803		attrs = {
804			sortCol: "data-tablesaw-sortable-col",
805			defaultCol: "data-tablesaw-sortable-default-col",
806			numericCol: "data-tablesaw-sortable-numeric",
807			subRow: "data-tablesaw-subrow",
808			ignoreRow: "data-tablesaw-ignorerow"
809		},
810		classes = {
811			head: pluginName + "-head",
812			ascend: pluginName + "-ascending",
813			descend: pluginName + "-descending",
814			switcher: pluginName + "-switch",
815			tableToolbar: 'tablesaw-toolbar',
816			sortButton: pluginName + "-btn"
817		},
818		methods = {
819			_create: function( o ){
820				return $( this ).each(function() {
821					var init = $( this ).data( pluginName + "-init" );
822					if( init ) {
823						return false;
824					}
825					$( this )
826						.data( pluginName + "-init", true )
827						.trigger( "beforecreate." + pluginName )
828						[ pluginName ]( "_init" , o )
829						.trigger( "create." + pluginName );
830				});
831			},
832			_init: function(){
833				var el = $( this ),
834					heads,
835					$switcher;
836
837				function addClassToHeads( h ){
838					$.each( h , function( i , v ){
839						$( v ).addClass( classes.head );
840					});
841				}
842
843				function makeHeadsActionable( h , fn ){
844					$.each( h , function( i , col ){
845						var b = $( "<button class='" + classes.sortButton + "'/>" );
846						b.on( "click" , { col: col } , fn );
847						$( col ).wrapInner( b ).find( "button" ).append( "<span class='tablesaw-sortable-arrow'>" );
848					});
849				}
850
851				function clearOthers( headcells ){
852					$.each( headcells , function( i , v ){
853						var col = $( v );
854						col.removeAttr( attrs.defaultCol );
855						col.removeClass( classes.ascend );
856						col.removeClass( classes.descend );
857					});
858				}
859
860				function headsOnAction( e ){
861					if( $( e.target ).is( 'a[href]' ) ) {
862						return;
863					}
864
865					e.stopPropagation();
866					var headCell = $( e.target ).closest( "[" + attrs.sortCol + "]" ),
867						v = e.data.col,
868						newSortValue = heads.index( headCell[0] );
869
870					clearOthers( headCell.closest( "thead" ).find( "th" ).filter(function() {
871						return this !== headCell[ 0 ];
872					}) );
873					if( headCell.is( "." + classes.descend ) || !headCell.is( "." + classes.ascend ) ){
874						el[ pluginName ]( "sortBy" , v , true);
875						newSortValue += '_asc';
876					} else {
877						el[ pluginName ]( "sortBy" , v );
878						newSortValue += '_desc';
879					}
880					if( $switcher ) {
881						$switcher.find( 'select' ).val( newSortValue ).trigger( 'refresh' );
882					}
883
884					e.preventDefault();
885				}
886
887				function handleDefault( heads ){
888					$.each( heads , function( idx , el ){
889						var $el = $( el );
890						if( $el.is( "[" + attrs.defaultCol + "]" ) ){
891							if( !$el.is( "." + classes.descend ) ) {
892								$el.addClass( classes.ascend );
893							}
894						}
895					});
896				}
897
898				function addSwitcher( heads ){
899					$switcher = $( '<div>' ).addClass( classes.switcher ).addClass( classes.tableToolbar );
900
901					var html = [ '<label>' + Tablesaw.i18n.sort + ':' ];
902
903					// TODO next major version: remove .btn
904					html.push( '<span class="btn tablesaw-btn"><select>' );
905					heads.each(function( j ) {
906						var $t = $( this );
907						var isDefaultCol = $t.is( "[" + attrs.defaultCol + "]" );
908						var isDescending = $t.is( "." + classes.descend );
909
910						var hasNumericAttribute = $t.is( '[' + attrs.numericCol + ']' );
911						var numericCount = 0;
912						// Check only the first four rows to see if the column is numbers.
913						var numericCountMax = 5;
914
915						$( this.cells.slice( 0, numericCountMax ) ).each(function() {
916							if( !isNaN( parseInt( getSortValue( this ), 10 ) ) ) {
917								numericCount++;
918							}
919						});
920						var isNumeric = numericCount === numericCountMax;
921						if( !hasNumericAttribute ) {
922							$t.attr( attrs.numericCol, isNumeric ? "" : "false" );
923						}
924
925						html.push( '<option' + ( isDefaultCol && !isDescending ? ' selected' : '' ) + ' value="' + j + '_asc">' + $t.text() + ' ' + ( isNumeric ? '&#x2191;' : '(A-Z)' ) + '</option>' );
926						html.push( '<option' + ( isDefaultCol && isDescending ? ' selected' : '' ) + ' value="' + j + '_desc">' + $t.text() + ' ' + ( isNumeric ? '&#x2193;' : '(Z-A)' ) + '</option>' );
927					});
928					html.push( '</select></span></label>' );
929
930					$switcher.html( html.join('') );
931
932					var $toolbar = el.prev().filter( '.tablesaw-bar' ),
933						$firstChild = $toolbar.children().eq( 0 );
934
935					if( $firstChild.length ) {
936						$switcher.insertBefore( $firstChild );
937					} else {
938						$switcher.appendTo( $toolbar );
939					}
940					$switcher.find( '.tablesaw-btn' ).tablesawbtn();
941					$switcher.find( 'select' ).on( 'change', function() {
942						var val = $( this ).val().split( '_' ),
943							head = heads.eq( val[ 0 ] );
944
945						clearOthers( head.siblings() );
946						el[ pluginName ]( 'sortBy', head.get( 0 ), val[ 1 ] === 'asc' );
947					});
948				}
949
950				el.addClass( pluginName );
951
952				heads = el.children().filter( "thead" ).find( "th[" + attrs.sortCol + "]" );
953
954				addClassToHeads( heads );
955				makeHeadsActionable( heads , headsOnAction );
956				handleDefault( heads );
957
958				if( el.is( sortableSwitchSelector ) ) {
959					addSwitcher( heads );
960				}
961			},
962			sortRows: function( rows, colNum, ascending, col, tbody ){
963				function convertCells( cellArr, belongingToTbody ){
964					var cells = [];
965					$.each( cellArr, function( i , cell ){
966						var row = cell.parentNode;
967						var $row = $( row );
968						// next row is a subrow
969						var subrows = [];
970						var $next = $row.next();
971						while( $next.is( "[" + attrs.subRow + "]" ) ) {
972							subrows.push( $next[ 0 ] );
973							$next = $next.next();
974						}
975
976						var tbody = row.parentNode;
977
978						// current row is a subrow
979						if( $row.is( "[" + attrs.subRow + "]" ) ) {
980						} else if( tbody === belongingToTbody ) {
981							cells.push({
982								element: cell,
983								cell: getSortValue( cell ),
984								row: row,
985								subrows: subrows.length ? subrows : null,
986								ignored: $row.is( "[" + attrs.ignoreRow + "]" )
987							});
988						}
989					});
990					return cells;
991				}
992
993				function getSortFxn( ascending, forceNumeric ){
994					var fn,
995						regex = /[^\-\+\d\.]/g;
996					if( ascending ){
997						fn = function( a , b ){
998							if( a.ignored || b.ignored ) {
999								return 0;
1000							}
1001							if( forceNumeric ) {
1002								return parseFloat( a.cell.replace( regex, '' ) ) - parseFloat( b.cell.replace( regex, '' ) );
1003							} else {
1004								return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
1005							}
1006						};
1007					} else {
1008						fn = function( a , b ){
1009							if( a.ignored || b.ignored ) {
1010								return 0;
1011							}
1012							if( forceNumeric ) {
1013								return parseFloat( b.cell.replace( regex, '' ) ) - parseFloat( a.cell.replace( regex, '' ) );
1014							} else {
1015								return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
1016							}
1017						};
1018					}
1019					return fn;
1020				}
1021
1022				function convertToRows( sorted ) {
1023					var newRows = [], i, l;
1024					for( i = 0, l = sorted.length ; i < l ; i++ ){
1025						newRows.push( sorted[ i ].row );
1026						if( sorted[ i ].subrows ) {
1027							newRows.push( sorted[ i ].subrows );
1028						}
1029					}
1030					return newRows;
1031				}
1032
1033				var fn;
1034				var sorted;
1035				var cells = convertCells( col.cells, tbody );
1036
1037				var customFn = $( col ).data( 'tablesaw-sort' );
1038
1039				fn = ( customFn && typeof customFn === "function" ? customFn( ascending ) : false ) ||
1040					getSortFxn( ascending, $( col ).is( '[' + attrs.numericCol + ']' ) && !$( col ).is( '[' + attrs.numericCol + '="false"]' ) );
1041
1042				sorted = cells.sort( fn );
1043
1044				rows = convertToRows( sorted );
1045
1046				return rows;
1047			},
1048			makeColDefault: function( col , a ){
1049				var c = $( col );
1050				c.attr( attrs.defaultCol , "true" );
1051				if( a ){
1052					c.removeClass( classes.descend );
1053					c.addClass( classes.ascend );
1054				} else {
1055					c.removeClass( classes.ascend );
1056					c.addClass( classes.descend );
1057				}
1058			},
1059			sortBy: function( col , ascending ){
1060				var el = $( this );
1061				var colNum;
1062				var tbl = el.data( "tablesaw" );
1063				tbl.$tbody.each(function() {
1064					var tbody = this;
1065					var $tbody = $( this );
1066					var rows = tbl.getBodyRows( tbody );
1067					var sortedRows;
1068					var map = tbl.headerMapping[ 0 ];
1069					var j, k;
1070
1071					// find the column number that we’re sorting
1072					for( j = 0, k = map.length; j < k; j++ ) {
1073						if( map[ j ] === col ) {
1074							colNum = j;
1075							break;
1076						}
1077					}
1078
1079					sortedRows = el[ pluginName ]( "sortRows" , rows, colNum, ascending, col, tbody );
1080
1081					// replace Table rows
1082					for( j = 0, k = sortedRows.length; j < k; j++ ) {
1083						$tbody.append( sortedRows[ j ] );
1084					}
1085				});
1086
1087				el[ pluginName ]( "makeColDefault" , col , ascending );
1088
1089				el.trigger( "tablesaw-sorted" );
1090			}
1091		};
1092
1093	// Collection method.
1094	$.fn[ pluginName ] = function( arrg ) {
1095		var args = Array.prototype.slice.call( arguments , 1),
1096			returnVal;
1097
1098		// if it's a method
1099		if( arrg && typeof( arrg ) === "string" ){
1100			returnVal = $.fn[ pluginName ].prototype[ arrg ].apply( this[0], args );
1101			return (typeof returnVal !== "undefined")? returnVal:$(this);
1102		}
1103		// check init
1104		if( !$( this ).data( pluginName + "-active" ) ){
1105			$( this ).data( pluginName + "-active", true );
1106			$.fn[ pluginName ].prototype._create.call( this , arrg );
1107		}
1108		return $(this);
1109	};
1110	// add methods
1111	$.extend( $.fn[ pluginName ].prototype, methods );
1112
1113	$( document ).on( Tablesaw.events.create, function( e, Tablesaw ) {
1114		if( Tablesaw.$table.is( initSelector ) ) {
1115			Tablesaw.$table[ pluginName ]();
1116		}
1117	});
1118
1119}());
1120
1121(function(){
1122
1123	var classes = {
1124		// TODO duplicate class, also in tables.js
1125		toolbar: "tablesaw-bar",
1126		hideBtn: "disabled",
1127		persistWidths: "tablesaw-fix-persist",
1128		allColumnsVisible: 'tablesaw-all-cols-visible'
1129	};
1130	var attrs = {
1131		disableTouchEvents: "data-tablesaw-no-touch"
1132	};
1133
1134	function createSwipeTable( tbl, $table ){
1135		var $btns = $( "<div class='tablesaw-advance'></div>" );
1136		// TODO next major version: remove .btn
1137		var $prevBtn = $( "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro left' title='Previous Column'></a>" ).appendTo( $btns );
1138		// TODO next major version: remove .btn
1139		var $nextBtn = $( "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro right' title='Next Column'></a>" ).appendTo( $btns );
1140
1141		var $headerCells = tbl._getPrimaryHeaderCells();
1142		var $headerCellsNoPersist = $headerCells.not( '[data-tablesaw-priority="persist"]' );
1143		var headerWidths = [];
1144		var $head = $( document.head || 'head' );
1145		var tableId = $table.attr( 'id' );
1146
1147		if( !$headerCells.length ) {
1148			throw new Error( "tablesaw swipe: no header cells found. Are you using <th> inside of <thead>?" );
1149		}
1150
1151		$table.addClass( "tablesaw-swipe" );
1152
1153		// Calculate initial widths
1154		$headerCells.each(function() {
1155			var width = this.offsetWidth;
1156			headerWidths.push( width );
1157		});
1158
1159		$btns.appendTo( $table.prev().filter( '.tablesaw-bar' ) );
1160
1161		if( !tableId ) {
1162			tableId = 'tableswipe-' + Math.round( Math.random() * 10000 );
1163			$table.attr( 'id', tableId );
1164		}
1165
1166		function $getCells( headerCell ) {
1167			return $( headerCell.cells ).add( headerCell );
1168		}
1169
1170		function showColumn( headerCell ) {
1171			$getCells( headerCell ).removeClass( 'tablesaw-cell-hidden' );
1172		}
1173
1174		function hideColumn( headerCell ) {
1175			$getCells( headerCell ).addClass( 'tablesaw-cell-hidden' );
1176		}
1177
1178		function persistColumn( headerCell ) {
1179			$getCells( headerCell ).addClass( 'tablesaw-cell-persist' );
1180		}
1181
1182		function isPersistent( headerCell ) {
1183			return $( headerCell ).is( '[data-tablesaw-priority="persist"]' );
1184		}
1185
1186		function unmaintainWidths() {
1187			$table.removeClass( classes.persistWidths );
1188			$( '#' + tableId + '-persist' ).remove();
1189		}
1190
1191		function maintainWidths() {
1192			var prefix = '#' + tableId + '.tablesaw-swipe ',
1193				styles = [],
1194				tableWidth = $table.width(),
1195				hash = [],
1196				newHash;
1197
1198			// save persistent column widths (as long as they take up less than 75% of table width)
1199			$headerCells.each(function( index ) {
1200				var width;
1201				if( isPersistent( this ) ) {
1202					width = this.offsetWidth;
1203
1204					if( width < tableWidth * 0.75 ) {
1205						hash.push( index + '-' + width );
1206						styles.push( prefix + ' .tablesaw-cell-persist:nth-child(' + ( index + 1 ) + ') { width: ' + width + 'px; }' );
1207					}
1208				}
1209			});
1210			newHash = hash.join( '_' );
1211
1212			if( styles.length ) {
1213				$table.addClass( classes.persistWidths );
1214				var $style = $( '#' + tableId + '-persist' );
1215				// If style element not yet added OR if the widths have changed
1216				if( !$style.length || $style.data( 'tablesaw-hash' ) !== newHash ) {
1217					// Remove existing
1218					$style.remove();
1219
1220					$( '<style>' + styles.join( "\n" ) + '</style>' )
1221						.attr( 'id', tableId + '-persist' )
1222						.data( 'tablesaw-hash', newHash )
1223						.appendTo( $head );
1224				}
1225			}
1226		}
1227
1228		function getNext(){
1229			var next = [],
1230				checkFound;
1231
1232			$headerCellsNoPersist.each(function( i ) {
1233				var $t = $( this ),
1234					isHidden = $t.css( "display" ) === "none" || $t.is( ".tablesaw-cell-hidden" );
1235
1236				if( !isHidden && !checkFound ) {
1237					checkFound = true;
1238					next[ 0 ] = i;
1239				} else if( isHidden && checkFound ) {
1240					next[ 1 ] = i;
1241
1242					return false;
1243				}
1244			});
1245
1246			return next;
1247		}
1248
1249		function getPrev(){
1250			var next = getNext();
1251			return [ next[ 1 ] - 1 , next[ 0 ] - 1 ];
1252		}
1253
1254		function nextpair( fwd ){
1255			return fwd ? getNext() : getPrev();
1256		}
1257
1258		function canAdvance( pair ){
1259			return pair[ 1 ] > -1 && pair[ 1 ] < $headerCellsNoPersist.length;
1260		}
1261
1262		function matchesMedia() {
1263			var matchMedia = $table.attr( "data-tablesaw-swipe-media" );
1264			return !matchMedia || ( "matchMedia" in win ) && win.matchMedia( matchMedia ).matches;
1265		}
1266
1267		function fakeBreakpoints() {
1268			if( !matchesMedia() ) {
1269				return;
1270			}
1271
1272			var	containerWidth = $table.parent().width(),
1273				persist = [],
1274				sum = 0,
1275				sums = [],
1276				visibleNonPersistantCount = $headerCells.length;
1277
1278			$headerCells.each(function( index ) {
1279				var $t = $( this ),
1280					isPersist = $t.is( '[data-tablesaw-priority="persist"]' );
1281
1282				persist.push( isPersist );
1283				sum += headerWidths[ index ];
1284				sums.push( sum );
1285
1286				// is persistent or is hidden
1287				if( isPersist || sum > containerWidth ) {
1288					visibleNonPersistantCount--;
1289				}
1290			});
1291
1292			// We need at least one column to swipe.
1293			var needsNonPersistentColumn = visibleNonPersistantCount === 0;
1294
1295			$headerCells.each(function( index ) {
1296				if( persist[ index ] ) {
1297
1298					// for visual box-shadow
1299					persistColumn( this );
1300					return;
1301				}
1302
1303				if( sums[ index ] <= containerWidth || needsNonPersistentColumn ) {
1304					needsNonPersistentColumn = false;
1305					showColumn( this );
1306				} else {
1307					hideColumn( this );
1308				}
1309			});
1310
1311			unmaintainWidths();
1312			$table.trigger( 'tablesawcolumns' );
1313		}
1314
1315		function advance( fwd ){
1316			var pair = nextpair( fwd );
1317			if( canAdvance( pair ) ){
1318				if( isNaN( pair[ 0 ] ) ){
1319					if( fwd ){
1320						pair[0] = 0;
1321					}
1322					else {
1323						pair[0] = $headerCellsNoPersist.length - 1;
1324					}
1325				}
1326
1327				maintainWidths();
1328
1329				hideColumn( $headerCellsNoPersist.get( pair[ 0 ] ) );
1330				showColumn( $headerCellsNoPersist.get( pair[ 1 ] ) );
1331
1332				$table.trigger( 'tablesawcolumns' );
1333			}
1334		}
1335
1336		$prevBtn.add( $nextBtn ).on( "click", function( e ){
1337			advance( !!$( e.target ).closest( $nextBtn ).length );
1338			e.preventDefault();
1339		});
1340
1341		function getCoord( event, key ) {
1342			return ( event.touches || event.originalEvent.touches )[ 0 ][ key ];
1343		}
1344
1345		if( !$table.is( "[" + attrs.disableTouchEvents + "]" ) ) {
1346
1347			$table
1348				.on( "touchstart.swipetoggle", function( e ){
1349					var originX = getCoord( e, 'pageX' );
1350					var originY = getCoord( e, 'pageY' );
1351					var x;
1352					var y;
1353					var scrollTop = window.pageYOffset;
1354
1355					$( win ).off( Tablesaw.events.resize, fakeBreakpoints );
1356
1357					$( this )
1358						.on( "touchmove.swipetoggle", function( e ){
1359							x = getCoord( e, 'pageX' );
1360							y = getCoord( e, 'pageY' );
1361						})
1362						.on( "touchend.swipetoggle", function() {
1363							var cfg = tbl.getConfig({
1364								swipeHorizontalThreshold: 30,
1365								swipeVerticalThreshold: 30
1366							});
1367
1368							// This config code is a little awkward because shoestring doesn’t support deep $.extend
1369							// Trying to work around when devs only override one of (not both) horizontalThreshold or
1370							// verticalThreshold in their TablesawConfig.
1371							var verticalThreshold = cfg.swipe ? cfg.swipe.verticalThreshold : cfg.swipeVerticalThreshold;
1372							var horizontalThreshold = cfg.swipe ? cfg.swipe.horizontalThreshold : cfg.swipeHorizontalThreshold;
1373
1374							var isPageScrolled = Math.abs( window.pageYOffset - scrollTop ) >= verticalThreshold;
1375							var isVerticalSwipe = Math.abs( y - originY ) >= verticalThreshold;
1376
1377							if( !isVerticalSwipe && !isPageScrolled ) {
1378								if( x - originX < -1 * horizontalThreshold ){
1379									advance( true );
1380								}
1381								if( x - originX > horizontalThreshold ){
1382									advance( false );
1383								}
1384							}
1385
1386							window.setTimeout(function() {
1387								$( win ).on( Tablesaw.events.resize, fakeBreakpoints );
1388							}, 300);
1389
1390							$( this ).off( "touchmove.swipetoggle touchend.swipetoggle" );
1391						});
1392				});
1393		}
1394
1395		$table
1396			.on( "tablesawcolumns.swipetoggle", function(){
1397				var canGoPrev = canAdvance( getPrev() );
1398				var canGoNext = canAdvance( getNext() );
1399				$prevBtn[ canGoPrev ? "removeClass" : "addClass" ]( classes.hideBtn );
1400				$nextBtn[ canGoNext ? "removeClass" : "addClass" ]( classes.hideBtn );
1401
1402				$prevBtn.closest( "." + classes.toolbar )[ !canGoPrev && !canGoNext ? 'addClass' : 'removeClass' ]( classes.allColumnsVisible );
1403			})
1404			.on( "tablesawnext.swipetoggle", function(){
1405				advance( true );
1406			} )
1407			.on( "tablesawprev.swipetoggle", function(){
1408				advance( false );
1409			} )
1410			.on( Tablesaw.events.destroy + ".swipetoggle", function(){
1411				var $t = $( this );
1412
1413				$t.removeClass( 'tablesaw-swipe' );
1414				$t.prev().filter( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
1415				$( win ).off( Tablesaw.events.resize, fakeBreakpoints );
1416
1417				$t.off( ".swipetoggle" );
1418			})
1419			.on( Tablesaw.events.refresh, function() {
1420				// manual refresh
1421				headerWidths = [];
1422				$headerCells.each(function() {
1423					var width = this.offsetWidth;
1424					headerWidths.push( width );
1425				});
1426
1427				fakeBreakpoints();
1428			});
1429
1430		fakeBreakpoints();
1431		$( win ).on( Tablesaw.events.resize, fakeBreakpoints );
1432	}
1433
1434	// on tablecreate, init
1435	$( document ).on( Tablesaw.events.create, function( e, tablesaw ){
1436		if( tablesaw.mode === 'swipe' ){
1437			createSwipeTable( tablesaw, tablesaw.$table );
1438		}
1439
1440	} );
1441
1442}());
1443
1444;(function(){
1445
1446	var MiniMap = {
1447		attr: {
1448			init: 'data-tablesaw-minimap'
1449		}
1450	};
1451
1452	function createMiniMap( $table ){
1453
1454		var $btns = $( '<div class="tablesaw-advance minimap">' ),
1455			$dotNav = $( '<ul class="tablesaw-advance-dots">' ).appendTo( $btns ),
1456			hideDot = 'tablesaw-advance-dots-hide',
1457			$headerCells = $table.find( 'thead th' );
1458
1459		// populate dots
1460		$headerCells.each(function(){
1461			$dotNav.append( '<li><i></i></li>' );
1462		});
1463
1464		$btns.appendTo( $table.prev().filter( '.tablesaw-bar' ) );
1465
1466		function showMinimap( $table ) {
1467			var mq = $table.attr( MiniMap.attr.init );
1468			return !mq || win.matchMedia && win.matchMedia( mq ).matches;
1469		}
1470
1471		function showHideNav(){
1472			if( !showMinimap( $table ) ) {
1473				$btns.css( "display", "none" );
1474				return;
1475			}
1476			$btns.css( "display", "block" );
1477
1478			// show/hide dots
1479			var dots = $dotNav.find( "li" ).removeClass( hideDot );
1480			$table.find( "thead th" ).each(function(i){
1481				if( $( this ).css( "display" ) === "none" ){
1482					dots.eq( i ).addClass( hideDot );
1483				}
1484			});
1485		}
1486
1487		// run on init and resize
1488		showHideNav();
1489		$( win ).on( Tablesaw.events.resize, showHideNav );
1490
1491
1492		$table
1493			.on( "tablesawcolumns.minimap", function(){
1494				showHideNav();
1495			})
1496			.on( Tablesaw.events.destroy + ".minimap", function(){
1497				var $t = $( this );
1498
1499				$t.prev().filter( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
1500				$( win ).off( Tablesaw.events.resize, showHideNav );
1501
1502				$t.off( ".minimap" );
1503			});
1504	}
1505
1506
1507
1508	// on tablecreate, init
1509	$( document ).on( Tablesaw.events.create, function( e, tablesaw ){
1510
1511		if( ( tablesaw.mode === 'swipe' || tablesaw.mode === 'columntoggle' ) && tablesaw.$table.is( '[ ' + MiniMap.attr.init + ']' ) ){
1512			createMiniMap( tablesaw.$table );
1513		}
1514
1515	} );
1516
1517}());
1518
1519;(function() {
1520
1521	var S = {
1522		selectors: {
1523			init: 'table[data-tablesaw-mode-switch]'
1524		},
1525		attributes: {
1526			excludeMode: 'data-tablesaw-mode-exclude'
1527		},
1528		classes: {
1529			main: 'tablesaw-modeswitch',
1530			toolbar: 'tablesaw-toolbar'
1531		},
1532		modes: [ 'stack', 'swipe', 'columntoggle' ],
1533		init: function( table ) {
1534			var $table = $( table ),
1535				ignoreMode = $table.attr( S.attributes.excludeMode ),
1536				$toolbar = $table.prev().filter( '.tablesaw-bar' ),
1537				modeVal = '',
1538				$switcher = $( '<div>' ).addClass( S.classes.main + ' ' + S.classes.toolbar );
1539
1540			var html = [ '<label>' + Tablesaw.i18n.columns + ':' ],
1541				dataMode = $table.attr( 'data-tablesaw-mode' ),
1542				isSelected;
1543
1544			// TODO next major version: remove .btn
1545			html.push( '<span class="btn tablesaw-btn"><select>' );
1546			for( var j=0, k = S.modes.length; j<k; j++ ) {
1547				if( ignoreMode && ignoreMode.toLowerCase() === S.modes[ j ] ) {
1548					continue;
1549				}
1550
1551				isSelected = dataMode === S.modes[ j ];
1552
1553				if( isSelected ) {
1554					modeVal = S.modes[ j ];
1555				}
1556
1557				html.push( '<option' +
1558					( isSelected ? ' selected' : '' ) +
1559					' value="' + S.modes[ j ] + '">' + Tablesaw.i18n.modes[ j ] + '</option>' );
1560			}
1561			html.push( '</select></span></label>' );
1562
1563			$switcher.html( html.join( '' ) );
1564
1565			var $otherToolbarItems = $toolbar.find( '.tablesaw-advance' ).eq( 0 );
1566			if( $otherToolbarItems.length ) {
1567				$switcher.insertBefore( $otherToolbarItems );
1568			} else {
1569				$switcher.appendTo( $toolbar );
1570			}
1571
1572			$switcher.find( '.tablesaw-btn' ).tablesawbtn();
1573			$switcher.find( 'select' ).on( 'change', S.onModeChange );
1574		},
1575		onModeChange: function() {
1576			var $t = $( this ),
1577				$switcher = $t.closest( '.' + S.classes.main ),
1578				$table = $t.closest( '.tablesaw-bar' ).next().eq( 0 ),
1579				val = $t.val();
1580
1581			$switcher.remove();
1582			$table.data( 'tablesaw' ).destroy();
1583
1584			$table.attr( 'data-tablesaw-mode', val );
1585			$table.tablesaw();
1586		}
1587	};
1588
1589	$( win.document ).on( Tablesaw.events.create, function( e, Tablesaw ) {
1590		if( Tablesaw.$table.is( S.selectors.init ) ) {
1591			S.init( Tablesaw.table );
1592		}
1593	});
1594
1595})();
1596(function(){
1597	var pluginName = "tablesawCheckAll";
1598
1599	function CheckAll( tablesaw ) {
1600		this.tablesaw = tablesaw;
1601		this.$table = tablesaw.$table;
1602
1603		this.attr = "data-tablesaw-checkall";
1604		this.checkAllSelector = "[" + this.attr + "]";
1605		this.forceCheckedSelector = "[" + this.attr + "-checked]";
1606		this.forceUncheckedSelector = "[" + this.attr + "-unchecked]";
1607		this.checkboxSelector = "input[type=\"checkbox\"]";
1608
1609		this.$triggers = null;
1610		this.$checkboxes = null;
1611
1612		if( this.$table.data( pluginName ) ) {
1613			return;
1614		}
1615		this.$table.data( pluginName, this );
1616		this.init();
1617	}
1618
1619	CheckAll.prototype._filterCells = function( $checkboxes ) {
1620		return $checkboxes.filter(function() {
1621			return !$( this ).closest( "tr" ).is( "[data-tablesaw-subrow],[data-tablesaw-ignorerow]" );
1622		}).find( this.checkboxSelector ).not( this.checkAllSelector );
1623	};
1624
1625	// With buttons you can use a scoping selector like: data-tablesaw-checkall="#my-scoped-id input[type='checkbox']"
1626	CheckAll.prototype.getCheckboxesForButton = function( button ) {
1627		return this._filterCells( $( $( button ).attr( this.attr ) ) );
1628	};
1629
1630	CheckAll.prototype.getCheckboxesForCheckbox = function( checkbox ) {
1631		return this._filterCells( $( $( checkbox ).closest( "th" )[ 0 ].cells ) );
1632	};
1633
1634	CheckAll.prototype.init = function() {
1635		var self = this;
1636		this.$table.find( this.checkAllSelector ).each(function() {
1637			var $trigger = $( this );
1638			if( $trigger.is( self.checkboxSelector ) ) {
1639				self.addCheckboxEvents( this );
1640			} else {
1641				self.addButtonEvents( this );
1642			}
1643		});
1644	};
1645
1646	CheckAll.prototype.addButtonEvents = function( trigger ) {
1647		var self = this;
1648
1649		// Update body checkboxes when header checkbox is changed
1650		$( trigger ).on( "click", function( event ) {
1651			event.preventDefault();
1652
1653			var $checkboxes = self.getCheckboxesForButton( this );
1654
1655			var allChecked = true;
1656			$checkboxes.each(function() {
1657				if( !this.checked ) {
1658					allChecked = false;
1659				}
1660			});
1661
1662			var setChecked;
1663			if( $( this ).is( self.forceCheckedSelector ) ) {
1664				setChecked = true;
1665			} else if( $( this ).is( self.forceUncheckedSelector ) ) {
1666				setChecked = false;
1667			} else {
1668				setChecked = allChecked ? false : true;
1669			}
1670
1671			$checkboxes.each(function() {
1672				this.checked = setChecked;
1673
1674				$( this ).trigger( "change." + pluginName );
1675			});
1676		});
1677	};
1678
1679	CheckAll.prototype.addCheckboxEvents = function( trigger ) {
1680		var self = this;
1681
1682		// Update body checkboxes when header checkbox is changed
1683		$( trigger ).on( "change", function() {
1684			var setChecked = this.checked;
1685
1686			self.getCheckboxesForCheckbox( this ).each(function() {
1687				this.checked = setChecked;
1688			});
1689		});
1690
1691		var $checkboxes = self.getCheckboxesForCheckbox( trigger );
1692
1693		// Update header checkbox when body checkboxes are changed
1694		$checkboxes.on( "change." + pluginName, function() {
1695			var checkedCount = 0;
1696			$checkboxes.each(function() {
1697				if( this.checked ) {
1698					checkedCount++;
1699				}
1700			});
1701
1702			var allSelected = checkedCount === $checkboxes.length;
1703
1704			trigger.checked = allSelected;
1705
1706			// only indeterminate if some are selected (not all and not none)
1707			trigger.indeterminate = checkedCount !== 0 && !allSelected;
1708		});
1709	};
1710
1711	// on tablecreate, init
1712	$( document ).on( Tablesaw.events.create, function( e, tablesaw ){
1713		new CheckAll( tablesaw );
1714	});
1715
1716}());
1717
1718}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.