MediaWiki:Common.js

/* */

/* This global variable specifies if client-side persistent storage is available. Currently, only Firefox 2+ supports this specification. This global storage is used to store information about which infoboxes are hidden. */ window.storagePresent = ( typeof globalStorage !== 'undefined' );

/* Stores the (unmodified) page title. */ function storePageName { var skin = mw.config.get( 'skin' ); if ( skin == 'monobook' || skin == 'vector' ) { window.pageName = jQuery( 'h1#firstHeading span' ).text; } else if ( skin == 'bluecloud' || skin == 'eminence' || skin == 'monaco' ) { window.pageName = jQuery( 'h1.firstHeading' ).text; } else if ( skin == 'games' || skin == 'nimbus' || skin == 'sports' ) { window.pageName = jQuery( 'h1.pagetitle' ).text; } else if ( skin == 'hope' ) { window.pageName = jQuery( 'h2#one' ).text; } else if ( skin == 'modern' ) { window.pageName = jQuery( 'h1#firstHeading span' ).text; } else if ( skin == 'truglass' ) { window.pageName = jQuery( 'h1#title' ).text; } }

/* Adds a trim method to string variables. */ String.prototype.trim = function { return this.replace( /^\s+|\s+$/g, '' ); };

/* Searches an array for an element and returns its index, or -1 if it's not in the array. */ function arrayFind( array, value ) { for ( var i = 0; i < array.length; i++ ) { if ( array[i] == value ) { return i;		} }

return -1; }

/* Removes the first occurrence of an element in an array, if it is there. */ function arrayRemove( array, value ) { var i = arrayFind( array, value );

if ( i != -1 ) { array.splice( i, 1 ); } }

/*	the ContentLoader class to encapsulate "creative differences" with XHR

Usage: - construct a ContentLoader object: var loader = new ContentLoader; - set necessary state parameters (via fields); e.g. loader.myvar = 'mytext'; - set the callback: loader.callback = myfunc; - send the request: loader.send(url, postdata = null, contentType = 'application/x-www-form-urlencoded'); (if postdata isn't null or omitted, POST is used, otherwise GET) - the callback function is called when the content is loaded - the ContentLoader object is this - the raw response data is this.text - the XML DOM object, if any, is this.document function ContentLoader { this.cache = true; }

ContentLoader.prototype.enableCache = function( caching ) { this.cache = ( caching == null ) ? true : this.cache; }

ContentLoader.prototype.createRequest = function { if ( typeof XMLHttpRequest !== 'undefined' ) { return new XMLHttpRequest; } else if ( typeof ActiveXObject !== 'undefined' ) { return new ActiveXObject( 'Msxml2.XMLHTTP' ); }

return null; }

ContentLoader.prototype.send = function( url, postdata, contentType ) { var method = ( postdata == null ) ? 'GET' : 'POST'; this.request = this.createRequest; this.request.open( method, url );

if ( !this.cache ) { this.request.setRequestHeader( 'If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT' ); }

var request = this.request; var loader = this;

if ( postdata == null ) { if ( contentType == null ) { contentType = 'application/x-www-form-urlencoded'; }

request.setRequestHeader( 'Content-type', contentType ); }

var f = function { if ( request.readyState == 4 ) { loader.text = request.responseText; loader.document = request.responseXML; request = null; loader.request = null; loader.callback; }	}

this.request.onreadystatechange = f;	this.request.send( postdata ); } /* end ContentLoader */

/*   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 */

/* Returns the parameter as it appears in the query string. Equivalent to $_GET[p] in PHP. */ function queryString( p ) { var re = RegExp( '[&?]' + p + '=([^&]*)' ); var matches;

if ( matches = re.exec( document.location ) ) { try { return decodeURI( matches[1] ); } catch( e ) { } }

return null; }

/* Dynamically load a combobox's content by pagename (e. g. Template:Stdsummaries). The page should be of the same format as http://starwars.wikia.com/wiki/Template:Stdsummaries */ function requestComboFill( id, page ) { var loader = new ContentLoader; loader.comboID = id; loader.callback = onComboDataArrival; loader.send( mw.config.get( 'wgScriptPath' ) + '/index.php?title=' + page + '&action=raw&ctype=text/plain' ); }

function onComboDataArrival { fillCombo( this.text, this.comboID ); }

function fillCombo( text, comboid ) { var combo = document.getElementById( comboid ); var lines = text.split( "\n" );

for ( var i = 0; i < lines.length; i++ ) { var value = lines[i].indexOf( '-- ' ) == 0 ? lines[i].substring( 3 ) : ''; var option = document.createElement( 'option' ); option.setAttribute( 'value', value ); option.appendChild( document.createTextNode( lines[i] ) ); combo.appendChild( option ); } } /* end combo fill code */

/* Loads the current source of the page "pagename" (as stored in the database) and inserts it at the cursor position */ function doPreload( pagename ) { var loader = new ContentLoader; loader.callback = onPreloadArrival; loader.send( mw.config.get( 'wgScriptPath' ) + '/index.php?title=' + pagename + '&action=raw&ctype=text/plain' ); }

function insertAtCursor( myField, myValue ) { // IE support if ( document.selection ) { myField.focus; sel = document.selection.createRange; sel.text = myValue; } else if ( myField.selectionStart || myField.selectionStart == '0' ) { // MOZILLA/NETSCAPE support var startPos = myField.selectionStart; var endPos = myField.selectionEnd; myField.value = myField.value.substring( 0, startPos ) + myValue + myField.value.substring( endPos, myField.value.length ); } else { myField.value += myValue; } }

function onPreloadArrival { insertAtCursor( document.getElementById( 'wpTextbox1' ), this.text ); } /* end preload code */

/* Returns h1.firstHeading (the page title element). */ function getFirstHeading { var elements = getElementsByClass( 'firstHeading', document.getElementById( 'content' ), 'h1' ); return ( elements !== null && elements.length > 0 ) ? elements[0] : null; }

/* Returns the element's nearest parent that has the specified CSS class. */ function getParentByClass( className, element ) { var tester = new ClassTester( className ); var node = element.parentNode;

while ( node != null && node != document ) { if ( tester.isMatch( node ) ) { return node; }

node = node.parentNode; }

return null; }

/* Makes the image on the search form, if one is present, point to the search page. */ function rewriteSearchFormLink { var links = document.getElementById( 'searchform' ).getElementsByTagName( 'a' );

if ( links.length > 0 ) { links[0].href = mw.config.get( 'wgScriptPath' ) + '/index.php?title=Special:Search&adv=1'; } }

/* Replaces with the name of the user browsing the page. Requires copying Template:USERNAME. */ function substUsername { $( '.insertusername' ).text( mw.config.get( 'wgUserName' ) ); }

/* Performs dynamic hover class rewriting to work around the IE6 :hover bug (needs CSS changes as well) */ function rewriteHover { var gbl = document.getElementById( 'hover-global' );

if ( gbl == null ) { return; }

var nodes = getElementsByClass( 'hoverable', gbl );

for ( var i = 0; i < nodes.length; i++ ) { nodes[i].onmouseover = function { this.className += ' over'; }		nodes[i].onmouseout = function { this.className = this.className.replace( new RegExp( " over\\b" ), '' ); }	} }

// onload stuff function loadFunc { storePageName; addHideButtons;

if ( document.getElementById( 'mp3-navlink' ) != null ) { document.getElementById( 'mp3-navlink' ).onclick = onArticleNavClick; document.getElementById( 'mp3-navlink' ).getElementsByTagName( 'a' )[0].href = 'javascript:void(0)'; }

if ( window.storagePresent ) { initVisibility; }

rewriteSearchFormLink; fillEditSummaries; fillPreloads;

substUsername; rewriteTitle; showEras( 'title-eraicons' ); showEras( 'title-shortcut' ); rewriteHover; addAlternatingRowColors; fixSearch;

if ( typeof onPageLoad !== 'undefined' ) { onPageLoad; } }

function infoboxToggle { var page = window.pageName.replace( /\W/g, '_' ); var nowShown;

if ( document.getElementById( 'infoboxtoggle' ).innerHTML == '[Hide]' ) { document.getElementById( 'infoboxinternal' ).style.display = 'none'; document.getElementById( 'infoboxtoggle' ).innerHTML = '[Show]'; nowShown = false; } else { document.getElementById( 'infoboxinternal' ).style.display = 'block'; document.getElementById( 'infoboxtoggle' ).innerHTML = '[Hide]'; nowShown = true; }

if ( window.storagePresent ) { var storage = globalStorage[window.location.hostname]; storage.setItem( 'infoboxshow-' + page, nowShown ); } }

function fillEditSummaries { var label = document.getElementById( 'wpSummaryLabel' );

if ( label == null ) { return; }

var comboString = 'Standard summaries: '; comboString += ' ';	label.innerHTML = comboString + label.innerHTML;

requestComboFill( 'stdSummaries', 'Template:Stdsummaries' ); }

function onStdSummaryChange { var combo = document.getElementById( 'stdSummaries' ); var value = combo.options[combo.selectedIndex].value;

if ( value != '' ) { document.getElementById( 'wpSummary' ).value = value; } }

function fillPreloads { var div = document.getElementById( 'lf-preload' );

if ( div == null ) { return; }

div.style.display = 'block'; var span = document.getElementById( 'lf-preload-cbox' );

var comboString = ''; comboString += ' '; span.innerHTML = comboString;

span = document.getElementById( 'lf-preload-pagename' ); span.innerHTML = ''; span = document.getElementById( 'lf-preload-button' ); span.innerHTML = '';

requestComboFill( 'stdPreloads', 'Template:Stdpreloads' ); }

function doCustomPreload { doPreload( document.getElementById( 'lf-preload-pagename' ).getElementsByTagName( 'input' )[0].value ); }

function onPreloadChange { var combo = document.getElementById( 'stdPreloads' ); var value = combo.options[combo.selectedIndex].value;

if ( value == '' ) { return; }

value = 'Template:' + value + '/preload'; value = value.replace( ' ', '_' ); doPreload( value ); }

// ============================================================ // BEGIN JavaScript title rewrite function rewriteTitle { if ( typeof window.SKIP_TITLE_REWRITE !== 'undefined' && window.SKIP_TITLE_REWRITE ) { return; }

var titleDiv = document.getElementById( 'title-meta' );

if ( titleDiv == null || titleDiv == undefined ) { return; }

var cloneNode = titleDiv.cloneNode( true ); var firstHeading = getFirstHeading; 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; }

function showEras( className ) { if ( typeof SKIP_ERAS !== 'undefined' && SKIP_ERAS ) { return; }

var titleDiv = document.getElementById( className );

if ( titleDiv == null || titleDiv == undefined ) { return; }

var cloneNode = titleDiv.cloneNode( true ); var firstHeading = getFirstHeading; firstHeading.insertBefore( cloneNode, firstHeading.childNodes[0] ); cloneNode.style.display = 'block'; } // END JavaScript title rewrite

function initVisibility { var storage = globalStorage[window.location.hostname];

var page = window.pageName.replace( /\W/g, '_' ); var show = storage.getItem( 'infoboxshow-' + page );

if ( show == 'false' ) { infoboxToggle; }

var hidables = getElementsByClass( 'hidable' );

for ( var i = 0; i < hidables.length; i++ ) { show = storage.getItem( 'hidableshow-' + i + '_' + page );

if ( show == 'false' ) { var content = getElementsByClass( 'hidable-content', hidables[i] ); var button = getElementsByClass( 'hidable-button', hidables[i] );

if (				content != null && content.length > 0 &&				button != null && button.length > 0 &&				content[0].style.display != 'none'			) { button[0].onclick( 'bypass' ); }		} else if ( show == 'true' ) { var content = getElementsByClass( 'hidable-content', hidables[i] ); var button = getElementsByClass( 'hidable-button', hidables[i] );

if (				content != null && content.length > 0 &&				button != null && button.length > 0 &&				content[0].style.display == 'none'			) { button[0].onclick( 'bypass' ); }		}	} }

function rewriteHover { var gbl = document.getElementById( 'hover-global' );

if ( gbl == null ) { return; }

var nodes = getElementsByClass( 'hoverable', gbl );

for ( var i = 0; i < nodes.length; i++ ) { nodes[i].onmouseover = function { this.className += ' over'; }		nodes[i].onmouseout = function { this.className = this.className.replace( new RegExp( " over\\b" ), '' ); }	} }

function onArticleNavClick { var div = document.getElementById( 'mp3-nav' );

if ( div.style.display == 'block' ) { div.style.display = 'none'; } else { div.style.display = 'block'; } }

function addAlternatingRowColors { var infoboxes = getElementsByClass( 'infobox', document.getElementById( 'content' ) );

if ( infoboxes.length == 0 ) { return; }

for ( var k = 0; k < infoboxes.length; k++ ) { var infobox = infoboxes[k];

var rows = infobox.getElementsByTagName( 'tr' ); var changeColor = false;

for ( var i = 0; i < rows.length; i++ ) { if ( rows[i].className.indexOf( 'infoboxstopalt' ) != -1 ) { break; }

var ths = rows[i].getElementsByTagName( 'th' );

if ( ths.length > 0 ) { continue; }

if ( changeColor ) { rows[i].style.backgroundColor = '#f9f9f9'; }

changeColor = !changeColor; }	} }

function addHideButtons { var hidables = getElementsByClass( 'hidable' ); for ( var i = 0; i < hidables.length; i++ ) { var box = hidables[i]; var button = getElementsByClass( 'hidable-button', box, 'span' );

if ( button != null && button.length > 0 ) { button = button[0];

button.onclick = toggleHidable; button.appendChild( document.createTextNode( '[Hide]' ) );

if ( new ClassTester( 'start-hidden' ).isMatch( box ) ) { button.onclick( 'bypass' ); }		}	} }

function toggleHidable( bypassStorage ) { var parent = getParentByClass( 'hidable', this ); var content = getElementsByClass( 'hidable-content', parent ); var nowShown;

if ( content != null && content.length > 0 ) { content = content[0];

if ( content.style.display == 'none' ) { content.style.display = content.oldDisplayStyle; this.firstChild.nodeValue = '[Hide]'; nowShown = true; } else { content.oldDisplayStyle = content.style.display; content.style.display = 'none'; this.firstChild.nodeValue = '[Show]'; nowShown = false; }

if ( window.storagePresent && ( typeof bypassStorage == 'undefined' || bypassStorage != 'bypass' ) ) { var page = window.pageName.replace( /\W/g, '_' ); var items = getElementsByClass( 'hidable' ); var item = -1;

for ( var i = 0; i < items.length; i++ ) { if ( items[i] == parent ) { item = i;					break; }			}

if ( item == -1 ) { return; }

var storage = globalStorage[window.location.hostname]; storage.setItem( 'hidableshow-' + item + '_' + page, nowShown ); }	} }

function fixSearch { var button = document.getElementById( 'searchSubmit' );

if ( button ) { button.name = 'go'; } }

/** * Adds Template:Information to the information box on Special:Upload * @author Jack Phoenix  * @date June 7, 2010 */ function addInformationToUploadForm { var box = document.getElementById( 'wpUploadDescription' ); box.value = ''; }

if ( mw.config.get( 'wgCanonicalSpecialPageName' ) == 'Upload' && queryString( 'wpForReUpload' ) === null ) { $( addInformationToUploadForm ); }

$( loadFunc );

//