MediaWiki:Common.js

/** Infobox collapsing script **/ $( ".infoboxBlockImage img" ).each( function {   var width = parseInt( $( this ).attr( "width" ), 10);    if ( width > 240 ) {        $( this ).attr( "height", "" );        $( this ).attr( "width", "240" );    } });

$( ".infobox:not(.infoboxNoCollapse) td" ).each( function {   if ( $( this ).html.match( /}/ ) ) {        $( this ).parent( "tr" ).hide;    } });

$( ".infobox:not(.infoboxNoCollapse) .infoboxSubsectionBreak, .infobox:not(.infoboxNoCollapse) tr.infoboxSectionHeader" ).each( function {   var flag = true,        next = $( this ).next;    while ( next && next !== undefined && next.html !== undefined && !next.hasClass( "infoboxSubsectionBreak" ) && !next.hasClass( "infoboxSectionHeader" ) ) {       if ( next.css( "display" ) != "none" ) {            flag = false;        }        next = next.next;    }    if ( flag ) {        $( this ).hide;    } });

/** Langbar **/ $( ".langbarLink" ).children( "a.new" ).parent( ".langbarLink" ).hide;

/* $( ".CraftingGrid" ).each( function {   var maxFrames = 0;
 * Automatic slide creation in crafting grids.

$( this ).find( ".CraftingGridCell" ).each( function {       var frames = $( this ).children( "span:not(.ignore), div.GridTank:not(.ignore)" ).length;        if ( frames > maxFrames) {            maxFrames = frames;        }        // Initialize cell states        $( this ).children( "span:first-child:not(.ignore), div.GridTank:first-child:not(.ignore)" ).addClass( "ActiveSlide" );    }); if ( maxFrames <= 1 ) { return; }

// Create crafting grid controls $( this ).append( ' \                           \                           1 / ' + String(maxFrames) + ' \                           " class="nextPage"> \                       '); $( this ).height( $( this ).height + $( this ).children( ".CraftingGridControls" ).height );

// Implement controls $( this ).find( ".nextPage" ).click( function {       var container = $( this ).parents( ".CraftingGrid" );        container.find( ".CraftingGridCell" ).each( function { if ( $( this ).children( ":not(.ignore)" ).length == 1) { $( this ).removeClass( ".CraftingGridCell" ); return 0; }           var cur = $( this ).find( ".ActiveSlide" ), next = cur.next( "span:not(.ignore), div.GridTank:not(.ignore)" ); if ( next.length === 0 ) { next = cur.siblings( "span:not(.ignore), div.GridTank:not(.ignore)" ).first; }           cur.removeClass( "ActiveSlide" ); next.addClass( "ActiveSlide" ); });       var pageNum = parseInt( $( this ).siblings( "span.pageNum" ).html, 10 ) + 1;        if ( pageNum > parseInt( $( this ).siblings( "span.pageCount" ).html, 10 ) ) {            pageNum = 1;        }        $( this ).siblings( "span.pageNum" ).html( pageNum );    });

$( this ).find( ".prevPage" ).click( function {       var container = $( this ).parents( ".CraftingGrid" );        container.find( ".CraftingGridCell" ).each( function { if ( $( this ).children( ":not(.ignore)" ).length == 1) { $( this ).removeClass( ".CraftingGridCell" ); return 0; }           var cur = $( this ).find( ".ActiveSlide" ), next = cur.prev( "span:not(.ignore), div.GridTank:not(.ignore)" ); if (next.length === 0) { next = cur.siblings( "span:not(.ignore), div.GridTank:not(.ignore)" ).last; }           cur.removeClass( "ActiveSlide" ); next.addClass( "ActiveSlide" ); });       var pageNum = parseInt( $( this ).siblings( "span.pageNum" ).html, 10 ) - 1;        if (pageNum === 0) {            pageNum = parseInt( $( this ).siblings( "span.pageCount" ).html, 10 );        }        $( this ).siblings( "span.pageNum" ).html(pageNum);    }); });

/* $( ".gallery > div, .gallery > span" ).addClass( "page" ); $( ".gallery" ).append( ' \                             \                             / \                             " class="nextPage"> \                         '); $( ".gallery > .page:first-child" ).addClass( "active" ); $( ".gallery span.controls span.pagenum" ).html( 1 );
 * Script for flipping through galleries, intended to be used with crafting grids.

$( ".gallery" ).each( function {   $( this ).find( "span.pagecount" ).html( $( this ).children( ".page" ).length ); });

$( ".gallery span.controls input.prevPage" ).click( function {   var cur = $( this ).parents( ".gallery" ).children( ".page.active" ),        next = cur.prev( ".page" ),        pageNum = parseInt( $( this ).siblings( "span.pagenum" ).html, 10 ) - 1;    if ( next.length === 0 ) {        next = cur.siblings( ".page" ).last;    }     cur.removeClass( "active" );    next.addClass( "active" );    if ( pageNum === 0 ) {        pageNum = parseInt( $( this ).siblings( "span.pagecount" ).html, 10 );    }    $( this ).siblings( "span.pagenum" ).html( pageNum ); });

$( ".gallery span.controls input.nextPage" ).click( function {   var cur = $( this ).parents( ".gallery" ).children( ".page.active" ),         next = cur.next( ".page" ),        pageNum = parseInt( $( this ).siblings( "span.pagenum" ).html, 10 ) + 1;    if ( next.length === 0 ) {        next = cur.siblings( ".page" ).first;    }     cur.removeClass( "active" );    next.addClass( "active" );    if (pageNum > parseInt( $( this ).siblings( "span.pagecount" ).html, 10 ) ) {        pageNum = 1;    }    $( this ).siblings( "span.pagenum" ).html( pageNum ); });

/** * Element animator (generic animation) * * Will cycle the active class on any child elements within an element with the animated class. */ // Remove from animated class if only one child $( ".animated" ).each( function {   if ( $( this ).children( "span, div" ).length == 1 ) {        $( this ).removeClass( "animated" );    } }); // Add the active class to all of the first child of .animated $( '.animated > span:first-child, .animated > div:first-child' ).addClass( 'active' ); if ( $( '.animated' ).length ) { setInterval( function {       $( '.animated' ).each( function { var current = $( this ).find( '.active' ).removeClass( 'active' ), next = current.next; if ( !current.next.length ) { next = $( this ).children.eq( 0 ); }           next.addClass( 'active' ); } );   }, 2000 ); }

/** * Pause grid templates with lots of cells in them (e.g. Template:Grid/Crafting Table) on mouseover * * This is so people have a chance to look at each image on the cell * and click on pages they want to view. */ function pauseGrid( grid ) { $( grid ).hover( function {        $( this ).find( '.grid .animated' ).removeClass( 'animated' ).addClass( 'paused' );    }, function {        $( this ).find( '.grid .paused' ).removeClass( 'paused' ).addClass( 'animated' );    } ); } pauseGrid( '.grid-Crafting_Table' ); pauseGrid( '.grid-Furnace' ); pauseGrid( '.grid-Brewing_Stand' );

$(document).ready( function {   var pops = function( elems ) {        for ( var i = 0; i < elems.length; i++ ) {            if ( !( ' ' + elems[i].className + ' ').match( / pops / ) ) {                continue;            }            var anchs = elems[i].getElementsByTagName( 'a' );            for ( var j = 0; j < anchs.length; j++ ) {                anchs[j].target = '_blank';            }        }    };    var bc = document.getElementById( 'bodyContent' ),    tags = ['span', 'div', 'table', 'td', 'th'];    for ( var i = 0; i < tags.length; i++ ) {        pops( bc.getElementsByTagName( tags[i] ) );    } } );

/** Collapsible tables ********************************************************* * * Description: Allows tables to be collapsed, showing only the header. See *                        http://www.mediawiki.org/wiki/Manual:Collapsible_tables. * Maintainers: en:User:R. Koot */ var autoCollapse = 2, collapseCaption = 'hide', expandCaption = 'show';

function collapseTable( tableIndex ) { var Button = document.getElementById( 'collapseButton' + tableIndex ), Table = document.getElementById( 'collapsibleTable' + tableIndex );

if ( !Table || !Button ) { return false; }   var Rows = Table.rows;

if ( Button.firstChild.data == collapseCaption ) { for ( var i = 1; i < Rows.length; i++ ) { Rows[i].style.display = 'none'; }       Button.firstChild.data = expandCaption; } else { for ( var j = 1; j < Rows.length; j++ ) { Rows[j].style.display = Rows[0].style.display; }       Button.firstChild.data = collapseCaption; } }

function createCollapseButtons( $content) { var tableIndex = 0, NavigationBoxes = {}, Tables = $content[0].getElementsByTagName( 'table' );

for ( var i = 0; i < Tables.length; i++ ) { if ( hasClass( Tables[i], 'collapsible' ) ) { /* only add button and increment count if there is a header row to work with */ var HeaderRow = Tables[i].getElementsByTagName( 'tr' )[0]; if ( !HeaderRow ) { continue; }           var Header = HeaderRow.getElementsByTagName( 'th' )[0]; if ( !Header ) { continue; }           NavigationBoxes[tableIndex] = Tables[i]; Tables[i].setAttribute( 'id', 'collapsibleTable' + tableIndex );

var Button = document.createElement( 'span' ), ButtonLink = document.createElement( 'a' ), ButtonText = document.createTextNode( collapseCaption );

Button.className = 'collapseButton'; // Styles are declared in MediaWiki:Common.css

ButtonLink.style.color = Header.style.color; ButtonLink.setAttribute( 'id', 'collapseButton' + tableIndex ); ButtonLink.setAttribute( 'href', "javascript:collapseTable( " + tableIndex + " );" ); Button.setAttribute( 'onClick', "collapseTable( " + tableIndex + " );" ); ButtonLink.appendChild( ButtonText );

Button.appendChild( document.createTextNode( '[' ) ); Button.appendChild( ButtonLink ); Button.appendChild( document.createTextNode( ']' ) );

Header.insertBefore( Button, Header.childNodes[0] ); Header.setAttribute( 'onClick', "collapseTable( " + tableIndex + " );" ); tableIndex++; }   }

for ( var j = 0; j < tableIndex; j++ ) { if ( hasClass( NavigationBoxes[j], 'collapsed' ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[j], 'autocollapse' ) ) ) { collapseTable( j ); } else if ( hasClass( NavigationBoxes[j], 'innercollapse' ) ) { var element = NavigationBoxes[j]; while ( element = element.parentNode ) { if ( hasClass( element, 'outercollapse' ) ) { collapseTable( j ); break; }           }        }    } }

mw.hook('wikipage.content').add( function ( content) {   ( function  { if (!content.find('.load-page').length) { console.log('Nothing to add hooks for!'); return; }       console.log( 'Adding hooks!' ); content.on( 'click', '.load-page-button > a', function( e ) {           e.preventDefault;            var button = $( this ).parent,                body = button.closest( '.load-page' );            new mw.Api.get( { action: 'parse', prop: 'text', page: body.data( 'page' ) } ).done( function ( data ) { console.log( 'Loaded data!' ); body.html( data.parse.text['*'] ); mw.hook( 'wikipage.content' ).fire( body ); } ).fail( function { console.log( 'Failed to load data!' ); } );           console.log( 'Firing request to load data!' );        } ); } );   createCollapseButtons( content ); });

/** Test if an element has a certain class ************************************** * * Description: Uses regular expressions and caching for better performance. * Maintainers: User:Mike Dillon, User:R. Koot, User:SG */

function hasClass( element, className ) { return new RegExp( "(?:\\s|^)" + className + "(?:\\s|$)" ).test( element.className ); }

/** * Creates minecraft style tooltips * * Replaces normal tooltips. Supports mcw:formatting codes (except k), * a description with line breaks ( "/" ), and character escaping with "\". */ ( function {   var tooltip,        escapeChars = { '\\&': '&#38;', '<': '&#60;', '>': '&#62;' },        escape = function( text ) {            // "\" must be escaped first            return text.replace( /\\\\/g, '&#92;' )                       .replace( /\\&|[<>]/g, function( char ) { return escapeChars[char]; } );       },        win = $( window ), winWidth, winHeight, width, height;

$( '#mw-content-text' ).on( {       'mouseenter.minetip': function( e ) {            var elem = $( this ),                title = elem.attr( 'data-minetip-title' );

// No title or title only contains formatting codes if ( title === undefined || title && title.replace( /&([0-9a-fl-or])|\s+/g,  ) ===  ) { // Find deepest child title var childElem = elem[0], childTitle; do { if ( childElem.hasAttribute( 'title' ) ) { childTitle = childElem.title; }                   childElem = childElem.firstChild; } while( childElem && childElem.nodeType === 1 ); if ( childTitle === undefined ) { return; }

// Append child title as title may contain formatting codes if ( !title ) { title = ''; }               title += childTitle;

// Set the retrieved title as data for future use elem.attr( 'data-minetip-title', title ); }

if ( !elem.data( 'minetip-ready' ) ) { // Remove title attributes so the native tooltip doesn't get in the way elem.find( '[title]' ).addBack.removeAttr( 'title' ); elem.data( 'minetip-ready', true ); }

if ( title === '' ) { return; }

// Apply normal escaping title = escape( title );

var text = ' ' + title + '&r ';

var description = elem.attr( 'data-minetip-text' ); if ( description ) { // Apply normal escaping plus "/" description = escape( description ).replace( /\\\//g, '&#47;' ); text += ' ' + description.replace( /\//g, ' ' ) + '&r '; }

// Add classes for minecraft formatting codes while ( /&[0-9a-fl-o]/.test( text ) ) { text = text.replace( /&([0-9a-fl-o])(.*?)(&r|$)/g, '$2 &r' ); }           // Remove reset formatting text = text.replace( /&r/g, '' );

// Unescape "&" so HTML entities work text = text.replace( /&#38;/g, '&' );

tooltip = $( '#minetip-tooltip' ); if ( !tooltip.length ) { tooltip = $( ' ' ).appendTo( 'body' ); }           tooltip.html( text );

// Cache current window and tooltip size winWidth = win.width; winHeight = win.height; width = tooltip.outerWidth( true ); height = tooltip.outerHeight( true );

// Trigger a mouse movement to position the tooltip elem.trigger( 'mousemove', e ); },       'mousemove.minetip': function( e, trigger ) { if ( !$( '#minetip-tooltip' ).length ) { $( this ).trigger( 'mouseenter' ); return; }

// Get event data from remote trigger e = trigger || e;

// Get mouse position and add default offsets var top = e.clientY - 34, left = e.clientX + 14;

// If going off the right of the screen, go to the left of the cursor if ( left + width > winWidth ) { left -= width + 36; }

// If now going off to the left of the screen, resort to going above the cursor if ( left < 0 ) { left = 0; top -= height - 22;

// Go below the cursor if too high if ( top < 0 ) { top += height + 47; }           // Don't go off the top of the screen } else if ( top < 0 ) { top = 0; // Don't go off the bottom of the screen } else if ( top + height > winHeight ) { top = winHeight - height; }

// Apply the positions tooltip.css( { top: top, left: left } ); },       'mouseleave.minetip': function { if ( !tooltip ) { return; }

tooltip.remove; }   }, '.minetip, .grid' ); } );

$( ".gridTankContainer" ).each( function {   // Get tank info    var max = $( this ).data( 'tank-max' ) || 10000;

// Tile liquid image $( this ).find( ".tankLiquidImageContainer.minetip .tankLiquidImage" ).each( function {       var usage = $( this ).data( 'tank-usage' ) || 5000,            imglink = $( this ).find( "img" ).hide.attr( "src" );        $( this ).css({ backgroundImage: 'url(' + imglink + ')', backgroundRepeat: 'repeat', backgroundPosition: 'bottom', height: usage / max * 100 + '%' });   }); });

/** * Special page reporting * * @athor cblair91 * @version 1.0 */ ( function ( $, mw) {   var pages = [        'BrokenRedirects',        'DoubleRedirects',        'Unusedcategories',        'Unusedimages',        'Wantedcategories',        'Wantedfiles',        'Wantedpages',        'Wantedtemplates'    ];    function getPages( page ) {        $.getJSON( '/api.php?action=query&list=querypage&qppage=' + page + '&qplimit=100&format=json', function ( data ) { $( '#' + page ).text( data.query.querypage.results.length ); });   }    function apiQuery {        for ( var i = 0; i < pages.length; i++ ) {            getPages( pages[i] );        }    }    $( function { if ( document.getElementsByClassName( 'specialMaintenance').length ) { apiQuery; }       if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Specialpages' ) { $('#mw-content-text').before(' ' +               ' Broken redirects  &bull; Double redirects  &bull; Unused categories  &bull; Unused images  ' +                ' Wanted categories  &bull; Wanted files  &bull; Wanted pages </a> &bull; Wanted templates </a> ' + ' ');           apiQuery;        }    }); }( jQuery, mediaWiki ) );