template/html/jquery-tablesorter.js
function( c, $tbodies ) {
         var rows, list, span, max, colIndex, indx, header, configHeaders,
          noParser, parser, extractor, time, tbody, len,
          table = c.table,
          tbodyIndex = 0,
          debug = {};
         // update table bodies in case we start with an empty table
         c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
         tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;
         len = tbody.length;
         if ( len === 0 ) {
            return c.debug ? console.warn( 'Warning: *Empty table!* Not building a parser cache' ) : '';
         } else if ( c.debug ) {
            time = new Date();
            console[ console.group ? 'group' : 'log' ]( 'Detecting parsers for each column' );
         }
         list = {
            extractors: [],
            parsers: []
         };
         while ( tbodyIndex < len ) {
            rows = tbody[ tbodyIndex ].rows;
            if ( rows.length ) {
               colIndex = 0;
               max = c.columns;
               for ( indx = 0; indx < max; indx++ ) {
                  header = c.$headerIndexed[ colIndex ];
                  if ( header && header.length ) {
                     // get column indexed table cell
                     configHeaders = ts.getColumnData( table, c.headers, colIndex );
                     // get column parser/extractor
                     extractor = ts.getParserById( ts.getData( header, configHeaders, 'extractor' ) );
                     parser = ts.getParserById( ts.getData( header, configHeaders, 'sorter' ) );
                     noParser = ts.getData( header, configHeaders, 'parser' ) === 'false';
                     // empty cells behaviour - keeping emptyToBottom for backwards compatibility
                     c.empties[colIndex] = (
                     ts.getData( header, configHeaders, 'empty' ) ||
                     c.emptyTo || ( c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();
                     // text strings behaviour in numerical sorts
                     c.strings[colIndex] = (
                     ts.getData( header, configHeaders, 'string' ) ||
                     c.stringTo ||
                     'max' ).toLowerCase();
                     if ( noParser ) {
                        parser = ts.getParserById( 'no-parser' );
                     }
                     if ( !extractor ) {
                        // For now, maybe detect someday
                        extractor = false;
                     }
                     if ( !parser ) {
                        parser = ts.detectParserForColumn( c, rows, -1, colIndex );
                     }
                     if ( c.debug ) {
                        debug[ '(' + colIndex + ') ' + header.text() ] = {
                           parser : parser.id,
                           extractor : extractor ? extractor.id : 'none',
                           string : c.strings[ colIndex ],
                           empty  : c.empties[ colIndex ]
                        };
                     }
                     list.parsers[ colIndex ] = parser;
                     list.extractors[ colIndex ] = extractor;
                     span = header[ 0 ].colSpan - 1;
                     if ( span > 0 ) {
                        colIndex += span;
                        max += span;
                        while ( span + 1 > 0 ) {
                           // set colspan columns to use the same parsers & extractors
                           list.parsers[ colIndex - span ] = parser;
                           list.extractors[ colIndex - span ] = extractor;
                           span--;
                        }
                     }
                  }
                  colIndex++;
               }
            }
            tbodyIndex += ( list.parsers.length ) ? len : 1;
         }
         if ( c.debug ) {
            if ( !ts.isEmptyObject( debug ) ) {
               console[ console.table ? 'table' : 'log' ]( debug );
            } else {
               console.warn( '  No parsers detected!' );
            }
            console.log( 'Completed detecting parsers' + ts.benchmark( time ) );
            if ( console.groupEnd ) { console.groupEnd(); }
         }
         c.parsers = list.parsers;
         c.extractors = list.extractors;
      }
function( c, $tbodies ) {
         var rows, list, span, max, colIndex, indx, header, configHeaders,
          noParser, parser, extractor, time, tbody, len,
          table = c.table,
          tbodyIndex = 0,
          debug = {};
         // update table bodies in case we start with an empty table
         c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
         tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;
         len = tbody.length;
         if ( len === 0 ) {
            return c.debug ? console.warn( 'Warning: *Empty table!* Not building a parser cache' ) : '';
         } else if ( c.debug ) {
            time = new Date();
            console[ console.group ? 'group' : 'log' ]( 'Detecting parsers for each column' );
         }
         list = {
            extractors: [],
            parsers: []
         };
         while ( tbodyIndex < len ) {
            rows = tbody[ tbodyIndex ].rows;
            if ( rows.length ) {
               colIndex = 0;
               max = c.columns;
               for ( indx = 0; indx < max; indx++ ) {
                  header = c.$headerIndexed[ colIndex ];
                  if ( header && header.length ) {
                     // get column indexed table cell
                     configHeaders = ts.getColumnData( table, c.headers, colIndex );
                     // get column parser/extractor
                     extractor = ts.getParserById( ts.getData( header, configHeaders, 'extractor' ) );
                     parser = ts.getParserById( ts.getData( header, configHeaders, 'sorter' ) );
                     noParser = ts.getData( header, configHeaders, 'parser' ) === 'false';
                     // empty cells behaviour - keeping emptyToBottom for backwards compatibility
                     c.empties[colIndex] = (
                     ts.getData( header, configHeaders, 'empty' ) ||
                     c.emptyTo || ( c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();
                     // text strings behaviour in numerical sorts
                     c.strings[colIndex] = (
                     ts.getData( header, configHeaders, 'string' ) ||
                     c.stringTo ||
                     'max' ).toLowerCase();
                     if ( noParser ) {
                        parser = ts.getParserById( 'no-parser' );
                     }
                     if ( !extractor ) {
                        // For now, maybe detect someday
                        extractor = false;
                     }
                     if ( !parser ) {
                        parser = ts.detectParserForColumn( c, rows, -1, colIndex );
                     }
                     if ( c.debug ) {
                        debug[ '(' + colIndex + ') ' + header.text() ] = {
                           parser : parser.id,
                           extractor : extractor ? extractor.id : 'none',
                           string : c.strings[ colIndex ],
                           empty  : c.empties[ colIndex ]
                        };
                     }
                     list.parsers[ colIndex ] = parser;
                     list.extractors[ colIndex ] = extractor;
                     span = header[ 0 ].colSpan - 1;
                     if ( span > 0 ) {
                        colIndex += span;
                        max += span;
                        while ( span + 1 > 0 ) {
                           // set colspan columns to use the same parsers & extractors
                           list.parsers[ colIndex - span ] = parser;
                           list.extractors[ colIndex - span ] = extractor;
                           span--;
                        }
                     }
                  }
                  colIndex++;
               }
            }
            tbodyIndex += ( list.parsers.length ) ? len : 1;
         }
         if ( c.debug ) {
            if ( !ts.isEmptyObject( debug ) ) {
               console[ console.table ? 'table' : 'log' ]( debug );
            } else {
               console.warn( '  No parsers detected!' );
            }
            console.log( 'Completed detecting parsers' + ts.benchmark( time ) );
            if ( console.groupEnd ) { console.groupEnd(); }
         }
         c.parsers = list.parsers;
         c.extractors = list.extractors;
      }
/*
█████▄ ▄████▄ █████▄ ▄█████ ██████ █████▄ ▄█████
██▄▄██ ██▄▄██ ██▄▄██ ▀█▄    ██▄▄   ██▄▄██ ▀█▄
██▀▀▀  ██▀▀██ ██▀██     ▀█▄ ██▀▀   ██▀██     ▀█▄
██     ██  ██ ██  ██ █████▀ ██████ ██  ██ █████▀