MediaWiki:Common.js
Note: After saving, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/* Any JavaScript here will be loaded for all users on every page load. */
/** Title rewrite ********************************************************
* Rewrites the page's title, used by [[Template:Title]]
*/
function rewriteTitle()
{
if(typeof(SKIP_TITLE_REWRITE) != 'undefined' && SKIP_TITLE_REWRITE)
return;
var titleDiv = document.getElementById('title-meta');
if(titleDiv == null || titleDiv == undefined)
return;
var cloneNode = titleDiv.cloneNode(true);
var firstHeading = YAHOO.util.Dom.getElementsByClassName('firstHeading', 'h1', document.getElementById('content') )[0];
var node = firstHeading.childNodes[0];
// new, then old!
firstHeading.replaceChild(cloneNode, node);
cloneNode.style.display = "inline";
var titleAlign = document.getElementById('title-align');
firstHeading.style.textAlign = titleAlign.childNodes[0].nodeValue;
}
addOnloadHook(rewriteTitle, false);
/* Dismissable Watchlist Message */
function addDismissButton() {
var watchlistMessage = document.getElementById("watchlist-message");
if ( watchlistMessage == null ) return;
var watchlistCookieID = watchlistMessage.className.replace(/cookie\-ID\_/ig,'');
if ( document.cookie.indexOf( "hidewatchlistmessage-" + watchlistCookieID + "=yes" ) != -1 ) {
watchlistMessage.style.display = "none";
}
var Button = document.createElement( "span" );
var ButtonLink = document.createElement( "a" );
var ButtonText = document.createTextNode( "dismiss" );
ButtonLink.setAttribute( "id", "dismissButton" );
ButtonLink.setAttribute( "href", "javascript:dismissWatchlistMessage();" );
ButtonLink.setAttribute( "title", "Hide this message for one week" );
ButtonLink.appendChild( ButtonText );
Button.appendChild( document.createTextNode( "[" ) );
Button.appendChild( ButtonLink );
Button.appendChild( document.createTextNode( "]" ) );
watchlistMessage.appendChild( Button );
}
function dismissWatchlistMessage() {
var e = new Date();
e.setTime( e.getTime() + (7*24*60*60*1000) );
var watchlistMessage = document.getElementById("watchlist-message");
var watchlistCookieID = watchlistMessage.className.replace(/cookie\-ID\_/ig,'');
document.cookie = "hidewatchlistmessage-" + watchlistCookieID + "=yes; expires=" + e.toGMTString() + "; path=/";
watchlistMessage.style.display = "none";
}
addOnloadHook( addDismissButton );
/** 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.style.styleFloat = "right";
Button.style.cssFloat = "right";
Button.style.fontWeight = "normal";
Button.style.textAlign = "right";
Button.style.width = "6em";
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 );
}
}
}
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 < 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 NavToggleText = document.createTextNode(NavigationBarHide);
for (
var NavChild = NavFrame.firstChild;
NavChild != null;
NavChild = NavChild.nextSibling
) {
if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
if (NavChild.style.display == 'none') {
NavToggleText = document.createTextNode(NavigationBarShow);
break;
}
}
}
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 );
/* 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);
};
})();
// **************************************************
// Experimental javascript countdown timer (Splarka)
// Version 0.0.3
// **************************************************
//
// Usage example:
// <span class="countdown" style="display:none;">
// Only <span class="countdowndate">January 01 2007 00:00:00 PST</span> until New years.
// </span>
// <span class="nocountdown">Javascript disabled.</span>
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 = 'ended... ';
} else {
var tpm = 'in... ';
}
// 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);
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 ""
}
// Embed live blogs from Cover It Live (can be altered to embed anything really)
function escapeString(str){
return str.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
}
function GetLiveBlog(){
var blip_elements = getElementsByClassName(document.getElementById('bodyContent'),'div','live_blog');
for(var i = 0; i < blip_elements.length; i++){
blip_elements[i].innerHTML = "<iframe src='"+ escapeString(blip_elements[i].firstChild.href) +"' scrolling='no' height='550px' width='550px' frameBorder='0'></iframe>";
}
}
GetLiveBlog();
/** Tooltips *********************************************************
* Allows popups tooltips.
*/
// Wrap the script in a closure to make the functions and variables private
(function() {
var containerSelector = '#content, article'; // jQuery selector for the content area of the article
var inlineSelector = '.tooltip-source'; // jQuery selector for the inline element which controls the tooltip
// Offset to position the tooltip slightly away from the mouse
var mouseOffset = {
top: 10,
bottom: 0,
left: 10,
right: 0
};
// Tooltip CSS; make the tooltip float over other content
var tooltipCSS = {
position: 'fixed',
'z-index': 1000
};
// Get the tooltip element from the inline element
function getTooltip(element) {
var inlineElement = $(element).closest(inlineSelector);
if (inlineElement.length > 0) {
var tooltipID = inlineElement.attr('id') + '-tooltip';
return $(document.getElementById(tooltipID)); // using getElementById removes the need to escape special characters
} else {
return $();
}
}
function showTooltip(element) {
var tooltip = getTooltip(element);
tooltip.find('img.lzyPlcHld:not(.lzyLoaded)').trigger('onload'); // load any lazy loaded elements
tooltip.css(tooltipCSS);
tooltip.show();
}
function hideTooltip(element) {
var tooltip = getTooltip(element);
tooltip.hide();
}
function positionTooltip(element, tooltip, mouseX, mouseY) {
var contentArea = getContentArea();
// For deciding if we need to switch sides for the tooltip
var tooltipHeight = tooltip.outerHeight();
var tooltipWidth = tooltip.outerWidth();
// Position the tooltip in the standard position (bottom-right of cursor)
var positionY = mouseY + mouseOffset.top;
var positionX = mouseX + mouseOffset.left;
// Adjust the tooltip so that as much of it fits in the content area as possible
if ((positionY + tooltipHeight) > contentArea.bottom) {
var spaceAbove = mouseY;
var spaceBelow = (contentArea.bottom - mouseY);
if (spaceAbove > spaceBelow) {
// Move the tooltip to above the element
positionY = mouseY - tooltipHeight - mouseOffset.bottom;
}
}
if ((positionX + tooltipWidth) > contentArea.right) {
var spaceLeft = mouseX;
var spaceRight = (contentArea.right - mouseX);
if (spaceLeft > spaceRight) {
// Move the tooltip to the left of the element
positionX = mouseX - tooltipWidth - mouseOffset.right;
}
}
// Position the tooltip
tooltip.css({
left: positionX + 'px',
top: positionY + 'px'
});
}
// Get the bounds of the content area which the tooltip should stay within
function getContentArea() {
var container = $(containerSelector);
var containerPosition = container.offset();
var containerMargins = {
top: parseFloat(container.css('margin-top')),
left: parseFloat(container.css('margin-left'))
};
return {
top: containerPosition.top - containerMargins.top,
left: containerPosition.left - containerMargins.left,
bottom: Math.max(container.height(), $(window).height()),
right: containerPosition.left + container.width()
};
}
$(document).ready(function() {
// Attach events to the inline element
var inlineElements = $(inlineSelector);
inlineElements.each(function() {
$(this).mouseenter(function(event) {
showTooltip(this);
});
$(this).mouseleave(function(event) {
hideTooltip(this);
});
$(this).mousemove(function(event) {
positionTooltip(this, getTooltip(this), event.clientX, event.clientY);
});
});
});
})();
/** Voting *******************************
* By [[User:Spang|Spang]]
* Voting system
* Add "ratings.disabled = true" without the quotes to your JS to disable
*/
ratings = new Object();
ratings.getCallback = {
success: function( o ){
var j = YAHOO.tools.JSONParse(o.responseText);
try {
with( j.query.wkvoteart[wgArticleId] ){
if( typeof votesavg != undefined && votesavg ){
ratings.avgVote = ( 5>=votesavg>=1 ? Math.round(votesavg*10)/10 : 5 );
ratings.text[0] = ( 'average rating: ' + ratings.avgVote );
}
if( typeof( uservote ) != 'undefined' && uservote ){
ratings.myVote = uservote;
ratings.hasVoted = true
} else {
ratings.hasVoted = false;
}
ratings.paint( 0 );
}
} catch( e ){}
},
failure: function( o ){
ratings.out('connection failure :(');
}
};
ratings.vote = function( a ){
if( wgUserName == null ){
window.location = '/wiki/Special:Userlogin?returnto=' + wgPageName;
return;
}
var b = ( ratings.hasVoted == true ? 'update' : 'insert' );
ratings.get = YAHOO.util.Connect.asyncRequest('GET', '/api.php?format=json&action=' + b + '&list=wkvoteart&wkuservote=1&wkctime=5&wkpage=' + wgArticleId + '&wkvote=' + a, ratings.voteCallback, null);
ratings.myVote = a;
ratings.paint(a, 'submitting vote...');
ratings.votingInProgress = true;
};
ratings.voteCallback = {
success: function( o ){
var j = YAHOO.tools.JSONParse(o.responseText);
if( j.item.wkvoteart[3] != undefined && ratings.retried != true ){
ratings.retried = true;
ratings.out('failed, retrying...');
ratings.get = YAHOO.util.Connect.asyncRequest('GET', '/api.php?format=json&action=delete&list=wkvoteart&wkpage=' + wgArticleId, ratings.retry, null);
return;
};
try {
with( j.item.wkvoteart[0] == undefined ? j.item.wkvoteart : j.item.wkvoteart[0] ){
ratings.hasVoted = true;
ratings.myVote = vote;
ratings.avgVote = Math.round(avgvote*10)/10;
if( ratings.avgVote > 5 )
ratings.avgVote = 5
}
} catch( e ){
ratings.out('Error: ' + e);
ratings.votingInProgress = false;
return;
}
ratings.votingInProgress = false;
ratings.out('thanks for voting!');
ratings.text[0] = ( 'average rating: ' + ratings.avgVote );
ratings.timeout = setTimeout('ratings.paint(0)', 1000);
},
failure: function( o ){
ratings.votingInProgress = false;
ratings.out('connection failure :(');
}
};
ratings.retry = {
success: function( o ){
ratings.get = YAHOO.util.Connect.asyncRequest('GET', '/api.php?format=json&action=insert&list=wkvoteart&wkuservote=1&wkctime=5&wkpage=' + wgArticleId + '&wkvote=' + ratings.myVote, ratings.voteCallback, null);
},
failure: function( o ){
ratings.out('error');
}
};
ratings.out = function( m ){
document.getElementById('ratingMsg').innerHTML = m;
};
ratings.paint = function( n, m ){
if( ratings.votingInProgress == true )
return;
YAHOO.util.Dom.setStyle(['vote-1','vote-2','vote-3','vote-4','vote-5'], 'backgroundPosition', '0 0');
for( var l = 1; l <= n; l++ ){
YAHOO.util.Dom.setStyle('vote-' + l, 'backgroundPosition', '0 -34px');
}
if( n === 0 && ( ratings.myVote != false || ratings.avgVote != undefined ) ){
var a = ratings.hasVoted == true ? '0 -34px' : '0 -17px';
var b = ratings.hasVoted != false ? ratings.myVote : ratings.avgVote;
for( var l = 1; l <= b; l++ ){
YAHOO.util.Dom.setStyle('vote-' + l, 'backgroundPosition', a);
}
if( l-ratings.avgVote < 1 && l <= 5 && ratings.hasVoted != true ){
var p = ratings.avgVote-(l-1);
var q = 0;
switch( true ){
case 0<p&&p<=.2:
q = '-51px';
break;
case .2<p&&p<=.4:
q = '-68px';
break;
case .4<p&&p<=.6:
q='-85px';
break;
case .6<p&&p<=.8:
q = '-102px';
break;
case .8<p&&p<1:
q = '-119px';
break;
default:
};
document.getElementById('vote-' + l).style.backgroundPosition = '0px ' + q
}
};
if( wgUserName == null && n != 0 )
ratings.out('please log in to vote');
else if( m == undefined )
ratings.out( ratings.text[n] );
else ratings.out( m );
};
ratings.setup = function(){
if( wgIsArticle == false || ratings.disabled == true )
return;
var a = document.getElementById('p-search');
if( !a )
return false;
ratings.p = document.createElement('div');
ratings.p.innerHTML = '<h5>rating</h5><div id="ratingBody" class="pBody"><div><ul id="ratingStars" onmouseout="ratings.paint(0);"><li id="vote-1" class="voteStar" onmouseover="ratings.paint(1)" onclick="ratings.vote(1);"> 1</li><li id="vote-2" class="voteStar" onmouseover="ratings.paint(2)" onclick="ratings.vote(2);"> 2</li><li id="vote-3" class="voteStar" onmouseover="ratings.paint(3)" onclick="ratings.vote(3);"> 3</li><li id="vote-4" class="voteStar" onmouseover="ratings.paint(4)" onclick="ratings.vote(4);"> 4</li><li id="vote-5" class="voteStar" onmouseover="ratings.paint(5)" onclick="ratings.vote(5);"> 5 </li></ul></div><span id="ratingMsg">rate this article!</span></div>';
ratings.p.className = 'portlet';
ratings.p.id = 'p-rating';
document.getElementById('column-one').insertBefore(ratings.p, a);
ratings.text = new Array('rate this article!', 'poor', 'nothing special', 'worth reading', 'pretty good', 'awesome!');
ratings.get = YAHOO.util.Connect.asyncRequest('GET', '/api.php?format=json&action=query&list=wkvoteart&wkuservote=1&wkctime=5&wkpage=' + wgArticleId, ratings.getCallback, null);
};
/* YAHOO.util.Event.onContentReady('column-one', ratings.setup); */
addEventHandler(window, "load", ratings.setup);