MediaWiki:Common.js: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
m (tweak to hover item box to position item image on right of item box by default)
(Just kidding. MediaWiki itself still throws an error if you use ES6 syntax. So much for embracing modernity.)
 
(41 intermediate revisions by 5 users not shown)
Line 1: Line 1:
/***
/* global mw */
* Redirect User:Name/skin.js and skin.css to the current skin's pages
/* jshint strict:true, jquery:true, esversion:5, bitwise:true, curly:true, eqeqeq:true, undef:true */
* (unless the 'skin' page really exists)
 
* @source: http://www.mediawiki.org/wiki/Snippets/Redirect_skin.js
( function() {
* @rev: 2
'use strict';
*/
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.wikiGetlink( userSkinPage + '.js' );
} else if ( titleParts.slice(-1) == 'skin.css' ) {
window.location.href = mw.util.wikiGetlink( userSkinPage + '.css' );
}
}
}


/** Map addPortletLink to mw.util
/* Translation strings */
*/
var i18n = {
window.addPortletLink = function(){
    expandAll: 'Expand all',
return mw.util.addPortletLink.apply( mw.util, arguments );
    collapseAll: 'Collapse all',
    defaultLicense: 'Copyright unlicensed',
};
};


/** extract a URL parameter from the current URL **********
/**
  *
  * Hoverbox
  * @deprecated: Use mw.util.getParamValue with proper escaping
  * @param  config  Object containing configuration
  */
  */
function getURLParamValue(paramName, url) {
function hoverbox(config) {
return mw.util.getParamValue(paramName, url);
    var defaults = {
}
        mainClass: 'hoverbox',
 
        activatorClass: 'hoverbox__activator',
/** &withCSS= and &withJS= URL parameters *******
        displayClass: 'hoverbox__display',
* Allow to try custom scripts from MediaWiki space
    };
* without editing personal .css or .js files
    config = Object.assign(defaults, config);
*/
    var timestamp = Date.now(),
var extraCSS = mw.util.getParamValue("withCSS");
        $container = $('#hoverbox-displays-' + timestamp);
if ( extraCSS && extraCSS.match(/^MediaWiki:[^&<>=%]*\.css$/) ) {
    if ( $container.length === 0 ) {
    importStylesheet(extraCSS);
        $container = $('<div id="hoverbox-displays-' + timestamp + '" class="hoverbox-display-container"></div>');
}
    }
var extraJS = mw.util.getParamValue("withJS");
     $('body').append($container);
if ( extraJS && extraJS.match(/^MediaWiki:[^&<>=%]*\.js$/) ) {
    var $hoverbox = $('.' + config.mainClass),
    importScript(extraJS);
        idCounter = 0;
}
    $hoverbox.each(function() {
 
        var $this = $(this),
// makeCollapsible (remove when deployed)
            $activator = $this.find('.' + config.activatorClass).first(),
importStylesheet('MediaWiki:JQuery-makeCollapsible.css');
            $display = $this.find('.' + config.displayClass).first(),
importScript('MediaWiki:JQuery-makeCollapsible.js');  
            id = $this.data('hoverbox-id') || idCounter++,
 
            $target = $container.find('[data-hoverbox-target="' + id + '"]');
 
        if ( $target.length === 0 ) {
/* Import more specific scripts if necessary */
            $container.append($display);
if (wgAction == 'edit' || wgAction == 'submit' || wgPageName == 'Special:Upload') { //scripts specific to editing pages
            $display.attr('data-hoverbox-target', id);
    importScript('MediaWiki:Common.js/edit.js');
}
else if (mw.config.get('wgPageName') == 'Special:Watchlist') { //watchlist scripts
    mw.loader.load(mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=MediaWiki:Common.js/watchlist.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400');
}
 
if ( wgNamespaceNumber == 6 ) {
     importScript('MediaWiki:Common.js/file.js');
}
 
/** For sysops and accountcreators *****************************************
*
*  Description: Allows for sysop-specific Javascript at [[MediaWiki:Sysop.js]],
*              and accountcreator-specific CSS at [[MediaWiki:Accountcreator.css]].
*/
if ( $.inArray( 'sysop', wgUserGroups) > -1 ) {
importStylesheet('MediaWiki:Sysop.css');
if ( !window.disableSysopJS ) {
  $(function(){
  importScript('MediaWiki:Sysop.js');
  });
}
} else if ( $.inArray( 'accountcreator', wgUserGroups ) > -1 ) {
importStylesheet('MediaWiki:Accountcreator.css');
}
 
 
/** 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.
  *  Maintainers: [[User:Dschwen]]
  */
 
var metaBase = 'http://meta.wikimedia.org';
if ( mw.config.get( 'wgServer' ) == 'https://secure.wikimedia.org' ) {
var metaBase = 'https://secure.wikimedia.org/wikipedia/meta';
}
mw.loader.load(metaBase + '/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400');
 
/* Scripts specific to Internet Explorer */
if (navigator.appName == 'Microsoft Internet Explorer'){
    /** Internet Explorer bug fix **************************************************
    *
    *  Description: Fixes IE horizontal scrollbar bug
    *  Maintainers: [[User:Tom-]]?
    */
   
    var oldWidth;
    var docEl = document.documentElement;
   
    var fixIEScroll = function() {
        if (!oldWidth || docEl.clientWidth > oldWidth) {
            doFixIEScroll();
         } else {
         } else {
             setTimeout(doFixIEScroll, 1);
             $display.remove();
            $display = $target;
         }
         }
          
         $activator.hover(function() {
        oldWidth = docEl.clientWidth;
            var viewport = {},
    };
                activator = {},
   
                display = {},
    var doFixIEScroll = function () {
                position, // position relative to the activator
        docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
                location; // location relative to the viewport
    };
            viewport.width = document.documentElement.clientWidth;
   
            viewport.height = document.documentElement.clientHeight;
    document.attachEvent("onreadystatechange", fixIEScroll);
            viewport.top = document.documentElement.scrollTop;
    document.attachEvent("onresize", fixIEScroll);
            viewport.left = document.documentElement.scrollLeft;
   
            viewport.bottom = viewport.top + viewport.height;
    // In print IE (7?) does not like line-height
            viewport.right = viewport.left + viewport.width;
    mw.util.addCSS( '@media print { sup, sub, p, .documentDescription { line-height: normal; }}');
            activator.width = $activator.outerWidth();
 
            activator.height = $activator.outerHeight();
    // IE overflow bug
            activator.top = $activator.offset().top;
    mw.util.addCSS('div.overflowbugx { overflow-x: scroll !important; overflow-y: hidden !important; } div.overflowbugy { overflow-y: scroll !important; overflow-x: hidden !important; }');
            activator.left = $activator.offset().left;
 
            activator.bottom = activator.top + activator.height;
    // IE zoomfix
            activator.right = activator.left + activator.width;
    // Use to fix right floating div/table inside tables
            display.width = $display.outerWidth();
    mw.util.addCSS('.iezoomfix div, .iezoomfix table { zoom: 1;}');
            display.height = $display.outerHeight();
}
            if (viewport.width < display.width) { // Don't bother showing the hoverbox at all if the viewport is too small
 
                return false;
/* Load fixes for Windows font rendering */
            }
if( navigator.platform.indexOf( "Win" ) != -1 ) {
            if (activator.left > viewport.width - activator.right) {
    importStylesheet( 'MediaWiki:Common.css/WinFixes.css' );
                location = 'right';
            } else {
                location = 'left';
            }
            if (activator.top - display.height > viewport.top) {
                position = 'above';
                display.top = activator.top - display.height;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            } else if (activator.right + display.width < viewport.right) {
                position = 'right-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.right;
            } else if (activator.left - display.width > viewport.left) {
                position = 'left-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.left - display.width;
            } else {
                position = 'below';
                display.top = activator.bottom;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            }
            display.top = Math.max(viewport.top, display.top);
            display.left = Math.max(viewport.left, Math.min(viewport.right - display.width, display.left));
            $display.addClass('is-visible is-' + position + '-activator is-' + location + '-side-of-viewport').offset(display);
        }, function() {
            $display.removeClass('is-visible is-above-activator is-below-activator is-left-of-activator is-right-of-activator is-left-side-of-viewport is-right-side-of-viewport');
        });
    });
}
}


/* Test if an element has a certain class
/*
  * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
  * Veiled modifiers
*
* @deprecated:  Use $(element).hasClass() instead.
  */
  */
 
function veiledModifier() {
var hasClass = (function () {
     var mainClass = 'veiled'; // Class name of veiled modifier elements
     var reCache = {};
     var affixCount = 6; // Number of veiled prefixes and veiled suffixes
     return function (element, className) {
     var affixClass = '-m0$1'; // $1 is replaced with a random number between 1 and affixCount
        return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
    var elements = document.getElementsByClassName(mainClass);
     };
     if ( elements.length > 0 ) {
})();
         var last, random;
 
         for ( var i = 0; i < elements.length; i++ ) {
 
             var element = elements[i];
/** Interwiki links to featured articles ***************************************
            if ( last === undefined ) { // Choose with a random integer between 1 and affixCount
*
                 random = Math.floor(Math.random() * affixCount) + 1;
*  Description: Highlights interwiki links to featured articles (or
             } else { // Continue choosing random integers in the same range while ensuring no repeats
*              equivalents) by changing the bullet before the interwiki link
                random = Math.floor(Math.random() * (affixCount - 1)) + 1;
*              into a star.
                if ( random >= last ) {
*  Maintainers: [[User:R. Koot]]
                    random = random + 1;
*/
                 }
 
function LinkFA() {
     if ( document.getElementById( "p-lang" ) ) {
         var InterwikiLinks = document.getElementById( "p-lang" ).getElementsByTagName( "li" );
 
         for ( var i = 0; i < InterwikiLinks.length; i++ ) {
             if ( document.getElementById( InterwikiLinks[i].className + "-fa" ) ) {
                 InterwikiLinks[i].className += " FA";
                InterwikiLinks[i].title = "This is a featured article in another language.";
             } else if ( document.getElementById( InterwikiLinks[i].className + "-ga" ) ) {
                InterwikiLinks[i].className += " GA";
                 InterwikiLinks[i].title = "This is a good article in another language.";
             }
             }
            last = random;
            element.classList.add(affixClass.replace('$1', random));
         }
         }
     }
     }
}
}


$( LinkFA );
function boolean_table() {
 
    $('.boolean-table').find('table').find('td').each(function () {
 
        var text = $(this).html();
/** Collapsible tables *********************************************************
        if (text == '0') {
*
            $(this).html('&#x2717;');
*  Description: Allows tables to be collapsed, showing only the header. See
            $(this).addClass('table-cell-xmark');
*              [[Wikipedia:NavFrame]].
        } else if (text == '1') {
*  Maintainers: [[User:R. Koot]]
            $(this).html('&#x2713;');
*/
             $(this).addClass('table-cell-checkmark');
 
var autoCollapse = 2;
var collapseCaption = "hide";
var expandCaption = "show";
 
function collapseTable( tableIndex ){
    var Button = document.getElementById( "collapseButton" + tableIndex );
    var 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 i = 1; i < Rows.length; i++ ) {
            Rows[i].style.display = Rows[0].style.display;
        }
        Button.firstChild.data = collapseCaption;
    }
}
}


function createCollapseButtons(){
/**
     var tableIndex = 0;
* Gem quality widget
    var NavigationBoxes = new Object();
* @param  widgets  Elements containing gem quality widgets
    var Tables = document.getElementsByTagName( "table" );
*/
 
function gem_quality_widget(widgets) {
    for ( var i = 0; i < Tables.length; i++ ) {
     if ( widgets.length > 0 ) {
        if ( hasClass( Tables[i], "collapsible" ) ) {
        var do_toggle = function (widget) {
 
            if ( ! this.classList.contains('is-selected') ) {
            /* only add button and increment count if there is a header row to work with */
                var options = widget.getElementsByClassName('gemqual-widget__option');
            var HeaderRow = Tables[i].getElementsByTagName( "tr" )[0];
                var stats_collection = widget.getElementsByClassName('gemqual-widget__stats');
            if (!HeaderRow) continue;
                for ( var i = 0; i < options.length; i++ ) {
            var Header = HeaderRow.getElementsByTagName( "th" )[0];
                    var option = options[i];
            if (!Header) continue;
                    var stats = stats_collection[i];
 
                    if ( option.dataset.qid === this.dataset.qid ) {
            NavigationBoxes[ tableIndex ] = Tables[i];
                        option.classList.add('is-selected');
            Tables[i].setAttribute( "id", "collapsibleTable" + tableIndex );
                        stats.classList.add('is-selected');
 
                    } else {
            var Button    = document.createElement( "span" );
                        option.classList.remove('is-selected');
            var ButtonLink = document.createElement( "a" );
                        stats.classList.remove('is-selected');
            var ButtonText = document.createTextNode( collapseCaption );
                    }
 
                }
             Button.className = "collapseButton";  //Styles are declared in Common.css
             }
 
        };
            ButtonLink.style.color = Header.style.color;
        for ( var i = 0; i < widgets.length; i++ ) {
            ButtonLink.setAttribute( "id", "collapseButton" + tableIndex );
             var widget = widgets[i];
            ButtonLink.setAttribute( "href", "#" );
             var qtypes = widget.dataset.qtypes;
            addHandler( ButtonLink,  "click", new Function( "evt", "collapseTable(" + tableIndex + " ); return killEvt( evt );") );
             qtypes = qtypes.split(',');
             ButtonLink.appendChild( ButtonText );
             var selector = document.createElement('div');
 
             selector.classList.add('gemqual-widget__selector');
             Button.appendChild( document.createTextNode( "[" ) );
             for ( var k = 0; k < qtypes.length; k++ ) {
             Button.appendChild( ButtonLink );
                var option = document.createElement('button');
             Button.appendChild( document.createTextNode( "]" ) );
                option.classList.add('gemqual-widget__option');
 
                option.setAttribute('data-qid', k+1);
             Header.insertBefore( Button, Header.childNodes[0] );
                option.innerHTML = qtypes[k];
             tableIndex++;
                 if ( k === 0 ) {
        }
                     option.classList.add('is-selected');
    }
 
    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;
                 }
                 }
                selector.append(option);
                option.addEventListener( 'click', do_toggle.bind(option, widget) );
             }
             }
            widget.prepend(selector);
         }
         }
     }
     }
}
}


$( createCollapseButtons );
/*
 
  * Accordion
 
  * @param config Object containing configuration
/** Dynamic Navigation Bars (experimental) *************************************
  *
  *  Description: See [[Wikipedia:NavFrame]].
* Maintainers: UNMAINTAINED
  */
  */
function accordion(config) {
    var defaults = {
        mainClass: 'accordion',
        toggleClass: 'accordion__toggle',
        openStateClass: 'is-open',
        controlsClass: 'accordion__controls',
    };
    config = Object.assign(defaults, config);


// set up the words in your language
     var accordions = document.getElementsByClassName(config.mainClass);
var NavigationBarHide = '[' + collapseCaption + ']';
     if ( accordions.length === 0 ) {
var NavigationBarShow = '[' + expandCaption + ']';
         return;
 
// shows and hides content and picture (if available) of navigation bars
// Parameters:
//    indexNavigationBar: the index of navigation bar to be toggled
function toggleNavigationBar(indexNavigationBar){
     var NavToggle = document.getElementById("NavToggle" + indexNavigationBar);
    var NavFrame = document.getElementById("NavFrame" + indexNavigationBar);
 
     if (!NavFrame || !NavToggle) {
         return false;
     }
     }
 
    var doToggle = function () {
     // if shown now
        this.parentNode.classList.toggle(config.openStateClass);
     if (NavToggle.firstChild.data == NavigationBarHide) {
     };
         for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
     for ( var i = 0; i < accordions.length; i++ ) {
            if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
        var accordion = accordions[i];
                 NavChild.style.display = 'none';
        var headings = accordion.getElementsByClassName(config.toggleClass);
         for ( var k = 0; k < headings.length; k++ ) {
            var heading = headings[k];
            var button = document.createElement('button');
            while ( heading.firstChild ) {
                 button.appendChild(heading.firstChild);
             }
             }
            heading.appendChild(button);
            button.addEventListener( 'click', doToggle.bind(button) );
         }
         }
     NavToggle.firstChild.data = NavigationBarShow;
     }


     // if hidden now
     var controls = document.getElementsByClassName(config.controlsClass);
     } else if (NavToggle.firstChild.data == NavigationBarShow) {
     if ( controls.length > 0 ) {
         for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
        var expandAll = function (toggles) {
             if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
            for ( var i = 0; i < toggles.length; i++ ) {
                 NavChild.style.display = 'block';
                toggles[i].classList.add(config.openStateClass);
            }
         };
        var collapseAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.remove(config.openStateClass);
            }
        };
        var findToggles = function(el) {
            if ( el === null ) {
                return false;
            }
            var toggles = el.getElementsByClassName(config.toggleClass);
            if ( toggles.length === 0 ) {
                return findToggles(el.parentElement);
            }
            return toggles;
        };
        for ( var i = 0; i < controls.length; i++ ) {
             var control = controls[i];
            var expandButton = document.createElement('button');
            expandButton.innerHTML = i18n.expandAll;
            var collapseButton = document.createElement('button');
            collapseButton.innerHTML = i18n.collapseAll;
            control.append('[', expandButton, '] [', collapseButton, ']');
            var toggles = findToggles(control);
            if ( toggles ) {
                 expandButton.addEventListener( 'click', expandAll.bind(expandButton, toggles) );
                collapseButton.addEventListener( 'click', collapseAll.bind(collapseButton, toggles) );
             }
             }
         }
         }
        NavToggle.firstChild.data = NavigationBarHide;
     }
     }
}
}


// adds show/hide-button to navigation bars
function setDefaultFileUploadLicense() {
function createNavigationBarToggleButton(){
     if ( mw.config.get('wgCanonicalSpecialPageName') === 'Upload' ) {
     var indexNavigationBar = 0;
         mw.loader.using( 'mediawiki.special.upload', function() {
    // iterate over all < div >-elements
             // Wait until the next event cycle to ensure that the licensing template preview loads
    var divs = document.getElementsByTagName("div");
             setTimeout( function() {
    for (var i = 0; NavFrame = divs[i]; i++) {
                 var licenseField = document.getElementById('wpLicense');
         // if found a navigation bar
                if ( licenseField ) {
        if (hasClass(NavFrame, "NavFrame")) {
                     if ( licenseField.value === '' ) {
 
                         licenseField.value = i18n.defaultLicense;
            indexNavigationBar++;
                        licenseField.dispatchEvent( new Event('change') );
            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';
                     }
                     }
                    licenseField.querySelector('option[title="{{}}"]').remove();
                 }
                 }
             }
             } );
            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")) {
                    NavToggle.style.color = NavFrame.childNodes[j].style.color;
                    NavFrame.childNodes[j].appendChild(NavToggle);
                }
            }
            NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
        }
     }
     }
}
}


$( createNavigationBarToggleButton );
/* Fires when DOM is ready */
$( function() {


    /* For adding expand/collapse all buttons for mw-collapsible */
    $(".mw-collapsible-collapse-all").on("click", function () {
        $('.mw-collapsible-toggle-expanded a').trigger('click');
    });
    $(".mw-collapsible-expand-all").on("click", function () {
        $(".mw-collapsible-toggle-collapsed a").trigger('click');
    });


/** Main Page layout fixes *********************************************************
    // Hoverbox
*
    hoverbox();
*  Description: Adds an additional link to the complete list of languages available.
*  Maintainers: [[User:AzaToth]], [[User:R. Koot]], [[User:Alex Smotrov]]
*/


if (wgPageName == 'Main_Page' || wgPageName == 'Talk:Main_Page') {
    // Item hoverbox
     $(function () {
     hoverbox({
         mw.util.addPortletLink('p-lang', 'http://meta.wikimedia.org/wiki/List_of_Wikipedias',
         mainClass: 'c-item-hoverbox',
                'Complete list', 'interwiki-completelist', 'Complete list of Wikipedias');
        activatorClass: 'c-item-hoverbox__activator',
         var nstab = document.getElementById('ca-nstab-main');
         displayClass: 'c-item-hoverbox__display',
        if (nstab && wgUserLanguage=='en') {
            while (nstab.firstChild) { nstab = nstab.firstChild; }
            nstab.nodeValue = 'Main Page';
        }
     });
     });
}


    // Veiled modifiers
    veiledModifier();
   
    // Change 1 & 0 to checkmarks in tables
    boolean_table();


/** Table sorting fixes ************************************************
    // Set default file upload license to unknown instead of none
  *
    setDefaultFileUploadLicense();
  *  Description: Disables code in table sorting routine to set classes on even/odd rows
  *  Maintainers: [[User:Random832]]
  */
ts_alternate_row_colors = false;
 


/***** uploadwizard_newusers ********
} );
* Switches in a message for non-autoconfirmed users at [[Wikipedia:Upload]]
/* End DOM ready */
*
*  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;
    }
  }
}
$(uploadwizard_newusers);


/* Fires when wiki content is added. */
mw.hook('wikipage.content').add( function($wikipageContent) {


/** IPv6 AAAA connectivity testing **/
    // Gem quality widget in item infobox
    gem_quality_widget( document.getElementsByClassName('gemqual-widget') );


var __ipv6wwwtest_factor = 100;
     // Accordions
var __ipv6wwwtest_done = 0;
     accordion();
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.
*  Maintainers: [[User:RockMFR]]
*/
 
function addEditIntro(name){
  var el = document.getElementById('ca-edit');
  if (!el) {
    return;
  }
  el = el.getElementsByTagName('a')[0];
  if (el) {
    el.href += '&editintro=' + name;
  }
}
 
 
if (wgNamespaceNumber === 0) {
  $(function(){
    if (document.getElementById('disambigbox')) {
      addEditIntro('Template:Disambig_editintro');
    }
  });
 
  $(function(){
    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;
      }
     }
  });
}
 
/**
* Description: Stay on the secure server as much as possible
* Maintainers: [[User:TheDJ]]
*/
if ( mw.config.get('wgServer') == 'https://secure.wikimedia.org' ) {
     importScript( 'MediaWiki:Common.js/secure.js');
}


/** Text area function for the account creation process */
} );
jQuery(function(){
  if (!(document.getElementById('signupuserpagefillmagic'))) return;
  /*
  * Puts an userpage edit-box inside a div with the ID 'signupuserpagefillmagic'
  * Created for [[:outreach:Account Creation Improvement Project]] by
  * [[:sv:User:Sertion]] on the behalf of [[:outreach:User:Hannibal]]
  *
  * Below are variables for internationalization. Please use \n for linebreaks
  * and escape all single quotation marks (') with \'
  */
  var preComment = '<!-- BELOW IS THE TEXT ABOUT YOU. YOU CAN CHANGE IT COMPLETELY OR IN PARTS AND THEN COME BACK TO IT. AFTER YOU ARE DONE, SCROLL DOWN A BIT FURTHER AND CLICK "SAVE PAGE".--\>{'+'{New user bar}}\n',
      postComment = '\n\n<!-- NOW, CLICK THE "SAVE PAGE" BUTTON. CONGRATULATIONS, YOU\'VE JUST MADE YOUR FIRST EDIT TO WIKIPEDIA. --\>',
      preSubmitButton ='Do not forget to click SAVE PAGE when you get to the next page!',
      submitText = 'Create my user page for me now!',
      SUPeditSummary = 'New user page through [[:outreach:Account Creation Improvement Project|Outreach:ACIP]]',
      preFilltemplate = 'Replace this example text with information about you. \n\n';
  /*
    * The actual magic:
    * Inserts a form with a single visible field that simulates the normal
    * edit-field. It uses the variables from above to set a text example (pre
    * filled), an automated edit summary and the label of the submit button.
    * 'fakewpTextbox1' is used to hide the assembling of the final output that
    * is made below.
    */
  jQuery('#signupuserpagefillmagic').html('<form action="'+wgServer+wgScript+'?title='+wgFormattedNamespaces[2]+':'+wgUserName+'&action=submit" method="post"><textarea id="fakewpTextbox1" style="width:46em;height:20em;">'+preFilltemplate+'</textarea><textarea name="wpTextbox1" id="wpTextbox1" style="display:none;"></textarea><input type="hidden" name="wpSummary" id="wpSummary" value="'+SUPeditSummary+'" /><br/>'+preSubmitButton+'<br/><input type="submit" value="'+submitText+'"/></form>');
  // Waits for the form to be submitted.
  jQuery('#signupuserpagefillmagic form').live('submit',function(r){
    // Stops the form from submitting
    r.preventDefault();
    /*
      * Uses the previously defined variables preComment and postComment
      * to assemble the final output in the hidden textarea.
      */
    $('#wpTextbox1').text( preComment + jQuery('#fakewpTextbox1').text() + postComment );
    /*
      * Submits the form.
      * For unknown reasons jQuery('#signupuserpagefillmagic form').submit() crashes
      * Firefox (only tested in version 4.0). This method seam to work cross browser.
      */
    document.getElementById('signupuserpagefillmagic').getElementsByTagName('form')[0].submit();
  });
});


/* Hover Item Box */
}() );
$(function(){"use strict";$(".itemhover").hover(function(){var e=$(this),t=e.next(".itembox-hover"),n=t.next(".itembox-hover-icon"),r=$(window).width(),i=$(window).height(),s=$(window).scrollTop(),o=$(window).scrollLeft(),u=e.offset(),a=e.outerWidth(),f=e.outerHeight(),l=t.outerWidth(),c=t.outerHeight(),h=12,p={},d=n.outerWidth(),v=n.outerHeight(),m={},g;if(u.top-h-c-s>0){g="t";p.top=u.top-c-h;p.left=u.left+a/2-l/2}else if(r+o-u.left-a-h-l-d>0){g="r";p.top=u.top+f/2-c/2;p.left=u.left+a+h}else if(u.left-o-h-l-d>0){g="l";p.top=u.top+f/2-c/2;p.left=u.left-l-h}else{g="b";p.top=u.top+f+h;p.left=u.left+a/2-l/2}if((g==="t"||g==="b")&&p.left<o){p.left=o}else if((g==="t"||g==="b")&&r+o-l<p.left){p.left=r+o-l}else if((g==="r"||g==="l")&&p.top<s){p.top=s}m.top=p.top;m.left=p.left+l;if(g==="l"||r+o-d<m.left){m.left=p.left-d}if(i+s-v<m.top){m.top=i+s-v}t.offset({top:p.top,left:p.left}).removeClass("itembox-hover-hide");n.offset({top:m.top,left:m.left}).removeClass("itembox-hover-hide")},function(){var e=$(this),t=e.next(".itembox-hover"),n=t.next(".itembox-hover-icon");t.addClass("itembox-hover-hide");n.addClass("itembox-hover-hide")}).children("a").removeAttr("title").end().nextAll(".itembox-hover, .itembox-hover-icon").removeClass("itembox-hover-nojs")});

Latest revision as of 15:54, 9 October 2023

/* global mw */
/* jshint strict:true, jquery:true, esversion:5, bitwise:true, curly:true, eqeqeq:true, undef:true */

( function() {
'use strict';

/* Translation strings */
var i18n = {
    expandAll: 'Expand all',
    collapseAll: 'Collapse all',
    defaultLicense: 'Copyright unlicensed',
};

/**
 * Hoverbox
 * @param  config  Object containing configuration
 */
function hoverbox(config) {
    var defaults = {
        mainClass: 'hoverbox',
        activatorClass: 'hoverbox__activator',
        displayClass: 'hoverbox__display',
    };
    config = Object.assign(defaults, config);
    var timestamp = Date.now(),
        $container = $('#hoverbox-displays-' + timestamp);
    if ( $container.length === 0 ) {
        $container = $('<div id="hoverbox-displays-' + timestamp + '" class="hoverbox-display-container"></div>');
    }
    $('body').append($container);
    var $hoverbox = $('.' + config.mainClass),
        idCounter = 0;
    $hoverbox.each(function() {
        var $this = $(this),
            $activator = $this.find('.' + config.activatorClass).first(),
            $display = $this.find('.' + config.displayClass).first(),
            id = $this.data('hoverbox-id') || idCounter++,
            $target = $container.find('[data-hoverbox-target="' + id + '"]');
        if ( $target.length === 0 ) {
            $container.append($display);
            $display.attr('data-hoverbox-target', id);
        } else {
            $display.remove();
            $display = $target;
        }
        $activator.hover(function() {
            var viewport = {},
                activator = {},
                display = {},
                position, // position relative to the activator
                location; // location relative to the viewport
            viewport.width = document.documentElement.clientWidth;
            viewport.height = document.documentElement.clientHeight;
            viewport.top = document.documentElement.scrollTop;
            viewport.left = document.documentElement.scrollLeft;
            viewport.bottom = viewport.top + viewport.height;
            viewport.right = viewport.left + viewport.width;
            activator.width = $activator.outerWidth();
            activator.height = $activator.outerHeight();
            activator.top = $activator.offset().top;
            activator.left = $activator.offset().left;
            activator.bottom = activator.top + activator.height;
            activator.right = activator.left + activator.width;
            display.width = $display.outerWidth();
            display.height = $display.outerHeight();
            if (viewport.width < display.width) { // Don't bother showing the hoverbox at all if the viewport is too small
                return false;
            }
            if (activator.left > viewport.width - activator.right) {
                location = 'right';
            } else {
                location = 'left';
            }
            if (activator.top - display.height > viewport.top) {
                position = 'above';
                display.top = activator.top - display.height;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            } else if (activator.right + display.width < viewport.right) {
                position = 'right-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.right;
            } else if (activator.left - display.width > viewport.left) {
                position = 'left-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.left - display.width;
            } else {
                position = 'below';
                display.top = activator.bottom;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            }
            display.top = Math.max(viewport.top, display.top);
            display.left = Math.max(viewport.left, Math.min(viewport.right - display.width, display.left));
            $display.addClass('is-visible is-' + position + '-activator is-' + location + '-side-of-viewport').offset(display);
        }, function() {
            $display.removeClass('is-visible is-above-activator is-below-activator is-left-of-activator is-right-of-activator is-left-side-of-viewport is-right-side-of-viewport');
        });
    });
}

/*
 * Veiled modifiers
 */
function veiledModifier() {
    var mainClass = 'veiled'; // Class name of veiled modifier elements
    var affixCount = 6; // Number of veiled prefixes and veiled suffixes
    var affixClass = '-m0$1'; // $1 is replaced with a random number between 1 and affixCount
    var elements = document.getElementsByClassName(mainClass);
    if ( elements.length > 0 ) {
        var last, random;
        for ( var i = 0; i < elements.length; i++ ) {
            var element = elements[i];
            if ( last === undefined ) { // Choose with a random integer between 1 and affixCount
                random = Math.floor(Math.random() * affixCount) + 1;
            } else { // Continue choosing random integers in the same range while ensuring no repeats
                random = Math.floor(Math.random() * (affixCount - 1)) + 1;
                if ( random >= last ) {
                    random = random + 1;
                }
            }
            last = random;
            element.classList.add(affixClass.replace('$1', random));
        }
    }
}

function boolean_table() {
    $('.boolean-table').find('table').find('td').each(function () {
        var text = $(this).html();
        if (text == '0') {
            $(this).html('&#x2717;');
            $(this).addClass('table-cell-xmark');
        } else if (text == '1') {
            $(this).html('&#x2713;');
            $(this).addClass('table-cell-checkmark');
        }
    });
}

/**
 * Gem quality widget
 * @param  widgets  Elements containing gem quality widgets
 */
function gem_quality_widget(widgets) {
    if ( widgets.length > 0 ) {
        var do_toggle = function (widget) {
            if ( ! this.classList.contains('is-selected') ) {
                var options = widget.getElementsByClassName('gemqual-widget__option');
                var stats_collection = widget.getElementsByClassName('gemqual-widget__stats');
                for ( var i = 0; i < options.length; i++ ) {
                    var option = options[i];
                    var stats = stats_collection[i];
                    if ( option.dataset.qid === this.dataset.qid ) {
                        option.classList.add('is-selected');
                        stats.classList.add('is-selected');
                    } else {
                        option.classList.remove('is-selected');
                        stats.classList.remove('is-selected');
                    }
                }
            }
        };
        for ( var i = 0; i < widgets.length; i++ ) {
            var widget = widgets[i];
            var qtypes = widget.dataset.qtypes;
            qtypes = qtypes.split(',');
            var selector = document.createElement('div');
            selector.classList.add('gemqual-widget__selector');
            for ( var k = 0; k < qtypes.length; k++ ) {
                var option = document.createElement('button');
                option.classList.add('gemqual-widget__option');
                option.setAttribute('data-qid', k+1);
                option.innerHTML = qtypes[k];
                if ( k === 0 ) {
                    option.classList.add('is-selected');
                }
                selector.append(option);
                option.addEventListener( 'click', do_toggle.bind(option, widget) );
            }
            widget.prepend(selector);
        }
    }
}

/*
 * Accordion
 * @param  config  Object containing configuration
 */
function accordion(config) {
    var defaults = {
        mainClass: 'accordion',
        toggleClass: 'accordion__toggle',
        openStateClass: 'is-open',
        controlsClass: 'accordion__controls',
    };
    config = Object.assign(defaults, config);

    var accordions = document.getElementsByClassName(config.mainClass);
    if ( accordions.length === 0 ) {
        return;
    }
    var doToggle = function () {
        this.parentNode.classList.toggle(config.openStateClass);
    };
    for ( var i = 0; i < accordions.length; i++ ) {
        var accordion = accordions[i];
        var headings = accordion.getElementsByClassName(config.toggleClass);
        for ( var k = 0; k < headings.length; k++ ) {
            var heading = headings[k];
            var button = document.createElement('button');
            while ( heading.firstChild ) {
                button.appendChild(heading.firstChild);
            }
            heading.appendChild(button);
            button.addEventListener( 'click', doToggle.bind(button) );
        }
    }

    var controls = document.getElementsByClassName(config.controlsClass);
    if ( controls.length > 0 ) {
        var expandAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.add(config.openStateClass);
            }
        };
        var collapseAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.remove(config.openStateClass);
            }
        };
        var findToggles = function(el) {
            if ( el === null ) {
                return false;
            }
            var toggles = el.getElementsByClassName(config.toggleClass);
            if ( toggles.length === 0 ) {
                return findToggles(el.parentElement);
            }
            return toggles;
        };
        for ( var i = 0; i < controls.length; i++ ) {
            var control = controls[i];
            var expandButton = document.createElement('button');
            expandButton.innerHTML = i18n.expandAll;
            var collapseButton = document.createElement('button');
            collapseButton.innerHTML = i18n.collapseAll;
            control.append('[', expandButton, '] [', collapseButton, ']');
            var toggles = findToggles(control);
            if ( toggles ) {
                expandButton.addEventListener( 'click', expandAll.bind(expandButton, toggles) );
                collapseButton.addEventListener( 'click', collapseAll.bind(collapseButton, toggles) );
            }
        }
    }
}

function setDefaultFileUploadLicense() {
    if ( mw.config.get('wgCanonicalSpecialPageName') === 'Upload' ) {
        mw.loader.using( 'mediawiki.special.upload', function() {
            // Wait until the next event cycle to ensure that the licensing template preview loads
            setTimeout( function() {
                var licenseField = document.getElementById('wpLicense');
                if ( licenseField ) {
                    if ( licenseField.value === '' ) {
                        licenseField.value = i18n.defaultLicense;
                        licenseField.dispatchEvent( new Event('change') );
                    }
                    licenseField.querySelector('option[title="{{}}"]').remove();
                }
            } );
        } );
    }
}

/* Fires when DOM is ready */
$( function() {

    /* For adding expand/collapse all buttons for mw-collapsible */
    $(".mw-collapsible-collapse-all").on("click", function () {
        $('.mw-collapsible-toggle-expanded a').trigger('click');
    });
    $(".mw-collapsible-expand-all").on("click", function () {
        $(".mw-collapsible-toggle-collapsed a").trigger('click');
    });

    // Hoverbox
    hoverbox();

    // Item hoverbox
    hoverbox({
        mainClass: 'c-item-hoverbox',
        activatorClass: 'c-item-hoverbox__activator',
        displayClass: 'c-item-hoverbox__display',
    });

    // Veiled modifiers
    veiledModifier();
    
    // Change 1 & 0 to checkmarks in tables 
    boolean_table();

    // Set default file upload license to unknown instead of none
    setDefaultFileUploadLicense();

} );
/* End DOM ready */

/* Fires when wiki content is added. */
mw.hook('wikipage.content').add( function($wikipageContent) {

    // Gem quality widget in item infobox
    gem_quality_widget( document.getElementsByClassName('gemqual-widget') );

    // Accordions
    accordion();

} );

}() );