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