<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.geministation.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-switch-infobox.js</id>
	<title>MediaWiki:Gadget-switch-infobox.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.geministation.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-switch-infobox.js"/>
	<link rel="alternate" type="text/html" href="https://wiki.geministation.com/index.php?title=MediaWiki:Gadget-switch-infobox.js&amp;action=history"/>
	<updated>2026-06-04T04:47:59Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki.geministation.com/index.php?title=MediaWiki:Gadget-switch-infobox.js&amp;diff=6788&amp;oldid=prev</id>
		<title>Banri: Created page with &quot;// &lt;nowiki&gt; ;(function ($, mw) { 	if (!($(&#039;.switch-infobox&#039;).length || $(&#039;.infobox-buttons&#039;).length)) { 		return; 	}  	var SWITCH_REF_REGEX = /^\$(\d+)/; 	/** 	 * Switch infob...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.geministation.com/index.php?title=MediaWiki:Gadget-switch-infobox.js&amp;diff=6788&amp;oldid=prev"/>
		<updated>2020-08-14T13:41:49Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;// &amp;lt;nowiki&amp;gt; ;(function ($, mw) { 	if (!($(&amp;#039;.switch-infobox&amp;#039;).length || $(&amp;#039;.infobox-buttons&amp;#039;).length)) { 		return; 	}  	var SWITCH_REF_REGEX = /^\$(\d+)/; 	/** 	 * Switch infob...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
;(function ($, mw) {&lt;br /&gt;
	if (!($(&amp;#039;.switch-infobox&amp;#039;).length || $(&amp;#039;.infobox-buttons&amp;#039;).length)) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var SWITCH_REF_REGEX = /^\$(\d+)/;&lt;br /&gt;
	/**&lt;br /&gt;
	 * Switch infobox psuedo-interface&lt;br /&gt;
	 * &lt;br /&gt;
	 * Switch infoboxes are given several similar functions so that they can be called similarly&lt;br /&gt;
	 * This is essentially like an interface or class structure, except I&amp;#039;m too lazy to implement that&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		switchfo.beginSwitchEvent(event)&lt;br /&gt;
	 * 			the reactionary event to buttons being clicked/selects being selected/etc&lt;br /&gt;
	 * 			tells SwitchEventManager to switch all the boxes&lt;br /&gt;
	 * 			should extract an index and anchor from the currentTarget and pass that to the SwitchEventManager.trigger function&lt;br /&gt;
	 * 			event		the jQuery event fired from $.click/$.change/etc&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		switchfo.switch(index, anchor)&lt;br /&gt;
	 * 			do all the actual switching of the infobox to the infobox specified by the anchor and index&lt;br /&gt;
	 * 			prefer using the anchor if there is a conflict&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		switchfo.defaultVer()&lt;br /&gt;
	 * 			called during script init&lt;br /&gt;
	 * 			returns either an anchor for the default version, if manually specified, or false if there is no default specified&lt;br /&gt;
	 * 			the page will automatically switch to the default version, or to version 1, when loaded.&lt;br /&gt;
	 * &lt;br /&gt;
	 */&lt;br /&gt;
	/** &lt;br /&gt;
	 * Switch Infoboxes based on [[Module:Infobox]]&lt;br /&gt;
	 * &lt;br /&gt;
	 * - the preferred way to do switch infoboxes&lt;br /&gt;
	 * - generates one table and a resources table, swaps resources into the table as required&lt;br /&gt;
	 * - with enough buttons, becomes a dropdown &amp;lt;select&amp;gt;&lt;br /&gt;
	 * &lt;br /&gt;
	 * parameters&lt;br /&gt;
	 *	  $box	jQuery object representing the infobox itself (.infobox-switch)&lt;br /&gt;
	 *	  index   index of this infobox, from $.each&lt;br /&gt;
	 */&lt;br /&gt;
	function SwitchInfobox($box, index) {&lt;br /&gt;
		var self = this;&lt;br /&gt;
		this.index = index;&lt;br /&gt;
		this.$infobox = $box;&lt;br /&gt;
		this.$resources = self.$infobox.parent().find(&amp;#039;.infobox-switch[data-resource-class=&amp;quot;&amp;#039;+self.$infobox.attr(&amp;#039;data-resource-class&amp;#039;)+&amp;#039;&amp;quot;] + .infobox-switch-resources&amp;#039;+self.$infobox.attr(&amp;#039;data-resource-class&amp;#039;));&lt;br /&gt;
		this.$buttons = self.$infobox.find(&amp;#039;div.infobox-buttons&amp;#039;);&lt;br /&gt;
		this.isSelect = self.$buttons.hasClass(&amp;#039;infobox-buttons-select&amp;#039;);&lt;br /&gt;
		this.$select = null;&lt;br /&gt;
		this.originalClasses = {};&lt;br /&gt;
&lt;br /&gt;
		/* click/change event - triggers switch event manager */&lt;br /&gt;
		this.beginSwitchEvent = function(e) {&lt;br /&gt;
			var $tgt = $(e.currentTarget);&lt;br /&gt;
			mw.log(&amp;#039;beginSwitchEvent triggered in module infobox, id &amp;#039;+self.index);&lt;br /&gt;
			if (self.isSelect) {&lt;br /&gt;
				window.switchEventManager.trigger($tgt.val(), $tgt.find(&amp;#039; &amp;gt; option[data-switch-index=&amp;#039;+$tgt.val()+&amp;#039;]&amp;#039;).attr(&amp;#039;data-switch-anchor&amp;#039;), self.$infobox);&lt;br /&gt;
			} else {&lt;br /&gt;
				window.switchEventManager.trigger($tgt.attr(&amp;#039;data-switch-index&amp;#039;), $tgt.attr(&amp;#039;data-switch-anchor&amp;#039;), self.$infobox);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/* switch event, triggered by manager */&lt;br /&gt;
		this.switchInfobox = function(index, text) {&lt;br /&gt;
			var ind, txt, $thisButton = self.$buttons.find(&amp;#039;[data-switch-anchor=&amp;quot;&amp;#039;+text+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
			mw.log(&amp;#039;switching module infobox, id &amp;#039;+self.index);&lt;br /&gt;
			// prefer text&lt;br /&gt;
			if ($thisButton.length) {&lt;br /&gt;
				txt = text;&lt;br /&gt;
				ind = $thisButton.attr(&amp;#039;data-switch-index&amp;#039;);&lt;br /&gt;
			} &lt;br /&gt;
			if (ind === undefined) {&lt;br /&gt;
				ind = index;&lt;br /&gt;
				$thisButton = self.$buttons.find(&amp;#039;[data-switch-index=&amp;quot;&amp;#039;+ind+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
				if ($thisButton.length) {&lt;br /&gt;
					txt = $thisButton.attr(&amp;#039;data-switch-anchor&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// for all things set to switch&lt;br /&gt;
			if (txt === undefined) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			if (self.isSelect) {&lt;br /&gt;
				self.$select.val(ind);&lt;br /&gt;
			} else {&lt;br /&gt;
				self.$buttons.find(&amp;#039;span.button&amp;#039;).removeClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
				$thisButton.addClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			self.$infobox.find(&amp;#039;[data-attr-param][data-attr-param!=&amp;quot;&amp;quot;]&amp;#039;).each(function(i,e) {&lt;br /&gt;
				var $e = $(e),&lt;br /&gt;
					param = $e.attr(&amp;#039;data-attr-param&amp;#039;),&lt;br /&gt;
					$switches = self.$resources.find(&amp;#039;span[data-attr-param=&amp;quot;&amp;#039;+param+&amp;#039;&amp;quot;]&amp;#039;),&lt;br /&gt;
					m,&lt;br /&gt;
					$val,&lt;br /&gt;
					$classTgt;&lt;br /&gt;
				&lt;br /&gt;
				// check if we found some switch data&lt;br /&gt;
				if (!$switches.length) return;&lt;br /&gt;
&lt;br /&gt;
				// find value&lt;br /&gt;
				$val = $switches.find(&amp;#039;span[data-attr-index=&amp;quot;&amp;#039;+ind+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
				if (!$val.length) {&lt;br /&gt;
					// didn&amp;#039;t find it, use default value&lt;br /&gt;
					$val = $switches.find(&amp;#039;span[data-attr-index=&amp;quot;0&amp;quot;]&amp;#039;);&lt;br /&gt;
					if (!$val.length) return;&lt;br /&gt;
				}&lt;br /&gt;
				// switch references support - $2 -&amp;gt; use the value for index 2&lt;br /&gt;
				m = SWITCH_REF_REGEX.exec($val.html());&lt;br /&gt;
				if (m) { // m is null if no matches&lt;br /&gt;
					$val = $switches.find(&amp;#039;span[data-attr-index=&amp;quot;&amp;#039;+m[1]+&amp;#039;&amp;quot;]&amp;#039;); // m is [ entire match, capture ]&lt;br /&gt;
					if (!$val.length) {&lt;br /&gt;
						$val = $switches.find(&amp;#039;span[data-attr-index=&amp;quot;0&amp;quot;]&amp;#039;); // fallback again&lt;br /&gt;
						if (!$val.length) return;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				$val = $val.clone();&lt;br /&gt;
				if ($e.find(&amp;#039;input+span&amp;#039;).length) {&lt;br /&gt;
					// this is a calculator from infoboxQty.js&lt;br /&gt;
					// replace the span (input+span returns the span)&lt;br /&gt;
					// reset the value&lt;br /&gt;
					$e.find(&amp;#039;input+span&amp;#039;).replaceWith($val.contents());&lt;br /&gt;
					$e.find(&amp;#039;input&amp;#039;).val(1);&lt;br /&gt;
				} else {&lt;br /&gt;
					// normal tag, just replace everything&lt;br /&gt;
					$e.empty().append($val.contents());&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// class switching&lt;br /&gt;
				// find the thing we&amp;#039;re switching classes for&lt;br /&gt;
				if ($e.is(&amp;#039;td, th&amp;#039;)) {&lt;br /&gt;
					$classTgt = $e.parent(&amp;#039;tr&amp;#039;);&lt;br /&gt;
				} else {&lt;br /&gt;
					$classTgt = $e;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// reset classes&lt;br /&gt;
				if (self.originalClasses.hasOwnProperty(param)) {&lt;br /&gt;
					$classTgt.attr(&amp;#039;class&amp;#039;, self.originalClasses[param]);&lt;br /&gt;
				} else {&lt;br /&gt;
					$classTgt.removeAttr(&amp;#039;class&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// change classes if needed&lt;br /&gt;
				if ($val.attr(&amp;#039;data-addclass&amp;#039;) !== undefined) {&lt;br /&gt;
					$classTgt.addClass($val.attr(&amp;#039;data-addclass&amp;#039;));&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
			// trigger complete event for inter-script functions&lt;br /&gt;
			self.$buttons.trigger(&amp;#039;switchinfoboxComplete&amp;#039;, {txt:txt, num:ind});&lt;br /&gt;
			console.log(this);&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		/* default version, return the anchor of the switchable if it exists */&lt;br /&gt;
		this.defaultVer = function () {&lt;br /&gt;
			var defver = self.$buttons.attr(&amp;#039;data-default-version&amp;#039;);&lt;br /&gt;
			if (defver !== undefined) {&lt;br /&gt;
				return { idx: defver, txt: self.$buttons.find(&amp;#039;[data-switch-index=&amp;quot;&amp;#039;+defver+&amp;#039;&amp;quot;]&amp;#039;).attr(&amp;#039;data-switch-anchor&amp;#039;) };&lt;br /&gt;
			}&lt;br /&gt;
			return false;&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		this.isParentOf = function ($triggerer) {&lt;br /&gt;
			return self.$infobox.find($triggerer).length &amp;gt; 0;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/* init */&lt;br /&gt;
		mw.log(&amp;#039;setting up module infobox, id &amp;#039;+self.index);&lt;br /&gt;
		// setup original classes&lt;br /&gt;
		this.$infobox.find(&amp;#039;[data-attr-param][data-attr-param!=&amp;quot;&amp;quot;]&amp;#039;).each(function(i,e){&lt;br /&gt;
			var $e = $(e), $classElem = $e, clas;&lt;br /&gt;
			if ($e.is(&amp;#039;td, th&amp;#039;)) {&lt;br /&gt;
				$classElem = $e.parent(&amp;#039;tr&amp;#039;);&lt;br /&gt;
			}&lt;br /&gt;
			clas = $classElem.attr(&amp;#039;class&amp;#039;);&lt;br /&gt;
			if (typeof clas === &amp;#039;string&amp;#039;) {&lt;br /&gt;
				self.originalClasses[$e.attr(&amp;#039;data-attr-param&amp;#039;)] = clas;&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		// setup select/buttons and events&lt;br /&gt;
		if (self.isSelect) {&lt;br /&gt;
			self.$select = $(&amp;#039;&amp;lt;select&amp;gt;&amp;#039;)&lt;br /&gt;
				.attr({&lt;br /&gt;
					id: &amp;#039;infobox-select-&amp;#039; + self.index,&lt;br /&gt;
					name: &amp;#039;infobox-select-&amp;#039; + self.index,&lt;br /&gt;
				});&lt;br /&gt;
			self.$buttons.find(&amp;#039;span.button&amp;#039;).each(function(i, e){&lt;br /&gt;
				var $e = $(e);&lt;br /&gt;
				self.$select.append(&lt;br /&gt;
					$(&amp;#039;&amp;lt;option&amp;gt;&amp;#039;).attr({&lt;br /&gt;
						value: $e.attr(&amp;#039;data-switch-index&amp;#039;),&lt;br /&gt;
						&amp;#039;data-switch-index&amp;#039;: $e.attr(&amp;#039;data-switch-index&amp;#039;),&lt;br /&gt;
						&amp;#039;data-switch-anchor&amp;#039;: $e.attr(&amp;#039;data-switch-anchor&amp;#039;)&lt;br /&gt;
					}).text($e.text())&lt;br /&gt;
				);&lt;br /&gt;
			});&lt;br /&gt;
			self.$buttons.empty().append(self.$select);&lt;br /&gt;
			self.$select.change(self.beginSwitchEvent);&lt;br /&gt;
		} else {&lt;br /&gt;
			self.$buttons&lt;br /&gt;
				.attr({&lt;br /&gt;
					id: &amp;#039;infobox-buttons-&amp;#039;+self.index&lt;br /&gt;
				})&lt;br /&gt;
				.find(&amp;#039;span&amp;#039;).each(function(i,e) {&lt;br /&gt;
					$(e).click(self.beginSwitchEvent);&lt;br /&gt;
				});&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		self.$buttons.css(&amp;#039;display&amp;#039;, &amp;#039;block&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
		window.switchEventManager.addSwitchInfobox(this);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Legacy switch infoboxes, as generated by [[Template:Switch infobox]]&lt;br /&gt;
	 * &lt;br /&gt;
	 * &lt;br /&gt;
	 * parameters&lt;br /&gt;
	 *	  $box	jQuery object representing the infobox itself (.switch-infobox)&lt;br /&gt;
	 *	  index   index of this infobox, from $.each&lt;br /&gt;
	 */&lt;br /&gt;
	function LegacySwitchInfobox($box, index) {&lt;br /&gt;
		var self = this;&lt;br /&gt;
		this.$parent = $box;&lt;br /&gt;
		this.index = index;&lt;br /&gt;
		this.$originalButtons = self.$parent.find(&amp;#039;.switch-infobox-triggers&amp;#039;);&lt;br /&gt;
		this.$items = self.$parent.find(&amp;#039;.item&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
		/* click/change event - triggers switch event manager */&lt;br /&gt;
		this.beginSwitchEvent = function(e) {&lt;br /&gt;
			var $tgt = $(e.currentTarget);&lt;br /&gt;
			mw.log(&amp;#039;beginSwitchEvent triggered in legacy infobox, id &amp;#039;+self.index);&lt;br /&gt;
			window.switchEventManager.trigger($tgt.attr(&amp;#039;data-id&amp;#039;), $tgt.attr(&amp;#039;data-anchor&amp;#039;), self.$parent);&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/* click/change event - triggers switch event manager */&lt;br /&gt;
		this.switchInfobox = function(index, text){&lt;br /&gt;
			var ind, txt, $thisButton = self.$buttons.find(&amp;#039;[data-anchor=&amp;quot;&amp;#039;+text+&amp;#039;&amp;quot;]&amp;#039;).first();&lt;br /&gt;
			mw.log(&amp;#039;switching legacy infobox, id &amp;#039;+self.index);&lt;br /&gt;
			if ($thisButton.length) {&lt;br /&gt;
				txt = text;&lt;br /&gt;
				ind = $thisButton.attr(&amp;#039;data-id&amp;#039;);&lt;br /&gt;
			} else {&lt;br /&gt;
				ind = index;&lt;br /&gt;
				$thisButton = self.$buttons.find(&amp;#039;[data-id=&amp;quot;&amp;#039;+ind+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
				if ($thisButton.length) {&lt;br /&gt;
					txt = $thisButton.attr(&amp;#039;data-anchor&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if (txt === undefined) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			self.$buttons.find(&amp;#039;.trigger&amp;#039;).removeClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
			self.$buttons.find(&amp;#039;.trigger[data-id=&amp;quot;&amp;#039;+ind+&amp;#039;&amp;quot;]&amp;#039;).addClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
			&lt;br /&gt;
			self.$items.filter(&amp;#039;.showing&amp;#039;).removeClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
			self.$items.filter(&amp;#039;[data-id=&amp;quot;&amp;#039;+ind+&amp;#039;&amp;quot;]&amp;#039;).addClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		/* default version - not supported by legacy, always false */&lt;br /&gt;
		this.defaultVer = function () { return false; };&lt;br /&gt;
		&lt;br /&gt;
		this.isParentOf = function ($triggerer) {&lt;br /&gt;
			return self.$parent.find($triggerer).length &amp;gt; 0;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/* init */&lt;br /&gt;
		mw.log(&amp;#039;setting up legacy infobox, id &amp;#039;+self.index);&lt;br /&gt;
		// add anchor text&lt;br /&gt;
		self.$originalButtons.find(&amp;#039;span.trigger.button&amp;#039;).each(function(i,e){&lt;br /&gt;
			var $e = $(e);&lt;br /&gt;
			$e.attr(&amp;#039;data-anchor&amp;#039;, &amp;#039;#&amp;#039;+$e.text().replace(&amp;#039; &amp;#039;, &amp;#039;_&amp;#039;));&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		// append triggers to every item&lt;br /&gt;
		// if contents has a gsw-infobox, add to a caption of that&lt;br /&gt;
		// else just put at top&lt;br /&gt;
		self.$items.each(function(i,e){&lt;br /&gt;
			var $item = $(e);&lt;br /&gt;
			if ($item.find(&amp;#039;table.gsw-infobox&amp;#039;).length &amp;gt; 0) {&lt;br /&gt;
				if ($item.find(&amp;#039;table.gsw-infobox caption&amp;#039;).length &amp;lt; 1) {&lt;br /&gt;
					$item.find(&amp;#039;table.gsw-infobox&amp;#039;).prepend(&amp;#039;&amp;lt;caption&amp;gt;&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
				$item.find(&amp;#039;table.gsw-infobox caption&amp;#039;).first().prepend(self.$originalButtons.clone());&lt;br /&gt;
			} else {&lt;br /&gt;
				$item.prepend(self.$originalButtons.clone());&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
		// remove buttons from current location&lt;br /&gt;
		self.$originalButtons.remove();&lt;br /&gt;
&lt;br /&gt;
		// update selection&lt;br /&gt;
		this.$buttons = self.$parent.find(&amp;#039;.switch-infobox-triggers&amp;#039;);&lt;br /&gt;
		self.$buttons.find(&amp;#039;.trigger&amp;#039;).each(function (i,e) {&lt;br /&gt;
			$(e).click(self.beginSwitchEvent);&lt;br /&gt;
		});&lt;br /&gt;
		&lt;br /&gt;
		window.switchEventManager.addSwitchInfobox(this);&lt;br /&gt;
		self.$parent.removeClass(&amp;#039;loading&amp;#039;).find(&amp;#039;span.loading-button&amp;#039;).remove();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Synced switches, as generated by [[Template:Synced switch]]&lt;br /&gt;
	 * &lt;br /&gt;
	 * &lt;br /&gt;
	 * parameters&lt;br /&gt;
	 *	  $box	jQuery object representing the synced switch itself (.gsw-synced-switch)&lt;br /&gt;
	 *	  index   index of this infobox, from $.each&lt;br /&gt;
	 */&lt;br /&gt;
	function SyncedSwitch($box, index) {&lt;br /&gt;
		var self = this;&lt;br /&gt;
		this.index = index;&lt;br /&gt;
		this.$syncedswitch = $box;&lt;br /&gt;
		this.$buttons = self.$syncedswitch.find(&amp;#039;div.synced-buttons&amp;#039;);&lt;br /&gt;
		this.attachedLabels = false;&lt;br /&gt;
&lt;br /&gt;
		/* click/change event - triggers switch event manager */&lt;br /&gt;
		this.beginSwitchEvent = function (e){&lt;br /&gt;
			var $tgt = $(e.currentTarget);&lt;br /&gt;
			mw.log(&amp;#039;beginSwitchEvent triggered in synced switch&amp;#039;+self.index);&lt;br /&gt;
			window.switchEventManager.trigger($tgt.attr(&amp;#039;data-item&amp;#039;), $tgt.attr(&amp;#039;data-item-text&amp;#039;));&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/* switch event, triggered by manager */&lt;br /&gt;
		this.switchInfobox = function(index, text){&lt;br /&gt;
			mw.log(&amp;#039;switching synced switch, id &amp;#039;+self.index);&lt;br /&gt;
			var $toShow = self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item[data-item-text=&amp;quot;&amp;#039;+text+&amp;#039;&amp;quot;]&amp;#039;),&lt;br /&gt;
				$thisButton = self.$buttons.find(&amp;#039;[data-item-text=&amp;quot;&amp;#039;+text+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
			if (!$toShow.length) {&lt;br /&gt;
				// Check for multi version data&lt;br /&gt;
				self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item[data-item-vers]&amp;#039;).each(function(j,k){&lt;br /&gt;
					var term = text.replace(/[.*+?^${}()|[\]\\]/g, &amp;#039;\\$&amp;amp;&amp;#039;) + &amp;#039;#&amp;#039;;&lt;br /&gt;
					if (term != &amp;#039;#&amp;#039; &amp;amp;&amp;amp; $(k).attr(&amp;#039;data-item-vers&amp;#039;).match(term)) {&lt;br /&gt;
						$toShow = $(k);&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
			if (!(self.attachedLabels &amp;amp;&amp;amp; $toShow.length)) {&lt;br /&gt;
				$toShow = self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item[data-item=&amp;quot;&amp;#039;+index+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
			}&lt;br /&gt;
			if ( self.$buttons &amp;amp;&amp;amp; !$thisButton.length &amp;amp;&amp;amp; $toShow.length) {&lt;br /&gt;
				$thisButton = self.$buttons.find(&amp;#039;[data-item=&amp;quot;&amp;#039;+$toShow.attr(&amp;#039;data-item&amp;#039;)+&amp;#039;&amp;quot;]&amp;#039;);&lt;br /&gt;
			}&lt;br /&gt;
			if (!$toShow.length) {&lt;br /&gt;
				// show default instead&lt;br /&gt;
				self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item&amp;#039;).removeClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
				$toShow = self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item[data-item=&amp;quot;0&amp;quot;]&amp;#039;);&lt;br /&gt;
				$toShow.addClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
				if (self.$buttons.length) {&lt;br /&gt;
					self.$buttons.find(&amp;#039;.button-selected&amp;#039;).removeClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
					self.$buttons.find(&amp;#039;.default-button&amp;#039;).addClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item&amp;#039;).removeClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
				$toShow.addClass(&amp;#039;showing&amp;#039;);&lt;br /&gt;
				if (self.$buttons.length) {&lt;br /&gt;
					self.$buttons.find(&amp;#039;.button-selected&amp;#039;).removeClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
					$thisButton.addClass(&amp;#039;button-selected&amp;#039;);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// show/hide categories in TOC&lt;br /&gt;
			this.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item .mw-header &amp;gt; a:first-child&amp;#039;).each(function(j,k){&lt;br /&gt;
				$(&amp;#039;#toc ul a[href=&amp;quot;#&amp;#039;+$(k).attr(&amp;#039;id&amp;#039;)+&amp;#039;&amp;quot;]&amp;#039;).parent().addClass(&amp;#039;sync-toc-hidden&amp;#039;);&lt;br /&gt;
			});&lt;br /&gt;
			$toShow.find(&amp;#039;.mw-header &amp;gt; a:first-child&amp;#039;).each(function(i,v){&lt;br /&gt;
				$(&amp;#039;#toc ul a[href=&amp;quot;#&amp;#039;+$(v).attr(&amp;#039;id&amp;#039;)+&amp;#039;&amp;quot;]&amp;#039;).parent().removeClass(&amp;#039;sync-toc-hidden&amp;#039;);&lt;br /&gt;
			});&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		/* default version - not supported by synced switches, always false */&lt;br /&gt;
		this.defaultVer = function () { return false; };&lt;br /&gt;
		&lt;br /&gt;
		this.isParentOf = function ($triggerer) {&lt;br /&gt;
			return self.$syncedswitch.find($triggerer).length &amp;gt; 0;&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		/* init */&lt;br /&gt;
		mw.log(&amp;#039;setting up synced switch, id &amp;#039;+self.index);&lt;br /&gt;
		// attempt to apply some button text from a SwitchInfobox&lt;br /&gt;
		if ($(&amp;#039;.gsw-infobox.infobox-switch&amp;#039;).length) {&lt;br /&gt;
			self.attachedLabels = true;&lt;br /&gt;
			var $linkedButtonTextInfobox = $(&amp;#039;.gsw-infobox.infobox-switch&amp;#039;).first();&lt;br /&gt;
			var allVers = &amp;#039;&amp;#039;, defVer = false;&lt;br /&gt;
			self.$syncedswitch.find(&amp;#039;.gsw-synced-switch-item&amp;#039;).each(function(i,e){&lt;br /&gt;
				var $e = $(e);&lt;br /&gt;
				if ($e.attr(&amp;#039;data-item-text&amp;#039;) === undefined) {&lt;br /&gt;
					$e.attr(&amp;#039;data-item-text&amp;#039;, $linkedButtonTextInfobox.find(&amp;#039;[data-switch-index=&amp;quot;&amp;#039;+i+&amp;#039;&amp;quot;]&amp;#039;).attr(&amp;#039;data-switch-anchor&amp;#039;));&lt;br /&gt;
				}&lt;br /&gt;
				allVers = allVers + $e.attr(&amp;#039;data-item-text&amp;#039;) + &amp;#039;#&amp;#039; + $e.attr(&amp;#039;data-item-vers&amp;#039;) + &amp;#039;#&amp;#039;;&lt;br /&gt;
			});&lt;br /&gt;
			self.$buttons.find(&amp;#039;[data-item]&amp;#039;).each(function(i,e){&lt;br /&gt;
				var $e = $(e);&lt;br /&gt;
				if ( $e.attr(&amp;#039;data-item-text&amp;#039;) === undefined) {&lt;br /&gt;
					var it = $linkedButtonTextInfobox.find(&amp;#039;[data-switch-index=&amp;quot;&amp;#039;+$e.attr(&amp;#039;data-item&amp;#039;)+&amp;#039;&amp;quot;]&amp;#039;).attr(&amp;#039;data-switch-anchor&amp;#039;);&lt;br /&gt;
					if (it) {&lt;br /&gt;
						$e.attr(&amp;#039;data-item-text&amp;#039;, it);&lt;br /&gt;
						if ( $e.text().length == 0 ) {&lt;br /&gt;
							$e.text( it.replace(/#/g, &amp;#039;&amp;#039;).replace(/_/g, &amp;#039; &amp;#039;) );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				allVers = allVers + $e.attr(&amp;#039;data-item-text&amp;#039;) + &amp;#039;#&amp;#039;;&lt;br /&gt;
			});&lt;br /&gt;
			// infobox value for default button&lt;br /&gt;
			$linkedButtonTextInfobox.find(&amp;#039;.infobox-buttons [data-switch-index]&amp;#039;).each(function(i,e){&lt;br /&gt;
				if (defVer) {&lt;br /&gt;
					return false;&lt;br /&gt;
				} else {&lt;br /&gt;
					var term = $(e).attr(&amp;#039;data-switch-anchor&amp;#039;).replace(/[.*+?^${}()|[\]\\]/g, &amp;#039;\\$&amp;amp;&amp;#039;)+&amp;#039;#&amp;#039;;&lt;br /&gt;
					if (!allVers.match(term)) {&lt;br /&gt;
						self.$buttons.find(&amp;#039;[data-item=&amp;quot;0&amp;quot;]&amp;#039;).attr({&lt;br /&gt;
							&amp;#039;data-item&amp;#039;:$(e).attr(&amp;#039;data-switch-index&amp;#039;),&lt;br /&gt;
							&amp;#039;data-item-text&amp;#039;:$(e).attr(&amp;#039;data-switch-anchor&amp;#039;)&lt;br /&gt;
						});&lt;br /&gt;
						defVer = true;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
			// remove default button if none apply&lt;br /&gt;
			self.$buttons.find(&amp;#039;[data-item=&amp;quot;0&amp;quot;]&amp;#039;).remove();&lt;br /&gt;
			if (self.$buttons.length) {&lt;br /&gt;
				self.$buttons&lt;br /&gt;
					.attr({ id: &amp;#039;sync-buttons-&amp;#039;+self.index})&lt;br /&gt;
					.find(&amp;#039;span&amp;#039;).each(function(i,e) {&lt;br /&gt;
						$(e).click(self.beginSwitchEvent);&lt;br /&gt;
					});&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// add events to buttons&lt;br /&gt;
		&lt;br /&gt;
		window.switchEventManager.addSwitchInfobox(this);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Event manager&lt;br /&gt;
	 * Observer pattern&lt;br /&gt;
	 * Globally available as window.switchEventManager&lt;br /&gt;
	 * &lt;br /&gt;
	 * Methods&lt;br /&gt;
	 *	  addSwitchInfobox(l)&lt;br /&gt;
	 *		  adds switch infobox (of any type) to the list of switch infoboxes listening to trigger events&lt;br /&gt;
	 *		  l	   switch infobox&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		addPreSwitchEvent(f)&lt;br /&gt;
	 * 			adds the function to a list of functions that runs when the switch event is triggered but before any other action is taken&lt;br /&gt;
	 * 			the function is passed the index and anchor (in that order) that was passed to the trigger function&lt;br /&gt;
	 * 			returning the boolean true from the function will cancel the switch event&lt;br /&gt;
	 * 			trying to add a non-function is a noop&lt;br /&gt;
	 * 			e		function to run&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		addPostSwitchEvent(f)&lt;br /&gt;
	 * 			adds the function to a list of functions that runs when the switch event is completed, after all of the switching is completed (including the hash change)&lt;br /&gt;
	 * 			the function is passed the index and anchor (in that order) that was passed to the trigger function&lt;br /&gt;
	 * 			the return value is ignored&lt;br /&gt;
	 * 			trying to add a non-function is a noop&lt;br /&gt;
	 * 			e		function to run&lt;br /&gt;
	 * &lt;br /&gt;
	 *	  trigger(i, a)&lt;br /&gt;
	 *		  triggers the switch event on all listeners&lt;br /&gt;
	 *		  will prefer switching to the anchor if available&lt;br /&gt;
	 *		  i	   index to switch to&lt;br /&gt;
	 *		  a	   anchor to switch to&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		makeSwitchInfobox($box)&lt;br /&gt;
	 * 			creates the correct object for the passed switch infobox, based on the classes of the infobox&lt;br /&gt;
	 * 			is a noop if it does not match any of the selectors&lt;br /&gt;
	 * 			infobox is given an index based on the internal counter for the switch&lt;br /&gt;
	 * 			$box		jQuery object for the switch infobox (the jQuery object passed to the above functions, see above for selectors checked)&lt;br /&gt;
	 * &lt;br /&gt;
	 * 		addIndex(i)&lt;br /&gt;
	 * 			updates the internal counter by adding i to it&lt;br /&gt;
	 * 			if i is not a number or is negative, is a noop&lt;br /&gt;
	 * 			used for manually setting up infoboxes (init) or creating a new type to plugin&lt;br /&gt;
	 * 			i	number to add&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	function SwitchEventManager() {&lt;br /&gt;
		var self = this, switchInfoboxes = [], preSwitchEvents = [], postSwitchEvents = [], index = 0;&lt;br /&gt;
		&lt;br /&gt;
		// actual switch infoboxes to change&lt;br /&gt;
		this.addSwitchInfobox = function(l) {&lt;br /&gt;
			switchInfoboxes.push(l);&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		// things to do when switch button is clicked but before any switching&lt;br /&gt;
		this.addPreSwitchEvent = function(e) {&lt;br /&gt;
			if (typeof(e) === &amp;#039;function&amp;#039;) {&lt;br /&gt;
				preSwitchEvents.push(e);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		this.addPostSwitchEvent = function(e) {&lt;br /&gt;
			if (typeof(e) === &amp;#039;function&amp;#039;) {&lt;br /&gt;
				postSwitchEvents.push(e);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		this.trigger = function(index, anchor, $triggerer) {&lt;br /&gt;
			mw.log(&amp;#039;Triggering switch event for index &amp;#039;+index+&amp;#039;; text &amp;#039;+anchor);&lt;br /&gt;
			// using a real for loop so we can use return to exit the trigger function&lt;br /&gt;
			for (var i=0; i &amp;lt; preSwitchEvents.length; i++){&lt;br /&gt;
				var ret = preSwitchEvents[i](index,anchor);&lt;br /&gt;
				if (typeof(ret) === &amp;#039;boolean&amp;#039;) {&lt;br /&gt;
					if (ret) {&lt;br /&gt;
						mw.log(&amp;#039;switching was cancelled&amp;#039;);&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// close all tooltips on the page&lt;br /&gt;
			$(&amp;#039;.js-tooltip-wrapper&amp;#039;).trigger(&amp;#039;js-tooltip-close&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
			// trigger switching on listeners&lt;br /&gt;
			switchInfoboxes.forEach(function (e) {&lt;br /&gt;
				if (!e.isParentOf($triggerer)) {&lt;br /&gt;
					e.switchInfobox(index, anchor);&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// update hash&lt;br /&gt;
			if (typeof anchor === &amp;#039;string&amp;#039;) {&lt;br /&gt;
				if (window.history &amp;amp;&amp;amp; window.history.replaceState) {&lt;br /&gt;
					if (window.location.hash !== &amp;#039;&amp;#039;) {&lt;br /&gt;
						window.history.replaceState({}, &amp;#039;&amp;#039;, window.location.href.replace(window.location.hash, anchor));&lt;br /&gt;
					} else {&lt;br /&gt;
						window.history.replaceState({}, &amp;#039;&amp;#039;, window.location.href + anchor);&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					// replaceState not supported, I guess we just change the hash normally?&lt;br /&gt;
					window.location.hash = anchor;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			postSwitchEvents.forEach(function(e){&lt;br /&gt;
				e(index, anchor);&lt;br /&gt;
			});&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		/* attempts to detect what type of switch infobox this is and applies the relevant type */&lt;br /&gt;
		// mostly for external access&lt;br /&gt;
		this.makeSwitchInfobox = function($e) {&lt;br /&gt;
			if ($e.is(&amp;#039;.infobox-switch&amp;#039;)) {&lt;br /&gt;
				return new SwitchInfobox($e, index++);&lt;br /&gt;
			}&lt;br /&gt;
			if ($e.hasClass(&amp;#039;switch-infobox&amp;#039;)) {&lt;br /&gt;
				return new LegacySwitchInfobox($e, index++);&lt;br /&gt;
			}&lt;br /&gt;
			if ($e.hasClass(&amp;#039;gsw-synced-switch&amp;#039;)) {&lt;br /&gt;
				return new SyncedSwitch($e, index++);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		this.addIndex = function(i) {&lt;br /&gt;
			if (typeof(i) === &amp;#039;number&amp;#039;) {&lt;br /&gt;
				 i += Math.max(Math.floor(i), 0);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		this.applyDefaultVersion = function() {&lt;br /&gt;
			if (window.location.hash !== &amp;#039;&amp;#039;) {&lt;br /&gt;
				self.trigger(1, window.location.hash);&lt;br /&gt;
				return;&lt;br /&gt;
			} else {&lt;br /&gt;
			// real for loop so we can return out of the function&lt;br /&gt;
				for (var i = 0; i&amp;lt;switchInfoboxes.length; i++) {&lt;br /&gt;
					var defver = switchInfoboxes[i].defaultVer();&lt;br /&gt;
					if (typeof(defver) === &amp;#039;object&amp;#039;) {&lt;br /&gt;
						self.trigger(defver.idx, defver.txt);&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			self.trigger(1, &amp;#039;&amp;#039;);&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function init() {&lt;br /&gt;
		var index = 0;&lt;br /&gt;
		window.switchEventManager = new SwitchEventManager();&lt;br /&gt;
		$(&amp;#039;.infobox-switch&amp;#039;).each(function(i,e){&lt;br /&gt;
			return new SwitchInfobox($(e), index++);&lt;br /&gt;
		});&lt;br /&gt;
		$(&amp;#039;.switch-infobox&amp;#039;).each(function(i,e){&lt;br /&gt;
			return new LegacySwitchInfobox($(e), index++);&lt;br /&gt;
		});&lt;br /&gt;
		$(&amp;#039;.gsw-synced-switch&amp;#039;).each(function(i,e){&lt;br /&gt;
			return new SyncedSwitch($(e), index++);&lt;br /&gt;
		});&lt;br /&gt;
		window.switchEventManager.addIndex(index);&lt;br /&gt;
		&lt;br /&gt;
		// reinitialize any kartographer map frames added due to a switch&lt;br /&gt;
		if ($(&amp;#039;.infobox-switch .mw-kartographer-map&amp;#039;).length&lt;br /&gt;
		 || $(&amp;#039;.switch-infobox .mw-kartographer-map&amp;#039;).length&lt;br /&gt;
		 || $(&amp;#039;.gsw-synced-switch .mw-karographer-map&amp;#039;).length) {&lt;br /&gt;
			window.switchEventManager.addPostSwitchEvent(function() {&lt;br /&gt;
				mw.hook(&amp;#039;wikipage.content&amp;#039;).fire($(&amp;#039;a.mw-kartographer-map&amp;#039;).parent());&lt;br /&gt;
			});&lt;br /&gt;
		}&lt;br /&gt;
		window.switchEventManager.applyDefaultVersion();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	$(init);&lt;br /&gt;
})(jQuery, mediaWiki);&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Banri</name></author>
	</entry>
</feed>