From 63601400e476c6cf43d985f3e7b9864681695ed4 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Fri, 18 Jan 2013 16:46:04 +0100 Subject: Update to MediaWiki 1.20.2 this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024 --- resources/jquery/jquery.tablesorter.js | 291 +++++++++++++++------------------ 1 file changed, 132 insertions(+), 159 deletions(-) (limited to 'resources/jquery/jquery.tablesorter.js') diff --git a/resources/jquery/jquery.tablesorter.js b/resources/jquery/jquery.tablesorter.js index ea86b64e..3ef71d57 100644 --- a/resources/jquery/jquery.tablesorter.js +++ b/resources/jquery/jquery.tablesorter.js @@ -56,11 +56,11 @@ * @author Christian Bach/christian.bach@polyester.se */ -( function( $ ) { +( function ( $, mw ) { /* Local scope */ - var ts, + var ts, parsers = []; /* Parser utility functions */ @@ -77,9 +77,15 @@ function getElementText( node ) { var $node = $( node ), - data = $node.attr( 'data-sort-value' ); - if ( data !== undefined ) { - return data; + // Use data-sort-value attribute. + // Use data() instead of attr() so that live value changes + // are processed as well (bug 38152). + data = $node.data( 'sortValue' ); + + if ( data !== null && data !== undefined ) { + // Cast any numbers or other stuff to a string, methods + // like charAt, toLowerCase and split are expected. + return String( data ); } else { return $node.text(); } @@ -94,7 +100,7 @@ } function detectParserForColumn( table, rows, cellIndex ) { - var l = parsers.length, + var l = parsers.length, nodeValue, // Start with 1 because 0 is the fallback parser i = 1, @@ -133,13 +139,13 @@ } function buildParserCache( table, $headers ) { - var rows = table.tBodies[0].rows, + var rows = table.tBodies[0].rows, sortType, parsers = []; if ( rows[0] ) { - var cells = rows[0].cells, + var cells = rows[0].cells, len = cells.length, i, parser; @@ -163,7 +169,7 @@ /* Other utility functions */ function buildCache( table ) { - var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0, + var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0, totalCells = ( table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length ) || 0, parsers = table.config.parsers, cache = { @@ -174,7 +180,7 @@ for ( var i = 0; i < totalRows; ++i ) { // Add the table data to main data array - var $row = $( table.tBodies[0].rows[i] ), + var $row = $( table.tBodies[0].rows[i] ), cols = []; // if this is a child row, add it to the last row's children and @@ -200,7 +206,7 @@ } function appendToTable( table, cache ) { - var row = cache.row, + var row = cache.row, normalized = cache.normalized, totalRows = normalized.length, checkCell = ( normalized[0].length - 1 ), @@ -218,22 +224,22 @@ } table.tBodies[0].appendChild( fragment ); } - + /** * Find all header rows in a thead-less table and put them in a tag. * This only treats a row as a header row if it contains only s (no s) * and if it is preceded entirely by header rows. The algorithm stops when * it encounters the first non-header row. - * + * * After this, it will look at all rows at the bottom for footer rows * And place these in a tfoot using similar rules. * @param $table jQuery object for a - */ + */ function emulateTHeadAndFoot( $table ) { var $rows = $table.find( '> tbody > tr' ); if( !$table.get(0).tHead ) { var $thead = $( '' ); - $rows.each( function() { + $rows.each( function () { if ( $(this).children( 'td' ).length > 0 ) { // This row contains a tag or a tag emulateTHeadAndFoot( $table ); - + // Still no thead? Then quit if ( !table.tHead ) { return; @@ -586,8 +560,8 @@ // Apply event handling to headers // this is too big, perhaps break it out? - $headers.click( function( e ) { - if ( e.target.nodeName.toLowerCase() == 'a' ) { + $headers.click( function ( e ) { + if ( e.target.nodeName.toLowerCase() === 'a' ) { // The user clicked on a link inside a table header // Do nothing and let the default link click action continue return true; @@ -612,9 +586,16 @@ explodeRowspans( $table ); // try to auto detect column type, and store in tables config table.config.parsers = buildParserCache( table, $headers ); - // build the cache for the tbody cells - cache = buildCache( table ); } + + // Build the cache for the tbody cells + // to share between calculations for this sort action. + // Re-calculated each time a sort action is performed due to possiblity + // that sort values change. Shouldn't be too expensive, but if it becomes + // too slow an event based system should be implemented somehow where + // cells get event .change() and bubbles up to the
, so it's not a header row // Stop here @@ -251,18 +257,18 @@ break; } $tfoot.prepend( $( $rows[i] )); - } + } $table.append( $tfoot ); } } function buildHeaders( table, msg ) { - var maxSeen = 0, + var maxSeen = 0, longest, realCellIndex = 0, $tableHeaders = $( 'thead:eq(0) > tr', table ); if ( $tableHeaders.length > 1 ) { - $tableHeaders.each( function() { + $tableHeaders.each( function () { if ( this.cells.length > maxSeen ) { maxSeen = this.cells.length; longest = this; @@ -270,7 +276,7 @@ }); $tableHeaders = $( longest ); } - $tableHeaders = $tableHeaders.children( 'th' ).each( function( index ) { + $tableHeaders = $tableHeaders.children( 'th' ).each( function ( index ) { this.column = realCellIndex; var colspan = this.colspan; @@ -299,7 +305,7 @@ function isValueInArray( v, a ) { var l = a.length; for ( var i = 0; i < l; i++ ) { - if ( a[i][0] == v ) { + if ( a[i][0] === v ) { return true; } } @@ -311,7 +317,7 @@ $headers.removeClass( css[0] ).removeClass( css[1] ); var h = []; - $headers.each( function( offset ) { + $headers.each( function ( offset ) { if ( !this.sortDisabled ) { h[this.column] = $( this ); } @@ -324,62 +330,31 @@ } function sortText( a, b ) { - return ( (a < b) ? false : ((a > b) ? true : 0) ); + return ( (a < b) ? -1 : ((a > b) ? 1 : 0) ); } function sortTextDesc( a, b ) { - return ( (b < a) ? false : ((b > a) ? true : 0) ); + return ( (b < a) ? -1 : ((b > a) ? 1 : 0) ); } - function checkSorting( array1, array2, sortList ) { - var col, fn, ret; - for ( var i = 0, len = sortList.length; i < len; i++ ) { - col = sortList[i][0]; - fn = ( sortList[i][1] ) ? sortTextDesc : sortText; - ret = fn.call( this, array1[col], array2[col] ); - if ( ret !== 0 ) { - return ret; - } + function multisort( table, sortList, cache ) { + var sortFn = []; + var len = sortList.length; + for ( var i = 0; i < len; i++ ) { + sortFn[i] = ( sortList[i][1] ) ? sortTextDesc : sortText; } - return ret; - } - - // Merge sort algorithm - // Based on http://en.literateprograms.org/Merge_sort_(JavaScript) - function mergeSortHelper( array, begin, beginRight, end, sortList ) { - for ( ; begin < beginRight; ++begin ) { - if ( checkSorting( array[begin], array[beginRight], sortList ) ) { - var v = array[begin]; - array[begin] = array[beginRight]; - var begin2 = beginRight; - while ( begin2 + 1 < end && checkSorting( v, array[begin2 + 1], sortList ) ) { - var tmp = array[begin2]; - array[begin2] = array[begin2 + 1]; - array[begin2 + 1] = tmp; - ++begin2; + cache.normalized.sort( function ( array1, array2 ) { + var col, ret; + for ( var i = 0; i < len; i++ ) { + col = sortList[i][0]; + ret = sortFn[i].call( this, array1[col], array2[col] ); + if ( ret !== 0 ) { + return ret; } - array[begin2] = v; } - } - } - - function mergeSort(array, begin, end, sortList) { - var size = end - begin; - if ( size < 2 ) { - return; - } - - var beginRight = begin + Math.floor(size / 2); - - mergeSort( array, begin, beginRight, sortList ); - mergeSort( array, beginRight, end, sortList ); - mergeSortHelper( array, begin, beginRight, end, sortList ); - } - - function multisort( table, sortList, cache ) { - var i = sortList.length; - mergeSort( cache.normalized, 0, cache.normalized.length, sortList ); - + // Fall back to index number column to ensure stable sort + return sortText.call( this, array1[array1.length - 1], array2[array2.length - 1] ); + } ); return cache; } @@ -413,16 +388,15 @@ function buildDateTable() { var regex = []; - ts.monthNames = [ - [], - [] - ]; + ts.monthNames = {}; for ( var i = 1; i < 13; i++ ) { - ts.monthNames[0][i] = mw.config.get( 'wgMonthNames' )[i].toLowerCase(); - ts.monthNames[1][i] = mw.config.get( 'wgMonthNamesShort' )[i].toLowerCase().replace( '.', '' ); - regex.push( $.escapeRE( ts.monthNames[0][i] ) ); - regex.push( $.escapeRE( ts.monthNames[1][i] ) ); + var name = mw.config.get( 'wgMonthNames' )[i].toLowerCase(); + ts.monthNames[name] = i; + regex.push( $.escapeRE( name ) ); + name = mw.config.get( 'wgMonthNamesShort' )[i].toLowerCase().replace( '.', '' ); + ts.monthNames[name] = i; + regex.push( $.escapeRE( name ) ); } // Build piped string @@ -430,19 +404,19 @@ // Build RegEx // Any date formated with . , ' - or / - ts.dateRegex[0] = new RegExp( /^\s*\d{1,2}[\,\.\-\/'\s]{1,2}\d{1,2}[\,\.\-\/'\s]{1,2}\d{2,4}\s*?/i); + ts.dateRegex[0] = new RegExp( /^\s*(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{2,4})\s*?/i); // Written Month name, dmy - ts.dateRegex[1] = new RegExp( '^\\s*\\d{1,2}[\\,\\.\\-\\/\'\\s]*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i' ); + ts.dateRegex[1] = new RegExp( '^\\s*(\\d{1,2})[\\,\\.\\-\\/\'\\s]*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*(\\d{2,4})\\s*$', 'i' ); // Written Month name, mdy - ts.dateRegex[2] = new RegExp( '^\\s*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{1,2}[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i' ); + ts.dateRegex[2] = new RegExp( '^\\s*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*(\\d{1,2})[\\,\\.\\-\\/\'\\s]*(\\d{2,4})\\s*$', 'i' ); } function explodeRowspans( $table ) { // Split multi row cells into multiple cells with the same content - $table.find( '> tbody > tr > [rowspan]' ).each(function() { + $table.find( '> tbody > tr > [rowspan]' ).each(function () { var rowSpan = this.rowSpan; this.rowSpan = 1; var cell = $( this ); @@ -487,8 +461,8 @@ new RegExp( /^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/) ], currency: [ - new RegExp( /^[£$€?.]/), - new RegExp( /[£$€]/g) + new RegExp( /(^[£$€¥]|[£$€¥]$)/), + new RegExp( /[£$€¥]/g) ], url: [ new RegExp( /^(https?|ftp|file):\/\/$/), @@ -529,16 +503,16 @@ }, dateRegex: [], - monthNames: [], + monthNames: {}, /** * @param $tables {jQuery} * @param settings {Object} (optional) */ - construct: function( $tables, settings ) { - return $tables.each( function( i, table ) { + construct: function ( $tables, settings ) { + return $tables.each( function ( i, table ) { // Declare and cache. - var $document, $headers, cache, config, sortOrder, + var $document, $headers, cache, config, sortOrder, $table = $( table ), shiftDown = 0, firstTime = true; @@ -551,7 +525,7 @@ // No thead found. Look for rows with s and // move them into a
here + cache = buildCache( table ); + var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0; if ( !table.sortDisabled && totalRows > 0 ) { @@ -643,7 +624,7 @@ for ( var j = 0; j < config.sortList.length; j++ ) { var s = config.sortList[j], o = config.headerList[s[0]]; - if ( s[0] == i ) { + if ( s[0] === i ) { o.count = s[1]; o.count++; s[1] = o.count % 2; @@ -666,9 +647,9 @@ } // Cancel selection - } ).mousedown( function() { + } ).mousedown( function () { if ( config.cancelSelection ) { - this.onselectstart = function() { + this.onselectstart = function () { return false; }; return false; @@ -677,11 +658,11 @@ } ); }, - addParser: function( parser ) { - var l = parsers.length, + addParser: function ( parser ) { + var l = parsers.length, a = true; for ( var i = 0; i < l; i++ ) { - if ( parsers[i].id.toLowerCase() == parser.id.toLowerCase() ) { + if ( parsers[i].id.toLowerCase() === parser.id.toLowerCase() ) { a = false; } } @@ -690,9 +671,9 @@ } }, - formatDigit: function( s ) { + formatDigit: function ( s ) { if ( ts.transformTable !== false ) { - var out = '', + var out = '', c; for ( var p = 0; p < s.length; p++ ) { c = s.charAt(p); @@ -708,19 +689,19 @@ return ( isNaN(i)) ? 0 : i; }, - formatFloat: function( s ) { + formatFloat: function ( s ) { var i = parseFloat(s); return ( isNaN(i)) ? 0 : i; }, - formatInt: function( s ) { + formatInt: function ( s ) { var i = parseInt( s, 10 ); return ( isNaN(i)) ? 0 : i; }, - clearTableBody: function( table ) { + clearTableBody: function ( table ) { if ( $.browser.msie ) { - var empty = function( el ) { + var empty = function ( el ) { while ( el.firstChild ) { el.removeChild( el.firstChild ); } @@ -736,21 +717,21 @@ ts = $.tablesorter; // Register as jQuery prototype method - $.fn.tablesorter = function( settings ) { + $.fn.tablesorter = function ( settings ) { return ts.construct( this, settings ); }; // Add default parsers ts.addParser( { id: 'text', - is: function( s ) { + is: function ( s ) { return true; }, - format: function( s ) { + format: function ( s ) { s = $.trim( s.toLowerCase() ); if ( ts.collationRegex ) { var tsc = ts.collationTable; - s = s.replace( ts.collationRegex, function( match ) { + s = s.replace( ts.collationRegex, function ( match ) { var r = tsc[match] ? tsc[match] : tsc[match.toUpperCase()]; return r.toLowerCase(); } ); @@ -762,18 +743,18 @@ ts.addParser( { id: 'IPAddress', - is: function( s ) { + is: function ( s ) { return ts.rgx.IPAddress[0].test(s); }, - format: function( s ) { - var a = s.split( '.' ), + format: function ( s ) { + var a = s.split( '.' ), r = '', l = a.length; for ( var i = 0; i < l; i++ ) { var item = a[i]; - if ( item.length == 1 ) { + if ( item.length === 1 ) { r += '00' + item; - } else if ( item.length == 2 ) { + } else if ( item.length === 2 ) { r += '0' + item; } else { r += item; @@ -786,10 +767,10 @@ ts.addParser( { id: 'currency', - is: function( s ) { + is: function ( s ) { return ts.rgx.currency[0].test(s); }, - format: function( s ) { + format: function ( s ) { return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[1], '' ) ); }, type: 'numeric' @@ -797,10 +778,10 @@ ts.addParser( { id: 'url', - is: function( s ) { + is: function ( s ) { return ts.rgx.url[0].test(s); }, - format: function( s ) { + format: function ( s ) { return $.trim( s.replace( ts.rgx.url[1], '' ) ); }, type: 'text' @@ -808,10 +789,10 @@ ts.addParser( { id: 'isoDate', - is: function( s ) { + is: function ( s ) { return ts.rgx.isoDate[0].test(s); }, - format: function( s ) { + format: function ( s ) { return $.tablesorter.formatFloat((s !== '') ? new Date(s.replace( new RegExp( /-/g), '/')).getTime() : '0' ); }, @@ -820,10 +801,10 @@ ts.addParser( { id: 'usLongDate', - is: function( s ) { + is: function ( s ) { return ts.rgx.usLongDate[0].test(s); }, - format: function( s ) { + format: function ( s ) { return $.tablesorter.formatFloat( new Date(s).getTime() ); }, type: 'numeric' @@ -831,55 +812,47 @@ ts.addParser( { id: 'date', - is: function( s ) { + is: function ( s ) { return ( ts.dateRegex[0].test(s) || ts.dateRegex[1].test(s) || ts.dateRegex[2].test(s )); }, - format: function( s, table ) { + format: function ( s, table ) { + var match; s = $.trim( s.toLowerCase() ); - for ( var i = 1, j = 0; i < 13 && j < 2; i++ ) { - s = s.replace( ts.monthNames[j][i], i ); - if ( i == 12 ) { - j++; - i = 0; + if ( ( match = s.match( ts.dateRegex[0] ) ) !== null ) { + if ( mw.config.get( 'wgDefaultDateFormat' ) === 'mdy' || mw.config.get( 'wgContentLanguage' ) === 'en' ) { + s = [ match[3], match[1], match[2] ]; + } else if ( mw.config.get( 'wgDefaultDateFormat' ) === 'dmy' ) { + s = [ match[3], match[2], match[1] ]; } + } else if ( ( match = s.match( ts.dateRegex[1] ) ) !== null ) { + s = [ match[3], '' + ts.monthNames[match[2]], match[1] ]; + } else if ( ( match = s.match( ts.dateRegex[2] ) ) !== null ) { + s = [ match[3], '' + ts.monthNames[match[1]], match[2] ]; + } else { + // Should never get here + return '99999999'; } - s = s.replace( /[\-\.\,' ]/g, '/' ); - - // Replace double slashes - s = s.replace( /\/\//g, '/' ); - s = s.replace( /\/\//g, '/' ); - s = s.split( '/' ); - // Pad Month and Day - if ( s[0] && s[0].length == 1 ) { - s[0] = '0' + s[0]; - } - if ( s[1] && s[1].length == 1 ) { + if ( s[1].length === 1 ) { s[1] = '0' + s[1]; } - var y; + if ( s[2].length === 1 ) { + s[2] = '0' + s[2]; + } - if ( !s[2] ) { - // Fix yearless dates - s[2] = 2000; - } else if ( ( y = parseInt( s[2], 10) ) < 100 ) { + var y; + if ( ( y = parseInt( s[0], 10) ) < 100 ) { // Guestimate years without centuries if ( y < 30 ) { - s[2] = 2000 + y; + s[0] = 2000 + y; } else { - s[2] = 1900 + y; + s[0] = 1900 + y; } } - // Resort array depending on preferences - if ( mw.config.get( 'wgDefaultDateFormat' ) == 'mdy' || mw.config.get( 'wgContentLanguage' ) == 'en' ) { - s.push( s.shift() ); - s.push( s.shift() ); - } else if ( mw.config.get( 'wgDefaultDateFormat' ) == 'dmy' ) { - var d = s.shift(); - s.push( s.shift() ); - s.push(d); + while ( s[0].length < 4 ) { + s[0] = '0' + s[0]; } return parseInt( s.join( '' ), 10 ); }, @@ -888,10 +861,10 @@ ts.addParser( { id: 'time', - is: function( s ) { + is: function ( s ) { return ts.rgx.time[0].test(s); }, - format: function( s ) { + format: function ( s ) { return $.tablesorter.formatFloat( new Date( '2000/01/01 ' + s ).getTime() ); }, type: 'numeric' @@ -899,13 +872,13 @@ ts.addParser( { id: 'number', - is: function( s, table ) { + is: function ( s, table ) { return $.tablesorter.numberRegex.test( $.trim( s )); }, - format: function( s ) { + format: function ( s ) { return $.tablesorter.formatDigit(s); }, type: 'numeric' } ); -} )( jQuery ); +}( jQuery, mediaWiki ) ); -- cgit v1.2.2