MediaWiki:Common.js

/* Any JavaScript here will be loaded for all users on every page load. A lot of this code has been taken from other Wikis, which follow the same copyright laws. */

// This script is from Wikipedia. For author attribution, please see http://en.wikipedia.org/w/index.php?title=MediaWiki:Common.js&action=history

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

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

/** Collapsible tables ********************************************************* * * Description: Allows tables to be collapsed, showing only the header. See *              Wikipedia:NavFrame. * Maintainers: User:R. Koot */ 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; var NavigationBoxes = new Object; var Tables = document.getElementsByTagName( "table" ); for ( var i = 0; i < Tables.length; i++ ) { if ( hasClass( Tables[i], "collapsible" ) ) { /* only add button and increment count if there is a header row to work with */ var HeaderRow = Tables[i].getElementsByTagName( "tr" )[0]; if (!HeaderRow) continue; var Header = HeaderRow.getElementsByTagName( "th" )[0]; if (!Header) continue; NavigationBoxes[ tableIndex ] = Tables[i]; Tables[i].setAttribute( "id", "collapsibleTable" + tableIndex ); var Button    = document.createElement( "span" ); var ButtonLink = document.createElement( "a" ); var ButtonText = document.createTextNode( collapseCaption ); Button.className = "collapseButton"; //Styles are declared in Common.css ButtonLink.style.color = Header.style.color; ButtonLink.setAttribute( "id", "collapseButton" + tableIndex ); ButtonLink.setAttribute( "href", "javascript:collapseTable(" + tableIndex + ");" ); ButtonLink.appendChild( ButtonText ); Button.appendChild( document.createTextNode( "[" ) ); Button.appendChild( ButtonLink ); Button.appendChild( document.createTextNode( "]" ) ); Header.insertBefore( Button, Header.childNodes[0] ); tableIndex++; }   }    for ( var i = 0;  i < tableIndex; i++ ) { if ( hasClass( NavigationBoxes[i], "collapsed" ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], "autocollapse" ) ) ) { collapseTable( i ); }        else if ( hasClass( NavigationBoxes[i], "innercollapse" ) ) { var element = NavigationBoxes[i]; while (element = element.parentNode) { if ( hasClass( element, "outercollapse" ) ) { collapseTable ( i ); break; }           }        }    } } addOnloadHook( createCollapseButtons ); /** Dynamic Navigation Bars (experimental) ************************************* * * Description: See Wikipedia:NavFrame. * 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, 'NavPic' ) ) { NavChild.style.display = 'none'; }           if ( hasClass( NavChild, 'NavContent') ) { 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, 'NavPic')) { NavChild.style.display = 'block'; }           if (hasClass(NavChild, 'NavContent')) { NavChild.style.display = 'block'; }       }        NavToggle.firstChild.data = NavigationBarHide; } } // adds show/hide-button to navigation bars function createNavigationBarToggleButton {   var indexNavigationBar = 0; // iterate over all -elements var divs = document.getElementsByTagName("div"); for (var i = 0; NavFrame = divs[i]; i++) { // if found a navigation bar if (hasClass(NavFrame, "NavFrame")) { indexNavigationBar++; var NavToggle = document.createElement("a"); NavToggle.className = 'NavToggle'; NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar); NavToggle.setAttribute('href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');'); var isCollapsed = hasClass( NavFrame, "collapsed" ); /*            * Check if any children are already hidden. This loop is here for backwards compatibility: * the old way of making NavFrames start out collapsed was to manually add style="display:none" * to all the NavPic/NavContent elements. Since this was bad for accessibility (no way to make            * the content visible without JavaScript support), the new recommended way is to add the class * "collapsed" to the NavFrame itself, just like with collapsible tables. */           for (var NavChild = NavFrame.firstChild; NavChild != null && !isCollapsed; NavChild = NavChild.nextSibling) { if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) { if ( NavChild.style.display == 'none' ) { isCollapsed = true; }               }            }            if (isCollapsed) { for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) { if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) { NavChild.style.display = 'none'; }               }            }            var NavToggleText = document.createTextNode(isCollapsed ? NavigationBarShow : NavigationBarHide); NavToggle.appendChild(NavToggleText); // Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked) for(var j=0; j < NavFrame.childNodes.length; j++) { if (hasClass(NavFrame.childNodes[j], "NavHead")) { NavFrame.childNodes[j].appendChild(NavToggle); }           }            NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar); }   } } addOnloadHook( createNavigationBarToggleButton );

// Code courtesy of pcj of WoWWiki. // This is a modified version of the WoWWiki site version, in that it is designed for global.js use.

// Code adds a checkbox at the top of the Special:RecentChanges list, next to the header. // Ticking it sets a cookie (should be individual to wikis) and starts updating the RC list. // This occurs silently every 60 seconds without a full page reload occuring.

function setCookie(c_name,value,expiredays) { var exdate=new Date exdate.setDate(exdate.getDate+expiredays) document.cookie=c_name+ "=" +escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString) }

function getCookie(c_name) { if (document.cookie.length>0) { c_start=document.cookie.indexOf(c_name + "=") if (c_start!=-1) { c_start=c_start + c_name.length+1 c_end=document.cookie.indexOf(";",c_start) if (c_end==-1) c_end=document.cookie.length return unescape(document.cookie.substring(c_start,c_end)) } } return "" }

function getXmlHttpRequestObject { if (window.XMLHttpRequest) { return new XMLHttpRequest; //Not Internet Explorer } else if(window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); //Internet Explorer } else { //fail silently } } getRCDataRO = getXmlHttpRequestObject; var cr = new RegExp("\r", "gm"); var lf = new RegExp("\n", "gm"); var endText = new RegExp(' [\t\s]*?[\t\s]*? ', "mi"); var rcTimer; var rcRefresh = 60000; function preloadAJAXRC { s = 0; ajaxRCCookie = getCookie("ajaxRC")=="on" ? true:false; document.getElementsByTagName("h1")[s].innerHTML += ' AJAX: '; document.getElementById("ajaxRCtoggle").checked = ajaxRCCookie; if (getCookie("ajaxRC")=="on") loadRCData; }

function toggleRC { if (document.getElementById("ajaxRCtoggle").checked == true) { setCookie("ajaxRC", "on", 30); loadRCData; } else { setCookie("ajaxRC", "off", 30); clearTimeout(rcTimer); } }

function loadRCData { if (getRCDataRO.readyState == 4 || getRCDataRO.readyState == 0) { if (location.href.indexOf("/wiki/")) { rcURL = "http://" + location.hostname + "/wiki/Special:RecentChanges" + location.search; } else { rcURL = "http://" + location.hostname + "/Special:RecentChanges" + location.search; } getRCDataRO.open("GET", rcURL, true); getRCDataRO.onreadystatechange = parseRCdata; getRCDataRO.send(null); } }

function parseRCdata { if (getRCDataRO.readyState == 4) { textFilter = new RegExp(' .*? [\t\s]*?[\t\s]*? ', "i"); rawRCdata = getRCDataRO.responseText.replace(cr, "").replace(lf, ""); filteredRCdata = textFilter.exec(rawRCdata); updatedText = filteredRCdata[0].replace(' ', "").replace(endText, ""); document.getElementById("bodyContent").innerHTML = updatedText; rcTimer = setTimeout("loadRCData;", rcRefresh); } }

if (wgPageName == "Special:RecentChanges") addOnloadHook(preloadAJAXRC);

/** The code marked below was taken from * http://mel-green.com/2009/02/javascript-1337-speak-translator/ * with a few minor translation improvements and tweaks to fit * the wiki framework. */

var PhrasesEnglish = new Array('the', 'dude', 'hacker',                 'hacks', 'you', 'cool', 'oh my gosh',                  'fear', 'power', 'own',                  'what the heck', 'elite', 'for the win',                   'loser', 'good game', 'sucks',                  'sucker', 'is', 'rocks', 'winner'); var PhrasesLeet = new Array('teh', 'dood', 'haxxor', 'hax', 'u',                 '1337', 'zomg', 'ph43', 'powwah', 'pwn',                   'wth', 'leet', 'ftw', 'n00b', 'gg',                  'sux', 'suxxor', 'iz', 'rox', 'pwnster');

var LettersEnglish = new Array('n', 'b', 'k', 'd', 'e', 'f', 'g', 'h',                 'p', 'm', 'r', 'l', 'o', 'q', 's', 't',                  'u', 'x', 'w', 'y', 'z', 'c', 'a', 'j',                   'i', 'v', ' '); var LettersLeet = new Array('/\\/', '|3', '|<', '[)', '3', '|=', '6', '|-|', '|*', '|\\/|', '|2', '|_', '0', '0.', '5', '+',                 '|_|', '><', '\\/\\/', '\'/', '2', '(', '/\\', '_|',                   '1', '\\/', '  ');

function translateText(inputString) {

for (i = 0; i < PhrasesEnglish.length; ++i) inputString = inputString.replace(                       new RegExp(PhrasesEnglish[i], "gi"),                        PhrasesLeet[i]                        ); for (i = 0; i < LettersEnglish.length; ++i) inputString = inputString.replace(                       new RegExp(LettersEnglish[i], "gi"),                        LettersLeet[i]                        ); return inputString; }

/* End of copied code, http://mel-green.com/2009/02/javascript-1337-speak-translator */

function LeetTrigger { $(".leet").each(function {     var originalText = $(this).html;     $(this).html(translateText(originalText));   }); } addOnloadHook(LeetTrigger);

/** Username replace function (Template:USERNAME) ******************************* * Inserts user name into * Originally by User:Splarka * New version by User:Spang */ function UserNameReplace { if(typeof(disableUsernameReplace) != 'undefined' && disableUsernameReplace || wgUserName == null) return; var n = YAHOO.util.Dom.getElementsByClassName('insertusername', 'span', document.getElementById('bodyContent')); for ( var x in n ) { n[x].innerHTML = wgUserName; } } addOnloadHook(UserNameReplace);

// ***************************************************** // * Experimental javascript countdown timer (Splarka) * // * Version 0.0.3                                    * // ***************************************************** // // Usage example: // //  Only January 01 2007 00:00:00 PST until New years. // //  Javascript disabled.

function updatetimer(i) { var now = new Date; var then = timers[i].eventdate; var diff = count=Math.floor((then.getTime-now.getTime)/1000);

// catch bad date strings if(isNaN(diff)) { timers[i].firstChild.nodeValue = '** ' + timers[i].eventdate + ' **' ; return; }

// determine plus/minus if(diff<0) { diff = -diff; var tpm = ''; } else { var tpm = ''; }

// calcuate the diff var left = (diff%60) + ' seconds'; diff=Math.floor(diff/60); if(diff > 0) left = (diff%60) + ' minutes ' + left; diff=Math.floor(diff/60); if(diff > 0) left = (diff%24) + ' hours ' + left; diff=Math.floor(diff/24); if(diff > 0) left = diff + ' days ' + left timers[i].firstChild.nodeValue = tpm + left;

// a setInterval is more efficient, but calling setTimeout // makes errors break the script rather than infinitely recurse timeouts[i] = setTimeout('updatetimer(' + i + ')',1000); }

function checktimers { //hide 'nocountdown' and show 'countdown' var nocountdowns = getElementsByClassName(document, 'span', 'nocountdown'); for(var i in nocountdowns) nocountdowns[i].style.display = 'none' var countdowns = getElementsByClassName(document, 'span', 'countdown'); for(var i in countdowns) countdowns[i].style.display = 'inline'

//set up global objects timers and timeouts. timers = getElementsByClassName(document, 'span', 'countdowndate'); //global timeouts = new Array; // generic holder for the timeouts, global if(timers.length == 0) return; for(var i in timers) { timers[i].eventdate = new Date(timers[i].firstChild.nodeValue); updatetimer(i); //start it up  } } addOnloadHook(checktimers);

// ************************************************** // - end -  Experimental javascript countdown timer // **************************************************

/* Sorting the seed, decoration, building, etc. tables. Code originally by OrbFu. */ function FVwDplTableSort {

var results = document.evaluate("id('SeedLevelHeader')/a", document, null, XPathResult.ANY_TYPE, null); var aResult; if (aResult = results.iterateNext) { aResult.onclick; return aResult; } return null; } addOnloadHook(FVwDplTableSort);