Difference between revisions of "MediaWiki:Common.js"

From Detective Conan Wiki
(Rewrote hook function for the tabbing system so that it loads natively and can be re-used in different possible scenarios. I'll update the extension itself later to take advantage of this.)
(Main Page layout fixes not needed anymore)
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
//<source lang="javascript">
+
/**
 +
* Keep code in MediaWiki:Common.js to a minimum as it is unconditionally
 +
* loaded for all users on every wiki page. If possible create a gadget that is
 +
* enabled by default instead of adding it here (since gadgets are fully
 +
* optimized ResourceLoader modules with possibility to add dependencies etc.)
 +
*
 +
* Since Common.js isn't a gadget, there is no place to declare its
 +
* dependencies, so we have to lazy load them with mw.loader.using on demand and
 +
* then execute the rest in the callback. In most cases these dependencies will
 +
* be loaded (or loading) already and the callback will not be delayed. In case a
 +
* dependency hasn't arrived yet it'll make sure those are loaded before this.
 +
*/
  
/* Import more specific scripts if necessary */
+
/* global mw, $ */
 +
/* jshint strict:false, browser:true */
  
if (wgAction == "edit" || wgAction == "submit" || wgPageName == "Special:Upload") //scripts specific to editing pages
+
mw.loader.using( ['mediawiki.user', 'mediawiki.util', 'mediawiki.notify'] ).done( function () {
{
+
/* Begin of mw.loader.using callback */
    importScript("MediaWiki:Common.js/edit.js")
 
}
 
else if (wgPageName == "Special:Watchlist") //watchlist scripts
 
{
 
    importScript("MediaWiki:Common.js/watchlist.js")
 
}
 
  
 
+
/**
/** Sysop Javascript *******************************************************
+
* Redirect User:Name/skin.js and skin.css to the current skin's pages
  *
+
* (unless the 'skin' page really exists)
  * Description: Allows for sysop-specific Javascript at [[MediaWiki:Sysop.js]].
+
* @source: http://www.mediawiki.org/wiki/Snippets/Redirect_skin.js
  */
+
* @rev: 2
function sysopFunctions() {
+
*/
    if ( wgUserGroups && !window.disableSysopJS ) {
+
if ( mw.config.get( 'wgArticleId' ) === 0 && mw.config.get( 'wgNamespaceNumber' ) === 2 ) {
        for ( var g = 0; g < wgUserGroups.length; ++g ) {
+
var titleParts = mw.config.get( 'wgPageName' ).split( '/' );
            if ( wgUserGroups[g] == "sysop" ) {
+
/* Make sure there was a part before and after the slash
                importScript( "MediaWiki:Sysop.js" );
+
  and that the latter is 'skin.js' or 'skin.css' */
                break;
+
if ( titleParts.length == 2 ) {
            }
+
var userSkinPage = titleParts.shift() + '/' + mw.config.get( 'skin' );
        }
+
if ( titleParts.slice( -1 ) == 'skin.js' ) {
    }
+
window.location.href = mw.util.getUrl( userSkinPage + '.js' );
 +
} else if ( titleParts.slice( -1 ) == 'skin.css' ) {
 +
window.location.href = mw.util.getUrl( userSkinPage + '.css' );
 +
}
 +
}
 
}
 
}
  
addOnloadHook( sysopFunctions );
+
/**
 +
* Map addPortletLink to mw.util
 +
* @deprecated: Use mw.util.addPortletLink instead.
 +
*/
 +
mw.log.deprecate( window, 'addPortletLink', mw.util.addPortletLink, 'Use mw.util.addPortletLink instead' );
  
 +
/**
 +
* Extract a URL parameter from the current URL
 +
* @deprecated: Use mw.util.getParamValue with proper escaping
 +
*/
 +
mw.log.deprecate( window, 'getURLParamValue', mw.util.getParamValue, 'Use mw.util.getParamValue instead' );
  
/** WikiMiniAtlas *******************************************************
+
/**
  *
+
* Test if an element has a certain class
  Description: WikiMiniAtlas is a popup click and drag world map.
+
* @deprecated: Use $(element).hasClass() instead.
  *              This script causes all of our coordinate links to display the WikiMiniAtlas popup button.
+
  */
  *              The script itself is located on meta because it is used by many projects.
+
mw.log.deprecate( window, 'hasClass', function ( element, className ) {
  *              See [[Meta:WikiMiniAtlas]] for more information.
+
return $( element ).hasClass( className );
  * Maintainers: [[User:Dschwen]]
+
}, 'Use jQuery.hasClass() instead' );
  */
 
 
 
if (wgServer == "https://secure.wikimedia.org") {
 
    var metaBase = "https://secure.wikimedia.org/wikipedia/meta";
 
} else {
 
    var metaBase = "http://meta.wikimedia.org";
 
}
 
importScriptURI(metaBase+"/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400")
 
 
 
  
/** Mobile Redirect Helper ************************************************
+
/**
  *
+
  * @source www.mediawiki.org/wiki/Snippets/Load_JS_and_CSS_by_URL
*  Redirects to the mobile-optimized gateway at en.m.wikimedia.org
+
  * @rev 6
  * for viewers on iPhone, iPod Touch, Palm Pre, and Android devices.
 
*
 
*  You can turn off the redirect by setting the cookie "stopMobileRedirect=true"
 
*
 
*  This code cannot be imported, because the JS only loads after all other files
 
*  and this was causing major issues for users with mobile devices. Must be loaded
 
*  *before* the images and etc of the page on all mobile devices.
 
*
 
*  Maintainer: [[User:Brion VIBBER]], [[User:hcatlin]]
 
 
  */
 
  */
if (/(Android|iPhone|iPod|webOS)/.test(navigator.userAgent)) {
+
var extraCSS = mw.util.getParamValue( 'withCSS' ),
 +
extraJS = mw.util.getParamValue( 'withJS' );
  
  var wgMainPageName = 'Main_Page';
+
if ( extraCSS ) {
+
if ( extraCSS.match( /^MediaWiki:[^&<>=%#]*\.css$/ ) ) {
  var stopMobileRedirectCookieExists = function() {
+
mw.loader.load( '/w/index.php?title=' + extraCSS + '&action=raw&ctype=text/css', 'text/css' );
    return (document.cookie.indexOf("stopMobileRedirect=true") >= 0);
+
} else {
  }
+
mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withCSS value' } );
+
}
  var mobileSiteLink = function() {
 
    if (wgCanonicalNamespace == 'Special' && wgCanonicalSpecialPageName == 'Search') {
 
        var pageLink = '?search=' + encodeURIComponent(document.getElementById('searchText').value);
 
    } else if (wgPageName == wgMainPageName) {
 
        var pageLink = '::Home'; // Special case
 
    } else {
 
        var pageLink = encodeURIComponent(wgPageName).replace('%2F','/').replace('%3A',':');
 
    }
 
    return 'http://' + wgContentLanguage + '.m.wikipedia.org/wiki/' + pageLink + "?wasRedirected=true"
 
  }
 
 
  if (!stopMobileRedirectCookieExists()) {
 
    document.location = mobileSiteLink();
 
  }
 
 
}
 
}
  
 
+
if ( extraJS ) {
/* Scripts specific to Internet Explorer */
+
if ( extraJS.match( /^MediaWiki:[^&<>=%#]*\.js$/ ) ) {
 
+
mw.loader.load( '/w/index.php?title=' + extraJS + '&action=raw&ctype=text/javascript' );
if (navigator.appName == "Microsoft Internet Explorer")
+
} else {
{
+
mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withJS value' } );
    /** Internet Explorer bug fix **************************************************
+
}
    *
 
    *  Description: Fixes IE horizontal scrollbar bug
 
    *  Maintainers: [[User:Tom-]]?
 
    */
 
   
 
    var oldWidth;
 
    var docEl = document.documentElement;
 
   
 
    function fixIEScroll()
 
    {
 
        if (!oldWidth || docEl.clientWidth > oldWidth)
 
            doFixIEScroll();
 
        else
 
            setTimeout(doFixIEScroll, 1);
 
       
 
        oldWidth = docEl.clientWidth;
 
    }
 
   
 
    function doFixIEScroll() {
 
        docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
 
    }
 
   
 
    document.attachEvent("onreadystatechange", fixIEScroll);
 
    document.attachEvent("onresize", fixIEScroll);
 
   
 
   
 
    /**
 
    * Remove need for CSS hacks regarding MSIE and IPA.
 
    */
 
    if (document.createStyleSheet) {
 
        document.createStyleSheet().addRule('.IPA', 'font-family: "Doulos SIL", "Charis SIL", Gentium, "DejaVu Sans", Code2000, "TITUS Cyberbit Basic", "Arial Unicode MS", "Lucida Sans Unicode", "Chrysanthi Unicode";');
 
    }
 
 
 
    // In print IE (7?) does not like line-height
 
    appendCSS( '@media print { sup, sub, p, .documentDescription { line-height: normal; }}');
 
   
 
    //Import scripts specific to Internet Explorer 6
 
    if (navigator.appVersion.substr(22, 1) == "6") {
 
        importScript("MediaWiki:Common.js/IE60Fixes.js")
 
    }
 
 
}
 
}
  
 
+
/**
/* Test if an element has a certain class **************************************
+
* WikiMiniAtlas
 
  *
 
  *
  * Description: Uses regular expressions and caching for better performance.
+
  * Description: WikiMiniAtlas is a popup click and drag world map.
  * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
+
*              This script causes all of our coordinate links to display the WikiMiniAtlas popup button.
 +
*              The script itself is located on meta because it is used by many projects.
 +
  *             See [[Meta:WikiMiniAtlas]] for more information.
 +
* Note - use of this service is recommended to be repalced with mw:Help:Extension:Kartographer
 
  */
 
  */
 +
( function () {
 +
var require_wikiminiatlas = false;
 +
var coord_filter = /geohack/;
 +
$( function () {
 +
$( 'a.external.text' ).each( function( key, link ) {
 +
if ( link.href && coord_filter.exec( link.href ) ) {
 +
require_wikiminiatlas = true;
 +
// break from loop
 +
return false;
 +
}
 +
} );
 +
if ( $( 'div.kmldata' ).length ) {
 +
require_wikiminiatlas = true;
 +
}
 +
if ( require_wikiminiatlas ) {
 +
mw.loader.load( '//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript' );
 +
}
 +
} );
 +
} )();
  
var hasClass = (function () {
+
/**
    var reCache = {};
+
* Collapsible tables; reimplemented with mw-collapsibe
    return function (element, className) {
+
* Styling is also in place to avoid FOUC
        return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
+
*
    };
+
* Allows tables to be collapsed, showing only the header. See [[Help:Collapsing]].
})();
+
* @version 3.0.0 (2018-05-20)
 +
* @source https://www.mediawiki.org/wiki/MediaWiki:Gadget-collapsibleTables.js
 +
* @author [[User:R. Koot]]
 +
* @author [[User:Krinkle]]
 +
* @author [[User:TheDJ]]
 +
* @deprecated Since MediaWiki 1.20: Use class="mw-collapsible" instead which
 +
* is supported in MediaWiki core. Shimmable since MediaWiki 1.32
 +
*/
 +
function makeCollapsibleMwCollapsible( $content ) {
 +
var $tables = $content
 +
.find( 'table.collapsible:not(.mw-collapsible)' )
 +
.addClass( 'mw-collapsible' );
  
 +
$.each( $tables, function( index, table ) {
 +
// mw.log.warn( 'This page is using the deprecated class collapsible. Please replace it with mw-collapsible.');
 +
if( $( table ).hasClass( 'collapsed') ) {
 +
$( table ).addClass( 'mw-collapsed' );
 +
// mw.log.warn( 'This page is using the deprecated class collapsed. Please replace it with mw-collapsed.');
 +
}
 +
} );
 +
if( $tables.length > 0 ) {
 +
mw.loader.using( 'jquery.makeCollapsible' ).then( function() {
 +
$tables.makeCollapsible();
 +
} );
 +
}
 +
}
 +
mw.hook( 'wikipage.content' ).add( makeCollapsibleMwCollapsible );
  
/** Interwiki links to featured articles ***************************************
+
/**
 +
* Add support to mw-collapsible for autocollapse, innercollapse and outercollapse
 
  *
 
  *
  * Description: Highlights interwiki links to featured articles (or
+
  * Maintainers: TheDJ
*              equivalents) by changing the bullet before the interwiki link
 
*              into a star.
 
Maintainers: [[User:R. Koot]]
 
 
  */
 
  */
 
+
function mwCollapsibleSetup( $collapsibleContent ) {
function LinkFA()  
+
var $element,
{
+
$toggle,
    if ( document.getElementById( "p-lang" ) ) {
+
autoCollapseThreshold = 2;
        var InterwikiLinks = document.getElementById( "p-lang" ).getElementsByTagName( "li" );
+
$.each( $collapsibleContent, function (index, element) {
 
+
$element = $( element );
        for ( var i = 0; i < InterwikiLinks.length; i++ ) {
+
if ( $element.hasClass( 'collapsible' ) ) {
            if ( document.getElementById( InterwikiLinks[i].className + "-fa" ) ) {
+
$element.find('tr:first > th:first').prepend( $element.find('tr:first > * > .mw-collapsible-toggle'));
                InterwikiLinks[i].className += " FA"
+
}
                InterwikiLinks[i].title = "This is a featured article in another language.";
+
if ( $collapsibleContent.length >= autoCollapseThreshold && $element.hasClass( 'autocollapse' ) ) {
            }
+
$element.data( 'mw-collapsible' ).collapse();
        }
+
} else if ( $element.hasClass( 'innercollapse' ) ) {
    }
+
if ( $element.parents( '.outercollapse' ).length > 0 ) {
 +
$element.data( 'mw-collapsible' ).collapse();
 +
}
 +
}
 +
// because of colored backgrounds, style the link in the text color
 +
// to ensure accessible contrast
 +
$toggle = $element.find( '.mw-collapsible-toggle' );
 +
if ( $toggle.length ) {
 +
// Make the toggle inherit text color
 +
if( $toggle.parent()[0].style.color ) {
 +
$toggle.find( 'a' ).css( 'color', 'inherit' );
 +
}
 +
}
 +
} );
 
}
 
}
  
addOnloadHook( LinkFA );
+
mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );
  
 
+
/**
/** Collapsible tables *********************************************************
+
* Dynamic Navigation Bars (experimental)
 
  *
 
  *
  * Description: Allows tables to be collapsed, showing only the header. See
+
  * Description: See [[Wikipedia:NavFrame]].
*              [[Wikipedia:NavFrame]].
+
  * Maintainers: UNMAINTAINED
  * Maintainers: [[User:R. Koot]]
 
 
  */
 
  */
 +
 +
var collapseCaption = 'hide';
 +
var expandCaption = 'show';
  
var autoCollapse = 2;
+
// Set up the words in your language
var collapseCaption = "hide";
+
var navigationBarHide = '[' + collapseCaption + ']';
var expandCaption = "show";
+
var navigationBarShow = '[' + expandCaption + ']';
 
 
function collapseTable( tableIndex )
 
{
 
    var Button = document.getElementById( "collapseButton" + tableIndex );
 
    var Table = document.getElementById( "collapsibleTable" + tableIndex );
 
  
    if ( !Table || !Button ) {
+
/**
        return false;
+
  * Shows and hides content and picture (if available) of navigation bars.
    }
 
 
 
    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 i = 1; i < Rows.length; i++ ) {
 
            Rows[i].style.display = Rows[0].style.display;
 
        }
 
        Button.firstChild.data = collapseCaption;
 
    }
 
}
 
 
 
function createCollapseButtons()
 
{
 
    var tableIndex = 0;
 
    var NavigationBoxes = new Object();
 
    var Tables = document.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" );
 
            var ButtonLink = document.createElement( "a" );
 
            var ButtonText = document.createTextNode( collapseCaption );
 
 
 
            Button.className = "collapseButton"; //Styles are declared in Common.css
 
 
 
            ButtonLink.style.color = Header.style.color;
 
            ButtonLink.setAttribute( "id", "collapseButton" + tableIndex );
 
            ButtonLink.setAttribute( "href", "javascript:collapseTable(" + tableIndex + ");" );
 
            ButtonLink.appendChild( ButtonText );
 
 
 
            Button.appendChild( document.createTextNode( "[" ) );
 
            Button.appendChild( ButtonLink );
 
            Button.appendChild( document.createTextNode( "]" ) );
 
 
 
            //Modified by Maurice to allow for better flexibility
 
            //Header.insertBefore( Button, Header.childNodes[0] );
 
            Header.appendChild( Button );
 
            tableIndex++;
 
        }
 
    }
 
 
 
    for ( var i = 0;  i < tableIndex; i++ ) {
 
        if ( hasClass( NavigationBoxes[i], "collapsed" ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], "autocollapse" ) ) ) {
 
            collapseTable( i );
 
        }
 
        else if ( hasClass( NavigationBoxes[i], "innercollapse" ) ) {
 
            var element = NavigationBoxes[i];
 
            while (element = element.parentNode) {
 
                if ( hasClass( element, "outercollapse" ) ) {
 
                    collapseTable ( i );
 
                    break;
 
                }
 
            }
 
        }
 
    }
 
}
 
 
 
addOnloadHook( createCollapseButtons );
 
 
 
 
 
/** Dynamic Navigation Bars (experimental) *************************************
 
 
  *
 
  *
  * Description: See [[Wikipedia:NavFrame]].
+
  * @param {number} indexNavigationBar The index of navigation bar to be toggled
  * Maintainers: UNMAINTAINED
+
  * @param {jQuery.Event} event Event object
 
  */
 
  */
 +
function toggleNavigationBar( indexNavigationBar, event ) {
 +
var navToggle = document.getElementById( 'NavToggle' + indexNavigationBar );
 +
var navFrame = document.getElementById( 'NavFrame' + indexNavigationBar );
 +
var navChild;
  
// set up the words in your language
+
if ( !navFrame || !navToggle ) {
var NavigationBarHide = '[' + collapseCaption + ']';
+
return false;
var NavigationBarShow = '[' + expandCaption + ']';
+
}
  
// shows and hides content and picture (if available) of navigation bars
+
// If shown now
// Parameters:
+
if ( navToggle.firstChild.data === navigationBarHide ) {
//    indexNavigationBar: the index of navigation bar to be toggled
+
for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
function toggleNavigationBar(indexNavigationBar)
+
if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
{
+
navChild.style.display = 'none';
    var NavToggle = document.getElementById("NavToggle" + indexNavigationBar);
+
}
    var NavFrame = document.getElementById("NavFrame" + indexNavigationBar);
+
}
 +
navToggle.firstChild.data = navigationBarShow;
  
    if (!NavFrame || !NavToggle) {
+
// If hidden now
        return false;
+
} else if ( navToggle.firstChild.data === navigationBarShow ) {
    }
+
for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
 
+
if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
    // if shown now
+
navChild.style.display = 'block';
    if (NavToggle.firstChild.data == NavigationBarHide) {
+
}
        for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
+
}
            if ( hasClass( NavChild, 'NavPic' ) ) {
+
navToggle.firstChild.data = navigationBarHide;
                NavChild.style.display = 'none';
+
}
            }
 
            if ( hasClass( NavChild, 'NavContent') ) {
 
                NavChild.style.display = 'none';
 
            }
 
        }
 
    NavToggle.firstChild.data = NavigationBarShow;
 
  
    // if hidden now
+
event.preventDefault();
    } else if (NavToggle.firstChild.data == NavigationBarShow) {
 
        for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
 
            if (hasClass(NavChild, 'NavPic')) {
 
                NavChild.style.display = 'block';
 
            }
 
            if (hasClass(NavChild, 'NavContent')) {
 
                NavChild.style.display = 'block';
 
            }
 
        }
 
        NavToggle.firstChild.data = NavigationBarHide;
 
    }
 
 
}
 
}
  
// adds show/hide-button to navigation bars
+
/**
function createNavigationBarToggleButton()
+
* Adds show/hide-button to navigation bars.
{
 
    var indexNavigationBar = 0;
 
    // iterate over all < div >-elements
 
    var divs = document.getElementsByTagName("div");
 
    for (var i = 0; NavFrame = divs[i]; i++) {
 
        // if found a navigation bar
 
        if (hasClass(NavFrame, "NavFrame")) {
 
 
 
            indexNavigationBar++;
 
            var NavToggle = document.createElement("a");
 
            NavToggle.className = 'NavToggle';
 
            NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar);
 
            NavToggle.setAttribute('href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');');
 
 
 
            var isCollapsed = hasClass( NavFrame, "collapsed" );
 
            /*
 
            * Check if any children are already hidden.  This loop is here for backwards compatibility:
 
            * the old way of making NavFrames start out collapsed was to manually add style="display:none"
 
            * to all the NavPic/NavContent elements.  Since this was bad for accessibility (no way to make
 
            * the content visible without JavaScript support), the new recommended way is to add the class
 
            * "collapsed" to the NavFrame itself, just like with collapsible tables.
 
            */
 
            for (var NavChild = NavFrame.firstChild; NavChild != null && !isCollapsed; NavChild = NavChild.nextSibling) {
 
                if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
 
                    if ( NavChild.style.display == 'none' ) {
 
                        isCollapsed = true;
 
                    }
 
                }
 
            }
 
            if (isCollapsed) {
 
                for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
 
                    if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
 
                        NavChild.style.display = 'none';
 
                    }
 
                }
 
            }
 
            var NavToggleText = document.createTextNode(isCollapsed ? NavigationBarShow : NavigationBarHide);
 
            NavToggle.appendChild(NavToggleText);
 
 
 
            // Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
 
            for(var j=0; j < NavFrame.childNodes.length; j++) {
 
                if (hasClass(NavFrame.childNodes[j], "NavHead")) {
 
                    NavFrame.childNodes[j].appendChild(NavToggle);
 
                }
 
            }
 
            NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
 
        }
 
    }
 
}
 
 
 
addOnloadHook( createNavigationBarToggleButton );
 
 
 
 
 
/** Main Page layout fixes *********************************************************
 
 
  *
 
  *
  * Description: Adds an additional link to the complete list of languages available.
+
  * @param {jQuery} $content
*  Maintainers: [[User:AzaToth]], [[User:R. Koot]], [[User:Alex Smotrov]]
 
 
  */
 
  */
 +
function createNavigationBarToggleButton( $content ) {
 +
var i, j, navChild, navToggle, navToggleText, isCollapsed,
 +
indexNavigationBar = 0;
 +
// Iterate over all < div >-elements
 +
var $divs = $content.find( 'div.NavFrame:not(.mw-collapsible)' );
 +
$divs.each( function ( i, navFrame ) {
 +
indexNavigationBar++;
 +
navToggle = document.createElement( 'a' );
 +
navToggle.className = 'NavToggle';
 +
navToggle.setAttribute( 'id', 'NavToggle' + indexNavigationBar );
 +
navToggle.setAttribute( 'href', '#' );
 +
$( navToggle ).on( 'click', $.proxy( toggleNavigationBar, null, indexNavigationBar ) );
  
if (wgPageName == 'Main_Page' || wgPageName == 'Talk:Main_Page')  
+
isCollapsed = $( navFrame ).hasClass( 'collapsed' );
    addOnloadHook(function () {
+
/**
        addPortletLink('p-lang', 'http://meta.wikimedia.org/wiki/List_of_Wikipedias',
+
* Check if any children are already hidden.  This loop is here for backwards compatibility:
                'Complete list', 'interwiki-completelist', 'Complete list of Wikipedias')
+
* the old way of making NavFrames start out collapsed was to manually add style="display:none"
        var nstab = document.getElementById('ca-nstab-main')
+
* to all the NavPic/NavContent elements.  Since this was bad for accessibility (no way to make
        if (nstab && wgUserLanguage=='en')  
+
* the content visible without JavaScript support), the new recommended way is to add the class
            nstab.firstChild.firstChild.nodeValue = 'Main Page'
+
* "collapsed" to the NavFrame itself, just like with collapsible tables.
    }
+
*/
)
+
for ( navChild = navFrame.firstChild; navChild !== null && !isCollapsed; navChild = navChild.nextSibling ) {
 +
if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
 +
if ( navChild.style.display === 'none' ) {
 +
isCollapsed = true;
 +
}
 +
}
 +
}
 +
if ( isCollapsed ) {
 +
for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
 +
if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
 +
navChild.style.display = 'none';
 +
}
 +
}
 +
}
 +
navToggleText = document.createTextNode( isCollapsed ? navigationBarShow : navigationBarHide );
 +
navToggle.appendChild( navToggleText );
  
 
+
// Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
/** Table sorting fixes ************************************************
+
for ( j = 0; j < navFrame.childNodes.length; j++ ) {
  *
+
if ( $( navFrame.childNodes[j] ).hasClass( 'NavHead' ) ) {
  *  Description: Disables code in table sorting routine to set classes on even/odd rows
+
navToggle.style.color = navFrame.childNodes[j].style.color;
  *  Maintainers: [[User:Random832]]
+
navFrame.childNodes[j].appendChild( navToggle );
  */
+
}
 
+
}
ts_alternate_row_colors = false;
+
navFrame.setAttribute( 'id', 'NavFrame' + indexNavigationBar );
 
+
} );
 
 
/***** uploadwizard_newusers ********
 
* Switches in a message for non-autoconfirmed users at [[Wikipedia:Upload]]
 
*
 
*  Maintainers: [[User:Krimpet]]
 
****/
 
function uploadwizard_newusers() {
 
  if (wgNamespaceNumber == 4 && wgTitle == "Upload" && wgAction == "view") {
 
    var oldDiv = document.getElementById("autoconfirmedusers"),
 
        newDiv = document.getElementById("newusers");
 
    if (oldDiv && newDiv) {
 
      if (typeof wgUserGroups == "object" && wgUserGroups) {
 
        for (i = 0; i < wgUserGroups.length; i++) {
 
          if (wgUserGroups[i] == "autoconfirmed") {
 
            oldDiv.style.display = "block";
 
            newDiv.style.display = "none";
 
            return;
 
          }
 
        }
 
      }
 
      oldDiv.style.display = "none";
 
      newDiv.style.display = "block";
 
      return;
 
    }
 
  }
 
 
}
 
}
addOnloadHook(uploadwizard_newusers);
 
  
 +
mw.hook( 'wikipage.content' ).add( createNavigationBarToggleButton );
  
/** IPv6 AAAA connectivity testing **/
+
/**
 
+
* Magic editintros ****************************************************
var __ipv6wwwtest_factor = 100;
 
var __ipv6wwwtest_done = 0;
 
if ((wgServer != "https://secure.wikimedia.org") && (Math.floor(Math.random()*__ipv6wwwtest_factor)==42)) {
 
    importScript("MediaWiki:Common.js/IPv6.js");
 
}
 
 
 
/** Magic editintros ****************************************************
 
 
  *
 
  *
  * Description: Adds editintros on disambiguation pages and BLP pages.
+
  * Description: Adds editintros on disambiguation pages and BLP pages.
  * Maintainers: [[User:RockMFR]]
+
  * Maintainers: [[User:RockMFR]]
 
  */
 
  */
 
+
function addEditIntro( name ) {
function addEditIntro(name)
+
$( '.mw-editsection, #ca-edit, #ca-ve-edit' ).find( 'a' ).each( function ( i, el ) {
{
+
el.href = $( this ).attr( 'href' ) + '&editintro=' + name;
  var el = document.getElementById('ca-edit');
+
} );
  if (!el)
 
    return;
 
  el = el.getElementsByTagName('a')[0];
 
  if (el)
 
    el.href += '&editintro=' + name;
 
 
}
 
}
  
 +
if ( mw.config.get( 'wgNamespaceNumber' ) === 0 ) {
 +
$( function () {
 +
if ( document.getElementById( 'disambigbox' ) ) {
 +
addEditIntro( 'Template:Disambig_editintro' );
 +
}
 +
} );
  
if (wgNamespaceNumber == 0) {
+
$( function () {
  addOnloadHook(function(){
+
var cats = mw.config.get('wgCategories');
    if (document.getElementById('disambigbox'))
+
if ( !cats ) {
      addEditIntro('Template:Disambig_editintro');
+
return;
  });
+
}
 
+
if ( $.inArray( 'Living people', cats ) !== -1 || $.inArray( 'Possibly living people', cats ) !== -1 ) {
  addOnloadHook(function(){
+
addEditIntro( 'Template:BLP_editintro' );
    var cats = document.getElementById('mw-normal-catlinks');
+
}
    if (!cats)
+
} );
      return;
 
    cats = cats.getElementsByTagName('a');
 
    for (var i = 0; i < cats.length; i++) {
 
      if (cats[i].title == 'Category:Living people' || cats[i].title == 'Category:Possibly living people') {
 
        addEditIntro('Template:BLP_editintro');
 
        break;
 
      }
 
    }
 
  });
 
 
}
 
}
  
var OnloadHook = {};
+
/* Actions specific to the edit page */
 
+
if ( mw.config.get( 'wgAction' ) === 'edit' || mw.config.get( 'wgAction' ) === 'submit' ) {
function addTabsToHook (jsId, width) {
+
/**
OnloadHook[jsId] = {
+
* Fix edit summary prompt for undo
                name: jsId,
+
*
                jsWidth: width,
+
*  Fixes the fact that the undo function combined with the "no edit summary prompter"
check: function () {
+
*  complains about missing editsummary, if leaving the edit summary unchanged.
if (typeof($) == "undefined") return true;
+
*  Added by [[User:Deskana]], code by [[User:Tra]].
if (typeof($.ui) == "undefined") return true;
+
*  See also [[phab:T10912]].
if (typeof($.fn["tabs"]) == "undefined") return true;
+
*/
if (typeof($("#"+this.name).tabs) == "undefined") return true;
+
$(function () {
this.initTabLink();
+
if (document.location.search.indexOf('undo=') !== -1 && document.getElementsByName('wpAutoSummary')[0]) {
return false;
+
document.getElementsByName('wpAutoSummary')[0].value = '1';
},
 
initTabLink: function ()
 
{
 
var strTabLink = "";
 
for(var name in TabsIndex)
 
{
 
var jsId = name;
 
var strTitle = TabsIndex[name].title;
 
strTabLink += "<li><a href=\"#"+jsId+"\"><span>"+strTitle+"</span></a></li>";
 
}
 
var tabs = $("#" + this.name + "_ul");
 
tabs.html(strTabLink);
 
},
 
func: function ()
 
{
 
var jsId = this.name;
 
var jsWidth = this.jsWidth;
 
var cmd = this;
 
if (cmd.check()) {
 
cmd.hTimer = setTimeout("OnloadHook['"+jsId+"'].func()",500);
 
} else
 
{
 
clearTimeout(cmd.hTimer);
 
$(document).ready(function(){
 
with ($("#"+jsId))
 
{
 
css("display", "inline-block");
 
css("overflow", "hidden");
 
if (jsWidth > 0)
 
css("width", jsWidth + "px");
 
tabs();
 
}
 
});
 
}
 
 
}
 
}
};
+
});
}
 
 
 
window.runOnloadHook = function() {
 
    for(var name in OnloadHook)
 
        OnloadHook[name].func();
 
 
}
 
}
  
//</source>
+
/* End of mw.loader.using callback */
 +
} );
 +
/* DO NOT ADD CODE BELOW THIS LINE */

Latest revision as of 15:39, 23 March 2022

/**
 * Keep code in MediaWiki:Common.js to a minimum as it is unconditionally
 * loaded for all users on every wiki page. If possible create a gadget that is
 * enabled by default instead of adding it here (since gadgets are fully
 * optimized ResourceLoader modules with possibility to add dependencies etc.)
 *
 * Since Common.js isn't a gadget, there is no place to declare its
 * dependencies, so we have to lazy load them with mw.loader.using on demand and
 * then execute the rest in the callback. In most cases these dependencies will
 * be loaded (or loading) already and the callback will not be delayed. In case a
 * dependency hasn't arrived yet it'll make sure those are loaded before this.
 */

/* global mw, $ */
/* jshint strict:false, browser:true */

mw.loader.using( ['mediawiki.user', 'mediawiki.util', 'mediawiki.notify'] ).done( function () {
/* Begin of mw.loader.using callback */

/**
 * Redirect User:Name/skin.js and skin.css to the current skin's pages
 * (unless the 'skin' page really exists)
 * @source: http://www.mediawiki.org/wiki/Snippets/Redirect_skin.js
 * @rev: 2
 */
if ( mw.config.get( 'wgArticleId' ) === 0 && mw.config.get( 'wgNamespaceNumber' ) === 2 ) {
	var titleParts = mw.config.get( 'wgPageName' ).split( '/' );
	/* Make sure there was a part before and after the slash
	   and that the latter is 'skin.js' or 'skin.css' */
	if ( titleParts.length == 2 ) {
		var userSkinPage = titleParts.shift() + '/' + mw.config.get( 'skin' );
		if ( titleParts.slice( -1 ) == 'skin.js' ) {
			window.location.href = mw.util.getUrl( userSkinPage + '.js' );
		} else if ( titleParts.slice( -1 ) == 'skin.css' ) {
			window.location.href = mw.util.getUrl( userSkinPage + '.css' );
		}
	}
}

/**
 * Map addPortletLink to mw.util
 * @deprecated: Use mw.util.addPortletLink instead.
 */
mw.log.deprecate( window, 'addPortletLink', mw.util.addPortletLink, 'Use mw.util.addPortletLink instead' );

/**
 * Extract a URL parameter from the current URL
 * @deprecated: Use mw.util.getParamValue with proper escaping
 */
mw.log.deprecate( window, 'getURLParamValue', mw.util.getParamValue, 'Use mw.util.getParamValue instead' );

/**
 * Test if an element has a certain class
 * @deprecated:  Use $(element).hasClass() instead.
 */
mw.log.deprecate( window, 'hasClass', function ( element, className ) {
	return $( element ).hasClass( className );
}, 'Use jQuery.hasClass() instead' );

/**
 * @source www.mediawiki.org/wiki/Snippets/Load_JS_and_CSS_by_URL
 * @rev 6
 */
var extraCSS = mw.util.getParamValue( 'withCSS' ),
	extraJS = mw.util.getParamValue( 'withJS' );

if ( extraCSS ) {
	if ( extraCSS.match( /^MediaWiki:[^&<>=%#]*\.css$/ ) ) {
		mw.loader.load( '/w/index.php?title=' + extraCSS + '&action=raw&ctype=text/css', 'text/css' );
	} else {
		mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withCSS value' } );
	}
}

if ( extraJS ) {
	if ( extraJS.match( /^MediaWiki:[^&<>=%#]*\.js$/ ) ) {
		mw.loader.load( '/w/index.php?title=' + extraJS + '&action=raw&ctype=text/javascript' );
	} else {
		mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withJS value' } );
	}
}

/**
 * WikiMiniAtlas
 *
 * Description: WikiMiniAtlas is a popup click and drag world map.
 *              This script causes all of our coordinate links to display the WikiMiniAtlas popup button.
 *              The script itself is located on meta because it is used by many projects.
 *              See [[Meta:WikiMiniAtlas]] for more information.
 * Note - use of this service is recommended to be repalced with mw:Help:Extension:Kartographer
 */
( function () {
	var require_wikiminiatlas = false;
	var coord_filter = /geohack/;
	$( function () {
		$( 'a.external.text' ).each( function( key, link ) {
			if ( link.href && coord_filter.exec( link.href ) ) {
				require_wikiminiatlas = true;
				// break from loop
				return false;
			}
		} );
		if ( $( 'div.kmldata' ).length ) {
			require_wikiminiatlas = true;
		}
		if ( require_wikiminiatlas ) {
			mw.loader.load( '//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript' );
		}
	} );
} )();

/**
 * Collapsible tables; reimplemented with mw-collapsibe
 * Styling is also in place to avoid FOUC
 * 
 * Allows tables to be collapsed, showing only the header. See [[Help:Collapsing]].
 * @version 3.0.0 (2018-05-20)
 * @source https://www.mediawiki.org/wiki/MediaWiki:Gadget-collapsibleTables.js
 * @author [[User:R. Koot]]
 * @author [[User:Krinkle]]
 * @author [[User:TheDJ]]
 * @deprecated Since MediaWiki 1.20: Use class="mw-collapsible" instead which
 * is supported in MediaWiki core. Shimmable since MediaWiki 1.32
 */
function makeCollapsibleMwCollapsible( $content ) {
	var $tables = $content
		.find( 'table.collapsible:not(.mw-collapsible)' )
		.addClass( 'mw-collapsible' );

	$.each( $tables, function( index, table ) {
		// mw.log.warn( 'This page is using the deprecated class collapsible. Please replace it with mw-collapsible.');
		if( $( table ).hasClass( 'collapsed') ) {
			$( table ).addClass( 'mw-collapsed' );
			// mw.log.warn( 'This page is using the deprecated class collapsed. Please replace it with mw-collapsed.');
		}
	} );
	if( $tables.length > 0 ) {
		mw.loader.using( 'jquery.makeCollapsible' ).then( function() {
			$tables.makeCollapsible();
		} );
	}
}
mw.hook( 'wikipage.content' ).add( makeCollapsibleMwCollapsible );

/**
 * Add support to mw-collapsible for autocollapse, innercollapse and outercollapse
 *
 * Maintainers: TheDJ
 */
function mwCollapsibleSetup( $collapsibleContent ) {
	var $element,
		$toggle,
		autoCollapseThreshold = 2;
	$.each( $collapsibleContent, function (index, element) {
		$element = $( element );
		if ( $element.hasClass( 'collapsible' ) ) {
			$element.find('tr:first > th:first').prepend( $element.find('tr:first > * > .mw-collapsible-toggle'));
		}
		if ( $collapsibleContent.length >= autoCollapseThreshold && $element.hasClass( 'autocollapse' ) ) {
			$element.data( 'mw-collapsible' ).collapse();
		} else if ( $element.hasClass( 'innercollapse' ) ) {
			if ( $element.parents( '.outercollapse' ).length > 0 ) {
				$element.data( 'mw-collapsible' ).collapse();
			}
		}
		// because of colored backgrounds, style the link in the text color
		// to ensure accessible contrast
		$toggle = $element.find( '.mw-collapsible-toggle' );
		if ( $toggle.length ) {
			// Make the toggle inherit text color
			if( $toggle.parent()[0].style.color ) {
				$toggle.find( 'a' ).css( 'color', 'inherit' );
			}
		}
	} );
}

mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );

/**
 * Dynamic Navigation Bars (experimental)
 *
 * Description: See [[Wikipedia:NavFrame]].
 * Maintainers: UNMAINTAINED
 */
 
var collapseCaption = 'hide';
var expandCaption = 'show';

// Set up the words in your language
var navigationBarHide = '[' + collapseCaption + ']';
var navigationBarShow = '[' + expandCaption + ']';

/**
 * Shows and hides content and picture (if available) of navigation bars.
 *
 * @param {number} indexNavigationBar The index of navigation bar to be toggled
 * @param {jQuery.Event} event Event object
 */
function toggleNavigationBar( indexNavigationBar, event ) {
	var navToggle = document.getElementById( 'NavToggle' + indexNavigationBar );
	var navFrame = document.getElementById( 'NavFrame' + indexNavigationBar );
	var navChild;

	if ( !navFrame || !navToggle ) {
		return false;
	}

	// If shown now
	if ( navToggle.firstChild.data === navigationBarHide ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'none';
			}
		}
		navToggle.firstChild.data = navigationBarShow;

	// If hidden now
	} else if ( navToggle.firstChild.data === navigationBarShow ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'block';
			}
		}
		navToggle.firstChild.data = navigationBarHide;
	}

	event.preventDefault();
}

/**
 * Adds show/hide-button to navigation bars.
 *
 * @param {jQuery} $content
 */
function createNavigationBarToggleButton( $content ) {
	var i, j, navChild, navToggle, navToggleText, isCollapsed,
		indexNavigationBar = 0;
	// Iterate over all < div >-elements
	var $divs = $content.find( 'div.NavFrame:not(.mw-collapsible)' );
	$divs.each( function ( i, navFrame ) {
		indexNavigationBar++;
		navToggle = document.createElement( 'a' );
		navToggle.className = 'NavToggle';
		navToggle.setAttribute( 'id', 'NavToggle' + indexNavigationBar );
		navToggle.setAttribute( 'href', '#' );
		$( navToggle ).on( 'click', $.proxy( toggleNavigationBar, null, indexNavigationBar ) );

		isCollapsed = $( navFrame ).hasClass( 'collapsed' );
		/**
		 * Check if any children are already hidden.  This loop is here for backwards compatibility:
		 * the old way of making NavFrames start out collapsed was to manually add style="display:none"
		 * to all the NavPic/NavContent elements.  Since this was bad for accessibility (no way to make
		 * the content visible without JavaScript support), the new recommended way is to add the class
		 * "collapsed" to the NavFrame itself, just like with collapsible tables.
		 */
		for ( navChild = navFrame.firstChild; navChild !== null && !isCollapsed; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
				if ( navChild.style.display === 'none' ) {
					isCollapsed = true;
				}
			}
		}
		if ( isCollapsed ) {
			for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
				if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
					navChild.style.display = 'none';
				}
			}
		}
		navToggleText = document.createTextNode( isCollapsed ? navigationBarShow : navigationBarHide );
		navToggle.appendChild( navToggleText );

		// Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
		for ( j = 0; j < navFrame.childNodes.length; j++ ) {
			if ( $( navFrame.childNodes[j] ).hasClass( 'NavHead' ) ) {
				navToggle.style.color = navFrame.childNodes[j].style.color;
				navFrame.childNodes[j].appendChild( navToggle );
			}
		}
		navFrame.setAttribute( 'id', 'NavFrame' + indexNavigationBar );
	} );
}

mw.hook( 'wikipage.content' ).add( createNavigationBarToggleButton );

/**
 * Magic editintros ****************************************************
 *
 * Description: Adds editintros on disambiguation pages and BLP pages.
 * Maintainers: [[User:RockMFR]]
 */
function addEditIntro( name ) {
	$( '.mw-editsection, #ca-edit, #ca-ve-edit' ).find( 'a' ).each( function ( i, el ) {
		el.href = $( this ).attr( 'href' ) + '&editintro=' + name;
	} );
}

if ( mw.config.get( 'wgNamespaceNumber' ) === 0 ) {
	$( function () {
		if ( document.getElementById( 'disambigbox' ) ) {
			addEditIntro( 'Template:Disambig_editintro' );
		}
	} );

	$( function () {
		var cats = mw.config.get('wgCategories');
		if ( !cats ) {
			return;
		}
		if ( $.inArray( 'Living people', cats ) !== -1 || $.inArray( 'Possibly living people', cats ) !== -1 ) {
			addEditIntro( 'Template:BLP_editintro' );
		}
	} );
}

/* Actions specific to the edit page */
if ( mw.config.get( 'wgAction' ) === 'edit' || mw.config.get( 'wgAction' ) === 'submit' ) {
	/**
	 * Fix edit summary prompt for undo
	 *
	 *  Fixes the fact that the undo function combined with the "no edit summary prompter"
	 *  complains about missing editsummary, if leaving the edit summary unchanged.
	 *  Added by [[User:Deskana]], code by [[User:Tra]].
	 *  See also [[phab:T10912]].
	 */
	$(function () {
		if (document.location.search.indexOf('undo=') !== -1 && document.getElementsByName('wpAutoSummary')[0]) {
			document.getElementsByName('wpAutoSummary')[0].value = '1';
		}
	});
}

/* End of mw.loader.using callback */
} );
/* DO NOT ADD CODE BELOW THIS LINE */