template/html/jquery-tablesorter.js
function( c, callback, $tbodies ) {
         var cache, val, txt, rowIndex, colIndex, tbodyIndex, $tbody, $row,
          cols, $cells, cell, cacheTime, totalRows, rowData, prevRowData,
          colMax, span, cacheIndex, hasParser, max, len, index,
          table = c.table,
          parsers = c.parsers;
         // update tbody variable
         c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
         $tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies,
          c.cache = {};
         c.totalRows = 0;
         // if no parsers found, return - it's an empty table.
         if ( !parsers ) {
            return c.debug ? console.warn( 'Warning: *Empty table!* Not building a cache' ) : '';
         }
         if ( c.debug ) {
            cacheTime = new Date();
         }
         // processing icon
         if ( c.showProcessing ) {
            ts.isProcessing( table, true );
         }
         for ( tbodyIndex = 0; tbodyIndex < $tbody.length; tbodyIndex++ ) {
            colMax = []; // column max value per tbody
            cache = c.cache[ tbodyIndex ] = {
               normalized: [] // array of normalized row data; last entry contains 'rowData' above
               // colMax: #   // added at the end
            };

            totalRows = ( $tbody[ tbodyIndex ] && $tbody[ tbodyIndex ].rows.length ) || 0;
            for ( rowIndex = 0; rowIndex < totalRows; ++rowIndex ) {
               rowData = {
                  // order: original row order #
                  // $row : jQuery Object[]
                  child: [], // child row text (filter widget)
                  raw: []    // original row text
               };
               /** Add the table data to main data array */
               $row = $( $tbody[ tbodyIndex ].rows[ rowIndex ] );
               cols = [];
               // if this is a child row, add it to the last row's children and continue to the next row
               // ignore child row class, if it is the first row
               if ( $row.hasClass( c.cssChildRow ) && rowIndex !== 0 ) {
                  len = cache.normalized.length - 1;
                  prevRowData = cache.normalized[ len ][ c.columns ];
                  prevRowData.$row = prevRowData.$row.add( $row );
                  // add 'hasChild' class name to parent row
                  if ( !$row.prev().hasClass( c.cssChildRow ) ) {
                     $row.prev().addClass( ts.css.cssHasChild );
                  }
                  // save child row content (un-parsed!)
                  $cells = $row.children( 'th, td' );
                  len = prevRowData.child.length;
                  prevRowData.child[ len ] = [];
                  // child row content does not account for colspans/rowspans; so indexing may be off
                  cacheIndex = 0;
                  max = c.columns;
                  for ( colIndex = 0; colIndex < max; colIndex++ ) {
                     cell = $cells[ colIndex ];
                     if ( cell ) {
                        prevRowData.child[ len ][ colIndex ] = ts.getParsedText( c, cell, colIndex );
                        span = $cells[ colIndex ].colSpan - 1;
                        if ( span > 0 ) {
                           cacheIndex += span;
                           max += span;
                        }
                     }
                     cacheIndex++;
                  }
                  // go to the next for loop
                  continue;
               }
               rowData.$row = $row;
               rowData.order = rowIndex; // add original row position to rowCache
               cacheIndex = 0;
               max = c.columns;
               for ( colIndex = 0; colIndex < max; ++colIndex ) {
                  cell = $row[ 0 ].cells[ colIndex ];
                  if ( cell && cacheIndex < c.columns ) {
                     hasParser = typeof parsers[ cacheIndex ] !== 'undefined';
                     if ( !hasParser && c.debug ) {
                        console.warn( 'No parser found for row: ' + rowIndex + ', column: ' + colIndex +
                         '; cell containing: "' + $(cell).text() + '"; does it have a header?' );
                     }
                     val = ts.getElementText( c, cell, cacheIndex );
                     rowData.raw[ cacheIndex ] = val; // save original row text
                     // save raw column text even if there is no parser set
                     txt = ts.getParsedText( c, cell, cacheIndex, val );
                     cols[ cacheIndex ] = txt;
                     if ( hasParser && ( parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {
                        // determine column max value (ignore sign)
                        colMax[ cacheIndex ] = Math.max( Math.abs( txt ) || 0, colMax[ cacheIndex ] || 0 );
                     }
                     // allow colSpan in tbody
                     span = cell.colSpan - 1;
                     if ( span > 0 ) {
                        index = 0;
                        while ( index <= span ) {
                           // duplicate text (or not) to spanned columns
                           // instead of setting duplicate span to empty string, use textExtraction to try to get a value
                           // see http://stackoverflow.com/q/36449711/145346
                           txt = c.duplicateSpan || index === 0 ?
                            val :
                            typeof c.textExtraction !== 'string' ?
                            ts.getElementText( c, cell, cacheIndex + index ) || '' :
                             '';
                           rowData.raw[ cacheIndex + index ] = txt;
                           cols[ cacheIndex + index ] = txt;
                           index++;
                        }
                        cacheIndex += span;
                        max += span;
                     }
                  }
                  cacheIndex++;
               }
               // ensure rowData is always in the same location (after the last column)
               cols[ c.columns ] = rowData;
               cache.normalized[ cache.normalized.length ] = cols;
            }
            cache.colMax = colMax;
            // total up rows, not including child rows
            c.totalRows += cache.normalized.length;

         }
         if ( c.showProcessing ) {
            ts.isProcessing( table ); // remove processing icon
         }
         if ( c.debug ) {
            len = Math.min( 5, c.cache[ 0 ].normalized.length );
            console[ console.group ? 'group' : 'log' ]( 'Building cache for ' + c.totalRows +
             ' rows (showing ' + len + ' rows in log)' + ts.benchmark( cacheTime ) );
            val = {};
            for ( colIndex = 0; colIndex < c.columns; colIndex++ ) {
               for ( cacheIndex = 0; cacheIndex < len; cacheIndex++ ) {
                  if ( !val[ 'row: ' + cacheIndex ] ) {
                     val[ 'row: ' + cacheIndex ] = {};
                  }
                  val[ 'row: ' + cacheIndex ][ c.$headerIndexed[ colIndex ].text() ] =
                   c.cache[ 0 ].normalized[ cacheIndex ][ colIndex ];
               }
            }
            console[ console.table ? 'table' : 'log' ]( val );
            if ( console.groupEnd ) { console.groupEnd(); }
         }
         if ( $.isFunction( callback ) ) {
            callback( table );
         }
      }
function( c, callback, $tbodies ) {
         var cache, val, txt, rowIndex, colIndex, tbodyIndex, $tbody, $row,
          cols, $cells, cell, cacheTime, totalRows, rowData, prevRowData,
          colMax, span, cacheIndex, hasParser, max, len, index,
          table = c.table,
          parsers = c.parsers;
         // update tbody variable
         c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
         $tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies,
          c.cache = {};
         c.totalRows = 0;
         // if no parsers found, return - it's an empty table.
         if ( !parsers ) {
            return c.debug ? console.warn( 'Warning: *Empty table!* Not building a cache' ) : '';
         }
         if ( c.debug ) {
            cacheTime = new Date();
         }
         // processing icon
         if ( c.showProcessing ) {
            ts.isProcessing( table, true );
         }
         for ( tbodyIndex = 0; tbodyIndex < $tbody.length; tbodyIndex++ ) {
            colMax = []; // column max value per tbody
            cache = c.cache[ tbodyIndex ] = {
               normalized: [] // array of normalized row data; last entry contains 'rowData' above
               // colMax: #   // added at the end
            };

            totalRows = ( $tbody[ tbodyIndex ] && $tbody[ tbodyIndex ].rows.length ) || 0;
            for ( rowIndex = 0; rowIndex < totalRows; ++rowIndex ) {
               rowData = {
                  // order: original row order #
                  // $row : jQuery Object[]
                  child: [], // child row text (filter widget)
                  raw: []    // original row text
               };
               /** Add the table data to main data array */
               $row = $( $tbody[ tbodyIndex ].rows[ rowIndex ] );
               cols = [];
               // if this is a child row, add it to the last row's children and continue to the next row
               // ignore child row class, if it is the first row
               if ( $row.hasClass( c.cssChildRow ) && rowIndex !== 0 ) {
                  len = cache.normalized.length - 1;
                  prevRowData = cache.normalized[ len ][ c.columns ];
                  prevRowData.$row = prevRowData.$row.add( $row );
                  // add 'hasChild' class name to parent row
                  if ( !$row.prev().hasClass( c.cssChildRow ) ) {
                     $row.prev().addClass( ts.css.cssHasChild );
                  }
                  // save child row content (un-parsed!)
                  $cells = $row.children( 'th, td' );
                  len = prevRowData.child.length;
                  prevRowData.child[ len ] = [];
                  // child row content does not account for colspans/rowspans; so indexing may be off
                  cacheIndex = 0;
                  max = c.columns;
                  for ( colIndex = 0; colIndex < max; colIndex++ ) {
                     cell = $cells[ colIndex ];
                     if ( cell ) {
                        prevRowData.child[ len ][ colIndex ] = ts.getParsedText( c, cell, colIndex );
                        span = $cells[ colIndex ].colSpan - 1;
                        if ( span > 0 ) {
                           cacheIndex += span;
                           max += span;
                        }
                     }
                     cacheIndex++;
                  }
                  // go to the next for loop
                  continue;
               }
               rowData.$row = $row;
               rowData.order = rowIndex; // add original row position to rowCache
               cacheIndex = 0;
               max = c.columns;
               for ( colIndex = 0; colIndex < max; ++colIndex ) {
                  cell = $row[ 0 ].cells[ colIndex ];
                  if ( cell && cacheIndex < c.columns ) {
                     hasParser = typeof parsers[ cacheIndex ] !== 'undefined';
                     if ( !hasParser && c.debug ) {
                        console.warn( 'No parser found for row: ' + rowIndex + ', column: ' + colIndex +
                         '; cell containing: "' + $(cell).text() + '"; does it have a header?' );
                     }
                     val = ts.getElementText( c, cell, cacheIndex );
                     rowData.raw[ cacheIndex ] = val; // save original row text
                     // save raw column text even if there is no parser set
                     txt = ts.getParsedText( c, cell, cacheIndex, val );
                     cols[ cacheIndex ] = txt;
                     if ( hasParser && ( parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {
                        // determine column max value (ignore sign)
                        colMax[ cacheIndex ] = Math.max( Math.abs( txt ) || 0, colMax[ cacheIndex ] || 0 );
                     }
                     // allow colSpan in tbody
                     span = cell.colSpan - 1;
                     if ( span > 0 ) {
                        index = 0;
                        while ( index <= span ) {
                           // duplicate text (or not) to spanned columns
                           // instead of setting duplicate span to empty string, use textExtraction to try to get a value
                           // see http://stackoverflow.com/q/36449711/145346
                           txt = c.duplicateSpan || index === 0 ?
                            val :
                            typeof c.textExtraction !== 'string' ?
                            ts.getElementText( c, cell, cacheIndex + index ) || '' :
                             '';
                           rowData.raw[ cacheIndex + index ] = txt;
                           cols[ cacheIndex + index ] = txt;
                           index++;
                        }
                        cacheIndex += span;
                        max += span;
                     }
                  }
                  cacheIndex++;
               }
               // ensure rowData is always in the same location (after the last column)
               cols[ c.columns ] = rowData;
               cache.normalized[ cache.normalized.length ] = cols;
            }
            cache.colMax = colMax;
            // total up rows, not including child rows
            c.totalRows += cache.normalized.length;

         }
         if ( c.showProcessing ) {
            ts.isProcessing( table ); // remove processing icon
         }
         if ( c.debug ) {
            len = Math.min( 5, c.cache[ 0 ].normalized.length );
            console[ console.group ? 'group' : 'log' ]( 'Building cache for ' + c.totalRows +
             ' rows (showing ' + len + ' rows in log)' + ts.benchmark( cacheTime ) );
            val = {};
            for ( colIndex = 0; colIndex < c.columns; colIndex++ ) {
               for ( cacheIndex = 0; cacheIndex < len; cacheIndex++ ) {
                  if ( !val[ 'row: ' + cacheIndex ] ) {
                     val[ 'row: ' + cacheIndex ] = {};
                  }
                  val[ 'row: ' + cacheIndex ][ c.$headerIndexed[ colIndex ].text() ] =
                   c.cache[ 0 ].normalized[ cacheIndex ][ colIndex ];
               }
            }
            console[ console.table ? 'table' : 'log' ]( val );
            if ( console.groupEnd ) { console.groupEnd(); }
         }
         if ( $.isFunction( callback ) ) {
            callback( table );
         }
      }
function ( c , callback , $tbodies ) { var cache , val , txt , rowIndex , colIndex , tbodyIndex , $tbody , $row , cols , $cells , cell , cacheTime , totalRows , rowData , prevRowData , colMax , span , cacheIndex , hasParser , max , len , index , table = c . table , parsers = c . parsers ; // update tbody variable c . $tbodies = c . $table . children ( 'tbody:not(.' + c . cssInfoBlock + ')' ) ; $tbody = typeof $tbodies === 'undefined' ? c . $tbodies : $tbodies , c . cache = { } ; c . totalRows = 0 ; // if no parsers found, return - it's an empty table. if ( ! parsers ) { return c . debug ? console . warn ( 'Warning: *Empty table!* Not building a cache' ) : '' ; } if ( c . debug ) { cacheTime = new Date ( ) ; } // processing icon if ( c . showProcessing ) { ts . isProcessing ( table , true ) ; } for ( tbodyIndex = 0 ; tbodyIndex < $tbody . length ; tbodyIndex ++ ) { colMax = [ ] ; // column max value per tbody cache = c . cache [ tbodyIndex ] = { normalized : [ ] // array of normalized row data; last entry contains 'rowData' above // colMax: #   // added at the end } ; totalRows = ( $tbody [ tbodyIndex ] && $tbody [ tbodyIndex ] . rows . length ) || 0 ; for ( rowIndex = 0 ; rowIndex < totalRows ; ++ rowIndex ) { rowData = { // order: original row order # // $row : jQuery Object[] child : [ ] , // child row text (filter widget) raw : [ ] // original row text } ; /** Add the table data to main data array */ $row = $ ( $tbody [ tbodyIndex ] . rows [ rowIndex ] ) ; cols = [ ] ; // if this is a child row, add it to the last row's children and continue to the next row // ignore child row class, if it is the first row if ( $row . hasClass ( c . cssChildRow ) && rowIndex !== 0 ) { len = cache . normalized . length - 1 ; prevRowData = cache . normalized [ len ] [ c . columns ] ; prevRowData . $row = prevRowData . $row . add ( $row ) ; // add 'hasChild' class name to parent row if ( ! $row . prev ( ) . hasClass ( c . cssChildRow ) ) { $row . prev ( ) . addClass ( ts . css . cssHasChild ) ; } // save child row content (un-parsed!) $cells = $row . children ( 'th, td' ) ; len = prevRowData . child . length ; prevRowData . child [ len ] = [ ] ; // child row content does not account for colspans/rowspans; so indexing may be off cacheIndex = 0 ; max = c . columns ; for ( colIndex = 0 ; colIndex < max ; colIndex ++ ) { cell = $cells [ colIndex ] ; if ( cell ) { prevRowData . child [ len ] [ colIndex ] = ts . getParsedText ( c , cell , colIndex ) ; span = $cells [ colIndex ] . colSpan - 1 ; if ( span > 0 ) { cacheIndex += span ; max += span ; } } cacheIndex ++ ; } // go to the next for loop continue ; } rowData . $row = $row ; rowData . order = rowIndex ; // add original row position to rowCache cacheIndex = 0 ; max = c . columns ; for ( colIndex = 0 ; colIndex < max ; ++ colIndex ) { cell = $row [ 0 ] . cells [ colIndex ] ; if ( cell && cacheIndex < c . columns ) { hasParser = typeof parsers [ cacheIndex ] !== 'undefined' ; if ( ! hasParser && c . debug ) { console . warn ( 'No parser found for row: ' + rowIndex + ', column: ' + colIndex + '; cell containing: "' + $ ( cell ) . text ( ) + '"; does it have a header?' ) ; } val = ts . getElementText ( c , cell , cacheIndex ) ; rowData . raw [ cacheIndex ] = val ; // save original row text // save raw column text even if there is no parser set txt = ts . getParsedText ( c , cell , cacheIndex , val ) ; cols [ cacheIndex ] = txt ; if ( hasParser && ( parsers [ cacheIndex ] . type || '' ) . toLowerCase ( ) === 'numeric' ) { // determine column max value (ignore sign) colMax [ cacheIndex ] = Math . max ( Math . abs ( txt ) || 0 , colMax [ cacheIndex ] || 0 ) ; } // allow colSpan in tbody span = cell . colSpan - 1 ; if ( span > 0 ) { index = 0 ; while ( index <= span ) { // duplicate text (or not) to spanned columns // instead of setting duplicate span to empty string, use textExtraction to try to get a value // see http://stackoverflow.com/q/36449711/145346 txt = c . duplicateSpan || index === 0 ? val : typeof c . textExtraction !== 'string' ? ts . getElementText ( c , cell , cacheIndex + index ) || '' : '' ; rowData . raw [ cacheIndex + index ] = txt ; cols [ cacheIndex + index ] = txt ; index ++ ; } cacheIndex += span ; max += span ; } } cacheIndex ++ ; } // ensure rowData is always in the same location (after the last column) cols [ c . columns ] = rowData ; cache . normalized [ cache . normalized . length ] = cols ; } cache . colMax = colMax ; // total up rows, not including child rows c . totalRows += cache . normalized . length ; } if ( c . showProcessing ) { ts . isProcessing ( table ) ; // remove processing icon } if ( c . debug ) { len = Math . min ( 5 , c . cache [ 0 ] . normalized . length ) ; console [ console . group ? 'group' : 'log' ] ( 'Building cache for ' + c . totalRows + ' rows (showing ' + len + ' rows in log)' + ts . benchmark ( cacheTime ) ) ; val = { } ; for ( colIndex = 0 ; colIndex < c . columns ; colIndex ++ ) { for ( cacheIndex = 0 ; cacheIndex < len ; cacheIndex ++ ) { if ( ! val [ 'row: ' + cacheIndex ] ) { val [ 'row: ' + cacheIndex ] = { } ; } val [ 'row: ' + cacheIndex ] [ c . $headerIndexed [ colIndex ] . text ( ) ] = c . cache [ 0 ] . normalized [ cacheIndex ] [ colIndex ] ; } } console [ console . table ? 'table' : 'log' ] ( val ) ; if ( console . groupEnd ) { console . groupEnd ( ) ; } } if ( $ . isFunction ( callback ) ) { callback ( table ) ; } }
/*
▄████▄ ▄████▄ ▄████▄ ██  ██ ██████
██  ▀▀ ██▄▄██ ██  ▀▀ ██▄▄██ ██▄▄
██  ▄▄ ██▀▀██ ██  ▄▄ ██▀▀██ ██▀▀
▀████▀ ██  ██ ▀████▀ ██  ██ ██████
/ * ▄████▄ ▄████▄ ▄████▄ ██ ██ ██████ ██ ▀▀ ██▄▄██ ██ ▀▀ ██▄▄██ ██▄▄ ██ ▄▄ ██▀▀██ ██ ▄▄ ██▀▀██ ██▀▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██████