-/**
+/*!
* TableSorter for MediaWiki
*
* Written 2011 Leo Koppelkamm
* and mw.language.months.
*
* Uses 'tableSorterCollation' in mw.config (if available)
- */
-/**
*
- * @description Create a sortable table with multi-column sorting capabilities
+ * Create a sortable table with multi-column sorting capabilities
*
- * @example $( 'table' ).tablesorter();
- * @desc Create a simple tablesorter interface.
+ * // Create a simple tablesorter interface
+ * $( 'table' ).tablesorter();
*
- * @example $( 'table' ).tablesorter( { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] } );
- * @desc Create a tablesorter interface initially sorting on the first and second column.
+ * // Create a tablesorter interface, initially sorting on the first and second column
+ * $( 'table' ).tablesorter( { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] } );
*
- * @option String cssHeader ( optional ) A string of the class name to be appended
- * to sortable tr elements in the thead of the table. Default value:
- * "header"
+ * @param {string} [cssHeader="header"] A string of the class name to be appended to sortable
+ * tr elements in the thead of the table.
*
- * @option String cssAsc ( optional ) A string of the class name to be appended to
- * sortable tr elements in the thead on a ascending sort. Default value:
- * "headerSortUp"
+ * @param {string} [cssAsc="headerSortUp"] A string of the class name to be appended to
+ * sortable tr elements in the thead on a ascending sort.
*
- * @option String cssDesc ( optional ) A string of the class name to be appended
- * to sortable tr elements in the thead on a descending sort. Default
- * value: "headerSortDown"
+ * @param {string} [cssDesc="headerSortDown"] A string of the class name to be appended to
+ * sortable tr elements in the thead on a descending sort.
*
- * @option String sortMultisortKey ( optional ) A string of the multi-column sort
- * key. Default value: "shiftKey"
+ * @param {string} [sortMultisortKey="shiftKey"] A string of the multi-column sort key.
*
- * @option Boolean cancelSelection ( optional ) Boolean flag indicating if
- * tablesorter should cancel selection of the table headers text.
- * Default value: true
+ * @param {boolean} [cancelSelection=true] Boolean flag indicating iftablesorter should cancel
+ * selection of the table headers text.
*
- * @option Array sortList ( optional ) An array containing objects specifying sorting.
- * By passing more than one object, multi-sorting will be applied. Object structure:
+ * @param {Array} [sortList] An array containing objects specifying sorting. By passing more
+ * than one object, multi-sorting will be applied. Object structure:
* { <Integer column index>: <String 'asc' or 'desc'> }
- * Default value: []
*
* @event sortEnd.tablesorter: Triggered as soon as any sorting has been applied.
*
- * @type jQuery
- *
- * @name tablesorter
- *
- * @cat Plugins/Tablesorter
- *
* @author Christian Bach/christian.bach@polyester.se
*/
-
( function ( $, mw ) {
- /* Local scope */
-
var ts,
parsers = [];
/* Parser utility functions */
function getParserById( name ) {
- var i,
- len = parsers.length;
- for ( i = 0; i < len; i++ ) {
+ var i;
+ for ( i = 0; i < parsers.length; i++ ) {
if ( parsers[ i ].id.toLowerCase() === name.toLowerCase() ) {
return parsers[ i ];
}
// Cast any numbers or other stuff to a string, methods
// like charAt, toLowerCase and split are expected.
return String( data );
- } else {
- if ( !node ) {
- return $node.text();
- } else if ( node.tagName.toLowerCase() === 'img' ) {
- return $node.attr( 'alt' ) || ''; // handle undefined alt
- } else {
- return $.map( $.makeArray( node.childNodes ), function ( elem ) {
- if ( elem.nodeType === Node.ELEMENT_NODE ) {
- return getElementSortKey( elem );
- } else {
- return $.text( elem );
- }
- } ).join( '' );
- }
}
+ if ( !node ) {
+ return $node.text();
+ }
+ if ( node.tagName.toLowerCase() === 'img' ) {
+ return $node.attr( 'alt' ) || ''; // handle undefined alt
+ }
+ return $.map( $.makeArray( node.childNodes ), function ( elem ) {
+ if ( elem.nodeType === Node.ELEMENT_NODE ) {
+ return getElementSortKey( elem );
+ }
+ return $.text( elem );
+ } ).join( '' );
}
function detectParserForColumn( table, rows, column ) {
var l = parsers.length,
+ config = $( table ).data( 'tablesorter' ).config,
cellIndex,
nodeValue,
// Start with 1 because 0 is the fallback parser
needed = ( rows.length > 4 ) ? 5 : rows.length;
while ( i < l ) {
- if ( rows[ rowIndex ] ) {
+ // if this is a child row, continue to the next row (as buildCache())
+ if ( rows[ rowIndex ] && !$( rows[ rowIndex ] ).hasClass( config.cssChildRow ) ) {
if ( rowIndex !== lastRowIndex ) {
lastRowIndex = rowIndex;
cellIndex = $( rows[ rowIndex ] ).data( 'columnToCell' )[ column ];
pos = normalized[ i ][ checkCell ];
l = row[ pos ].length;
-
for ( j = 0; j < l; j++ ) {
fragment.appendChild( row[ pos ][ j ] );
}
function uniqueElements( array ) {
var uniques = [];
- $.each( array, function ( index, elem ) {
+ $.each( array, function ( i, elem ) {
if ( elem !== undefined && $.inArray( elem, uniques ) === -1 ) {
uniques.push( elem );
}
exploded,
$tableHeaders = $( [] ),
$tableRows = $( 'thead:eq(0) > tr', table );
+
if ( $tableRows.length <= 1 ) {
$tableHeaders = $tableRows.children( 'th' );
} else {
}
function isValueInArray( v, a ) {
- var i,
- len = a.length;
- for ( i = 0; i < len; i++ ) {
+ var i;
+ for ( i = 0; i < a.length; i++ ) {
if ( a[ i ][ 0 ] === v ) {
return true;
}
$headers.removeClass( css[ 0 ] ).removeClass( css[ 1 ] ).attr( 'title', msg[ 1 ] );
for ( var i = 0; i < list.length; i++ ) {
- $headers.eq( columnToHeader[ list[ i ][ 0 ] ] )
+ $headers
+ .eq( columnToHeader[ list[ i ][ 0 ] ] )
.addClass( css[ list[ i ][ 1 ] ] )
.attr( 'title', msg[ list[ i ][ 1 ] ] );
}
function multisort( table, sortList, cache ) {
var i,
- sortFn = [],
- len = sortList.length;
- for ( i = 0; i < len; i++ ) {
+ sortFn = [];
+
+ for ( i = 0; i < sortList.length; i++ ) {
sortFn[ i ] = ( sortList[ i ][ 1 ] ) ? sortTextDesc : sortText;
}
cache.normalized.sort( function ( array1, array2 ) {
var i, col, ret;
- for ( i = 0; i < len; i++ ) {
+ for ( i = 0; i < sortList.length; i++ ) {
col = sortList[ i ][ 0 ];
ret = sortFn[ i ].call( this, array1[ col ], array2[ col ] );
if ( ret !== 0 ) {
ascii = separatorTransformTable[ 0 ].split( '\t' ).concat( digitTransformTable[ 0 ].split( '\t' ) );
localised = separatorTransformTable[ 1 ].split( '\t' ).concat( digitTransformTable[ 1 ].split( '\t' ) );
- // Construct regex for number identification
+ // Construct regexes for number identification
for ( i = 0; i < ascii.length; i++ ) {
ts.transformTable[ localised[ i ] ] = ascii[ i ];
digits.push( mw.RegExp.escape( localised[ i ] ) );
$table.find( '> tbody > tr' ).each( function () {
var i,
col = 0,
- l = this.cells.length;
- for ( i = 0; i < l; i++ ) {
+ len = this.cells.length;
+ for ( i = 0; i < len; i++ ) {
$( this.cells[ i ] ).data( 'tablesorter', {
realCellIndex: col,
realRowIndex: this.rowIndex
* Converts sort objects [ { Integer: String }, ... ] to the internally used nested array
* structure [ [ Integer , Integer ], ... ]
*
- * @param sortObjects {Array} List of sort objects.
+ * @param {Array} sortObjects List of sort objects.
* @return {Array} List of internal sort definitions.
*/
-
function convertSortList( sortObjects ) {
var sortList = [];
$.each( sortObjects, function ( i, sortObject ) {
$.data( table, 'tablesorter', { config: config } );
// Get the CSS class names, could be done elsewhere
- sortCSS = [ config.cssDesc, config.cssAsc ];
+ sortCSS = [ config.cssAsc, config.cssDesc ];
+ // Messages tell the the user what the *next* state will be
+ // so are in reverse order to the CSS classes.
sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
// Build headers
},
addParser: function ( parser ) {
- var i,
- len = parsers.length,
- a = true;
- for ( i = 0; i < len; i++ ) {
- if ( parsers[ i ].id.toLowerCase() === parser.id.toLowerCase() ) {
- a = false;
- }
- }
- if ( a ) {
+ if ( !getParserById( parser.id ) ) {
parsers.push( parser );
}
},
format: function ( s ) {
var i, item,
a = s.split( '.' ),
- r = '',
- len = a.length;
- for ( i = 0; i < len; i++ ) {
+ r = '';
+ for ( i = 0; i < a.length; i++ ) {
item = a[ i ];
if ( item.length === 1 ) {
r += '00' + item;
return ts.rgx.isoDate[ 0 ].test( s );
},
format: function ( s ) {
- var isodate,
- matches;
+ var isodate, matches;
if ( !Date.prototype.toISOString ) {
// Old browsers don't understand iso, Fallback to US date parsing and ignore the time part.
matches = $.trim( s ).match( ts.rgx.isoDate[ 1 ] );
- if ( matches ) {
- isodate = new Date( matches[ 2 ] + '/' + matches[ 3 ] + '/' + matches[ 1 ] );
- } else {
+ if ( !matches ) {
return $.tablesorter.formatFloat( 0 );
}
+ isodate = new Date( matches[ 2 ] + '/' + matches[ 3 ] + '/' + matches[ 1 ] );
} else {
matches = s.match( ts.rgx.isoDate[ 0 ] );
- if ( matches ) {
- isodate = new Date( $.trim( matches[ 0 ] ) );
- } else {
+ if ( !matches ) {
return $.tablesorter.formatFloat( 0 );
}
+ isodate = new Date( $.trim( matches[ 0 ] ) );
}
return $.tablesorter.formatFloat( ( isodate !== undefined ) ? isodate.getTime() : 0 );
},