MediaWiki:Common.js

/* Any JavaScript here will be loaded for all users on every page load. */

/** Collapsible tables ********************************************************* * * Description: Allows tables to be collapsed, showing only the header. See *			  http://www.mediawiki.org/wiki/Manual:Collapsible_tables. * Maintainers: en: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 MediaWiki: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 );

/** 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 */ if ( wgIsArticle || window.location.href.indexOf( 'action=submit' ) > -1 ) { var script = document.createElement( 'script' ); script.src = '/index.php?title=MediaWiki:Common.js/CollapsibleTables.js&action=raw&ctype=text/javascript'; script.type = 'text/javascript'; document.getElementsByTagName( 'head' )[0].appendChild( script );

if ( typeof( CollapsibleTables ) != 'undefined' ) { addOnloadHook( CollapsibleTables ); } }

/* Function for getting the page's h1 element. Required dependency for era icon code (function showEras, see below). */ function getFirstHeading { if ( skin != 'nimbus' ) { var elements = getElementsByClass( 'firstHeading', document.getElementById( 'content' ), 'h1' ); } else if ( skin == 'nimbus' ) { var elements = getElementsByClass( 'pagetitle', document.getElementById( 'article-body' ), 'h1' ); }	return ( elements != null && elements.length > 0 ) ? elements[0] : null; }

/*	Source: http://www.dustindiaz.com/getelementsbyclass/ getElementsByClass, which complements getElementById and getElementsByTagName, returns an array of all subelements of node that are tagged with a specific CSS class (searchClass) and are of the tag name tag. If tag is null, it searches for any suitable elements regardless of the tag name. Example: getElementsByClass( 'infobox', document.getElementById( 'content' ), 'div' ) selects the same elements as the CSS declaration #content div.infobox function getElementsByClass( searchClass, node, tag ) { var classElements = new Array;

if( node == null ) { node = document; }

if( tag == null ) { tag = '*'; }

var els = node.getElementsByTagName( tag ); var elsLen = els.length; var tester = new ClassTester( searchClass );

for( i = 0, j = 0; i < elsLen; i++ ) { if( tester.isMatch( els[i] ) ) { classElements[j] = els[i]; j++; }	}

return classElements; }

function ClassTester( className ) { this.regex = new RegExp( "(^|\\s)" + className + "(\\s|$)" ); }

ClassTester.prototype.isMatch = function( element ) { return this.regex.test( element.className ); } /* end getElementsByClass */

/* JS Tab System, Jacked and Hacked from the jsprefs in wikibits.js -Dantman */ function tabSystem { var tabcontainers = $( 'div.tabcontainer' ); for( var tc = 0; tc < tabcontainers.length; tc++ ) { if ( !tabcontainers[tc] || !document.createElement ) { return; }		if ( tabcontainers[tc].nodeName.toLowerCase == 'a' ) { return; // Occasional IE problem }		tabcontainers[tc].className += ' jstabs'; var sections = []; var children = tabcontainers[tc].childNodes; var seci = 0; for ( var i = 0; i < children.length; i++ ) { if ( children[i].className && children[i].className.match( /tab/i ) ) { children[i].id = 'tabsection-' + seci + '-' + tc; children[i].className += ' tabsection'; if ( $.client.profile.name == 'opera' || ( navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ) ) ) { children[i].className += ' tabsection operatabsection'; }				var legends = getElementsByClass( 'tab', children[i], 'div' ); sections[seci] = {}; legends[0].className = 'mainTab'; if ( legends[0] && legends[0].firstChild.nodeValue ) { sections[seci].text = legends[0].firstChild.nodeValue; } else { sections[seci].text = '# ' + seci; }				sections[seci].secid = children[i].id; seci++; if ( sections.length != 1 ) { children[i].style.display = 'none'; } else { var selectedid = children[i].id; }			}		}		var toc = document.createElement( 'ul' ); toc.className = 'tabtoc'; toc.id = 'tabtoc-' + tc; toc.selectedid = selectedid; for ( i = 0; i < sections.length; i++ ) { var li = document.createElement( 'li' ); if ( i === 0 ) { li.className = 'selected'; }			var a = document.createElement( 'a' ); a.href = '#' + sections[i].secid; a.onmousedown = a.onclick = uncoverTabSection; a.appendChild( document.createTextNode( sections[i].text ) ); a.tc = tc; a.secid = sections[i].secid; li.appendChild( a ); toc.appendChild( li ); }		tabcontainers[tc].parentNode.insertBefore( toc, tabcontainers[tc] ); } }

function uncoverTabSection { var oldsecid = this.parentNode.parentNode.selectedid; var newsec = document.getElementById( this.secid ); if ( oldsecid != this.secid ) { var ul = document.getElementById( 'tabtoc-' + this.tc ); document.getElementById( oldsecid ).style.display = 'none'; newsec.style.display = 'block'; ul.selectedid = this.secid; var lis = ul.getElementsByTagName( 'li' ); for ( var i = 0; i< lis.length; i++ ) { lis[i].className = ''; }		this.parentNode.className = 'selected'; }	return false; }

addOnloadHook( tabSystem );

/** * jQuery corner plugin from https://github.com/malsup/corner/raw/master/jquery.corner.js?v2.09 * the fadeToggle code below uses it * * I stylized the code a bit (spaces -> tabs for indentation) and changed $ to * jQuery because right now (2 June 2011, MW 1.16) the former is defined for * MonoBook but the latter isn't */

/*! * jQuery corner plugin: simple corner rounding * Examples and documentation at: http://jquery.malsup.com/corner/ * version 2.12 (23-MAY-2011) * Requires jQuery v1.3.2 or later * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * Authors: Dave Methvin and Mike Alsup */

/** * corner takes a single string argument: jQuery( '#myDiv' ).corner( 'effect corners width' ); * * effect:  name of the effect to apply, such as round, bevel, notch, bite, etc (default is round). * corners: one or more of: top, bottom, tr, tl, br, or bl.  (default is all corners) * width:   width of the effect; in the case of rounded corners this is the radius. *		  specify this value using the px suffix such as 10px (yes, it must be pixels). */
 * ( function( jQuery ) {

var style = document.createElement( 'div' ).style, moz = style['MozBorderRadius'] !== undefined, webkit = style['WebkitBorderRadius'] !== undefined, radius = style['borderRadius'] !== undefined || style['BorderRadius'] !== undefined, mode = document.documentMode || 0, noBottomFold = jQuery.browser.msie && ( ( jQuery.browser.version < 8 && !mode ) || mode < 8 ),

expr = jQuery.browser.msie && ( function {		var div = document.createElement( 'div' );		try {			div.style.setExpression( 'width', '0+0' );			div.style.removeExpression( 'width' );		} catch( e ) {			return false;		}		return true;	});

jQuery.support = jQuery.support || {}; jQuery.support.borderRadius = moz || webkit || radius; // so you can do: if (!jQuery.support.borderRadius) jQuery('#myDiv').corner;

function sz( el, p ) { return parseInt( jQuery.css( el, p ) ) || 0; }; function hex2( s ) { s = parseInt( s ).toString( 16 ); return ( s.length < 2 ) ? '0' + s : s; }; function gpc( node ) { while( node ) { var v = jQuery.css( node, 'backgroundColor' ), rgb; if ( v && v != 'transparent' && v != 'rgba(0, 0, 0, 0)') { if ( v.indexOf( 'rgb' ) >= 0) { rgb = v.match( /\d+/g ); return '#' + hex2( rgb[0] ) + hex2( rgb[1] ) + hex2( rgb[2] ); }			return v;		} if ( node.nodeName.toLowerCase == 'html' ) { break; }		node = node.parentNode; // keep walking if transparent }	return '#ffffff'; };

function getWidth( fx, i, width ) { switch( fx ) { case 'round': return Math.round( width * ( 1 - Math.cos( Math.asin( i / width ) ) ) ); case 'cool': return Math.round( width * ( 1 + Math.cos( Math.asin( i / width ) ) ) ); case 'sharp': return width - i;		case 'bite': return Math.round( width * ( Math.cos( Math.asin( ( width - i - 1 ) / width ) ) ) ); case 'slide': return Math.round( width * ( Math.atan2( i,width / i ) ) ); case 'jut': return Math.round( width * ( Math.atan2( width, ( width - i - 1 ) ) ) ); case 'curl': return Math.round( width * ( Math.atan( i ) ) ); case 'tear': return Math.round( width * ( Math.cos( i ) ) ); case 'wicked': return Math.round( width * ( Math.tan( i ) ) ); case 'long': return Math.round( width * ( Math.sqrt( i ) ) ); case 'sculpt': return Math.round( width * ( Math.log( ( width - i - 1 ), width ) ) ); case 'dogfold': case 'dog': return ( i & 1 ) ? ( i + 1 ) : width; case 'dog2': return ( i & 2 ) ? ( i + 1 ) : width; case 'dog3': return ( i & 3 ) ? ( i + 1 ) : width; case 'fray': return ( i % 2 ) * width; case 'notch': return width; case 'bevelfold': case 'bevel': return i + 1; case 'steep': return i/2 + 1; case 'invsteep': return ( width - i ) / 2 + 1; } };

jQuery.fn.corner = function( options ) { // in 1.3+ we can fix mistakes with the ready state if ( this.length == 0 ) { if ( !jQuery.isReady && this.selector ) { var s = this.selector, c = this.context; jQuery( function {				jQuery( s, c ).corner( options );			}); }		return this; }

return this.each( function( index ) {		var $this = jQuery( this ),			// meta values override options			o = [$this.attr( jQuery.fn.corner.defaults.metaAttr ) || , options || ].join( ' ' ).toLowerCase,			keep = /keep/.test( o ),                                    // keep borders?			cc = ( ( o.match( /cc:(#[0-9a-f]+)/ ) || [] )[1] ),          // corner color			sc = ( ( o.match( /sc:(#[0-9a-f]+)/ ) || [] )[1] ),          // strip color			width = parseInt( ( o.match( /(\d+)px/ ) || [] )[1] ) || 10, // corner width			re = /round|bevelfold|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dogfold|dog|invsteep|steep/,			fx = ( ( o.match( re ) || ['round'] )[0] ),			fold = /dogfold|bevelfold/.test( o ),			edges = { T:0, B:1 },			opts = {				TL:  /top|tl|left/.test( o ),				TR:  /top|tr|right/.test( o ),				BL:  /bottom|bl|left/.test( o ),				BR:  /bottom|br|right/.test( o ) },			// vars used in func later strip, pad, cssHeight, j, bot, d, ds, bw, i, w, e, c, common, $horz;

if ( !opts.TL && !opts.TR && !opts.BL && !opts.BR ) { opts = { TL:1, TR:1, BL:1, BR:1 }; }

// support native rounding if ( jQuery.fn.corner.defaults.useNative && fx == 'round' && ( radius || moz || webkit ) && !cc && !sc ) { if ( opts.TL ) { $this.css( radius ? 'border-top-left-radius' : moz ? '-moz-border-radius-topleft' : '-webkit-border-top-left-radius', width + 'px' ); }			if ( opts.TR ) { $this.css( radius ? 'border-top-right-radius' : moz ? '-moz-border-radius-topright' : '-webkit-border-top-right-radius', width + 'px' ); }			if ( opts.BL ) { $this.css( radius ? 'border-bottom-left-radius' : moz ? '-moz-border-radius-bottomleft' : '-webkit-border-bottom-left-radius', width + 'px' ); }			if ( opts.BR ) { $this.css( radius ? 'border-bottom-right-radius' : moz ? '-moz-border-radius-bottomright' : '-webkit-border-bottom-right-radius', width + 'px' ); }			return; }

strip = document.createElement( 'div' ); jQuery( strip ).css({			overflow: 'hidden',			height: '1px',			minHeight: '1px',			fontSize: '1px',			backgroundColor: sc || 'transparent',			borderStyle: 'solid'		});

pad = { T: parseInt( jQuery.css( this, 'paddingTop' ) ) || 0, R: parseInt( jQuery.css( this, 'paddingRight' ) ) || 0, B: parseInt( jQuery.css( this, 'paddingBottom' ) ) || 0, L: parseInt( jQuery.css( this, 'paddingLeft' ) ) || 0 };

if ( typeof this.style.zoom != undefined ) { this.style.zoom = 1; // force 'hasLayout' in IE		} if ( !keep ) { this.style.border = 'none'; }		strip.style.borderColor = cc || gpc( this.parentNode ); cssHeight = jQuery( this ).outerHeight;

for ( j in edges ) { bot = edges[j]; // only add stips if needed if ( ( bot && ( opts.BL || opts.BR ) ) || ( !bot && ( opts.TL || opts.TR ) ) ) { strip.style.borderStyle = 'none ' + ( opts[j + 'R'] ? 'solid' : 'none' ) + ' none ' + ( opts[j + 'L'] ? 'solid' : 'none' ); d = document.createElement( 'div' ); jQuery( d ).addClass( 'jquery-corner' ); ds = d.style;

bot ? this.appendChild( d ) : this.insertBefore( d, this.firstChild );

if ( bot && cssHeight != 'auto' ) { if ( jQuery.css( this, 'position' ) == 'static' ) { this.style.position = 'relative'; }					ds.position = 'absolute'; ds.bottom = ds.left = ds.padding = ds.margin = '0'; if ( expr ) { ds.setExpression( 'width', 'this.parentNode.offsetWidth' ); } else { ds.width = '100%'; }				} else if ( !bot && jQuery.browser.msie ) { if ( jQuery.css( this, 'position' ) == 'static' ) { this.style.position = 'relative'; }					ds.position = 'absolute'; ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';

// fix ie6 problem when blocked element has a border width if ( expr ) { bw = sz( this, 'borderLeftWidth' ) + sz( this, 'borderRightWidth' ); ds.setExpression( 'width', 'this.parentNode.offsetWidth - ' + bw + '+ "px"' ); } else { ds.width = '100%'; }				} else { ds.position = 'relative'; ds.margin = !bot ? '-' + pad.T + 'px -' + pad.R + 'px ' + ( pad.T - width ) + 'px -' + pad.L + 'px' : ( pad.B - width ) + 'px -' + pad.R + 'px -' + pad.B + 'px -' + pad.L + 'px'; }

for ( i = 0; i < width; i++ ) { w = Math.max( 0, getWidth( fx, i, width ) ); e = strip.cloneNode( false ); e.style.borderWidth = '0 ' + ( opts[j + 'R'] ? w : 0 ) + 'px 0 ' + ( opts[j + 'L'] ? w : 0 ) + 'px'; bot ? d.appendChild( e ) : d.insertBefore( e, d.firstChild ); }

if ( fold && jQuery.support.boxModel ) { if ( bot && noBottomFold ) { continue; }					for ( c in opts ) { if ( !opts[c] ) { continue; }						if ( bot && ( c == 'TL' || c == 'TR' ) ) { continue; }						if ( !bot && ( c == 'BL' || c == 'BR' ) ) { continue; }

common = { position: 'absolute', border: 'none', margin: 0, padding: 0, overflow: 'hidden', backgroundColor: strip.style.borderColor };						$horz = jQuery( ' ' ).css( common ).css({							width: width + 'px',							height: '1px'						}); switch( c ) { case 'TL': $horz.css({ bottom: 0, left: 0 }); break; case 'TR': $horz.css({ bottom: 0, right: 0 }); break; case 'BL': $horz.css({ top: 0, left: 0 }); break; case 'BR': $horz.css({ top: 0, right: 0 }); break; }						d.appendChild( $horz[0] );

var $vert = jQuery( ' ' ).css( common ).css({							top: 0,							bottom: 0,							width: '1px',							height: width + 'px'						}); switch( c ) { case 'TL': $vert.css({ left: width }); break; case 'TR': $vert.css({ right: width }); break; case 'BL': $vert.css({ left: width }); break; case 'BR': $vert.css({ right: width }); break; }						d.appendChild( $vert[0] ); }				}			}		}	}); };

jQuery.fn.uncorner = function { if ( radius || moz || webkit ) { this.css( radius ? 'border-radius' : moz ? '-moz-border-radius' : '-webkit-border-radius', 0 ); }	jQuery( 'div.jquery-corner', this ).remove; return this; };

// expose options jQuery.fn.corner.defaults = { useNative: true, // true if plugin should attempt to use native browser support for border radius rounding metaAttr: 'data-corner' // name of meta attribute to use for options };

})( jQuery );

/* end jQuery corner plugin code */

// ===================== // BEGIN fadeToggle JS // =====================

jQuery( function( jQuery ) { /** * Title :fadeToggle * Name   :Toggle fade function * Action :will toggle the opacity of called object * Usage :  .fadeToggle */ jQuery.fn.fadeToggle = function( speed, easing, callback ) {	return this.animate( {opacity: 'toggle'}, speed, easing, callback ); };

jQuery( '.footdrop' ).click( function( e ) {	jQuery( this ).text( jQuery( this ).text == 'Show ▼' ? 'Hide ▲' : 'Show ▼' );	jQuery( this ).next.slideToggle( 'slow' );	jQuery( '.popup' ).fadeOut( 100 ); });

jQuery( '.footdrop' ).hover(	function { jQuery( this ).toggleClass( 'whitet' ).toggleClass( 'oranget' ); },	function { jQuery( this ).toggleClass( 'oranget' ).toggleClass( 'whitet' ); });

jQuery( '.popup' ).click( function( e ) {	jQuery( this ).fadeToggle( 100 ); });

jQuery( '.pop' ).click( function( e ) {	jQuery( this ).next.fadeToggle( 100 ); });

jQuery( '.roundtop' ).corner( 'top 10px' ); jQuery( '.roundbod' ).corner( 'bottom 10px' );

});

// =================== // END fadeToggle JS // ===================

/** ImageFade JS **/

$( document ).ready( function {	$( 'div.fadeout img' ).mouseenter( function { $( this ).animate( {opacity: 0}, 800 ); }).mouseleave( function { $( this ).animate( {opacity: 1}, 800 ); }); });

// Code courtesy of pcj of WoWWiki. // This is a modified version of the WoWWiki site version.

// 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 30 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 ) { var c_start, c_end; 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 ''; }

var ajaxPages = new Array( 'Special:RecentChanges' ); var ajaxRCOverride = false; var rcRefresh = 30000;

function ajaxRC { var appTo; if ( skin == 'nimbus' ) { appTo = $( '.pagetitle' ); } else if ( skin != 'nimbus' ) { appTo = $( '.firstHeading' ); }	appTo.append(		'  AUTO-REFRESH:  '	); $( '#autoRefreshToggle' ).click( function {		setCookie( 'ajaxRC', $( '#autoRefreshToggle' ).is( ':checked' ) ? 'on' : 'off' );		loadRCData;	} ); $( '#autoRefreshProgress' ).hide; if ( getCookie( 'ajaxRC' ) == 'on' || ajaxRCOverride ) { $( '#autoRefreshToggle' ).attr( 'checked', 'checked' ); setTimeout( 'loadRCData;', rcRefresh ); } }

function loadRCData { if ( !$( '#autoRefreshToggle' ).is( ':checked' ) ) { return; }	$( '#autoRefreshProgress').show; var article; if ( skin == 'nimbus' ) { article = '#mw-content-text'; } else if ( skin != 'nimbus' ) { article = '#bodyContent'; }	$( article ).load( location.href + ' ' + article + ' > *', function( data ) {		$( article + ' .mw-collapsible' ).makeCollapsible;		$( '#autoRefreshProgress' ).hide;		if ( $( '#autoRefreshToggle' ).is( ':checked' ) ) {			setTimeout( 'loadRCData;', rcRefresh );		}	} ); }

$( function {	for ( x in ajaxPages ) {		if ( wgPageName == ajaxPages[x] && $( '#autoRefreshToggle' ).length == 0 ) {			ajaxRC;		}	} } );