MediaWiki:Monobook.js
From A KoL Wiki
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Only javascript specific to this skin should go here. Otherwise, use [[Mediawiki:Common.js]]. <pre>*/ /* * Table sorting script based on one (c) 1997-2006 Stuart Langridge and Joost * de Valk: * http://www.joostdevalk.nl/code/sortable-table/ * http://www.kryogenix.org/code/browser/sorttable/ * * @todo don't break on colspans/rowspans (bug 8028) * @todo language-specific digit grouping/decimals (bug 8063) * @todo support all accepted date formats (bug 8226) */ window.ts_image_path = stylepath + '/common/images/'; window.ts_image_up = 'sort_up.gif'; window.ts_image_down = 'sort_down.gif'; window.ts_image_none = 'sort_none.gif'; window.ts_europeandate = wgContentLanguage != 'en'; // The non-American-inclined can change to "true" window.ts_alternate_row_colors = false; window.ts_number_transform_table = null; window.ts_number_regex = null; window.sortables_init = function() { var idnum = 0; // Find all tables with class sortable and make them sortable var tables = getElementsByClassName( document, 'table', 'sortable' ); for ( var ti = 0; ti < tables.length ; ti++ ) { if ( !tables[ti].id ) { tables[ti].setAttribute( 'id', 'sortable_table_id_' + idnum ); ++idnum; } ts_makeSortable( tables[ti] ); } // and find all old sorttables too tables = getElementsByClassName( document, 'table', 'sorttable' ); for ( var ti = 0; ti < tables.length ; ti++ ) { if ( !tables[ti].id ) { tables[ti].setAttribute( 'id', 'sortable_table_id_' + idnum ); ++idnum; } ts_makeSortable( tables[ti] ); } }; window.ts_makeSortable = function( table ) { var firstRow; if ( table.rows && table.rows.length > 0 ) { if ( table.tHead && table.tHead.rows.length > 0 ) { firstRow = table.tHead.rows[table.tHead.rows.length-1]; } else { firstRow = table.rows[0]; } } if ( !firstRow ) { return; } // We have a first row: assume it's the header, and make its contents clickable links for ( var i = 0; i < firstRow.cells.length; i++ ) { var cell = firstRow.cells[i]; if ( (' ' + cell.className + ' ').indexOf(' unsortable ') == -1 ) { $(cell).append ( '<a href="#" class="sortheader" ' + 'onclick="ts_resortTable(this);return false;">' + '<span class="sortarrow">' + '<img src="' + ts_image_path + ts_image_none + '" alt="↓"/></span></a>'); } } if ( ts_alternate_row_colors ) { ts_alternate( table ); } }; window.ts_getInnerText = function( el ) { return getInnerText( el ); }; window.ts_resortTable = function( lnk ) { // get the span var span = lnk.getElementsByTagName('span')[0]; var td = lnk.parentNode; var tr = td.parentNode; var column = td.cellIndex; var table = tr.parentNode; while ( table && !( table.tagName && table.tagName.toLowerCase() == 'table' ) ) { table = table.parentNode; } if ( !table ) { return; } if ( table.rows.length <= 1 ) { return; } // Generate the number transform table if it's not done already if ( ts_number_transform_table === null ) { ts_initTransformTable(); } // Work out a type for the column // Skip the first row if that's where the headings are var rowStart = ( table.tHead && table.tHead.rows.length > 0 ? 0 : 1 ); var bodyRows = 0; if (rowStart == 0 && table.tBodies) { for (var i=0; i < table.tBodies.length; i++ ) { bodyRows += table.tBodies[i].rows.length; } if (bodyRows < table.rows.length) rowStart = 1; } var doopt=(table.className.indexOf('complextable')>=0) ? true : false; if (doopt) { var rows=table.rows; // first, unoptimize the table for (var i = rowStart; i < rows.length-1; i++) { var cells1 = rows[i].cells; var cells2 = rows[i+1].cells; for (var j=0;j<cells1.length;j++) { var rspan = cells1[j].getAttribute('rowspan'); if (rspan && rspan>1) { var cn = cells1[j].cloneNode(true); if (cells2.length<=j) table.rows[i+1].appendChild(cn); else rows[i+1].insertBefore(cn,cells2[j]); cells1[j].removeAttribute('rowspan'); cn.setAttribute('rowspan',rspan-1); } } } } var itm = ''; for ( var i = rowStart; i < table.rows.length; i++ ) { if ( table.rows[i].cells.length > column ) { itm = ts_getInnerText(table.rows[i].cells[column]); itm = itm.replace(/^[\s\xa0]+/, '').replace(/[\s\xa0]+$/, ''); if ( itm != '' ) { break; } } } // TODO: bug 8226, localised date formats var sortfn = ts_sort_generic; var preprocessor = ts_toLowerCase; if ( /^\d\d[\/. -][a-zA-Z]{3}[\/. -]\d\d\d\d$/.test( itm ) ) { preprocessor = ts_dateToSortKey; } else if ( /^\d\d[\/.-]\d\d[\/.-]\d\d\d\d$/.test( itm ) ) { preprocessor = ts_dateToSortKey; } else if ( /^\d\d[\/.-]\d\d[\/.-]\d\d$/.test( itm ) ) { preprocessor = ts_dateToSortKey; // (minus sign)([pound dollar euro yen currency]|cents) } else if ( /(^([-\u2212] *)?[\u00a3$\u20ac\u00a4\u00a5]|\u00a2$)/.test( itm ) ) { preprocessor = ts_currencyToSortKey; } else if ( ts_number_regex.test( itm ) ) { preprocessor = ts_parseFloat; } var reverse = ( span.getAttribute( 'sortdir' ) == 'down' ); var newRows = new Array(); var staticRows = new Array(); for ( var j = rowStart; j < table.rows.length; j++ ) { var row = table.rows[j]; if( (' ' + row.className + ' ').indexOf(' unsortable ') < 0 ) { var keyText = ts_getInnerText( row.cells[column] ); if( keyText === undefined ) { keyText = ''; } var oldIndex = ( reverse ? -j : j ); var preprocessed = preprocessor( keyText.replace(/^[\s\xa0]+/, '').replace(/[\s\xa0]+$/, '') ); newRows[newRows.length] = new Array( row, preprocessed, oldIndex ); } else { staticRows[staticRows.length] = new Array( row, false, j-rowStart ); } } newRows.sort( sortfn ); var arrowHTML; if ( reverse ) { arrowHTML = '<img src="' + ts_image_path + ts_image_down + '" alt="↓"/>'; newRows.reverse(); span.setAttribute( 'sortdir', 'up' ); } else { arrowHTML = '<img src="' + ts_image_path + ts_image_up + '" alt="↑"/>'; span.setAttribute( 'sortdir', 'down' ); } for ( var i = 0; i < staticRows.length; i++ ) { var row = staticRows[i]; newRows.splice( row[2], 0, row ); } // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones // don't do sortbottom rows for ( var i = 0; i < newRows.length; i++ ) { if ( ( ' ' + newRows[i][0].className + ' ').indexOf(' sortbottom ') == -1 ) { table.tBodies[0].appendChild( newRows[i][0] ); } } // do sortbottom rows only for ( var i = 0; i < newRows.length; i++ ) { if ( ( ' ' + newRows[i][0].className + ' ').indexOf(' sortbottom ') != -1 ) { table.tBodies[0].appendChild( newRows[i][0] ); } } if (doopt) { var rows=table.rows; // now, reoptimize the table for (var i = rows.length-1;i>rowStart;i--) { var cells1 = rows[i-1].cells; var cells2 = rows[i].cells; for (var j=cells2.length-1;j>=0;j--) { if (cells1[j].innerHTML==cells2[j].innerHTML && rows[i-1].getAttribute('bgcolor')==rows[i].getAttribute('bgcolor')) { var rspan = cells2[j].getAttribute('rowspan'); if (rspan) { cells2[j].removeAttribute('rowspan'); rspan=parseInt(rspan)+1; } else { rspan=2; } rows[i].removeChild(cells2[j]); cells1[j].setAttribute('rowspan',rspan); } } } } // Delete any other arrows there may be showing var spans = getElementsByClassName( tr, 'span', 'sortarrow' ); for ( var i = 0; i < spans.length; i++ ) { spans[i].innerHTML = '<img src="' + ts_image_path + ts_image_none + '" alt="↓"/>'; } span.innerHTML = arrowHTML; if ( ts_alternate_row_colors ) { ts_alternate( table ); } }; window.ts_initTransformTable = function() { if ( typeof wgSeparatorTransformTable == 'undefined' || ( wgSeparatorTransformTable[0] == '' && wgDigitTransformTable[2] == '' ) ) { var digitClass = "[0-9,.]"; ts_number_transform_table = false; } else { ts_number_transform_table = {}; // Unpack the transform table // Separators var ascii = wgSeparatorTransformTable[0].split("\t"); var localised = wgSeparatorTransformTable[1].split("\t"); for ( var i = 0; i < ascii.length; i++ ) { ts_number_transform_table[localised[i]] = ascii[i]; } // Digits ascii = wgDigitTransformTable[0].split("\t"); localised = wgDigitTransformTable[1].split("\t"); for ( var i = 0; i < ascii.length; i++ ) { ts_number_transform_table[localised[i]] = ascii[i]; } // Construct regex for number identification var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '\\.']; var maxDigitLength = 1; for ( var digit in ts_number_transform_table ) { // Escape regex metacharacters digits.push( digit.replace( /[\\\\$\*\+\?\.\(\)\|\{\}\[\]\-]/, function( s ) { return '\\' + s; } ) ); if ( digit.length > maxDigitLength ) { maxDigitLength = digit.length; } } if ( maxDigitLength > 1 ) { var digitClass = '[' + digits.join( '', digits ) + ']'; } else { var digitClass = '(' + digits.join( '|', digits ) + ')'; } } // We allow a trailing percent sign, which we just strip. This works fine // if percents and regular numbers aren't being mixed. ts_number_regex = new RegExp( "^(" + "[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?" + // Fortran-style scientific "|" + "[-+\u2212]?" + digitClass + "+%?" + // Generic localised ")$", "i" ); }; window.ts_toLowerCase = function( s ) { return s.toLowerCase(); }; window.ts_dateToSortKey = function( date ) { // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX if ( date.length == 11 ) { switch ( date.substr( 3, 3 ).toLowerCase() ) { case 'jan': var month = '01'; break; case 'feb': var month = '02'; break; case 'mar': var month = '03'; break; case 'apr': var month = '04'; break; case 'may': var month = '05'; break; case 'jun': var month = '06'; break; case 'jul': var month = '07'; break; case 'aug': var month = '08'; break; case 'sep': var month = '09'; break; case 'oct': var month = '10'; break; case 'nov': var month = '11'; break; case 'dec': var month = '12'; break; // default: var month = '00'; } return date.substr( 7, 4 ) + month + date.substr( 0, 2 ); } else if ( date.length == 10 ) { if ( ts_europeandate == false ) { return date.substr( 6, 4 ) + date.substr( 0, 2 ) + date.substr( 3, 2 ); } else { return date.substr( 6, 4 ) + date.substr( 3, 2 ) + date.substr( 0, 2 ); } } else if ( date.length == 8 ) { var yr = date.substr( 6, 2 ); if ( parseInt( yr ) < 50 ) { yr = '20' + yr; } else { yr = '19' + yr; } if ( ts_europeandate == true ) { return yr + date.substr( 3, 2 ) + date.substr( 0, 2 ); } else { return yr + date.substr( 0, 2 ) + date.substr( 3, 2 ); } } return '00000000'; }; window.ts_parseFloat = function( s ) { if ( !s ) { return 0; } if ( ts_number_transform_table != false ) { var newNum = '', c; for ( var p = 0; p < s.length; p++ ) { c = s.charAt( p ); if ( c in ts_number_transform_table ) { newNum += ts_number_transform_table[c]; } else { newNum += c; } } s = newNum; } var num = parseFloat( s.replace(/[, ]/g, '').replace("\u2212", '-') ); return ( isNaN( num ) ? -Infinity : num ); }; window.ts_currencyToSortKey = function( s ) { return ts_parseFloat(s.replace(/[^-\u22120-9.,]/g,'')); }; window.ts_sort_generic = function( a, b ) { return a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[2] - b[2]; }; window.ts_alternate = function( table ) { // Take object table and get all it's tbodies. var tableBodies = table.getElementsByTagName( 'tbody' ); // Loop through these tbodies for ( var i = 0; i < tableBodies.length; i++ ) { // Take the tbody, and get all it's rows var tableRows = tableBodies[i].getElementsByTagName( 'tr' ); // Loop through these rows // Start at 1 because we want to leave the heading row untouched for ( var j = 0; j < tableRows.length; j++ ) { // Check if j is even, and apply classes for both possible results var oldClasses = tableRows[j].className.split(' '); var newClassName = ''; for ( var k = 0; k < oldClasses.length; k++ ) { if ( oldClasses[k] != '' && oldClasses[k] != 'even' && oldClasses[k] != 'odd' ) { newClassName += oldClasses[k] + ' '; } } tableRows[j].className = newClassName + ( j % 2 == 0 ? 'even' : 'odd' ); } } }; addOnloadHook(sortables_init); /* * End of table sorting code */ /*</pre>*/