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 = " "; 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 ? '↑' : '(A-Z)' ) + '</option>' ); 926 html.push( '<option' + ( isDefaultCol && isDescending ? ' selected' : '' ) + ' value="' + j + '_desc">' + $t.text() + ' ' + ( isNumeric ? '↓' : '(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.