Difference between revisions of "MediaWiki:Common.js"
(Remove top seekrit script) |
(Add simple license check) |
||
| (40 intermediate revisions by 2 users not shown) | |||
| Line 18: | Line 18: | ||
var autoCollapse = 2; | var autoCollapse = 2; | ||
| − | var collapseCaption = ' | + | var collapseCaptionLang = {'ar': 'أخف', 'cs': 'sbalit', 'da': 'fold sammen', 'de': 'einklappen', 'es': 'contraer', 'fi': 'supista', 'fr': 'masquer', 'hu': 'becsuk', 'it': 'comprimi', 'ja': '折り畳む', 'ko': '접기', 'nl': 'samenvouwen', 'pl': 'zwiń', 'pt': 'ocultar', 'pt-br': 'ocultar', 'ro': 'restrânge', 'ru': 'свернуть', 'sv': 'dölj', 'tr': 'daralt', 'zh-hans': '折叠', 'zh-hant': '合併'}; |
| − | var expandCaption = ' | + | var expandCaptionLang = {'ar': 'أظهر', 'cs': 'rozbalit', 'da': 'fold ud', 'de': 'ausklappen', 'es': 'expandir', 'fi': 'Laajenna', 'fr': 'afficher', 'hu': 'kinyit', 'it': 'espandi', 'ja': '展開する', 'ko': '펼치기', 'nl': 'uitvouwen', 'pl': 'rozwiń', 'pt': 'expandir', 'pt-br': 'expandir', 'ro': 'extinde', 'ru': 'развернуть', 'sv': 'visa', 'tr': 'genişlet', 'zh-hans': '展开', 'zh-hant': '展開'}; |
| + | var collapseCaption = collapseCaptionLang[mw.config.get("wgPageName").split("/").pop()] || 'collapse'; | ||
| + | var expandCaption = expandCaptionLang[mw.config.get("wgPageName").split("/").pop()] || 'expand'; | ||
window.collapseTable = function ( tableIndex ) { | window.collapseTable = function ( tableIndex ) { | ||
| Line 319: | Line 321: | ||
init: function() { | init: function() { | ||
// Supported list of languages (not including the default one): | // Supported list of languages (not including the default one): | ||
| − | var langList = ['ar', 'cs', 'da', 'de', 'es', 'fi', 'fr', 'hu', 'it', 'ja', 'ko', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sv', 'zh-hans', 'zh-hant']; | + | var langList = ['ar', 'cs', 'da', 'de', 'es', 'fi', 'fr', 'hu', 'it', 'ja', 'ko', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sv', 'tr', 'zh-hans', 'zh-hant']; |
// Assumed language if the page is in none of the languages above: | // Assumed language if the page is in none of the languages above: | ||
var defaultLang = 'en'; | var defaultLang = 'en'; | ||
| Line 333: | Line 335: | ||
}; | }; | ||
$(langFixes.init); | $(langFixes.init); | ||
| + | |||
| + | // Main Page event video embed. See documentation on Template:Main Page event | ||
| + | var embedHeroVid = { | ||
| + | init: function () { | ||
| + | var $container = $('.mp-event-container'); | ||
| + | var $image = $('.mp-event-image'); | ||
| + | var isVideo = !!($container.data('mpEventVideo')); | ||
| + | |||
| + | if ($image[0] && isVideo) { | ||
| + | var _video = $('<video/>', { | ||
| + | muted: true, | ||
| + | autoplay: true, | ||
| + | loop: true, | ||
| + | class: 'mp-event-video' | ||
| + | }); | ||
| + | |||
| + | embedHeroVid.getSource($container) | ||
| + | .done(function (url) { | ||
| + | var extension = url[1]; | ||
| + | _video.insertAfter($image); | ||
| + | $('<source/>', { | ||
| + | src: url[0], | ||
| + | type: 'video/' + extension | ||
| + | }).appendTo(_video); | ||
| + | |||
| + | _video[0].oncanplaythrough = function () { | ||
| + | $image.remove(); | ||
| + | $container.attr('data-video-url', null); | ||
| + | }; | ||
| + | }); | ||
| + | } | ||
| + | }, | ||
| + | getSource: function (source) { | ||
| + | var deferred = $.Deferred(); | ||
| + | var url = source.attr('data-video-url'); | ||
| + | |||
| + | if (typeof url === 'undefined' || url === '') { | ||
| + | throw new Error('Video URL is undefined. If it\'s blank, it is due to the internal file name being incorrect or that the "video-url" parameter is unset.'); | ||
| + | } | ||
| + | |||
| + | var extension = url.split('/').reverse()[0].split('.')[1]; | ||
| + | $.get(url) | ||
| + | .done(function () { | ||
| + | deferred.resolve([url, extension]); | ||
| + | }) | ||
| + | .fail(function () { | ||
| + | throw new Error('Whoops, invalid video! Please ensure the URL is right\nVideo URL: ' + url); | ||
| + | }); | ||
| + | |||
| + | return deferred.promise(); | ||
| + | } | ||
| + | }; | ||
| + | $(embedHeroVid.init); | ||
// Logged-in body class injection | // Logged-in body class injection | ||
| Line 491: | Line 546: | ||
$(talkpageplus); | $(talkpageplus); | ||
| − | // Konami code easter egg by WindPower | + | // Konami code easter egg by WindPower, modified by Wookipan |
// Constants: | // Constants: | ||
var spaiConstants = {}; | var spaiConstants = {}; | ||
// Editable constants: | // Editable constants: | ||
// General info: | // General info: | ||
| + | spaiConstants.spaiEnabled = true; | ||
spaiConstants.spaiImage = '/w/images/7/73/Team_Fortress_Wiki_Egg_Spy.png'; | spaiConstants.spaiImage = '/w/images/7/73/Team_Fortress_Wiki_Egg_Spy.png'; | ||
spaiConstants.spaiHeight = 196; | spaiConstants.spaiHeight = 196; | ||
| − | spaiConstants. | + | spaiConstants.sapperClass = '--sapped'; |
spaiConstants.spaiSappingMahWikiWav = '/w/images/4/4a/Team_Fortress_Wiki_Egg.wav'; | spaiConstants.spaiSappingMahWikiWav = '/w/images/4/4a/Team_Fortress_Wiki_Egg.wav'; | ||
spaiConstants.timeStep = 40; // In milliseconds; 40 ms => 25 fps | spaiConstants.timeStep = 40; // In milliseconds; 40 ms => 25 fps | ||
| Line 511: | Line 567: | ||
spaiConstants.preloadingImages = []; | spaiConstants.preloadingImages = []; | ||
spaiConstants.preloadingRefs = {}; | spaiConstants.preloadingRefs = {}; | ||
| − | spaiConstants. | + | spaiConstants.toPreloadImage = spaiConstants.spaiImage; |
spaiConstants.self = null; | spaiConstants.self = null; | ||
spaiConstants.loadedSound = false; | spaiConstants.loadedSound = false; | ||
| Line 655: | Line 711: | ||
spaiConstants.theBody().appendChild(spai); | spaiConstants.theBody().appendChild(spai); | ||
var logoPortlet = document.getElementById('p-logo'); | var logoPortlet = document.getElementById('p-logo'); | ||
| − | |||
var changeHeight = function(progress) { | var changeHeight = function(progress) { | ||
progress = parseInt(progress * spaiConstants.spaiHeight); | progress = parseInt(progress * spaiConstants.spaiHeight); | ||
| Line 663: | Line 718: | ||
self.playSound(spaiConstants.spaiSappingMahWikiWav); | self.playSound(spaiConstants.spaiSappingMahWikiWav); | ||
setTimeout(function(){ | setTimeout(function(){ | ||
| − | + | logoPortlet.classList.add('wiki-logo' + spaiConstants.sapperClass); | |
| − | |||
self.animate(function(progress){changeHeight(1.0-progress);}, spaiConstants.anim_spaiBackUp, function(){ | self.animate(function(progress){changeHeight(1.0-progress);}, spaiConstants.anim_spaiBackUp, function(){ | ||
setTimeout(function(){ | setTimeout(function(){ | ||
| − | logoPortlet. | + | logoPortlet.removeAttribute('class'); |
self.spyAnimationFinished([spai]); | self.spyAnimationFinished([spai]); | ||
}, spaiConstants.anim_sapperDestroyed); | }, spaiConstants.anim_sapperDestroyed); | ||
| Line 685: | Line 739: | ||
* :: Now with support for touch events and multiple instances for | * :: Now with support for touch events and multiple instances for | ||
* :: those situations that call for multiple easter eggs! | * :: those situations that call for multiple easter eggs! | ||
| − | * Code: https://github.com/ | + | * Code: https://github.com/georgemandis/konami-js |
| − | * Copyright (c) 2009 George Mandis ( | + | * Copyright (c) 2009 George Mandis (https://george.mand.is) |
| − | * Version: 1.6. | + | * Version: 1.6.3 (11/11/2021) |
* Licensed under the MIT License (http://opensource.org/licenses/MIT) | * Licensed under the MIT License (http://opensource.org/licenses/MIT) | ||
* Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1+ and Android | * Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1+ and Android | ||
| Line 820: | Line 874: | ||
// End of Konami-JS | // End of Konami-JS | ||
var konami = new Konami(); | var konami = new Konami(); | ||
| − | konami.code = function(){self.hitItDoc.apply(self)}; | + | konami.code = function() { |
| + | if (spaiConstants.spaiEnabled) { | ||
| + | self.hitItDoc.apply(self); | ||
| + | } | ||
| + | |||
| + | document.dispatchEvent(new CustomEvent('konami:fire')); | ||
| + | }; | ||
konami.load(); | konami.load(); | ||
} | } | ||
| Line 899: | Line 959: | ||
// Page-specific JavaScript/CSS | // Page-specific JavaScript/CSS | ||
var pageScripts = { | var pageScripts = { | ||
| − | pagesJS: [ | + | pagesJS: ["Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2021/Main_Page", "User:Lexar/Main_Page/Template:Benjas", "User:Lexar/sandbox", "User:MogDog66", "User:Tark", "User:Tark/Sandbox", "User:WindPower", "User:WindPower/Main_Page", "User:Wookipan/Sandbox"], |
| − | + | pagesCSS: ["Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2019/Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2021/Main_Page", "User:Ashe", "User:Ath", "User:Boba", "User:Carez", "User:CrushBOT", "User:Esky", "User:FanCyy", "User:Foxbite", "User:FreeXMan", "User:GrampaSwood", "User:Hagbard Celine", "User:Jestie", "User:Lagg", "User:Lexar", "User:Lexar/Main_Page/Template:Benjas", "User:Lexar/sandbox", "User:Mediarch", "User:MogDog66", "User:MogDog66/MPR", "User:MogDog66/Sandbox", "User:MogDog66/userpagev2", "User:Moussekateer/3DViewer", "User:NVis", "User:NVis/Sandbox", "User:Nixshadow", "User:Obilisk", "User:PhoneWave", "User:Pilk", "User:Pilk/armory", "User:Sour_Dani", "User:T-Wayne", "User:Tark", "User:Tark/Sandbox", "User:WindPower", "User:WindPower/Main_Page", "User:Wookipan", "User:Wookipan/Sandbox"], | |
suffixJS: '/Page.js', | suffixJS: '/Page.js', | ||
suffixCSS: '/Page.css', | suffixCSS: '/Page.css', | ||
| Line 1,245: | Line 1,305: | ||
// End weapon wear table tabs ----- | // End weapon wear table tabs ----- | ||
| − | // Start | + | // Start Bilibili iframe support ----- |
var Bilibili = { | var Bilibili = { | ||
| − | + | init: function() { | |
| − | + | var $videos = $('.bilibili-video'); | |
| − | + | $videos.each(function() { | |
| − | + | var $this = $(this); | |
| − | + | var aid = parseInt($this.data('vaid')); | |
| − | + | var danmaku = parseInt($this.data('vdanmaku')); | |
| + | var page = parseInt($this.data('vpage')); | ||
| + | var width = $this.data('vwidth'); | ||
| + | var height = $this.data('vheight'); | ||
| + | var iframeSrc = 'https://www.bilibili.com/blackboard/html5mobileplayer.html?aid=' + aid + '&high_quality=1&danmaku=' + danmaku + '&page=' + page + '&hideCoverInfo=1&hideDanmakuButton=1'; | ||
| + | var iframe = '<iframe src="' + iframeSrc + '" width="' + width + '" height="' + height + '" frameborder="0" allowfullscreen="true"></iframe>'; | ||
| + | $this.append(iframe); | ||
| + | }); | ||
| + | } | ||
}; | }; | ||
$(Bilibili.init); | $(Bilibili.init); | ||
| − | // End | + | // End Bilibili iframe support ----- |
| + | |||
| + | // Start custom username highlighting ----- | ||
| + | var uGroupHighlight = { | ||
| + | init: function() { | ||
| + | if ($('.mw-userlink')[0]) { | ||
| + | var params = { | ||
| + | action: 'query', | ||
| + | list: 'allusers', | ||
| + | augroup: ['sysop', 'moderator', 'bot'], | ||
| + | auprop: 'groups', | ||
| + | aulimit: 100, | ||
| + | format: 'json' | ||
| + | }; | ||
| + | |||
| + | var api = new mw.Api(); | ||
| + | |||
| + | api.get(params).done(function(data) { | ||
| + | var uGroups = data.query.allusers, user; | ||
| + | for (user in uGroups) { | ||
| + | var name = uGroups[user].name; | ||
| + | var group = uGroups[user].groups; | ||
| + | |||
| + | $('bdi').each(function() { | ||
| + | if ($(this).text().match('\\b' + name + '\\b')) { | ||
| + | $(this).closest('.mw-userlink').addClass(group.includes('bot') ? 'bot' : 'staff'); | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | }, | ||
| + | }; | ||
| + | $(uGroupHighlight.init); | ||
| + | // End custom username highlighting ----- | ||
// Start login icon randomizer ----- | // Start login icon randomizer ----- | ||
| Line 1,288: | Line 1,390: | ||
// End login icon randomizer ----- | // End login icon randomizer ----- | ||
| − | // Start | + | // Start 'Audio player' |
| − | var | + | var audioPlayer = { |
| − | init: function() { | + | currentAudio: null, |
| − | var | + | |
| − | var | + | init: function () { |
| − | + | var audioPauseImg = new Image(); | |
| − | + | var audioPlayImg = new Image(); | |
| − | + | audioPauseImg.src = '/w/images/d/d2/Pause_icon.png'; | |
| − | + | audioPlayImg.src = '/w/images/6/67/Play_icon.png'; | |
| − | + | ||
| − | + | $('.tfwiki-audio-player').each(function () { | |
| − | + | var audioPlayerElement = $(this); | |
| − | + | var audioLink = audioPlayerElement.children('a'); | |
| − | + | var audioURL = audioLink.attr('href'); | |
| − | + | var audio = null; | |
| − | + | var audioStatus = audioPlayerElement.find('.tfwiki-audio-player-action'); | |
| − | + | ||
| − | + | audioStatus.removeClass('inactive'); | |
| − | + | ||
| − | + | audioPlayerElement.on('click', function (e) { | |
| − | + | if (e.target !== audioStatus[0]) { | |
| − | + | return; | |
| − | + | } | |
| − | + | ||
| − | + | e.preventDefault(); | |
| − | + | ||
| − | + | if (!audio) { | |
| − | + | audio = new Audio(audioURL); | |
| − | + | audio.volume = 0.5; | |
| − | + | audio.addEventListener('ended', function () { | |
| − | + | audioStatus.text(audioStatus.data('text-play')); | |
| − | + | audioStatus.removeClass('playing'); | |
| − | } | + | }); |
| − | } | + | } |
| + | |||
| + | if (audioPlayer.currentAudio && audioPlayer.currentAudio !== audio) { | ||
| + | audioPlayer.currentAudio.pause(); | ||
| + | audioPlayer.currentAudio.currentTime = 0; | ||
| + | audioPlayer.currentAudioStatus.text(audioPlayer.currentAudioStatus.data('text-play')); | ||
| + | audioPlayer.currentAudioStatus.removeClass('playing'); | ||
| + | } | ||
| + | |||
| + | if (audio.paused) { | ||
| + | audio.play(); | ||
| + | audioStatus.text(audioStatus.data('text-pause')); | ||
| + | audioPlayer.currentAudio = audio; | ||
| + | audioPlayer.currentAudioStatus = audioStatus; | ||
| + | audioStatus.addClass('playing'); | ||
| + | } else { | ||
| + | audio.pause(); | ||
| + | audioStatus.text(audioStatus.data('text-resume')); | ||
| + | audioPlayer.currentAudio = null; | ||
| + | audioPlayer.currentAudioStatus = null; | ||
| + | audioStatus.removeClass('playing'); | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | audioLink.on('click', function (e) { | ||
| + | e.preventDefault(); | ||
| + | window.open(audioURL, '_blank'); | ||
| + | }); | ||
| + | }); | ||
} | } | ||
}; | }; | ||
| − | $( | + | $(audioPlayer.init); |
| − | // End | + | // End 'Audio player' |
| + | // Force user to choose a proper license when they select "another license" | ||
| + | function anotlicense() { | ||
| + | if (mw.config.get("wgCanonicalSpecialPageName") === "Upload") { | ||
| + | document.getElementById("wpLicense").addEventListener("change", function() { | ||
| + | var uploadBtn = document.getElementsByName("wpUpload")[0]; | ||
| + | if (uploadBtn) { | ||
| + | uploadBtn.disabled = this.value === "Another license"; | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| + | $(anotlicense); | ||
| + | |||
| + | // Do not track if user is logged in | ||
| + | if (!mw.config.get("wgUserName")) { | ||
/* Google Analytics */ | /* Google Analytics */ | ||
var _gaq = _gaq || []; | var _gaq = _gaq || []; | ||
| Line 1,355: | Line 1,500: | ||
w.attachEvent("onload", gs); | w.attachEvent("onload", gs); | ||
})(window); | })(window); | ||
| + | } | ||
Latest revision as of 19:11, 7 October 2025
// This is the non-compressed version of MediaWiki:Common.js
// External links open in new windows/tabs:
$('a.external').attr('target', '_blank');
/** Collapsible tables *********************************************************
*
* Description: Allows tables to be collapsed, showing only the header. See
* [[Wikipedia:NavFrame]].
* Maintainers: [[User:R. Koot]]
*/
var hasClass = (function () {
var reCache = {};
return function (element, className) {
return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
};
})();
var autoCollapse = 2;
var collapseCaptionLang = {'ar': 'أخف', 'cs': 'sbalit', 'da': 'fold sammen', 'de': 'einklappen', 'es': 'contraer', 'fi': 'supista', 'fr': 'masquer', 'hu': 'becsuk', 'it': 'comprimi', 'ja': '折り畳む', 'ko': '접기', 'nl': 'samenvouwen', 'pl': 'zwiń', 'pt': 'ocultar', 'pt-br': 'ocultar', 'ro': 'restrânge', 'ru': 'свернуть', 'sv': 'dölj', 'tr': 'daralt', 'zh-hans': '折叠', 'zh-hant': '合併'};
var expandCaptionLang = {'ar': 'أظهر', 'cs': 'rozbalit', 'da': 'fold ud', 'de': 'ausklappen', 'es': 'expandir', 'fi': 'Laajenna', 'fr': 'afficher', 'hu': 'kinyit', 'it': 'espandi', 'ja': '展開する', 'ko': '펼치기', 'nl': 'uitvouwen', 'pl': 'rozwiń', 'pt': 'expandir', 'pt-br': 'expandir', 'ro': 'extinde', 'ru': 'развернуть', 'sv': 'visa', 'tr': 'genişlet', 'zh-hans': '展开', 'zh-hant': '展開'};
var collapseCaption = collapseCaptionLang[mw.config.get("wgPageName").split("/").pop()] || 'collapse';
var expandCaption = expandCaptionLang[mw.config.get("wgPageName").split("/").pop()] || 'expand';
window.collapseTable = function ( tableIndex ) {
var Button = document.getElementById( 'collapseButton' + tableIndex );
var Table = document.getElementById( 'collapsibleTable' + tableIndex );
if ( !Table || !Button ) {
return false;
}
var Rows = Table.rows;
var i;
if ( Button.firstChild.data === collapseCaption ) {
for ( i = 1; i < Rows.length; i++ ) {
Rows[i].style.display = 'none';
}
Button.firstChild.data = expandCaption;
} else {
for ( 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 = {};
var Tables = document.getElementsByTagName( 'table' );
var i;
function handleButtonLink( index, e ) {
window.collapseTable( index );
e.preventDefault();
}
for ( i = 0; i < Tables.length; i++ ) {
if ( $( Tables[i] ).hasClass( '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', '#' );
$( ButtonLink ).on( 'click', $.proxy( handleButtonLink, ButtonLink, tableIndex ) );
ButtonLink.appendChild( ButtonText );
Button.appendChild( document.createTextNode( '[' ) );
Button.appendChild( ButtonLink );
Button.appendChild( document.createTextNode( ']' ) );
Header.insertBefore( Button, Header.firstChild );
tableIndex++;
}
}
for ( i = 0; i < tableIndex; i++ ) {
if ( $( NavigationBoxes[i] ).hasClass( 'collapsed' ) || ( tableIndex >= autoCollapse && $( NavigationBoxes[i] ).hasClass( 'autocollapse' ) ) ) {
window.collapseTable( i );
}
else if ( $( NavigationBoxes[i] ).hasClass ( 'innercollapse' ) ) {
var element = NavigationBoxes[i];
while ((element = element.parentNode)) {
if ( $( element ).hasClass( 'outercollapse' ) ) {
window.collapseTable ( i );
break;
}
}
}
}
}
$( createCollapseButtons );
/** Dynamic Navigation Bars (experimental) *************************************
*
* Description: See [[Wikipedia:NavFrame]].
* Maintainers: UNMAINTAINED
*/
// set up the words in your language
var NavigationBarHide = '[' + collapseCaption + ']';
var NavigationBarShow = '[' + expandCaption + ']';
// 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;
}
// if shown now
if (NavToggle.firstChild.data == NavigationBarHide) {
for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
NavChild.style.display = 'none';
}
}
NavToggle.firstChild.data = NavigationBarShow;
// if hidden now
} else if (NavToggle.firstChild.data == NavigationBarShow) {
for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
NavChild.style.display = 'block';
}
}
NavToggle.firstChild.data = NavigationBarHide;
}
}
// adds show/hide-button to navigation bars
function createNavigationBarToggleButton(){
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")) {
NavToggle.style.color = NavFrame.childNodes[j].style.color;
NavFrame.childNodes[j].appendChild(NavToggle);
}
}
NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
}
}
}
$( createNavigationBarToggleButton );
//END Collapsible tables *********************************************************
// PootTabs by User:WindPower~
// It puts tabs on pages.
var pootTabsHere = {
animationsEnabled: $.support.opacity,
getTab:function(poot, index) {
return $(poot.children('.poot-tabs').children('ul').children('li')[parseInt(index)]);
},
changeTab:function(poot, index, duration, force) {
if(index == parseInt(poot.attr('pootSelected')) && !force && duration) return;
if(!pootTabsHere.animationsEnabled) {
duration = 0;
}
poot.attr('pootSelected', index.toString());
var babies = poot.children('.poot-tabs-content').children();
babies.each(function() {
$(this).fadeOut(duration, function(){
$(this).removeClass('poot-tabs-selected');
});
});
$(babies[index]).each(function() {
$(this).fadeIn(duration, function(){
$(this).addClass('poot-tabs-selected');
});
});
var cowtabs = poot.children('.poot-tabs').children('ul').children('li');
cowtabs.removeClass('poot-tabs-selected');
$(cowtabs[index]).addClass('poot-tabs-selected');
pootTabsHere.updatePoot(poot, $(babies[index]).height());
},
updatePoot:function(poot, babysize) {
if(poot.hasClass('poot-tabs-notitle')) {
poot.find('.poot-tabs-titletext').html(pootTabsHere.getTab(poot, poot.attr('pootSelected')).html());
} else {
poot.find('.poot-tabs-titletext').html(poot.attr('originalTitle') + ' — ' + pootTabsHere.getTab(poot, poot.attr('pootSelected')).html());
}
if(poot.has('.poot-tabs-edittabs') && poot.has('.poot-tabs-navbar')) {
try {
poot.find('.poot-tabs-navbar').html($(poot.children('.poot-tabs-edittabs').children('span')[parseInt(poot.attr('pootSelected'))]).html());
} catch(e) {}
}
var bestHeight = Math.max(poot.children('.poot-tabs-content').height(), Math.max(poot.children('.poot-tabs').height(), babysize)).toString() + 'px';
poot.children('.poot-tabs-content').css('height', bestHeight);
if(poot.attr('vertical')) {
poot.children('.poot-tabs').css('height', bestHeight);
}
},
toggleCollapse:function(poot) {
var pootLinkText = poot.children('.poot-tabs-showhide').text().split(';');
var duration = pootTabsHere.animationsEnabled ? parseInt(poot.attr('pootslideduration')) : 0;
if(poot.attr('pootcollapse') != 'true') {
poot.attr('pootcollapse', 'true');
poot.find('.poot-tabs-hidelink a').text(pootLinkText[0]);
poot.children('.poot-tabs, .poot-tabs-content').slideUp(duration);
}
else {
poot.attr('pootcollapse', '');
poot.find('.poot-tabs-hidelink a').text(pootLinkText[1]);
poot.children('.poot-tabs, .poot-tabs-content').slideDown(duration);
}
},
delayHeight:function(poot, selected) {
setTimeout(function() {
poot.attr('pootselected', selected.toString());
pootTabsHere.changeTab(poot, selected, 0, true);
if(poot.hasClass('poot-tabs-collapsed')) {
pootTabsHere.toggleCollapse(poot);
}
}, 100);
},
poot:function() {
var dis = $(this);
dis.removeClass('poot-tabs-nojs'); // If this thing runs, JS is on
var ind = 0;
dis.attr('originalTitle', dis.find('.poot-tabs-titletext').html());
var selected = /poot-tabs-selected-(\d+)/i.exec(dis.attr('class'));
if(selected) {
pootTabsHere.delayHeight(dis, parseInt(selected[1])-1);
}
else {
pootTabsHere.delayHeight(dis, 0);
}
var duration = dis.hasClass('poot-tabs-noanimations') ? 0 : 200;
dis.attr('pootslideduration', dis.hasClass('poot-tabs-noanimations') ? '0' : '75');
dis.children('.poot-tabs').children('ul').children('li').each(function(){
var thisInd = ind;
$(this).click(function(){
pootTabsHere.changeTab(dis, thisInd, duration, false);
$(this).blur();
$(this).find('*').blur();
return false;
});
ind++;
});
var isVertical = dis.hasClass('poot-tabs-vertical');
dis.attr('pootvertical', isVertical ? 'true' : '');
if(isVertical) {
var teenie = dis.children('.poot-tabs').width().toString() + 'px';
dis.children('.poot-tabs-content').css('margin-left', teenie);
}
dis.attr('pootcollapse', ''); // False
dis.find('.poot-tabs-hidelink a').click(function(){
pootTabsHere.toggleCollapse(dis);
return false;
});
},
init:function() {
$('.poot-tabs-container').each(pootTabsHere.poot);
}
};
$(pootTabsHere.init);
// Language support fixes
var langFixes = {
init: function() {
// Supported list of languages (not including the default one):
var langList = ['ar', 'cs', 'da', 'de', 'es', 'fi', 'fr', 'hu', 'it', 'ja', 'ko', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sv', 'tr', 'zh-hans', 'zh-hant'];
// Assumed language if the page is in none of the languages above:
var defaultLang = 'en';
var lang = defaultLang;
for(var i in langList) {
if(mw.config.get('wgPageName').substr(mw.config.get('wgPageName').length - 1 - langList[i].length).toLowerCase() == '/' + langList[i].toLowerCase()) {
lang = langList[i];
break;
}
}
$('body').addClass('lang-' + lang);
}
};
$(langFixes.init);
// Main Page event video embed. See documentation on Template:Main Page event
var embedHeroVid = {
init: function () {
var $container = $('.mp-event-container');
var $image = $('.mp-event-image');
var isVideo = !!($container.data('mpEventVideo'));
if ($image[0] && isVideo) {
var _video = $('<video/>', {
muted: true,
autoplay: true,
loop: true,
class: 'mp-event-video'
});
embedHeroVid.getSource($container)
.done(function (url) {
var extension = url[1];
_video.insertAfter($image);
$('<source/>', {
src: url[0],
type: 'video/' + extension
}).appendTo(_video);
_video[0].oncanplaythrough = function () {
$image.remove();
$container.attr('data-video-url', null);
};
});
}
},
getSource: function (source) {
var deferred = $.Deferred();
var url = source.attr('data-video-url');
if (typeof url === 'undefined' || url === '') {
throw new Error('Video URL is undefined. If it\'s blank, it is due to the internal file name being incorrect or that the "video-url" parameter is unset.');
}
var extension = url.split('/').reverse()[0].split('.')[1];
$.get(url)
.done(function () {
deferred.resolve([url, extension]);
})
.fail(function () {
throw new Error('Whoops, invalid video! Please ensure the URL is right\nVideo URL: ' + url);
});
return deferred.promise();
}
};
$(embedHeroVid.init);
// Logged-in body class injection
var loggedinBodyClass = {
init: function() {
$('body').addClass(mw.config.get('wgUserName') == null ? 'not-logged-in' : 'logged-in');
}
};
$(loggedinBodyClass.init);
// Resize YouTube embed, turn HD on, etc, by User:WindPower
var youtubeHelper = {
chromeSize: 25, // This is the height (in pixels) of the chrome of YouTube's embedded video player. Update this whenever they release a new embedded video player
maxWidth: 0.85, // Maximum fraction of the available width that the video may take
infoboxes: ['.infobox', '.testchamber'], // Selectors of infobox-style boxes that should be deducted from the page's available width
ratioR: /ratio-(\d+)x(\d+)/i,
widthsR: /widths((?:\D+\d+)+)/i,
setSize:function() {
var widths = youtubeHelper.widthsR.exec($(this).attr('class'));
if(widths != null) {
widths = widths[1].substr(1).split(/\D+/g);
var availableWidth = $('#bodyContent').width();
for(var i in youtubeHelper.infoboxes) {
if($(youtubeHelper.infoboxes[i]).length) {
availableWidth -= $(youtubeHelper.infoboxes[i]).width();
}
}
availableWidth *= youtubeHelper.maxWidth;
var intWidths = [];
for(var w = 0; w < widths.length; w++) {
intWidths[w] = parseInt(widths[w]);
}
intWidths.sort(function(a, b){return b - a;});
for(var w = 0; w < intWidths.length; w++) {
if(intWidths[w] <= availableWidth || w == intWidths.length-1) {
youtubeHelper.setWidth(this, intWidths[w]);
break;
}
}
}
else {
youtubeHelper.setWidth(this, parseFloat(obj.attr('width')));
}
},
setUrl:function() {
var obj = $(this).children('object');
if(!obj.length) return;
obj.append($('<param name="allowscriptaccess" value="true"></param>'));
obj.append($('<param name="allowfullscreen" value="true"></param>'));
var titleParts = mw.config.get('wgPageName').split(/\//g);
var lang = 'en';
if(titleParts.length == 2 && !mw.config.get('wgCanonicalSpecialPageName')) {
lang = titleParts[titleParts.length-1];
}
var playerUrl = obj.children('param[name="movie"]').attr('value') + '&version=2&fs=1&theme=dark&color=white' + ($(this).hasClass('hd-on') ? '&hd=1' : '') + '&cc_load_policy=1&modestbranding=1&hl=' + lang + '&cc_lang_pref=' + lang;
obj.children('param[name="movie"]').attr('value', playerUrl);
obj.children('embed').attr('src', playerUrl).attr('allowscriptaccess', 'always').attr('allowfullscreen', 'true');
var resultHtml = $(this).html();
$(this).html('').html(resultHtml);
},
setWidth:function(youtube, width) {
var obj = $(youtube).children('object');
if(!obj) return;
if($(youtube).hasClass('youtube-audio')) {
obj.attr('width', width).attr('height', youtubeHelper.chromeSize); // Set <object> height
obj.children('embed').attr('width', width).attr('height', youtubeHelper.chromeSize); // Set <embed> height
}
else {
var ratio = youtubeHelper.ratioR.exec($(youtube).attr('class'));
if(ratio != null) {
ratio = parseFloat(ratio[1])/parseFloat(ratio[2]);
var newHeight = Math.round(width / ratio + youtubeHelper.chromeSize).toString();
obj.attr('width', width).attr('height', newHeight); // Set <object> height
obj.children('embed').attr('width', width).attr('height', newHeight); // Set <embed> height
}
}
},
resizeTimer:null,
resize:function() {
if(youtubeHelper.resizeTimer != null) {
clearTimeout(youtubeHelper.resizeTimer);
}
youtubeHelper.resizeTimer = setTimeout(youtubeHelper.onResize, 100);
},
onResize:function() {
$('.youtubebox').each(youtubeHelper.setSize);
},
init:function() {
$('.youtubebox').each(youtubeHelper.setUrl);
$(window).resize(youtubeHelper.resize);
youtubeHelper.onResize();
}
};
$(youtubeHelper.init);
// Edittools loader copied from http://en.wikipedia.org/wiki/MediaWiki:Common.js/edit.js?oldid=407371785
// Only slightly modified by seb26
/**
* Edittools javascript loader ************************************************
*
* Description: Pulls in [[MediaWiki:Edittools.js]]. Includes a cache-bypassing
* version number in the URL in order to allow any changes to the edittools to
* be rapidly deployed to users.
*
* Note that, by default, this function does nothing unless the element with
* the ID "editpage-specialchars" (which contains the old edittools code in
* [[MediaWiki:Edittools]], and will be retained as a placeholder in the new
* implementation) has a class named "edittools-version-NNN", where NNN is a
* number. If the class name has "test" before the number, the code will only
* run for users who have set "window.testJsEdittools = true" in their user JS.
* The "test" should be retained in the class name until the new edittools
* implementation is ready and fully tested, and until at least 30 days have
* passed since this loader stub was added (which will be in 27 June 2008).
*
* For compatibility with Alex Smotrov's original implementation, on which this
* code is loosely based (see [[mw:User talk:Alex Smotrov/edittools.js]]), this
* loader can also be disabled by setting "window.noDefaultEdittools = true".
*
* Maintainers: [[User:Ilmari Karonen]]
*/
if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1 || mw.config.get('wgPageName') == "Special:Upload") //scripts specific to editing pages
{
// Prevent the static edittools from flashing before the compact edittools below is loaded.
mw.util.addCSS('div.edittools-text { display:none; }');
$(function () {
// needs to be deferred until the DOM has fully loaded
var placeholder = document.getElementById("editpage-specialchars");
if (!placeholder || window.noDefaultEdittools) {
//Show the static edittools again for users with "window.noDefaultEdittools=true".
mw.util.addCSS('div.edittools-text { display:block; }');
return;
}
var match = /(?:^| )edittools-version-(\d+)(?: |$)/.exec(placeholder.className);
// set window.testJsEdittools = true to enable testing before full deployment
if (!match && window.testJsEdittools)
match = /(?:^| )edittools-version-(test\d+)(?: |$)/.exec(placeholder.className);
if (!match) return;
var url = mw.config.get('wgScript') + '?title=MediaWiki:Edittools.js&action=raw&ctype=text/javascript&nocache=' + match[1];
mw.loader.load(url);
});
}
/********* MediaWiki:Valve.js *********/
function talkpageplus()
{
var talkpagelink = document.getElementById('ca-talk');
if (talkpagelink && talkpagelink.className == 'new')
{
talkpagelink.firstChild.href += '§ion=new';
}
}
$(talkpageplus);
// Konami code easter egg by WindPower, modified by Wookipan
// Constants:
var spaiConstants = {};
// Editable constants:
// General info:
spaiConstants.spaiEnabled = true;
spaiConstants.spaiImage = '/w/images/7/73/Team_Fortress_Wiki_Egg_Spy.png';
spaiConstants.spaiHeight = 196;
spaiConstants.sapperClass = '--sapped';
spaiConstants.spaiSappingMahWikiWav = '/w/images/4/4a/Team_Fortress_Wiki_Egg.wav';
spaiConstants.timeStep = 40; // In milliseconds; 40 ms => 25 fps
// Animation timing (all times in milliseconds):
spaiConstants.anim_spaiFallDown = 2000; // Time for Spy to fall down
spaiConstants.anim_spaiWait = 900; // Time Spy waits before going back up
spaiConstants.anim_spaiBackUp = 2000; // Time for Spy to go back up
spaiConstants.anim_sapperDestroyed = 2250; // Time until Sapper gets destroyed
// End editable constants
spaiConstants.theBody = function(){return document.getElementById('content');};
spaiConstants.preloadedImages = [];
spaiConstants.preloadingImages = [];
spaiConstants.preloadingRefs = {};
spaiConstants.toPreloadImage = spaiConstants.spaiImage;
spaiConstants.self = null;
spaiConstants.loadedSound = false;
spaiConstants.loadedImages = false;
spaiConstants.fired = false;
// End constants
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
var spaiSappinMahWiki = {
constants: spaiConstants,
createImgDiv:function(image) {
var self = spaiConstants.self;
var div = document.createElement('div');
var img = document.createElement('img');
img.src = image;
div.appendChild(img);
setTimeout(function(){spaiConstants.theBody().appendChild(div);}, 1);
return {
'div': div,
'img': img
};
},
imagesLoaded:function() {
spaiConstants.loadedImages = true;
if(spaiConstants.loadedSound) {
spaiConstants.self.spySappingMahWiki();
}
},
soundLoaded:function() {
spaiConstants.loadedSound = true;
if(spaiConstants.loadedImages) {
spaiConstants.self.spySappingMahWiki();
}
},
preloadSound:function(sound, callback) {
var self = spaiConstants.self;
try {
var audio = document.createElement('audio');
audio.setAttribute('src', sound);
audio.setAttribute('style', 'display: none;');
audio.setAttribute('preload', 'true');
spaiConstants.theBody().appendChild(audio);
audio.addEventListener('canplaythrough', callback, false);
}
catch(e) {}
setTimeout(callback, 1000); // Fallback
},
preloadImage:function(image) {
var self = spaiConstants.self;
if(spaiConstants.preloadingImages.indexOf(image) == -1) {
spaiConstants.preloadingImages[spaiConstants.preloadingImages.length] = image;
var nodes = self.createImgDiv(image);
spaiConstants.preloadingRefs[image] = nodes['img'];
nodes['div'].setAttribute('style', 'visibility: hidden; height: 0px; width: 0px; overflow: hidden; z-index: -10000;');
}
if(spaiConstants.preloadingRefs[image].width) {
spaiConstants.preloadedImages[spaiConstants.preloadedImages.length] = image;
}
else
{
setTimeout(function(){self.preloadImage(image);}, spaiConstants.timeStep);
}
},
preloadImages:function(callback) {
var self = spaiConstants.self;
var allPreloaded = true;
for(var i in spaiConstants.toPreloadImages) {
if(spaiConstants.preloadedImages.indexOf(spaiConstants.toPreloadImages[i]) == -1) {
allPreloaded = false;
}
if(spaiConstants.preloadingImages.indexOf(spaiConstants.toPreloadImages[i]) == -1) {
self.preloadImage(spaiConstants.toPreloadImages[i]);
}
}
if(allPreloaded) {
callback();
} else {
setTimeout(function(){self.preloadImages(callback);}, spaiConstants.timeStep);
}
},
destroyNode:function(node) {
try {
node.parentNode.removeChild(node);
} catch(e) {
// Ze goggles, zey do nothin
}
},
smoothInOut:function(progress) {
return (Math.sin((progress-.5)*Math.PI)+1)/2;
},
inAnimation:function(func, progressTime, totalTime, callback, easing) {
var self = spaiConstants.self;
func(easing(progressTime / totalTime));
if(progressTime >= totalTime) {
callback();
} else {
setTimeout(function(){self.inAnimation(func, progressTime + spaiConstants.timeStep, totalTime, callback, easing);}, spaiConstants.timeStep);
}
},
animate:function(func, totalTime, callback, easing) {
var self = spaiConstants.self;
return self.inAnimation(func, 0.0, totalTime, callback, easing);
},
playSound:function(sound) {
var self = spaiConstants.self;
try {
var audio = document.createElement('audio');
audio.setAttribute('src', sound);
audio.setAttribute('style', 'display: none;');
audio.setAttribute('autoplay', 'true');
spaiConstants.theBody().appendChild(audio);
}
catch(e) {}
},
spyAnimationFinished:function(nodes) {
var self = spaiConstants.self;
for(var node in nodes) {
self.destroyNode(nodes[node]);
}
spaiConstants.fired = false;
},
spySappingMahWiki:function() {
var self = spaiConstants.self;
if(spaiConstants.fired) return;
spaiConstants.fired = true;
var spai = document.createElement('a');
spai.setAttribute('href', '/');
spai.setAttribute('style', 'display:block; position: absolute; top: 0px; left: 0px; width: 160px; height: 200px; border: 0px; background: url('+spaiConstants.spaiImage+') no-repeat 0px -50000px; z-index: 10000;');
spaiConstants.theBody().appendChild(spai);
var logoPortlet = document.getElementById('p-logo');
var changeHeight = function(progress) {
progress = parseInt(progress * spaiConstants.spaiHeight);
spai.style.backgroundPosition = '0px ' + (-spaiConstants.spaiHeight + progress).toString() + 'px';
};
self.animate(changeHeight, spaiConstants.anim_spaiFallDown, function(){
self.playSound(spaiConstants.spaiSappingMahWikiWav);
setTimeout(function(){
logoPortlet.classList.add('wiki-logo' + spaiConstants.sapperClass);
self.animate(function(progress){changeHeight(1.0-progress);}, spaiConstants.anim_spaiBackUp, function(){
setTimeout(function(){
logoPortlet.removeAttribute('class');
self.spyAnimationFinished([spai]);
}, spaiConstants.anim_sapperDestroyed);
}, self.smoothInOut);
}, spaiConstants.anim_spaiWait);
}, self.smoothInOut);
},
hitItDoc:function() {
var self = spaiConstants.self;
self.preloadImages(self.imagesLoaded);
self.preloadSound(spaiConstants.spaiSappingMahWikiWav, self.soundLoaded);
},
initKonami: function () {
var self = spaiConstants.self;
/*
* Konami-JS ~
* :: Now with support for touch events and multiple instances for
* :: those situations that call for multiple easter eggs!
* Code: https://github.com/georgemandis/konami-js
* Copyright (c) 2009 George Mandis (https://george.mand.is)
* Version: 1.6.3 (11/11/2021)
* Licensed under the MIT License (http://opensource.org/licenses/MIT)
* Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1+ and Android
*/
var Konami = function (callback) {
var konami = {
addEvent: function (obj, type, fn, ref_obj) {
if (obj.addEventListener)
obj.addEventListener(type, fn, false);
else if (obj.attachEvent) {
// IE
obj["e" + type + fn] = fn;
obj[type + fn] = function () {
obj["e" + type + fn](window.event, ref_obj);
}
obj.attachEvent("on" + type, obj[type + fn]);
}
},
removeEvent: function (obj, eventName, eventCallback) {
if (obj.removeEventListener) {
obj.removeEventListener(eventName, eventCallback);
} else if (obj.attachEvent) {
obj.detachEvent(eventName);
}
},
input: "",
pattern: "38384040373937396665",
keydownHandler: function (e, ref_obj) {
if (ref_obj) {
konami = ref_obj;
} // IE
konami.input += e ? e.keyCode : event.keyCode;
if (konami.input.length > konami.pattern.length) {
konami.input = konami.input.substr((konami.input.length - konami.pattern.length));
}
if (konami.input === konami.pattern) {
konami.code(konami._currentLink);
konami.input = '';
e.preventDefault();
return false;
}
},
load: function (link) {
this._currentLink = link;
this.addEvent(document, "keydown", this.keydownHandler, this);
this.iphone.load(link);
},
unload: function () {
this.removeEvent(document, 'keydown', this.keydownHandler);
this.iphone.unload();
},
code: function (link) {
window.location = link
},
iphone: {
start_x: 0,
start_y: 0,
stop_x: 0,
stop_y: 0,
tap: false,
capture: false,
orig_keys: "",
keys: ["UP", "UP", "DOWN", "DOWN", "LEFT", "RIGHT", "LEFT", "RIGHT", "TAP", "TAP"],
input: [],
code: function (link) {
konami.code(link);
},
touchmoveHandler: function (e) {
if (e.touches.length === 1 && konami.iphone.capture === true) {
var touch = e.touches[0];
konami.iphone.stop_x = touch.pageX;
konami.iphone.stop_y = touch.pageY;
konami.iphone.tap = false;
konami.iphone.capture = false;
konami.iphone.check_direction();
}
},
touchendHandler: function () {
konami.iphone.input.push(konami.iphone.check_direction());
if (konami.iphone.input.length > konami.iphone.keys.length) konami.iphone.input.shift();
if (konami.iphone.input.length === konami.iphone.keys.length) {
var match = true;
for (var i = 0; i < konami.iphone.keys.length; i++) {
if (konami.iphone.input[i] !== konami.iphone.keys[i]) {
match = false;
}
}
if (match) {
konami.iphone.code(konami._currentLink);
}
}
},
touchstartHandler: function (e) {
konami.iphone.start_x = e.changedTouches[0].pageX;
konami.iphone.start_y = e.changedTouches[0].pageY;
konami.iphone.tap = true;
konami.iphone.capture = true;
},
load: function (link) {
this.orig_keys = this.keys;
konami.addEvent(document, "touchmove", this.touchmoveHandler);
konami.addEvent(document, "touchend", this.touchendHandler, false);
konami.addEvent(document, "touchstart", this.touchstartHandler);
},
unload: function () {
konami.removeEvent(document, 'touchmove', this.touchmoveHandler);
konami.removeEvent(document, 'touchend', this.touchendHandler);
konami.removeEvent(document, 'touchstart', this.touchstartHandler);
},
check_direction: function () {
x_magnitude = Math.abs(this.start_x - this.stop_x);
y_magnitude = Math.abs(this.start_y - this.stop_y);
x = ((this.start_x - this.stop_x) < 0) ? "RIGHT" : "LEFT";
y = ((this.start_y - this.stop_y) < 0) ? "DOWN" : "UP";
result = (x_magnitude > y_magnitude) ? x : y;
result = (this.tap === true) ? "TAP" : result;
return result;
}
}
}
typeof callback === "string" && konami.load(callback);
if (typeof callback === "function") {
konami.code = callback;
konami.load();
}
return konami;
};
// End of Konami-JS
var konami = new Konami();
konami.code = function() {
if (spaiConstants.spaiEnabled) {
self.hitItDoc.apply(self);
}
document.dispatchEvent(new CustomEvent('konami:fire'));
};
konami.load();
}
};
spaiConstants.self = spaiSappinMahWiki;
$(spaiSappinMahWiki.initKonami);
// Dynamic background by WindPower
// WindPower is secksy and makes this wiki awesome with his very breath. (- Smashman)
var dynamicBg = {
categories: {
// Format:
// 'CategoryName': 'URL of background image', ---OR--- 'title-PageTitle': 'URL of background image',
// Categories don't have to be class names, they can be things like "Weapons", "Featured articles", "Maps", "Help", etc.
'Scout': '/w/images/e/ea/Background_Scout_vector.png',
'Soldier': '/w/images/5/54/Background_Soldier_vector.png',
'Pyro': '/w/images/e/ed/Background_Pyro_vector.png',
'Demoman': '/w/images/5/59/Background_Demoman_vector.png',
'Engineer': '/w/images/f/f7/Background_Engineer_vector.png',
'Heavy': '/w/images/0/03/Background_Heavy_vector.png',
'Medic': '/w/images/2/24/Background_Medic_vector.png',
'Sniper': '/w/images/e/ed/Background_Sniper_vector.png',
'Spy': '/w/images/b/b9/Background_Spy_vector.png'
// (No comma at the end of the last line)
},
getCategories:function() {
var catlinksnode = document.getElementById('catlinks');
if(!catlinksnode) return [];
var catlinks = document.getElementById('catlinks').getElementsByTagName('a');
var cats = [];
var l;
for(var i = 0; i < catlinks.length; i++) {
l = catlinks[i].getAttribute('title');
if(l.match(/^Category:/i, '')) {
cats[cats.length] = l.substr(9).replace(/\/[^/]+$/, '');
}
}
return cats;
},
inArray:function(haystack, needle) {
for(var i = 0; i < haystack.length; i++) {
if(haystack[i] == needle) {
return i;
}
}
return -1;
},
init:function() {
if(typeof(wPrefs) != 'undefined') {
if(dynamicBg.inArray(wPrefs, 'noDynamicBackground') != -1) {
return; // Script disabled
}
}
try {
var cats = dynamicBg.getCategories();
var body = document.getElementsByTagName('body')[0];
} catch(e) {
return;
}
var selectedCats = [];
if(typeof(dynamicBg.categories['title-' + mw.config.get('wgTitle')]) != 'undefined') {
selectedCats[0] = dynamicBg.categories['title-' + mw.config.get('wgTitle')];
}
else {
for(var i in dynamicBg.categories) {
if(dynamicBg.inArray(cats, i) != -1) {
selectedCats[selectedCats.length] = dynamicBg.categories[i];
}
}
}
if(!selectedCats.length) return; // No match, keep default style
var selectedCat = selectedCats[Math.floor(Math.random()*selectedCats.length)];
body.style.backgroundImage='url('+selectedCat+')';
}
};
$(dynamicBg.init);
// Page-specific JavaScript/CSS
var pageScripts = {
pagesJS: ["Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2021/Main_Page", "User:Lexar/Main_Page/Template:Benjas", "User:Lexar/sandbox", "User:MogDog66", "User:Tark", "User:Tark/Sandbox", "User:WindPower", "User:WindPower/Main_Page", "User:Wookipan/Sandbox"],
pagesCSS: ["Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2019/Main_Page", "Team_Fortress_Wiki:April_Fools'_Day/2021/Main_Page", "User:Ashe", "User:Ath", "User:Boba", "User:Carez", "User:CrushBOT", "User:Esky", "User:FanCyy", "User:Foxbite", "User:FreeXMan", "User:GrampaSwood", "User:Hagbard Celine", "User:Jestie", "User:Lagg", "User:Lexar", "User:Lexar/Main_Page/Template:Benjas", "User:Lexar/sandbox", "User:Mediarch", "User:MogDog66", "User:MogDog66/MPR", "User:MogDog66/Sandbox", "User:MogDog66/userpagev2", "User:Moussekateer/3DViewer", "User:NVis", "User:NVis/Sandbox", "User:Nixshadow", "User:Obilisk", "User:PhoneWave", "User:Pilk", "User:Pilk/armory", "User:Sour_Dani", "User:T-Wayne", "User:Tark", "User:Tark/Sandbox", "User:WindPower", "User:WindPower/Main_Page", "User:Wookipan", "User:Wookipan/Sandbox"],
suffixJS: '/Page.js',
suffixCSS: '/Page.css',
init: function() {
for(var i in pageScripts.pagesJS) {
if(mw.config.get('wgPageName') == pageScripts.pagesJS[i]) {
mw.loader.load(mw.config.get('wgScript') + '?title=' + encodeURIComponent(mw.config.get('wgPageName') + pageScripts.suffixJS) + '&ctype=text/javascript&action=raw');
}
}
for(var i in pageScripts.pagesCSS) {
if(mw.config.get('wgPageName') == pageScripts.pagesCSS[i]) {
mw.loader.load(mw.config.get('wgScript') + '?title=' + encodeURIComponent(mw.config.get('wgPageName') + pageScripts.suffixCSS) + '&ctype=text/css&action=raw', 'text/css');
}
}
}
};
$(pageScripts.init);
// Fancy diffs
var fancyDiffs = {
isBigDiff: false,
isBigDiffThreshold: 72,
toggle: function(element) {
var expanded = element.hasClass('diff-expanded');
var contents = element.parent().children('.diff-contents');
if(expanded) { // Just collapse then
element.removeClass('diff-expanded');
if(fancyDiffs.isBigDiff) {
contents.hide();
} else {
contents.slideUp('fast');
}
} else if(element.hasClass('diff-data-loaded')) { // Stuff is already loaded, expand
element.addClass('diff-expanded');
contents.slideDown('fast');
} else if(!element.hasClass('diff-data-requested')) { // Stuff is not loaded
element.addClass('diff-data-requested');
var fileName = element.find('span').text().replace(/^\s+|\s+$/g);
var patchName = element.closest('.diffname');
var diffName = mw.config.get('wgPageName');
if(patchName && patchName.length && patchName.attr('class')) {
diffName = patchName.attr('class').substr(9);
}
$.get('/w/?title=Template:PatchDiff/' + encodeURIComponent(diffName.replace(/^Template:PatchDiff\//, '')) + '/' + encodeURIComponent(fileName) + '&action=raw', function(data) {
contents.html(data);
if(fancyDiffs.isBigDiff) {
contents.show();
} else {
contents.slideDown('fast');
}
element.removeClass('diff-data-requested').addClass('diff-data-loaded').addClass('diff-expanded');
});
}
},
init: function() {
var diffText = $('.diff-name-text');
if(diffText.length) {
// Preload leetle gif
$('body').append($('<img/>').attr('src', '/w/images/4/43/Patch_diff_loading.gif').css('display', 'none'));
diffText.find('span').each(function() {
$(this).text($(this).find('a').text().replace(/^\s+|\s+$/g));
});
diffText.click(function() {
fancyDiffs.toggle($(this));
return false;
});
fancyDiffs.isBigDiff = $('.diff-file').length > fancyDiffs.isBigDiffThreshold;
}
}
};
$(fancyDiffs.init);
// 3D/2D viewer
$('#switch-to-3d').click(function() {
$('.container-2d').hide();
$('.viewer-3d, .viewer-3d-multi, .buttons-container-3d').show();
});
$('#switch-to-2d').click(function() {
$('.viewer-3d, .viewer-3d-multi, .buttons-container-3d').hide();
$('.container-2d').show();
});
// 3D model viewer
var viewer3d = {
dragging: null,
draggingFrameX: 0,
draggingFrameY: 0,
viewers: [],
frameThresholdX: 10,
frameThresholdY: 128,
realMod: function(x, y) {
return ((x % y) + y) % y;
},
init: function() {
$('.viewer-3d').each(viewer3d.bind);
$(document).mouseup(viewer3d.release);
$(document).mousemove(viewer3d.move);
},
bind: function() {
var v = $(this);
var num = viewer3d.viewers.length;
var allModels = [];
var modelID = 0;
var viewerSize = 0;
while(true) {
var modelMap = v.find('.viewer-3d-map-' + modelID);
var urlNode = v.find('.viewer-3d-url-' + modelID);
if(!modelMap.length || !urlNode.length) break;
var url = $('<div/>').html(urlNode.text()).text();
var framesS = $('<div/>').html(modelMap.text()).text().replace(/^\s+|\s+$/g).split(/,/g);
var frameMap = [];
var heightMap = [];
var leftCropMap = [];
var totalW = parseInt(framesS[0]);
var maxFrameW = parseInt(framesS[1]);
var totalH = parseInt(framesS[2]);
var verticalSteps = parseInt(framesS[3]);
var midVertical = Math.floor(verticalSteps / 2);
for(var f = 4; f < framesS.length; f += 3) {
frameMap.push(parseInt(framesS[f]));
heightMap.push(parseInt(framesS[f + 1]));
leftCropMap.push(parseInt(framesS[f + 2]));
}
allModels.push({
imageURL: url,
map: frameMap,
cropMap: leftCropMap,
totalWidth: totalW,
totalHeight: totalH,
maxFrameWidth: maxFrameW,
xStep: verticalSteps
});
viewerSize = Math.max(viewerSize, totalH, maxFrameW);
modelID++;
}
if(!modelID) return;
var overlayNode = $('<div class="viewer-3d-overlay"></div>');
var frameN = v.find('.viewer-3d-frame');
v.find('img').detach();
var klasses = v.attr('class').split(/ /g);
var startFrame = 0;
for(var k in klasses) {
if(klasses[k].substr(0, 11) == 'startframe-') {
startFrame = Math.max(0, parseInt(klasses[k].substr(11)));
}
}
var viewer = {
node: v,
frameX: startFrame,
frameY: midVertical,
models: allModels,
currentModel: -1,
frameNode: frameN,
width: viewerSize,
height: viewerSize,
mouseX: 0,
mouseY: 0,
overlay: overlayNode
};
viewer3d.viewers.push(viewer);
v.hover(viewer3d.hover, viewer3d.unhover).mousedown(viewer3d.drag).append(overlayNode).attr('data-id', num).css({
width: viewer.width + 'px',
height: viewer.height + 'px'
});
frameN.mousedown(viewer3d.drag).attr('data-id', num).css('height', viewer.height + 'px');
viewer3d.changeVersion(viewer, 0);
},
getCurrentModel: function(v) {
return v.models[v.currentModel];
},
changeVersion: function(v, version) {
version = Math.max(0, Math.min(v.models.length - 1, version));
if(v.currentModel == version) return;
v.currentModel = version;
v.frameNode.css('background', 'url(' + viewer3d.getCurrentModel(v).imageURL + ') top left no-repeat');
viewer3d.display(v, v.frameX, v.frameY);
},
hover: function(e) {
var v = viewer3d.getViewer(this);
if(viewer3d.dragging != v) {
v.overlay.animate({'opacity': '1'}, 'fast');
}
},
unhover: function(e) {
var v = viewer3d.getViewer(this);
if(viewer3d.dragging != v) {
v.overlay.animate({'opacity': '0.5'}, 'fast');
}
},
drag: function(e) {
var v = viewer3d.getViewer(this);
v.mouseX = e.pageX;
v.mouseY = e.pageY;
viewer3d.dragging = v;
draggingFrameX = v.frameX;
draggingFrameY = v.frameY;
return false;
},
release: function() {
var v = viewer3d.dragging;
viewer3d.dragging = null;
if(v != null) {
v.frameX = viewer3d.draggingFrameX;
v.frameY = viewer3d.draggingFrameY;
v.overlay.animate({'opacity': '0.5'}, 'fast');
}
viewer3d.draggingFrameX = 0;
viewer3d.draggingFrameY = 0;
},
getViewer: function(node) {
return viewer3d.viewers[parseInt($(node).attr('data-id'))];
},
display: function(v, frameX, frameY) {
var model = viewer3d.getCurrentModel(v);
var frameID = viewer3d.realMod(frameX * model.xStep + frameY, model.map.length);
var frameOffset = model.map[frameID];
var frameWidth = 0;
if(frameID == model.map.length - 1) {
frameWidth = model.totalWidth - frameOffset;
} else {
frameWidth = model.map[frameID + 1] - frameOffset;
}
v.frameNode.css({
backgroundPosition: (-frameOffset - frameID) + 'px 0px',
left: Math.round((v.width - model.maxFrameWidth) / 2.0 + model.cropMap[frameID]) + 'px',
top: Math.round((v.height - model.totalHeight) / 2) + 'px',
width: frameWidth + 'px',
height: model.totalHeight + 'px'
});
},
move: function(e) {
if(viewer3d.dragging == null) {
return;
}
var v = viewer3d.dragging;
var model = viewer3d.getCurrentModel(v);
var mouseDeltaX = e.pageX - v.mouseX;
var mouseDeltaY = e.pageY - v.mouseY;
var frameDeltaX = Math.round(mouseDeltaX / viewer3d.frameThresholdX);
var frameDeltaY = -Math.round(mouseDeltaY / viewer3d.frameThresholdY);
viewer3d.draggingFrameX = v.frameX + frameDeltaX;
viewer3d.draggingFrameY = Math.max(0, Math.min(model.xStep - 1, v.frameY + frameDeltaY));
viewer3d.display(v, viewer3d.draggingFrameX, viewer3d.draggingFrameY);
}
};
$(viewer3d.init);
var selector3d = {
bind: function() {
var viewer = viewer3d.getViewer($(this).find('.viewer-3d'));
var keepGoing = true;
var modelVariant = 0;
var selector;
while(keepGoing) {
selector = $(this).find('.selector-' + modelVariant);
if(selector.length) {
selector.attr('data-variant', modelVariant).click(function() {
viewer3d.changeVersion(viewer, parseInt($(this).attr('data-variant')));
return false;
});
}
modelVariant++;
keepGoing = selector.length;
}
},
init: function() {
$('.viewer-3d-multi, .viewer-3d-container').each(selector3d.bind);
}
};
$(selector3d.init);
// Code to get 3D viewer drag working on touch devices
// Source: http://www.jquery4u.com/mobile/jquery-add-dragtouch-support-ipad/
$.fn.addTouch = function(){
this.each(function(i,el){
$(el).bind('touchstart touchmove touchend touchcancel',function(){
//we pass the original event object because the jQuery event
//object is normalized to w3c specs and does not provide the TouchList
handleTouch(event);
});
});
var handleTouch = function(event)
{
var touches = event.changedTouches,
first = touches[0],
type = '';
switch(event.type)
{
case 'touchstart':
type = 'mousedown';
break;
case 'touchmove':
type = 'mousemove';
event.preventDefault();
break;
case 'touchend':
type = 'mouseup';
break;
default:
return;
}
var simulatedEvent = document.createEvent('MouseEvent');
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
};
};
$('.viewer-3d').addTouch();
// End 3D viewer touch device code
// Start weapon wear table tabs -----
var WeaponWearTable = {
tabSwitch: function($this,tab,weapons,weapon) {
if (!$this.hasClass('current')) {
var tabIndex = $this.index();
$this.parent().find('.current').removeClass('current');
$this.addClass('current');
weapons.find('.current').removeClass('current');
weapon.eq(tabIndex).addClass('current');
}
},
init: function() {
$('.weapon-wear-table').each(function(){
var $this = $(this),
tabs = $this.children('.tabs'),
tab = tabs.children('li'),
weapons = $this.children('.weapons'),
weapon = weapons.children('li');
tab.click(function(){
WeaponWearTable.tabSwitch($(this),tab,weapons,weapon);
});
});
}
};
$(WeaponWearTable.init);
// End weapon wear table tabs -----
// Start Bilibili iframe support -----
var Bilibili = {
init: function() {
var $videos = $('.bilibili-video');
$videos.each(function() {
var $this = $(this);
var aid = parseInt($this.data('vaid'));
var danmaku = parseInt($this.data('vdanmaku'));
var page = parseInt($this.data('vpage'));
var width = $this.data('vwidth');
var height = $this.data('vheight');
var iframeSrc = 'https://www.bilibili.com/blackboard/html5mobileplayer.html?aid=' + aid + '&high_quality=1&danmaku=' + danmaku + '&page=' + page + '&hideCoverInfo=1&hideDanmakuButton=1';
var iframe = '<iframe src="' + iframeSrc + '" width="' + width + '" height="' + height + '" frameborder="0" allowfullscreen="true"></iframe>';
$this.append(iframe);
});
}
};
$(Bilibili.init);
// End Bilibili iframe support -----
// Start custom username highlighting -----
var uGroupHighlight = {
init: function() {
if ($('.mw-userlink')[0]) {
var params = {
action: 'query',
list: 'allusers',
augroup: ['sysop', 'moderator', 'bot'],
auprop: 'groups',
aulimit: 100,
format: 'json'
};
var api = new mw.Api();
api.get(params).done(function(data) {
var uGroups = data.query.allusers, user;
for (user in uGroups) {
var name = uGroups[user].name;
var group = uGroups[user].groups;
$('bdi').each(function() {
if ($(this).text().match('\\b' + name + '\\b')) {
$(this).closest('.mw-userlink').addClass(group.includes('bot') ? 'bot' : 'staff');
}
});
}
});
}
},
};
$(uGroupHighlight.init);
// End custom username highlighting -----
// Start login icon randomizer -----
var iconRandomizer = {
init: function() {
var classes = [
'/w/images/3/33/Login_Scout.png',
'/w/images/d/d8/Login_Soldier.png',
'/w/images/7/71/Login_Pyro.png',
'/w/images/5/53/Login_Demoman.png',
'/w/images/3/35/Login_Heavy.png',
'/w/images/a/ab/Login_Engineer.png',
'/w/images/d/d4/Login_Medic.png',
'/w/images/e/e4/Login_Sniper.png',
'/w/images/2/27/Login_Spy.png'
];
// pick a random class image out of nine choices
pickClass = classes[Math.floor(Math.random() * classes.length)];
// ensure all relative elements are hit
var nodes = $('#pt-userpage, #pt-anonuserpage, #pt-login');
if (nodes.length) {
for (var i = 0; i < nodes.length; i++) {
nodes.css('background-image', 'url(' + pickClass + ')');
}
}
}
};
$(iconRandomizer.init);
// End login icon randomizer -----
// Start 'Audio player'
var audioPlayer = {
currentAudio: null,
init: function () {
var audioPauseImg = new Image();
var audioPlayImg = new Image();
audioPauseImg.src = '/w/images/d/d2/Pause_icon.png';
audioPlayImg.src = '/w/images/6/67/Play_icon.png';
$('.tfwiki-audio-player').each(function () {
var audioPlayerElement = $(this);
var audioLink = audioPlayerElement.children('a');
var audioURL = audioLink.attr('href');
var audio = null;
var audioStatus = audioPlayerElement.find('.tfwiki-audio-player-action');
audioStatus.removeClass('inactive');
audioPlayerElement.on('click', function (e) {
if (e.target !== audioStatus[0]) {
return;
}
e.preventDefault();
if (!audio) {
audio = new Audio(audioURL);
audio.volume = 0.5;
audio.addEventListener('ended', function () {
audioStatus.text(audioStatus.data('text-play'));
audioStatus.removeClass('playing');
});
}
if (audioPlayer.currentAudio && audioPlayer.currentAudio !== audio) {
audioPlayer.currentAudio.pause();
audioPlayer.currentAudio.currentTime = 0;
audioPlayer.currentAudioStatus.text(audioPlayer.currentAudioStatus.data('text-play'));
audioPlayer.currentAudioStatus.removeClass('playing');
}
if (audio.paused) {
audio.play();
audioStatus.text(audioStatus.data('text-pause'));
audioPlayer.currentAudio = audio;
audioPlayer.currentAudioStatus = audioStatus;
audioStatus.addClass('playing');
} else {
audio.pause();
audioStatus.text(audioStatus.data('text-resume'));
audioPlayer.currentAudio = null;
audioPlayer.currentAudioStatus = null;
audioStatus.removeClass('playing');
}
});
audioLink.on('click', function (e) {
e.preventDefault();
window.open(audioURL, '_blank');
});
});
}
};
$(audioPlayer.init);
// End 'Audio player'
// Force user to choose a proper license when they select "another license"
function anotlicense() {
if (mw.config.get("wgCanonicalSpecialPageName") === "Upload") {
document.getElementById("wpLicense").addEventListener("change", function() {
var uploadBtn = document.getElementsByName("wpUpload")[0];
if (uploadBtn) {
uploadBtn.disabled = this.value === "Another license";
}
});
}
}
$(anotlicense);
// Do not track if user is logged in
if (!mw.config.get("wgUserName")) {
/* Google Analytics */
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18260470-1']);
_gaq.push(['_setDomainName', '.teamfortress.com']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
/* GoSquared analytics */
var GoSquared = {};
GoSquared.acct = "GSN-106863-S";
(function(w){
function gs(){
w._gstc_lt = +new Date;
var d = document, g = d.createElement("script");
g.type = "text/javascript";
g.src = "//d1l6p2sc9645hc.cloudfront.net/tracker.js";
var s = d.getElementsByTagName("script")[0];
s.parentNode.insertBefore(g, s);
}
w.addEventListener ?
w.addEventListener("load", gs, false) :
w.attachEvent("onload", gs);
})(window);
}