<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-TabbedLanguages.js</id>
	<title>MediaWiki:Gadget-TabbedLanguages.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-TabbedLanguages.js"/>
	<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=MediaWiki:Gadget-TabbedLanguages.js&amp;action=history"/>
	<updated>2026-04-09T10:22:08Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://linguifex.com/w/index.php?title=MediaWiki:Gadget-TabbedLanguages.js&amp;diff=474993&amp;oldid=prev</id>
		<title>Sware: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=MediaWiki:Gadget-TabbedLanguages.js&amp;diff=474993&amp;oldid=prev"/>
		<updated>2025-11-04T17:52:10Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:52, 4 November 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
	<entry>
		<id>https://linguifex.com/w/index.php?title=MediaWiki:Gadget-TabbedLanguages.js&amp;diff=474992&amp;oldid=prev</id>
		<title>wikt&gt;Ioaxxere: Polyfill deprecated function newNode</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=MediaWiki:Gadget-TabbedLanguages.js&amp;diff=474992&amp;oldid=prev"/>
		<updated>2025-09-17T01:06:23Z</updated>

		<summary type="html">&lt;p&gt;Polyfill deprecated function newNode&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// ******** imported from [[MediaWiki:Gadget-LegacyScriptsNewNode.js]] ********&lt;br /&gt;
var newNode = window.newNode = function newNode(tagname) {&lt;br /&gt;
	var node = document.createElement(tagname);&lt;br /&gt;
&lt;br /&gt;
	for (var i = 1; i &amp;lt; arguments.length; i++) {&lt;br /&gt;
		var argument = arguments[i];&lt;br /&gt;
		if (typeof argument == &amp;#039;string&amp;#039;) { //Text&lt;br /&gt;
			node.appendChild(document.createTextNode(argument));&lt;br /&gt;
		} else if (typeof argument == &amp;#039;object&amp;#039;) {&lt;br /&gt;
			if (argument instanceof Node) { // If it is a DOM Node&lt;br /&gt;
				node.appendChild(argument);&lt;br /&gt;
			} else { // Attributes (hopefully)&lt;br /&gt;
				for (var j in argument) {&lt;br /&gt;
					if (j === &amp;#039;class&amp;#039;) { // Classname different because...&lt;br /&gt;
						node.className = argument[j];&lt;br /&gt;
					} else if (j == &amp;#039;style&amp;#039;) { // Style is special&lt;br /&gt;
						node.style.cssText = argument[j];&lt;br /&gt;
					} else if (typeof argument[j] == &amp;#039;function&amp;#039;) { // Basic event handlers&lt;br /&gt;
						node.addEventListener(j, argument[j], false);&lt;br /&gt;
					} else {&lt;br /&gt;
						node.setAttribute(j, argument[j]); //Normal attributes&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
	return node;&lt;br /&gt;
};&lt;br /&gt;
// ****************************************************************************&lt;br /&gt;
&lt;br /&gt;
(function ( $ ) {&lt;br /&gt;
// {{documentation}}&lt;br /&gt;
// This is a (very) modified version of User:Atelaes/TabbedLanguages.js.&lt;br /&gt;
// Tabbed languages with tabs on the side.&lt;br /&gt;
// Tabs design by [[User:Jorm (WMF)]]&lt;br /&gt;
&lt;br /&gt;
/*jshint maxerr:1048576, strict:true, undef:true, latedef:true, es5:true */&lt;br /&gt;
/*global mw, jQuery, importScript, importScriptURI, $, ObjectStorage */&lt;br /&gt;
&lt;br /&gt;
if (($.cookie(&amp;#039;disable-tabbed-languages&amp;#039;) !== null) || (location.search.indexOf(&amp;quot;tabbedlanguages=off&amp;quot;) !== -1))&lt;br /&gt;
	return;&lt;br /&gt;
if (!((mw.config.get(&amp;#039;wgNamespaceNumber&amp;#039;) === 0) || (mw.config.get(&amp;#039;wgPageName&amp;#039;) === &amp;quot;Wiktionary:Sandbox&amp;quot;)))&lt;br /&gt;
	return;&lt;br /&gt;
&lt;br /&gt;
var bodyContent = $(&amp;quot;.mw-content-ltr .mw-parser-output&amp;quot;)[0], // NOT #bodyContent&lt;br /&gt;
	languageLinks, ttr,&lt;br /&gt;
	languageButtons,&lt;br /&gt;
	caption,&lt;br /&gt;
	bodyContentFragment,&lt;br /&gt;
	complete = false,&lt;br /&gt;
	MO = window.MutationObserver || window.WebKitMutationObserver,&lt;br /&gt;
	observerStyleSheet;&lt;br /&gt;
&lt;br /&gt;
// Setting up the tabs has not yet been started.&lt;br /&gt;
function makeTabsfromScratch() {&lt;br /&gt;
	// Set up the variables...&lt;br /&gt;
	window.tabbedLanguages = [];&lt;br /&gt;
	window.languageContainers = [];&lt;br /&gt;
	window.currentLanguageTab = 0;&lt;br /&gt;
	window.languageHeaderEditButtons = [];&lt;br /&gt;
	languageButtons = [];&lt;br /&gt;
	window.tabstable = newNode(&amp;#039;table&amp;#039;, {id: &amp;#039;tabstable&amp;#039;},&lt;br /&gt;
		newNode(&amp;#039;tbody&amp;#039;,&lt;br /&gt;
			ttr = newNode(&amp;#039;tr&amp;#039;,&lt;br /&gt;
				newNode(&amp;#039;td&amp;#039;, {&amp;#039;style&amp;#039;: &amp;#039;padding-top:0px;vertical-align:top;&amp;#039;},&lt;br /&gt;
					newNode(&amp;#039;table&amp;#039;, {&amp;#039;style&amp;#039;: &amp;#039;margin-top: -2px;&amp;#039;},&lt;br /&gt;
						languageLinks = newNode(&amp;#039;tbody&amp;#039;, {id: &amp;#039;languageLinks&amp;#039;}))))));&lt;br /&gt;
	window.loadremovecatbuttons = false;&lt;br /&gt;
&lt;br /&gt;
	bodyContentFragment = document.createDocumentFragment();&lt;br /&gt;
&lt;br /&gt;
	// If bodyContent is complete, do it all at once.&lt;br /&gt;
	// Otherwise, only start working, but don&amp;#039;t attempt the whole thing.&lt;br /&gt;
	// Use catlinks+*, as gEBCN isn&amp;#039;t always available.&lt;br /&gt;
	var catlinks = document.getElementById( &amp;quot;catlinks&amp;quot; );&lt;br /&gt;
	if( bodyContent &amp;amp;&amp;amp; catlinks &amp;amp;&amp;amp; catlinks.nextSibling ) {&lt;br /&gt;
		allAtOnce();&lt;br /&gt;
	} else {&lt;br /&gt;
		createObserver();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function allAtOnce() {&lt;br /&gt;
	var languageContainer, toc = document.getElementById( &amp;quot;toc&amp;quot; );&lt;br /&gt;
	currentLanguageTab = 0;&lt;br /&gt;
	while ( bodyContent.firstChild ) {&lt;br /&gt;
		if ( bodyContent.firstChild.nodeName === &amp;quot;SECTION&amp;quot; ) {&lt;br /&gt;
			// Unwrap and remove top-level &amp;lt;section&amp;gt; tags in Parsoid content &lt;br /&gt;
			// https://www.mediawiki.org/wiki/Specs/HTML/2.8.0#Headings_and_Sections&lt;br /&gt;
			while ( bodyContent.firstChild.firstChild ) {&lt;br /&gt;
				bodyContentFragment.appendChild( bodyContent.firstChild.firstChild );&lt;br /&gt;
			}&lt;br /&gt;
			bodyContent.removeChild( bodyContent.firstChild );&lt;br /&gt;
		} else {&lt;br /&gt;
			bodyContentFragment.appendChild( bodyContent.firstChild );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	try {&lt;br /&gt;
		for( var child = bodyContentFragment.firstChild; child &amp;amp;&amp;amp; !isHeader( child ); ){&lt;br /&gt;
			child = child.nextSibling;&lt;br /&gt;
		}&lt;br /&gt;
		for (&lt;br /&gt;
			child = child &amp;amp;&amp;amp; bodyContentFragment.insertBefore(tabstable, child).nextSibling;&lt;br /&gt;
			child &amp;amp;&amp;amp; child.className !== &amp;#039;printfooter&amp;#039; &amp;amp;&amp;amp; child.className !== &amp;#039;catlinks&amp;#039;;&lt;br /&gt;
			child = child.nextSibling&lt;br /&gt;
		) {&lt;br /&gt;
			if ( isHeader( child ) ) {&lt;br /&gt;
				var langspan = getHeaderContent( child ),&lt;br /&gt;
					language = langspan &amp;amp;&amp;amp; ( langspan.innerText || langspan.textContent );&lt;br /&gt;
&lt;br /&gt;
				if ( language ) {&lt;br /&gt;
					newTab( tabbedLanguages.push(language) - 1, language );&lt;br /&gt;
					processEditButton( child.getElementsByClassName(&amp;#039;mw-editsection&amp;#039;)[ 0 ] );&lt;br /&gt;
					// should probably be set from a return value of above.&lt;br /&gt;
					languageContainer = languageContainers[ languageContainers.length - 1 ];&lt;br /&gt;
&lt;br /&gt;
					bodyContentFragment.removeChild( child );&lt;br /&gt;
&lt;br /&gt;
					child = tabstable;&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				if ( child.nodeName !== &amp;quot;HR&amp;quot; ) {&lt;br /&gt;
					languageContainer.insertBefore(child, languageContainer.lastChild);&lt;br /&gt;
				} else {&lt;br /&gt;
					bodyContentFragment.removeChild(child);&lt;br /&gt;
				}&lt;br /&gt;
				child = tabstable;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if( tabbedLanguages.length ) {&lt;br /&gt;
			if( toc ) {&lt;br /&gt;
				toc.parentNode.removeChild( toc );&lt;br /&gt;
			}&lt;br /&gt;
			sortCats();&lt;br /&gt;
			bodyContent.appendChild( bodyContentFragment );&lt;br /&gt;
			setUpHashChange()();&lt;br /&gt;
			if( location.hash === &amp;#039;&amp;#039; ) {&lt;br /&gt;
				location.replace( &amp;quot;#&amp;quot; + tabbedLanguages[ currentLanguageTab ] );&lt;br /&gt;
			}&lt;br /&gt;
			complete = true;&lt;br /&gt;
		} else {&lt;br /&gt;
			bodyContent.appendChild( bodyContentFragment );&lt;br /&gt;
		}&lt;br /&gt;
	} catch( e ) {&lt;br /&gt;
		window.console &amp;amp;&amp;amp; console.error( e );&lt;br /&gt;
		bodyContent.appendChild( bodyContentFragment );&lt;br /&gt;
		complete || setUpHashChange()();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Set up a MutationObserver to detect when new elements are loaded.&lt;br /&gt;
function createObserver() {&lt;br /&gt;
&lt;br /&gt;
	// If .ready happens early (or MO and animstart aren&amp;#039;t supported), go ahead.&lt;br /&gt;
	// TODO the following code was commented out 2023-11-09 as $.isReady was suddenly&lt;br /&gt;
	// always evaluating to true, meaning that TabbedLanguages would not load.&lt;br /&gt;
	//if( $.isReady ) {&lt;br /&gt;
	//	return; // ??? How did we get $.isReady if bC or catlinks aren&amp;#039;t loaded?&lt;br /&gt;
	//} else {&lt;br /&gt;
		$( document ).ready( function () {&lt;br /&gt;
			if( tabbedLanguages.length === 0 ) {&lt;br /&gt;
				removeObserver();&lt;br /&gt;
				if( !bodyContent ) {&lt;br /&gt;
					bodyContent = $(&amp;quot;.mw-content-ltr&amp;quot;)[0];&lt;br /&gt;
				}&lt;br /&gt;
				if( bodyContent ) {&lt;br /&gt;
					allAtOnce();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
	//}&lt;br /&gt;
&lt;br /&gt;
	if( !document.getElementsByClassName ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if( !MO ) {&lt;br /&gt;
		var supportsAnimations = false;&lt;br /&gt;
		// Check if we can use animations as a fallback. If not, abort.&lt;br /&gt;
		// Basically yoinked from Modernizr.&lt;br /&gt;
		$.each(&lt;br /&gt;
			&amp;quot;animationName WebkitAnimationName MozAnimationName OAnimationName msAnimationName&amp;quot;.split(&amp;quot; &amp;quot;),&lt;br /&gt;
			function(a, b){&lt;br /&gt;
				// Do documentElements even always have .style? If not, this&amp;#039;ll need fixing.&lt;br /&gt;
				if( document.documentElement.style[ b ] !== undefined ) {&lt;br /&gt;
					supportsAnimations = true;&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		);&lt;br /&gt;
		if( supportsAnimations === false ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var foundHeader = false,&lt;br /&gt;
		toc, recentChild,&lt;br /&gt;
		timer = false, // It&amp;#039;s the setTimeout value, or false otherwise.&lt;br /&gt;
		recentHeader = -1,&lt;br /&gt;
		checkTab, tabFound = false,&lt;br /&gt;
		// If anyone on this project even considers making a random element&lt;br /&gt;
		// on a page have the class &amp;quot;visualClear&amp;quot;...&lt;br /&gt;
		visualClear = document.getElementsByClassName( &amp;quot;visualClear&amp;quot; ),&lt;br /&gt;
		languageContainer,&lt;br /&gt;
		observer;&lt;br /&gt;
&lt;br /&gt;
	// TODO: Deal with the little jumping elements below the tabstable.&lt;br /&gt;
	// ...How?&lt;br /&gt;
&lt;br /&gt;
	function elemFound() {&lt;br /&gt;
		if( timer === false ) {&lt;br /&gt;
			timer = setTimeout( function() {&lt;br /&gt;
				reactToObserver();&lt;br /&gt;
				timer = false;&lt;br /&gt;
			}, 1);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if( MO ) {&lt;br /&gt;
		observer = new MO( elemFound );&lt;br /&gt;
		observer.observe( document, { childList: true, subtree: true } );&lt;br /&gt;
	} else {&lt;br /&gt;
		// Fallback for browsers that don&amp;#039;t support MO, but do support animations:&lt;br /&gt;
		// IE10, FF5-13, Chrome 17&amp;lt;, Safari 4-5.1, Opera 12-12.1&lt;br /&gt;
		// Set up a stylesheet that uses animations/keyframes to allow&lt;br /&gt;
		// animationStart to see each time a new node loads onto the bodyContent.&lt;br /&gt;
&lt;br /&gt;
		observerStyleSheet =&lt;br /&gt;
			document.getElementsByTagName( &amp;#039;head&amp;#039; )[0].appendChild(&lt;br /&gt;
				document.createElement( &amp;quot;style&amp;quot; )&lt;br /&gt;
			);&lt;br /&gt;
		var oSSText = &amp;quot;@/@-moz-/@-webkit-/@-ms-/@-o-/&amp;quot;.split(&amp;quot;/&amp;quot;)&lt;br /&gt;
			.join(&amp;quot;keyframes nodeInserted{&amp;quot; +&lt;br /&gt;
				&amp;quot;from{outline-color:#fff;}&amp;quot; +&lt;br /&gt;
				&amp;quot;to{outline-color:#000;}&amp;quot; +&lt;br /&gt;
			&amp;quot;}\n&amp;quot;) +&lt;br /&gt;
		&amp;quot;.mw-content-ltr&amp;gt;*,.mw-content-ltr+*,.visualClear{&amp;quot; +&lt;br /&gt;
			// TODO: Fix duplication here.&lt;br /&gt;
			&amp;quot;/-moz-/-webkit-/-ms-/-o-/&amp;quot;.split(&amp;quot;/&amp;quot;).join(&amp;quot;animation-duration:0.01s;&amp;quot;) +&lt;br /&gt;
			&amp;quot;/-moz-/-webkit-/-ms-/-o-/&amp;quot;.split(&amp;quot;/&amp;quot;).join(&amp;quot;animation-name:nodeInserted;&amp;quot;) +&lt;br /&gt;
		&amp;quot;}&amp;quot;;&lt;br /&gt;
		// Pretty much copied from mw.util.&lt;br /&gt;
		// Don&amp;#039;t have time to wait until it would ordinarily load.&lt;br /&gt;
		if( observerStyleSheet.styleSheet ) {&lt;br /&gt;
			observerStyleSheet.styleSheet.cssText = oSSText;&lt;br /&gt;
		} else {&lt;br /&gt;
			observerStyleSheet.appendChild( document.createTextNode( oSSText ) );&lt;br /&gt;
		}&lt;br /&gt;
		observerStyleSheet = observerStyleSheet.sheet ||&lt;br /&gt;
			observerStyleSheet.styleSheet ||&lt;br /&gt;
			observerStyleSheet;&lt;br /&gt;
		document.addEventListener(&amp;#039;animationstart&amp;#039;, elemFound, false);&lt;br /&gt;
		document.addEventListener(&amp;#039;MSAnimationStart&amp;#039;, elemFound, false);&lt;br /&gt;
		document.addEventListener(&amp;#039;webkitAnimationStart&amp;#039;, elemFound, false);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function reactToObserver() {&lt;br /&gt;
		if( complete ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// TODO: Surround main areas in try{} so that if it breaks, at least&lt;br /&gt;
		// the content gets dumped back into visibility.&lt;br /&gt;
&lt;br /&gt;
		// First: What part are we up to?&lt;br /&gt;
		if( !foundHeader ) {&lt;br /&gt;
			// search for header or toc&lt;br /&gt;
			if( !recentChild ) { // Just starting, apparently.&lt;br /&gt;
				if( !bodyContent ) {&lt;br /&gt;
					bodyContent = $(&amp;quot;.mw-content-ltr&amp;quot;)[0];&lt;br /&gt;
					if( !bodyContent ) {&lt;br /&gt;
						// bC hasn&amp;#039;t loaded yet. Nothing to do here.&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				// Check if we can do the whole thing in one go.&lt;br /&gt;
				if( visualClear.length ) {&lt;br /&gt;
					removeObserver();&lt;br /&gt;
					allAtOnce();&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				recentChild = bodyContent.firstChild;&lt;br /&gt;
				if( !recentChild ) {&lt;br /&gt;
					return; // Somehow got activated between bodyContent load&lt;br /&gt;
					// and bodyContent&amp;#039;s content&amp;#039;s load.&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for( ; !isHeader( recentChild ) &amp;amp;&amp;amp; recentChild.nextSibling; ) {&lt;br /&gt;
				recentChild = recentChild.nextSibling;&lt;br /&gt;
			}&lt;br /&gt;
			if( isHeader( recentChild ) ) { // should simplify check. Maybe !recentChild.nextSibling?&lt;br /&gt;
				// We have our first header.&lt;br /&gt;
				foundHeader = true;&lt;br /&gt;
&lt;br /&gt;
				checkTab = setUpHashChange();&lt;br /&gt;
&lt;br /&gt;
				// Default to the first tab.&lt;br /&gt;
				currentLanguageTab = 0;&lt;br /&gt;
&lt;br /&gt;
				toc = document.getElementById(&amp;#039;toc&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
				if ( toc ) {&lt;br /&gt;
					if ( toc.nextSibling ) {&lt;br /&gt;
						// And we have a usable ToC. Makes things much easier.&lt;br /&gt;
						// Analyze the ToC. We&amp;#039;ll be using it to determine what&lt;br /&gt;
						// the tabs are going to be.&lt;br /&gt;
						$( &amp;quot;.toclevel-1 &amp;gt; a &amp;gt; .toctext&amp;quot; ).each( function() {&lt;br /&gt;
							var language = $( this ).text();&lt;br /&gt;
							tabbedLanguages.push( language );&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						// Build all the tabs.&lt;br /&gt;
						$( tabbedLanguages ).each( newTab );&lt;br /&gt;
&lt;br /&gt;
						toc.parentNode.removeChild( toc );&lt;br /&gt;
&lt;br /&gt;
						// Afterwards, we&amp;#039;ll check if the right section&lt;br /&gt;
						// is already available.&lt;br /&gt;
					} else {&lt;br /&gt;
						// Potential panic situation: Evil formatting places&lt;br /&gt;
						// ToC *after* the first header, so it&amp;#039;s actually&lt;br /&gt;
						// *partly* loaded at this point, with no  nextSibling.&lt;br /&gt;
						// (Alternatively, someone put it alone in a box.) CSS&lt;br /&gt;
						// builds it up as a huge tabbing block, but we can&amp;#039;t&lt;br /&gt;
						// remove it here. Oy.&lt;br /&gt;
						// &amp;quot;Solution&amp;quot;:&lt;br /&gt;
						// Temporarily hide the ToC until ready() fires, then&lt;br /&gt;
						// remove it. I&amp;#039;m not removing it right away, as I have&lt;br /&gt;
						// no idea what doom might occur if something like this&lt;br /&gt;
						// is removed while stuff is being loaded into it.&lt;br /&gt;
						toc.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						( function ( toc ) {&lt;br /&gt;
							$( function() {&lt;br /&gt;
								if( toc.parentNode ) {&lt;br /&gt;
									toc.parentNode.removeChild( toc );&lt;br /&gt;
								}&lt;br /&gt;
							});&lt;br /&gt;
						})( toc );&lt;br /&gt;
						toc = undefined;&lt;br /&gt;
						window.console &amp;amp;&amp;amp; console.error( &amp;quot;TL notice: &amp;quot; +&lt;br /&gt;
							&amp;quot;Malformed entry. ToC either appears after &amp;quot; +&lt;br /&gt;
							&amp;quot;headers, or is placed in a box. Mind fixing &amp;quot; +&lt;br /&gt;
							&amp;quot;it or alerting me? Thanks. -- YR&amp;quot; );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				languageContainer = languageContainers[ 0 ];&lt;br /&gt;
&lt;br /&gt;
				// Edit buttons.&lt;br /&gt;
				processEditButton(&lt;br /&gt;
					recentChild.getElementsByClassName( &amp;quot;mw-editsection&amp;quot; )[ 0 ]&lt;br /&gt;
				);&lt;br /&gt;
&lt;br /&gt;
				// Either way, start displaying the tabs right.&lt;br /&gt;
				bodyContent.insertBefore( tabstable, recentChild );&lt;br /&gt;
&lt;br /&gt;
				if( toc ) {&lt;br /&gt;
					tabFound = checkTab();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if( foundHeader ) {&lt;br /&gt;
			// Note that there may or may not be a ToC available...&lt;br /&gt;
			// Should this be reworked so that the toc check is inside the loop?&lt;br /&gt;
			if( recentChild.nextSibling ) {&lt;br /&gt;
				// I hope I&amp;#039;m not going to regret leaving out a recentChild &amp;amp;&amp;amp; condition here...&lt;br /&gt;
				for( var nextChild; recentChild.nextSibling; ) {&lt;br /&gt;
					nextChild = recentChild.nextSibling;&lt;br /&gt;
					if( isHeader( recentChild ) ) {&lt;br /&gt;
						var langspan = getHeaderContent( recentChild );&lt;br /&gt;
						var editspan = recentChild.getElementsByClassName(&amp;#039;mw-editsection&amp;#039;)[ 0 ];&lt;br /&gt;
						if( recentHeader &amp;gt;= 0 ) {&lt;br /&gt;
							languageContainer.insertBefore( bodyContentFragment, languageContainer.lastChild );&lt;br /&gt;
						}&lt;br /&gt;
						recentHeader++;&lt;br /&gt;
&lt;br /&gt;
						var language = ( language = langspan ).innerText || language.textContent;&lt;br /&gt;
&lt;br /&gt;
						// Make sure it actually matches, when necessary.&lt;br /&gt;
						if( toc &amp;amp;&amp;amp; language !== tabbedLanguages[ recentHeader ]) {&lt;br /&gt;
							// PANIC!!!&lt;br /&gt;
							// Okay, maybe don&amp;#039;t panic. TL has encountered&lt;br /&gt;
							// a header that doesn&amp;#039;t match the ToC&amp;#039;s&lt;br /&gt;
							// description of the page. Possibilities&lt;br /&gt;
							// include an h1 on the page, a fake header&lt;br /&gt;
							// around somewhere, or some other malformed&lt;br /&gt;
							// kind of header. This really isn&amp;#039;t supposed&lt;br /&gt;
							// to happen ever.&lt;br /&gt;
&lt;br /&gt;
							// Response: Clear everything after this point,&lt;br /&gt;
							// and from there act as though the ToC never&lt;br /&gt;
							// existed.&lt;br /&gt;
							if( recentHeader &amp;gt; 0 ) {&lt;br /&gt;
								toggleLanguageTabs( tabbedLanguages[ 0 ] );&lt;br /&gt;
							} else {&lt;br /&gt;
								currentLanguageTab = 0;&lt;br /&gt;
							}&lt;br /&gt;
							while( tabbedLanguages.length &amp;gt; recentHeader ) {&lt;br /&gt;
								tabbedLanguages.pop();&lt;br /&gt;
								ttr.removeChild(&lt;br /&gt;
									languageContainers.pop()&lt;br /&gt;
								);&lt;br /&gt;
								languageLinks.removeChild(&lt;br /&gt;
									languageButtons.pop().parentNode&lt;br /&gt;
								);&lt;br /&gt;
							}&lt;br /&gt;
							toc = undefined; // Never. Existed.&lt;br /&gt;
							tabFound = false;&lt;br /&gt;
&lt;br /&gt;
							window.console &amp;amp;&amp;amp; console.error( &amp;quot;TL notice: &amp;quot; +&lt;br /&gt;
								&amp;quot;Malformed entry. ToC does not match &amp;quot; +&lt;br /&gt;
								&amp;quot;headers. Possibly a misplaced H1, fake &amp;quot; +&lt;br /&gt;
								&amp;quot;header, or header with incorrect &amp;quot; +&lt;br /&gt;
								&amp;quot;contents. Mind fixing it or &amp;quot; +&lt;br /&gt;
								&amp;quot;alerting me? Thanks. -- YR &amp;quot;&lt;br /&gt;
							);&lt;br /&gt;
						}&lt;br /&gt;
						if( !toc ) {&lt;br /&gt;
							tabbedLanguages.push( language );&lt;br /&gt;
							newTab( recentHeader, language );&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						// Check to see if the target tab is found.&lt;br /&gt;
						// TODO: Need a better system of knowing when to check:&lt;br /&gt;
						//   If it&amp;#039;s found, stop checking.&lt;br /&gt;
						//   Whether or not we have a ToC, checking can be necessary.&lt;br /&gt;
						//   If we do have a ToC, but no hash, we don&amp;#039;t check, right?&lt;br /&gt;
						//   Put another way:&lt;br /&gt;
						//     No hash? W/ ToC, don&amp;#039;t check. W/o ToC, only check when new headers come in.&lt;br /&gt;
						//     Hash? Depends.&lt;br /&gt;
						//       W/ ToC: Technically, target could come in at any non-header element... ???&lt;br /&gt;
						//       W/o ToC: Could be whenever. Target header coming in is rather likely, in fact. Oy.&lt;br /&gt;
						//       Either way: If the target, whether header or random element, is found, stop looking.&lt;br /&gt;
						//     Does delaying the tab switch to a element target until full load matter? Not sure.&lt;br /&gt;
						//&lt;br /&gt;
						//	Plan B: Regardless of ToC presence, only&lt;br /&gt;
						//	check for potential target elems&lt;br /&gt;
						//	at each new header, unless target is found.&lt;br /&gt;
						if( recentHeader &amp;gt; 0 &amp;amp;&amp;amp; tabFound === false ) {&lt;br /&gt;
							tabFound = checkTab();&lt;br /&gt;
						}&lt;br /&gt;
						languageContainer = languageContainers[ recentHeader ];&lt;br /&gt;
						if( recentHeader &amp;gt; 0 ) { // I have too many of these checks...&lt;br /&gt;
							// Don&amp;#039;t duplicate earlier pEB for first header.&lt;br /&gt;
							processEditButton( editspan );&lt;br /&gt;
						}&lt;br /&gt;
						// All done. Clear.&lt;br /&gt;
						bodyContent.removeChild( recentChild );&lt;br /&gt;
					} else {&lt;br /&gt;
						if( recentChild.nodeName === &amp;quot;HR&amp;quot; ) {&lt;br /&gt;
							// Kill unnecessary bars.&lt;br /&gt;
							bodyContent.removeChild( recentChild );&lt;br /&gt;
						} else {&lt;br /&gt;
							// Regular content. Prepare for dumping into the&lt;br /&gt;
							// latest tab.&lt;br /&gt;
							bodyContentFragment.appendChild( recentChild );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					recentChild = nextChild;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			/*&lt;br /&gt;
			// If we&amp;#039;re all done, finish up.&lt;br /&gt;
			// How to tell?&lt;br /&gt;
			// Option one: Repeatedly check for nextSibling.&lt;br /&gt;
			// 	 - Won&amp;#039;t work. bodyContent doesn&amp;#039;t always have a nS at the end.&lt;br /&gt;
			//   - Currently in use only for dealing with the last elem. (Uses O2 as fallback.)&lt;br /&gt;
			// Option two: Set up getElemsByClassName, and poll for length.&lt;br /&gt;
			//	 - presumably visualClear. This would probably be pretty heavy.&lt;br /&gt;
			//   - Currently in use.&lt;br /&gt;
			// Option three: Use $.ready.&lt;br /&gt;
			//	 - Potentially introduces substantial delay...&lt;br /&gt;
			// Option four: In the listener, check for classnames each time.&lt;br /&gt;
			//	 - Every time there&amp;#039;s a new node? Lots of processing.&lt;br /&gt;
			// Option five: ...&lt;br /&gt;
			*/&lt;br /&gt;
			if( bodyContent.nextSibling &amp;amp;&amp;amp; bodyContent.lastChild === recentChild ) { // are we done? ...&lt;br /&gt;
				// bodyContent.nextSibling doesn&amp;#039;t always exist, but if it&lt;br /&gt;
				// does, get a head start on the stuff that can be done already.&lt;br /&gt;
				bodyContentFragment.appendChild( bodyContent.lastChild );&lt;br /&gt;
				/*&lt;br /&gt;
				// Problem: recentChild is now inside the languageContainer,&lt;br /&gt;
				// and it&amp;#039;s possible that reactToObserver will be called again&lt;br /&gt;
				// before the post-visualClear stuff runs.&lt;br /&gt;
				// Option one: recentChild = tabstable;&lt;br /&gt;
				// - Nope. That would mean bodyContent.lastChild = recentChild again&lt;br /&gt;
				// Option two: recentChild = false;&lt;br /&gt;
				// - Nope. The check at the top would cause us to start over again.&lt;br /&gt;
				// Blargh. This is an awful solution that probably violates every...&lt;br /&gt;
				*/&lt;br /&gt;
				recentChild = 1;&lt;br /&gt;
				// &amp;quot;1&amp;quot; is hereby the indicator that we&amp;#039;re not doing anything with&lt;br /&gt;
				// this particular variable, okay?&lt;br /&gt;
				// I&amp;#039;ll try to make this nicer later.&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// Dump collected elems into most recent languageContainer.&lt;br /&gt;
			if( bodyContentFragment.firstChild ) { // Exact duplicate of above code. TODO: Fix.&lt;br /&gt;
				languageContainer.insertBefore( bodyContentFragment, languageContainer.lastChild );&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if( visualClear.length ) {&lt;br /&gt;
				complete = true;&lt;br /&gt;
				if( bodyContent.lastChild === recentChild ) {&lt;br /&gt;
					// bC.nS didn&amp;#039;t exist. Move the last one left now.&lt;br /&gt;
					languageContainer.insertBefore( bodyContent.lastChild, languageContainer.lastChild );&lt;br /&gt;
				}&lt;br /&gt;
				removeObserver();&lt;br /&gt;
				sortCats();&lt;br /&gt;
				if( tabFound !== true ) {&lt;br /&gt;
					checkTab();&lt;br /&gt;
					if( location.hash === &amp;#039;&amp;#039; ) {&lt;br /&gt;
						location.replace( &amp;quot;#&amp;quot; + tabbedLanguages[currentLanguageTab] );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	function removeObserver() {&lt;br /&gt;
		if( observer ) {&lt;br /&gt;
			observer.disconnect();&lt;br /&gt;
		} else if( observerStyleSheet ) {&lt;br /&gt;
			document.removeEventListener(&amp;#039;animationstart&amp;#039;, elemFound, false);&lt;br /&gt;
			document.removeEventListener(&amp;#039;MSAnimationStart&amp;#039;, elemFound, false);&lt;br /&gt;
			document.removeEventListener(&amp;#039;webkitAnimationStart&amp;#039;, elemFound, false);&lt;br /&gt;
			observerStyleSheet.disabled = true;&lt;br /&gt;
		}&lt;br /&gt;
		if( timer !== false ) {&lt;br /&gt;
			clearTimeout( timer );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function isHeader( elem ) {&lt;br /&gt;
	// Handle two versions of the markup: https://www.mediawiki.org/wiki/Heading_HTML_changes&lt;br /&gt;
	return elem &amp;amp;&amp;amp; elem.nodeType === Node.ELEMENT_NODE &amp;amp;&amp;amp; (&lt;br /&gt;
		elem.nodeName === &amp;quot;H2&amp;quot; &amp;amp;&amp;amp; elem.getElementsByClassName( &amp;quot;mw-headline&amp;quot; ).length !== 0 ||&lt;br /&gt;
		elem.classList.contains( &amp;quot;mw-heading2&amp;quot; ) &amp;amp;&amp;amp; elem.getElementsByTagName( &amp;quot;H2&amp;quot; ).length !== 0&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function getHeaderContent( elem ) {&lt;br /&gt;
	// Handle two versions of the markup: https://www.mediawiki.org/wiki/Heading_HTML_changes&lt;br /&gt;
	return elem.nodeName === &amp;quot;H2&amp;quot; ?&lt;br /&gt;
		elem.getElementsByClassName( &amp;quot;mw-headline&amp;quot; )[0] :&lt;br /&gt;
		elem.getElementsByTagName( &amp;quot;H2&amp;quot; )[0];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function newTab( index, language ) {&lt;br /&gt;
	var active = index === currentLanguageTab;&lt;br /&gt;
	var languageContainer = ttr.appendChild( newNode(&amp;#039;td&amp;#039;, {&lt;br /&gt;
		&amp;#039;class&amp;#039;: &amp;#039;languageContainer&amp;#039;,&lt;br /&gt;
		&amp;#039;id&amp;#039;: language + &amp;#039;container&amp;#039;&lt;br /&gt;
	}, active ? undefined : { &amp;#039;style&amp;#039; : &amp;#039;display:none;&amp;#039; } ));&lt;br /&gt;
	languageContainers.push( languageContainer );&lt;br /&gt;
	newCategoryBox( languageContainer, language );&lt;br /&gt;
	// lB contains .(un)?selectedTab nodes&lt;br /&gt;
	languageButtons.push(&lt;br /&gt;
		languageLinks.appendChild( newNode(&amp;#039;tr&amp;#039;, newNode(&amp;#039;td&amp;#039;, {&lt;br /&gt;
			&amp;#039;class&amp;#039;: ( active ? &amp;#039;&amp;#039; : &amp;#039;un&amp;#039; ) + &amp;#039;selectedTab&amp;#039;&lt;br /&gt;
		}, newNode(&amp;#039;a&amp;#039;, language, {&lt;br /&gt;
			// Note: &amp;#039; + language&amp;#039; makes this inconsistent with the ordinary links&lt;br /&gt;
			// themselves, which have the language name encoded. Issue?&lt;br /&gt;
			// Keep in mind that the parser itself actually corrects for this,&lt;br /&gt;
			// changing #!Xóõ links to the proper #.C7.83X.C3.B3.C3.B5 links.&lt;br /&gt;
			// Probably nothing to worry about.&lt;br /&gt;
			&amp;#039;href&amp;#039;: location.pathname + location.search + &amp;#039;#&amp;#039; + language.replace(/ /g, &amp;#039;_&amp;#039;)&lt;br /&gt;
		}), &amp;#039; &amp;#039;))).firstChild&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function newCategoryBox( container, name ) {&lt;br /&gt;
	// Put a container in each for categories.&lt;br /&gt;
	return container.appendChild( newNode(&amp;#039;div&amp;#039;, name + &amp;#039; categories: &amp;#039;, newNode(&amp;#039;ul&amp;#039;), {&lt;br /&gt;
		&amp;#039;class&amp;#039;: &amp;#039;catlinks&amp;#039;,&lt;br /&gt;
		&amp;#039;id&amp;#039;: &amp;#039;catlinks&amp;#039;&lt;br /&gt;
	}));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function processEditButton( button ) {&lt;br /&gt;
	if( button ) {&lt;br /&gt;
		// Yes, theoretically if you have some fake H2s the edit buttons will&lt;br /&gt;
		// be misplaced. Yet another TODO...&lt;br /&gt;
		var len = languageHeaderEditButtons.push( button );&lt;br /&gt;
		if( len === 1 ) {&lt;br /&gt;
			caption = document.createElement(&amp;#039;caption&amp;#039;);&lt;br /&gt;
			tabstable.insertBefore( caption, tabstable.firstChild );&lt;br /&gt;
		}&lt;br /&gt;
		button.className += &amp;quot; editlangsection&amp;quot;;&lt;br /&gt;
		// use a argument or variable ( from .push? ) instead of .length?&lt;br /&gt;
		if( len - 1 === currentLanguageTab ) {&lt;br /&gt;
			caption.firstChild &amp;amp;&amp;amp; caption.removeChild( caption.firstChild );&lt;br /&gt;
			caption.appendChild( button );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Sets up the hash toggle system.&lt;br /&gt;
// Returns the checkTab() function, which returns true if&lt;br /&gt;
// we found whatever it was.&lt;br /&gt;
function setUpHashChange() {&lt;br /&gt;
&lt;br /&gt;
	// Important Note: The decodeURI mess is a real mess.&lt;br /&gt;
	// #.C7.83X.C3.B3.C3.B5 should go to tab &amp;quot;!Xóõ&amp;quot;, with&lt;br /&gt;
	// the id &amp;quot;!Xóõcontainer&amp;quot; (no encoding). Urgh.&lt;br /&gt;
	// Also, &amp;quot;#Old_English&amp;quot; needs to go to decoded &amp;quot;Old English&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
	// Remember to .substr( 1 ) before passing here.&lt;br /&gt;
	function decodeHash( hash ) {&lt;br /&gt;
		return decodeURI(&lt;br /&gt;
			hash&lt;br /&gt;
				.replace(/\.(?=[0-9A-F]{2})/g, &amp;#039;%&amp;#039;)&lt;br /&gt;
				.replace(/_/g, &amp;#039; &amp;#039;)&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Called by onhashchange.&lt;br /&gt;
	function hashToggleLT() {&lt;br /&gt;
		var destination = decodeHash( location.hash.substr(1) );&lt;br /&gt;
		toggleLanguageTabs( destination );&lt;br /&gt;
		tabbedLanguages[currentLanguageTab] !== destination &amp;amp;&amp;amp; resetHash();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// For updating page positioning.&lt;br /&gt;
	// Doesn&amp;#039;t activate hashchange, at least in Chrome. Not sure about others.&lt;br /&gt;
	function resetHash() {&lt;br /&gt;
		location.replace( location.hash );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Need to decide if language arg is encoded or decoded.&lt;br /&gt;
	// Will work with either for the moment. Decoded works earlier.&lt;br /&gt;
	// Currently passed as decoded by every function but itself.&lt;br /&gt;
	// The hashes are encoded, but hashToggleLT decodes them.&lt;br /&gt;
&lt;br /&gt;
	// Toggles to a different language tab.&lt;br /&gt;
	window.toggleLanguageTabs = function (language) {&lt;br /&gt;
		// Find the destination language.&lt;br /&gt;
&lt;br /&gt;
		var destinationLanguageTab = $.inArray( language, tabbedLanguages );&lt;br /&gt;
&lt;br /&gt;
		if( destinationLanguageTab === -1 ) {&lt;br /&gt;
			var decoded = decodeHash( language );&lt;br /&gt;
			if( decoded !== language ) {&lt;br /&gt;
				destinationLanguageTab = $.inArray( decoded, tabbedLanguages );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Style the right toggle button, hide the old language section and show the new one.&lt;br /&gt;
&lt;br /&gt;
		// var languageButtons = $(&amp;quot;#languageLinks .selectedTab, #languageLinks .unselectedTab&amp;quot;);&lt;br /&gt;
		if (destinationLanguageTab !== -1 ) {&lt;br /&gt;
			if( destinationLanguageTab !== currentLanguageTab ) {&lt;br /&gt;
				languageButtons[currentLanguageTab].className = &amp;#039;unselectedTab&amp;#039;;&lt;br /&gt;
				languageContainers[currentLanguageTab].style.display = &amp;#039;none&amp;#039;;&lt;br /&gt;
				currentLanguageTab = destinationLanguageTab;&lt;br /&gt;
				languageButtons[destinationLanguageTab].className = &amp;#039;selectedTab&amp;#039;;&lt;br /&gt;
				languageContainers[destinationLanguageTab].style.display = &amp;#039;&amp;#039;;&lt;br /&gt;
				if (caption) {&lt;br /&gt;
					// extra checks shouldn&amp;#039;t be necessary...&lt;br /&gt;
					caption.firstChild &amp;amp;&amp;amp; caption.removeChild(caption.firstChild);&lt;br /&gt;
					languageHeaderEditButtons[currentLanguageTab] &amp;amp;&amp;amp; caption.appendChild(languageHeaderEditButtons[currentLanguageTab]);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			// Does the hash match the id of a node in a tab?&lt;br /&gt;
			language = encodeURI( language.replace(/\ /g, &amp;#039;_&amp;#039;) );&lt;br /&gt;
			// Yes, I just possibly undid the decoding from hashToggleLT.&lt;br /&gt;
			// Worse, this might double-encode, breaking things.&lt;br /&gt;
			// Or maybe not? I think everything might be decoded before being&lt;br /&gt;
			// sent here?&lt;br /&gt;
			// I&amp;#039;ll deal with it later.&lt;br /&gt;
&lt;br /&gt;
			// Find the node, and go up the node tree until&lt;br /&gt;
			// you hit .languageContainer, or nothing.&lt;br /&gt;
			language = document.getElementById( language );&lt;br /&gt;
			for( ; language &amp;amp;&amp;amp; ( language = language.parentNode ) &amp;amp;&amp;amp;&lt;br /&gt;
				language.className !== &amp;#039;languageContainer&amp;#039;; )&lt;br /&gt;
				;&lt;br /&gt;
			// language = language &amp;amp;&amp;amp; language.parentNode.parentNode;&lt;br /&gt;
			if ( language ) {&lt;br /&gt;
				// If someone maliciously makes a languageContainer with a&lt;br /&gt;
				// non-compliant ID, boom.&lt;br /&gt;
				toggleLanguageTabs( language.id.split(&amp;#039;container&amp;#039;)[0] );&lt;br /&gt;
			}&lt;br /&gt;
			// Possible doom bug: Endless loop?&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// This function gets returned as checkTab(), btw.&lt;br /&gt;
	// For during or immediately after load: Check if we have a&lt;br /&gt;
	// good &amp;quot;starting&amp;quot; tab. Return true if we have a definitive find.&lt;br /&gt;
	function checkTab() {&lt;br /&gt;
		// If there&amp;#039;s a location hash, the window may have scrolled down before&lt;br /&gt;
		// we got a chance to reorganize everything.&lt;br /&gt;
		// If the destination was a subsection or sense id, switch to the right&lt;br /&gt;
		// tab, and rescroll.&lt;br /&gt;
		// If it was simply a language, switch to the appropriate tab, and&lt;br /&gt;
		// scroll back up.&lt;br /&gt;
		// If there&amp;#039;s no hash at all, work off the TargetedTranslations prefs.&lt;br /&gt;
		try {&lt;br /&gt;
			var hash = &amp;#039;&amp;#039;;&lt;br /&gt;
			var destination = &amp;#039;English&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
			if ( location.hash !== &amp;#039;&amp;#039; ) {&lt;br /&gt;
				hash = ( location.hash ).substr( 1 ); // does hash.substr always exist?&lt;br /&gt;
				destination = decodeHash( hash );&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// &amp;#039;k, this is still awful.&lt;br /&gt;
			if ( $.inArray( destination, tabbedLanguages ) !== -1 ) {&lt;br /&gt;
				toggleLanguageTabs( destination );&lt;br /&gt;
				window.scrollY &amp;amp;&amp;amp; window.scroll(0, 0);&lt;br /&gt;
				return true;&lt;br /&gt;
			} else if ( hash !== &amp;#039;&amp;#039; &amp;amp;&amp;amp; document.getElementById( hash ) ) {&lt;br /&gt;
				// This was going&lt;br /&gt;
				// to receive an area to search from an argument, but it turns&lt;br /&gt;
				// out that elem.getElementById doesn&amp;#039;t actually exist. Meh.&lt;br /&gt;
				toggleLanguageTabs( destination );&lt;br /&gt;
				resetHash(); // Scroll to the element. (Necessary since we&lt;br /&gt;
				// this isn&amp;#039;t running through hashToggleLT, which normally does&lt;br /&gt;
				// it in these situations.)&lt;br /&gt;
				return true;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// No hash. Work from TargetedTranslations.&lt;br /&gt;
			if (&amp;#039;localStorage&amp;#039; in window) {&lt;br /&gt;
				if (tabbedLanguages[0] !== &amp;#039;Translingual&amp;#039; &amp;amp;&amp;amp; tabbedLanguages[0] !== &amp;#039;English&amp;#039; &amp;amp;&amp;amp; localStorage.TargetedTranslations) {&lt;br /&gt;
					for (&lt;br /&gt;
						var tt_ = localStorage.TargetedTranslations.split(&amp;quot;|&amp;quot;), tt = tt_[0].split(&amp;quot;;&amp;quot;).concat(&lt;br /&gt;
							$.grep(&lt;br /&gt;
								tt_[1].replace(/[^;\/]+\//g, &amp;#039;&amp;#039;).split(&amp;quot;;&amp;quot;),&lt;br /&gt;
								function (z) {&lt;br /&gt;
									return z &amp;amp;&amp;amp; z !== &amp;quot;Latin&amp;quot; &amp;amp;&amp;amp; z !== &amp;quot;Hebrew&amp;quot; &amp;amp;&amp;amp; z !== &amp;quot;Arabic&amp;quot;;&lt;br /&gt;
								}&lt;br /&gt;
							)&lt;br /&gt;
						).concat( tt_[1].replace(/\/[^;]+/g, &amp;#039;&amp;#039;).split(&amp;quot;;&amp;quot;) ), i = 0;&lt;br /&gt;
						i &amp;lt; tt.length;&lt;br /&gt;
						i++&lt;br /&gt;
					) {&lt;br /&gt;
						if ($.inArray(tt[i], tabbedLanguages) !== -1) {&lt;br /&gt;
							toggleLanguageTabs(tabbedLanguages[$.inArray(tt[i], tabbedLanguages)]);&lt;br /&gt;
							break;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return false;&lt;br /&gt;
		} catch ( e ) {&lt;br /&gt;
			// This probably isn&amp;#039;t all that unlikely to happen. Too complicated. :(&lt;br /&gt;
			window.console &amp;amp;&amp;amp; console.error( &amp;quot;TL error: checkTab broke.&amp;quot;, e );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	if (&amp;quot;onhashchange&amp;quot; in window &amp;amp;&amp;amp; (document.documentMode === undefined || document.documentMode &amp;gt; 7)) {&lt;br /&gt;
		window.onhashchange = hashToggleLT;&lt;br /&gt;
	} else {&lt;br /&gt;
		$( bodyContent ).on(&lt;br /&gt;
			&amp;#039;click&amp;#039;,&lt;br /&gt;
			&amp;#039;a[href^=&amp;quot;&amp;#039; + location.pathname + location.search + &amp;#039;#&amp;quot;], a[href^=&amp;quot;#&amp;quot;]&amp;#039;,&lt;br /&gt;
			function () {&lt;br /&gt;
				setTimeout( hashToggleLT, 10 );&lt;br /&gt;
			}&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return checkTab;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function sortCats() {&lt;br /&gt;
	var catDiv = document.getElementById(&amp;#039;mw-normal-catlinks&amp;#039;),&lt;br /&gt;
		currentCatDiv;&lt;br /&gt;
	if (catDiv) {&lt;br /&gt;
		var cats = catDiv.getElementsByTagName(&amp;#039;li&amp;#039;),&lt;br /&gt;
			catname,&lt;br /&gt;
			langcurrent = 0,&lt;br /&gt;
			catskip = 1;&lt;br /&gt;
		do {&lt;br /&gt;
			while (cats.length &amp;gt; 0) {&lt;br /&gt;
				catname = cats[ 0 ].getElementsByTagName(&amp;#039;a&amp;#039;)[0].innerHTML;&lt;br /&gt;
				if (catname.indexOf(tabbedLanguages[langcurrent + catskip]) === 0 &amp;amp;&amp;amp;&lt;br /&gt;
					!/letter\snames$|script\scharacters$|mythology$/.test(catname)&lt;br /&gt;
				) {&lt;br /&gt;
					langcurrent += catskip;&lt;br /&gt;
					catskip = 1;&lt;br /&gt;
				}&lt;br /&gt;
				currentCatDiv = languageContainers[langcurrent].lastChild;&lt;br /&gt;
				currentCatDiv.lastChild.appendChild(cats[0]);&lt;br /&gt;
			}&lt;br /&gt;
			if (langcurrent + 1 &amp;lt; languageContainers.length - catskip) {&lt;br /&gt;
				// Didn&amp;#039;t make it to the end, which means there&amp;#039;s a section&lt;br /&gt;
				// without any categories. Dump what&amp;#039;s left back and try again.&lt;br /&gt;
				while (currentCatDiv.lastChild.firstChild) {&lt;br /&gt;
					catDiv.lastChild.appendChild(currentCatDiv.lastChild.firstChild);&lt;br /&gt;
				}&lt;br /&gt;
				catskip++;&lt;br /&gt;
			} else {&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		} while (true);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if( currentCatDiv ) {&lt;br /&gt;
		// place patrol link at the bottom of the page&lt;br /&gt;
		var pl = currentCatDiv.previousSibling; // languageContainer.lastChild.previousSibling;&lt;br /&gt;
		// Got it, the patrollink is sometimes the lagging last elem.&lt;br /&gt;
		if( pl &amp;amp;&amp;amp; pl.className === &amp;quot;patrollink&amp;quot; ) {&lt;br /&gt;
			tabstable.parentNode.appendChild(pl);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	/*&lt;br /&gt;
	// category editing buttons&lt;br /&gt;
	if (mw.config.get(&amp;#039;wgAction&amp;#039;) === &amp;quot;view&amp;quot; &amp;amp;&amp;amp; !/&amp;amp;printable=yes|&amp;amp;diff=|&amp;amp;oldid=/.test(location.search)) {&lt;br /&gt;
		for (z = 0; z &amp;lt; languageContainers.length; z++) {&lt;br /&gt;
			// TODO: import&lt;br /&gt;
			// addTabbedLanguageNewCatButton(z);&lt;br /&gt;
		}&lt;br /&gt;
		if ( window.loadremovecatbuttons === true ) {&lt;br /&gt;
			$.get(&lt;br /&gt;
				mw.config.get( &amp;#039;wgScript&amp;#039; ),&lt;br /&gt;
				{ &amp;#039;title&amp;#039; : mw.config.get(&amp;#039;wgPageName&amp;#039;), &amp;#039;action&amp;#039; : &amp;#039;raw&amp;#039; },&lt;br /&gt;
				// Note that this isn&amp;#039;t actually defined. I&amp;#039;m considering not&lt;br /&gt;
				// actually importing the function, and just dumping this section.&lt;br /&gt;
				addRemoveCatButtons&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	*/&lt;br /&gt;
	// Remove old cat box, allow display of hidden cats box.&lt;br /&gt;
	if (catDiv &amp;amp;&amp;amp; !(catDiv.nextSibling &amp;amp;&amp;amp; catDiv.nextSibling.className === &amp;quot;mw-hidden-catlinks mw-hidden-cats-user-shown&amp;quot;)) {&lt;br /&gt;
		catDiv.parentNode.style.display = &amp;#039;none&amp;#039;;&lt;br /&gt;
	} else {&lt;br /&gt;
		if (catDiv) {&lt;br /&gt;
			catDiv.style.display = &amp;#039;none&amp;#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function testStuff() {&lt;br /&gt;
	var delay = 5000, f = document.createDocumentFragment();&lt;br /&gt;
	var x = [&lt;br /&gt;
		function () {&lt;br /&gt;
			// $(&amp;quot;#toc&amp;quot;).remove();&lt;br /&gt;
			var x = document.getElementById( &amp;quot;mw-content-text&amp;quot; );&lt;br /&gt;
			while( x.nextSibling ) {&lt;br /&gt;
				f.appendChild( x.nextSibling );&lt;br /&gt;
			}&lt;br /&gt;
		}, function () {&lt;br /&gt;
			var y = $( &amp;quot;.mw-content-ltr&amp;quot; )[ 0 ];&lt;br /&gt;
			var q = document.createDocumentFragment();&lt;br /&gt;
			while( y.firstChild ) {&lt;br /&gt;
				q.appendChild( y.firstChild );&lt;br /&gt;
			}&lt;br /&gt;
			function u( i, e ) {&lt;br /&gt;
				setTimeout( function () {&lt;br /&gt;
					y.appendChild( q.firstChild );&lt;br /&gt;
				}, i / e * delay );&lt;br /&gt;
			}&lt;br /&gt;
			for( var i = 0, e = q.childNodes.length; i &amp;lt; e; i++ ) {&lt;br /&gt;
				u( i, e ); // encapsulate&lt;br /&gt;
			}&lt;br /&gt;
			makeTabsfromScratch();&lt;br /&gt;
		}, function () {&lt;br /&gt;
			function u( i, e ) {&lt;br /&gt;
				setTimeout( function () {&lt;br /&gt;
					$(&amp;quot;.mw-content-ltr&amp;quot;).after( f.firstChild );&lt;br /&gt;
				}, i / e * delay / 5 );&lt;br /&gt;
			}&lt;br /&gt;
			for( var i = 0, e = f.childNodes.length; i &amp;lt; e; i++ ) {&lt;br /&gt;
				u( i, e ); // encapsulate&lt;br /&gt;
			}&lt;br /&gt;
			console.log(9);&lt;br /&gt;
		}&lt;br /&gt;
	];&lt;br /&gt;
&lt;br /&gt;
	x[0]();&lt;br /&gt;
	for( var i = 1; i &amp;lt; x.length; i++ ) {&lt;br /&gt;
		setTimeout( x[ i ], (i-1) * delay + 50 );&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//testStuff();&lt;br /&gt;
makeTabsfromScratch();&lt;br /&gt;
&lt;br /&gt;
// This is officially deprecated as of MW1.22. Should be replaced by mw.hook,&lt;br /&gt;
// but the docs don&amp;#039;t say what event, so...&lt;br /&gt;
$(mw).on(&amp;#039;LivePreviewDone&amp;#039;, function () {&lt;br /&gt;
	bodyContent = $(&amp;quot;.mw-content-ltr&amp;quot;)[0]; // reset&lt;br /&gt;
	makeTabsfromScratch();&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
})( window.jQuery );&lt;/div&gt;</summary>
		<author><name>wikt&gt;Ioaxxere</name></author>
	</entry>
</feed>