template/html/jquery-tablesorter.js
function( c ) { /*jshint loopfunc:true */
         var tbodyIndex, sortTime, colMax, rows,
          table = c.table,
          dir = 0,
          textSorter = c.textSorter || '',
          sortList = c.sortList,
          sortLen = sortList.length,
          len = c.$tbodies.length;
         if ( c.serverSideSorting || ts.isEmptyObject( c.cache ) ) {
            // empty table - fixes #206/#346
            return;
         }
         if ( c.debug ) { sortTime = new Date(); }
         for ( tbodyIndex = 0; tbodyIndex < len; tbodyIndex++ ) {
            colMax = c.cache[ tbodyIndex ].colMax;
            rows = c.cache[ tbodyIndex ].normalized;

            rows.sort( function( a, b ) {
               var sortIndex, num, col, order, sort, x, y;
               // rows is undefined here in IE, so don't use it!
               for ( sortIndex = 0; sortIndex < sortLen; sortIndex++ ) {
                  col = sortList[ sortIndex ][ 0 ];
                  order = sortList[ sortIndex ][ 1 ];
                  // sort direction, true = asc, false = desc
                  dir = order === 0;

                  if ( c.sortStable && a[ col ] === b[ col ] && sortLen === 1 ) {
                     return a[ c.columns ].order - b[ c.columns ].order;
                  }

                  // fallback to natural sort since it is more robust
                  num = /n/i.test( ts.getSortType( c.parsers, col ) );
                  if ( num && c.strings[ col ] ) {
                     // sort strings in numerical columns
                     if ( typeof ( ts.string[ c.strings[ col ] ] ) === 'boolean' ) {
                        num = ( dir ? 1 : -1 ) * ( ts.string[ c.strings[ col ] ] ? -1 : 1 );
                     } else {
                        num = ( c.strings[ col ] ) ? ts.string[ c.strings[ col ] ] || 0 : 0;
                     }
                     // fall back to built-in numeric sort
                     // var sort = $.tablesorter['sort' + s]( a[col], b[col], dir, colMax[col], table );
                     sort = c.numberSorter ? c.numberSorter( a[ col ], b[ col ], dir, colMax[ col ], table ) :
                      ts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], num, colMax[ col ], col, c );
                  } else {
                     // set a & b depending on sort direction
                     x = dir ? a : b;
                     y = dir ? b : a;
                     // text sort function
                     if ( typeof textSorter === 'function' ) {
                        // custom OVERALL text sorter
                        sort = textSorter( x[ col ], y[ col ], dir, col, table );
                     } else if ( typeof textSorter === 'object' && textSorter.hasOwnProperty( col ) ) {
                        // custom text sorter for a SPECIFIC COLUMN
                        sort = textSorter[ col ]( x[ col ], y[ col ], dir, col, table );
                     } else {
                        // fall back to natural sort
                        sort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], col, c );
                     }
                  }
                  if ( sort ) { return sort; }
               }
               return a[ c.columns ].order - b[ c.columns ].order;
            });
         }
         if ( c.debug ) {
            console.log( 'Applying sort ' + sortList.toString() + ts.benchmark( sortTime ) );
         }
      }
function( c ) { /*jshint loopfunc:true */
         var tbodyIndex, sortTime, colMax, rows,
          table = c.table,
          dir = 0,
          textSorter = c.textSorter || '',
          sortList = c.sortList,
          sortLen = sortList.length,
          len = c.$tbodies.length;
         if ( c.serverSideSorting || ts.isEmptyObject( c.cache ) ) {
            // empty table - fixes #206/#346
            return;
         }
         if ( c.debug ) { sortTime = new Date(); }
         for ( tbodyIndex = 0; tbodyIndex < len; tbodyIndex++ ) {
            colMax = c.cache[ tbodyIndex ].colMax;
            rows = c.cache[ tbodyIndex ].normalized;

            rows.sort( function( a, b ) {
               var sortIndex, num, col, order, sort, x, y;
               // rows is undefined here in IE, so don't use it!
               for ( sortIndex = 0; sortIndex < sortLen; sortIndex++ ) {
                  col = sortList[ sortIndex ][ 0 ];
                  order = sortList[ sortIndex ][ 1 ];
                  // sort direction, true = asc, false = desc
                  dir = order === 0;

                  if ( c.sortStable && a[ col ] === b[ col ] && sortLen === 1 ) {
                     return a[ c.columns ].order - b[ c.columns ].order;
                  }

                  // fallback to natural sort since it is more robust
                  num = /n/i.test( ts.getSortType( c.parsers, col ) );
                  if ( num && c.strings[ col ] ) {
                     // sort strings in numerical columns
                     if ( typeof ( ts.string[ c.strings[ col ] ] ) === 'boolean' ) {
                        num = ( dir ? 1 : -1 ) * ( ts.string[ c.strings[ col ] ] ? -1 : 1 );
                     } else {
                        num = ( c.strings[ col ] ) ? ts.string[ c.strings[ col ] ] || 0 : 0;
                     }
                     // fall back to built-in numeric sort
                     // var sort = $.tablesorter['sort' + s]( a[col], b[col], dir, colMax[col], table );
                     sort = c.numberSorter ? c.numberSorter( a[ col ], b[ col ], dir, colMax[ col ], table ) :
                      ts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], num, colMax[ col ], col, c );
                  } else {
                     // set a & b depending on sort direction
                     x = dir ? a : b;
                     y = dir ? b : a;
                     // text sort function
                     if ( typeof textSorter === 'function' ) {
                        // custom OVERALL text sorter
                        sort = textSorter( x[ col ], y[ col ], dir, col, table );
                     } else if ( typeof textSorter === 'object' && textSorter.hasOwnProperty( col ) ) {
                        // custom text sorter for a SPECIFIC COLUMN
                        sort = textSorter[ col ]( x[ col ], y[ col ], dir, col, table );
                     } else {
                        // fall back to natural sort
                        sort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], col, c );
                     }
                  }
                  if ( sort ) { return sort; }
               }
               return a[ c.columns ].order - b[ c.columns ].order;
            });
         }
         if ( c.debug ) {
            console.log( 'Applying sort ' + sortList.toString() + ts.benchmark( sortTime ) );
         }
      }
sort multiple columns