PageSourceSearch

https://svll.ca/wp-content/plugins/bbpowerpack/assets/js/tablesaw.js?ver=2.0.1

js svll.ca collected 2026-10-01 23:54:39 UTC 33,824 bytes, 1,249 lines download raw bytes

1/*! Tablesaw - v2.0.1 - 2015-10-09
2* https://github.com/filamentgroup/tablesaw
3* Copyright (c) 2015 Filament Group; Licensed MIT */
4/*
5* tablesaw: A set of plugins for responsive tables
6* Stack and Column Toggle tables
7* Copyright (c) 2013 Filament Group, Inc.
8* MIT License
9*/
10
11if( typeof Tablesaw === "undefined" ) {
12	Tablesaw = {
13		i18n: {
14			modes: [ 'Stack', 'Swipe', 'Toggle' ],
15			columns: 'Col<span class=\"a11y-sm\">umn</span>s',
16			columnBtnText: 'Columns',
17			columnsDialogError: 'No eligible columns.',
18			sort: 'Sort'
19		},
20		// cut the mustard
21		mustard: 'querySelector' in document &&
22			( !window.blackberry || window.WebKitPoint ) &&
23			!window.operamini
24	};
25}
26if( !Tablesaw.config ) {
27	Tablesaw.config = {};
28}
29if( Tablesaw.mustard ) {
30	jQuery( document.documentElement ).addClass( 'tablesaw-enhanced' );
31}
32
33;(function( $ ) {
34	var pluginName = "table",
35		classes = {
36			toolbar: "tablesaw-bar"
37		},
38		events = {
39			create: "tablesawcreate",
40			destroy: "tablesawdestroy",
41			refresh: "tablesawrefresh"
42		},
43		defaultMode = "stack",
44		initSelector = "table[data-tablesaw-mode],table[data-tablesaw-sortable]";
45
46	var Table = function( element ) {
47		if( !element ) {
48			throw new Error( "Tablesaw requires an element." );
49		}
50
51		this.table = element;
52		this.$table = $( element );
53
54		this.mode = this.$table.attr( "data-tablesaw-mode" ) || defaultMode;
55
56		this.init();
57	};
58
59	Table.prototype.init = function() {
60		// assign an id if there is none
61		if ( !this.$table.attr( "id" ) ) {
62			this.$table.attr( "id", pluginName + "-" + Math.round( Math.random() * 10000 ) );
63		}
64
65		this.createToolbar();
66
67		var colstart = this._initCells();
68
69		this.$table.trigger( events.create, [ this, colstart ] );
70	};
71
72	Table.prototype._initCells = function() {
73		var colstart,
74			thrs = this.table.querySelectorAll( "thead tr" ),
75			self = this;
76
77		$( thrs ).each( function(){
78			var coltally = 0;
79
80			$( this ).children().each( function(){
81				var span = parseInt( this.getAttribute( "colspan" ), 10 ),
82					sel = ":nth-child(" + ( coltally + 1 ) + ")";
83
84				colstart = coltally + 1;
85
86				if( span ){
87					for( var k = 0; k < span - 1; k++ ){
88						coltally++;
89						sel += ", :nth-child(" + ( coltally + 1 ) + ")";
90					}
91				}
92
93				// Store "cells" data on header as a reference to all cells in the same column as this TH
94				this.cells = self.$table.find("tr").not( thrs[0] ).not( this ).children().filter( sel );
95				coltally++;
96			});
97		});
98
99		return colstart;
100	};
101
102	Table.prototype.refresh = function() {
103		this._initCells();
104
105		this.$table.trigger( events.refresh );
106	};
107
108	Table.prototype.createToolbar = function() {
109		// Insert the toolbar
110		// TODO move this into a separate component
111		var $toolbar = this.$table.prev().filter( '.' + classes.toolbar );
112		if( !$toolbar.length ) {
113			$toolbar = $( '<div>' )
114				.addClass( classes.toolbar )
115				.insertBefore( this.$table );
116		}
117		this.$toolbar = $toolbar;
118
119		if( this.mode ) {
120			this.$toolbar.addClass( 'mode-' + this.mode );
121		}
122	};
123
124	Table.prototype.destroy = function() {
125		// Don’t remove the toolbar. Some of the table features are not yet destroy-friendly.
126		this.$table.prev().filter( '.' + classes.toolbar ).each(function() {
127			this.className = this.className.replace( /\bmode\-\w*\b/gi, '' );
128		});
129
130		var tableId = this.$table.attr( 'id' );
131		$( document ).unbind( "." + tableId );
132		$( window ).unbind( "." + tableId );
133
134		// other plugins
135		this.$table.trigger( events.destroy, [ this ] );
136
137		this.$table.removeAttr( 'data-tablesaw-mode' );
138
139		this.$table.removeData( pluginName );
140	};
141
142	// Collection method.
143	$.fn[ pluginName ] = function() {
144		return this.each( function() {
145			var $t = $( this );
146
147			if( $t.data( pluginName ) ){
148				return;
149			}
150
151			var table = new Table( this );
152			$t.data( pluginName, table );
153		});
154	};
155
156	$( document ).on( "enhance.tablesaw", function( e ) {
157		// Cut the mustard
158		if( Tablesaw.mustard ) {
159			$( e.target ).find( initSelector )[ pluginName ]();
160		}
161	});
162
163}( jQuery ));
164
165;(function( win, $, undefined ){
166
167	var classes = {
168		stackTable: 'tablesaw-stack',
169		cellLabels: 'tablesaw-cell-label',
170		cellContentLabels: 'tablesaw-cell-content'
171	};
172
173	var data = {
174		obj: 'tablesaw-stack'
175	};
176
177	var attrs = {
178		labelless: 'data-tablesaw-no-labels',
179		hideempty: 'data-tablesaw-hide-empty'
180	};
181
182	var Stack = function( element ) {
183
184		this.$table = $( element );
185
186		this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
187		this.hideempty = this.$table.is( '[' + attrs.hideempty + ']' );
188
189		if( !this.labelless ) {
190			// allHeaders references headers, plus all THs in the thead, which may include several rows, or not
191			this.allHeaders = this.$table.find( "th" );
192		}
193
194		this.$table.data( data.obj, this );
195	};
196
197	Stack.prototype.init = function( colstart ) {
198		this.$table.addClass( classes.stackTable );
199
200		if( this.labelless ) {
201			return;
202		}
203
204		// get headers in reverse order so that top-level headers are appended last
205		var reverseHeaders = $( this.allHeaders );
206		var hideempty = this.hideempty;
207
208		// create the hide/show toggles
209		reverseHeaders.each(function(){
210			var $t = $( this ),
211				$cells = $( this.cells ).filter(function() {
212					return !$( this ).parent().is( "[" + attrs.labelless + "]" ) && ( !hideempty || !$( this ).is( ":empty" ) );
213				}),
214				hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " tablesaw-cell-label-top",
215				// TODO reduce coupling with sortable
216				$sortableButton = $t.find( ".tablesaw-sortable-btn" ),
217				html = $sortableButton.length ? $sortableButton.html() : $t.html();
218
219			if( html !== "" ){
220				if( hierarchyClass ){
221					var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
222						filter = "";
223
224					if( iteration ){
225						filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
226					}
227					$cells.filter( filter ).prepend( "<b class='" + classes.cellLabels + hierarchyClass + "'>" + html + "</b>"  );
228				} else {
229					$cells.wrapInner( "<span class='" + classes.cellContentLabels + "'></span>" );
230					$cells.prepend( "<b class='" + classes.cellLabels + "'>" + html + "</b>"  );
231				}
232			}
233		});
234	};
235
236	Stack.prototype.destroy = function() {
237		this.$table.removeClass( classes.stackTable );
238		this.$table.find( '.' + classes.cellLabels ).remove();
239		this.$table.find( '.' + classes.cellContentLabels ).each(function() {
240			$( this ).replaceWith( this.childNodes );
241		});
242	};
243
244	// on tablecreate, init
245	$( document ).on( "tablesawcreate", function( e, Tablesaw, colstart ){
246		if( Tablesaw.mode === 'stack' ){
247			var table = new Stack( Tablesaw.table );
248			table.init( colstart );
249		}
250
251	} );
252
253	$( document ).on( "tablesawdestroy", function( e, Tablesaw ){
254
255		if( Tablesaw.mode === 'stack' ){
256			$( Tablesaw.table ).data( data.obj ).destroy();
257		}
258
259	} );
260
261}( this, jQuery ));
262;(function( $ ) {
263	var pluginName = "tablesawbtn",
264		methods = {
265			_create: function(){
266				return $( this ).each(function() {
267					$( this )
268						.trigger( "beforecreate." + pluginName )
269						[ pluginName ]( "_init" )
270						.trigger( "create." + pluginName );
271				});
272			},
273			_init: function(){
274				var oEl = $( this ),
275					sel = this.getElementsByTagName( "select" )[ 0 ];
276
277				if( sel ) {
278					$( this )
279						.addClass( "btn-select" )
280						[ pluginName ]( "_select", sel );
281				}
282				return oEl;
283			},
284			_select: function( sel ) {
285				var update = function( oEl, sel ) {
286					var opts = $( sel ).find( "option" ),
287						label, el, children;
288
289					opts.each(function() {
290						var opt = this;
291						if( opt.selected ) {
292							label = document.createTextNode( opt.text );
293						}
294					});
295
296					children = oEl.childNodes;
297					if( opts.length > 0 ){
298						for( var i = 0, l = children.length; i < l; i++ ) {
299							el = children[ i ];
300
301							if( el && el.nodeType === 3 ) {
302								oEl.replaceChild( label, el );
303							}
304						}
305					}
306				};
307
308				update( this, sel );
309				$( this ).bind( "change refresh", function() {
310					update( this, sel );
311				});
312			}
313		};
314
315	// Collection method.
316	$.fn[ pluginName ] = function( arrg, a, b, c ) {
317		return this.each(function() {
318
319		// if it's a method
320		if( arrg && typeof( arrg ) === "string" ){
321			return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
322		}
323
324		// don't re-init
325		if( $( this ).data( pluginName + "active" ) ){
326			return $( this );
327		}
328
329		// otherwise, init
330
331		$( this ).data( pluginName + "active", true );
332			$.fn[ pluginName ].prototype._create.call( this );
333		});
334	};
335
336	// add methods
337	$.extend( $.fn[ pluginName ].prototype, methods );
338
339}( jQuery ));
340;(function( win, $, undefined ){
341
342	var ColumnToggle = function( element ) {
343
344		this.$table = $( element );
345
346		this.classes = {
347			columnToggleTable: 'tablesaw-columntoggle',
348			columnBtnContain: 'tablesaw-columntoggle-btnwrap tablesaw-advance',
349			columnBtn: 'tablesaw-columntoggle-btn tablesaw-nav-btn down',
350			popup: 'tablesaw-columntoggle-popup',
351			priorityPrefix: 'tablesaw-priority-',
352			// TODO duplicate class, also in tables.js
353			toolbar: 'tablesaw-bar'
354		};
355
356		// Expose headers and allHeaders properties on the widget
357		// headers references the THs within the first TR in the table
358		this.headers = this.$table.find( 'tr:first > th' );
359
360		this.$table.data( 'tablesaw-coltoggle', this );
361	};
362
363	ColumnToggle.prototype.init = function() {
364
365		var tableId,
366			id,
367			$menuButton,
368			$popup,
369			$menu,
370			$btnContain,
371			self = this;
372
373		this.$table.addClass( this.classes.columnToggleTable );
374
375		tableId = this.$table.attr( "id" );
376		id = tableId + "-popup";
377		$btnContain = $( "<div class='" + this.classes.columnBtnContain + "'></div>" );
378		$menuButton = $( "<a href='#" + id + "' class='btn btn-micro " + this.classes.columnBtn +"' data-popup-link>" +
379										"<span>" + Tablesaw.i18n.columnBtnText + "</span></a>" );
380		$popup = $( "<div class='dialog-table-coltoggle " + this.classes.popup + "' id='" + id + "'></div>" );
381		$menu = $( "<div class='btn-group'></div>" );
382
383		var hasNonPersistentHeaders = false;
384		$( this.headers ).not( "td" ).each( function() {
385			var $this = $( this ),
386				priority = $this.attr("data-tablesaw-priority"),
387				$cells = $this.add( this.cells );
388
389			if( priority && priority !== "persist" ) {
390				$cells.addClass( self.classes.priorityPrefix + priority );
391
392				$("<label><input type='checkbox' checked>" + $this.text() + "</label>" )
393					.appendTo( $menu )
394					.children( 0 )
395					.data( "cells", $cells );
396
397				hasNonPersistentHeaders = true;
398			}
399		});
400
401		if( !hasNonPersistentHeaders ) {
402			$menu.append( '<label>' + Tablesaw.i18n.columnsDialogError + '</label>' );
403		}
404
405		$menu.appendTo( $popup );
406
407		// bind change event listeners to inputs - TODO: move to a private method?
408		$menu.find( 'input[type="checkbox"]' ).on( "change", function(e) {
409			var checked = e.target.checked;
410
411			$( e.target ).data( "cells" )
412				.toggleClass( "tablesaw-cell-hidden", !checked )
413				.toggleClass( "tablesaw-cell-visible", checked );
414
415			self.$table.trigger( 'tablesawcolumns' );
416		});
417
418		$menuButton.appendTo( $btnContain );
419		$btnContain.appendTo( this.$table.prev().filter( '.' + this.classes.toolbar ) );
420
421		var closeTimeout;
422		function openPopup() {
423			$btnContain.addClass( 'visible' );
424			$menuButton.removeClass( 'down' ).addClass( 'up' );
425
426			$( document ).unbind( 'click.' + tableId, closePopup );
427
428			window.clearTimeout( closeTimeout );
429			closeTimeout = window.setTimeout(function() {
430				$( document ).one( 'click.' + tableId, closePopup );
431			}, 15 );
432		}
433
434		function closePopup( event ) {
435			// Click came from inside the popup, ignore.
436			if( event && $( event.target ).closest( "." + self.classes.popup ).length ) {
437				return;
438			}
439
440			$( document ).unbind( 'click.' + tableId );
441			$menuButton.removeClass( 'up' ).addClass( 'down' );
442			$btnContain.removeClass( 'visible' );
443		}
444
445		$menuButton.on( "click.tablesaw", function( event ) {
446			event.preventDefault();
447
448			if( !$btnContain.is( ".visible" ) ) {
449				openPopup();
450			} else {
451				closePopup();
452			}
453		});
454
455		$popup.appendTo( $btnContain );
456
457		this.$menu = $menu;
458
459		$(window).on( "resize." + tableId, function(){
460			self.refreshToggle();
461		});
462
463		this.refreshToggle();
464	};
465
466	ColumnToggle.prototype.refreshToggle = function() {
467		this.$menu.find( "input" ).each( function() {
468			var $this = $( this );
469
470			this.checked = $this.data( "cells" ).eq( 0 ).css( "display" ) === "table-cell";
471		});
472	};
473
474	ColumnToggle.prototype.refreshPriority = function(){
475		var self = this;
476		$(this.headers).not( "td" ).each( function() {
477			var $this = $( this ),
478				priority = $this.attr("data-tablesaw-priority"),
479				$cells = $this.add( this.cells );
480
481			if( priority && priority !== "persist" ) {
482				$cells.addClass( self.classes.priorityPrefix + priority );
483			}
484		});
485	};
486
487	ColumnToggle.prototype.destroy = function() {
488		// table toolbars, document and window .tableId events
489		// removed in parent tables.js destroy method
490
491		this.$table.removeClass( this.classes.columnToggleTable );
492		this.$table.find( 'th, td' ).each(function() {
493			var $cell = $( this );
494			$cell.removeClass( 'tablesaw-cell-hidden' )
495				.removeClass( 'tablesaw-cell-visible' );
496
497			this.className = this.className.replace( /\bui\-table\-priority\-\d\b/g, '' );
498		});
499	};
500
501	// on tablecreate, init
502	$( document ).on( "tablesawcreate", function( e, Tablesaw ){
503
504		if( Tablesaw.mode === 'columntoggle' ){
505			var table = new ColumnToggle( Tablesaw.table );
506			table.init();
507		}
508
509	} );
510
511	$( document ).on( "tablesawdestroy", function( e, Tablesaw ){
512		if( Tablesaw.mode === 'columntoggle' ){
513			$( Tablesaw.table ).data( 'tablesaw-coltoggle' ).destroy();
514		}
515	} );
516
517}( this, jQuery ));
518;(function( win, $, undefined ){
519
520	$.extend( Tablesaw.config, {
521		swipe: {
522			horizontalThreshold: 15,
523			verticalThreshold: 30
524		}
525	});
526
527	function isIE8() {
528		var div = document.createElement('div'),
529			all = div.getElementsByTagName('i');
530
531		div.innerHTML = '<!--[if lte IE 8]><i></i><![endif]-->';
532
533		return !!all.length;
534	}
535
536	function createSwipeTable( $table ){
537
538		var $btns = $( "<div class='tablesaw-advance'></div>" ),
539			$prevBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro left' title='Previous Column'></a>" ).appendTo( $btns ),
540			$nextBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro right' title='Next Column'></a>" ).appendTo( $btns ),
541			hideBtn = 'disabled',
542			persistWidths = 'tablesaw-fix-persist',
543			$headerCells = $table.find( "thead th" ),
544			$headerCellsNoPersist = $headerCells.not( '[data-tablesaw-priority="persist"]' ),
545			headerWidths = [],
546			$head = $( document.head || 'head' ),
547			tableId = $table.attr( 'id' ),
548			// TODO switch this to an nth-child feature test
549			supportsNthChild = !isIE8();
550
551		if( !$headerCells.length ) {
552			//throw new Error( "tablesaw swipe: no header cells found. Are you using <th> inside of <thead>?" );
553		}
554
555		// Calculate initial widths
556		$table.css('width', 'auto');
557		$headerCells.each(function() {
558			headerWidths.push( $( this ).outerWidth() );
559		});
560		$table.css( 'width', '' );
561
562		$btns.appendTo( $table.prev().filter( '.tablesaw-bar' ) );
563
564		$table.addClass( "tablesaw-swipe" );
565
566		if( !tableId ) {
567			tableId = 'tableswipe-' + Math.round( Math.random() * 10000 );
568			$table.attr( 'id', tableId );
569		}
570
571		function $getCells( headerCell ) {
572			return $( headerCell.cells ).add( headerCell );
573		}
574
575		function showColumn( headerCell ) {
576			$getCells( headerCell ).removeClass( 'tablesaw-cell-hidden' );
577		}
578
579		function hideColumn( headerCell ) {
580			$getCells( headerCell ).addClass( 'tablesaw-cell-hidden' );
581		}
582
583		function persistColumn( headerCell ) {
584			$getCells( headerCell ).addClass( 'tablesaw-cell-persist' );
585		}
586
587		function isPersistent( headerCell ) {
588			return $( headerCell ).is( '[data-tablesaw-priority="persist"]' );
589		}
590
591		function unmaintainWidths() {
592			$table.removeClass( persistWidths );
593			$( '#' + tableId + '-persist' ).remove();
594		}
595
596		function maintainWidths() {
597			var prefix = '#' + tableId + '.tablesaw-swipe ',
598				styles = [],
599				tableWidth = $table.width(),
600				hash = [],
601				newHash;
602
603			$headerCells.each(function( index ) {
604				var width;
605				if( isPersistent( this ) ) {
606					width = $( this ).outerWidth();
607
608					// Only save width on non-greedy columns (take up less than 75% of table width)
609					if( width < tableWidth * 0.75 ) {
610						hash.push( index + '-' + width );
611						styles.push( prefix + ' .tablesaw-cell-persist:nth-child(' + ( index + 1 ) + ') { width: ' + width + 'px; }' );
612					}
613				}
614			});
615			newHash = hash.join( '_' );
616
617			$table.addClass( persistWidths );
618
619			var $style = $( '#' + tableId + '-persist' );
620			// If style element not yet added OR if the widths have changed
621			if( !$style.length || $style.data( 'hash' ) !== newHash ) {
622				// Remove existing
623				$style.remove();
624
625				if( styles.length ) {
626					$( '<style>' + styles.join( "\n" ) + '</style>' )
627						.attr( 'id', tableId + '-persist' )
628						.data( 'hash', newHash )
629						.appendTo( $head );
630				}
631			}
632		}
633
634		function getNext(){
635			var next = [],
636				checkFound;
637
638			$headerCellsNoPersist.each(function( i ) {
639				var $t = $( this ),
640					isHidden = $t.css( "display" ) === "none" || $t.is( ".tablesaw-cell-hidden" );
641
642				if( !isHidden && !checkFound ) {
643					checkFound = true;
644					next[ 0 ] = i;
645				} else if( isHidden && checkFound ) {
646					next[ 1 ] = i;
647
648					return false;
649				}
650			});
651
652			return next;
653		}
654
655		function getPrev(){
656			var next = getNext();
657			return [ next[ 1 ] - 1 , next[ 0 ] - 1 ];
658		}
659
660		function nextpair( fwd ){
661			return fwd ? getNext() : getPrev();
662		}
663
664		function canAdvance( pair ){
665			return pair[ 1 ] > -1 && pair[ 1 ] < $headerCellsNoPersist.length;
666		}
667
668		function matchesMedia() {
669			var matchMedia = $table.attr( "data-tablesaw-swipe-media" );
670			return !matchMedia || ( "matchMedia" in win ) && win.matchMedia( matchMedia ).matches;
671		}
672
673		function fakeBreakpoints() {
674			if( !matchesMedia() ) {
675				return;
676			}
677
678			var extraPaddingPixels = 20,
679				containerWidth = $table.parent().width(),
680				persist = [],
681				sum = 0,
682				sums = [],
683				visibleNonPersistantCount = $headerCells.length;
684
685			$headerCells.each(function( index ) {
686				var $t = $( this ),
687					isPersist = $t.is( '[data-tablesaw-priority="persist"]' );
688
689				persist.push( isPersist );
690
691				sum += headerWidths[ index ] + ( isPersist ? 0 : extraPaddingPixels );
692				sums.push( sum );
693
694				// is persistent or is hidden
695				if( isPersist || sum > containerWidth ) {
696					visibleNonPersistantCount--;
697				}
698			});
699
700			var needsNonPersistentColumn = visibleNonPersistantCount === 0;
701
702			$headerCells.each(function( index ) {
703				if( persist[ index ] ) {
704
705					// for visual box-shadow
706					persistColumn( this );
707					return;
708				}
709
710				if( sums[ index ] <= containerWidth || needsNonPersistentColumn ) {
711					needsNonPersistentColumn = false;
712					showColumn( this );
713				} else {
714					hideColumn( this );
715				}
716			});
717
718			if( supportsNthChild ) {
719				unmaintainWidths();
720			}
721			$table.trigger( 'tablesawcolumns' );
722		}
723
724		function advance( fwd ){
725			var pair = nextpair( fwd );
726			if( canAdvance( pair ) ){
727				if( isNaN( pair[ 0 ] ) ){
728					if( fwd ){
729						pair[0] = 0;
730					}
731					else {
732						pair[0] = $headerCellsNoPersist.length - 1;
733					}
734				}
735
736				if( supportsNthChild ) {
737					maintainWidths();
738				}
739
740				hideColumn( $headerCellsNoPersist.get( pair[ 0 ] ) );
741				showColumn( $headerCellsNoPersist.get( pair[ 1 ] ) );
742
743				$table.trigger( 'tablesawcolumns' );
744			}
745		}
746
747		$prevBtn.add( $nextBtn ).click(function( e ){
748			advance( !!$( e.target ).closest( $nextBtn ).length );
749			e.preventDefault();
750		});
751
752		function getCoord( event, key ) {
753			return ( event.touches || event.originalEvent.touches )[ 0 ][ key ];
754		}
755
756		$table
757			.bind( "touchstart.swipetoggle", function( e ){
758				var originX = getCoord( e, 'pageX' ),
759					originY = getCoord( e, 'pageY' ),
760					x,
761					y;
762
763				$( win ).off( "resize", fakeBreakpoints );
764
765				$( this )
766					.bind( "touchmove", function( e ){
767						x = getCoord( e, 'pageX' );
768						y = getCoord( e, 'pageY' );
769						var cfg = Tablesaw.config.swipe;
770						if( Math.abs( x - originX ) > cfg.horizontalThreshold && Math.abs( y - originY ) < cfg.verticalThreshold ) {
771							e.preventDefault();
772						}
773					})
774					.bind( "touchend.swipetoggle", function(){
775						var cfg = Tablesaw.config.swipe;
776						if( Math.abs( y - originY ) < cfg.verticalThreshold ) {
777							if( x - originX < -1 * cfg.horizontalThreshold ){
778								advance( true );
779							}
780							if( x - originX > cfg.horizontalThreshold ){
781								advance( false );
782							}
783						}
784
785						window.setTimeout(function() {
786							$( win ).on( "resize", fakeBreakpoints );
787						}, 300);
788						$( this ).unbind( "touchmove touchend" );
789					});
790
791			})
792			.bind( "tablesawcolumns.swipetoggle", function(){
793				$prevBtn[ canAdvance( getPrev() ) ? "removeClass" : "addClass" ]( hideBtn );
794				$nextBtn[ canAdvance( getNext() ) ? "removeClass" : "addClass" ]( hideBtn );
795			})
796			.bind( "tablesawnext.swipetoggle", function(){
797				advance( true );
798			} )
799			.bind( "tablesawprev.swipetoggle", function(){
800				advance( false );
801			} )
802			.bind( "tablesawdestroy.swipetoggle", function(){
803				var $t = $( this );
804
805				$t.removeClass( 'tablesaw-swipe' );
806				$t.prev().filter( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
807				$( win ).off( "resize", fakeBreakpoints );
808
809				$t.unbind( ".swipetoggle" );
810			});
811
812		fakeBreakpoints();
813		$( win ).on( "resize", fakeBreakpoints );
814	}
815
816
817
818	// on tablecreate, init
819	$( document ).on( "tablesawcreate", function( e, Tablesaw ){
820
821		if( Tablesaw.mode === 'swipe' ){
822			createSwipeTable( Tablesaw.$table );
823		}
824
825	} );
826
827}( this, jQuery ));
828
829;(function( $ ) {
830	function getSortValue( cell ) {
831		return $.map( cell.childNodes, function( el ) {
832				var $el = $( el );
833				if( $el.is( 'input, select' ) ) {
834					return $el.val();
835				} else if( $el.hasClass( 'tablesaw-cell-label' ) ) {
836					return;
837				}
838				return $.trim( $el.text() );
839			}).join( '' );
840	}
841
842	var pluginName = "tablesaw-sortable",
843		initSelector = "table[data-" + pluginName + "]",
844		sortableSwitchSelector = "[data-" + pluginName + "-switch]",
845		attrs = {
846			defaultCol: "data-tablesaw-sortable-default-col"
847		},
848		classes = {
849			head: pluginName + "-head",
850			ascend: pluginName + "-ascending",
851			descend: pluginName + "-descending",
852			switcher: pluginName + "-switch",
853			tableToolbar: 'tablesaw-toolbar',
854			sortButton: pluginName + "-btn"
855		},
856		methods = {
857			_create: function( o ){
858				return $( this ).each(function() {
859					var init = $( this ).data( "init" + pluginName );
860					if( init ) {
861						return false;
862					}
863					$( this )
864						.data( "init"+ pluginName, true )
865						.trigger( "beforecreate." + pluginName )
866						[ pluginName ]( "_init" , o )
867						.trigger( "create." + pluginName );
868				});
869			},
870			_init: function(){
871				var el = $( this ),
872					heads,
873					$switcher;
874
875				var addClassToTable = function(){
876						el.addClass( pluginName );
877					},
878					addClassToHeads = function( h ){
879						$.each( h , function( i , v ){
880							$( v ).addClass( classes.head );
881						});
882					},
883					makeHeadsActionable = function( h , fn ){
884						$.each( h , function( i , v ){
885							var b = $( "<button class='" + classes.sortButton + "'/>" );
886							b.bind( "click" , { col: v } , fn );
887							$( v ).wrapInner( b );
888						});
889					},
890					clearOthers = function( sibs ){
891						$.each( sibs , function( i , v ){
892							var col = $( v );
893							col.removeAttr( attrs.defaultCol );
894							col.removeClass( classes.ascend );
895							col.removeClass( classes.descend );
896						});
897					},
898					headsOnAction = function( e ){
899						if( $( e.target ).is( 'a[href]' ) ) {
900							return;
901						}
902
903						e.stopPropagation();
904						var head = $( this ).parent(),
905							v = e.data.col,
906							newSortValue = heads.index( head );
907
908						clearOthers( head.siblings() );
909						if( head.hasClass( classes.descend ) ){
910							el[ pluginName ]( "sortBy" , v , true);
911							newSortValue += '_asc';
912						} else {
913							el[ pluginName ]( "sortBy" , v );
914							newSortValue += '_desc';
915						}
916						if( $switcher ) {
917							$switcher.find( 'select' ).val( newSortValue ).trigger( 'refresh' );
918						}
919
920						e.preventDefault();
921					},
922					handleDefault = function( heads ){
923						$.each( heads , function( idx , el ){
924							var $el = $( el );
925							if( $el.is( "[" + attrs.defaultCol + "]" ) ){
926								if( !$el.hasClass( classes.descend ) ) {
927									$el.addClass( classes.ascend );
928								}
929							}
930						});
931					},
932					addSwitcher = function( heads ){
933						$switcher = $( '<div>' ).addClass( classes.switcher ).addClass( classes.tableToolbar ).html(function() {
934							var html = [ '<label>' + Tablesaw.i18n.sort + ':' ];
935
936							html.push( '<span class="btn btn-small">&#160;<select>' );
937							heads.each(function( j ) {
938								var $t = $( this ),
939									isDefaultCol = $t.is( "[" + attrs.defaultCol + "]" ),
940									isDescending = $t.hasClass( classes.descend ),
941									isNumeric = false;
942
943								// Check only the first three rows to see if the column is numbers.
944								$( this.cells ).slice( 0, 3 ).each(function() {
945									if( !isNaN( parseInt( getSortValue( this ), 10 ) ) ) {
946										isNumeric = true;
947										return false;
948									}
949								});
950
951								html.push( '<option' + ( isDefaultCol && !isDescending ? ' selected' : '' ) + ' value="' + j + '_asc">' + $t.text() + ' ' + ( isNumeric ? '&#x2191;' : '(A-Z)' ) + '</option>' );
952								html.push( '<option' + ( isDefaultCol && isDescending ? ' selected' : '' ) + ' value="' + j + '_desc">' + $t.text() + ' ' + ( isNumeric ? '&#x2193;' : '(Z-A)' ) + '</option>' );
953							});
954							html.push( '</select></span></label>' );
955
956							return html.join('');
957						});
958
959						var $toolbar = el.prev().filter( '.tablesaw-bar' ),
960							$firstChild = $toolbar.children().eq( 0 );
961
962						if( $firstChild.length ) {
963							$switcher.insertBefore( $firstChild );
964						} else {
965							$switcher.appendTo( $toolbar );
966						}
967						$switcher.find( '.btn' ).tablesawbtn();
968						$switcher.find( 'select' ).on( 'change', function() {
969							var val = $( this ).val().split( '_' ),
970								head = heads.eq( val[ 0 ] );
971
972							clearOthers( head.siblings() );
973							el[ pluginName ]( 'sortBy', head.get( 0 ), val[ 1 ] === 'asc' );
974						});
975					};
976
977					addClassToTable();
978					heads = el.find( "thead th[data-" + pluginName + "-col]" );
979					addClassToHeads( heads );
980					makeHeadsActionable( heads , headsOnAction );
981					handleDefault( heads );
982
983					if( el.is( sortableSwitchSelector ) ) {
984						addSwitcher( heads, el.find('tbody tr:nth-child(-n+3)') );
985					}
986			},
987			getColumnNumber: function( col ){
988				return $( col ).prevAll().length;
989			},
990			getTableRows: function(){
991				return $( this ).find( "tbody tr" );
992			},
993			sortRows: function( rows , colNum , ascending, col ){
994				var cells, fn, sorted;
995				var getCells = function( rows ){
996						var cells = [];
997						$.each( rows , function( i , r ){
998							cells.push({
999								cell: getSortValue( $( r ).children().get( colNum ) ),
1000								rowNum: i
1001							});
1002						});
1003						return cells;
1004					},
1005					getSortFxn = function( ascending, forceNumeric ){
1006						var fn,
1007							regex = /[^\-\+\d\.]/g;
1008						if( ascending ){
1009							fn = function( a , b ){
1010								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
1011									return parseFloat( a.cell.replace( regex, '' ) ) - parseFloat( b.cell.replace( regex, '' ) );
1012								} else {
1013									return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
1014								}
1015							};
1016						} else {
1017							fn = function( a , b ){
1018								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
1019									return parseFloat( b.cell.replace( regex, '' ) ) - parseFloat( a.cell.replace( regex, '' ) );
1020								} else {
1021									return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
1022								}
1023							};
1024						}
1025						return fn;
1026					},
1027					applyToRows = function( sorted , rows ){
1028						var newRows = [], i, l, cur;
1029						for( i = 0, l = sorted.length ; i < l ; i++ ){
1030							cur = sorted[ i ].rowNum;
1031							newRows.push( rows[cur] );
1032						}
1033						return newRows;
1034					};
1035
1036				cells = getCells( rows );
1037				var customFn = $( col ).data( 'tablesaw-sort' );
1038				fn = ( customFn && typeof customFn === "function" ? customFn( ascending ) : false ) ||
1039					getSortFxn( ascending, $( col ).is( '[data-sortable-numeric]' ) );
1040				sorted = cells.sort( fn );
1041				rows = applyToRows( sorted , rows );
1042				return rows;
1043			},
1044			replaceTableRows: function( rows ){
1045				var el = $( this ),
1046					body = el.find( "tbody" );
1047				body.html( rows );
1048			},
1049			makeColDefault: function( col , a ){
1050				var c = $( col );
1051				c.attr( attrs.defaultCol , "true" );
1052				if( a ){
1053					c.removeClass( classes.descend );
1054					c.addClass( classes.ascend );
1055				} else {
1056					c.removeClass( classes.ascend );
1057					c.addClass( classes.descend );
1058				}
1059			},
1060			sortBy: function( col , ascending ){
1061				var el = $( this ), colNum, rows;
1062
1063				colNum = el[ pluginName ]( "getColumnNumber" , col );
1064				rows = el[ pluginName ]( "getTableRows" );
1065				rows = el[ pluginName ]( "sortRows" , rows , colNum , ascending, col );
1066				el[ pluginName ]( "replaceTableRows" , rows );
1067				el[ pluginName ]( "makeColDefault" , col , ascending );
1068			}
1069		};
1070
1071	// Collection method.
1072	$.fn[ pluginName ] = function( arrg ) {
1073		var args = Array.prototype.slice.call( arguments , 1),
1074			returnVal;
1075
1076		// if it's a method
1077		if( arrg && typeof( arrg ) === "string" ){
1078			returnVal = $.fn[ pluginName ].prototype[ arrg ].apply( this[0], args );
1079			return (typeof returnVal !== "undefined")? returnVal:$(this);
1080		}
1081		// check init
1082		if( !$( this ).data( pluginName + "data" ) ){
1083			$( this ).data( pluginName + "active", true );
1084			$.fn[ pluginName ].prototype._create.call( this , arrg );
1085		}
1086		return $(this);
1087	};
1088	// add methods
1089	$.extend( $.fn[ pluginName ].prototype, methods );
1090
1091	$( document ).on( "tablesawcreate", function( e, Tablesaw ) {
1092		if( Tablesaw.$table.is( initSelector ) ) {
1093			Tablesaw.$table[ pluginName ]();
1094		}
1095	});
1096
1097}( jQuery ));
1098
1099;(function( win, $, undefined ){
1100
1101	var MM = {
1102		attr: {
1103			init: 'data-tablesaw-minimap'
1104		}
1105	};
1106
1107	function createMiniMap( $table ){
1108
1109		var $btns = $( '<div class="tablesaw-advance minimap">' ),
1110			$dotNav = $( '<ul class="tablesaw-advance-dots">' ).appendTo( $btns ),
1111			hideDot = 'tablesaw-advance-dots-hide',
1112			$headerCells = $table.find( 'thead th' );
1113
1114		// populate dots
1115		$headerCells.each(function(){
1116			$dotNav.append( '<li><i></i></li>' );
1117		});
1118
1119		$btns.appendTo( $table.prev().filter( '.tablesaw-bar' ) );
1120
1121		function showMinimap( $table ) {
1122			var mq = $table.attr( MM.attr.init );
1123			return !mq || win.matchMedia && win.matchMedia( mq ).matches;
1124		}
1125
1126		function showHideNav(){
1127			if( !showMinimap( $table ) ) {
1128				$btns.hide();
1129				return;
1130			}
1131			$btns.show();
1132
1133			// show/hide dots
1134			var dots = $dotNav.find( "li" ).removeClass( hideDot );
1135			$table.find( "thead th" ).each(function(i){
1136				if( $( this ).css( "display" ) === "none" ){
1137					dots.eq( i ).addClass( hideDot );
1138				}
1139			});
1140		}
1141
1142		// run on init and resize
1143		showHideNav();
1144		$( win ).on( "resize", showHideNav );
1145
1146
1147		$table
1148			.bind( "tablesawcolumns.minimap", function(){
1149				showHideNav();
1150			})
1151			.bind( "tablesawdestroy.minimap", function(){
1152				var $t = $( this );
1153
1154				$t.prev().filter( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
1155				$( win ).off( "resize", showHideNav );
1156
1157				$t.unbind( ".minimap" );
1158			});
1159	}
1160
1161
1162
1163	// on tablecreate, init
1164	$( document ).on( "tablesawcreate", function( e, Tablesaw ){
1165
1166		if( ( Tablesaw.mode === 'swipe' || Tablesaw.mode === 'columntoggle' ) && Tablesaw.$table.is( '[ ' + MM.attr.init + ']' ) ){
1167			createMiniMap( Tablesaw.$table );
1168		}
1169
1170	} );
1171
1172}( this, jQuery ));
1173
1174;(function( win, $ ) {
1175
1176	var S = {
1177		selectors: {
1178			init: 'table[data-tablesaw-mode-switch]'
1179		},
1180		attributes: {
1181			excludeMode: 'data-tablesaw-mode-exclude'
1182		},
1183		classes: {
1184			main: 'tablesaw-modeswitch',
1185			toolbar: 'tablesaw-toolbar'
1186		},
1187		modes: [ 'stack', 'swipe', 'columntoggle' ],
1188		init: function( table ) {
1189			var $table = $( table ),
1190				ignoreMode = $table.attr( S.attributes.excludeMode ),
1191				$toolbar = $table.prev().filter( '.tablesaw-bar' ),
1192				modeVal = '',
1193				$switcher = $( '<div>' ).addClass( S.classes.main + ' ' + S.classes.toolbar ).html(function() {
1194					var html = [ '<label>' + Tablesaw.i18n.columns + ':' ],
1195						dataMode = $table.attr( 'data-tablesaw-mode' ),
1196						isSelected;
1197
1198					html.push( '<span class="btn btn-small">&#160;<select>' );
1199					for( var j=0, k = S.modes.length; j<k; j++ ) {
1200						if( ignoreMode && ignoreMode.toLowerCase() === S.modes[ j ] ) {
1201							continue;
1202						}
1203
1204						isSelected = dataMode === S.modes[ j ];
1205
1206						if( isSelected ) {
1207							modeVal = S.modes[ j ];
1208						}
1209
1210						html.push( '<option' +
1211							( isSelected ? ' selected' : '' ) +
1212							' value="' + S.modes[ j ] + '">' + Tablesaw.i18n.modes[ j ] + '</option>' );
1213					}
1214					html.push( '</select></span></label>' );
1215
1216					return html.join('');
1217				});
1218
1219			var $otherToolbarItems = $toolbar.find( '.tablesaw-advance' ).eq( 0 );
1220			if( $otherToolbarItems.length ) {
1221				$switcher.insertBefore( $otherToolbarItems );
1222			} else {
1223				$switcher.appendTo( $toolbar );
1224			}
1225
1226			$switcher.find( '.btn' ).tablesawbtn();
1227			$switcher.find( 'select' ).bind( 'change', S.onModeChange );
1228		},
1229		onModeChange: function() {
1230			var $t = $( this ),
1231				$switcher = $t.closest( '.' + S.classes.main ),
1232				$table = $t.closest( '.tablesaw-bar' ).nextUntil( $table ).eq( 0 ),
1233				val = $t.val();
1234
1235			$switcher.remove();
1236			$table.data( 'table' ).destroy();
1237
1238			$table.attr( 'data-tablesaw-mode', val );
1239			$table.table();
1240		}
1241	};
1242
1243	$( win.document ).on( "tablesawcreate", function( e, Tablesaw ) {
1244		if( Tablesaw.$table.is( S.selectors.init ) ) {
1245			S.init( Tablesaw.table );
1246		}
1247	});
1248
1249})( this, jQuery );

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.