MediaWiki:Common.js

From the Star Wars Merchandise Wiki.
Jump to navigationJump to search

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.
/* <pre><nowiki> */

/* 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 {{USERNAME}} 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: <select id="stdSummaries" onchange="onStdSummaryChange()">';
	comboString += '</select><br />';
	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 = '<select id="stdPreloads" onchange="onPreloadChange()">';
	comboString += '</select>';
	span.innerHTML = comboString;

	span = document.getElementById( 'lf-preload-pagename' );
	span.innerHTML = '<input type="text" class="textbox" />';
	span = document.getElementById( 'lf-preload-button' );
	span.innerHTML = '<input type="button" class="button" value="Insert" onclick="doCustomPreload()" />';

	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 <jack@countervandalism.net>
 * @date June 7, 2010
 */
function addInformationToUploadForm() {
	var box = document.getElementById( 'wpUploadDescription' );
	box.value = '{{Information\n|attention = \n|description = \n|source = \n|author = \n|licensing = \n|other versions = \n}}';
}

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

$( loadFunc );

// </nowiki></pre>